summaryrefslogtreecommitdiff
path: root/LedgerSMB/CP.pm
blob: da39ba767df19017d5eb1dda39ab555b34907ce8 (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. $sth = $dbh->prepare($query);
  300. $sth->execute($form->{"id_$i"}, $id,
  301. $form->{date_paid}, $amount * $ml)
  302. || $form->dberror($query, 'CP.pm', 427);
  303. # add payment
  304. $query = qq|
  305. INSERT INTO acc_trans
  306. (trans_id, chart_id, transdate,
  307. amount, source, memo)
  308. VALUES (?, (SELECT id
  309. FROM chart
  310. WHERE accno = ?),
  311. ?, ?, ?, ?)|;
  312. $sth = $dbh->prepare($query);
  313. $sth->execute(
  314. $form->{"id_$i"}, $paymentaccno,
  315. $form->{datepaid}, $form->{"paid_$i"} * $ml *-1,
  316. $form->{source}, $form->{memo})
  317. || $form->dberror(
  318. $query, 'CP.pm', 444);
  319. # add exchangerate difference if currency ne defaultcurrency
  320. $amount = $form->round_amount(
  321. $form->{"paid_$i"} *
  322. ($form->{exchangerate} - 1),
  323. 2);
  324. if ($amount) {
  325. # exchangerate difference
  326. $query = qq|
  327. INSERT INTO acc_trans
  328. (trans_id, chart_id,
  329. transdate, amount, cleared,
  330. fx_transaction, source)
  331. VALUES (?, (SELECT id
  332. FROM chart
  333. WHERE accno = ?),
  334. ?, ?, '0', '1', ?)|;
  335. $sth = $dbh->prepare($query);
  336. $sth->execute(
  337. $form->{"id_$i"}, $paymentaccno,
  338. $form->{datepaid}, $amount * $ml * -1,
  339. $form->{source})
  340. || $form->dberror(
  341. $query, 'CP.pm', 470);
  342. # gain/loss
  343. $amount =
  344. ($form->round_amount(
  345. $form->{"paid_$i"} *
  346. $exchangerate,
  347. 2) -
  348. $form->round_amount(
  349. $form->{"paid_$i"} *
  350. $form->{exchangerate},
  351. 2))
  352. * $ml * -1;
  353. if ($amount) {
  354. my $accno_id =
  355. ($amount > 0)
  356. ? $fxgain_accno_id
  357. : $fxloss_accno_id;
  358. $query = qq|
  359. INSERT INTO acc_trans
  360. (trans_id,
  361. chart_id,
  362. transdate,
  363. amount, cleared,
  364. fx_transaction)
  365. VALUES (?, ?, ?, ?, '0', '1')|;
  366. $sth = $dbh->prepare($query);
  367. $sth->execute(
  368. $form->{"id_$i"}, $accno_id,
  369. $form->{datepaid}, $amount)
  370. || $form->dberror(
  371. $query,
  372. 'CP.pm',
  373. 506);
  374. }
  375. }
  376. $form->{"paid_$i"} =
  377. $form->round_amount(
  378. $form->{"paid_$i"} * $exchangerate, 2);
  379. $pth->execute($form->{"id_$i"}) || $form->dberror;
  380. ($amount) = $pth->fetchrow_array;
  381. $pth->finish;
  382. $amount += $form->{"paid_$i"};
  383. # update AR/AP transaction
  384. $query = qq|
  385. UPDATE $form->{arap}
  386. SET paid = ?,
  387. datepaid = ?
  388. WHERE id = ?|;
  389. $sth = $dbh->prepare($query);
  390. $sth->execute(
  391. $amount, $form->{datepaid}, $form->{"id_$i"})
  392. || $form->dberror($query, 'CP.pm',
  393. 530);
  394. %audittrail = (
  395. tablename => $form->{arap},
  396. reference => $form->{source},
  397. formname => $form->{formname},
  398. action => 'posted',
  399. id => $form->{"id_$i"} );
  400. $form->audittrail($dbh, "", \%audittrail);
  401. }
  402. }
  403. # record a AR/AP with a payment
  404. if ($form->round_amount($paymentamount, 2)) {
  405. $form->{invnumber} = "";
  406. OP::overpayment("", $myconfig, $form, $dbh, $paymentamount, $ml, 1);
  407. }
  408. my $rc = $dbh->commit;
  409. $rc;
  410. }
  411. sub post_payments {
  412. my ($self, $myconfig, $form) = @_;
  413. # connect to database, turn AutoCommit off
  414. my $dbh = $form->{dbh};
  415. my $sth;
  416. my ($paymentaccno) = split /--/, $form->{account};
  417. # if currency ne defaultcurrency update exchangerate
  418. if ($form->{currency} ne $form->{defaultcurrency}) {
  419. $form->{exchangerate} = $form->parse_amount($myconfig, $form->{exchangerate});
  420. if ($form->{vc} eq 'customer') {
  421. $form->update_exchangerate($dbh, $form->{currency}, $form->{datepaid}, $form->{exchangerate}, 0);
  422. } else {
  423. $form->update_exchangerate($dbh, $form->{currency}, $form->{datepaid}, 0, $form->{exchangerate});
  424. }
  425. } else {
  426. $form->{exchangerate} = 1;
  427. }
  428. my $query = qq|
  429. SELECT (SELECT value FROM defaults
  430. WHERE setting_key='fxgain_accno_id'),
  431. (SELECT value FROM defaults
  432. WHERE setting_key='fxloss_accno_id')|;
  433. my ($fxgain_accno_id, $fxloss_accno_id) = $dbh->selectrow_array($query);
  434. my ($buysell);
  435. if ($form->{vc} eq 'customer') {
  436. $buysell = "buy";
  437. } else {
  438. $buysell = "sell";
  439. }
  440. my $ml;
  441. my $where;
  442. if ($form->{ARAP} eq 'AR') {
  443. $ml = 1;
  444. $where = qq| (c.link = 'AR' OR c.link LIKE 'AR:%') |;
  445. } else {
  446. $ml = -1;
  447. $where = qq| (c.link = 'AP' OR c.link LIKE '%:AP' OR c.link LIKE '%:AP:%') |;
  448. }
  449. # get AR/AP account
  450. $query = qq|SELECT c.accno
  451. FROM chart c
  452. JOIN acc_trans ac ON (ac.chart_id = c.id)
  453. WHERE trans_id = ?
  454. AND $where|;
  455. my $ath = $dbh->prepare($query) || $form->dberror($query);
  456. # query to retrieve paid amount
  457. $query = qq|SELECT paid
  458. FROM $form->{arap}
  459. WHERE id = ?
  460. FOR UPDATE|;
  461. my $pth = $dbh->prepare($query) || $form->dberror($query);
  462. my %audittrail;
  463. my $overpayment = 0;
  464. my $accno_id;
  465. # go through line by line
  466. for my $i (1 .. $form->{rowcount}) {
  467. $ath->execute($form->{"id_$i"});
  468. ($form->{$form->{ARAP}}) = $ath->fetchrow_array;
  469. $ath->finish;
  470. $form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"});
  471. $form->{"due_$i"} = $form->parse_amount($myconfig, $form->{"due_$i"});
  472. if ($form->{"$form->{vc}_id_$i"} ne $sameid) {
  473. # record a AR/AP with a payment
  474. if ($overpayment > 0 && $form->{$form->{ARAP}}) {
  475. $form->{invnumber} = "";
  476. OP::overpayment("", $myconfig, $form, $dbh, $overpayment, $ml, 1);
  477. }
  478. $overpayment = 0;
  479. $form->{"$form->{vc}_id"} = $form->{"$form->{vc}_id_$i"};
  480. for (qw(source memo)) { $form->{$_} = $form->{"${_}_$i"} }
  481. }
  482. if ($form->{"checked_$i"} && $form->{"paid_$i"}) {
  483. $overpayment += ($form->{"paid_$i"} - $form->{"due_$i"});
  484. # get exchangerate for original
  485. $query = qq|
  486. SELECT $buysell
  487. FROM exchangerate e
  488. JOIN $form->{arap} a
  489. ON (a.transdate = e.transdate)
  490. WHERE e.curr = ?
  491. AND a.id = ?|;
  492. $sth = $sbh->prepare($query);
  493. $sth->execute($form->{currency}, $form->{"id_$i"})
  494. || $form->dberror($query, 'CP.pm', 671);
  495. my ($exchangerate) = $sth->fetchrow_array;
  496. $exchangerate ||= 1;
  497. $query = qq|
  498. SELECT c.id
  499. FROM chart c
  500. JOIN acc_trans a ON (a.chart_id = c.id)
  501. WHERE $where
  502. AND a.trans_id = $form->{"id_$i"}|;
  503. $sth = $dbh->prepare($query);
  504. $sth->execute($form->{"id_$i"});
  505. $paid = ($form->{"paid_$i"} > $form->{"due_$i"}) ? $form->{"due_$i"} : $form->{"paid_$i"};
  506. $amount = $form->round_amount($paid * $exchangerate, 2);
  507. # add AR/AP
  508. $query = qq|
  509. INSERT INTO acc_trans
  510. (trans_id, chart_id, transdate,
  511. amount)
  512. VALUES (?, ?, ?, ?)|;
  513. $sth = $dbh->prepare($query);
  514. $sth->execute(
  515. $form->{"id_$i"}, $id, $form->{datepaid},
  516. $amount * $ml)
  517. || $form->dberror($query, 'CP.pm',
  518. 701);
  519. $query = qq|SELECT id
  520. FROM chart
  521. WHERE accno = ?|;
  522. $sth = $dbh->prepare($query);
  523. $sth->execute($paymentaccno);
  524. ($accno_id) = $sth->fetchrow_array;
  525. # add payment
  526. $query = qq|
  527. INSERT INTO acc_trans
  528. (trans_id, chart_id, transdate,
  529. amount, source, memo)
  530. VALUES (?, ?, ?, ?, ?, ?)|;
  531. $sth = $dbh->prepare($query);
  532. $sth->execute(
  533. $form->{"id_$i"}, $accno_id, $form->{datepaid},
  534. $paid * $ml * -1, $form->{source},
  535. $form->{memo})
  536. || $form->dberror($query, 'CP.pm',
  537. 723);
  538. # add exchangerate difference if currency ne defaultcurrency
  539. $amount =
  540. $form->round_amount(
  541. $paid * ($form->{exchangerate} - 1)
  542. * $ml * -1,
  543. 2);
  544. if ($amount) {
  545. # exchangerate difference
  546. $query = qq|
  547. INSERT INTO acc_trans
  548. (trans_id, chart_id,
  549. transdate,
  550. amount, source)
  551. VALUES (?, ?, ?, ?, ?)|;
  552. $sth = $dbh->prepare($query);
  553. $sth->execute(
  554. $form->{"id_$i"}, $accno_id,
  555. $form->{datepaid}, $amount,
  556. $form->{source})
  557. || $form->dberror(
  558. $query, 'CP.pm', 748);
  559. # gain/loss
  560. $amount = ($form->round_amount($paid * $exchangerate,2) - $form->round_amount($paid * $form->{exchangerate},2)) * $ml * -1;
  561. if ($amount) {
  562. $accno_id =
  563. ($amount > 0)
  564. ? $fxgain_accno_id
  565. : $fxloss_accno_id;
  566. $query = qq|
  567. INSERT INTO acc_trans
  568. (trans_id,
  569. chart_id,
  570. transdate,
  571. amount,
  572. fx_transaction)
  573. VALUES (?, ?, ?, ?, '1')|;
  574. $sth = $dbh->prepare($query);
  575. $sth->execute(
  576. $form->{"id_$i"}, $accno_id,
  577. $form->{datepaid}, $amount)
  578. || $form->dberror(
  579. $query,
  580. 'CP.pm', 775);
  581. }
  582. }
  583. $paid = $form->round_amount($paid * $exchangerate, 2);
  584. $pth->execute($form->{"id_$i"}) || $form->dberror;
  585. ($amount) = $pth->fetchrow_array;
  586. $pth->finish;
  587. $amount += $paid;
  588. # update AR/AP transaction
  589. $query = qq|
  590. UPDATE $form->{arap}
  591. SET paid = $amount,
  592. datepaid = '$form->{datepaid}'
  593. WHERE id = $form->{"id_$i"}|;
  594. $sth = $dbh->prepare($query);
  595. $sth->execute(
  596. $amount, $form->{datepaid}, $form->{"id_$i"})
  597. || $form->dberror($query, 'CP.pm',
  598. 796);
  599. %audittrail = ( tablename => $form->{arap},
  600. reference => $form->{source},
  601. formname => $form->{formname},
  602. action => 'posted',
  603. id => $form->{"id_$i"} );
  604. $form->audittrail($dbh, "", \%audittrail);
  605. }
  606. $sameid = $form->{"$form->{vc}_id_$i"};
  607. }
  608. # record a AR/AP with a payment
  609. if ($overpayment > 0 && $form->{$form->{ARAP}}) {
  610. $form->{invnumber} = "";
  611. OP::overpayment("", $myconfig, $form, $dbh, $overpayment, $ml, 1);
  612. }
  613. my $rc = $dbh->commit;
  614. $rc;
  615. }
  616. 1;