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