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