title>
summaryrefslogtreecommitdiff
path: root/LedgerSMB/IC.pm
blob: f20cabf055b4424d19899fb35eb06b6692b1755d (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) 2000
  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. # Inventory Control backend
  31. #
  32. #======================================================================
  33. package IC;
  34. sub get_part {
  35. my ( $self, $myconfig, $form ) = @_;
  36. # connect to db
  37. my $dbh = $form->{dbh};
  38. my $i;
  39. my $query = qq|
  40. SELECT p.*, c1.accno AS inventory_accno,
  41. c1.description AS inventory_description,
  42. c2.accno AS income_accno,
  43. c2.description AS income_description,
  44. c3.accno AS expense_accno,
  45. c3.description AS expense_description, pg.partsgroup
  46. FROM parts p
  47. LEFT JOIN chart c1 ON (p.inventory_accno_id = c1.id)
  48. LEFT JOIN chart c2 ON (p.income_accno_id = c2.id)
  49. LEFT JOIN chart c3 ON (p.expense_accno_id = c3.id)
  50. LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
  51. WHERE p.id = ?|;
  52. my $sth = $dbh->prepare($query);
  53. $sth->execute( $form->{id} ) || $form->dberror($query);
  54. my $ref = $sth->fetchrow_hashref(NAME_lc);
  55. $form->db_parse_numeric(sth => $sth, hashref => $ref);
  56. # copy to $form variables
  57. for ( keys %$ref ) { $form->{$_} = $ref->{$_} }
  58. $sth->finish;
  59. # part, service item or labor
  60. $form->{item} = ( $form->{inventory_accno_id} ) ? 'part' : 'service';
  61. $form->{item} = 'labor' if !$form->{income_accno_id};
  62. if ( $form->{assembly} ) {
  63. $form->{item} = 'assembly';
  64. # retrieve assembly items
  65. $query = qq|
  66. SELECT p.id, p.partnumber, p.description,
  67. p.sellprice, p.weight, a.qty, a.bom, a.adj,
  68. p.unit, p.lastcost, p.listprice,
  69. pg.partsgroup, p.assembly, p.partsgroup_id
  70. FROM parts p
  71. JOIN assembly a ON (a.parts_id = p.id)
  72. LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
  73. WHERE a.id = ?|;
  74. $sth = $dbh->prepare($query);
  75. $sth->execute( $form->{id} ) || $form->dberror($query);
  76. $form->{assembly_rows} = 0;
  77. while ( my $ref = $sth->fetchrow_hashref('NAME_lc') ) {
  78. $form->db_parse_numeric(sth => $sth, hashref => $ref);
  79. $form->{assembly_rows}++;
  80. foreach my $key ( keys %{$ref} ) {
  81. $form->{"${key}_$form->{assembly_rows}"} = $ref->{$key};
  82. }
  83. }
  84. $sth->finish;
  85. }
  86. # setup accno hash for <option checked>
  87. # {amount} is used in create_links
  88. for (qw(inventory income expense)) {
  89. $form->{amount}{"IC_$_"} = {
  90. accno => $form->{"${_}_accno"},
  91. description => $form->{"${_}_description"}
  92. };
  93. }
  94. if ( $form->{item} =~ /(part|assembly)/ ) {
  95. if ( $form->{makemodel} ne "" ) {
  96. $query = qq|
  97. SELECT make, model
  98. FROM makemodel
  99. WHERE parts_id = ?|;
  100. $sth = $dbh->prepare($query);
  101. $sth->execute( $form->{id} ) || $form->dberror($query);
  102. while ( $ref = $sth->fetchrow_hashref('NAME_lc') ) {
  103. push @{ $form->{makemodels} }, $ref;
  104. }
  105. $sth->finish;
  106. }
  107. }
  108. # now get accno for taxes
  109. $query = qq|
  110. SELECT c.accno FROM chart c, partstax pt
  111. WHERE pt.chart_id = c.id AND pt.parts_id = ?|;
  112. $sth = $dbh->prepare($query);
  113. $sth->execute( $form->{id} ) || $form->dberror($query);
  114. while ( ($key) = $sth->fetchrow_array ) {
  115. $form->{amount}{$key} = $key;
  116. }
  117. $sth->finish;
  118. my $id = $dbh->quote( $form->{id} );
  119. # is it an orphan
  120. $query = qq|
  121. SELECT parts_id FROM invoice WHERE parts_id = $id
  122. UNION
  123. SELECT parts_id FROM orderitems WHERE parts_id = $id
  124. UNION
  125. SELECT parts_id FROM assembly WHERE parts_id = $id
  126. UNION
  127. SELECT parts_id FROM jcitems WHERE parts_id = $id|;
  128. ( $form->{orphaned} ) = $dbh->selectrow_array($query);
  129. $form->{orphaned} = !$form->{orphaned};
  130. $form->{orphaned} = 0 if $form->{project_id};
  131. if ( $form->{item} eq 'assembly' ) {
  132. if ( $form->{orphaned} ) {
  133. $form->{orphaned} = !$form->{onhand};
  134. }
  135. }
  136. if ( $form->{item} =~ /(part|service)/ ) {
  137. # get vendors
  138. $query = qq|
  139. SELECT v.id, v.name, pv.partnumber,
  140. pv.lastcost, pv.leadtime,
  141. pv.curr AS vendorcurr
  142. FROM partsvendor pv
  143. JOIN vendor v ON (v.id = pv.vendor_id)
  144. WHERE pv.parts_id = ?
  145. ORDER BY 2|;
  146. $sth = $dbh->prepare($query);
  147. $sth->execute( $form->{id} ) || $form->dberror($query);
  148. while ( $ref = $sth->fetchrow_hashref('NAME_lc') ) {
  149. $form->db_parse_numeric(sth => $sth, hashref => $ref);
  150. push @{ $form->{vendormatrix} }, $ref;
  151. }
  152. $sth->finish;
  153. }
  154. # get matrix
  155. if ( $form->{item} ne 'labor' ) {
  156. $query = qq|
  157. SELECT pc.pricebreak, pc.sellprice AS customerprice,
  158. pc.curr AS customercurr, pc.validfrom,
  159. pc.validto, c.name, c.id AS cid,
  160. g.pricegroup, g.id AS gid
  161. FROM partscustomer pc
  162. LEFT JOIN customer c ON (c.id = pc.customer_id)
  163. LEFT JOIN pricegroup g ON (g.id = pc.pricegroup_id)
  164. WHERE pc.parts_id = ?
  165. ORDER BY c.name, g.pricegroup, pc.pricebreak|;
  166. $sth = $dbh->prepare($query);
  167. $sth->execute( $form->{id} ) || $form->dberror($query);
  168. while ( $ref = $sth->fetchrow_hashref('NAME_lc') ) {
  169. $form->db_parse_numeric(sth => $sth, hashref => $ref);
  170. push @{ $form->{customermatrix} }, $ref;
  171. }
  172. $sth->finish;
  173. }
  174. $form->run_custom_queries( 'parts', 'SELECT' );
  175. }
  176. sub save {
  177. my ( $self, $myconfig, $form ) = @_;
  178. $form->{partnumber} =
  179. $form->update_defaults( $myconfig, "partnumber", $dbh )
  180. if !$form->{partnumber};
  181. ( $form->{inventory_accno} ) = split( /--/, $form->{IC_inventory} );
  182. ( $form->{expense_accno} ) = split( /--/, $form->{IC_expense} );
  183. ( $form->{income_accno} ) = split( /--/, $form->{IC_income} );
  184. my $dbh = $form->{dbh};
  185. # undo amount formatting
  186. for (qw(rop weight listprice sellprice lastcost stock)) {
  187. $form->{$_} = $form->parse_amount( $myconfig, $form->{$_} );
  188. }
  189. $form->{makemodel} =
  190. ( ( $form->{make_1} ) || ( $form->{model_1} ) ) ? 1 : 0;
  191. $form->{assembly} = ( $form->{item} eq 'assembly' ) ? 1 : 0;
  192. for (qw(alternate obsolete onhand)) { $form->{$_} *= 1 }
  193. my $query;
  194. my $sth;
  195. my $i;
  196. my $null;
  197. my $vendor_id;
  198. my $customer_id;
  199. if ( $form->{id} ) {
  200. # get old price
  201. $query = qq|
  202. SELECT id, listprice, sellprice, lastcost, weight,
  203. project_id
  204. FROM parts
  205. WHERE id = ?|;
  206. my $sth = $dbh->prepare($query);
  207. $sth->execute( $form->{id} );
  208. my ( $id, $listprice, $sellprice, $lastcost, $weight, $project_id ) =
  209. $sth->fetchrow_array();
  210. if ($id) {
  211. if ( !$project_id ) {
  212. # if item is part of an assembly
  213. # adjust all assemblies
  214. $query = qq|
  215. SELECT id, qty, adj
  216. FROM assembly
  217. WHERE parts_id = ?|;
  218. $sth = $dbh->prepare($query);
  219. $sth->execute( $form->{id} )
  220. || $form->dberror($query);
  221. while ( my ( $id, $qty, $adj ) = $sth->fetchrow_array ) {
  222. &update_assembly(
  223. $dbh, $form,
  224. $id, $qty,
  225. $adj, $listprice * 1,
  226. $sellprice * 1, $lastcost * 1,
  227. $weight * 1
  228. );
  229. }
  230. $sth->finish;
  231. }
  232. if ( $form->{item} =~ /(part|service)/ ) {
  233. # delete partsvendor records
  234. $query = qq|
  235. DELETE FROM partsvendor
  236. WHERE parts_id = ?|;
  237. $sth = $dbh->prepare($query);
  238. $sth->execute( $form->{id} )
  239. || $form->dberror($query);
  240. }
  241. if ( $form->{item} !~ /(service|labor)/ ) {
  242. # delete makemodel records
  243. $query = qq|
  244. DELETE FROM makemodel
  245. WHERE parts_id = ?|;
  246. $sth = $dbh->prepare($query);
  247. $sth->execute( $form->{id} )
  248. || $form->dberror($query);
  249. }
  250. if ( $form->{item} eq 'assembly' ) {
  251. if ( $form->{onhand} ) {
  252. &adjust_inventory( $dbh, $form, $form->{id},
  253. $form->{onhand} * -1 );
  254. }
  255. if ( $form->{orphaned} ) {
  256. # delete assembly records
  257. $query = qq|
  258. DELETE FROM assembly
  259. WHERE id = ?|;
  260. $sth = $dbh->prepare($query);
  261. $sth->execute( $form->{id} )
  262. || $form->dberror($query);
  263. }
  264. else {
  265. for $i ( 1 .. $form->{assembly_rows} - 1 ) {
  266. # update BOM, A only
  267. for (qw(bom adj)) {
  268. $form->{"${_}_$i"} *= 1;
  269. }
  270. $query = qq|
  271. UPDATE assembly
  272. SET bom = ?,
  273. adj = ?
  274. WHERE id = ?
  275. AND parts_id = ?|;
  276. $sth = $dbh->prepare($query);
  277. $sth->execute(
  278. $form->{"bom_$i"}, $form->{"adj_$i"},
  279. $form->{id}, $form->{"id_$i"}
  280. ) || $form->dberror($query);
  281. }
  282. }
  283. $form->{onhand} += $form->{stock};
  284. }
  285. # delete tax records
  286. $query = qq|DELETE FROM partstax WHERE parts_id = ?|;
  287. $sth = $dbh->prepare($query);
  288. $sth->execute( $form->{id} ) || $form->dberror($query);
  289. # delete matrix
  290. $query = qq|
  291. DELETE FROM partscustomer
  292. WHERE parts_id = ?|;
  293. $sth = $dbh->prepare($query);
  294. $sth->execute( $form->{id} ) || $form->dberror($query);
  295. }
  296. else {
  297. $query = qq|INSERT INTO parts (id) VALUES (?)|;
  298. $sth = $dbh->prepare($query);
  299. $sth->execute( $form->{id} ) || $form->dberror($query);
  300. }
  301. }
  302. if ( !$form->{id} ) {
  303. my $uid = localtime;
  304. $uid .= "$$";
  305. $query = qq|INSERT INTO parts (partnumber) VALUES ('$uid')|;
  306. $dbh->do($query) || $form->dberror($query);
  307. $query = qq|SELECT id FROM parts WHERE partnumber = '$uid'|;
  308. $sth = $dbh->prepare($query);
  309. $sth->execute || $form->dberror($query);
  310. ( $form->{id} ) = $sth->fetchrow_array;
  311. $sth->finish;
  312. $form->{orphaned} = 1;
  313. $form->{onhand} = ( $form->{stock} * 1 )
  314. if $form->{item} eq 'assembly';
  315. }
  316. my $partsgroup_id;
  317. ( $null, $partsgroup_id ) = split /--/, $form->{partsgroup};
  318. $partsgroup_id *= 1;
  319. if ( !$form->{priceupdate} ) {
  320. $form->{priceupdate} = 'now';
  321. }
  322. $query = qq|
  323. UPDATE parts