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