summaryrefslogtreecommitdiff
path: root/LedgerSMB/AA.pm
blob: 77c97b0aee8c43eaff45e241e57b76ded1e7dd0b (plain)
  1. #=====================================================================
  2. # LedgerSMB
  3. # Small Medium Business Accounting software
  4. # http://www.ledgersmb.org/
  5. # Copyright (C) 2006
  6. # This work contains copyrighted information from a number of sources all used
  7. # with permission.
  8. #
  9. # This file contains source code included with or based on SQL-Ledger which
  10. # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
  11. # under the GNU General Public License version 2 or, at your option, any later
  12. # version. For a full list including contact information of contributors,
  13. # maintainers, and copyright holders, see the CONTRIBUTORS file.
  14. #
  15. # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
  16. # Copyright (C) 2006
  17. #
  18. # Author: DWS Systems Inc.
  19. # Web: http://www.sql-ledger.org
  20. #
  21. # Contributors:
  22. #
  23. #
  24. # See COPYRIGHT file for copyright information
  25. #======================================================================
  26. #
  27. # This file has undergone whitespace cleanup.
  28. #
  29. #======================================================================
  30. #
  31. # AR/AP backend routines
  32. # common routines
  33. #
  34. #======================================================================
  35. package AA;
  36. use LedgerSMB::Sysconfig;
  37. sub post_transaction {
  38. my ($self, $myconfig, $form) = @_;
  39. # connect to database
  40. my $dbh = $form->{dbh};
  41. my $query;
  42. my $sth;
  43. my $null;
  44. ($null, $form->{department_id}) = split(/--/, $form->{department});
  45. $form->{department_id} *= 1;
  46. my $ml = 1;
  47. my $table = 'ar';
  48. my $buysell = 'buy';
  49. my $ARAP = 'AR';
  50. my $invnumber = "sinumber";
  51. my $keepcleared;
  52. if ($form->{vc} eq 'vendor') {
  53. $table = 'ap';
  54. $buysell = 'sell';
  55. $ARAP = 'AP';
  56. $ml = -1;
  57. $invnumber = "vinumber";
  58. }
  59. if ($form->{currency} eq $form->{defaultcurrency}) {
  60. $form->{exchangerate} = 1;
  61. } else {
  62. $exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, $buysell);
  63. $form->{exchangerate} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{exchangerate});
  64. }
  65. my @taxaccounts = split / /, $form->{taxaccounts};
  66. my $tax = 0;
  67. my $fxtax = 0;
  68. my $amount;
  69. my $diff;
  70. my %tax = ();
  71. my $accno;
  72. # add taxes
  73. foreach $accno (@taxaccounts) {
  74. $fxtax += $tax{fxamount}{$accno} = $form->parse_amount($myconfig, $form->{"tax_$accno"});
  75. $tax += $tax{fxamount}{$accno};
  76. push @{ $form->{acc_trans}{taxes} }, {
  77. accno => $accno,
  78. amount => $tax{fxamount}{$accno},
  79. project_id => undef,
  80. fx_transaction => 0 };
  81. $amount = $tax{fxamount}{$accno} * $form->{exchangerate};
  82. $tax{amount}{$accno} = $form->round_amount($amount - $diff, 2);
  83. $diff = $tax{amount}{$accno} - ($amount - $diff);
  84. $amount = $tax{amount}{$accno} - $tax{fxamount}{$accno};
  85. $tax += $amount;
  86. if ($form->{currency} ne $form->{defaultcurrency}) {
  87. push @{ $form->{acc_trans}{taxes} }, {
  88. accno => $accno,
  89. amount => $amount,
  90. project_id => undef,
  91. fx_transaction => 1 };
  92. }
  93. }
  94. my %amount = ();
  95. my $fxinvamount = 0;
  96. for (1 .. $form->{rowcount}) {
  97. $fxinvamount += $amount{fxamount}{$_} = $form->parse_amount($myconfig, $form->{"amount_$_"})
  98. }
  99. $form->{taxincluded} *= 1;
  100. my $i;
  101. my $project_id;
  102. my $cleared = 0;
  103. $diff = 0;
  104. # deduct tax from amounts if tax included
  105. for $i (1 .. $form->{rowcount}) {
  106. if ($amount{fxamount}{$i}) {
  107. if ($form->{taxincluded}) {
  108. $amount = ($fxinvamount) ? $fxtax * $amount{fxamount}{$i} / $fxinvamount : 0;
  109. $amount{fxamount}{$i} -= $amount;
  110. }
  111. # multiply by exchangerate
  112. $amount = $amount{fxamount}{$i} * $form->{exchangerate};
  113. $amount{amount}{$i} = $form->round_amount($amount - $diff, 2);
  114. $diff = $amount{amount}{$i} - ($amount - $diff);
  115. ($null, $project_id) = split /--/, $form->{"projectnumber_$i"};
  116. $project_id ||= undef;
  117. ($accno) = split /--/, $form->{"${ARAP}_amount_$i"};
  118. if ($keepcleared) {
  119. $cleared = ($form->{"cleared_$i"}) ? 1 : 0;
  120. }
  121. push @{ $form->{acc_trans}{lineitems} }, {
  122. accno => $accno,
  123. amount => $amount{fxamount}{$i},
  124. project_id => $project_id,
  125. description => $form->{"description_$i"},
  126. cleared => $cleared,
  127. fx_transaction => 0 };
  128. if ($form->{currency} ne $form->{defaultcurrency}) {
  129. $amount = $amount{amount}{$i} - $amount{fxamount}{$i};
  130. push @{ $form->{acc_trans}{lineitems} }, {
  131. accno => $accno,
  132. amount => $amount,
  133. project_id => $project_id,
  134. description => $form->{"description_$i"},
  135. cleared => $cleared,
  136. fx_transaction => 1 };
  137. }
  138. }
  139. }
  140. my $invnetamount = 0;
  141. for (@{ $form->{acc_trans}{lineitems} }) { $invnetamount += $_->{amount} }
  142. my $invamount = $invnetamount + $tax;
  143. # adjust paidaccounts if there is no date in the last row
  144. $form->{paidaccounts}--
  145. unless ($form->{"datepaid_$form->{paidaccounts}"});
  146. if ($form->{vc} ne "customer"){
  147. $form->{vc} = "vendor";
  148. }
  149. my $paid = 0;
  150. my $fxamount;
  151. $diff = 0;
  152. # add payments
  153. for $i (1 .. $form->{paidaccounts}) {
  154. $fxamount = $form->parse_amount($myconfig, $form->{"paid_$i"});
  155. if ($fxamount) {
  156. $paid += $fxamount;
  157. $paidamount = $fxamount * $form->{exchangerate};
  158. $amount = $form->round_amount($paidamount - $diff, 2);
  159. $diff = $amount - ($paidamount - $diff);
  160. $form->{datepaid} = $form->{"datepaid_$i"};
  161. $paid{fxamount}{$i} = $fxamount;
  162. $paid{amount}{$i} = $amount;
  163. }
  164. }
  165. $fxinvamount += $fxtax unless $form->{taxincluded};
  166. $fxinvamount = $form->round_amount($fxinvamount, 2);
  167. $invamount = $form->round_amount($invamount, 2);
  168. $paid = $form->round_amount($paid, 2);
  169. $paid = ($fxinvamount == $paid)
  170. ? $invamount
  171. : $form->round_amount($paid * $form->{exchangerate}, 2);
  172. $query = q|
  173. SELECT (SELECT value FROM defaults
  174. WHERE setting_key = 'fxgain_accno_id'),
  175. (SELECT value FROM defaults
  176. WHERE setting_key = 'fxloss_accno_id')|;
  177. my ($fxgain_accno_id, $fxloss_accno_id) = $dbh->selectrow_array($query);
  178. ($null, $form->{employee_id}) = split /--/, $form->{employee};
  179. unless ($form->{employee_id}) {
  180. ($form->{employee}, $form->{employee_id}) =
  181. $form->get_employee($dbh);
  182. }
  183. # check if id really exists
  184. if ($form->{id}) {
  185. my $id = $dbh->quote($form->{id});
  186. $keepcleared = 1;
  187. $query = qq|
  188. SELECT id
  189. FROM $table
  190. WHERE id = $id|;
  191. if ($dbh->selectrow_array($query)) {
  192. # delete detail records
  193. $query = qq|
  194. DELETE FROM acc_trans
  195. WHERE trans_id = $id|;
  196. $dbh->do($query) || $form->dberror($query);
  197. }
  198. } else {
  199. my $uid = localtime;
  200. $uid .= "$$";
  201. $query = qq|
  202. INSERT INTO $table (invnumber)
  203. VALUES ('$uid')|;
  204. $dbh->do($query) || $form->dberror($query);
  205. $query = qq|
  206. SELECT id FROM $table
  207. WHERE invnumber = '$uid'|;
  208. ($form->{id}) = $dbh->selectrow_array($query);
  209. }
  210. # record last payment date in ar/ap table
  211. $form->{datepaid} = $form->{transdate} unless $form->{datepaid};
  212. my $datepaid = ($paid) ? qq|'$form->{datepaid}'| : 'NOW';
  213. $form->{invnumber} = $form->update_defaults($myconfig, $invnumber) unless $form->{invnumber};
  214. $query = qq|
  215. UPDATE $table
  216. SET invnumber = ?,
  217. ordnumber = ?,
  218. transdate = ?,
  219. $form->{vc}_id = ?,
  220. taxincluded = ?,
  221. amount = ?,
  222. duedate = ?,
  223. paid = ?,
  224. datepaid = ?,
  225. netamount = ?,
  226. curr = ?,
  227. notes = ?,
  228. department_id = ?,
  229. employee_id = ?,
  230. ponumber = ?
  231. WHERE id = ?
  232. |;
  233. my @queryargs = ($form->{invnumber}, $form->{ordnumber},
  234. $form->{transdate}, $form->{"$form->{vc}_id"},
  235. $form->{taxincluded}, $invamount, $form->{duedate}, $paid,
  236. $datepaid, $invnetamout, $form->{currency}, $form->{notes},
  237. $form->{department_id}, $form->{employee_id},
  238. $form->{ponumber}, $form->{id});
  239. $dbh->prepare($query)->execute(@queryargs) || $form->dberror($query);
  240. @queries = $form->run_custom_queries($table, 'INSERT');
  241. # update exchangerate
  242. my $buy = $form->{exchangerate};
  243. my $sell = 0;
  244. if ($form->{vc} eq 'vendor') {
  245. $buy = 0;
  246. $sell = $form->{exchangerate};
  247. }
  248. if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
  249. $form->update_exchangerate(
  250. $dbh, $form->{currency}, $form->{transdate},
  251. $buy, $sell);
  252. }
  253. my $ref;
  254. # add individual transactions
  255. foreach $ref (@{ $form->{acc_trans}{lineitems} }) {
  256. # insert detail records in acc_trans
  257. if ($ref->{amount}) {
  258. $query = qq|
  259. INSERT INTO acc_trans
  260. (trans_id, chart_id, amount,
  261. transdate, project_id, memo,
  262. fx_transaction, cleared)
  263. VALUES (?, (SELECT id FROM chart
  264. WHERE accno = ?),
  265. ?, ?, ?, ?, ?, ?)|;
  266. @queryargs = ($form->{id}, $ref->{accno},
  267. $ref->{amount} * $ml, $form->{transdate},
  268. $ref->{project_id}, $ref->{description},
  269. $ref->{fx_transaction}, $ref->{cleared});
  270. $dbh->prepare($query)->execute(@queryargs)
  271. || $form->dberror($query);
  272. }
  273. }
  274. # save taxes
  275. foreach $ref (@{ $form->{acc_trans}{taxes} }) {
  276. if ($ref->{amount}) {
  277. $query = qq|
  278. INSERT INTO acc_trans
  279. (trans_id, chart_id, amount,
  280. transdate, fx_transaction)
  281. VALUES (?, (SELECT id FROM chart
  282. WHERE accno = ?),
  283. ?, ?, ?)|;
  284. @queryargs = ($form->{id}, $ref->{accno},
  285. $ref->{amount} * $ml, $form->{transdate},
  286. $ref->{fx_transaction});
  287. $dbh->prepare($query)->execute(@queryargs)
  288. || $form->dberror($query);
  289. }
  290. }
  291. my $arap;
  292. # record ar/ap
  293. if (($arap = $invamount)) {
  294. ($accno) = split /--/, $form->{$ARAP};
  295. $query = qq|
  296. INSERT INTO acc_trans
  297. (trans_id, chart_id, amount, transdate)
  298. VALUES (?, (SELECT id FROM chart
  299. WHERE accno = '?'),
  300. ?, ?)|;
  301. @queryargs = ($form->{id}, $accno, $invamount * -1 * $ml,
  302. $form->{transdate});
  303. $dbh->prepare($query)->execute(@queryargs)
  304. || $form->dberror($query);
  305. }
  306. # if there is no amount force ar/ap
  307. if ($fxinvamount == 0) {
  308. $arap = 1;
  309. }
  310. my $exchangerate;
  311. # add paid transactions
  312. for $i (1 .. $form->{paidaccounts}) {
  313. if ($paid{fxamount}{$i}) {
  314. ($accno) = split(/--/, $form->{"${ARAP}_paid_$i"});
  315. $form->{"datepaid_$i"} = $form->{transdate} unless ($form->{"datepaid_$i"});
  316. $exchangerate = 0;
  317. if ($form->{currency} eq $form->{defaultcurrency}) {
  318. $form->{"exchangerate_$i"} = 1;
  319. } else {
  320. $exchangerate = $form->check_exchangerate(
  321. $myconfig, $form->{currency},
  322. $form->{"datepaid_$i"}, $buysell);
  323. $form->{"exchangerate_$i"} = ($exchangerate)
  324. ? $exchangerate
  325. : $form->parse_amount(
  326. $myconfig,
  327. $form->{"exchangerate_$i"});
  328. }
  329. # if there is no amount
  330. if ($fxinvamount == 0) {
  331. $form->{exchangerate} =
  332. $form->{"exchangerate_$i"};
  333. }
  334. # ar/ap amount
  335. if ($arap) {
  336. ($accno) = split /--/, $form->{$ARAP};
  337. # add ar/ap
  338. $query = qq|
  339. INSERT INTO acc_trans
  340. (trans_id, chart_id,
  341. amount,transdate)
  342. VALUES (?, (SELECT id FROM chart
  343. WHERE accno = ?),
  344. ?, ?)|;
  345. @queryargs = ($form->{id},
  346. $paid{amount}{$i} * $ml,
  347. $form->{"datepaid_$i"});
  348. $dbh->prepare($query)->execute(@queryargs)
  349. || $form->dberror($query);
  350. }
  351. $arap = $paid{amount}{$i};
  352. # add payment
  353. if ($paid{fxamount}{$i}) {
  354. ($accno) = split /--/, $form->{"${ARAP}_paid_$i"};
  355. my $cleared = ($form->{"cleared_$i"}) ? 1 : 0;
  356. $amount = $paid{fxamount}{$i};
  357. $query = qq|
  358. INSERT INTO acc_trans
  359. (trans_id, chart_id, amount,
  360. transdate, source, memo,
  361. cleared)
  362. VALUES (?, (SELECT id FROM chart
  363. WHERE accno = ?),
  364. ? * -1 * $ml, ?, ?, ?, ?)|;
  365. @queryargs = ($form->{id}, $accno,
  366. $amount * -1 * $ml,
  367. $form->{"datepaid_$i"},
  368. $form->{"source_$i"},
  369. $form->{"memo_$i"},
  370. $cleared);
  371. $dbh->prepare($query)->execute(@queryargs)
  372. || $form->dberror($query);
  373. if ($form->{currency}
  374. ne $form->{defaultcurrency}) {
  375. # exchangerate gain/loss
  376. $amount = ($form->round_amount(
  377. $paid{fxamount}{$i}
  378. * $form->{exchangerate},2) -
  379. $form->round_amount(
  380. $paid{fxamount}{$i}
  381. * $form->{"exchangerate_$i"},
  382. 2)) * -1;
  383. if ($amount) {
  384. my $accno_id = (($amount * $ml) > 0) ? $fxgain_accno_id : $fxloss_accno_id;
  385. $query = qq|
  386. INSERT INTO acc_trans
  387. (trans_id,
  388. chart_id,
  389. amount,
  390. transdate,
  391. fx_transaction,
  392. cleared)
  393. VALUES (?, ?,
  394. ?,
  395. ?, '1', ?)|;
  396. @queryargs = ($form->{id},
  397. $accno_id,
  398. $amount * $ml,
  399. $form->{"datepaid_$i"},
  400. $cleared);
  401. $sth = $dbh->prepare($query);
  402. $sth->execute(@queryargs)
  403. ||
  404. $form->dberror($query);
  405. }
  406. # exchangerate difference
  407. $amount = $paid{amount}{$i} - $paid{fxamount}{$i} + $amount;
  408. $query = qq|
  409. INSERT INTO acc_trans
  410. (trans_id, chart_id,
  411. amount,
  412. transdate,
  413. fx_transaction,
  414. cleared, source)
  415. VALUES (?, (SELECT id
  416. FROM chart
  417. WHERE accno
  418. = ?),
  419. ?, ?, '1', ?, ?)|;
  420. @queryargs = ($form->{id}, $accno,
  421. $amount * -1 * $ml,
  422. $form->{"datepaid_$i"},
  423. $cleared, $form->{"source_$i"});
  424. $sth = $dbh->prepare($query) ;
  425. $sth->execute(@queryargs)
  426. || $form->dberror($query);
  427. }
  428. # update exchangerate record
  429. $buy = $form->{"exchangerate_$i"};
  430. $sell = 0;
  431. if ($form->{vc} eq 'vendor') {
  432. $buy = 0;
  433. $sell = $form->{"exchangerate_$i"};
  434. }
  435. if (($form->{currency} ne
  436. $form->{defaultcurrency}) && !$exchangerate) {
  437. $form->update_exchangerate(
  438. $dbh, $form->{currency},
  439. $form->{"datepaid_$i"}, $buy,
  440. $sell);
  441. }
  442. }
  443. }
  444. }
  445. # save printed and queued
  446. $form->save_status($dbh);
  447. my %audittrail = ( tablename => $table,
  448. reference => $form->{invnumber},
  449. formname => 'transaction',
  450. action => 'posted',
  451. id => $form->{id} );
  452. $form->audittrail($dbh, "", \%audittrail);
  453. $form->save_recurring($dbh, $myconfig);
  454. my $rc = $dbh->commit;
  455. $rc;
  456. }
  457. sub delete_transaction {
  458. my ($self, $myconfig, $form) = @_;
  459. # connect to database, turn AutoCommit off
  460. my $dbh = $form->{dbh};
  461. my $table = ($form->{vc} eq 'customer') ? 'ar' : 'ap';
  462. my %audittrail = ( tablename => $table,
  463. reference => $form->{invnumber},
  464. formname => 'transaction',
  465. action => 'deleted',
  466. id => $form->{id} );
  467. $form->audittrail($dbh, "", \%audittrail);
  468. my $query = qq|DELETE FROM $table WHERE id = $form->{id}|;
  469. $dbh->do($query) || $form->dberror($query);
  470. $query = qq|DELETE FROM acc_trans WHERE trans_id = ?|;
  471. $dbh->prepare($query)->execute($form->{id}) || $form->dberror($query);
  472. # get spool files
  473. $query = qq|SELECT spoolfile
  474. FROM status
  475. WHERE trans_id = ?
  476. AND spoolfile IS NOT NULL|;
  477. my $sth = $dbh->prepare($query);
  478. $sth->execute($form->{id}) || $form->dberror($query);
  479. my $spoolfile;
  480. my @spoolfiles = ();
  481. while (($spoolfile) = $sth->fetchrow_array) {
  482. push @spoolfiles, $spoolfile;
  483. }
  484. $sth->finish;
  485. $query = qq|DELETE FROM status WHERE trans_id = ?|;
  486. $dbh->prepare($query)->execute($form->{id}) || $form->dberror($query);
  487. # commit
  488. my $rc = $dbh->commit;
  489. if ($rc) {
  490. foreach $spoolfile (@spoolfiles) {
  491. unlink "${LedgerSMB::Sysconfig::spool}/$spoolfile" if $spoolfile;
  492. }
  493. }
  494. $rc;
  495. }
  496. sub transactions {
  497. my ($self, $myconfig, $form) = @_;
  498. # connect to database
  499. my $dbh = $form->{dbh};
  500. my $null;
  501. my $var;
  502. my $paid = "a.paid";
  503. my $ml = 1;
  504. my $ARAP = 'AR';
  505. my $table = 'ar';
  506. my $buysell = 'buy';
  507. my $acc_trans_join;
  508. my $acc_trans_flds;
  509. if ($form->{vc} eq 'vendor') {
  510. $ml = -1;
  511. $ARAP = 'AP';
  512. $table = 'ap';
  513. $buysell = 'sell';
  514. }
  515. ($form->{transdatefrom}, $form->{transdateto}) = $form->from_to($form->{year}, $form->{month}, $form->{interval}) if $form->{year} && $form->{month};
  516. my @paidargs = ();
  517. if ($form->{outstanding}) {
  518. $paid = qq|
  519. SELECT SUM(ac.amount) * -1 * $ml
  520. FROM acc_trans ac
  521. JOIN chart c ON (c.id = ac.chart_id)
  522. WHERE ac.trans_id = a.id
  523. AND (c.link LIKE '%${ARAP}_paid%'
  524. OR c.link = '')|;
  525. if ($form->{transdateto}){
  526. $paid .= qq|
  527. AND ac.transdate <= ?|;
  528. push @paidargs, $form->{transdateto};
  529. }
  530. $form->{summary} = 1;
  531. }
  532. if (!$form->{summary}) {
  533. $acc_trans_flds = qq|
  534. , c.accno, ac.source,
  535. pr.projectnumber, ac.memo AS description,
  536. ac.amount AS linetotal,
  537. i.description AS linedescription|;
  538. $acc_trans_join = qq|
  539. JOIN acc_trans ac ON (a.id = ac.trans_id)
  540. JOIN chart c ON (c.id = ac.chart_id)
  541. LEFT JOIN project pr ON (pr.id = ac.project_id)
  542. LEFT JOIN invoice i ON (i.id = ac.invoice_id)|;
  543. }
  544. my $query = qq|
  545. SELECT a.id, a.invnumber, a.ordnumber, a.transdate,
  546. a.duedate, a.netamount, a.amount, ($paid) AS paid,
  547. a.invoice, a.datepaid, a.terms, a.notes,
  548. a.shipvia, a.shippingpoint, e.name AS employee,
  549. vc.name,
  550. a.$form->{vc}_id, a.till, m.name AS manager, a.curr,
  551. ex.$buysell AS exchangerate,
  552. d.description AS department,
  553. a.ponumber $acc_trans_flds
  554. FROM $table a
  555. JOIN $form->{vc} vc ON (a.$form->{vc}_id = vc.id)
  556. LEFT JOIN employees e ON (a.employee_id = e.id)
  557. LEFT JOIN employees m ON (e.managerid = m.id)
  558. LEFT JOIN exchangerate ex ON (ex.curr = a.curr
  559. AND ex.transdate = a.transdate)
  560. LEFT JOIN department d ON (a.department_id = d.id)
  561. $acc_trans_join|;
  562. my %ordinal = ( id => 1,
  563. invnumber => 2,
  564. ordnumber => 3,
  565. transdate => 4,
  566. duedate => 5,
  567. datepaid => 10,
  568. shipvia => 13,
  569. shippingpoint => 14,
  570. employee => 15,
  571. name => 16,
  572. manager => 19,
  573. curr => 20,
  574. department => 22,
  575. ponumber => 23,
  576. accno => 24,
  577. source => 25,
  578. project => 26,
  579. description => 27);
  580. my @a = (transdate, invnumber, name);
  581. push @a, "employee" if $form->{l_employee};
  582. push @a, "manager" if $form->{l_manager};
  583. my $sortorder = $form->sort_order(\@a, \%ordinal);
  584. my $where = "1 = 1";
  585. if ($form->{"$form->{vc}_id"}) {
  586. $where .= qq| AND a.$form->{vc}_id = $form->{"$form->{vc}_id"}|;
  587. } else {
  588. if ($form->{$form->{vc}}) {
  589. $var = $dbh->quote(
  590. $form->like(lc $form->{$form->{vc}}));
  591. $where .= " AND lower(vc.name) LIKE $var";
  592. }
  593. }
  594. for (qw(department employee)) {
  595. if ($form->{$_}) {
  596. ($null, $var) = split /--/, $form->{$_};
  597. $var = $dbh->quote($var);
  598. $where .= " AND a.${_}_id = $var";
  599. }
  600. }
  601. for (qw(invnumber ordnumber)) {
  602. if ($form->{$_}) {
  603. $var = $dbh->quote($form->like(lc $form->{$_}));
  604. $where .= " AND lower(a.$_) LIKE $var";
  605. $form->{open} = $form->{closed} = 0;
  606. }
  607. }
  608. if ($form->{partsid}){
  609. my $partsid = $dbh->quote($form->{partsid});
  610. $where .= " AND a.id IN (select trans_id FROM invoice
  611. WHERE parts_id = $partsid)";
  612. }
  613. for (qw(ponumber shipvia notes)) {
  614. if ($form->{$_}) {
  615. $var = $dbh->quote($form->like(lc $form->{$_}));
  616. $where .= " AND lower(a.$_) LIKE $var";
  617. }
  618. }
  619. if ($form->{description}) {
  620. if ($acc_trans_flds) {
  621. $var = $dbh->quote(
  622. $form->like(lc $form->{description})
  623. );
  624. $where .= " AND lower(ac.memo) LIKE $var
  625. OR lower(i.description) LIKE $var";
  626. } else {
  627. $where .= " AND a.id = 0";
  628. }
  629. }
  630. if ($form->{source}) {
  631. if ($acc_trans_flds) {
  632. $var = $dbh->quote($form->like(lc $form->{source}));
  633. $where .= " AND lower(ac.source) LIKE $var";
  634. } else {
  635. $where .= " AND a.id = 0";
  636. }
  637. }
  638. my $transdatefrom = $dbh->quote($form->{transdatefrom});
  639. $where .= " AND a.transdate >= $transdatefrom"
  640. if $form->{transdatefrom};
  641. my $transdateto = $dbh->quote($form->{transdateto});
  642. $where .= " AND a.transdate <= $transdateto" if $form->{transdateto};
  643. if ($form->{open} || $form->{closed}) {
  644. unless ($form->{open} && $form->{closed}) {
  645. $where .= " AND a.amount != a.paid" if ($form->{open});
  646. $where .= " AND a.amount = a.paid" if ($form->{closed});
  647. }
  648. }
  649. if ($form->{till} ne "") {
  650. $where .= " AND a.invoice = '1'
  651. AND a.till = $form->{till}";
  652. if ($myconfig->{role} eq 'user') {
  653. my $login = $dbh->quote($form->{login});
  654. $where .= " AND e.login = $login";
  655. }
  656. }
  657. if ($form->{$ARAP}) {
  658. my ($accno) = split /--/, $form->{$ARAP};
  659. $accno = $dbh->quote($accno);
  660. $where .= qq|
  661. AND a.id IN (SELECT ac.trans_id
  662. FROM acc_trans ac
  663. JOIN chart c ON (c.id = ac.chart_id)
  664. WHERE a.id = ac.trans_id
  665. AND c.accno = $accno)|;
  666. }
  667. if ($form->{description}) {
  668. $var = $dbh->quote($form->like(lc $form->{description}));
  669. $where .= qq|
  670. AND (a.id IN (SELECT DISTINCT trans_id
  671. FROM acc_trans
  672. WHERE lower(memo) LIKE '$var')
  673. OR a.id IN
  674. (SELECT DISTINCT trans_id
  675. FROM invoice
  676. WHERE lower(description)
  677. LIKE '$var'))|;
  678. }
  679. $query .= "WHERE $where
  680. ORDER BY $sortorder";
  681. my $sth = $dbh->prepare($query);
  682. $sth->execute(@paidargs) || $form->dberror($query);
  683. while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
  684. $ref->{exchangerate} = 1 unless $ref->{exchangerate};
  685. if ($ref->{linetotal} <= 0) {
  686. $ref->{debit} = $ref->{linetotal} * -1;
  687. $ref->{credit} = 0;
  688. } else {
  689. $ref->{debit} = 0;
  690. $ref->{credit} = $ref->{linetotal};
  691. }
  692. if ($ref->{invoice}) {
  693. $ref->{description} ||= $ref->{linedescription};
  694. }
  695. if ($form->{outstanding}) {
  696. next if $form->round_amount($ref->{amount}, 2)
  697. == $form->round_amount($ref->{paid}, 2);
  698. }
  699. push @{ $form->{transactions} }, $ref;
  700. }
  701. $sth->finish;
  702. $dbh->commit;
  703. }
  704. # this is used in IS, IR to retrieve the name
  705. sub get_name {
  706. my ($self, $myconfig, $form) = @_;
  707. # sanitize $form->{vc}
  708. if ($form->{vc} ne 'customer'){
  709. $form->{vc} = 'vendor';
  710. } else {
  711. $form->{vc} = 'customer';
  712. }
  713. # connect to database
  714. my $dbh = $form->{dbh};
  715. my $dateformat = $myconfig->{dateformat};
  716. if ($myconfig->{dateformat} !~ /^y/) {
  717. my @a = split /\W/, $form->{transdate};
  718. $dateformat .= "yy" if (length $a[2] > 2);
  719. }
  720. if ($form->{transdate} !~ /\W/) {
  721. $dateformat = 'yyyymmdd';
  722. }
  723. my $duedate;
  724. $dateformat = $dbh->quote($dateformat);
  725. my $tdate = $dbh->quote($form->{transdate});
  726. $duedate = ($form->{transdate})
  727. ? "to_date($tdate, $dateformat)
  728. + c.terms"
  729. : "current_date + c.terms";
  730. $form->{"$form->{vc}_id"} *= 1;
  731. # get customer/vendor
  732. my $query = qq|
  733. SELECT c.name AS $form->{vc}, c.discount, c.creditlimit,
  734. c.terms, c.email, c.cc, c.bcc, c.taxincluded,
  735. c.address1, c.address2, c.city, c.state,
  736. c.zipcode, c.country, c.curr AS currency,
  737. c.language_code, $duedate AS duedate,
  738. c.notes AS intnotes,
  739. b.discount AS tradediscount,
  740. b.description AS business,
  741. e.name AS employee, e.id AS employee_id
  742. FROM $form->{vc} c
  743. LEFT JOIN business b ON (b.id = c.business_id)
  744. LEFT JOIN employees e ON (e.id = c.employee_id)
  745. WHERE c.id = ?|;
  746. @queryargs = ($form->{"$form->{vc}_id"});
  747. my $sth = $dbh->prepare($query);
  748. $sth->execute(@queryargs) || $form->dberror($query);
  749. $ref = $sth->fetchrow_hashref(NAME_lc);
  750. if ($form->{id}) {
  751. for (qw(currency employee employee_id intnotes)) {
  752. delete $ref->{$_};
  753. }
  754. }
  755. for (keys %$ref) { $form->{$_} = $ref->{$_} }
  756. $sth->finish;
  757. my $buysell = ($form->{vc} eq 'customer') ? "buy" : "sell";
  758. # if no currency use defaultcurrency
  759. $form->{currency} =
  760. ($form->{currency})
  761. ? $form->{currency}
  762. : $form->{defaultcurrency};
  763. $form->{exchangerate} = 0
  764. if $form->{currency} eq $form->{defaultcurrency};
  765. if ($form->{transdate} && ($form->{currency}
  766. ne $form->{defaultcurrency})) {
  767. $form->{exchangerate} = $form->get_exchangerate(
  768. $dbh, $form->{currency}, $form->{transdate}, $buysell);
  769. }
  770. $form->{forex} = $form->{exchangerate};
  771. # if no employee, default to login
  772. ($form->{employee}, $form->{employee_id}) = $form->get_employee($dbh)
  773. unless $form->{employee_id};
  774. my $arap = ($form->{vc} eq 'customer') ? 'ar' : 'ap';
  775. my $ARAP = uc $arap;
  776. $form->{creditremaining} = $form->{creditlimit};
  777. $query = qq|
  778. SELECT SUM(amount - paid)
  779. FROM $arap
  780. WHERE $form->{vc}_id = ?|;
  781. $sth = $dbh->prepare($query);
  782. $sth->execute($form->{"$form->{vc}_id"})
  783. || $form->dberror($query);
  784. ($form->{creditremaining}) -= $sth->fetchrow_array;
  785. $sth->finish;
  786. if ($form->{vc} ne "customer"){
  787. $form->{vc} = 'vendor';
  788. }
  789. $query = qq|
  790. SELECT o.amount, (SELECT e.$buysell FROM exchangerate e
  791. WHERE e.curr = o.curr
  792. AND e.transdate = o.transdate)
  793. FROM oe o
  794. WHERE o.$form->{vc}_id = ?
  795. AND o.quotation = '0' AND o.closed = '0'|;
  796. $sth = $dbh->prepare($query);
  797. $sth->execute ($form->{"$form->{vc}_id"}) || $form->dberror($query);
  798. while (my ($amount, $exch) = $sth->fetchrow_array) {
  799. $exch = 1 unless $exch;
  800. $form->{creditremaining} -= $amount * $exch;
  801. }
  802. $sth->finish;
  803. # get shipto if we did not converted an order or invoice
  804. if (!$form->{shipto}) {
  805. for (
  806. qw(shiptoname shiptoaddress1 shiptoaddress2
  807. shiptocity shiptostate shiptozipcode
  808. shiptocountry shiptocontact shiptophone
  809. shiptofax shiptoemail)
  810. ) {
  811. delete $form->{$_}
  812. }
  813. ## needs fixing (SELECT *)
  814. $query = qq|
  815. SELECT *
  816. FROM shipto
  817. WHERE trans_id = $form->{"$form->{vc}_id"}|;
  818. $sth = $dbh->prepare($query);
  819. $sth->execute || $form->dberror($query);
  820. $ref = $sth->fetchrow_hashref(NAME_lc);
  821. for (keys %$ref) { $form->{$_} = $ref->{$_} }
  822. $sth->finish;
  823. }
  824. # get taxes
  825. $query = qq|
  826. SELECT c.accno
  827. FROM chart c
  828. JOIN $form->{vc}tax ct ON (ct.chart_id = c.id)
  829. WHERE ct.$form->{vc}_id = ?|;
  830. $sth = $dbh->prepare($query);
  831. $sth->execute( $form->{"$form->{vc}_id"}) || $form->dberror($query);
  832. my %tax;
  833. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  834. $tax{$ref->{accno}} = 1;
  835. }
  836. $sth->finish;
  837. $transdate = $dbh->quote($form->{transdate});
  838. my $where = qq|AND (t.validto >= $transdate OR t.validto IS NULL)|
  839. if $form->{transdate};
  840. # get tax rates and description
  841. $query = qq|
  842. SELECT c.accno, c.description, t.rate, t.taxnumber
  843. FROM chart c
  844. JOIN tax t ON (c.id = t.chart_id)
  845. WHERE c.link LIKE '%${ARAP}_tax%'
  846. $where
  847. ORDER BY accno, validto|;
  848. $sth = $dbh->prepare($query);
  849. $sth->execute || $form->dberror($query);
  850. $form->{taxaccounts} = "";
  851. my %a = ();
  852. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  853. if ($tax{$ref->{accno}}) {
  854. if (not exists $a{$ref->{accno}}) {
  855. for (qw(rate description taxnumber)) {
  856. $form->{"$ref->{accno}_$_"} =
  857. $ref->{$_};
  858. }
  859. $form->{taxaccounts} .= "$ref->{accno} ";
  860. $a{$ref->{accno}} = 1;
  861. }
  862. }
  863. }
  864. $sth->finish;
  865. chop $form->{taxaccounts};
  866. # setup last accounts used for this customer/vendor
  867. if (!$form->{id} && $form->{type} !~ /_(order|quotation)/) {
  868. $query = qq|
  869. SELECT c.accno, c.description, c.link, c.category,
  870. ac.project_id, p.projectnumber,
  871. a.department_id, d.description AS department
  872. FROM chart c
  873. JOIN acc_trans ac ON (ac.chart_id = c.id)
  874. JOIN $arap a ON (a.id = ac.trans_id)
  875. LEFT JOIN project p ON (ac.project_id = p.id)
  876. LEFT JOIN department d ON (d.id = a.department_id)
  877. WHERE a.$form->{vc}_id = ?
  878. AND a.id IN (SELECT max(id)
  879. FROM $arap
  880. WHERE $form->{vc}_id =
  881. ?)
  882. |;
  883. $sth = $dbh->prepare($query);
  884. $sth->execute($form->{"$form->{vc}_id"},
  885. $form->{"$form->{vc}_id"}) || $form->dberror($query);
  886. my $i = 0;
  887. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  888. $form->{department} = $ref->{department};
  889. $form->{department_id} = $ref->{department_id};
  890. if ($ref->{link} =~ /_amount/) {
  891. $i++;
  892. $form->{"$form->{ARAP}_amount_$i"} =
  893. "$ref->{accno}--$ref->{description}"
  894. if $ref->{accno};
  895. $form->{"projectnumber_$i"} =
  896. "$ref->{projectnumber}--" .
  897. "$ref->{project_id}"
  898. if $ref->{project_id};
  899. }
  900. if ($ref->{link} eq $form->{ARAP}) {
  901. $form->{$form->{ARAP}} =
  902. $form->{"$form->{ARAP}_1"} =
  903. "$ref->{accno}--".
  904. "$ref->{description}"
  905. if $ref->{accno};
  906. }
  907. }
  908. $sth->finish;
  909. $form->{rowcount} = $i if ($i && !$form->{type});
  910. }
  911. $dbh->commit;
  912. }
  913. 1;