summaryrefslogtreecommitdiff
path: root/LedgerSMB/PE.pm
blob: 02b7b59d3f0fe1a84bc38cea2e75c1c886aea8de (plain)
  1. #=====================================================================
  2. # LedgerSMB
  3. # Small Medium Business Accounting software
  4. # http://www.ledgersmb.org/
  5. #
  6. # Copyright (C) 2006
  7. # This work contains copyrighted information from a number of sources all used
  8. # with permission.
  9. #
  10. # This file contains source code included with or based on SQL-Ledger which
  11. # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
  12. # under the GNU General Public License version 2 or, at your option, any later
  13. # version. For a full list including contact information of contributors,
  14. # maintainers, and copyright holders, see the CONTRIBUTORS file.
  15. #
  16. # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
  17. # Copyright (C) 2003
  18. #
  19. # Author: DWS Systems Inc.
  20. # Web: http://www.sql-ledger.org
  21. #
  22. # Contributors:
  23. #
  24. #======================================================================
  25. #
  26. # This file has NOT undergone whitespace cleanup.
  27. #
  28. #======================================================================
  29. #
  30. # Project module
  31. # also used for partsgroups
  32. #
  33. #======================================================================
  34. package PE;
  35. sub projects {
  36. my ($self, $myconfig, $form) = @_;
  37. # connect to database
  38. my $dbh = $form->dbconnect($myconfig);
  39. $form->{sort} = "projectnumber" unless $form->{sort};
  40. my @a = ($form->{sort});
  41. my %ordinal = ( projectnumber => 2,
  42. description => 3,
  43. startdate => 4,
  44. enddate => 5,
  45. );
  46. my $sortorder = $form->sort_order(\@a, \%ordinal);
  47. my $query;
  48. my $where = "WHERE 1=1";
  49. $query = qq|SELECT pr.*, c.name
  50. FROM project pr
  51. LEFT JOIN customer c ON (c.id = pr.customer_id)|;
  52. if ($form->{type} eq 'job') {
  53. $where .= qq| AND pr.id NOT IN (SELECT DISTINCT id
  54. FROM parts
  55. WHERE project_id > 0)|;
  56. }
  57. my $var;
  58. if ($form->{projectnumber} ne "") {
  59. $var = $form->like(lc $form->{projectnumber});
  60. $where .= " AND lower(pr.projectnumber) LIKE '$var'";
  61. }
  62. if ($form->{description} ne "") {
  63. $var = $form->like(lc $form->{description});
  64. $where .= " AND lower(pr.description) LIKE '$var'";
  65. }
  66. ($form->{startdatefrom}, $form->{startdateto}) = $form->from_to($form->{year}, $form->{month}, $form->{interval}) if $form->{year} && $form->{month};
  67. if ($form->{startdatefrom}) {
  68. $where .= " AND (pr.startdate IS NULL OR pr.startdate >= '$form->{startdatefrom}')";
  69. }
  70. if ($form->{startdateto}) {
  71. $where .= " AND (pr.startdate IS NULL OR pr.startdate <= '$form->{startdateto}')";
  72. }
  73. if ($form->{status} eq 'orphaned') {
  74. $where .= qq| AND pr.id NOT IN (SELECT DISTINCT project_id
  75. FROM acc_trans
  76. WHERE project_id > 0
  77. UNION
  78. SELECT DISTINCT project_id
  79. FROM invoice
  80. WHERE project_id > 0
  81. UNION
  82. SELECT DISTINCT project_id
  83. FROM orderitems
  84. WHERE project_id > 0
  85. UNION
  86. SELECT DISTINCT project_id
  87. FROM jcitems
  88. WHERE project_id > 0)
  89. |;
  90. }
  91. if ($form->{status} eq 'active') {
  92. $where .= qq| AND (pr.enddate IS NULL OR pr.enddate >= current_date)|;
  93. }
  94. if ($form->{status} eq 'inactive') {
  95. $where .= qq| AND pr.enddate <= current_date|;
  96. }
  97. $query .= qq|
  98. $where
  99. ORDER BY $sortorder|;
  100. $sth = $dbh->prepare($query);
  101. $sth->execute || $form->dberror($query);
  102. my $i = 0;
  103. while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
  104. push @{ $form->{all_project} }, $ref;
  105. $i++;
  106. }
  107. $sth->finish;
  108. $dbh->disconnect;
  109. $i;
  110. }
  111. sub get_project {
  112. my ($self, $myconfig, $form) = @_;
  113. # connect to database
  114. my $dbh = $form->dbconnect($myconfig);
  115. my $query;
  116. my $sth;
  117. my $ref;
  118. my $where;
  119. if ($form->{id}) {
  120. $where = "WHERE pr.id = $form->{id}" if $form->{id};
  121. $query = qq|SELECT pr.*,
  122. c.name AS customer
  123. FROM project pr
  124. LEFT JOIN customer c ON (c.id = pr.customer_id)
  125. $where|;
  126. $sth = $dbh->prepare($query);
  127. $sth->execute || $form->dberror($query);
  128. $ref = $sth->fetchrow_hashref(NAME_lc);
  129. for (keys %$ref) { $form->{$_} = $ref->{$_} }
  130. $sth->finish;
  131. # check if it is orphaned
  132. $query = qq|SELECT count(*)
  133. FROM acc_trans
  134. WHERE project_id = $form->{id}
  135. UNION
  136. SELECT count(*)
  137. FROM invoice
  138. WHERE project_id = $form->{id}
  139. UNION
  140. SELECT count(*)
  141. FROM orderitems
  142. WHERE project_id = $form->{id}
  143. UNION
  144. SELECT count(*)
  145. FROM jcitems
  146. WHERE project_id = $form->{id}
  147. |;
  148. $sth = $dbh->prepare($query);
  149. $sth->execute || $form->dberror($query);
  150. my $count;
  151. while (($count) = $sth->fetchrow_array) {
  152. $form->{orphaned} += $count;
  153. }
  154. $sth->finish;
  155. $form->{orphaned} = !$form->{orphaned};
  156. }
  157. PE->get_customer($myconfig, $form, $dbh);
  158. $form->run_custom_queries('project', 'SELECT');
  159. $dbh->disconnect;
  160. }
  161. sub save_project {
  162. my ($self, $myconfig, $form) = @_;
  163. # connect to database
  164. my $dbh = $form->dbconnect($myconfig);
  165. $form->{customer_id} ||= 'NULL';
  166. $form->{projectnumber} = $form->update_defaults($myconfig, "projectnumber", $dbh) unless $form->{projectnumber};
  167. if ($form->{id}) {
  168. $query = qq|UPDATE project SET
  169. projectnumber = |.$dbh->quote($form->{projectnumber}).qq|,
  170. description = |.$dbh->quote($form->{description}).qq|,
  171. startdate = |.$form->dbquote($form->{startdate}, SQL_DATE).qq|,
  172. enddate = |.$form->dbquote($form->{enddate}, SQL_DATE).qq|,
  173. customer_id = $form->{customer_id}
  174. WHERE id = $form->{id}|;
  175. } else {
  176. $query = qq|INSERT INTO project
  177. (projectnumber, description, startdate, enddate, customer_id)
  178. VALUES (|
  179. .$dbh->quote($form->{projectnumber}).qq|, |
  180. .$dbh->quote($form->{description}).qq|, |
  181. .$form->dbquote($form->{startdate}, SQL_DATE).qq|, |
  182. .$form->dbquote($form->{enddate}, SQL_DATE).qq|,
  183. $form->{customer_id}
  184. )|;
  185. }
  186. $dbh->do($query) || $form->dberror($query);
  187. $form->run_custom_queries('project', 'UPDATE');
  188. $dbh->disconnect;
  189. }
  190. sub list_stock {
  191. my ($self, $myconfig, $form) = @_;
  192. # connect to database
  193. my $dbh = $form->dbconnect($myconfig);
  194. my $var;
  195. my $where = "1 = 1";
  196. if ($form->{status} eq 'active') {
  197. $where = qq|(pr.enddate IS NULL
  198. OR pr.enddate >= current_date)
  199. AND pr.completed < pr.production|;
  200. }
  201. if ($form->{status} eq 'inactive') {
  202. $where = qq|pr.completed = pr.production|;
  203. }
  204. if ($form->{projectnumber}) {
  205. $var = $form->like(lc $form->{projectnumber});
  206. $where .= " AND lower(pr.projectnumber) LIKE '$var'";
  207. }
  208. if ($form->{description}) {
  209. $var = $form->like(lc $form->{description});
  210. $where .= " AND lower(pr.description) LIKE '$var'";
  211. }
  212. $form->{sort} = "projectnumber" unless $form->{sort};
  213. my @a = ($form->{sort});
  214. my %ordinal = ( projectnumber => 2,
  215. description => 3
  216. );
  217. my $sortorder = $form->sort_order(\@a, \%ordinal);
  218. my $query = qq|SELECT pr.*, p.partnumber
  219. FROM project pr
  220. JOIN parts p ON (p.id = pr.parts_id)
  221. WHERE $where
  222. ORDER BY $sortorder|;
  223. $sth = $dbh->prepare($query);
  224. $sth->execute || $form->dberror($query);
  225. while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
  226. push @{ $form->{all_project} }, $ref;
  227. }
  228. $sth->finish;
  229. $query = qq|SELECT current_date|;
  230. ($form->{stockingdate}) = $dbh->selectrow_array($query) if !$form->{stockingdate};
  231. $dbh->disconnect;
  232. }
  233. sub jobs {
  234. my ($self, $myconfig, $form) = @_;
  235. # connect to database
  236. my $dbh = $form->dbconnect($myconfig);
  237. $form->{sort} = "projectnumber" unless $form->{sort};
  238. my @a = ($form->{sort});
  239. my %ordinal = ( projectnumber => 2,
  240. description => 3,
  241. startdate => 4,
  242. );
  243. my $sortorder = $form->sort_order(\@a, \%ordinal);
  244. my $query = qq|SELECT pr.*, p.partnumber, p.onhand, c.name
  245. FROM project pr
  246. JOIN parts p ON (p.id = pr.parts_id)
  247. LEFT JOIN customer c ON (c.id = pr.customer_id)
  248. WHERE 1=1|;
  249. if ($form->{projectnumber} ne "") {
  250. $var = $form->like(lc $form->{projectnumber});
  251. $query .= " AND lower(pr.projectnumber) LIKE '$var'";
  252. }
  253. if ($form->{description} ne "") {
  254. $var = $form->like(lc $form->{description});
  255. $query .= " AND lower(pr.description) LIKE '$var'";
  256. }
  257. ($form->{startdatefrom}, $form->{startdateto}) = $form->from_to($form->{year}, $form->{month}, $form->{interval}) if $form->{year} && $form->{month};
  258. if ($form->{startdatefrom}) {
  259. $query .= " AND pr.startdate >= '$form->{startdatefrom}'";
  260. }
  261. if ($form->{startdateto}) {
  262. $query .= " AND pr.startdate <= '$form->{startdateto}'";
  263. }
  264. if ($form->{status} eq 'active') {
  265. $query .= qq| AND NOT pr.production = pr.completed|;
  266. }
  267. if ($form->{status} eq 'inactive') {
  268. $query .= qq| AND pr.production = pr.completed|;
  269. }
  270. if ($form->{status} eq 'orphaned') {
  271. $query .= qq| AND pr.completed = 0
  272. AND (pr.id NOT IN SELECT DISTINCT project_id
  273. FROM invoice
  274. WHERE project_id > 0)
  275. UNION
  276. SELECT DISTINCT project_id
  277. FROM orderitems
  278. WHERE project_id > 0
  279. SELECT DISTINCT project_id
  280. FROM jcitems
  281. WHERE project_id > 0
  282. )|;
  283. }
  284. $query .= qq|
  285. ORDER BY $sortorder|;
  286. $sth = $dbh->prepare($query);
  287. $sth->execute || $form->dberror($query);
  288. while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
  289. push @{ $form->{all_project} }, $ref;
  290. }
  291. $sth->finish;
  292. $dbh->disconnect;
  293. }
  294. sub get_job {
  295. my ($self, $myconfig, $form) = @_;
  296. # connect to database
  297. my $dbh = $form->dbconnect($myconfig);
  298. my $query;
  299. my $sth;
  300. my $ref;
  301. if ($form->{id}) {
  302. $query = qq|SELECT value FROM defaults WHERE setting_key = 'weightunit'|;
  303. ($form->{weightunit}) = $dbh->selectrow_array($query);
  304. $query = qq|SELECT pr.*,
  305. p.partnumber, p.description AS partdescription, p.unit, p.listprice,
  306. p.sellprice, p.priceupdate, p.weight, p.notes, p.bin,
  307. p.partsgroup_id,
  308. ch.accno AS income_accno, ch.description AS income_description,
  309. pr.customer_id, c.name AS customer,
  310. pg.partsgroup
  311. FROM project pr
  312. LEFT JOIN parts p ON (p.id = pr.parts_id)
  313. LEFT JOIN chart ch ON (ch.id = p.income_accno_id)
  314. LEFT JOIN customer c ON (c.id = pr.customer_id)
  315. LEFT JOIN partsgroup pg ON (pg.id = p.partsgroup_id)
  316. WHERE pr.id = $form->{id}|;
  317. } else {
  318. $query = qq|
  319. SELECT value, current_date AS startdate FROM defaults
  320. WHERE setting_key = 'weightunit'|;
  321. }
  322. $sth = $dbh->prepare($query);
  323. $sth->execute || $form->dberror($query);
  324. $ref = $sth->fetchrow_hashref(NAME_lc);
  325. for (keys %$ref) { $form->{$_} = $ref->{$_} }
  326. $sth->finish;
  327. if ($form->{id}) {
  328. # check if it is orphaned
  329. $query = qq|SELECT count(*)
  330. FROM invoice
  331. WHERE project_id = $form->{id}
  332. UNION
  333. SELECT count(*)
  334. FROM orderitems
  335. WHERE project_id = $form->{id}
  336. UNION
  337. SELECT count(*)
  338. FROM jcitems
  339. WHERE project_id = $form->{id}
  340. |;
  341. $sth = $dbh->prepare($query);
  342. $sth->execute || $form->dberror($query);
  343. my $count;
  344. while (($count) = $sth->fetchrow_array) {
  345. $form->{orphaned} += $count;
  346. }
  347. $sth->finish;
  348. }
  349. $form->{orphaned} = !$form->{orphaned};
  350. $query = qq|SELECT accno, description, link
  351. FROM chart
  352. WHERE link LIKE '%IC%'
  353. ORDER BY accno|;
  354. $sth = $dbh->prepare($query);
  355. $sth->execute || $form->dberror($query);
  356. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  357. for (split /:/, $ref->{link}) {
  358. if (/IC/) {
  359. push @{ $form->{IC_links}{$_} }, { accno => $ref->{accno},
  360. description => $ref->{description} };
  361. }
  362. }
  363. }
  364. $sth->finish;
  365. if ($form->{id}) {
  366. $query = qq|SELECT ch.accno
  367. FROM parts p
  368. JOIN partstax pt ON (pt.parts_id = p.id)
  369. JOIN chart ch ON (pt.chart_id = ch.id)
  370. WHERE p.id = $form->{id}|;
  371. $sth = $dbh->prepare($query);
  372. $sth->execute || $form->dberror($query);
  373. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  374. $form->{amount}{$ref->{accno}} = $ref->{accno};
  375. }
  376. $sth->finish;
  377. }
  378. PE->get_customer($myconfig, $form, $dbh);
  379. $dbh->disconnect;
  380. }
  381. sub get_customer {
  382. my ($self, $myconfig, $form, $dbh) = @_;
  383. my $disconnect = 0;
  384. if (! $dbh) {
  385. $dbh = $form->dbconnect($myconfig);
  386. $disconnect = 1;
  387. }
  388. my $query;
  389. my $sth;
  390. my $ref;
  391. if (! $form->{startdate}) {
  392. $query = qq|SELECT current_date|;
  393. ($form->{startdate}) = $dbh->selectrow_array($query);
  394. }
  395. my $where = qq|(startdate >= '$form->{startdate}' OR startdate IS NULL OR enddate IS NULL)|;
  396. if ($form->{enddate}) {
  397. $where .= qq| AND (enddate >= '$form->{enddate}' OR enddate IS NULL)|;
  398. } else {
  399. $where .= qq| AND (enddate >= current_date OR enddate IS NULL)|;
  400. }
  401. $query = qq|SELECT count(*)
  402. FROM customer
  403. WHERE $where|;
  404. my ($count) = $dbh->selectrow_array($query);
  405. if ($count < $myconfig->{vclimit}) {
  406. $query = qq|SELECT id, name
  407. FROM customer
  408. WHERE $where|;
  409. if ($form->{customer_id}) {
  410. $query .= qq|
  411. UNION SELECT id,name
  412. FROM customer
  413. WHERE id = $form->{customer_id}|;
  414. }
  415. $query .= qq|
  416. ORDER BY name|;
  417. $sth = $dbh->prepare($query);
  418. $sth->execute || $form->dberror($query);
  419. @{ $form->{all_customer} } = ();
  420. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  421. push @{ $form->{all_customer} }, $ref;
  422. }
  423. $sth->finish;
  424. }
  425. $dbh->disconnect if $disconnect;
  426. }
  427. sub save_job {
  428. my ($self, $myconfig, $form) = @_;
  429. # connect to database
  430. my $dbh = $form->dbconnect_noauto($myconfig);
  431. my ($income_accno) = split /--/, $form->{IC_income};
  432. my ($partsgroup, $partsgroup_id) = split /--/, $form->{partsgroup};
  433. $partsgroup_id ||= 'NULL';
  434. if ($form->{id}) {
  435. $query = qq|SELECT id FROM project
  436. WHERE id = $form->{id}|;
  437. ($form->{id}) = $dbh->selectrow_array($query);
  438. }
  439. if (!$form->{id}) {
  440. my $uid = localtime;
  441. $uid .= "$$";
  442. $query = qq|INSERT INTO project (projectnumber)
  443. VALUES ('$uid')|;
  444. $dbh->do($query) || $form->dberror($query);
  445. $query = qq|SELECT id FROM project
  446. WHERE projectnumber = '$uid'|;
  447. ($form->{id}) = $dbh->selectrow_array($query);
  448. }
  449. $form->{projectnumber} = $form->update_defaults($myconfig, "projectnumber", $dbh) unless $form->{projectnumber};
  450. $query = qq|UPDATE project SET
  451. projectnumber = |.$dbh->quote($form->{projectnumber}).qq|,
  452. description = |.$dbh->quote($form->{description}).qq|,
  453. startdate = |.$form->dbquote($form->{startdate}, SQL_DATE).qq|,
  454. enddate = |.$form->dbquote($form->{enddate}, SQL_DATE).qq|,
  455. parts_id = $form->{id},
  456. production = |.$form->parse_amount($myconfig, $form->{production}).qq|,
  457. customer_id = $form->{customer_id}
  458. WHERE id = $form->{id}|;
  459. $dbh->do($query) || $form->dberror($query);
  460. #### add/edit assembly
  461. $query = qq|SELECT id FROM parts
  462. WHERE id = $form->{id}|;
  463. my ($id) = $dbh->selectrow_array($query);
  464. if (!$id) {
  465. $query = qq|INSERT INTO parts (id)
  466. VALUES ($form->{id})|;
  467. $dbh->do($query) || $form->dberror($query);
  468. }
  469. my $partnumber = ($form->{partnumber}) ? $form->{partnumber} : $form->{projectnumber};
  470. $query = qq|UPDATE parts SET
  471. partnumber = |.$dbh->quote($partnumber).qq|,
  472. description = |.$dbh->quote($form->{partdescription}).qq|,
  473. priceupdate = |.$form->dbquote($form->{priceupdate}, SQL_DATE).qq|,
  474. listprice = |.$form->parse_amount($myconfig, $form->{listprice}).qq|,
  475. sellprice = |.$form->parse_amount($myconfig, $form->{sellprice}).qq|,
  476. weight = |.$form->parse_amount($myconfig, $form->{weight}).qq|,
  477. bin = '$form->{bin}',
  478. unit = |.$dbh->quote($form->{unit}).qq|,
  479. notes = |.$dbh->quote($form->{notes}).qq|,
  480. income_accno_id = (SELECT id FROM chart
  481. WHERE accno = '$income_accno'),
  482. partsgroup_id = $partsgroup_id,
  483. assembly = '1',
  484. obsolete = '1',
  485. project_id = $form->{id}
  486. WHERE id = $form->{id}|;
  487. $dbh->do($query) || $form->dberror($query);
  488. $query = qq|DELETE FROM partstax
  489. WHERE parts_id = $form->{id}|;
  490. $dbh->do($query) || $form->dberror($query);
  491. for (split / /, $form->{taxaccounts}) {
  492. if ($form->{"IC_tax_$_"}) {
  493. $query = qq|INSERT INTO partstax (parts_id, chart_id)
  494. VALUES ($form->{id},
  495. (SELECT id
  496. FROM chart
  497. WHERE accno = '$_'))|;
  498. $dbh->do($query) || $form->dberror($query);
  499. }
  500. }
  501. $dbh->commit;
  502. $dbh->disconnect;
  503. }
  504. sub stock_assembly {
  505. my ($self, $myconfig, $form) = @_;
  506. # connect to database
  507. my $dbh = $form->dbconnect_noauto($myconfig);
  508. my $ref;
  509. my $query = qq|SELECT *
  510. FROM project
  511. WHERE id = ?|;
  512. my $sth = $dbh->prepare($query) || $form->dberror($query);
  513. $query = qq|SELECT COUNT(*)
  514. FROM parts
  515. WHERE project_id = ?|;
  516. my $rvh = $dbh->prepare($query) || $form->dberror($query);
  517. if (! $form->{stockingdate}) {
  518. $query = qq|SELECT current_date|;
  519. ($form->{stockingdate}) = $dbh->selectrow_array($query);
  520. }
  521. $query = qq|SELECT *
  522. FROM parts
  523. WHERE id = ?|;
  524. my $pth = $dbh->prepare($query) || $form->dberror($query);
  525. $query = qq|SELECT j.*, p.lastcost FROM jcitems j
  526. JOIN parts p ON (p.id = j.parts_id)
  527. WHERE j.project_id = ?
  528. AND j.checkedin <= '$form->{stockingdate}'
  529. ORDER BY parts_id|;
  530. my $jth = $dbh->prepare($query) || $form->dberror($query);
  531. $query = qq|INSERT INTO assembly (id, parts_id, qty, bom, adj)
  532. VALUES (?, ?, ?, '0', '0')|;
  533. my $ath = $dbh->prepare($query) || $form->dberror($query);
  534. my $i = 0;
  535. my $sold;
  536. my $ship;
  537. while (1) {
  538. $i++;
  539. last unless $form->{"id_$i"};
  540. $stock = $form->parse_amount($myconfig, $form->{"stock_$i"});
  541. if ($stock) {
  542. $sth->execute($form->{"id_$i"});
  543. $ref = $sth->fetchrow_hashref(NAME_lc);
  544. if ($stock > ($ref->{production} - $ref->{completed})) {
  545. $stock = $ref->{production} - $ref->{completed};
  546. }
  547. if (($stock * -1) > $ref->{completed}) {
  548. $stock = $ref->{completed} * -1;
  549. }
  550. $pth->execute($form->{"id_$i"});
  551. $pref = $pth->fetchrow_hashref(NAME_lc);
  552. my %assembly = ();
  553. my $lastcost = 0;
  554. my $sellprice = 0;
  555. my $listprice = 0;
  556. $jth->execute($form->{"id_$i"});
  557. while ($jref = $jth->fetchrow_hashref(NAME_lc)) {
  558. $assembly{qty}{$jref->{parts_id}} += ($jref->{qty} - $jref->{allocated});
  559. $assembly{parts_id}{$jref->{parts_id}} = $jref->{parts_id};
  560. $assembly{jcitems}{$jref->{id}} = $jref->{id};
  561. $lastcost += $form->round_amount(($jref->{lastcost} * ($jref->{qty} - $jref->{allocated})), 2);
  562. $sellprice += $form->round_amount(($jref->{sellprice} * ($jref->{qty} - $jref->{allocated})), 2);
  563. $listprice += $form->round_amount(($jref->{listprice} * ($jref->{qty} - $jref->{allocated})), 2);
  564. }
  565. $jth->finish;
  566. $uid = localtime;
  567. $uid .= "$$";
  568. $query = qq|INSERT INTO parts (partnumber)
  569. VALUES ('$uid')|;
  570. $dbh->do($query) || $form->dberror($query);
  571. $query = qq|SELECT id
  572. FROM parts
  573. WHERE partnumber = '$uid'|;
  574. ($uid) = $dbh->selectrow_array($query);
  575. $lastcost = $form->round_amount($lastcost / $stock, 2);
  576. $sellprice = ($pref->{sellprice}) ? $pref->{sellprice} : $form->round_amount($sellprice / $stock, 2);
  577. $listprice = ($pref->{listprice}) ? $pref->{listprice} : $form->round_amount($listprice / $stock, 2);
  578. $rvh->execute($form->{"id_$i"});
  579. my ($rev) = $rvh->fetchrow_array;
  580. $rvh->finish;
  581. $query = qq|UPDATE parts SET
  582. partnumber = '$pref->{partnumber}-$rev',
  583. description = '$pref->{partdescription}',
  584. priceupdate = '$form->{stockingdate}',
  585. unit = '$pref->{unit}',
  586. listprice = $listprice,
  587. sellprice = $sellprice,
  588. lastcost = $lastcost,
  589. weight = $pref->{weight},
  590. onhand = $stock,
  591. notes = '$pref->{notes}',
  592. assembly = '1',
  593. income_accno_id = $pref->{income_accno_id},
  594. bin = '$pref->{bin}',
  595. project_id = $form->{"id_$i"}
  596. WHERE id = $uid|;
  597. $dbh->do($query) || $form->dberror($query);
  598. $query = qq|INSERT INTO partstax (parts_id, chart_id)
  599. SELECT '$uid', chart_id FROM partstax
  600. WHERE parts_id = $pref->{id}|;
  601. $dbh->do($query) || $form->dberror($query);
  602. $pth->finish;
  603. for (keys %{$assembly{parts_id}}) {
  604. if ($assembly{qty}{$_}) {
  605. $ath->execute($uid, $assembly{parts_id}{$_}, $form->round_amount($assembly{qty}{$_} / $stock, 4));
  606. $ath->finish;
  607. }
  608. }
  609. $form->update_balance($dbh,
  610. "project",
  611. "completed",
  612. qq|id = $form->{"id_$i"}|,
  613. $stock);
  614. $query = qq|UPDATE jcitems SET
  615. allocated = qty
  616. WHERE allocated != qty
  617. AND checkedin <= '$form->{stockingdate}'
  618. AND project_id = $form->{"id_$i"}|;
  619. $dbh->do($query) || $form->dberror($query);
  620. $sth->finish;
  621. }
  622. }
  623. my $rc = $dbh->commit;
  624. $dbh->disconnect;
  625. $rc;
  626. }
  627. sub delete_project {
  628. my ($self, $myconfig, $form) = @_;
  629. # connect to database
  630. my $dbh = $form->dbconnect_noauto($myconfig);
  631. $query = qq|DELETE FROM project
  632. WHERE id = $form->{id}|;
  633. $dbh->do($query) || $form->dberror($query);
  634. $query = qq|DELETE FROM translation
  635. WHERE trans_id = $form->{id}|;
  636. $dbh->do($query) || $form->dberror($query);
  637. my $rc = $dbh->commit;
  638. $dbh->disconnect;
  639. $rc;
  640. }
  641. sub delete_partsgroup {
  642. my ($self, $myconfig, $form) = @_;
  643. # connect to database
  644. my $dbh = $form->dbconnect_noauto($myconfig);
  645. $query = qq|DELETE FROM partsgroup
  646. WHERE id = $form->{id}|;
  647. $dbh->do($query) || $form->dberror($query);
  648. $query = qq|DELETE FROM translation
  649. WHERE trans_id = $form->{id}|;
  650. $dbh->do($query) || $form->dberror($query);
  651. my $rc = $dbh->commit;
  652. $dbh->disconnect;
  653. $rc;
  654. }
  655. sub delete_pricegroup {
  656. my ($self, $myconfig, $form) = @_;
  657. # connect to database
  658. my $dbh = $form->dbconnect_noauto($myconfig);
  659. $query = qq|DELETE FROM pricegroup
  660. WHERE id = $form->{id}|;
  661. $dbh->do($query) || $form->dberror($query);
  662. my $rc = $dbh->commit;
  663. $dbh->disconnect;
  664. $rc;
  665. }
  666. sub delete_job {
  667. my ($self, $myconfig, $form) = @_;
  668. # connect to database
  669. my $dbh = $form->dbconnect_noauto($myconfig);
  670. my %audittrail = ( tablename => 'project',
  671. reference => $form->{id},
  672. formname => $form->{type},
  673. action => 'deleted',
  674. id => $form->{id} );
  675. $form->audittrail($dbh, "", \%audittrail);
  676. my $query = qq|DELETE FROM project
  677. WHERE id = $form->{id}|;
  678. $dbh->do($query) || $form->dberror($query);
  679. $query = qq|DELETE FROM translation
  680. WHERE trans_id = $form->{id}|;
  681. $dbh->do($query) || $form->dberror($query);
  682. # delete all the assemblies
  683. $query = qq|DELETE FROM assembly a
  684. JOIN parts p ON (a.id = p.id)
  685. WHERE p.project_id = $form->{id}|;
  686. $dbh->do($query) || $form->dberror($query);
  687. $query = qq|DELETE FROM parts
  688. WHERE project_id = $form->{id}|;
  689. $dbh->do($query) || $form->dberror($query);
  690. my $rc = $dbh->commit;
  691. $dbh->disconnect;
  692. $rc;
  693. }
  694. sub partsgroups {
  695. my ($self, $myconfig, $form) = @_;
  696. my $var;
  697. # connect to database
  698. my $dbh = $form->dbconnect($myconfig);
  699. $form->{sort} = "partsgroup" unless $form->{partsgroup};
  700. my @a = (partsgroup);
  701. my $sortorder = $form->sort_order(\@a);
  702. my $query = qq|SELECT g.*
  703. FROM partsgroup g|;
  704. my $where = "1 = 1";
  705. if ($form->{partsgroup} ne "") {
  706. $var = $form->like(lc $form->{partsgroup});
  707. $where .= " AND lower(partsgroup) LIKE '$var'";
  708. }
  709. $query .= qq|
  710. WHERE $where
  711. ORDER BY $sortorder|;
  712. if ($form->{status} eq 'orphaned') {
  713. $query = qq|SELECT g.*
  714. FROM partsgroup g
  715. LEFT JOIN parts p ON (p.partsgroup_id = g.id)
  716. WHERE $where
  717. EXCEPT
  718. SELECT g.*
  719. FROM partsgroup g
  720. JOIN parts p ON (p.partsgroup_id = g.id)
  721. WHERE $where
  722. ORDER BY $sortorder|;
  723. }
  724. $sth = $dbh->prepare($query);
  725. $sth->execute || $form->dberror($query);
  726. my $i = 0;
  727. while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
  728. push @{ $form->{item_list} }, $ref;
  729. $i++;
  730. }
  731. $sth->finish;
  732. $dbh->disconnect;
  733. $i;
  734. }
  735. sub save_partsgroup {
  736. my ($self, $myconfig, $form) = @_;
  737. # connect to database
  738. my $dbh = $form->dbconnect($myconfig);
  739. if ($form->{id}) {
  740. $query = qq|UPDATE partsgroup SET
  741. partsgroup = |.$dbh->quote($form->{partsgroup}).qq|
  742. WHERE id = $form->{id}|;
  743. } else {
  744. $query = qq|INSERT INTO partsgroup
  745. (partsgroup)
  746. VALUES (|.$dbh->quote($form->{partsgroup}).qq|)|;
  747. }
  748. $dbh->do($query) || $form->dberror($query);
  749. $dbh->disconnect;
  750. }
  751. sub get_partsgroup {
  752. my ($self, $myconfig, $form) = @_;
  753. # connect to database
  754. my $dbh = $form->dbconnect($myconfig);
  755. my $query = qq|SELECT *
  756. FROM partsgroup
  757. WHERE id = $form->{id}|;
  758. my $sth = $dbh->prepare($query);
  759. $sth->execute || $form->dberror($query);
  760. my $ref = $sth->fetchrow_hashref(NAME_lc);
  761. for (keys %$ref) { $form->{$_} = $ref->{$_} }
  762. $sth->finish;
  763. # check if it is orphaned
  764. $query = qq|SELECT count(*)
  765. FROM parts
  766. WHERE partsgroup_id = $form->{id}|;
  767. $sth = $dbh->prepare($query);
  768. $sth->execute || $form->dberror($query);
  769. ($form->{orphaned}) = $sth->fetchrow_array;
  770. $form->{orphaned} = !$form->{orphaned};
  771. $sth->finish;
  772. $dbh->disconnect;
  773. }
  774. sub pricegroups {
  775. my ($self, $myconfig, $form) = @_;
  776. my $var;
  777. # connect to database
  778. my $dbh = $form->dbconnect($myconfig);
  779. $form->{sort} = "pricegroup" unless $form->{sort};
  780. my @a = (pricegroup);
  781. my $sortorder = $form->sort_order(\@a);
  782. my $query = qq|SELECT g.*
  783. FROM pricegroup g|;
  784. my $where = "1 = 1";
  785. if ($form->{pricegroup} ne "") {
  786. $var = $form->like(lc $form->{pricegroup});
  787. $where .= " AND lower(pricegroup) LIKE '$var'";
  788. }
  789. $query .= qq|
  790. WHERE $where
  791. ORDER BY $sortorder|;
  792. if ($form->{status} eq 'orphaned') {
  793. $query = qq|SELECT g.*
  794. FROM pricegroup g
  795. WHERE $where
  796. AND g.id NOT IN (SELECT DISTINCT pricegroup_id
  797. FROM partscustomer
  798. WHERE pricegroup_id > 0)
  799. ORDER BY $sortorder|;
  800. }
  801. $sth = $dbh->prepare($query);
  802. $sth->execute || $form->dberror($query);
  803. my $i = 0;
  804. while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
  805. push @{ $form->{item_list} }, $ref;
  806. $i++;
  807. }
  808. $sth->finish;
  809. $dbh->disconnect;
  810. $i;
  811. }
  812. sub save_pricegroup {
  813. my ($self, $myconfig, $form) = @_;
  814. # connect to database
  815. my $dbh = $form->dbconnect($myconfig);
  816. if ($form->{id}) {
  817. $query = qq|UPDATE pricegroup SET
  818. pricegroup = |.$dbh->quote($form->{pricegroup}).qq|
  819. WHERE id = $form->{id}|;
  820. } else {
  821. $query = qq|INSERT INTO pricegroup
  822. (pricegroup)
  823. VALUES (|.$dbh->quote($form->{pricegroup}).qq|)|;
  824. }
  825. $dbh->do($query) || $form->dberror($query);
  826. $dbh->disconnect;
  827. }
  828. sub get_pricegroup {
  829. my ($self, $myconfig, $form) = @_;
  830. # connect to database
  831. my $dbh = $form->dbconnect($myconfig);
  832. my $query = qq|SELECT *
  833. FROM pricegroup
  834. WHERE id = $form->{id}|;
  835. my $sth = $dbh->prepare($query);
  836. $sth->execute || $form->dberror($query);
  837. my $ref = $sth->fetchrow_hashref(NAME_lc);
  838. for (keys %$ref) { $form->{$_} = $ref->{$_} }
  839. $sth->finish;
  840. # check if it is orphaned
  841. $query = qq|SELECT count(*)
  842. FROM partscustomer
  843. WHERE pricegroup_id = $form->{id}|;
  844. $sth = $dbh->prepare($query);
  845. $sth->execute || $form->dberror($query);
  846. ($form->{orphaned}) = $sth->fetchrow_array;
  847. $form->{orphaned} = !$form->{orphaned};
  848. $sth->finish;
  849. $dbh->disconnect;
  850. }
  851. sub description_translations {
  852. my ($self, $myconfig, $form) = @_;
  853. my $where = "1 = 1";
  854. my $var;
  855. my $ref;
  856. for (qw(partnumber description)) {
  857. if ($form->{$_}) {
  858. $var = $form->like(lc $form->{$_});
  859. $where .= " AND lower(p.$_) LIKE '$var'";
  860. }
  861. }
  862. $where .= " AND p.obsolete = '0'";
  863. $where .= " AND p.id = $form->{id}" if $form->{id};
  864. # connect to database
  865. my $dbh = $form->dbconnect($myconfig);
  866. my %ordinal = ( 'partnumber' => 2,
  867. 'description' => 3
  868. );
  869. my @a = qw(partnumber description);
  870. my $sortorder = $form->sort_order(\@a, \%ordinal);
  871. my $query = qq|SELECT l.description AS language, t.description AS translation,
  872. l.code
  873. FROM translation t
  874. JOIN language l ON (l.code = t.language_code)
  875. WHERE trans_id = ?
  876. ORDER BY 1|;
  877. my $tth = $dbh->prepare($query);
  878. $query = qq|SELECT p.id, p.partnumber, p.description
  879. FROM parts p
  880. WHERE $where
  881. ORDER BY $sortorder|;
  882. my $sth = $dbh->prepare($query);
  883. $sth->execute || $form->dberror($query);
  884. my $tra;
  885. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  886. push @{ $form->{translations} }, $ref;
  887. # get translations for description
  888. $tth->execute($ref->{id}) || $form->dberror;
  889. while ($tra = $tth->fetchrow_hashref(NAME_lc)) {
  890. $form->{trans_id} = $ref->{id};
  891. $tra->{id} = $ref->{id};
  892. push @{ $form->{translations} }, $tra;
  893. }
  894. $tth->finish;
  895. }
  896. $sth->finish;
  897. &get_language("", $dbh, $form) if $form->{id};
  898. $dbh->disconnect;
  899. }
  900. sub partsgroup_translations {
  901. my ($self, $myconfig, $form) = @_;
  902. my $where = "1 = 1";
  903. my $ref;
  904. my $var;
  905. if ($form->{description}) {
  906. $var = $form->like(lc $form->{description});
  907. $where .= " AND lower(p.partsgroup) LIKE '$var'";
  908. }
  909. $where .= " AND p.id = $form->{id}" if $form->{id};
  910. # connect to database
  911. my $dbh = $form->dbconnect($myconfig);
  912. my $query = qq|SELECT l.description AS language, t.description AS translation,
  913. l.code
  914. FROM translation t
  915. JOIN language l ON (l.code = t.language_code)
  916. WHERE trans_id = ?
  917. ORDER BY 1|;
  918. my $tth = $dbh->prepare($query);
  919. $form->sort_order();
  920. $query = qq|SELECT p.id, p.partsgroup AS description
  921. FROM partsgroup p
  922. WHERE $where
  923. ORDER BY 2 $form->{direction}|;
  924. my $sth = $dbh->prepare($query);
  925. $sth->execute || $form->dberror($query);
  926. my $tra;
  927. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  928. push @{ $form->{translations} }, $ref;
  929. # get translations for partsgroup
  930. $tth->execute($ref->{id}) || $form->dberror;
  931. while ($tra = $tth->fetchrow_hashref(NAME_lc)) {
  932. $form->{trans_id} = $ref->{id};
  933. push @{ $form->{translations} }, $tra;
  934. }
  935. $tth->finish;
  936. }
  937. $sth->finish;
  938. &get_language("", $dbh, $form) if $form->{id};
  939. $dbh->disconnect;
  940. }
  941. sub project_translations {
  942. my ($self, $myconfig, $form) = @_;
  943. my $where = "1 = 1";
  944. my $var;
  945. my $ref;
  946. for (qw(projectnumber description)) {
  947. if ($form->{$_}) {
  948. $var = $form->like(lc $form->{$_});
  949. $where .= " AND lower(p.$_) LIKE '$var'";
  950. }
  951. }
  952. $where .= " AND p.id = $form->{id}" if $form->{id};
  953. # connect to database
  954. my $dbh = $form->dbconnect($myconfig);
  955. my %ordinal = ( 'projectnumber' => 2,
  956. 'description' => 3
  957. );
  958. my @a = qw(projectnumber description);
  959. my $sortorder = $form->sort_order(\@a, \%ordinal);
  960. my $query = qq|SELECT l.description AS language, t.description AS translation,
  961. l.code
  962. FROM translation t
  963. JOIN language l ON (l.code = t.language_code)
  964. WHERE trans_id = ?
  965. ORDER BY 1|;
  966. my $tth = $dbh->prepare($query);
  967. $query = qq|SELECT p.id, p.projectnumber, p.description
  968. FROM project p
  969. WHERE $where
  970. ORDER BY $sortorder|;
  971. my $sth = $dbh->prepare($query);
  972. $sth->execute || $form->dberror($query);
  973. my $tra;
  974. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  975. push @{ $form->{translations} }, $ref;
  976. # get translations for description
  977. $tth->execute($ref->{id}) || $form->dberror;
  978. while ($tra = $tth->fetchrow_hashref(NAME_lc)) {
  979. $form->{trans_id} = $ref->{id};
  980. $tra->{id} = $ref->{id};
  981. push @{ $form->{translations} }, $tra;
  982. }
  983. $tth->finish;
  984. }
  985. $sth->finish;
  986. &get_language("", $dbh, $form) if $form->{id};
  987. $dbh->disconnect;
  988. }
  989. sub get_language {
  990. my ($self, $dbh, $form) = @_;
  991. # get language
  992. my $query = qq|SELECT *
  993. FROM language
  994. ORDER BY 2|;
  995. my $sth = $dbh->prepare($query);
  996. $sth->execute || $form->dberror($query);
  997. while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
  998. push @{ $form->{all_language} }, $ref;
  999. }
  1000. $sth->finish;
  1001. }
  1002. sub save_translation {
  1003. my ($self, $myconfig, $form) = @_;
  1004. # connect to database
  1005. my $dbh = $form->dbconnect_noauto($myconfig);
  1006. my $query = qq|DELETE FROM translation
  1007. WHERE trans_id = $form->{id}|;
  1008. $dbh->do($query) || $form->dberror($query);
  1009. $query = qq|INSERT INTO translation (trans_id, language_code, description)
  1010. VALUES ($form->{id}, ?, ?)|;
  1011. my $sth = $dbh->prepare($query) || $form->dberror($query);
  1012. foreach my $i (1 .. $form->{translation_rows}) {
  1013. if ($form->{"language_code_$i"} ne "") {
  1014. $sth->execute($form->{"language_code_$i"}, $form->{"translation_$i"});
  1015. $sth->finish;
  1016. }
  1017. }
  1018. $dbh->commit;
  1019. $dbh->disconnect;
  1020. }
  1021. sub delete_translation {
  1022. my ($self, $myconfig, $form) = @_;
  1023. # connect to database
  1024. my $dbh = $form->dbconnect($myconfig);
  1025. my $query = qq|DELETE FROM translation
  1026. WHERE trans_id = $form->{id}|;
  1027. $dbh->do($query) || $form->dberror($query);
  1028. $dbh->disconnect;
  1029. }
  1030. sub project_sales_order {
  1031. my ($self, $myconfig, $form) = @_;
  1032. # connect to database
  1033. my $dbh = $form->dbconnect($myconfig);
  1034. my $query = qq|SELECT current_date|;
  1035. my ($transdate) = $dbh->selectrow_array($query);
  1036. $form->all_years($myconfig, $dbh);
  1037. $form->all_projects($myconfig, $dbh, $transdate);
  1038. $form->all_employees($myconfig, $dbh, $transdate);
  1039. $dbh->disconnect;
  1040. }
  1041. sub get_jcitems {
  1042. my ($self, $myconfig, $form) = @_;
  1043. # connect to database
  1044. my $dbh = $form->dbconnect($myconfig);
  1045. my $null;
  1046. my $var;
  1047. my $where;
  1048. if ($form->{projectnumber}) {
  1049. ($null, $var) = split /--/, $form->{projectnumber};
  1050. $where .= " AND j.project_id = $var";
  1051. }
  1052. if ($form->{employee}) {
  1053. ($null, $var) = split /--/, $form->{employee};
  1054. $where .= " AND j.employee_id = $var";
  1055. }
  1056. ($form->{transdatefrom}, $form->{transdateto}) = $form->from_to($form->{year}, $form->{month}, $form->{interval}) if $form->{year} && $form->{month};
  1057. if ($form->{transdatefrom}) {
  1058. $where .= " AND j.checkedin >= '$form->{transdatefrom}'";
  1059. }
  1060. if ($form->{transdateto}) {
  1061. $where .= " AND j.checkedout <= (date '$form->{transdateto}' + interval '1 days')";
  1062. }
  1063. my $query;
  1064. my $ref;
  1065. $query = qq|SELECT j.id, j.description, j.qty - j.allocated AS qty,
  1066. j.sellprice, j.parts_id, pr.$form->{vc}_id, j.project_id,
  1067. j.checkedin::date AS transdate, j.notes,
  1068. c.name AS $form->{vc}, pr.projectnumber, p.partnumber
  1069. FROM jcitems j
  1070. JOIN project pr ON (pr.id = j.project_id)
  1071. JOIN employee e ON (e.id = j.employee_id)
  1072. JOIN parts p ON (p.id = j.parts_id)
  1073. LEFT JOIN $form->{vc} c ON (c.id = pr.$form->{vc}_id)
  1074. WHERE pr.parts_id IS NULL
  1075. AND j.allocated != j.qty
  1076. $where
  1077. ORDER BY pr.projectnumber, c.name, j.checkedin::date|;
  1078. if ($form->{summary}) {
  1079. $query =~ s/j\.description/p\.description/;
  1080. $query =~ s/c\.name,/c\.name, j\.parts_id, /;
  1081. }
  1082. $sth = $dbh->prepare($query);
  1083. $sth->execute || $form->dberror($query);
  1084. # tax accounts
  1085. $query = qq|SELECT c.accno
  1086. FROM chart c
  1087. JOIN partstax pt ON (pt.chart_id = c.id)
  1088. WHERE pt.parts_id = ?|;
  1089. my $tth = $dbh->prepare($query) || $form->dberror($query);
  1090. my $ptref;
  1091. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  1092. $tth->execute($ref->{parts_id});
  1093. $ref->{taxaccounts} = "";
  1094. while ($ptref = $tth->fetchrow_hashref(NAME_lc)) {
  1095. $ref->{taxaccounts} .= "$ptref->{accno} ";
  1096. }
  1097. $tth->finish;
  1098. chop $ref->{taxaccounts};
  1099. $ref->{amount} = $ref->{sellprice} * $ref->{qty};
  1100. push @{ $form->{jcitems} }, $ref;
  1101. }
  1102. $sth->finish;
  1103. $query = qq|SELECT value FROM defaults WHERE setting_key = 'curr'|;
  1104. ($form->{currency}) = $dbh->selectrow_array($query);
  1105. $form->{currency} =~ s/:.*//;
  1106. $form->{defaultcurrency} = $form->{currency};
  1107. $query = qq|SELECT c.accno, t.rate
  1108. FROM tax t
  1109. JOIN chart c ON (c.id = t.chart_id)|;
  1110. $sth = $dbh->prepare($query);
  1111. $sth->execute || $form->dberror($query);
  1112. while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
  1113. $form->{taxaccounts} .= "$ref->{accno} ";
  1114. $form->{"$ref->{accno}_rate"} = $ref->{rate};
  1115. }
  1116. chop $form->{taxaccounts};
  1117. $sth->finish;
  1118. $dbh->disconnect;
  1119. }
  1120. sub allocate_projectitems {
  1121. my ($self, $myconfig, $form) = @_;
  1122. # connect to database
  1123. my $dbh = $form->dbconnect_noauto($myconfig);
  1124. for my $i (1 .. $form->{rowcount}) {
  1125. for (split / /, $form->{"jcitems_$i"}) {
  1126. my ($id, $qty) = split /:/, $_;
  1127. $form->update_balance($dbh,
  1128. 'jcitems',
  1129. 'allocated',
  1130. "id = $id",
  1131. $qty);
  1132. }
  1133. }
  1134. $rc = $dbh->commit;
  1135. $dbh->disconnect;
  1136. $rc;
  1137. }
  1138. 1;