summaryrefslogtreecommitdiff
path: root/LedgerSMB/AA.pm
blob: f5b8a4708d7e8bf45f822066958b38e5a1032ca7 (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->dbconnect_noauto($myconfig);
  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}-- unless ($form->{"datepaid_$form->{paidaccounts}"});
  144. my $paid = 0;
  145. my $fxamount;
  146. $diff = 0;
  147. # add payments
  148. for $i (1 .. $form->{paidaccounts}) {
  149. $fxamount = $form->parse_amount($myconfig, $form->{"paid_$i"});
  150. if ($fxamount) {
  151. $paid += $fxamount;
  152. $paidamount = $fxamount * $form->{exchangerate};
  153. $amount = $form->round_amount($paidamount - $diff, 2);
  154. $diff = $amount - ($paidamount - $diff);
  155. $form->{datepaid} = $form->{"datepaid_$i"};
  156. $paid{fxamount}{$i} = $fxamount;
  157. $paid{amount}{$i} = $amount;
  158. }
  159. }
  160. $fxinvamount += $fxtax unless $form->{taxincluded};
  161. $fxinvamount = $form->round_amount($fxinvamount, 2);
  162. $invamount = $form->round_amount($invamount, 2);
  163. $paid = $form->round_amount($paid, 2);
  164. $paid = ($fxinvamount == $paid) ? $invamount : $form->round_amount($paid * $form->{exchangerate}, 2);
  165. $query = q|SELECT fxgain_accno_id, fxloss_accno_id
  166. FROM defaults|;
  167. my ($fxgain_accno_id, $fxloss_accno_id) = $dbh->selectrow_array($query);
  168. ($null, $form->{employee_id}) = split /--/, $form->{employee};
  169. unless ($form->{employee_id}) {
  170. ($form->{employee}, $form->{employee_id}) = $form->get_employee($dbh);
  171. }
  172. # check if id really exists
  173. if ($form->{id}) {
  174. $keepcleared = 1;
  175. $query = qq|SELECT id FROM $table
  176. WHERE id = $form->{id}|;
  177. if ($dbh->selectrow_array($query)) {
  178. # delete detail records
  179. $query = qq|DELETE FROM acc_trans
  180. WHERE trans_id = $form->{id}|;
  181. $dbh->do($query) || $form->dberror($query);
  182. }
  183. } else {
  184. my $uid = localtime;
  185. $uid .= "$$";
  186. $query = qq|INSERT INTO $table (invnumber)
  187. VALUES ('$uid')|;
  188. $dbh->do($query) || $form->dberror($query);
  189. $query = qq|SELECT id FROM $table
  190. WHERE invnumber = '$uid'|;
  191. ($form->{id}) = $dbh->selectrow_array($query);
  192. }
  193. # record last payment date in ar/ap table
  194. $form->{datepaid} = $form->{transdate} unless $form->{datepaid};
  195. my $datepaid = ($paid) ? qq|'$form->{datepaid}'| : 'NULL';
  196. $form->{invnumber} = $form->update_defaults($myconfig, $invnumber) unless $form->{invnumber};
  197. $query = qq|
  198. UPDATE $table
  199. SET invnumber = |.$dbh->quote($form->{invnumber}).qq|,
  200. ordnumber = |.$dbh->quote($form->{ordnumber}).qq|,
  201. transdate = '$form->{transdate}',
  202. $form->{vc}_id = $form->{"$form->{vc}_id"},
  203. taxincluded = '$form->{taxincluded}',
  204. amount = $invamount,
  205. duedate = '$form->{duedate}',
  206. paid = $paid,
  207. datepaid = $datepaid,
  208. netamount = $invnetamount,
  209. curr = '$form->{currency}',
  210. notes = |.$dbh->quote($form->{notes}).qq|,
  211. department_id = $form->{department_id},
  212. employee_id = $form->{employee_id},
  213. ponumber = |.$dbh->quote($form->{ponumber}).qq|
  214. WHERE id = $form->{id}
  215. |;
  216. $dbh->do($query) || $form->dberror($query);
  217. @queries = $form->get_custom_queries($table, 'INSERT');
  218. for (@queries){
  219. $query = shift (@{$_});
  220. $sth = $dbh->prepare($query) || $form->db_error($query);
  221. $sth->execute(@{$_}, $form->{id})|| $form->dberror($query);;
  222. $sth->finish;
  223. $did_insert = 1;
  224. }
  225. # update exchangerate
  226. my $buy = $form->{exchangerate};
  227. my $sell = 0;
  228. if ($form->{vc} eq 'vendor') {
  229. $buy = 0;
  230. $sell = $form->{exchangerate};
  231. }
  232. if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
  233. $form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, $buy, $sell);
  234. }
  235. my $ref;
  236. # add individual transactions
  237. foreach $ref (@{ $form->{acc_trans}{lineitems} }) {
  238. # insert detail records in acc_trans
  239. if ($ref->{amount}) {
  240. $query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate,
  241. project_id, memo, fx_transaction, cleared)
  242. VALUES ($form->{id}, (SELECT id FROM chart
  243. WHERE accno = '$ref->{accno}'),
  244. $ref->{amount} * $ml, '$form->{transdate}',
  245. $ref->{project_id}, |.$dbh->quote($ref->{description}).qq|,
  246. '$ref->{fx_transaction}', '$ref->{cleared}')|;
  247. $dbh->do($query) || $form->dberror($query);
  248. }
  249. }
  250. # save taxes
  251. foreach $ref (@{ $form->{acc_trans}{taxes} }) {
  252. if ($ref->{amount}) {
  253. $query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
  254. transdate, fx_transaction)
  255. VALUES ($form->{id},
  256. (SELECT id FROM chart
  257. WHERE accno = '$ref->{accno}'),
  258. $ref->{amount} * $ml, '$form->{transdate}',
  259. '$ref->{fx_transaction}')|;
  260. $dbh->do($query) || $form->dberror($query);
  261. }
  262. }
  263. my $arap;
  264. # record ar/ap
  265. if (($arap = $invamount)) {
  266. ($accno) = split /--/, $form->{$ARAP};
  267. $query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate)
  268. VALUES ($form->{id},
  269. (SELECT id FROM chart
  270. WHERE accno = '$accno'),
  271. $invamount * -1 * $ml, '$form->{transdate}')|;
  272. $dbh->do($query) || $form->dberror($query);
  273. }
  274. # if there is no amount force ar/ap
  275. if ($fxinvamount == 0) {
  276. $arap = 1;
  277. }
  278. my $exchangerate;
  279. # add paid transactions
  280. for $i (1 .. $form->{paidaccounts}) {
  281. if ($paid{fxamount}{$i}) {
  282. ($accno) = split(/--/, $form->{"${ARAP}_paid_$i"});
  283. $form->{"datepaid_$i"} = $form->{transdate} unless ($form->{"datepaid_$i"});
  284. $exchangerate = 0;
  285. if ($form->{currency} eq $form->{defaultcurrency}) {
  286. $form->{"exchangerate_$i"} = 1;
  287. } else {
  288. $exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, $buysell);
  289. $form->{"exchangerate_$i"} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{"exchangerate_$i"});
  290. }
  291. # if there is no amount
  292. if ($fxinvamount == 0) {
  293. $form->{exchangerate} = $form->{"exchangerate_$i"};
  294. }
  295. # ar/ap amount
  296. if ($arap) {
  297. ($accno) = split /--/, $form->{$ARAP};
  298. # add ar/ap
  299. $query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,transdate)
  300. VALUES ($form->{id}, (SELECT id FROM chart
  301. WHERE accno = '$accno'),
  302. $paid{amount}{$i} * $ml, '$form->{"datepaid_$i"}')|;
  303. $dbh->do($query) || $form->dberror($query);
  304. }
  305. $arap = $paid{amount}{$i};
  306. # add payment
  307. if ($paid{fxamount}{$i}) {
  308. ($accno) = split /--/, $form->{"${ARAP}_paid_$i"};
  309. my $cleared = ($form->{"cleared_$i"}) ? 1 : 0;
  310. $amount = $paid{fxamount}{$i};
  311. $query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
  312. transdate, source, memo, cleared)
  313. VALUES ($form->{id}, (SELECT id FROM chart
  314. WHERE accno = '$accno'),
  315. $amount * -1 * $ml, '$form->{"datepaid_$i"}', |
  316. .$dbh->quote($form->{"source_$i"}).qq|, |
  317. .$dbh->quote($form->{"memo_$i"}).qq|, '$cleared')|;
  318. $dbh->do($query) || $form->dberror($query);
  319. if ($form->{currency} ne $form->{defaultcurrency}) {
  320. # exchangerate gain/loss
  321. $amount = ($form->round_amount($paid{fxamount}{$i} * $form->{exchangerate},2) - $form->round_amount($paid{fxamount}{$i} * $form->{"exchangerate_$i"},2)) * -1;
  322. if ($amount) {
  323. my $accno_id = (($amount * $ml) > 0) ? $fxgain_accno_id : $fxloss_accno_id;
  324. $query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
  325. transdate, fx_transaction, cleared)
  326. VALUES ($form->{id}, $accno_id,
  327. $amount * $ml, '$form->{"datepaid_$i"}', '1',
  328. '$cleared')|;
  329. $dbh->do($query) || $form->dberror($query);
  330. }
  331. # exchangerate difference
  332. $amount = $paid{amount}{$i} - $paid{fxamount}{$i} + $amount;
  333. $query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
  334. transdate, fx_transaction, cleared, source)
  335. VALUES ($form->{id}, (SELECT id FROM chart
  336. WHERE accno = '$accno'),
  337. $amount * -1 * $ml, '$form->{"datepaid_$i"}', '1',
  338. '$cleared', |
  339. .$dbh->quote($form->{"source_$i"}).qq|)|;
  340. $dbh->do($query) || $form->dberror($query);
  341. }
  342. # update exchangerate record
  343. $buy = $form->{"exchangerate_$i"};
  344. $sell = 0;
  345. if ($form->{vc} eq 'vendor') {
  346. $buy = 0;
  347. $sell = $form->{"exchangerate_$i"};
  348. }
  349. if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
  350. $form->update_exchangerate($dbh, $form->{currency}, $form->{"datepaid_$i"}, $buy, $sell);
  351. }
  352. }
  353. }
  354. }
  355. # save printed and queued
  356. $form->save_status($dbh);
  357. my %audittrail = ( tablename => $table,
  358. reference => $form->{invnumber},
  359. formname => 'transaction',
  360. action => 'posted',
  361. id => $form->{id} );
  362. $form->audittrail($dbh, "", \%audittrail);
  363. $form->save_recurring($dbh, $myconfig);
  364. my $rc = $dbh->commit;
  365. $dbh->disconnect;
  366. $rc;
  367. }
  368. sub delete_transaction {
  369. my ($self, $myconfig, $form) = @_;
  370. # connect to database, turn AutoCommit off
  371. my $dbh = $form->dbconnect_noauto($myconfig);
  372. my $table = ($form->{vc} eq 'customer') ? 'ar' : 'ap';
  373. my %audittrail = ( tablename => $table,
  374. reference => $form->{invnumber},
  375. formname => 'transaction',
  376. action => 'deleted',
  377. id => $form->{id} );
  378. $form->audittrail($dbh, "", \%audittrail);
  379. my $query = qq|DELETE FROM $table WHERE id = $form->{id}|;
  380. $dbh->do($query) || $form->dberror($query);
  381. $query = qq|DELETE FROM acc_trans WHERE trans_id = $form->{id}|;
  382. $dbh->do($query) || $form->dberror($query);
  383. # get spool files
  384. $query = qq|SELECT spoolfile
  385. FROM status
  386. WHERE trans_id = $form->{id}
  387. AND spoolfile IS NOT NULL|;
  388. my $sth = $dbh->prepare($query);
  389. $sth->execute || $form->dberror($query);
  390. my $spoolfile;
  391. my @spoolfiles = ();
  392. while (($spoolfile) = $sth->fetchrow_array) {
  393. push @spoolfiles, $spoolfile;
  394. }
  395. $sth->finish;
  396. $query = qq|DELETE FROM status WHERE trans_id = $form->{id}|;
  397. $dbh->do($query) || $form->dberror($query);
  398. # commit
  399. my $rc = $dbh->commit;
  400. $dbh->disconnect;
  401. if ($rc) {
  402. foreach $spoolfile (@spoolfiles) {
  403. unlink "$spool/$spoolfile" if $spoolfile;
  404. }
  405. }
  406. $rc;
  407. }
  408. sub transactions {
  409. my ($self, $myconfig, $form) = @_;
  410. # connect to database
  411. my $dbh = $form->dbconnect($myconfig);
  412. my $null;
  413. my $var;
  414. my $paid = "a.paid";
  415. my $ml = 1;
  416. my $ARAP = 'AR';
  417. my $table = 'ar';
  418. my $buysell = 'buy';
  419. my $acc_trans_join;
  420. my $acc_trans_flds;
  421. if ($form->{vc} eq 'vendor') {
  422. $ml = -1;
  423. $ARAP = 'AP';
  424. $table = 'ap';
  425. $buysell = 'sell';
  426. }
  427. ($form->{transdatefrom}, $form->{transdateto}) = $form->from_to($form->{year}, $form->{month}, $form->{interval}) if $form->{year} && $form->{month};
  428. if ($form->{outstanding}) {
  429. $paid = qq|SELECT SUM(ac.amount) * -1 * $ml
  430. FROM acc_trans ac
  431. JOIN chart c ON (c.id = ac.chart_id)
  432. WHERE ac.trans_id = a.id
  433. AND (c.link LIKE '%${ARAP}_paid%' OR c.link = '')|;
  434. $paid .= qq|
  435. AND ac.transdate <= '$form->{transdateto}'| if $form->{transdateto};
  436. $form->{summary} = 1;
  437. }
  438. if (!$form->{summary}) {
  439. $acc_trans_flds = qq|, c.accno, ac.source,
  440. pr.projectnumber, ac.memo AS description,
  441. ac.amount AS linetotal,
  442. i.description AS linedescription|;
  443. $acc_trans_join = qq| JOIN acc_trans ac ON (a.id = ac.trans_id)
  444. JOIN chart c ON (c.id = ac.chart_id)
  445. LEFT JOIN project pr ON (pr.id = ac.project_id)
  446. LEFT JOIN invoice i ON (i.id = ac.invoice_id)|;
  447. }
  448. my $query = qq|SELECT a.id, a.invnumber, a.ordnumber, a.transdate,
  449. a.duedate, a.netamount, a.amount, ($paid) AS paid,
  450. a.invoice, a.datepaid, a.terms, a.notes,
  451. a.shipvia, a.shippingpoint, e.name AS employee, vc.name,
  452. a.$form->{vc}_id, a.till, m.name AS manager, a.curr,
  453. ex.$buysell AS exchangerate, d.description AS department,
  454. a.ponumber $acc_trans_flds
  455. FROM $table a
  456. JOIN $form->{vc} vc ON (a.$form->{vc}_id = vc.id)
  457. LEFT JOIN employee e ON (a.employee_id = e.id)
  458. LEFT JOIN employee m ON (e.managerid = m.id)
  459. LEFT JOIN exchangerate ex ON (ex.curr = a.curr
  460. AND ex.transdate = a.transdate)
  461. LEFT JOIN department d ON (a.department_id = d.id)
  462. $acc_trans_join|;
  463. my %ordinal = ( id => 1,
  464. invnumber => 2,
  465. ordnumber => 3,
  466. transdate => 4,
  467. duedate => 5,
  468. datepaid => 10,
  469. shipvia => 13,
  470. shippingpoint => 14,
  471. employee => 15,
  472. name => 16,
  473. manager => 19,
  474. curr => 20,
  475. department => 22,
  476. ponumber => 23,
  477. accno => 24,
  478. source => 25,
  479. project => 26,
  480. description => 27);
  481. my @a = (transdate, invnumber, name);
  482. push @a, "employee" if $form->{l_employee};
  483. push @a, "manager" if $form->{l_manager};
  484. my $sortorder = $form->sort_order(\@a, \%ordinal);
  485. my $where = "1 = 1";
  486. if ($form->{"$form->{vc}_id"}) {
  487. $where .= qq| AND a.$form->{vc}_id = $form->{"$form->{vc}_id"}|;
  488. } else {
  489. if ($form->{$form->{vc}}) {
  490. $var = $form->like(lc $form->{$form->{vc}});
  491. $where .= " AND lower(vc.name) LIKE '$var'";
  492. }
  493. }
  494. for (qw(department employee)) {
  495. if ($form->{$_}) {
  496. ($null, $var) = split /--/, $form->{$_};
  497. $where .= " AND a.${_}_id = $var";
  498. }
  499. }
  500. for (qw(invnumber ordnumber)) {
  501. if ($form->{$_}) {
  502. $var = $form->like(lc $form->{$_});
  503. $where .= " AND lower(a.$_) LIKE '$var'";
  504. $form->{open} = $form->{closed} = 0;
  505. }
  506. }
  507. if ($form->{partsid}){
  508. $where .= " AND a.id IN (select trans_id FROM invoice
  509. WHERE parts_id = $form->{partsid})";
  510. }
  511. for (qw(ponumber shipvia notes)) {
  512. if ($form->{$_}) {
  513. $var = $form->like(lc $form->{$_});
  514. $where .= " AND lower(a.$_) LIKE '$var'";
  515. }
  516. }
  517. if ($form->{description}) {
  518. if ($acc_trans_flds) {
  519. $var = $form->like(lc $form->{description});
  520. $where .= " AND lower(ac.memo) LIKE '$var'
  521. OR lower(i.description) LIKE '$var'";
  522. } else {
  523. $where .= " AND a.id = 0";
  524. }
  525. }
  526. if ($form->{source}) {
  527. if ($acc_trans_flds) {
  528. $var = $form->like(lc $form->{source});
  529. $where .= " AND lower(ac.source) LIKE '$var'";
  530. } else {
  531. $where .= " AND a.id = 0";
  532. }
  533. }
  534. $where .= " AND a.transdate >= '$form->{transdatefrom}'" if $form->{transdatefrom};
  535. $where .= " AND a.transdate <= '$form->{transdateto}'" if $form->{transdateto};
  536. if ($form->{open} || $form->{closed}) {
  537. unless ($form->{open} && $form->{closed}) {
  538. $where .= " AND a.amount != a.paid" if ($form->{open});
  539. $where .= " AND a.amount = a.paid" if ($form->{closed});
  540. }
  541. }
  542. if ($form->{till} ne "") {
  543. $where .= " AND a.invoice = '1'
  544. AND a.till IS NOT NULL";
  545. if ($myconfig->{role} eq 'user') {
  546. $where .= " AND e.login = '$form->{login}'";
  547. }
  548. }
  549. if ($form->{$ARAP}) {
  550. my ($accno) = split /--/, $form->{$ARAP};
  551. $where .= qq|AND a.id IN (SELECT ac.trans_id
  552. FROM acc_trans ac
  553. JOIN chart c ON (c.id = ac.chart_id)
  554. WHERE a.id = ac.trans_id
  555. AND c.accno = '$accno')|;
  556. }
  557. if ($form->{description}) {
  558. $var = $form->like(lc $form->{description});
  559. $where .= qq| AND (a.id IN (SELECT DISTINCT trans_id
  560. FROM acc_trans
  561. WHERE lower(memo) LIKE '$var')
  562. OR a.id IN (SELECT DISTINCT trans_id
  563. FROM invoice
  564. WHERE lower(description) LIKE '$var'))|;
  565. }
  566. $query .= "WHERE $where
  567. ORDER BY $sortorder";
  568. my $sth = $dbh->prepare($query);
  569. $sth->execute || $form->dberror($query);
  570. while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
  571. $ref->{exchangerate} = 1 unless $ref->{exchangerate};
  572. if ($ref->{linetotal} <= 0) {
  573. $ref->{debit} = $ref->{linetotal} * -1;
  574. $ref->{credit} = 0;
  575. } else {
  576. $ref->{debit} = 0;
  577. $ref->{credit} = $ref->{linetotal};
  578. }
  579. if ($ref->{invoice}) {
  580. $ref->{description} ||= $ref->{linedescription};
  581. }
  582. if ($form->{outstanding}) {
  583. next if $form->round_amount($ref->{amount}, 2) == $form->round_amount($ref->{paid}, 2);
  584. }
  585. push @{ $form->{transactions} }, $ref;
  586. }
  587. $sth->finish;
  588. $dbh->disconnect;
  589. }
  590. # this is used in IS, IR to retrieve the name
  591. sub get_name {
  592. my ($self, $myconfig, $form) = @_;
  593. # connect to database
  594. my $dbh = $form->dbconnect($myconfig);
  595. my $dateformat = $myconfig->{dateformat};
  596. if ($myconfig->{dateformat} !~ /^y/) {
  597. my @a = split /\W/, $form->{transdate};
  598. $dateformat .= "yy" if (length $a[2] > 2);
  599. }
  600. if ($form->{transdate} !~ /\W/) {
  601. $dateformat = 'yyyymmdd';
  602. }
  603. my $duedate;
  604. if ($myconfig->{dbdriver} eq 'DB2') {
  605. $duedate = ($form->{transdate}) ? "date('$form->{transdate}') + c.terms DAYS" : "current_date + c.terms DAYS";
  606. } else {
  607. $duedate = ($form->{transdate}) ? "to_date('$form->{transdate}', '$dateformat') + c.terms" : "current_date + c.terms";
  608. }
  609. $form->{"$form->{vc}_id"} *= 1;
  610. # get customer/vendor
  611. my $query = qq|SELECT c.name AS $form->{vc}, c.discount, c.creditlimit, c.terms,
  612. c.email, c.cc, c.bcc, c.taxincluded,
  613. c.address1, c.address2, c.city, c.state,
  614. c.zipcode, c.country, c.curr AS currency, c.language_code,
  615. $duedate AS duedate, c.notes AS intnotes,
  616. b.discount AS tradediscount, b.description AS business,
  617. e.name AS employee, e.id AS employee_id
  618. FROM $form->{vc} c
  619. LEFT JOIN business b ON (b.id = c.business_id)
  620. LEFT JOIN employee e ON (e.id = c.employee_id)
  621. WHERE c.id = $form->{"$form->{vc}_id"}|;
  622. my $sth = $dbh->prepare($query);
  623. $sth->execute || $form->dberror($query);
  624. $ref = $sth->fetchrow_hashref(NAME_lc);
  625. if ($form->{id}) {
  626. for (qw(currency employee employee_id intnotes)) { delete $ref->{$_} }
  627. }
  628. for (keys %$ref) { $form->{$_} = $ref->{$_} }
  629. $sth->finish;
  630. my $buysell = ($form->{vc} eq 'customer') ? "buy" : "sell";
  631. # if no currency use defaultcurrency
  632. $form->{currency} = ($form->{currency}) ? $form->{currency} : $form->{defaultcurrency};
  633. $form->{exchangerate} = 0 if $form->{currency} eq $form->{defaultcurrency};
  634. if ($form->{transdate} && ($form->{currency} ne $form->{defaultcurrency})) {
  635. $form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{transdate}, $buysell);
  636. }
  637. $form->{forex} = $form->{exchangerate};
  638. # if no employee, default to login
  639. ($form->{employee}, $form->{employee_id}) = $form->get_employee($dbh) unless $form->{employee_id};
  640. my $arap = ($form->{vc} eq 'customer') ? 'ar' : 'ap';
  641. my $ARAP = uc $arap;
  642. $form->{creditremaining} = $form->{creditlimit};
  643. $query = qq|SELECT SUM(amount - paid)
  644. FROM $arap
  645. WHERE $form->{vc}_id = $form->{"$form->{vc}_id"}|;
  646. $sth = $dbh->prepare($query);
  647. $sth->execute || $form->dberror($query);
  648. ($form->{creditremaining}) -= $sth->fetchrow_array;
  649. $sth->finish;
  650. $query = qq|SELECT o.amount, (SELECT e.$buysell FROM exchangerate e
  651. WHERE e.curr = o.curr
  652. AND e.transdate = o.transdate)
  653. FROM oe o
  654. WHERE o.$form->{vc}_id = $form->{"$form->{vc}_id"}
  655. AND o.quotation = '0'
  656. AND o.closed = '0'|;
  657. $sth = $dbh->prepare($query);
  658. $sth->execute || $form->dberror($query);
  659. while (my ($amount, $exch) = $sth->fetchrow_array) {
  660. $exch = 1 unless $exch;
  661. $form->{creditremaining} -= $amount * $exch;
  662. }
  663. $sth->finish;
  664. # get shipto if we did not converted an order or invoice
  665. if (!$form->{shipto}) {
  666. for (qw(shiptoname shiptoaddress1 shiptoaddress2 shiptocity
  667. shiptostate shiptozipcode shiptocountry shiptocontact
  668. shiptophone shiptofax shiptoemail)) {
  669. delete $form->{$_}
  670. }
  671. ## needs fixing (SELECT *)
  672. $query = qq|SELECT *
  673. FROM shipto
  674. WHERE trans_id = $form->{"$form->{vc}_id"}|;
  675. $sth = $dbh->prepare($query);
  676. $sth->execute || $form->dberror($query);
  677. $ref = $sth->fetchrow_hashref(NAME_lc);
  678. for (keys %$ref) { $form->{$_} = $ref->{$_} }
  679. $sth->finish;
  680. }
  681. # get taxes
  682. $query = qq|SELECT c.accno
  683. FROM chart c
  684. JOIN $form->{vc}tax ct ON (ct.chart_id = c.id)
  685. WHERE ct.$form->{vc}_id = $form->{"$form->{vc}_id"}|;
  686. $sth = $dbh->prepare($query);
  687. $sth->execute || $form->dberror($query);
  688. my %tax;
  689. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  690. $tax{$ref->{accno}} = 1;
  691. }
  692. $sth->finish;
  693. my $where = qq|AND (t.validto >= '$form->{transdate}' OR t.validto IS NULL)| if $form->{transdate};
  694. # get tax rates and description
  695. $query = qq|SELECT c.accno, c.description, t.rate, t.taxnumber
  696. FROM chart c
  697. JOIN tax t ON (c.id = t.chart_id)
  698. WHERE c.link LIKE '%${ARAP}_tax%'
  699. $where
  700. ORDER BY accno, validto|;
  701. $sth = $dbh->prepare($query);
  702. $sth->execute || $form->dberror($query);
  703. $form->{taxaccounts} = "";
  704. my %a = ();
  705. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  706. if ($tax{$ref->{accno}}) {
  707. if (not exists $a{$ref->{accno}}) {
  708. for (qw(rate description taxnumber)) { $form->{"$ref->{accno}_$_"} = $ref->{$_} }
  709. $form->{taxaccounts} .= "$ref->{accno} ";
  710. $a{$ref->{accno}} = 1;
  711. }
  712. }
  713. }
  714. $sth->finish;
  715. chop $form->{taxaccounts};
  716. # setup last accounts used for this customer/vendor
  717. if (!$form->{id} && $form->{type} !~ /_(order|quotation)/) {
  718. $query = qq|SELECT c.accno, c.description, c.link, c.category,
  719. ac.project_id, p.projectnumber, a.department_id,
  720. d.description AS department
  721. FROM chart c
  722. JOIN acc_trans ac ON (ac.chart_id = c.id)
  723. JOIN $arap a ON (a.id = ac.trans_id)
  724. LEFT JOIN project p ON (ac.project_id = p.id)
  725. LEFT JOIN department d ON (d.id = a.department_id)
  726. WHERE a.$form->{vc}_id = $form->{"$form->{vc}_id"}
  727. AND a.id IN (SELECT max(id)
  728. FROM $arap
  729. WHERE $form->{vc}_id = $form->{"$form->{vc}_id"})|;
  730. $sth = $dbh->prepare($query);
  731. $sth->execute || $form->dberror($query);
  732. my $i = 0;
  733. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  734. $form->{department} = $ref->{department};
  735. $form->{department_id} = $ref->{department_id};
  736. if ($ref->{link} =~ /_amount/) {
  737. $i++;
  738. $form->{"$form->{ARAP}_amount_$i"} = "$ref->{accno}--$ref->{description}" if $ref->{accno};
  739. $form->{"projectnumber_$i"} = "$ref->{projectnumber}--$ref->{project_id}" if $ref->{project_id};
  740. }
  741. if ($ref->{link} eq $form->{ARAP}) {
  742. $form->{$form->{ARAP}} = $form->{"$form->{ARAP}_1"} = "$ref->{accno}--$ref->{description}" if $ref->{accno};
  743. }
  744. }
  745. $sth->finish;
  746. $form->{rowcount} = $i if ($i && !$form->{type});
  747. }
  748. $dbh->disconnect;
  749. }
  750. 1;