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