summaryrefslogtreecommitdiff
path: root/LedgerSMB/CP.pm
blob: b5aa6258ea9bf84c4beba05826cd278a737f56f4 (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->{datepaid}, $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. ($id) = $sth->fetchrow_array();
  510. $paid = ($form->{"paid_$i"} > $form->{"due_$i"}) ? $form->{"due_$i"} : $form->{"paid_$i"};
  511. $amount = $form->round_amount($paid * $exchangerate, 2);
  512. # add AR/AP
  513. $query = qq|
  514. INSERT INTO acc_trans
  515. (trans_id, chart_id, transdate,
  516. amount)
  517. VALUES (?, ?, ?, ?)|;
  518. $sth = $dbh->prepare($query);
  519. $sth->execute(
  520. $form->{"id_$i"}, $id, $form->{datepaid},
  521. $amount * $ml)
  522. || $form->dberror($query, 'CP.pm',
  523. 701);
  524. $query = qq|SELECT id
  525. FROM chart
  526. WHERE accno = ?|;
  527. $sth = $dbh->prepare($query);
  528. $sth->execute($paymentaccno);
  529. ($accno_id) = $sth->fetchrow_array;
  530. # add payment
  531. $query = qq|
  532. INSERT INTO acc_trans
  533. (trans_id, chart_id, transdate,
  534. amount, source, memo)
  535. VALUES (?, ?, ?, ?, ?, ?)|;
  536. $sth = $dbh->prepare($query);
  537. $sth->execute(
  538. $form->{"id_$i"}, $accno_id, $form->{datepaid},
  539. $paid * $ml * -1, $form->{source},
  540. $form->{memo})
  541. || $form->dberror($query, 'CP.pm',
  542. 723);
  543. # add exchangerate difference if currency ne defaultcurrency
  544. $amount =
  545. $form->round_amount(
  546. $paid * ($form->{exchangerate} - 1)
  547. * $ml * -1,
  548. 2);
  549. if ($amount) {
  550. # exchangerate difference
  551. $query = qq|
  552. INSERT INTO acc_trans
  553. (trans_id, chart_id,
  554. transdate,
  555. amount, source)
  556. VALUES (?, ?, ?, ?, ?)|;
  557. $sth = $dbh->prepare($query);
  558. $sth->execute(
  559. $form->{"id_$i"}, $accno_id,
  560. $form->{datepaid}, $amount,
  561. $form->{source})
  562. || $form->dberror(
  563. $query, 'CP.pm', 748);
  564. # gain/loss
  565. $amount = ($form->round_amount($paid * $exchangerate,2) - $form->round_amount($paid * $form->{exchangerate},2)) * $ml * -1;
  566. if ($amount) {
  567. $accno_id =
  568. ($amount > 0)
  569. ? $fxgain_accno_id
  570. : $fxloss_accno_id;
  571. $query = qq|
  572. INSERT INTO acc_trans
  573. (trans_id,
  574. chart_id,
  575. transdate,
  576. amount,
  577. fx_transaction)
  578. VALUES (?, ?, ?, ?, '1')|;
  579. $sth = $dbh->prepare($query);
  580. $sth->execute(
  581. $form->{"id_$i"}, $accno_id,
  582. $form->{datepaid}, $amount)
  583. || $form->dberror(
  584. $query,
  585. 'CP.pm', 775);
  586. }
  587. }
  588. $paid = $form->round_amount($paid * $exchangerate, 2);
  589. $pth->execute($form->{"id_$i"}) || $form->dberror;
  590. ($amount) = $pth->fetchrow_array;
  591. $pth->finish;
  592. $amount += $paid;
  593. # update AR/AP transaction
  594. $query = qq|
  595. UPDATE $form->{arap}
  596. SET paid = ?,
  597. datepaid = ?
  598. WHERE id = ?|;
  599. $sth = $dbh->prepare($query);
  600. $sth->execute(
  601. $amount, $form->{datepaid}, $form->{"id_$i"})
  602. || $form->dberror($query, 'CP.pm',
  603. 796);
  604. %audittrail = ( tablename => $form->{arap},
  605. reference => $form->{source},
  606. formname => $form->{formname},
  607. action => 'posted',
  608. id => $form->{"id_$i"} );
  609. $form->audittrail($dbh, "", \%audittrail);
  610. }
  611. $sameid = $form->{"$form->{vc}_id_$i"};
  612. }
  613. # record a AR/AP with a payment
  614. if ($overpayment > 0 && $form->{$form->{ARAP}}) {
  615. $form->{invnumber} = "";
  616. OP::overpayment("", $myconfig, $form, $dbh, $overpayment, $ml, 1);
  617. }
  618. my $rc = $dbh->commit;
  619. $rc;
  620. }
  621. 1;