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