daba6887e5944f3d4033c541dd6cd6c698f52fac
[kivitendo-erp.git] / bin / mozilla / ic.pl
1 #=====================================================================
2 # LX-Office ERP
3 # Copyright (C) 2004
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
6 #
7 #=====================================================================
8 # SQL-Ledger, Accounting
9 # Copyright (c) 2001
10 #
11 #  Author: Dieter Simader
12 #   Email: dsimader@sql-ledger.org
13 #     Web: http://www.sql-ledger.org
14 #
15 #
16 # This program is free software; you can redistribute it and/or modify
17 # it under the terms of the GNU General Public License as published by
18 # the Free Software Foundation; either version 2 of the License, or
19 # (at your option) any later version.
20 #
21 # This program is distributed in the hope that it will be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #======================================================================
29 #
30 # Inventory Control module
31 #
32 #======================================================================
33 #$locale->text('ea');
34
35 use POSIX qw(strftime);
36
37 use SL::IC;
38 use SL::ReportGenerator;
39
40 #use SL::PE;
41
42 # use strict;
43 #use warnings;
44
45 # global imports
46 our ($form, $locale, %myconfig, $lxdebug);
47
48 require "bin/mozilla/io.pl";
49 require "bin/mozilla/invoice_io.pl";
50 require "bin/mozilla/common.pl";
51 require "bin/mozilla/reportgenerator.pl";
52
53 1;
54
55 # end of main
56
57 sub add {
58   $lxdebug->enter_sub();
59
60   $form->{title} = $locale->text('Add ' . ucfirst $form->{item});
61
62   $form->{callback} =
63     "$form->{script}?action=add&item=$form->{item}&login=$form->{login}&password=$form->{password}"
64     unless $form->{callback};
65
66   $form->{"unit_changeable"} = 1;
67
68   IC->get_pricegroups(\%myconfig, \%$form);
69   &link_part;
70   &display_form;
71
72   $lxdebug->leave_sub();
73 }
74
75 sub search {
76   $lxdebug->enter_sub();
77
78   # switch for backward sorting
79   $form->{revers} = 0;
80
81   # memory for which table was sort at last time
82   $form->{lastsort} = "";
83
84   # counter for added entries to top100
85   $form->{ndxs_counter} = 0;
86
87   # $locale->text('Parts')
88   # $locale->text('Services')
89
90   my $is_service  = $form->{searchitems} eq 'service';
91   my $is_assembly = $form->{searchitems} eq 'assembly';
92
93   $form->{title} = (ucfirst $form->{searchitems}) . "s";
94   $form->{title} = $locale->text($form->{title});
95   $form->{title} = $locale->text('Assemblies') if $is_assembly;
96
97   $form->{jsscript} = 1;
98
99   $form->header;
100
101   print $form->parse_html_template('ic/search', { is_assembly => $is_assembly, 
102                                                   is_service  => $is_service, 
103                                                   dateformat  => $myconfig{dateformat}, });
104
105   $lxdebug->leave_sub();
106 }    #end search()
107
108 sub search_update_prices {
109   $lxdebug->enter_sub();
110
111   my $pricegroups = IC->get_pricegroups(\%myconfig, \%$form);
112
113   $form->header;
114
115   print $form->parse_html_template('ic/search_update_prices', { PRICE_ROWS => $pricegroups });
116
117   $lxdebug->leave_sub();
118 }    #end search()
119
120 sub confirm_price_update {
121   $lxdebug->enter_sub();
122
123   $form->{nextsub} = "update_prices";
124   $form->header;
125
126   map { delete $form->{$_} } qw(action header);
127   
128   print $form->parse_html_template('ic/confirm_price_update', { HIDDENS => [ map { name => $_, value => $form->{$_} }, keys %$form ] });
129
130   $lxdebug->leave_sub();
131 }
132
133 sub update_prices {
134   $lxdebug->enter_sub();
135
136   if (IC->update_prices(\%myconfig, \%$form)) {
137     $form->redirect($form->{update_count} . $locale->text('prices updated!'));
138   } else {
139     $form->error($locale->text('Could not update prices!'));
140   }
141
142   $lxdebug->leave_sub();
143 }
144
145 sub choice {
146   $lxdebug->enter_sub();
147
148   our ($j, $lastndx);
149   my ($totop100);
150
151   $form->{title} = $locale->text('Top 100 hinzufuegen');
152
153   $form->header;
154
155   print qq|
156   <body>
157
158   <form method=post action=$form->{script}>
159
160   <input type=hidden name=searchitems value=$form->{searchitems}>
161   <input type=hidden name=title value="$form->{title}">
162
163   <input type=hidden name=revers value="$form->{revers}">
164   <input type=hidden name=lastsort value="$form->{lastsort}">|;
165
166   print qq|
167       <table>
168         <tr class=listheading>
169          <th class=listheading nowrap>| . $locale->text('Part Number') . qq|</th>
170          <th class=listheading nowrap>| . $locale->text('Part Description') . qq|</th>
171         </tr>
172         <tr valign=top>
173          <td><input type=text name=partnumber size=20 value=></td>
174          <td><input type=text name=description size=30 value=></td>
175        </tr>
176       </table>
177      <br>|;
178
179   print qq|
180
181 <input type=hidden name=login value=$form->{login}>
182 <input type=hidden name=password value=$form->{password}>
183
184 <input type=hidden name=itemstatus value="$form->{itemstatus}">
185 <input type=hidden name=l_linetotal value="$form->{l_linetotal}">
186 <input type=hidden name=l_partnumber value="$form->{l_partnumber}">
187 <input type=hidden name=l_description value="$form->{l_description}">
188 <input type=hidden name=l_onhand value="$form->{l_onhand}">
189 <input type=hidden name=l_unit value="$form->{l_unit}">
190 <input type=hidden name=l_sellprice value="$form->{l_sellprice}">
191 <input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
192 <input type=hidden name=sort value="$form->{sort}">
193 <input type=hidden name=revers value="$form->{revers}">
194 <input type=hidden name=lastsort value="$form->{lastsort}">
195
196 <input type=hidden name=bom value="$form->{bom}">
197 <input type=hidden name=titel value="$form->{titel}">
198 <input type=hidden name=searchitems value="$form->{searchitems}">
199
200 <input type=hidden name=row value=$j>
201
202 <input type=hidden name=nextsub value=item_selected>
203
204 <input type=hidden name=test value=item_selected>
205
206 <input name=lastndx type=hidden value=$lastndx>
207
208 <input name=ndxs_counter type=hidden value=$form->{ndxs_counter}>
209
210 <input name=extras type=hidden value=$form->{extras}>|;
211
212   my ($partnumber, $description, $unit, $sellprice, $soldtotal);
213   # if choice set data
214   if ($form->{ndx}) {
215     for (my $i = 0; $i < $form->{ndxs_counter}; $i++) {
216
217       # prepeare data
218       $partnumber  = $form->{"totop100_partnumber_$j"};
219       $description = $form->{"totop100_description_$j"};
220       $unit        = $form->{"totop100_unit_$j"};
221       $sellprice   = $form->{"totop100_sellprice_$j"};
222       $soldtotal   = $form->{"totop100_soldtotal_$j"};
223
224       # insert data into top100
225       push @{ $form->{parts} },
226         { number      => "",
227           partnumber  => "$partnumber",
228           description => "$description",
229           unit        => "$unit",
230           sellprice   => "$sellprice",
231           soldtotal   => "$soldtotal" };
232     }    #rof
233   }    #fi
234
235   $totop100 = "";
236
237   # set data for next page
238   if (($form->{ndxs_counter}) > 0) {
239     for (my $i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
240       $partnumber  = $form->{"totop100_partnumber_$i"};
241       $description = $form->{"totop100_description_$i"};
242       $unit        = $form->{"totop100_unit_$i"};
243       $sellprice   = $form->{"totop100_sellprice_$i"};
244       $soldtotal   = $form->{"totop100_soldtotal_$i"};
245
246       $totop100 .= qq|
247 <input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
248 <input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
249 <input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
250 <input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
251 <input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
252       |;
253     }    #rof
254   }    #fi
255
256   print $totop100;
257
258   print qq|
259      <input class=submit type=submit name=action value="|
260     . $locale->text('list') . qq|">
261     </form>
262
263    </body>
264   </html>|;
265   $lxdebug->leave_sub();
266 }    #end choice
267
268 sub list {
269   $lxdebug->enter_sub();
270
271   our ($lastndx);
272   our ($partnumber, $description, $unit, $sellprice, $soldtotal);
273
274   my @sortorders = ("", "partnumber", "description", "all");
275   my $sortorder = $sortorders[($form->{description} ? 2 : 0) + ($form->{partnumber} ? 1 : 0)];
276   IC->get_parts(\%myconfig, \%$form, $sortorder);
277
278   $form->{title} = $locale->text('Top 100 hinzufuegen');
279
280   $form->header;
281
282   print qq|
283 <body>
284   <form method=post action=ic.pl>
285     <table width=100%>
286      <tr>
287       <th class=listtop colspan=6>| . $locale->text('choice part') . qq|</th>
288      </tr>
289         <tr height="5"></tr>
290         <tr class=listheading>
291           <th>&nbsp;</th>
292           <th class=listheading>| . $locale->text('Part Number') . qq|</th>
293           <th class=listheading>| . $locale->text('Part Description') . qq|</th>
294           <th class=listheading>| . $locale->text('Unit of measure') . qq|</th>
295           <th class=listheading>| . $locale->text('Sell Price') . qq|</th>
296           <th class=listheading>| . $locale->text('soldtotal') . qq|</th>
297         </tr>|;
298
299   my $j = 0;
300   my $i = $form->{rows};
301
302   for ($j = 1; $j <= $i; $j++) {
303
304     print qq|
305         <tr class=listrow1>|;
306     if ($j == 1) {
307       print qq|
308             <td><input name=ndx class=radio type=radio value=$j checked></td>|;
309     } else {
310       print qq|
311           <td><input name=ndx class=radio type=radio value=$j></td>|;
312     }
313     print qq|
314           <td><input name="new_partnumber_$j" type=hidden value="$form->{"partnumber_$j"}">$form->{"partnumber_$j"}</td>
315           <td><input name="new_description_$j" type=hidden value="$form->{"description_$j"}">$form->{"description_$j"}</td>
316           <td><input name="new_unit_$j" type=hidden value="$form->{"unit_$j"}">$form->{"unit_$j"}</td>
317           <td><input name="new_sellprice_$j" type=hidden value="$form->{"sellprice_$j"}">$form->{"sellprice_$j"}</td>
318           <td><input name="new_soldtotal_$j" type=hidden value="$form->{"soldtotal_$j"}">$form->{"soldtotal_$j"}</td>
319         </tr>
320
321         <input name="new_id_$j" type=hidden value="$form->{"id_$j"}">|;
322   }
323
324   print qq|
325
326 </table>
327
328 <br>
329
330
331 <input type=hidden name=login value=$form->{login}>
332 <input type=hidden name=password value=$form->{password}>
333
334 <input type=hidden name=itemstatus value="$form->{itemstatus}">
335 <input type=hidden name=l_linetotal value="$form->{l_linetotal}">
336 <input type=hidden name=l_partnumber value="$form->{l_partnumber}">
337 <input type=hidden name=l_description value="$form->{l_description}">
338 <input type=hidden name=l_onhand value="$form->{l_onhand}">
339 <input type=hidden name=l_unit value="$form->{l_unit}">
340 <input type=hidden name=l_sellprice value="$form->{l_sellprice}">
341 <input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
342 <input type=hidden name=sort value="$form->{sort}">
343 <input type=hidden name=revers value="$form->{revers}">
344 <input type=hidden name=lastsort value="$form->{lastsort}">
345
346 <input type=hidden name=bom value="$form->{bom}">
347 <input type=hidden name=titel value="$form->{titel}">
348 <input type=hidden name=searchitems value="$form->{searchitems}">
349
350 <input type=hidden name=row value=$j>
351
352 <input type=hidden name=nextsub value=item_selected>
353
354 <input name=lastndx type=hidden value=$lastndx>
355
356 <input name=ndxs_counter type=hidden value=$form->{ndxs_counter}>|;
357
358   my $totop100 = "";
359
360   if (($form->{ndxs_counter}) > 0) {
361     for ($i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
362
363       $partnumber  = $form->{"totop100_partnumber_$i"};
364       $description = $form->{"totop100_description_$i"};
365       $unit        = $form->{"totop100_unit_$i"};
366       $sellprice   = $form->{"totop100_sellprice_$i"};
367       $soldtotal   = $form->{"totop100_soldtotal_$i"};
368
369       $totop100 .= qq|
370 <input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
371 <input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
372 <input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
373 <input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
374 <input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
375       |;
376     }    #rof
377   }    #fi
378
379   print $totop100;
380
381   print qq|
382 <input class=submit type=submit name=action value="|
383     . $locale->text('TOP100') . qq|">
384
385 </form>
386 </body>
387 </html>
388 |;
389   $lxdebug->leave_sub();
390 }    #end list()
391
392 sub top100 {
393   $lxdebug->enter_sub();
394
395   if ($form->{ndx}) {
396     $form->{ndxs_counter}++;
397
398     if ($form->{ndxs_counter} > 0) {
399
400       my $index = $form->{ndx};
401
402       $form->{"totop100_partnumber_$form->{ndxs_counter}"} = $form->{"new_partnumber_$index"};
403       $form->{"totop100_description_$form->{ndxs_counter}"} = $form->{"new_description_$index"};
404       $form->{"totop100_unit_$form->{ndxs_counter}"} = $form->{"new_unit_$index"};
405       $form->{"totop100_sellprice_$form->{ndxs_counter}"} = $form->{"new_sellprice_$index"};
406       $form->{"totop100_soldtotal_$form->{ndxs_counter}"} = $form->{"new_soldtotal_$index"};
407     }    #fi
408   }    #fi
409   &addtop100();
410   $lxdebug->leave_sub();
411 }    #end top100
412
413 sub addtop100 {
414   $lxdebug->enter_sub();
415
416   my ($revers, $lastsort, $callback, $option, $description, $sameitem,
417       $partnumber, $unit, $sellprice, $soldtotal, $totop100, $onhand, $align);
418   my (@column_index, %column_header, %column_data);
419   my ($totalsellprice, $totallastcost, $totallistprice, $subtotalonhand, $subtotalsellprice, $subtotallastcost, $subtotallistprice);
420
421   $form->{top100}      = "top100";
422   $form->{l_soldtotal} = "Y";
423   $form->{soldtotal}   = "soldtotal";
424   $form->{sort}        = "soldtotal";
425   $form->{l_qty}       = "N";
426   $form->{l_linetotal} = "";
427   $form->{revers}      = 1;
428   $form->{number}      = "position";
429   $form->{l_number}    = "Y";
430
431   $totop100 = "";
432
433   $form->{title} = $locale->text('Top 100');
434
435   $revers   = $form->{revers};
436   $lastsort = $form->{lastsort};
437
438   if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
439     $form->{revers}   = 0;
440     $form->{lastsort} = "partnumber";
441     $form->{sort}     = "partnumber";
442   }    #fi
443
444   $callback =
445     "$form->{script}?action=top100&login=$form->{login}&password=$form->{password}&searchitems=$form->{searchitems}&itemstatus=$form->{itemstatus}&bom=$form->{bom}&l_linetotal=$form->{l_linetotal}&title="
446     . $form->escape($form->{title}, 1);
447
448   # if we have a serialnumber limit search
449   if ($form->{serialnumber} || $form->{l_serialnumber}) {
450     $form->{l_serialnumber} = "Y";
451     unless (   $form->{bought}
452             || $form->{sold}
453             || $form->{rfq}
454             || $form->{quoted}) {
455       $form->{bought} = $form->{sold} = 1;
456     }
457   }
458   IC->all_parts(\%myconfig, \%$form);
459
460   if ($form->{itemstatus} eq 'active') {
461     $option .= $locale->text('Active') . " : ";
462   }
463   if ($form->{itemstatus} eq 'obsolete') {
464     $option .= $locale->text('Obsolete') . " : ";
465   }
466   if ($form->{itemstatus} eq 'orphaned') {
467     $option .= $locale->text('Orphaned') . " : ";
468   }
469   if ($form->{itemstatus} eq 'onhand') {
470     $option .= $locale->text('On Hand') . " : ";
471     $form->{l_onhand} = "Y";
472   }
473   if ($form->{itemstatus} eq 'short') {
474     $option .= $locale->text('Short') . " : ";
475     $form->{l_onhand} = "Y";
476   }
477   if ($form->{onorder}) {
478     $form->{l_ordnumber} = "Y";
479     $callback .= "&onorder=$form->{onorder}";
480     $option   .= $locale->text('On Order') . " : ";
481   }
482   if ($form->{ordered}) {
483     $form->{l_ordnumber} = "Y";
484     $callback .= "&ordered=$form->{ordered}";
485     $option   .= $locale->text('Ordered') . " : ";
486   }
487   if ($form->{rfq}) {
488     $form->{l_quonumber} = "Y";
489     $callback .= "&rfq=$form->{rfq}";
490     $option   .= $locale->text('RFQ') . " : ";
491   }
492   if ($form->{quoted}) {
493     $form->{l_quonumber} = "Y";
494     $callback .= "&quoted=$form->{quoted}";
495     $option   .= $locale->text('Quoted') . " : ";
496   }
497   if ($form->{bought}) {
498     $form->{l_invnumber} = "Y";
499     $callback .= "&bought=$form->{bought}";
500     $option   .= $locale->text('Bought') . " : ";
501   }
502   if ($form->{sold}) {
503     $form->{l_invnumber} = "Y";
504     $callback .= "&sold=$form->{sold}";
505     $option   .= $locale->text('Sold') . " : ";
506   }
507   if (   $form->{bought}
508       || $form->{sold}
509       || $form->{onorder}
510       || $form->{ordered}
511       || $form->{rfq}
512       || $form->{quoted}) {
513
514     $form->{l_lastcost} = "";
515     $form->{l_name}     = "Y";
516     if ($form->{transdatefrom}) {
517       $callback .= "&transdatefrom=$form->{transdatefrom}";
518       $option   .= "\n<br>"
519         . $locale->text('From')
520         . "&nbsp;"
521         . $locale->date(\%myconfig, $form->{transdatefrom}, 1);
522     }
523     if ($form->{transdateto}) {
524       $callback .= "&transdateto=$form->{transdateto}";
525       $option   .= "\n<br>"
526         . $locale->text('To')
527         . "&nbsp;"
528         . $locale->date(\%myconfig, $form->{transdateto}, 1);
529     }
530   }
531
532   $option .= "<br>";
533
534   if ($form->{partnumber}) {
535     $callback .= "&partnumber=$form->{partnumber}";
536     $option   .= $locale->text('Part Number') . qq| : $form->{partnumber}<br>|;
537   }
538   if ($form->{ean}) {
539     $callback .= "&partnumber=$form->{ean}";
540     $option   .= $locale->text('EAN') . qq| : $form->{ean}<br>|;
541   }
542   if ($form->{partsgroup}) {
543     $callback .= "&partsgroup=$form->{partsgroup}";
544     $option   .= $locale->text('Group') . qq| : $form->{partsgroup}<br>|;
545   }
546   if ($form->{serialnumber}) {
547     $callback .= "&serialnumber=$form->{serialnumber}";
548     $option   .=
549       $locale->text('Serial Number') . qq| : $form->{serialnumber}<br>|;
550   }
551   if ($form->{description}) {
552     $callback .= "&description=$form->{description}";
553     $description = $form->{description};
554     $description =~ s/
555 /<br>/g;
556     $option .=
557       $locale->text('Part Description') . qq| : $form->{description}<br>|;
558   }
559   if ($form->{make}) {
560     $callback .= "&make=$form->{make}";
561     $option   .= $locale->text('Make') . qq| : $form->{make}<br>|;
562   }
563   if ($form->{model}) {
564     $callback .= "&model=$form->{model}";
565     $option   .= $locale->text('Model') . qq| : $form->{model}<br>|;
566   }
567   if ($form->{drawing}) {
568     $callback .= "&drawing=$form->{drawing}";
569     $option   .= $locale->text('Drawing') . qq| : $form->{drawing}<br>|;
570   }
571   if ($form->{microfiche}) {
572     $callback .= "&microfiche=$form->{microfiche}";
573     $option   .= $locale->text('Microfiche') . qq| : $form->{microfiche}<br>|;
574   }
575   if ($form->{l_soldtotal}) {
576     $callback .= "&soldtotal=$form->{soldtotal}";
577     $option   .= $locale->text('soldtotal') . qq| : $form->{soldtotal}<br>|;
578   }
579
580   my @columns = $form->sort_columns(
581     qw(number partnumber ean description partsgroup bin onhand rop unit listprice linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost priceupdate weight image drawing microfiche invnumber ordnumber quonumber name serialnumber soldtotal)
582   );
583
584   if ($form->{l_linetotal}) {
585     $form->{l_onhand} = "Y";
586     $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
587     if ($form->{l_lastcost}) {
588       $form->{l_linetotallastcost} = "Y";
589       if (($form->{searchitems} eq 'assembly') && !$form->{bom}) {
590         $form->{l_linetotallastcost} = "";
591       }
592     }
593     $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
594   }
595
596   if ($form->{searchitems} eq 'service') {
597
598     # remove bin, weight and rop from list
599     map { $form->{"l_$_"} = "" } qw(bin weight rop);
600
601     $form->{l_onhand} = "";
602
603     # qty is irrelevant unless bought or sold
604     if (   $form->{bought}
605         || $form->{sold}
606         || $form->{onorder}
607         || $form->{ordered}
608         || $form->{rfq}
609         || $form->{quoted}) {
610       $form->{l_onhand} = "Y";
611     } else {
612       $form->{l_linetotalsellprice} = "";
613       $form->{l_linetotallastcost}  = "";
614     }
615   }
616
617   $form->{l_lastcost} = ""
618     if ($form->{searchitems} eq 'assembly' && !$form->{bom});
619
620   foreach my $item (@columns) {
621     if ($form->{"l_$item"} eq "Y") {
622       push @column_index, $item;
623
624       # add column to callback
625       $callback .= "&l_$item=Y";
626     }
627   }
628
629   if ($form->{l_subtotal} eq 'Y') {
630     $callback .= "&l_subtotal=Y";
631   }
632
633   $column_header{number} =
634     qq|<th class=listheading nowrap>| . $locale->text('number') . qq|</th>|;
635   $column_header{partnumber} =
636     qq|<th nowrap><a class=listheading href=$callback&sort=partnumber&revers=$form->{revers}&lastsort=$form->{lastsort}>|
637     . $locale->text('Part Number')
638     . qq|</a></th>|;
639   $column_header{description} =
640     qq|<th nowrap><a class=listheading href=$callback&sort=description&revers=$form->{revers}&lastsort=$form->{lastsort}>|
641     . $locale->text('Part Description')
642     . qq|</a></th>|;
643   $column_header{partsgroup} =
644       qq|<th nowrap><a class=listheading href=$callback&sort=partsgroup>|
645     . $locale->text('Group')
646     . qq|</a></th>|;
647   $column_header{bin} =
648       qq|<th><a class=listheading href=$callback&sort=bin>|
649     . $locale->text('Bin')
650     . qq|</a></th>|;
651   $column_header{priceupdate} =
652       qq|<th nowrap><a class=listheading href=$callback&sort=priceupdate>|
653     . $locale->text('Updated')
654     . qq|</a></th>|;
655   $column_header{onhand} =
656     qq|<th nowrap><a  class=listheading href=$callback&sort=onhand&revers=$form->{revers}&lastsort=$form->{lastsort}>|
657     . $locale->text('Qty')
658     . qq|</th>|;
659   $column_header{unit} =
660     qq|<th class=listheading nowrap>| . $locale->text('Unit') . qq|</th>|;
661   $column_header{listprice} =
662       qq|<th class=listheading nowrap>|
663     . $locale->text('List Price')
664     . qq|</th>|;
665   $column_header{lastcost} =
666     qq|<th class=listheading nowrap>| . $locale->text('Last Cost') . qq|</th>|;
667   $column_header{rop} =
668     qq|<th class=listheading nowrap>| . $locale->text('ROP') . qq|</th>|;
669   $column_header{weight} =
670     qq|<th class=listheading nowrap>| . $locale->text('Weight') . qq|</th>|;
671
672   $column_header{invnumber} =
673       qq|<th nowrap><a class=listheading href=$callback&sort=invnumber>|
674     . $locale->text('Invoice Number')
675     . qq|</a></th>|;
676   $column_header{ordnumber} =
677       qq|<th nowrap><a class=listheading href=$callback&sort=ordnumber>|
678     . $locale->text('Order Number')
679     . qq|</a></th>|;
680   $column_header{quonumber} =
681       qq|<th nowrap><a class=listheading href=$callback&sort=quonumber>|
682     . $locale->text('Quotation')
683     . qq|</a></th>|;
684
685   $column_header{name} =
686       qq|<th nowrap><a class=listheading href=$callback&sort=name>|
687     . $locale->text('Name')
688     . qq|</a></th>|;
689
690   $column_header{sellprice} =
691       qq|<th class=listheading nowrap>|
692     . $locale->text('Sell Price')
693     . qq|</th>|;
694   $column_header{linetotalsellprice} =
695     qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
696   $column_header{linetotallastcost} =
697     qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
698   $column_header{linetotallistprice} =
699     qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
700
701   $column_header{image} =
702     qq|<th class=listheading nowrap>| . $locale->text('Image') . qq|</a></th>|;
703   $column_header{drawing} =
704       qq|<th nowrap><a class=listheading href=$callback&sort=drawing>|
705     . $locale->text('Drawing')
706     . qq|</a></th>|;
707   $column_header{microfiche} =
708       qq|<th nowrap><a class=listheading href=$callback&sort=microfiche>|
709     . $locale->text('Microfiche')
710     . qq|</a></th>|;
711
712   $column_header{serialnumber} =
713       qq|<th nowrap><a class=listheading href=$callback&sort=serialnumber>|
714     . $locale->text('Serial Number')
715     . qq|</a></th>|;
716   $column_header{soldtotal} =
717     qq|<th nowrap><a class=listheading href=$callback&sort=soldtotal&revers=$form->{revers}&lastsort=$form->{lastsort}>|
718     . $locale->text('soldtotal')
719     . qq|</a></th>|;
720
721   $form->header;
722   my $colspan = $#column_index + 1;
723
724   print qq|
725 <body>
726
727 <table width=100%>
728   <tr>
729     <th class=listtop colspan=$colspan>$form->{title}</th>
730   </tr>
731   <tr height="5"></tr>
732
733   <tr><td colspan=$colspan>$option</td></tr>
734
735   <tr class=listheading>
736 |;
737
738   map { print "\n$column_header{$_}" } @column_index;
739
740   print qq|
741   </tr>
742   |;
743
744   # add order to callback
745   $form->{callback} = $callback .= "&sort=$form->{sort}";
746
747   # escape callback for href
748   $callback = $form->escape($callback);
749
750   if (@{ $form->{parts} }) {
751     $sameitem = $form->{parts}->[0]->{ $form->{sort} };
752   }
753
754   # insert numbers for top100
755   my $j = 0;
756   foreach my $ref (@{ $form->{parts} }) {
757     $j++;
758     $ref->{number} = $j;
759   }
760
761   # if avaible -> insert choice here
762   if (($form->{ndxs_counter}) > 0) {
763     for (my $i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
764       $partnumber  = $form->{"totop100_partnumber_$i"};
765       $description = $form->{"totop100_description_$i"};
766       $unit        = $form->{"totop100_unit_$i"};
767       $sellprice   = $form->{"totop100_sellprice_$i"};
768       $soldtotal   = $form->{"totop100_soldtotal_$i"};
769
770       $totop100 .= qq|
771 <input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
772 <input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
773 <input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
774 <input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
775 <input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
776       |;
777
778       # insert into list
779       push @{ $form->{parts} },
780         { number      => "",
781           partnumber  => "$partnumber",
782           description => "$description",
783           unit        => "$unit",
784           sellprice   => "$sellprice",
785           soldtotal   => "$soldtotal" };
786     }    #rof
787   }    #fi
788        # build data for columns
789   foreach my $ref (@{ $form->{parts} }) {
790     my $i = 0;
791
792     if ($form->{l_subtotal} eq 'Y' && !$ref->{assemblyitem}) {
793       if ($sameitem ne $ref->{ $form->{sort} }) {
794         &parts_subtotal;
795         $sameitem = $ref->{ $form->{sort} };
796       }
797     }
798
799     $ref->{exchangerate} = 1 unless $ref->{exchangerate};
800     $ref->{sellprice} *= $ref->{exchangerate};
801     $ref->{listprice} *= $ref->{exchangerate};
802     $ref->{lastcost}  *= $ref->{exchangerate};
803
804     # use this for assemblies
805     $onhand = $ref->{onhand};
806
807     $align = "left";
808     if ($ref->{assemblyitem}) {
809       $align = "right";
810       $onhand = 0 if ($form->{sold});
811     }
812
813     $ref->{description} =~ s/
814 /<br>/g;
815
816     $column_data{number} =
817         "<td align=right>"
818       . $form->format_amount(\%myconfig, $ref->{number})
819       . "</td>";
820     $column_data{partnumber} =
821       "<td align=$align>$ref->{partnumber}&nbsp;</a></td>";
822     $column_data{description} = "<td>$ref->{description}&nbsp;</td>";
823     $column_data{partsgroup}  = "<td>$ref->{partsgroup}&nbsp;</td>";
824
825     $column_data{onhand} =
826         "<td align=right>"
827       . $form->format_amount(\%myconfig, $ref->{onhand})
828       . "</td>";
829     $column_data{sellprice} =
830         "<td align=right>"
831       . $form->format_amount(\%myconfig, $ref->{sellprice})
832       . "</td>";
833     $column_data{listprice} =
834         "<td align=right>"
835       . $form->format_amount(\%myconfig, $ref->{listprice})
836       . "</td>";
837     $column_data{lastcost} =
838         "<td align=right>"
839       . $form->format_amount(\%myconfig, $ref->{lastcost})
840       . "</td>";
841
842     $column_data{linetotalsellprice} = "<td align=right>"
843       . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{sellprice}, 2)
844       . "</td>";
845     $column_data{linetotallastcost} = "<td align=right>"
846       . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{lastcost}, 2)
847       . "</td>";
848     $column_data{linetotallistprice} = "<td align=right>"
849       . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{listprice}, 2)
850       . "</td>";
851
852     if (!$ref->{assemblyitem}) {
853       $totalsellprice += $onhand * $ref->{sellprice};
854       $totallastcost  += $onhand * $ref->{lastcost};
855       $totallistprice += $onhand * $ref->{listprice};
856
857       $subtotalonhand    += $onhand;
858       $subtotalsellprice += $onhand * $ref->{sellprice};
859       $subtotallastcost  += $onhand * $ref->{lastcost};
860       $subtotallistprice += $onhand * $ref->{listprice};
861     }
862
863     $column_data{rop} =
864       "<td align=right>"
865       . $form->format_amount(\%myconfig, $ref->{rop}) . "</td>";
866     $column_data{weight} =
867         "<td align=right>"
868       . $form->format_amount(\%myconfig, $ref->{weight})
869       . "</td>";
870     $column_data{unit}        = "<td>$ref->{unit}&nbsp;</td>";
871     $column_data{bin}         = "<td>$ref->{bin}&nbsp;</td>";
872     $column_data{priceupdate} = "<td>$ref->{priceupdate}&nbsp;</td>";
873
874     $column_data{invnumber} =
875       ($ref->{module} ne 'oe')
876       ? "<td><a href=$ref->{module}.pl?action=edit&type=invoice&id=$ref->{trans_id}&login=$form->{login}&password=$form->{password}&callback=$callback>$ref->{invnumber}</a></td>"
877       : "<td>$ref->{invnumber}</td>";
878     $column_data{ordnumber} =
879       ($ref->{module} eq 'oe')
880       ? "<td><a href=$ref->{module}.pl?action=edit&type=$ref->{type}&id=$ref->{trans_id}&login=$form->{login}&password=$form->{password}&callback=$callback>$ref->{ordnumber}</a></td>"
881       : "<td>$ref->{ordnumber}</td>";
882     $column_data{quonumber} =
883       ($ref->{module} eq 'oe' && !$ref->{ordnumber})
884       ? "<td><a href=$ref->{module}.pl?action=edit&type=$ref->{type}&id=$ref->{trans_id}&login=$form->{login}&password=$form->{password}&callback=$callback>$ref->{quonumber}</a></td>"
885       : "<td>$ref->{quonumber}</td>";
886
887     $column_data{name} = "<td>$ref->{name}</td>";
888
889     $column_data{image} =
890       ($ref->{image})
891       ? "<td><a href=$ref->{image}><img src=$ref->{image} height=32 border=0></a></td>"
892       : "<td>&nbsp;</td>";
893     $column_data{drawing} =
894       ($ref->{drawing})
895       ? "<td><a href=$ref->{drawing}>$ref->{drawing}</a></td>"
896       : "<td>&nbsp;</td>";
897     $column_data{microfiche} =
898       ($ref->{microfiche})
899       ? "<td><a href=$ref->{microfiche}>$ref->{microfiche}</a></td>"
900       : "<td>&nbsp;</td>";
901
902     $column_data{serialnumber} = "<td>$ref->{serialnumber}</td>";
903
904     $column_data{soldtotal} = "<td  align=right>$ref->{soldtotal}</td>";
905
906     $i++;
907     $i %= 2;
908     print "<tr class=listrow$i>";
909
910     map { print "\n$column_data{$_}" } @column_index;
911
912     print qq|
913     </tr>
914 |;
915   }
916
917   if ($form->{l_subtotal} eq 'Y') {
918     &parts_subtotal;
919   }    #fi
920
921   if ($form->{"l_linetotal"}) {
922     map { $column_data{$_} = "<td>&nbsp;</td>" } @column_index;
923     $column_data{linetotalsellprice} =
924         "<th class=listtotal align=right>"
925       . $form->format_amount(\%myconfig, $totalsellprice, 2)
926       . "</th>";
927     $column_data{linetotallastcost} =
928         "<th class=listtotal align=right>"
929       . $form->format_amount(\%myconfig, $totallastcost, 2)
930       . "</th>";
931     $column_data{linetotallistprice} =
932         "<th class=listtotal align=right>"
933       . $form->format_amount(\%myconfig, $totallistprice, 2)
934       . "</th>";
935
936     print "<tr class=listtotal>";
937
938     map { print "\n$column_data{$_}" } @column_index;
939
940     print qq|</tr>
941     |;
942   }
943
944   print qq|
945   <tr><td colspan=$colspan><hr size=3 noshade></td></tr>
946 </table>
947
948 |;
949
950   print qq|
951
952 <br>
953
954 <form method=post action=$form->{script}>
955
956 <input type=hidden name=login value=$form->{login}>
957 <input type=hidden name=password value=$form->{password}>
958
959 <input type=hidden name=itemstatus value="$form->{itemstatus}">
960 <input type=hidden name=l_linetotal value="$form->{l_linetotal}">
961 <input type=hidden name=l_partnumber value="$form->{l_partnumber}">
962 <input type=hidden name=l_description value="$form->{l_description}">
963 <input type=hidden name=l_onhand value="$form->{l_onhand}">
964 <input type=hidden name=l_unit value="$form->{l_unit}">
965 <input type=hidden name=l_sellprice value="$form->{l_sellprice}">
966 <input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
967 <input type=hidden name=sort value="$form->{sort}">
968 <input type=hidden name=revers value="$form->{revers}">
969 <input type=hidden name=lastsort value="$form->{lastsort}">
970 <input type=hidden name=parts value="$form->{parts}">
971
972 <input type=hidden name=bom value="$form->{bom}">
973 <input type=hidden name=titel value="$form->{titel}">
974 <input type=hidden name=searchitems value="$form->{searchitems}">|;
975
976   print $totop100;
977
978   print qq|
979     <input type=hidden name=ndxs_counter value="$form->{ndxs_counter}">
980
981     <input class=submit type=submit name=action value="|
982     . $locale->text('choice') . qq|">
983
984   </form>
985
986 </body>
987 </html>
988 |;
989
990   $lxdebug->leave_sub();
991 }    # end addtop100
992
993 #
994 # Report for Wares.
995 # Warning, deep magic ahead.
996 # This function parses the requested details, sanity checks them, and converts them into a format thats usable for IC->all_parts
997 #
998 # flags coming from the form:
999 # hardcoded:
1000 #  searchitems=part revers=0 lastsort=''
1001 #
1002 # filter:
1003 # partnumber ean description partsgroup serialnumber make model drawing microfiche
1004 # transdatefrom transdateto
1005 #
1006 # radio:
1007 #  itemstatus = active | onhand | short | obsolete | orphaned
1008 #  action     = continue | top100
1009 #
1010 # checkboxes:
1011 #  bought sold onorder ordered rfq quoted
1012 #  l_partnumber l_description l_serialnumber l_unit l_listprice l_sellprice l_lastcost
1013 #  l_linetotal l_priceupdate l_bin l_rop l_weight l_image l_drawing l_microfiche
1014 #  l_partsgroup l_subtotal l_soldtotal l_deliverydate
1015 #
1016 # hiddens: 
1017 #  nextsub login password revers lastsort sort ndxs_counter
1018 #
1019 sub generate_report {
1020   $lxdebug->enter_sub();
1021
1022   my ($revers, $lastsort, $description);
1023
1024   $form->{title} = (ucfirst $form->{searchitems}) . "s";
1025   $form->{title} = $locale->text($form->{title});
1026
1027   my $revers     = $form->{revers};
1028   my $lastsort   = $form->{lastsort};
1029
1030   # sorting and direction of sorting
1031   # ToDO: change this to the simpler field+direction method
1032   if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
1033     $form->{revers}   = 0;
1034     $form->{lastsort} = "partnumber";
1035     $form->{sort}     = "partnumber";
1036   } else {
1037     if ($form->{lastsort} eq $form->{sort}) {
1038       $form->{revers} = 1 - $form->{revers};
1039     } else {
1040       $form->{revers} = 0;
1041       $form->{lastsort} = $form->{sort};
1042     }    #fi
1043   }    #fi
1044
1045   # special case if we have a serialnumber limit search
1046   # serialnumbers are only given in invoices and orders, 
1047   # so they can only pop up in bought, sold, rfq, and quoted stuff
1048   $form->{no_sn_joins} = 'Y' if (   !$form->{bought} && !$form->{sold} 
1049                                  && !$form->{rfq}    && !$form->{quoted} 
1050                                  && ($form->{l_serialnumber} || $form->{serialnumber}));
1051
1052   # special case for any checkbox of bought | sold | onorder | ordered | rfq | quoted.
1053   # if any of these are ticked the behavior changes slightly for lastcost
1054   # since all those are aggregation checks for the legder tables this is an internal switch
1055   # refered to as ledgerchecks
1056   $form->{ledgerchecks} = 'Y' if (   $form->{bought} || $form->{sold} || $form->{onorder}
1057                                   || $form->{ordered} || $form->{rfq} || $form->{quoted});
1058
1059   # if something should be activated if something else is active, enter it here
1060   my %dependencies = (
1061     onhand       => [ qw(l_onhand) ],
1062     short        => [ qw(l_onhand) ],
1063     onorder      => [ qw(l_ordnumber) ],
1064     ordered      => [ qw(l_ordnumber) ],
1065     rfq          => [ qw(l_quonumber) ],
1066     quoted       => [ qw(l_quonumber) ],
1067     bought       => [ qw(l_invnumber) ],
1068     sold         => [ qw(l_invnumber) ],
1069     ledgerchecks => [ qw(l_name) ],
1070     serialnumber => [ qw(l_serialnumber) ],
1071     no_sn_joins  => [ qw(bought sold) ],
1072   );
1073
1074   # these strings get displayed at the top of the results to indicate the user which switches were used
1075   my %optiontexts = (
1076     active        => $locale->text('Active'),
1077     obsolete      => $locale->text('Obsolete'),
1078     orphaned      => $locale->text('Orphaned'),
1079     onhand        => $locale->text('On Hand'),
1080     short         => $locale->text('Short'),
1081     onorder       => $locale->text('On Order'),
1082     ordered       => $locale->text('Ordered'),
1083     rfq           => $locale->text('RFQ'),
1084     quoted        => $locale->text('Quoted'),
1085     bought        => $locale->text('Bought'),
1086     sold          => $locale->text('Sold'),
1087     transdatefrom => $locale->text('From')       . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1),
1088     transdateto   => $locale->text('To (time)')  . " " . $locale->date(\%myconfig, $form->{transdateto}, 1),
1089     partnumber    => $locale->text('Part Number')      . ": '$form->{partnumber}'",
1090     partsgroup    => $locale->text('Group')            . ": '$form->{partsgroup}'",
1091     serialnumber  => $locale->text('Serial Number')    . ": '$form->{serialnumber}'",
1092     description   => $locale->text('Part Description') . ": '$form->{description}'",
1093     make          => $locale->text('Make')             . ": '$form->{make}'",
1094     model         => $locale->text('Model')            . ": '$form->{model}'",
1095     drawing       => $locale->text('Drawing')          . ": '$form->{drawing}'",
1096     microfiche    => $locale->text('Microfiche')       . ": '$form->{microfiche}'",
1097     l_soldtotal   => $locale->text('soldtotal'),
1098   );
1099
1100   my @itemstatus_keys = qw(active obsolete orphaned onhand short);
1101   my @callback_keys   = qw(onorder ordered rfq quoted bought sold partnumber partsgroup serialnumber description make model
1102                            drawing microfiche l_soldtotal l_deliverydate transdatefrom transdateto ean);
1103
1104   # calculate dependencies
1105   for (@itemstatus_keys, @callback_keys) {
1106     next if ($form->{itemstatus} ne $_ && !$form->{$_});
1107     map { $form->{$_} = 'Y' } @{ $dependencies{$_} } if $dependencies{$_};
1108   }
1109
1110   # generate callback and optionstrings
1111   my @options;
1112   for my  $key (@itemstatus_keys, @callback_keys) { 
1113     next if ($form->{itemstatus} ne $key && !$form->{$key});
1114     push @options, $optiontexts{$key};
1115   }
1116
1117   # special case for lastcost
1118   $form->{l_lastcost} = "" if $form->{ledgerchecks};
1119
1120   if ($form->{description}) {
1121     $description = $form->{description};
1122     $description =~ s/\n/<br>/g;
1123   }
1124
1125   if ($form->{l_linetotal}) {
1126     $form->{l_onhand} = "Y";
1127     $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
1128     if ($form->{l_lastcost}) {
1129       $form->{l_linetotallastcost} = "Y";
1130       if (($form->{searchitems} eq 'assembly') && !$form->{bom}) {
1131         $form->{l_linetotallastcost} = "";
1132       }
1133     }
1134     $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
1135   }
1136
1137   if ($form->{searchitems} eq 'service') {
1138
1139     # remove bin, weight and rop from list
1140     map { $form->{"l_$_"} = "" } qw(bin weight rop);
1141
1142     $form->{l_onhand} = "";
1143
1144     # qty is irrelevant unless bought or sold
1145     if (   $form->{bought}
1146         || $form->{sold}
1147         || $form->{onorder}
1148         || $form->{ordered}
1149         || $form->{rfq}
1150         || $form->{quoted}) {
1151       $form->{l_onhand} = "Y";
1152     } else {
1153       $form->{l_linetotalsellprice} = "";
1154       $form->{l_linetotallastcost}  = "";
1155     }
1156   }
1157
1158   $form->{l_lastcost} = "" if ($form->{searchitems} eq 'assembly' && !$form->{bom});
1159
1160   IC->all_parts(\%myconfig, \%$form);
1161
1162   my @columns =
1163     qw(partnumber description partsgroup bin onhand rop unit listprice linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
1164        priceupdate weight image drawing microfiche invnumber ordnumber quonumber name serialnumber soldtotal deliverydate);
1165
1166   my %column_defs = (
1167     'bin'                => { 'text' => $locale->text('Bin'), },
1168     'deliverydate'       => { 'text' => $locale->text('deliverydate'), },
1169     'description'        => { 'text' => $locale->text('Part Description'), },
1170     'drawing'            => { 'text' => $locale->text('Drawing'), },
1171     'image'              => { 'text' => $locale->text('Image'), },
1172     'invnumber'          => { 'text' => $locale->text('Invoice Number'), },
1173     'lastcost'           => { 'text' => $locale->text('Last Cost'), },
1174     'linetotallastcost'  => { 'text' => $locale->text('Extended'), },
1175     'linetotallistprice' => { 'text' => $locale->text('Extended'), },
1176     'linetotalsellprice' => { 'text' => $locale->text('Extended'), },
1177     'listprice'          => { 'text' => $locale->text('List Price'), },
1178     'microfiche'         => { 'text' => $locale->text('Microfiche'), },
1179     'name'               => { 'text' => $locale->text('Name'), },
1180     'onhand'             => { 'text' => $locale->text('Qty'), },
1181     'ordnumber'          => { 'text' => $locale->text('Order Number'), },
1182     'partnumber'         => { 'text' => $locale->text('Part Number'), },
1183     'partsgroup'         => { 'text' => $locale->text('Group'), },
1184     'priceupdate'        => { 'text' => $locale->text('Updated'), },
1185     'quonumber'          => { 'text' => $locale->text('Quotation'), },
1186     'rop'                => { 'text' => $locale->text('ROP'), },
1187     'sellprice'          => { 'text' => $locale->text('Sell Price'), },
1188     'serialnumber'       => { 'text' => $locale->text('Serial Number'), },
1189     'soldtotal'          => { 'text' => $locale->text('soldtotal'), },
1190     'unit'               => { 'text' => $locale->text('Unit'), },
1191     'weight'             => { 'text' => $locale->text('Weight'), },
1192   );
1193
1194   map { $column_defs{$_}->{visible} = $form->{"l_$_"} ? 1 : 0 } @columns;
1195   map { $column_defs{$_}->{align}   = 'right' } qw(onhand sellprice listprice lastcost linetotalsellprice linetotallastcost linetotallistprice rop weight soldtotal);
1196
1197   my @hidden_variables = (qw(l_subtotal l_linetotal searchitems itemstatus bom), @itemstatus_keys, @callback_keys, map { "l_$_" } @columns);
1198   my $callback         = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
1199
1200   my @sort_full        = qw(partnumber description onhand soldtotal deliverydate);
1201   my @sort_no_revers   = qw(partsgroup bin priceupdate invnumber ordnumber quonumber name image drawing serialnumber);
1202
1203   foreach my $col (@sort_full) {
1204     $column_defs{$col}->{link} = join '&', $callback, "sort=$col", map { "$_=" . E($form->{$_}) } qw(revers lastsort);
1205   }
1206   map { $column_defs{$_}->{link} = "${callback}&sort=$_" } @sort_no_revers;
1207
1208   # add order to callback
1209   $form->{callback} = join '&', ($callback, map { "${_}=" . E($form->{$_}) } qw(sort revers));
1210
1211   my $report = SL::ReportGenerator->new(\%myconfig, $form);
1212
1213   my %attachment_basenames = (
1214     'part'     => $locale->text('part_list'),
1215     'service'  => $locale->text('service_list'),
1216     'assembly' => $locale->text('assembly_list'),
1217   );
1218
1219   $report->set_options('top_info_text'         => $locale->text('Options') . ': ' . join(', ', grep $_, @options),
1220                        'raw_bottom_info_text'  => $form->parse_html_template('ic/generate_report_bottom'),
1221                        'output_format'         => 'HTML',
1222                        'title'                 => $form->{title},
1223                        'attachment_basename'   => $attachment_basenames{$form->{searchitems}} . strftime('_%Y%m%d', localtime time),
1224   );
1225   $report->set_options_from_form();
1226
1227   $report->set_columns(%column_defs);
1228   $report->set_column_order(@columns);
1229
1230   $report->set_export_options('generate_report', @hidden_variables, qw(sort revers));
1231
1232   $report->set_sort_indicator($form->{sort}, $form->{revers} ? 0 : 1);
1233
1234   my @subtotal_columns = qw(sellprice listprice lastcost);
1235   my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
1236   my %totals    = map { $_ => 0 } @subtotal_columns;
1237   my $idx       = 0;
1238   my $same_item = $form->{parts}[0]{ $form->{sort} } if (scalar @{ $form->{parts} });
1239
1240   # postprocess parts
1241   foreach my $ref (@{ $form->{parts} }) {
1242
1243     # fresh row, for inserting later
1244     my $row = { map { $_ => { 'data' => $ref->{$_} } } @columns };
1245
1246     $ref->{exchangerate} ||= 1;
1247     $ref->{price_factor} ||= 1;
1248     $ref->{sellprice}     *= $ref->{exchangerate} / $ref->{price_factor};
1249     $ref->{listprice}     *= $ref->{exchangerate} / $ref->{price_factor};
1250     $ref->{lastcost}      *= $ref->{exchangerate} / $ref->{price_factor};
1251
1252     # use this for assemblies
1253     my $onhand = $ref->{onhand};
1254
1255     if ($ref->{assemblyitem}) {
1256       $row->{partnumber}{align}   = 'right';
1257       $row->{onhand}{data}        = 0;
1258       $onhand                     = 0 if ($form->{sold});
1259     }
1260
1261     my $edit_link               = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
1262     $row->{partnumber}->{link}  = $edit_link;
1263     $row->{description}->{link} = $edit_link;
1264
1265     foreach (qw(sellprice listprice lastcost)) {
1266       $row->{$_}{data}            = $form->format_amount(\%myconfig, $ref->{$_}, -2);
1267       $row->{"linetotal$_"}{data} = $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{$_}, 2);
1268     }
1269
1270     map { $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}); } qw(onhand rop weight soldtotal);
1271
1272     if (!$ref->{assemblyitem}) {
1273       foreach my $col (@subtotal_columns) {
1274         $totals{$col}    += $onhand * $ref->{$col};
1275         $subtotals{$col} += $onhand * $ref->{$col};
1276       }
1277
1278       $subtotals{onhand} += $onhand;
1279     }
1280
1281     # set module stuff
1282     if ($ref->{module} eq 'oe') {
1283       my $edit_oe_link = build_std_url("script=oe.pl", 'action=edit', 'type=' . E($ref->{type}), 'id=' . E($ref->{trans_id}), 'callback');
1284       $row->{ordnumber}{link} = $edit_oe_link;
1285       $row->{quonumber}{link} = $edit_oe_link if (!$ref->{ordnumber});
1286
1287     } else {
1288       $row->{invnumber}{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'type=invoice', 'id=' . E($ref->{trans_id}), 'callback');
1289     }
1290
1291     # set properties of images
1292     if ($ref->{image} && (lc $report->{options}->{output_format} eq 'html')) {
1293       $row->{image}{data}     = '';
1294       $row->{image}{raw_data} = '<a href="' . H($ref->{image}) . '"><img src="' . H($ref->{image}) . '" height="32" border="0"></a>';
1295     }
1296     map { $row->{$_}{link} = $ref->{$_} } qw(drawing microfiche);
1297
1298     $report->add_data($row);
1299
1300     my $next_ref = $form->{parts}[$idx + 1];
1301
1302     # insert subtotal rows
1303     if (($form->{l_subtotal} eq 'Y') &&
1304         (!$next_ref ||
1305          (!$next_ref->{assemblyitem} && ($same_item ne $next_ref->{ $form->{sort} })))) {
1306       my $row = { map { $_ => { 'class' => 'listsubtotal', } } @columns };
1307
1308       if (($form->{searchitems} ne 'assembly') || !$form->{bom}) {
1309         $row->{onhand}->{data} = $form->format_amount(\%myconfig, $subtotals{onhand});
1310       }
1311
1312       map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $subtotals{$_}, 2) } @subtotal_columns;
1313       map { $subtotals{$_} = 0 } ('onhand', @subtotal_columns);
1314
1315       $report->add_data($row);
1316
1317       $same_item = $next_ref->{ $form->{sort} };
1318     }
1319
1320     $idx++;
1321   }
1322
1323   if ($form->{"l_linetotal"}) {
1324     my $row = { map { $_ => { 'class' => 'listtotal', } } @columns };
1325
1326     map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $totals{$_}, 2) } @subtotal_columns;
1327
1328     $report->add_separator();
1329     $report->add_data($row);
1330   }
1331
1332   $report->generate_with_headers();
1333
1334   $lxdebug->leave_sub();
1335 }    #end generate_report
1336
1337 sub parts_subtotal {
1338   $lxdebug->enter_sub();
1339   
1340   # imports
1341   our (%column_data, @column_index);
1342   our ($subtotalonhand, $totalsellprice, $totallastcost, $totallistprice, $subtotalsellprice, $subtotallastcost, $subtotallistprice);
1343
1344   map { $column_data{$_} = "<td>&nbsp;</td>" } @column_index;
1345   $subtotalonhand = 0 if ($form->{searchitems} eq 'assembly' && $form->{bom});
1346
1347   $column_data{onhand} =
1348       "<th class=listsubtotal align=right>"
1349     . $form->format_amount(\%myconfig, $subtotalonhand)
1350     . "</th>";
1351
1352   $column_data{linetotalsellprice} =
1353       "<th class=listsubtotal align=right>"
1354     . $form->format_amount(\%myconfig, $subtotalsellprice, 2)
1355     . "</th>";
1356   $column_data{linetotallistprice} =
1357       "<th class=listsubtotal align=right>"
1358     . $form->format_amount(\%myconfig, $subtotallistprice, 2)
1359     . "</th>";
1360   $column_data{linetotallastcost} =
1361       "<th class=listsubtotal align=right>"
1362     . $form->format_amount(\%myconfig, $subtotallastcost, 2)
1363     . "</th>";
1364
1365   $subtotalonhand    = 0;
1366   $subtotalsellprice = 0;
1367   $subtotallistprice = 0;
1368   $subtotallastcost  = 0;
1369
1370   print "<tr class=listsubtotal>";
1371
1372   map { print "\n$column_data{$_}" } @column_index;
1373
1374   print qq|
1375   </tr>
1376 |;
1377
1378   $lxdebug->leave_sub();
1379 }
1380
1381 sub edit {
1382   $lxdebug->enter_sub();
1383   # show history button
1384   $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
1385   #/show hhistory button
1386   IC->get_part(\%myconfig, \%$form);
1387
1388   $form->{"original_partnumber"} = $form->{"partnumber"};
1389
1390   $form->{title} = $locale->text('Edit ' . ucfirst $form->{item});
1391
1392   &link_part;
1393   &display_form;
1394
1395   $lxdebug->leave_sub();
1396 }
1397
1398 sub link_part {
1399   $lxdebug->enter_sub();
1400
1401   IC->create_links("IC", \%myconfig, \%$form);
1402
1403   # currencies
1404   map({ $form->{selectcurrency} .= "<option>$_\n" }
1405       split(/:/, $form->{currencies}));
1406
1407   # parts and assemblies have the same links
1408   my $item = $form->{item};
1409   if ($form->{item} eq 'assembly') {
1410     $item = 'part';
1411   }
1412
1413   # build the popup menus
1414   $form->{taxaccounts} = "";
1415   foreach my $key (keys %{ $form->{IC_links} }) {
1416     foreach my $ref (@{ $form->{IC_links}{$key} }) {
1417
1418       # if this is a tax field
1419       if ($key =~ /IC_tax/) {
1420         if ($key =~ /\Q$item\E/) {
1421           $form->{taxaccounts} .= "$ref->{accno} ";
1422           $form->{"IC_tax_$ref->{accno}_description"} =
1423             "$ref->{accno}--$ref->{description}";
1424
1425           if ($form->{id}) {
1426             if ($form->{amount}{ $ref->{accno} }) {
1427               $form->{"IC_tax_$ref->{accno}"} = "checked";
1428             }
1429           } else {
1430             $form->{"IC_tax_$ref->{accno}"} = "checked";
1431           }
1432         }
1433       } else {
1434
1435         $form->{"select$key"} .=
1436           "<option $ref->{selected}>$ref->{accno}--$ref->{description}\n";
1437         if ($form->{amount}{$key} eq $ref->{accno}) {
1438           $form->{$key} = "$ref->{accno}--$ref->{description}";
1439         }
1440
1441       }
1442     }
1443   }
1444   chop $form->{taxaccounts};
1445
1446   if (($form->{item} eq "part") || ($form->{item} eq "assembly")) {
1447     $form->{selectIC_income}  = $form->{selectIC_sale};
1448     $form->{selectIC_expense} = $form->{selectIC_cogs};
1449     $form->{IC_income}        = $form->{IC_sale};
1450     $form->{IC_expense}       = $form->{IC_cogs};
1451   }
1452
1453   delete $form->{IC_links};
1454   delete $form->{amount};
1455
1456   $form->get_partsgroup(\%myconfig, { all => 1 });
1457
1458   $form->{partsgroup} = "$form->{partsgroup}--$form->{partsgroup_id}";
1459
1460   if (@{ $form->{all_partsgroup} }) {
1461     $form->{selectpartsgroup} = qq|<option>\n|;
1462     map {
1463       $form->{selectpartsgroup} .=
1464         qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n|
1465     } @{ $form->{all_partsgroup} };
1466   }
1467
1468   if ($form->{item} eq 'assembly') {
1469
1470     foreach my $i (1 .. $form->{assembly_rows}) {
1471       if ($form->{"partsgroup_id_$i"}) {
1472         $form->{"partsgroup_$i"} =
1473           qq|$form->{"partsgroup_$i"}--$form->{"partsgroup_id_$i"}|;
1474       }
1475     }
1476     $form->get_partsgroup(\%myconfig);
1477
1478     if (@{ $form->{all_partsgroup} }) {
1479       $form->{selectassemblypartsgroup} = qq|<option>\n|;
1480
1481       map {
1482         $form->{selectassemblypartsgroup} .=
1483           qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n|
1484       } @{ $form->{all_partsgroup} };
1485     }
1486   }
1487   $lxdebug->leave_sub();
1488 }
1489
1490 sub form_header {
1491   $lxdebug->enter_sub();
1492
1493   my ($payment, $rows, $notes, $description, $ean, $buchungsgruppe, $partsgroup, $group, $tax, $lastcost, $eur, $linkaccounts, $weight, $n, $rop, $bin, $vegv);
1494   my ($notdiscountableok, $notdiscountable);
1495   my ($formula, $formula_label, $imagelinks, $obsolete, $shopok, $shop);
1496
1497   $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
1498
1499   map({ $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, -2) }
1500       qw(sellprice listprice lastcost gv));
1501
1502   map { $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}) }
1503     qw(weight rop stock);
1504
1505   foreach my $item (qw(partnumber description unit notes)) {
1506     $form->{$item} =~ s/\"/&quot;/g;
1507   }
1508
1509   $payment = qq|<option value=""></option>|;
1510   foreach my $item (@{ $form->{payment_terms} }) {
1511     if ($form->{payment_id} eq $item->{id}) {
1512       $payment .= qq|<option value="$item->{id}" selected>$item->{description}</option>|;
1513     } else {
1514       $payment .= qq|<option value="$item->{id}">$item->{description}</option>|;
1515     }
1516   }
1517
1518
1519   if (($rows = $form->numtextrows($form->{notes}, 40)) < 2) {
1520     $rows = 4;
1521   }
1522
1523   $notes =
1524     qq|<textarea name=notes rows=$rows cols=45 wrap=soft>$form->{notes}</textarea>|;
1525   if (($rows = $form->numtextrows($form->{description}, 40)) > 1) {
1526     $description =
1527       qq|<textarea name="description" rows=$rows cols=40 wrap=soft>$form->{description}</textarea>|;
1528   } else {
1529     $description =
1530       qq|<input name=description size=40 value="$form->{description}">|;
1531   }
1532
1533   $ean =  qq|<input name=ean size=40 value="$form->{ean}">|;
1534
1535   foreach my $item (split / /, $form->{taxaccounts}) {
1536     $form->{"IC_tax_$item"} = ($form->{"IC_tax_$item"}) ? "checked" : "";
1537   }
1538
1539   IC->retrieve_buchungsgruppen(\%myconfig, $form);
1540   if (@{ $form->{BUCHUNGSGRUPPEN} }) {
1541     foreach my $item (@{ $form->{BUCHUNGSGRUPPEN} }) {
1542       if ($item->{id} == $form->{buchungsgruppen_id}) {
1543         $form->{selectbuchungsgruppe} .=
1544           "<option value=$item->{id} selected>$item->{description}\n";
1545       } elsif (($form->{id} && $form->{orphaned}) || (!$form->{id})) {
1546         $form->{selectbuchungsgruppe} .=
1547           "<option value=$item->{id}>$item->{description}\n";
1548       }
1549
1550     }
1551   }
1552
1553   $buchungsgruppe = qq|
1554               <tr>
1555                 <th align=right>| . $locale->text('Buchungsgruppe') . qq|</th>
1556                 <td><select name=buchungsgruppen_id>$form->{selectbuchungsgruppe}</select></td>
1557               </tr>|;
1558
1559
1560   # set option
1561   foreach my $item (qw(IC IC_income IC_expense)) {
1562     if ($form->{$item}) {
1563       if ($form->{id} && $form->{orphaned}) {
1564         $form->{"select$item"} =~ s/ selected//;
1565         $form->{"select$item"} =~
1566           s/option>\Q$form->{$item}\E/option selected>$form->{$item}/;
1567       } else {
1568         $form->{"select$item"} = qq|<option selected>$form->{$item}|;
1569       }
1570     }
1571   }
1572
1573   if ($form->{selectpartsgroup}) {
1574     $form->{selectpartsgroup} = $form->unescape($form->{selectpartsgroup});
1575     $partsgroup =
1576       qq|<input type=hidden name=selectpartsgroup value="|
1577       . $form->escape($form->{selectpartsgroup}, 1) . qq|">|;
1578     $form->{selectpartsgroup} =~
1579       s/(<option value="\Q$form->{partsgroup}\E")/$1 selected/;
1580
1581     $partsgroup .=
1582       qq|<select name=partsgroup>$form->{selectpartsgroup}</select>|;
1583     $group = $locale->text('Group');
1584   }
1585
1586   # tax fields
1587   foreach my $item (split / /, $form->{taxaccounts}) {
1588     $tax .= qq|
1589       <input class=checkbox type=checkbox name="IC_tax_$item" value=1 $form->{"IC_tax_$item"}>&nbsp;<b>$form->{"IC_tax_${item}_description"}</b>
1590       <br><input type=hidden name=IC_tax_${item}_description value="$form->{"IC_tax_${item}_description"}">
1591 |;
1592   }
1593
1594   $form->{obsolete} = "checked" if $form->{obsolete};
1595
1596   $lastcost = qq|
1597               <tr>
1598                 <th align="right" nowrap="true">|
1599     . $locale->text('Last Cost') . qq|</th>
1600                 <td><input name=lastcost size=11 value=$form->{lastcost}></td>
1601               </tr>
1602 |;
1603   if (!$eur) {
1604     $linkaccounts = qq|
1605                <tr>
1606                 <th align=right>| . $locale->text('Inventory') . qq|</th>
1607                 <td><select name=IC>$form->{selectIC}</select></td>
1608                 <input name=selectIC type=hidden value="$form->{selectIC}">
1609               </tr>|;
1610   }
1611
1612   if ($form->{item} eq "part") {
1613
1614     $linkaccounts .= qq|
1615               <tr>
1616                 <th align=right>| . $locale->text('Revenue') . qq|</th>
1617                 <td><select name=IC_income>$form->{selectIC_income}</select></td>
1618                 <input name=selectIC_income type=hidden value="$form->{selectIC_income}">
1619               </tr>
1620               <tr>
1621                 <th align=right>| . $locale->text('Expense') . qq|</th>
1622                 <td><select name=IC_expense>$form->{selectIC_expense}</select></td>
1623                 <input name=selectIC_expense type=hidden value="$form->{selectIC_expense}">
1624               </tr>
1625 |;
1626
1627     $weight = qq|
1628               <tr>
1629                 <th align="right" nowrap="true">| . $locale->text('Weight') . qq|</th>
1630                 <td>
1631                   <table>
1632                     <tr>
1633                       <td>
1634                         <input name=weight size=10 value=$form->{weight}>
1635                       </td>
1636                     </tr>
1637                   </table>
1638                 </td>
1639               </tr>
1640 |;
1641
1642   }
1643
1644   if ($form->{item} eq "assembly") {
1645
1646     $lastcost = "";
1647
1648     $linkaccounts = qq|
1649               <tr>
1650                 <th align=right>| . $locale->text('Revenue') . qq|</th>
1651                 <td><select name=IC_income>$form->{selectIC_income}</select></td>
1652                 <input name=selectIC_income type=hidden value="$form->{selectIC_income}">
1653               </tr>
1654 |;
1655
1656     $weight = qq|
1657               <tr>
1658                 <th align="right" nowrap="true">| . $locale->text('Weight') . qq|</th>
1659                 <td>
1660                   <table>
1661                     <tr>
1662                       <td>
1663                         &nbsp;$form->{weight}
1664                         <input type=hidden name=weight value=$form->{weight}>
1665                       </td>
1666                     </tr>
1667                   </table>
1668                 </td>
1669               </tr>
1670 |;
1671
1672   }
1673
1674   if ($form->{item} eq "service") {
1675
1676     $linkaccounts = qq|
1677               <tr>
1678                 <th align=right>| . $locale->text('Revenue') . qq|</th>
1679                 <td><select name=IC_income>$form->{selectIC_income}</select></td>
1680                 <input name=selectIC_income type=hidden value="$form->{selectIC_income}">
1681               </tr>
1682               <tr>
1683                 <th align=right>| . $locale->text('Expense') . qq|</th>
1684                 <td><select name=IC_expense>$form->{selectIC_expense}</select></td>
1685                 <input name=selectIC_expense type=hidden value="$form->{selectIC_expense}">
1686               </tr>
1687 |;
1688
1689   }
1690   $linkaccounts = qq|<input type=hidden name=IC_income value="$form->{IC_income_default}">|;
1691
1692   if ($form->{IC_cogs_default}) {
1693     $form->{IC_expense_default} = $form->{IC_cogs_default};
1694   }
1695
1696   if (($form->{item} eq "service") || ($form->{item} eq "part")) {
1697     $linkaccounts .= qq|<input type=hidden name=IC_expense value="$form->{IC_expense_default}">|;
1698   }
1699   if ($form->{item} eq "part") {
1700     $linkaccounts .= qq|<input type=hidden name=IC value="$form->{IC_default}">|;
1701   }
1702
1703   if ($form->{item} ne 'service') {
1704     $n   = ($form->{onhand} > 0) ? "1" : "0";
1705     $rop = qq|
1706               <tr>
1707                 <th align="right" nowrap>| . $locale->text('On Hand') . qq|</th>
1708                 <th align=left nowrap class="plus$n">&nbsp;|
1709       . $form->format_amount(\%myconfig, $form->{onhand}) . qq|</th>
1710               </tr>
1711 |;
1712
1713     if ($form->{item} eq 'assembly') {
1714       $rop .= qq|
1715               <tr>
1716                 <th align="right" nowrap>| . $locale->text('Stock') . qq|</th>
1717                 <td><input name=stock size=10 value=$form->{stock}></td>
1718               </tr>
1719 |;
1720     }
1721
1722     $rop .= qq|
1723               <tr>
1724                 <th align="right" nowrap="true">| . $locale->text('ROP') . qq|</th>
1725                 <td><input name=rop size=10 value=$form->{rop}></td>
1726               </tr>
1727 |;
1728
1729     $bin = qq|
1730               <tr>
1731                 <th align="right" nowrap="true">| . $locale->text('Bin') . qq|</th>
1732                 <td><input name=bin size=10 value=$form->{bin}></td>
1733               </tr>
1734 |;
1735     $vegv = qq|
1736               <tr>
1737                 <th align="right" nowrap="true">|
1738       . $locale->text('Verrechnungseinheit') . qq|</th>
1739                 <td><input name=ve size=10 value=$form->{ve}></td>
1740               </tr>
1741               <tr>
1742                 <th align="right" nowrap="true">|
1743       . $locale->text('Business Volume') . qq|</th>
1744                 <td><input name=gv size=10 value=$form->{gv}></td>
1745               </tr>
1746 |;
1747     $notdiscountableok = ($form->{not_discountable}) == 1 ? "checked" : "";
1748     $notdiscountable .= qq|
1749               <tr>
1750                 <th align=right nowrap>|
1751     . $locale->text('Not Discountable') . qq|</th>
1752                 <td><input class=checkbox type=checkbox name=not_discountable value=1 $notdiscountableok></td>
1753              </tr>
1754 |;
1755
1756     $formula =
1757       qq|<ilayer><layer  onmouseover="this.T_STICKY=true;this.T_STATIC=true;return escape('| . $locale->text('The formula needs the following syntax:<br>For regular article:<br>Variablename= Variable Unit;<br>Variablename2= Variable2 Unit2;<br>...<br>###<br>Variable + ( Variable2 / Variable )<br><b>Please be beware of the spaces in the formula</b><br>') . qq|')"><textarea name=formel rows=4 cols=30 wrap=soft>$form->{formel}</textarea></layer><ilayer>|;
1758
1759     $formula_label = $locale->text('Formula');
1760
1761     $imagelinks = qq|
1762   <tr>
1763     <td>
1764       <table width=100%>
1765         <tr>
1766           <th align=right nowrap>| . $locale->text('Image') . qq|</th>
1767           <td><input name=image size=40 value="$form->{image}"></td>
1768           <th align=right nowrap>| . $locale->text('Microfiche') . qq|</th>
1769           <td><input name=microfiche size=20 value="$form->{microfiche}"></td>
1770         </tr>
1771         <tr>
1772           <th align=right nowrap>| . $locale->text('Drawing') . qq|</th>
1773           <td><input name=drawing size=40 value="$form->{drawing}"></td>
1774         </tr>
1775       </table>
1776     </td>
1777   </tr>
1778 |;
1779
1780   }
1781
1782   if ($form->{id}) {
1783     $obsolete = qq|
1784               <tr>
1785                 <th align="right" nowrap="true">| . $locale->text('Obsolete') . qq|</th>
1786                 <td><input name=obsolete type=checkbox class=checkbox value=1 $form->{obsolete}></td>
1787               </tr>
1788 |;
1789   }
1790   $shopok = $form->{shop} == 1 ? "checked" : "";
1791   $shop .= qq|
1792               <tr>
1793                 <th align=right nowrap>|
1794     . $locale->text('Shopartikel') . qq|</th>
1795                 <td><input class=checkbox type=checkbox name=shop value=1 $shopok></td>
1796              </tr>
1797 |;
1798
1799
1800   # type=submit $locale->text('Add Part')
1801   # type=submit $locale->text('Add Service')
1802   # type=submit $locale->text('Add Assembly')
1803
1804   # type=submit $locale->text('Edit Part')
1805   # type=submit $locale->text('Edit Service')
1806   # type=submit $locale->text('Edit Assembly')
1807   # use JavaScript Calendar or not
1808   my ($jsscript, $button1);
1809   $form->{jsscript} = 1;
1810   $jsscript = "";
1811   if ($form->{jsscript}) {
1812
1813     # with JavaScript Calendar
1814     $button1 = qq|
1815        <td width="13"><input name=priceupdate id=priceupdate size=11  title="$myconfig{dateformat}" value="$form->{priceupdate}"></td>
1816        <td width="4" align="left"><input type=button name=priceupdate id="trigger1" value=|
1817       . $locale->text('button') . qq|></td>
1818       |;
1819
1820     #write Trigger
1821     $jsscript =
1822       Form->write_trigger(\%myconfig, "1", "priceupdate", "BL", "trigger1");
1823   } else {
1824
1825     # without JavaScript Calendar
1826     $button1 = qq|
1827                               <td><input name=transdatefrom id=transdatefrom size=11 title="$myconfig{dateformat}"></td>|;
1828   }
1829
1830   my $unit_select = '<input type="hidden" name="unit_changeable" value="' . $form->{"unit_changeable"} . '">';
1831   if (!$form->{"unit_changeable"}) {
1832     $unit_select .= '<input type="hidden" name="unit" value="' . $form->{"unit"} . '">' . $form->{"unit"};
1833   } else {
1834     my $units = AM->retrieve_units(\%myconfig, $form, $form->{"item"} eq "service" ? "service" : "dimension");
1835     $unit_select .= AM->unit_select_html($units, "unit", $form->{"unit"});
1836   }
1837
1838   my $price_factor;
1839   if (0 < scalar @{ $form->{ALL_PRICE_FACTORS} }) {
1840     my @values = ('', map { $_->{id}                      } @{ $form->{ALL_PRICE_FACTORS} });
1841     my %labels =      map { $_->{id} => $_->{description} } @{ $form->{ALL_PRICE_FACTORS} };
1842
1843     $price_factor =
1844         qq|<tr><th align="right">|
1845       . $locale->text('Price Factor')
1846       . qq|</th><td>|
1847       . NTI($cgi->popup_menu('-name'    => 'price_factor_id',
1848                              '-default' => $form->{price_factor_id},
1849                              '-values'  => \@values,
1850                              '-labels'  => \%labels))
1851       . qq|</td></tr>|;
1852   }
1853
1854   $form->{fokus} = "ic.partnumber";
1855   $form->header;
1856
1857   print qq|
1858   <body onLoad="fokus()">
1859  <script type="text/javascript" src="js/common.js"></script>
1860  <script type="text/javascript" src="js/parts_language_selection.js"></script>
1861
1862 <form method=post name="ic" action=$form->{script}>
1863
1864 <input name=id type=hidden value=$form->{id}>
1865 <input name=item type=hidden value=$form->{item}>
1866 <input name=title type=hidden value="$form->{title}">
1867 <input name=makemodel type=hidden value="$form->{makemodel}">
1868 <input name=alternate type=hidden value="$form->{alternate}">
1869 <input name=onhand type=hidden value=$form->{onhand}>
1870 <input name=orphaned type=hidden value=$form->{orphaned}>
1871 <input name=taxaccounts type=hidden value="$form->{taxaccounts}">
1872 <input name=rowcount type=hidden value=$form->{rowcount}>
1873 <input name=eur type=hidden value=$eur>
1874 <input name=language_values type=hidden value="$form->{language_values}">
1875 <input name="original_partnumber" type="hidden" value="| . $form->quote($form->{"original_partnumber"}) . qq|">
1876
1877 <table width="100%">
1878   <tr>
1879     <th class=listtop>$form->{title}</th>
1880   </tr>
1881   <tr height="5"></tr>
1882   <tr>
1883     <td>
1884       <table width="100%">
1885         <tr valign=top>
1886           <th align=left>| . $locale->text('Part Number') . qq|</th>
1887           <th align=left>| . $locale->text('Part Description') . qq|</th>
1888           <th align=left>$group</th>
1889         </tr>
1890         <tr valign=top>
1891           <td><input name=partnumber value="$form->{partnumber}" size=20></td>
1892           <td>$description</td>
1893           <td>$partsgroup</td>
1894           <input type=hidden name=oldpartsgroup value="$form->{oldpartsgroup}">
1895         </tr>
1896       </table>
1897     </td>
1898   </tr>
1899   <tr>
1900     <td>
1901       <table width="100%" height="100%">
1902         <tr valign=top>
1903           <td width=70%>
1904             <table width="100%" height="100%">
1905               <tr>
1906                 <td colspan=2>
1907                   <table>
1908                     $buchungsgruppe
1909                     $linkaccounts
1910                   </table>
1911                 </td>
1912               </tr>
1913               <tr>
1914                 <th align="left">| . $locale->text('Notes') . qq|</th>
1915                 <th align="left">$formula_label</th>
1916               </tr>
1917               <tr>
1918                 <td>
1919                   $notes
1920                 </td>
1921                 <td>
1922                   $formula
1923                 </td>
1924               </tr>
1925               <tr>
1926                 <th align="left"></th>
1927                 <th align="left">| . $locale->text('EAN-Code') . qq|</th>
1928               </tr>
1929               <tr>
1930                 <td>
1931                   <button type="button" onclick="parts_language_selection_window('language_values')">| . $locale->text('Set Language Values') . qq|</button>
1932                 </td>
1933                 <td>
1934                   $ean  
1935                 </td>
1936               </tr>
1937               <tr>
1938               <td colspan=2>
1939                 <table>
1940                 <tr>
1941                <th align=right>| . $locale->text('Payment Terms') . qq|</th>
1942                  <td><select name=payment_id>$payment</select></td>
1943                 </tr>
1944                </table>
1945               </td>
1946               </tr>
1947             </table>
1948           </td>
1949           <td width="30%">
1950             <table width="100%">
1951               <tr>
1952                 <th align="right" nowrap="true">|
1953     . $locale->text('Updated') . qq|</th>
1954                 $button1
1955               </tr>
1956               <tr>
1957                 <th align="right" nowrap="true">| . $locale->text('List Price') . qq|</th>
1958                 <td><input name=listprice size=11 value=$form->{listprice}></td>
1959               </tr>
1960               <tr>
1961                 <th align="right" nowrap="true">| . $locale->text('Sell Price') . qq|</th>
1962                 <td><input name=sellprice size=11 value=$form->{sellprice}></td>
1963               </tr>
1964               $lastcost
1965               $price_factor
1966               <tr>
1967                 <th align="right" nowrap="true">| . $locale->text('Unit') . qq|</th>
1968                 <td>$unit_select</td>
1969               </tr>
1970               $weight
1971               $rop
1972               $bin
1973               $notdiscountable
1974               $vegv
1975               $shop
1976               $obsolete
1977             </table>
1978           </td>
1979         </tr>
1980       </table>
1981     </td>
1982   </tr>
1983   $imagelinks
1984
1985 $jsscript
1986 |;
1987   $lxdebug->leave_sub();
1988 }
1989
1990 sub form_footer {
1991   $lxdebug->enter_sub();
1992
1993   if ($form->{item} eq "assembly") {
1994
1995     print qq|
1996         <tr>
1997           <td>
1998             <table width="100%">
1999               <tr>
2000                 <th colspan=2 align=right>|
2001       . $locale->text('Total') . qq|&nbsp;</th>
2002                 <th align=right>|
2003       . $form->format_amount(\%myconfig, $form->{assemblytotal}, 2) . qq|</th>
2004               </tr>
2005             </table>
2006           </td>
2007         </tr>
2008         <input type=hidden name=assembly_rows value=$form->{assembly_rows}>
2009 |;
2010   }
2011
2012   print qq|
2013       <input type=hidden name=login value=$form->{login}>
2014       <input type=hidden name=password value=$form->{password}>
2015       <input type=hidden name=callback value="$form->{callback}">
2016       <input type=hidden name=previousform value="$form->{previousform}">
2017       <input type=hidden name=taxaccount2 value="$form->{taxaccount2}">
2018       <input type=hidden name=vc value=$form->{vc}>
2019   <tr>
2020     <td><hr size=3 noshade></td>
2021   </tr>
2022 </table>
2023
2024 <br>
2025 <input class=submit type=submit name=action value="|
2026     . $locale->text('Update') . qq|">
2027   |;
2028
2029   unless ($form->{item} eq "service") {
2030     print qq|
2031       <input type=hidden name=makemodel_rows value=$form->{makemodel_rows}>
2032     |;
2033   }
2034
2035   print qq|
2036      <input type=hidden name=price_rows value=$form->{price_rows}>|;
2037
2038   print qq|
2039       <input class=submit type=submit name=action value="|
2040     . $locale->text('Save') . qq|">|;
2041
2042   if ($form->{id}) {
2043
2044     if (!$form->{previousform}) {
2045       print qq|
2046       <input class=submit type=submit name=action value="|
2047         . $locale->text('Save as new') . qq|">|;
2048     }
2049
2050     if ($form->{orphaned}) {
2051       if (!$form->{previousform}) {
2052         if ($form->{item} eq 'assembly') {
2053           if (!$form->{onhand}) {
2054             print qq|
2055       <input class=submit type=submit name=action value="|
2056               . $locale->text('Delete') . qq|">|;
2057           }
2058         } else {
2059           print qq|
2060       <input class=submit type=submit name=action value="|
2061             . $locale->text('Delete') . qq|">|;
2062         }
2063       }
2064     }
2065   }
2066
2067   if (!$form->{previousform}) {
2068     if ($form->{menubar}) {
2069       require "bin/mozilla/menu.pl";
2070       &menubar;
2071     }
2072   }
2073 # button for saving history
2074   if($form->{id} ne "") {
2075         print qq|
2076                 <input type=button class=submit onclick=set_history_window(|
2077                 . $form->{id} 
2078                 . qq|); name=history id=history value=|
2079                 . $locale->text('history') 
2080                 . qq|>|;
2081   }
2082 # /button for saving history
2083   print qq|
2084
2085 </form>
2086
2087 <script type="text/javascript" src="js/wz_tooltip.js"></script>
2088
2089 </body>
2090 </html>
2091 |;
2092
2093   $lxdebug->leave_sub();
2094 }
2095
2096 sub makemodel_row {
2097   $lxdebug->enter_sub();
2098   my ($numrows) = @_;
2099   
2100   print qq|
2101   <tr>
2102     <td>
2103       <table width=100%>
2104         <tr>
2105           <th class="listheading">| . $locale->text('Make') . qq|</th>
2106           <th class="listheading">| . $locale->text('Model') . qq|</th>
2107         </tr>
2108 |;
2109
2110   for my $i (1 .. $numrows) {
2111     $form->{"make_$i"}  =~ s/\"/&quot;/g;
2112     $form->{"model_$i"} =~ s/\"/&quot;/g;
2113     print qq|
2114         <tr>
2115           <td width=50%><input name="make_$i" size=30 value="$form->{"make_$i"}"></td>
2116           <td width=50%><input name="model_$i" size=30 value="$form->{"model_$i"}"></td>
2117         </tr>
2118 |;
2119   }
2120
2121   print qq|
2122       </table>
2123     </td>
2124   </tr>
2125 |;
2126
2127   $lxdebug->leave_sub();
2128 }
2129
2130 sub assembly_row {
2131   $lxdebug->enter_sub();
2132   my ($numrows) = @_;
2133   my (@column_index, %column_data, %column_header);
2134   my ($nochange, $callback, $previousform, $linetotal, $href);
2135
2136   our ($deliverydate); # ToDO: cjeck if this indeed comes from global context
2137
2138   @column_index =
2139     qw(runningnumber qty unit bom partnumber description partsgroup total);
2140
2141   if ($form->{previousform}) {
2142     $nochange     = 1;
2143     @column_index = qw(qty unit bom partnumber description partsgroup total);
2144   } else {
2145
2146     # change callback
2147     $form->{old_callback} = $form->{callback};
2148     $callback             = $form->{callback};
2149     $form->{callback}     = "$form->{script}?action=display_form";
2150
2151     # delete action
2152     map { delete $form->{$_} } qw(action header);
2153
2154     $previousform = "";
2155
2156     # save form variables in a previousform variable
2157     foreach my $key (sort keys %$form) {
2158
2159       # escape ampersands
2160       $form->{$key} =~ s/&/%26/g;
2161       $previousform .= qq|$key=$form->{$key}&|;
2162     }
2163     chop $previousform;
2164     $previousform = $form->escape($form->escape($previousform, 1));
2165     $form->{callback} = $callback;
2166
2167     $form->{assemblytotal} = 0;
2168     $form->{weight}        = 0;
2169
2170   }
2171   $column_header{runningnumber} =
2172     qq|<th nowrap width=5%>| . $locale->text('No.') . qq|</th>|;
2173   $column_header{qty} =
2174     qq|<th align=left nowrap width=10%>| . $locale->text('Qty') . qq|</th>|;
2175   $column_header{unit} =
2176     qq|<th align=left nowrap width=5%>| . $locale->text('Unit') . qq|</th>|;
2177   $column_header{partnumber} =
2178       qq|<th align=left nowrap width=20%>|
2179     . $locale->text('Part Number')
2180     . qq|</th>|;
2181   $column_header{description} =
2182     qq|<th nowrap width=50%>| . $locale->text('Part Description') . qq|</th>|;
2183   $column_header{total} =
2184     qq|<th align=right nowrap>| . $locale->text('Extended') . qq|</th>|;
2185   $column_header{bom}        = qq|<th>| . $locale->text('BOM') . qq|</th>|;
2186   $column_header{partsgroup} = qq|<th>| . $locale->text('Group') . qq|</th>|;
2187
2188   print qq|
2189   <tr class=listheading>
2190     <th class=listheading>| . $locale->text('Individual Items') . qq|</th>
2191   </tr>
2192   <tr>
2193     <td>
2194       <table width=100%>
2195         <tr>
2196 |;
2197
2198   map { print "\n$column_header{$_}" } @column_index;
2199
2200   print qq|
2201         </tr>
2202 |;
2203
2204   for my $i (1 .. $numrows) {
2205     $form->{"partnumber_$i"} =~ s/\"/&quot;/g;
2206
2207     $linetotal =
2208       $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2);
2209     $form->{assemblytotal} += $linetotal;
2210
2211     $form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
2212
2213     $linetotal = $form->format_amount(\%myconfig, $linetotal, 2);
2214
2215     if (($i >= 1) && ($i == $numrows)) {
2216
2217       if ($nochange) {
2218         map { $column_data{$_} = qq|<td></td>| }
2219           qw(qty unit partnumber description bom partsgroup);
2220       } else {
2221
2222         map { $column_data{$_} = qq|<td></td>| } qw(runningnumber unit bom);
2223
2224         $column_data{qty} =
2225           qq|<td><input name="qty_$i" size=5 value="$form->{"qty_$i"}"></td>|;
2226         $column_data{partnumber} =
2227           qq|<td><input name="partnumber_$i" size=15 value="$form->{"partnumber_$i"}"></td>|;
2228         $column_data{description} =
2229           qq|<td><input name="description_$i" size=40 value="$form->{"description_$i"}"></td>|;
2230         $column_data{partsgroup} =
2231           qq|<td><input name="partsgroup_$i" size=10 value="$form->{"partsgroup_$i"}"></td>|;
2232
2233       }
2234
2235     } else {
2236
2237       if ($form->{previousform}) {
2238         $column_data{partnumber} =
2239           qq|<td><input type=hidden name="partnumber_$i" value="$form->{"partnumber_$i"}">$form->{"partnumber_$i"}</td>|;
2240         $column_data{qty} =
2241           qq|<td align=right><input type=hidden name="qty_$i" value="$form->{"qty_$i"}">$form->{"qty_$i"}</td>|;
2242
2243         $column_data{bom} =
2244           qq|<td align=center><input type=hidden name="bom_$i" value=$form->{"bom_$i"}>|;
2245         $column_data{bom} .= ($form->{"bom_$i"}) ? "x" : "&nbsp;";
2246         $column_data{bom} .= qq|</td>|;
2247
2248         $column_data{partsgroup} =
2249           qq|<td><input type=hidden name="partsgroup_$i" value="$form->{"partsgroup_$i"}">$form->{"partsgroup_$i"}</td>|;
2250
2251       } else {
2252         $href =
2253           qq|$form->{script}?action=edit&id=$form->{"id_$i"}&login=$form->{login}&password=$form->{password}&rowcount=$i&previousform=$previousform|;
2254         $column_data{partnumber} =
2255           qq|<td><input type=hidden name="partnumber_$i" value="$form->{"partnumber_$i"}"><a href=$href>$form->{"partnumber_$i"}</a></td>|;
2256         $column_data{runningnumber} =
2257           qq|<td><input name="runningnumber_$i" size=3 value="$i"></td>|;
2258         $column_data{qty} =
2259           qq|<td><input name="qty_$i" size=5 value="$form->{"qty_$i"}"></td>|;
2260
2261         $form->{"bom_$i"} = ($form->{"bom_$i"}) ? "checked" : "";
2262         $column_data{bom} =
2263           qq|<td align=center><input name="bom_$i" type=checkbox class=checkbox value=1 $form->{"bom_$i"}></td>|;
2264
2265         $column_data{partsgroup} =
2266           qq|<td><input type=hidden name="partsgroup_$i" value="$form->{"partsgroup_$i"}">$form->{"partsgroup_$i"}</td>|;
2267       }
2268
2269       $column_data{unit} =
2270         qq|<td><input type=hidden name="unit_$i" value="$form->{"unit_$i"}">$form->{"unit_$i"}</td>|;
2271       $column_data{description} =
2272         qq|<td><input type=hidden name="description_$i" value="$form->{"description_$i"}">$form->{"description_$i"}</td>|;
2273     }
2274
2275     $column_data{total} = qq|<td align=right>$linetotal</td>|;
2276
2277     $column_data{deliverydate} = qq|<td align=right>$deliverydate</td>|;
2278
2279     print qq|
2280         <tr>|;
2281
2282     map { print "\n$column_data{$_}" } @column_index;
2283
2284     print qq|
2285         </tr>
2286   <input type=hidden name="id_$i" value=$form->{"id_$i"}>
2287   <input type=hidden name="sellprice_$i" value=$form->{"sellprice_$i"}>
2288   <input type=hidden name="weight_$i" value=$form->{"weight_$i"}>
2289 |;
2290   }
2291
2292   print qq|
2293       </table>
2294     </td>
2295   </tr>
2296 |;
2297
2298   $lxdebug->leave_sub();
2299 }
2300
2301 sub update {
2302   $lxdebug->enter_sub();
2303
2304   if ($form->{item} eq "assembly") {
2305     my $i = $form->{assembly_rows};
2306
2307     # if last row is empty check the form otherwise retrieve item
2308     if (   ($form->{"partnumber_$i"} eq "")
2309         && ($form->{"description_$i"} eq "")
2310         && ($form->{"partsgroup_$i"}  eq "")) {
2311
2312       &check_form;
2313
2314     } else {
2315
2316       IC->assembly_item(\%myconfig, \%$form);
2317
2318       my $rows = scalar @{ $form->{item_list} };
2319
2320       if ($rows) {
2321         $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
2322
2323         if ($rows > 1) {
2324           $form->{makemodel_rows}--;
2325           &select_item;
2326           exit;
2327         } else {
2328           map { $form->{item_list}[$i]{$_} =~ s/\"/&quot;/g }
2329             qw(partnumber description unit partsgroup);
2330           map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} }
2331             keys %{ $form->{item_list}[0] };
2332           $form->{"runningnumber_$i"} = $form->{assembly_rows};
2333           $form->{assembly_rows}++;
2334
2335           &check_form;
2336
2337         }
2338
2339       } else {
2340
2341         $form->{rowcount} = $i;
2342         $form->{assembly_rows}++;
2343
2344         &new_item;
2345
2346       }
2347     }
2348
2349   } elsif (($form->{item} eq 'part') || ($form->{item} eq 'service')) {
2350     &check_form;
2351   }
2352
2353   $lxdebug->leave_sub();
2354 }
2355
2356 sub save {
2357   $lxdebug->enter_sub();
2358
2359   my ($parts_id, %newform, $previousform, $amount, $callback);
2360
2361   # check if there is a part number - commented out, cause there is an automatic allocation of numbers
2362   # $form->isblank("partnumber", $locale->text(ucfirst $form->{item}." Part Number missing!"));
2363
2364   # check if there is a description
2365   $form->isblank("description", $locale->text("Part Description missing!"));
2366
2367   if ($form->{obsolete}) {
2368     $form->error(
2369       $locale->text(
2370         "Inventory quantity must be zero before you can set this $form->{item} obsolete!"
2371       ))
2372       if ($form->{onhand} * 1);
2373   }
2374
2375   if (!$form->{buchungsgruppen_id}) {
2376     $form->error($locale->text("Parts must have an entry type.") . " " . 
2377      $locale->text("If you see this message, you most likely just setup your LX-Office and haven't added any entry types. If this is the case, the option is accessible for administrators in the System menu.") 
2378     );
2379   }
2380
2381   $form->error($locale->text('Description must not be empty!')) unless $form->{description};
2382   $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
2383
2384   # expand dynamic strings
2385   # $locale->text('Inventory quantity must be zero before you can set this part obsolete!')
2386   # $locale->text('Inventory quantity must be zero before you can set this assembly obsolete!')
2387   # $locale->text('Part Number missing!')
2388   # $locale->text('Service Number missing!')
2389   # $locale->text('Assembly Number missing!')
2390
2391   # save part
2392   $lxdebug->message($LXDebug::DEBUG1, "ic.pl: sellprice in save = $form->{sellprice}\n");
2393   if (IC->save(\%myconfig, \%$form) == 3) {
2394     $form->error($locale->text('Partnumber not unique!'));
2395   }
2396   # saving the history
2397   if(!exists $form->{addition}) {
2398     $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
2399         $form->{addition} = "SAVED";
2400         $form->save_history($form->dbconnect(\%myconfig));
2401   }
2402   # /saving the history
2403   $parts_id = $form->{id};
2404
2405   my $i;
2406   # load previous variables
2407   if ($form->{previousform}) {
2408
2409     # save the new form variables before splitting previousform
2410     map { $newform{$_} = $form->{$_} } keys %$form;
2411
2412     $previousform = $form->unescape($form->{previousform});
2413
2414     # don't trample on previous variables
2415     map { delete $form->{$_} } keys %newform;
2416
2417     # now take it apart and restore original values
2418     foreach my $item (split /&/, $previousform) {
2419       my ($key, $value) = split m/=/, $item, 2;
2420       $value =~ s/%26/&/g;
2421       $form->{$key} = $value;
2422     }
2423     $form->{taxaccounts} = $newform{taxaccount2};
2424
2425     if ($form->{item} eq 'assembly') {
2426
2427       # undo number formatting
2428       map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
2429         qw(weight listprice sellprice rop);
2430
2431       $form->{assembly_rows}--;
2432       $i = $newform{rowcount};
2433       $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
2434
2435       $form->{sellprice} -= $form->{"sellprice_$i"} * $form->{"qty_$i"};
2436       $form->{weight}    -= $form->{"weight_$i"} * $form->{"qty_$i"};
2437
2438       # change/add values for assembly item
2439       map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit weight listprice sellprice inventory_accno income_accno expense_accno price_factor_id);
2440
2441       $form->{sellprice} += $form->{"sellprice_$i"} * $form->{"qty_$i"};
2442       $form->{weight}    += $form->{"weight_$i"} * $form->{"qty_$i"};
2443
2444     } else {
2445
2446       # set values for last invoice/order item
2447       $i = $form->{rowcount};
2448       $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
2449
2450       map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit listprice inventory_accno income_accno expense_accno sellprice lastcost price_factor_id);
2451
2452       $form->{"sellprice_$i"} = $newform{lastcost} if ($form->{vendor_id});
2453
2454       if ($form->{exchangerate} != 0) {
2455         $form->{"sellprice_$i"} /= $form->{exchangerate};
2456       }
2457
2458       $lxdebug->message($LXDebug::DEBUG1, qq|sellprice_$i in previousform 2 = | . $form->{"sellprice_$i"} . qq|\n|);
2459
2460       map { $form->{"taxaccounts_$i"} .= "$_ " } split / /, $newform{taxaccount};
2461       chop $form->{"taxaccounts_$i"};
2462       foreach my $item (qw(description rate taxnumber)) {
2463         my $index = $form->{"taxaccounts_$i"} . "_$item";
2464         $form->{$index} = $newform{$index};
2465       }
2466
2467       # credit remaining calculation
2468       $amount = $form->{"sellprice_$i"} * (1 - $form->{"discount_$i"} / 100) * $form->{"qty_$i"};
2469
2470       map { $form->{"${_}_base"} += $amount } (split / /, $form->{"taxaccounts_$i"});
2471       map { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) } split / /, $form->{"taxaccounts_$i"} if !$form->{taxincluded};
2472
2473       $form->{creditremaining} -= $amount;
2474
2475       # redo number formatting, because invoice parse them!
2476       map { $form->{"${_}_$i"} = $form->format_amount(\%myconfig, $form->{"${_}_$i"}) } qw(weight listprice sellprice rop);
2477     }
2478
2479     $form->{"id_$i"} = $parts_id;
2480
2481     # Get the actual price factor (not just the ID) for the marge calculation.
2482     $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
2483     foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
2484       next if ($pfac->{id} != $newform{price_factor_id});
2485       $form->{"marge_price_factor_$i"} = $pfac->{factor};
2486       last;
2487     }
2488     delete $form->{ALL_PRICE_FACTORS};
2489
2490     delete $form->{action};
2491
2492     # restore original callback
2493     $callback = $form->unescape($form->{callback});
2494     $form->{callback} = $form->unescape($form->{old_callback});
2495     delete $form->{old_callback};
2496
2497     $form->{makemodel_rows}--;
2498
2499     # put callback together
2500     foreach my $key (keys %$form) {
2501
2502       # do single escape for Apache 2.0
2503       my $value = $form->escape($form->{$key}, 1);
2504       $callback .= qq|&$key=$value|;
2505     }
2506     $form->{callback} = $callback;
2507   }
2508   $lxdebug->message($LXDebug::DEBUG1, qq|ic.pl: sellprice_$i nach sub save = | . $form->{"sellprice_$i"} . qq|\n|);
2509
2510   # redirect
2511   $form->redirect;
2512
2513   $lxdebug->leave_sub();
2514 }
2515
2516 sub save_as_new {
2517   $lxdebug->enter_sub();
2518
2519   # saving the history
2520   if(!exists $form->{addition}) {
2521     $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
2522         $form->{addition} = "SAVED AS NEW";
2523         $form->save_history($form->dbconnect(\%myconfig));
2524   }
2525   # /saving the history
2526   $form->{id} = 0;
2527   if ($form->{"original_partnumber"} &&
2528       ($form->{"partnumber"} eq $form->{"original_partnumber"})) {
2529     $form->{partnumber} = "";
2530   }
2531   &save;
2532   $lxdebug->leave_sub();
2533 }
2534
2535 sub delete {
2536   $lxdebug->enter_sub();
2537   # saving the history
2538   if(!exists $form->{addition}) {
2539     $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
2540         $form->{addition} = "DELETED";
2541         $form->save_history($form->dbconnect(\%myconfig));
2542   }
2543   # /saving the history
2544   my $rc = IC->delete(\%myconfig, \%$form);
2545
2546   # redirect
2547   $form->redirect($locale->text('Item deleted!')) if ($rc > 0);
2548   $form->error($locale->text('Cannot delete item!'));
2549
2550   $lxdebug->leave_sub();
2551 }
2552
2553 sub price_row {
2554   $lxdebug->enter_sub();
2555
2556   my ($numrows) = @_;
2557
2558   print qq|
2559   <tr>
2560     <td>
2561       <table width=100%>
2562         <tr>
2563           <th class="listheading">| . $locale->text('Preisklasse') . qq|</th>
2564           <th class="listheading">| . $locale->text('Preis') . qq|</th>
2565         </tr>
2566 |;
2567   for my $i (1 .. $numrows) {
2568     print qq|
2569         <tr>
2570           <td width=50%><input type=hidden name="pricegroup_$i" size=30  value="$form->{"pricegroup_$i"}">$form->{"pricegroup_$i"}</td>
2571           <td width=50%><input name="price_$i" size=11 value="$form->{"price_$i"}"></td>
2572           <input type=hidden name="pricegroup_id_$i" value="$form->{"pricegroup_id_$i"}">
2573         </tr>
2574 |;
2575   }
2576
2577   print qq|
2578       </table>
2579     </td>
2580   </tr>
2581 |;
2582
2583   $lxdebug->leave_sub();
2584 }
2585
2586 sub parts_language_selection {
2587   $lxdebug->enter_sub();
2588
2589   our ($onload);
2590
2591   my $languages = IC->retrieve_languages(\%myconfig, $form);
2592
2593   if ($form->{language_values} ne "") {
2594     foreach $item (split(/---\+\+\+---/, $form->{language_values})) {
2595       my ($language_id, $translation, $longdescription) = split(/--\+\+--/, $item);
2596
2597       foreach my $language (@{ $languages }) {
2598         next unless ($language->{id} == $language_id);
2599
2600         $language->{translation}     = $translation;
2601         $language->{longdescription} = $longdescription;
2602         last;
2603       }
2604     }
2605   }
2606
2607   my @header_sort = qw(name longdescription);
2608   my %header_title = ( "name" => $locale->text("Name"),
2609                        "longdescription" => $locale->text("Long Description"),
2610                        );
2611
2612   my @header =
2613     map(+{ "column_title" => $header_title{$_},
2614            "column" => $_,
2615            "callback" => $callback,
2616          },
2617         @header_sort);
2618
2619   $form->{"title"} = $locale->text("Language Values");
2620   $form->header();
2621   print $form->parse_html_template("ic/parts_language_selection", { "HEADER"    => \@header,
2622                                                                     "LANGUAGES" => $languages,
2623                                                                     "onload"    => $onload });
2624
2625   $lxdebug->leave_sub();
2626 }
2627
2628 sub continue { call_sub($form->{"nextsub"}); }