summaryrefslogtreecommitdiff
path: root/LedgerSMB/CP.pm
blob: 3722a265db97a65b9adff62eee58f4086ab9a80e (plain)
  1. #=====================================================================
  2. # LedgerSMB
  3. # Small Medium Business Accounting software
  4. # http://www.ledgersmb.org/
  5. #
  6. # Copyright (C) 2006
  7. # This work contains copyrighted information from a number of sources all used
  8. # with permission.
  9. #
  10. # This file contains source code included with or based on SQL-Ledger which
  11. # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
  12. # under the GNU General Public License version 2 or, at your option, any later
  13. # version. For a full list including contact information of contributors,
  14. # maintainers, and copyright holders, see the CONTRIBUTORS file.
  15. #
  16. # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
  17. # Copyright (C) 2003
  18. #
  19. # Author: DWS Systems Inc.
  20. # Web: http://www.sql-ledger.org
  21. #
  22. # Contributors:
  23. #
  24. #
  25. #======================================================================
  26. #
  27. # This file has undergone whitespace cleanup.
  28. #
  29. #======================================================================
  30. #
  31. # Check and receipt printing payment module backend routines
  32. # Number to text conversion routines are in
  33. # locale/{countrycode}/Num2text
  34. #
  35. #======================================================================
  36. package CP;
  37. use LedgerSMB::Sysconfig;
  38. sub new {
  39. my ($type, $countrycode) = @_;
  40. $self = {};
  41. use LedgerSMB::Num2text;
  42. use LedgerSMB::Locale;
  43. $self->{'locale'} = LedgerSMB::Locale->get_handle($countrycode);
  44. bless $self, $type;
  45. }
  46. sub paymentaccounts {
  47. my ($self, $myconfig, $form) = @_;
  48. my $dbh = $form->{dbh};
  49. my $query = qq|SELECT accno, description, link
  50. FROM chart
  51. WHERE link LIKE ?
  52. ORDER BY accno|;
  53. my $sth = $dbh->prepare($query);
  54. $sth->execute("%$form->{ARAP}%") || $form->dberror($query);
  55. $form->{PR}{$form->{ARAP}} = ();
  56. $form->{PR}{"$form->{ARAP}_paid"} = ();
  57. while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
  58. foreach my $item (split /:/, $ref->{link}) {
  59. if ($item eq $form->{ARAP}) {
  60. push @{ $form->{PR}{$form->{ARAP}} }, $ref;
  61. }
  62. if ($item eq "$form->{ARAP}_paid") {
  63. push @{ $form->{PR}{"$form->{ARAP}_paid"} }, $ref;
  64. }
  65. }
  66. }
  67. $sth->finish;
  68. # get currencies and closedto
  69. $query = qq|
  70. SELECT value, (SELECT value FROM defaults
  71. WHERE setting_key = 'closedto'),
  72. current_date
  73. FROM defaults
  74. WHERE setting_key = 'curr'|;
  75. ($form->{currencies}, $form->{closedto}, $form->{datepaid}) = $dbh->selectrow_array($query);
  76. if ($form->{payment} eq 'payments') {
  77. # get language codes
  78. $query = qq|SELECT *
  79. FROM language
  80. ORDER BY 2|;
  81. $sth = $dbh->prepare($query);
  82. $sth->execute || $self->dberror($query);
  83. $form->{all_language} = ();
  84. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  85. push @{ $form->{all_language} }, $ref;
  86. }
  87. $sth->finish;
  88. $form->all_departments($myconfig, $dbh, $form->{vc});
  89. }
  90. $dbh->commit;
  91. }
  92. sub get_openvc {
  93. my ($self, $myconfig, $form) = @_;
  94. my $dbh = $form->{dbh};
  95. my $arap = ($form->{vc} eq 'customer') ? 'ar' : 'ap';
  96. my $query = qq|SELECT count(*)
  97. FROM $form->{vc} ct, $arap a
  98. WHERE a.$form->{vc}_id = ct.id
  99. AND a.amount != a.paid|;
  100. my ($count) = $dbh->selectrow_array($query);
  101. my $sth;
  102. my $ref;
  103. my $i = 0;
  104. my $where = qq|WHERE a.$form->{vc}_id = ct.id
  105. AND a.amount != a.paid|;
  106. if ($form->{$form->{vc}}) {
  107. my $var = $dbh->quote($form->like(lc $form->{$form->{vc}}));
  108. $where .= " AND lower(name) LIKE $var";
  109. }
  110. # build selection list
  111. $query = qq|SELECT DISTINCT ct.*
  112. FROM $form->{vc} ct, $arap a
  113. $where
  114. ORDER BY name|;
  115. $sth = $dbh->prepare($query);
  116. $sth->execute || $form->dberror($query);
  117. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  118. $i++;
  119. push @{ $form->{name_list} }, $ref;
  120. }
  121. $sth->finish;
  122. $form->all_departments($myconfig, $dbh, $form->{vc});
  123. # get language codes
  124. $query = qq|SELECT *
  125. FROM language
  126. ORDER BY 2|;
  127. $sth = $dbh->prepare($query);
  128. $sth->execute || $self->dberror($query);
  129. $form->{all_language} = ();
  130. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  131. push @{ $form->{all_language} }, $ref;
  132. }
  133. $sth->finish;
  134. # get currency for first name
  135. if (@{ $form->{name_list} }) {
  136. # Chris T: I don't like this but it seems safe injection-wise
  137. # Leaving it so we can change it when we go to a new system
  138. $query = qq|SELECT curr
  139. FROM $form->{vc}
  140. WHERE id = $form->{name_list}->[0]->{id}|;
  141. ($form->{currency}) = $dbh->selectrow_array($query);
  142. $form->{currency} ||= $form->{defaultcurrency};
  143. }
  144. $dbh->commit;
  145. $i;
  146. }
  147. sub get_openinvoices {
  148. my ($self, $myconfig, $form) = @_;
  149. my $null;
  150. my $department_id;
  151. # connect to database
  152. my $dbh = $form->{dbh};
  153. $vc_id = $dbh->quote($form->{"$form->{vc}_id"});
  154. my $where = qq|WHERE a.$form->{vc}_id = $vc_id
  155. AND a.amount != a.paid|;
  156. $curr = $dbh->quote($form->{currency});
  157. $where .= qq| AND a.curr = $curr| if $form->{currency};
  158. my $sortorder = "transdate, invnumber";
  159. my ($buysell);
  160. if ($form->{vc} eq 'customer') {
  161. $buysell = "buy";
  162. } else {
  163. $buysell = "sell";
  164. }
  165. if ($form->{payment} eq 'payments') {
  166. $where = qq|WHERE a.amount != a.paid|;
  167. $where .= qq| AND a.curr = $curr| if $form->{currency};
  168. if ($form->{duedatefrom}) {
  169. $where .= qq| AND a.duedate >=
  170. |.$dbh->quote($form->{duedatefrom});
  171. }
  172. if ($form->{duedateto}) {
  173. $where .= qq| AND a.duedate <= |.
  174. $dbh->quote($form->{duedateto});
  175. }
  176. $sortorder = "name, transdate";
  177. }
  178. ($null, $department_id) = split /--/, $form->{department};
  179. if ($department_id) {
  180. $where .= qq| AND a.department_id = $department_id|;
  181. }
  182. my $query = qq|SELECT a.id, a.invnumber, a.transdate, a.amount, a.paid,
  183. a.curr, c.name, a.$form->{vc}_id, c.language_code
  184. FROM $form->{arap} a
  185. JOIN $form->{vc} c ON (c.id = a.$form->{vc}_id)
  186. $where
  187. ORDER BY $sortorder|;
  188. my $sth = $dbh->prepare($query);
  189. $sth->execute || $form->dberror($query);
  190. $query = qq|SELECT s.spoolfile
  191. FROM status s
  192. WHERE s.formname = '$form->{formname}'
  193. AND s.trans_id = ?|;
  194. my $vth = $dbh->prepare($query);
  195. my $spoolfile;
  196. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  197. # if this is a foreign currency transaction get exchangerate
  198. $ref->{exchangerate} =
  199. $form->get_exchangerate($dbh,
  200. $ref->{curr},
  201. $ref->{transdate},
  202. $buysell)
  203. if ($form->{currency}
  204. ne $form->{defaultcurrency});
  205. $vth->execute($ref->{id});
  206. $ref->{queue} = "";
  207. while (($spoolfile) = $vth->fetchrow_array) {
  208. $ref->{queued} .= "$form->{formname} $spoolfile ";
  209. }
  210. $vth->finish;
  211. $ref->{queued} =~ s/ +$//g;
  212. push @{ $form->{PR} }, $ref;
  213. }
  214. $sth->finish;
  215. $dbh->commit;
  216. }
  217. sub post_payment {
  218. my ($self, $myconfig, $form) = @_;
  219. # connect to database, turn AutoCommit off
  220. my $dbh = $form->{dbh};
  221. my $sth;
  222. my ($paymentaccno) = split /--/, $form->{account};
  223. # if currency ne defaultcurrency update exchangerate
  224. if ($form->{currency} ne $form->{defaultcurrency}) {
  225. $form->{exchangerate} = $form->parse_amount($myconfig, $form->{exchangerate});
  226. if ($form->{vc} eq 'customer') {
  227. $form->update_exchangerate($dbh, $form->{currency}, $form->{datepaid}, $form->{exchangerate}, 0);
  228. } else {
  229. $form->update_exchangerate($dbh, $form->{currency}, $form->{datepaid}, 0, $form->{exchangerate});
  230. }
  231. } else {
  232. $form->{exchangerate} = 1;
  233. }
  234. my $query = qq|
  235. SELECT (SELECT value FROM defaults
  236. WHERE setting_key='fxgain_accno_id'),
  237. (SELECT value FROM defaults
  238. WHERE setting_key='fxloss_accno_id')|;
  239. my ($fxgain_accno_id, $fxloss_accno_id) = $dbh->selectrow_array($query);
  240. my ($buysell);
  241. if ($form->{vc} eq 'customer') {
  242. $buysell = "buy";
  243. } else {
  244. $buysell = "sell";
  245. }
  246. my $ml;
  247. my $where;
  248. if ($form->{ARAP} eq 'AR') {
  249. $ml = 1;
  250. $where = qq| (c.link = 'AR' OR c.link LIKE 'AR:%') |;
  251. } else {
  252. $ml = -1;
  253. $where = qq| (c.link = 'AP' OR c.link LIKE '%:AP' OR c.link LIKE '%:AP:%') |;
  254. }
  255. my $paymentamount = $form->parse_amount($myconfig, $form->{amount});
  256. # query to retrieve paid amount
  257. $query = qq|SELECT paid
  258. FROM $form->{arap}
  259. WHERE id = ?
  260. FOR UPDATE|;
  261. my $pth = $dbh->prepare($query) || $form->dberror($query);
  262. my %audittrail;
  263. # go through line by line
  264. for my $i (1 .. $form->{rowcount}) {
  265. $form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"});
  266. $form->{"due_$i"} = $form->parse_amount($myconfig, $form->{"due_$i"});
  267. if ($form->{"checked_$i"} && $form->{"paid_$i"}) {
  268. $paymentamount -= $form->{"paid_$i"};
  269. # get exchangerate for original
  270. $query = qq|
  271. SELECT $buysell
  272. FROM exchangerate e
  273. JOIN $form->{arap} a
  274. ON (a.transdate = e.transdate)
  275. WHERE e.curr = ?
  276. AND a.id = ?|;
  277. my $sth = $dbh->prepare($query);
  278. $sth->execute($form->{currency}, $form->{"id_$i"});
  279. my ($exchangerate) = $sth->fetchrow_array();
  280. $exchangerate = 1 unless $exchangerate;
  281. $query = qq|
  282. SELECT c.id
  283. FROM chart c
  284. JOIN acc_trans a ON (a.chart_id = c.id)
  285. WHERE $where
  286. AND a.trans_id = ?|;
  287. my $sth = $dbh->prepare($query);
  288. $sth->execute($form->{"id_$i"});
  289. my ($id) = $sth->fetchrow_array;
  290. $amount =
  291. $form->round_amount(
  292. $form->{"paid_$i"} * $exchangerate, 2);
  293. # add AR/AP
  294. $query = qq|
  295. INSERT INTO acc_trans
  296. (trans_id, chart_id, transdate,
  297. amount)
  298. VALUES (?, ?,
  299. ?,
  300. ?)|;
  301. $sth = $dbh->prepare($query);
  302. $sth->execute($form->{"id_$i"}, $id,
  303. $form->{date_paid}, $amount * $ml)
  304. || $form->dberror($query, __file__, __line__);
  305. # add payment
  306. $query = qq|
  307. INSERT INTO acc_trans
  308. (trans_id, chart_id, transdate,
  309. amount, source, memo)
  310. VALUES (?, (SELECT id
  311. FROM chart
  312. WHERE accno = ?),
  313. ?, ?, ?, ?)|;
  314. $sth = $dbh->prepare($query);
  315. $sth->execute(
  316. $form->{"id_$i"}, $paymentaccno,
  317. $form->{datepaid},
  318. $form->{"paid_$i"} * $ml * -1,
  319. $form->{source}, $form->{memo})
  320. || $form->dberror(
  321. $query, 'CP.pm', 444);
  322. # add exchangerate difference if currency ne defaultcurrency
  323. $amount = $form->round_amount(
  324. $form->{"paid_$i"} *
  325. ($form->{exchangerate} - 1),
  326. 2);
  327. if ($amount) {
  328. # exchangerate difference
  329. $query = qq|
  330. INSERT INTO acc_trans
  331. (trans_id, chart_id,
  332. transdate, amount, cleared,
  333. fx_transaction, source)
  334. VALUES (?, (SELECT id
  335. FROM chart
  336. WHERE accno = ?),
  337. ?, ?, '0', '1',
  338. ?)|;
  339. $sth = $dbh->prepare($query);
  340. $sth->execute(
  341. $form->{"id_$i"}, $paymentaccno,
  342. $form->{datepaid}, $amount * $ml * -1,
  343. $form->{source})
  344. || $form->dberror(
  345. $query, 'CP.pm', 470);
  346. # gain/loss
  347. $amount =
  348. ($form->round_amount(
  349. $form->{"paid_$i"} *
  350. $exchangerate,
  351. 2) -
  352. $form->round_amount(
  353. $form->{"paid_$i"} *
  354. $form->{exchangerate},
  355. 2))
  356. * $ml * -1;
  357. if ($amount) {
  358. my $accno_id =
  359. ($amount > 0)
  360. ? $fxgain_accno_id
  361. : $fxloss_accno_id;
  362. $query = qq|
  363. INSERT INTO acc_trans
  364. (trans_id,
  365. chart_id,
  366. transdate,
  367. amount, cleared,
  368. fx_transaction)
  369. VALUES (?, ?, ?, ?, '0', '1')|;
  370. $sth = $dbh->prepare($query);
  371. $sth->execute(
  372. $form->{"id_$i"}, $accno_id,
  373. $form->{datepaid}, $amount)
  374. || $form->dberror(
  375. $query,
  376. 'CP.pm',
  377. 506);
  378. }
  379. }
  380. $form->{"paid_$i"} =
  381. $form->round_amount(
  382. $form->{"paid_$i"} * $exchangerate, 2);
  383. $pth->execute($form->{"id_$i"}) || $form->dberror;
  384. ($amount) = $pth->fetchrow_array;
  385. $pth->finish;
  386. $amount += $form->{"paid_$i"};
  387. # update AR/AP transaction
  388. $query = qq|
  389. UPDATE $form->{arap}
  390. SET paid = ?,
  391. datepaid = ?
  392. WHERE id = ?|;
  393. $sth = $dbh->prepare($query);
  394. $sth->execute(
  395. $amount, $form->{datepaid}, $form->{"id_$i"})
  396. || $form->dberror($query, 'CP.pm',
  397. 530);
  398. %audittrail = (
  399. tablename => $form->{arap},
  400. reference => $form->{source},
  401. formname => $form->{formname},
  402. action => 'posted',
  403. id => $form->{"id_$i"} );
  404. $form->audittrail($dbh, "", \%audittrail);
  405. }
  406. }
  407. # record a AR/AP with a payment
  408. if ($form->round_amount($paymentamount, 2)) {
  409. $form->{invnumber} = "";
  410. OP::overpayment("", $myconfig, $form, $dbh, $paymentamount, $ml, 1);
  411. }
  412. my $rc = $dbh->commit;
  413. $rc;
  414. }
  415. sub post_payments {
  416. my ($self, $myconfig, $form) = @_;
  417. # connect to database, turn AutoCommit off
  418. my $dbh = $form->{dbh};
  419. my $sth;
  420. my ($paymentaccno) = split /--/, $form->{account};
  421. # if currency ne defaultcurrency update exchangerate
  422. if ($form->{currency} ne $form->{defaultcurrency}) {
  423. $form->{exchangerate} = $form->parse_amount($myconfig, $form->{exchangerate});
  424. if ($form->{vc} eq 'customer') {
  425. $form->update_exchangerate($dbh, $form->{currency}, $form->{datepaid}, $form->{exchangerate}, 0);
  426. } else {
  427. $form->update_exchangerate($dbh, $form->{currency}, $form->{datepaid}, 0, $form->{exchangerate});
  428. }
  429. } else {
  430. $form->{exchangerate} = 1;
  431. }
  432. my $query = qq|
  433. SELECT (SELECT value FROM defaults
  434. WHERE setting_key='fxgain_accno_id'),
  435. (SELECT value FROM defaults
  436. WHERE setting_key='fxloss_accno_id')|;
  437. my ($fxgain_accno_id, $fxloss_accno_id) = $dbh->selectrow_array($query);
  438. my ($buysell);
  439. if ($form->{vc} eq 'customer') {
  440. $buysell = "buy";
  441. } else {
  442. $buysell = "sell";
  443. }
  444. my $ml;
  445. my $where;
  446. if ($form->{ARAP} eq 'AR') {
  447. $ml = 1;
  448. $where = qq| (c.link = 'AR' OR c.link LIKE 'AR:%') |;
  449. } else {
  450. $ml = -1;
  451. $where = qq| (c.link = 'AP' OR c.link LIKE '%:AP' OR c.link LIKE '%:AP:%') |;
  452. }
  453. # get AR/AP account
  454. $query = qq|SELECT c.accno
  455. FROM chart c
  456. JOIN acc_trans ac ON (ac.chart_id = c.id)
  457. WHERE trans_id = ?
  458. AND $where|;
  459. my $ath = $dbh->prepare($query) || $form->dberror($query);
  460. # query to retrieve paid amount
  461. $query = qq|SELECT paid
  462. FROM $form->{arap}
  463. WHERE id = ?
  464. FOR UPDATE|;
  465. my $pth = $dbh->prepare($query) || $form->dberror($query);
  466. my %audittrail;
  467. my $overpayment = 0;
  468. my $accno_id;
  469. # go through line by line
  470. for my $i (1 .. $form->{rowcount}) {
  471. $ath->execute($form->{"id_$i"});
  472. ($form->{$form->{ARAP}}) = $ath->fetchrow_array;
  473. $ath->finish;
  474. $form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"});
  475. $form->{"due_$i"} = $form->parse_amount($myconfig, $form->{"due_$i"});
  476. if ($form->{"$form->{vc}_id_$i"} ne $sameid) {
  477. # record a AR/AP with a payment
  478. if ($overpayment > 0 && $form->{$form->{ARAP}}) {
  479. $form->{invnumber} = "";
  480. OP::overpayment("", $myconfig, $form, $dbh, $overpayment, $ml, 1);
  481. }
  482. $overpayment = 0;
  483. $form->{"$form->{vc}_id"} = $form->{"$form->{vc}_id_$i"};
  484. for (qw(source memo)) { $form->{$_} = $form->{"${_}_$i"} }
  485. }
  486. if ($form->{"checked_$i"} && $form->{"paid_$i"}) {
  487. $overpayment += ($form->{"paid_$i"} - $form->{"due_$i"});
  488. # get exchangerate for original
  489. $query = qq|
  490. SELECT $buysell
  491. FROM exchangerate e
  492. JOIN $form->{arap} a
  493. ON (a.transdate = e.transdate)
  494. WHERE e.curr = ?
  495. AND a.id = ?|;
  496. $sth = $dbh->prepare($query);
  497. $sth->execute($form->{currency}, $form->{"id_$i"})
  498. || $form->dberror($query, 'CP.pm', 671);
  499. my ($exchangerate) = $sth->fetchrow_array;
  500. $exchangerate ||= 1;
  501. $query = qq|
  502. SELECT c.id
  503. FROM chart c
  504. JOIN acc_trans a ON (a.chart_id = c.id)
  505. WHERE $where
  506. AND a.trans_id = ?|;
  507. $sth = $dbh->prepare($query);
  508. $sth->execute($form->{"id_$i"});
  509. $paid = ($form->{"paid_$i"} > $form->{"due_$i"}) ? $form->{"due_$i"} : $form->{"paid_$i"};
  510. $amount = $form->round_amount($paid * $exchangerate, 2);
  511. # add AR/AP
  512. $query = qq|
  513. INSERT INTO acc_trans
  514. (trans_id, chart_id, transdate,
  515. amount)
  516. VALUES (?, ?, ?, ?)|;
  517. $sth = $dbh->prepare($query);
  518. $sth->execute(
  519. $form->{"id_$i"}, $id, $form->{datepaid},
  520. $amount * $ml)
  521. || $form->dberror($query, 'CP.pm',
  522. 701);
  523. $query = qq|SELECT id
  524. FROM chart
  525. WHERE accno = ?|;
  526. $sth = $dbh->prepare($query);
  527. $sth->execute($paymentaccno);
  528. ($accno_id) = $sth->fetchrow_array;
  529. # add payment
  530. $query = qq|
  531. INSERT INTO acc_trans
  532. (trans_id, chart_id, transdate,
  533. amount, source, memo)
  534. VALUES (?, ?, ?, ?, ?, ?)|;
  535. $sth = $dbh->prepare($query);
  536. $sth->execute(
  537. $form->{"id_$i"}, $accno_id, $form->{datepaid},
  538. $paid * $ml * -1, $form->{source},
  539. $form->{memo})
  540. || $form->dberror($query, 'CP.pm',
  541. 723);
  542. # add exchangerate difference if currency ne defaultcurrency
  543. $amount =
  544. $form->round_amount(
  545. $paid * ($form->{exchangerate} - 1)
  546. * $ml * -1,
  547. 2);
  548. if ($amount) {
  549. # exchangerate difference
  550. $query = qq|
  551. INSERT INTO acc_trans
  552. (trans_id, chart_id,
  553. transdate,
  554. amount, source)
  555. VALUES (?, ?, ?, ?, ?)|;
  556. $sth = $dbh->prepare($query);
  557. $sth->execute(
  558. $form->{"id_$i"}, $accno_id,
  559. $form->{datepaid}, $amount,
  560. $form->{source})
  561. || $form->dberror(
  562. $query, 'CP.pm', 748);
  563. # gain/loss
  564. $amount = ($form->round_amount($paid * $exchangerate,2) - $form->round_amount($paid * $form->{exchangerate},2)) * $ml * -1;
  565. if ($amount) {
  566. $accno_id =
  567. ($amount > 0)
  568. ? $fxgain_accno_id
  569. : $fxloss_accno_id;
  570. $query = qq|
  571. INSERT INTO acc_trans
  572. (trans_id,
  573. chart_id,
  574. transdate,
  575. amount,
  576. fx_transaction)
  577. VALUES (?, ?, ?, ?, '1')|;
  578. $sth = $dbh->prepare($query);
  579. $sth->execute(
  580. $form->{"id_$i"}, $accno_id,
  581. $form->{datepaid}, $amount)
  582. || $form->dberror(
  583. $query,
  584. 'CP.pm', 775);
  585. }
  586. }
  587. $paid = $form->round_amount($paid * $exchangerate, 2);
  588. $pth->execute($form->{"id_$i"}) || $form->dberror;
  589. ($amount) = $pth->fetchrow_array;
  590. $pth->finish;
  591. $amount += $paid;
  592. # update AR/AP transaction
  593. $query = qq|
  594. UPDATE $form->{arap}
  595. SET paid = ?,
  596. datepaid = ?
  597. WHERE id = ?|;
  598. $sth = $dbh->prepare($query);
  599. $sth->execute(
  600. $amount, $form->{datepaid}, $form->{"id_$i"})
  601. || $form->dberror($query, 'CP.pm',
  602. 796);
  603. %audittrail = ( tablename => $form->{arap},
  604. reference => $form->{source},
  605. formname => $form->{formname},
  606. action => 'posted',
  607. id => $form->{"id_$i"} );
  608. $form->audittrail($dbh, "", \%audittrail);
  609. }
  610. $sameid = $form->{"$form->{vc}_id_$i"};
  611. }
  612. # record a AR/AP with a payment
  613. if ($overpayment > 0 && $form->{$form->{ARAP}}) {
  614. $form->{invnumber} = "";
  615. OP::overpayment("", $myconfig, $form, $dbh, $overpayment, $ml, 1);
  616. }
  617. my $rc = $dbh->commit;
  618. $rc;
  619. }
  620. 1;