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