1 #=====================================================================
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
7 #=====================================================================
8 # SQL-Ledger, Accounting
11 # Author: Dieter Simader
12 # Email: dsimader@sql-ledger.org
13 # Web: http://www.sql-ledger.org
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.
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 #======================================================================
30 # Inventory Control module
32 #======================================================================
34 use POSIX qw(strftime);
35 use List::Util qw(max);
36 use List::MoreUtils qw(any);
41 use SL::ReportGenerator;
49 our ($form, $locale, %myconfig, $lxdebug, $auth);
51 require "bin/mozilla/io.pl";
52 require "bin/mozilla/invoice_io.pl";
53 require "bin/mozilla/common.pl";
54 require "bin/mozilla/reportgenerator.pl";
59 # type=submit $locale->text('Add Part')
60 # type=submit $locale->text('Add Service')
61 # type=submit $locale->text('Add Assembly')
62 # type=submit $locale->text('Edit Part')
63 # type=submit $locale->text('Edit Service')
64 # type=submit $locale->text('Edit Assembly')
65 # $locale->text('Parts')
66 # $locale->text('Services')
67 # $locale->text('Inventory quantity must be zero before you can set this part obsolete!')
68 # $locale->text('Inventory quantity must be zero before you can set this assembly obsolete!')
69 # $locale->text('Part Number missing!')
70 # $locale->text('Service Number missing!')
71 # $locale->text('Assembly Number missing!')
72 # $locale->text('ea');
77 $lxdebug->enter_sub();
79 $auth->assert('part_service_assembly_edit');
81 $form->{title} = $locale->text('Add ' . ucfirst $form->{item});
82 $form->{callback} = "$form->{script}?action=add&item=$form->{item}" unless $form->{callback};
83 $form->{unit_changeable} = 1;
85 IC->get_pricegroups(\%myconfig, \%$form);
89 $lxdebug->leave_sub();
93 $lxdebug->enter_sub();
95 $auth->assert('part_service_assembly_edit');
97 $form->{revers} = 0; # switch for backward sorting
98 $form->{lastsort} = ""; # memory for which table was sort at last time
99 $form->{ndxs_counter} = 0; # counter for added entries to top100
101 my %is_xyz = map { +"is_$_" => ($form->{searchitems} eq $_) } qw(part service assembly);
103 $form->{title} = (ucfirst $form->{searchitems}) . "s";
104 $form->{title} = $locale->text($form->{title});
105 $form->{title} = $locale->text('Assemblies') if ($is_xyz{is_assembly});
107 $form->{jsscript} = 1;
109 $form->{CUSTOM_VARIABLES} = CVar->get_configs('module' => 'IC');
110 ($form->{CUSTOM_VARIABLES_FILTER_CODE},
111 $form->{CUSTOM_VARIABLES_INCLUSION_CODE}) = CVar->render_search_options('variables' => $form->{CUSTOM_VARIABLES},
112 'include_prefix' => 'l_',
113 'include_value' => 'Y');
117 print $form->parse_html_template('ic/search', { %is_xyz,
118 dateformat => $myconfig{dateformat}, });
120 $lxdebug->leave_sub();
123 sub search_update_prices {
124 $lxdebug->enter_sub();
126 $auth->assert('part_service_assembly_edit');
128 my $pricegroups = IC->get_pricegroups(\%myconfig, \%$form);
132 print $form->parse_html_template('ic/search_update_prices', { PRICE_ROWS => $pricegroups });
134 $lxdebug->leave_sub();
137 sub confirm_price_update {
138 $lxdebug->enter_sub();
140 $auth->assert('part_service_assembly_edit');
143 my $value_found = undef;
145 foreach my $idx (qw(sellprice listprice), (1..$form->{price_rows})) {
146 my $name = $idx =~ m/\d/ ? $form->{"pricegroup_${idx}"} : $idx eq 'sellprice' ? $locale->text('Sell Price') : $locale->text('List Price');
147 my $type = $idx =~ m/\d/ ? $form->{"pricegroup_type_${idx}"} : $form->{"${idx}_type"};
148 my $value_idx = $idx =~ m/\d/ ? "price_${idx}" : $idx;
149 my $value = $form->parse_amount(\%myconfig, $form->{$value_idx});
151 if ((0 > $value) && ($type eq 'percent')) {
152 push @errors, $locale->text('You cannot adjust the price for pricegroup "#1" by a negative percentage.', $name);
154 } elsif (!$value && ($form->{$value_idx} ne '')) {
155 push @errors, $locale->text('No valid number entered for pricegroup "#1".', $name);
157 } elsif (0 < $value) {
162 push @errors, $locale->text('No prices will be updated because no prices have been entered.') if (!$value_found);
164 my $num_matches = IC->get_num_matches_for_priceupdate();
169 $form->show_generic_error(join('<br>', @errors), 'back_button' => 1);
172 $form->{nextsub} = "update_prices";
174 map { delete $form->{$_} } qw(action header);
176 print $form->parse_html_template('ic/confirm_price_update', { HIDDENS => [ map { name => $_, value => $form->{$_} }, keys %$form ],
177 num_matches => $num_matches });
179 $lxdebug->leave_sub();
183 $lxdebug->enter_sub();
185 $auth->assert('part_service_assembly_edit');
187 my $num_updated = IC->update_prices(\%myconfig, \%$form);
189 if (-1 != $num_updated) {
190 $form->redirect($locale->text('#1 prices were updated.', $num_updated));
192 $form->error($locale->text('Could not update prices!'));
195 $lxdebug->leave_sub();
199 # $lxdebug->enter_sub();
201 # $auth->assert('part_service_assembly_edit');
203 # our ($j, $lastndx);
206 # $form->{title} = $locale->text('Top 100 hinzufuegen');
210 # push @custom_hiddens, qw(searchitems title bom titel revers lastsort sort ndxs_counter extras);
211 # push @custom_hiddens, qw(itemstatus l_linetotal l_partnumber l_description l_onhand l_unit l_sellprice l_linetotalsellprice);
213 # +{ name => 'row', value => $j },
214 # +{ name => 'nextsub', value => 'item_selected' },
215 # +{ name => 'test', value => 'item_selected' },
216 # +{ name => 'lastndx', value => $lastndx },
217 # map(+{ name => $_, value => $form->{$_} }, @custom_hiddens),
220 # my ($partnumber, $description, $unit, $sellprice, $soldtotal);
221 # # if choice set data
222 ## if ($form->{ndx}) {
223 ## for my $i (0 .. $form->{ndxs_counter}) {
225 ## # insert data into top100
226 ## push @{ $form->{parts} },
228 ## partnumber => $form->{"totop100_partnumber_$j"},
229 ## description => $form->{"totop100_description_$j"},
230 ## unit => $form->{"totop100_unit_$j"},
231 ## sellprice => $form->{"totop100_sellprice_$j"},
232 ## soldtotal => $form->{"totop100_soldtotal_$j"},
239 # # set data for next page
240 # for my $i (1 .. $form->{ndxs_counter}) {
241 # $partnumber = $form->{"totop100_partnumber_$i"};
242 # $description = $form->{"totop100_description_$i"};
243 # $unit = $form->{"totop100_unit_$i"};
244 # $sellprice = $form->{"totop100_sellprice_$i"};
245 # $soldtotal = $form->{"totop100_soldtotal_$i"};
248 # totop100_partnumber => $form->{"totop100_partnumber_$i"},
249 # totop100_description => $form->{"totop100_description_$i"},
250 # totop100_unit => $form->{"totop100_unit_$i"},
251 # totop100_sellprice => $form->{"totop100_sellprice_$i"},
252 # totop100_soldtotal => $form->{"totop100_soldtotal_$i"},
256 ##<input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
257 ##<input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
258 ##<input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
259 ##<input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
260 ##<input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
264 # print $form->parse_html_template('ic/choice', +{ HIDDENS => \@HIDDENS, PARTS => \@PARTS });
266 # $lxdebug->leave_sub();
270 # $lxdebug->enter_sub();
272 # $auth->assert('part_service_assembly_edit');
275 # our ($partnumber, $description, $unit, $sellprice, $soldtotal);
277 # my @sortorders = ("", "partnumber", "description", "all");
278 # my $sortorder = $sortorders[($form->{description} ? 2 : 0) + ($form->{partnumber} ? 1 : 0)];
279 # IC->get_parts(\%myconfig, \%$form, $sortorder);
281 # $form->{title} = $locale->text('Top 100 hinzufuegen');
287 # <form method=post action=ic.pl>
290 # <th class=listtop colspan=6>| . $locale->text('choice part') . qq|</th>
292 # <tr height="5"></tr>
293 # <tr class=listheading>
295 # <th class=listheading>| . $locale->text('Part Number') . qq|</th>
296 # <th class=listheading>| . $locale->text('Part Description') . qq|</th>
297 # <th class=listheading>| . $locale->text('Unit of measure') . qq|</th>
298 # <th class=listheading>| . $locale->text('Sell Price') . qq|</th>
299 # <th class=listheading>| . $locale->text('soldtotal') . qq|</th>
303 # my $i = $form->{rows};
305 # for ($j = 1; $j <= $i; $j++) {
308 # <tr class=listrow| . ($j % 2) . qq|>|;
311 # <td><input name=ndx class=radio type=radio value=$j checked></td>|;
314 # <td><input name=ndx class=radio type=radio value=$j></td>|;
317 # <td><input name="new_partnumber_$j" type=hidden value="$form->{"partnumber_$j"}">$form->{"partnumber_$j"}</td>
318 # <td><input name="new_description_$j" type=hidden value="$form->{"description_$j"}">$form->{"description_$j"}</td>
319 # <td><input name="new_unit_$j" type=hidden value="$form->{"unit_$j"}">$form->{"unit_$j"}</td>
320 # <td><input name="new_sellprice_$j" type=hidden value="$form->{"sellprice_$j"}">$form->{"sellprice_$j"}</td>
321 # <td><input name="new_soldtotal_$j" type=hidden value="$form->{"soldtotal_$j"}">$form->{"soldtotal_$j"}</td>
324 # <input name="new_id_$j" type=hidden value="$form->{"id_$j"}">|;
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}">
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}">
350 #<input type=hidden name=row value=$j>
352 #<input type=hidden name=nextsub value=item_selected>
354 #<input name=lastndx type=hidden value=$lastndx>
356 #<input name=ndxs_counter type=hidden value=$form->{ndxs_counter}>|;
360 # if (($form->{ndxs_counter}) > 0) {
361 # for ($i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
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"};
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"}>
382 #<input class=submit type=submit name=action value="|
383 # . $locale->text('TOP100') . qq|">
389 # $lxdebug->leave_sub();
393 $lxdebug->enter_sub();
395 $auth->assert('part_service_assembly_edit');
398 $form->{ndxs_counter}++;
400 if ($form->{ndxs_counter} > 0) {
402 my $index = $form->{ndx};
404 $form->{"totop100_partnumber_$form->{ndxs_counter}"} = $form->{"new_partnumber_$index"};
405 $form->{"totop100_description_$form->{ndxs_counter}"} = $form->{"new_description_$index"};
406 $form->{"totop100_unit_$form->{ndxs_counter}"} = $form->{"new_unit_$index"};
407 $form->{"totop100_sellprice_$form->{ndxs_counter}"} = $form->{"new_sellprice_$index"};
408 $form->{"totop100_soldtotal_$form->{ndxs_counter}"} = $form->{"new_soldtotal_$index"};
412 $lxdebug->leave_sub();
416 $lxdebug->enter_sub();
418 $auth->assert('part_service_assembly_edit');
420 my ($revers, $lastsort, $callback, $option, $description, $sameitem,
421 $partnumber, $unit, $sellprice, $soldtotal, $totop100, $onhand, $align);
422 my (@column_index, %column_header, %column_data);
423 my ($totalsellprice, $totallastcost, $totallistprice, $subtotalonhand, $subtotalsellprice, $subtotallastcost, $subtotallistprice);
425 $form->{top100} = "top100";
426 $form->{l_soldtotal} = "Y";
427 $form->{soldtotal} = "soldtotal";
428 $form->{sort} = "soldtotal";
429 $form->{l_qty} = "N";
430 $form->{l_linetotal} = "";
432 $form->{number} = "position";
433 $form->{l_number} = "Y";
437 $form->{title} = $locale->text('Top 100');
439 $revers = $form->{revers};
440 $lastsort = $form->{lastsort};
442 if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
444 $form->{lastsort} = "partnumber";
445 $form->{sort} = "partnumber";
449 "$form->{script}?action=top100&searchitems=$form->{searchitems}&itemstatus=$form->{itemstatus}&bom=$form->{bom}&l_linetotal=$form->{l_linetotal}&title="
450 . $form->escape($form->{title}, 1);
452 # if we have a serialnumber limit search
453 if ($form->{serialnumber} || $form->{l_serialnumber}) {
454 $form->{l_serialnumber} = "Y";
455 unless ( $form->{bought}
458 || $form->{quoted}) {
459 $form->{bought} = $form->{sold} = 1;
462 IC->all_parts(\%myconfig, \%$form);
464 if ($form->{itemstatus} eq 'active') {
465 $option .= $locale->text('Active') . " : ";
467 if ($form->{itemstatus} eq 'obsolete') {
468 $option .= $locale->text('Obsolete') . " : ";
470 if ($form->{itemstatus} eq 'orphaned') {
471 $option .= $locale->text('Orphaned') . " : ";
473 if ($form->{itemstatus} eq 'onhand') {
474 $option .= $locale->text('On Hand') . " : ";
475 $form->{l_onhand} = "Y";
477 if ($form->{itemstatus} eq 'short') {
478 $option .= $locale->text('Short') . " : ";
479 $form->{l_onhand} = "Y";
481 if ($form->{onorder}) {
482 $form->{l_ordnumber} = "Y";
483 $callback .= "&onorder=$form->{onorder}";
484 $option .= $locale->text('On Order') . " : ";
486 if ($form->{ordered}) {
487 $form->{l_ordnumber} = "Y";
488 $callback .= "&ordered=$form->{ordered}";
489 $option .= $locale->text('Ordered') . " : ";
492 $form->{l_quonumber} = "Y";
493 $callback .= "&rfq=$form->{rfq}";
494 $option .= $locale->text('RFQ') . " : ";
496 if ($form->{quoted}) {
497 $form->{l_quonumber} = "Y";
498 $callback .= ""ed=$form->{quoted}";
499 $option .= $locale->text('Quoted') . " : ";
501 if ($form->{bought}) {
502 $form->{l_invnumber} = "Y";
503 $callback .= "&bought=$form->{bought}";
504 $option .= $locale->text('Bought') . " : ";
507 $form->{l_invnumber} = "Y";
508 $callback .= "&sold=$form->{sold}";
509 $option .= $locale->text('Sold') . " : ";
516 || $form->{quoted}) {
518 $form->{l_lastcost} = "";
519 $form->{l_name} = "Y";
520 if ($form->{transdatefrom}) {
521 $callback .= "&transdatefrom=$form->{transdatefrom}";
523 . $locale->text('From')
525 . $locale->date(\%myconfig, $form->{transdatefrom}, 1);
527 if ($form->{transdateto}) {
528 $callback .= "&transdateto=$form->{transdateto}";
530 . $locale->text('To')
532 . $locale->date(\%myconfig, $form->{transdateto}, 1);
538 if ($form->{partnumber}) {
539 $callback .= "&partnumber=$form->{partnumber}";
540 $option .= $locale->text('Part Number') . qq| : $form->{partnumber}<br>|;
543 $callback .= "&partnumber=$form->{ean}";
544 $option .= $locale->text('EAN') . qq| : $form->{ean}<br>|;
546 if ($form->{partsgroup}) {
547 $callback .= "&partsgroup=$form->{partsgroup}";
548 $option .= $locale->text('Group') . qq| : $form->{partsgroup}<br>|;
550 if ($form->{serialnumber}) {
551 $callback .= "&serialnumber=$form->{serialnumber}";
552 $option .= $locale->text('Serial Number') . qq| : $form->{serialnumber}<br>|;
554 if ($form->{description}) {
555 $callback .= "&description=$form->{description}";
556 $description = $form->{description};
557 $description =~ s/\n/<br>/g;
558 $option .= $locale->text('Part Description') . qq| : $form->{description}<br>|;
561 $callback .= "&make=$form->{make}";
562 $option .= $locale->text('Make') . qq| : $form->{make}<br>|;
564 if ($form->{model}) {
565 $callback .= "&model=$form->{model}";
566 $option .= $locale->text('Model') . qq| : $form->{model}<br>|;
568 if ($form->{drawing}) {
569 $callback .= "&drawing=$form->{drawing}";
570 $option .= $locale->text('Drawing') . qq| : $form->{drawing}<br>|;
572 if ($form->{microfiche}) {
573 $callback .= "µfiche=$form->{microfiche}";
574 $option .= $locale->text('Microfiche') . qq| : $form->{microfiche}<br>|;
576 if ($form->{l_soldtotal}) {
577 $callback .= "&soldtotal=$form->{soldtotal}";
578 $option .= $locale->text('soldtotal') . qq| : $form->{soldtotal}<br>|;
581 my @columns = $form->sort_columns(
582 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)
585 if ($form->{l_linetotal}) {
586 $form->{l_onhand} = "Y";
587 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
588 if ($form->{l_lastcost}) {
589 $form->{l_linetotallastcost} = "Y";
590 if (($form->{searchitems} eq 'assembly') && !$form->{bom}) {
591 $form->{l_linetotallastcost} = "";
594 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
597 if ($form->{searchitems} eq 'service') {
599 # remove bin, weight and rop from list
600 map { $form->{"l_$_"} = "" } qw(bin weight rop);
602 $form->{l_onhand} = "";
604 # qty is irrelevant unless bought or sold
610 || $form->{quoted}) {
611 $form->{l_onhand} = "Y";
613 $form->{l_linetotalsellprice} = "";
614 $form->{l_linetotallastcost} = "";
618 foreach my $item (@columns) {
619 if ($form->{"l_$item"} eq "Y") {
620 push @column_index, $item;
622 # add column to callback
623 $callback .= "&l_$item=Y";
627 if ($form->{l_subtotal} eq 'Y') {
628 $callback .= "&l_subtotal=Y";
631 $column_header{number} =
632 qq|<th class=listheading nowrap>| . $locale->text('number') . qq|</th>|;
633 $column_header{partnumber} =
634 qq|<th nowrap><a class=listheading href=$callback&sort=partnumber&revers=$form->{revers}&lastsort=$form->{lastsort}>|
635 . $locale->text('Part Number')
637 $column_header{description} =
638 qq|<th nowrap><a class=listheading href=$callback&sort=description&revers=$form->{revers}&lastsort=$form->{lastsort}>|
639 . $locale->text('Part Description')
641 $column_header{partsgroup} =
642 qq|<th nowrap><a class=listheading href=$callback&sort=partsgroup>|
643 . $locale->text('Group')
645 $column_header{bin} =
646 qq|<th><a class=listheading href=$callback&sort=bin>|
647 . $locale->text('Bin')
649 $column_header{priceupdate} =
650 qq|<th nowrap><a class=listheading href=$callback&sort=priceupdate>|
651 . $locale->text('Updated')
653 $column_header{onhand} =
654 qq|<th nowrap><a class=listheading href=$callback&sort=onhand&revers=$form->{revers}&lastsort=$form->{lastsort}>|
655 . $locale->text('Qty')
657 $column_header{unit} =
658 qq|<th class=listheading nowrap>| . $locale->text('Unit') . qq|</th>|;
659 $column_header{listprice} =
660 qq|<th class=listheading nowrap>|
661 . $locale->text('List Price')
663 $column_header{lastcost} =
664 qq|<th class=listheading nowrap>| . $locale->text('Last Cost') . qq|</th>|;
665 $column_header{rop} =
666 qq|<th class=listheading nowrap>| . $locale->text('ROP') . qq|</th>|;
667 $column_header{weight} =
668 qq|<th class=listheading nowrap>| . $locale->text('Weight') . qq|</th>|;
670 $column_header{invnumber} =
671 qq|<th nowrap><a class=listheading href=$callback&sort=invnumber>|
672 . $locale->text('Invoice Number')
674 $column_header{ordnumber} =
675 qq|<th nowrap><a class=listheading href=$callback&sort=ordnumber>|
676 . $locale->text('Order Number')
678 $column_header{quonumber} =
679 qq|<th nowrap><a class=listheading href=$callback&sort=quonumber>|
680 . $locale->text('Quotation')
683 $column_header{name} =
684 qq|<th nowrap><a class=listheading href=$callback&sort=name>|
685 . $locale->text('Name')
688 $column_header{sellprice} =
689 qq|<th class=listheading nowrap>|
690 . $locale->text('Sell Price')
692 $column_header{linetotalsellprice} =
693 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
694 $column_header{linetotallastcost} =
695 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
696 $column_header{linetotallistprice} =
697 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
699 $column_header{image} =
700 qq|<th class=listheading nowrap>| . $locale->text('Image') . qq|</a></th>|;
701 $column_header{drawing} =
702 qq|<th nowrap><a class=listheading href=$callback&sort=drawing>|
703 . $locale->text('Drawing')
705 $column_header{microfiche} =
706 qq|<th nowrap><a class=listheading href=$callback&sort=microfiche>|
707 . $locale->text('Microfiche')
710 $column_header{serialnumber} =
711 qq|<th nowrap><a class=listheading href=$callback&sort=serialnumber>|
712 . $locale->text('Serial Number')
714 $column_header{soldtotal} =
715 qq|<th nowrap><a class=listheading href=$callback&sort=soldtotal&revers=$form->{revers}&lastsort=$form->{lastsort}>|
716 . $locale->text('soldtotal')
720 my $colspan = $#column_index + 1;
727 <th class=listtop colspan=$colspan>$form->{title}</th>
731 <tr><td colspan=$colspan>$option</td></tr>
733 <tr class=listheading>
736 map { print "\n$column_header{$_}" } @column_index;
742 # add order to callback
743 $form->{callback} = $callback .= "&sort=$form->{sort}";
745 # escape callback for href
746 $callback = $form->escape($callback);
748 if (@{ $form->{parts} }) {
749 $sameitem = $form->{parts}->[0]->{ $form->{sort} };
752 # insert numbers for top100
754 foreach my $ref (@{ $form->{parts} }) {
759 # if avaible -> insert choice here
760 if (($form->{ndxs_counter}) > 0) {
761 for (my $i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
762 $partnumber = $form->{"totop100_partnumber_$i"};
763 $description = $form->{"totop100_description_$i"};
764 $unit = $form->{"totop100_unit_$i"};
765 $sellprice = $form->{"totop100_sellprice_$i"};
766 $soldtotal = $form->{"totop100_soldtotal_$i"};
769 <input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
770 <input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
771 <input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
772 <input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
773 <input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
777 push @{ $form->{parts} },
779 partnumber => "$partnumber",
780 description => "$description",
782 sellprice => "$sellprice",
783 soldtotal => "$soldtotal" };
786 # build data for columns
788 foreach my $ref (@{ $form->{parts} }) {
790 if ($form->{l_subtotal} eq 'Y' && !$ref->{assemblyitem}) {
791 if ($sameitem ne $ref->{ $form->{sort} }) {
792 parts_subtotal(\@column_index, \$subtotalonhand, \$subtotalsellprice, \$subtotallastcost, \$subtotallistprice);
793 $sameitem = $ref->{ $form->{sort} };
797 $ref->{exchangerate} = 1 unless $ref->{exchangerate};
798 $ref->{sellprice} *= $ref->{exchangerate};
799 $ref->{listprice} *= $ref->{exchangerate};
800 $ref->{lastcost} *= $ref->{exchangerate};
802 # use this for assemblies
803 $onhand = $ref->{onhand};
806 if ($ref->{assemblyitem}) {
808 $onhand = 0 if ($form->{sold});
811 $ref->{description} =~ s/\n/<br>/g;
813 $column_data{number} =
815 . $form->format_amount(\%myconfig, $ref->{number})
817 $column_data{partnumber} =
818 "<td align=$align>$ref->{partnumber} </a></td>";
819 $column_data{description} = "<td>$ref->{description} </td>";
820 $column_data{partsgroup} = "<td>$ref->{partsgroup} </td>";
822 $column_data{onhand} =
824 . $form->format_amount(\%myconfig, $ref->{onhand})
826 $column_data{sellprice} =
828 . $form->format_amount(\%myconfig, $ref->{sellprice})
830 $column_data{listprice} =
832 . $form->format_amount(\%myconfig, $ref->{listprice})
834 $column_data{lastcost} =
836 . $form->format_amount(\%myconfig, $ref->{lastcost})
839 $column_data{linetotalsellprice} = "<td align=right>"
840 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{sellprice}, 2)
842 $column_data{linetotallastcost} = "<td align=right>"
843 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{lastcost}, 2)
845 $column_data{linetotallistprice} = "<td align=right>"
846 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{listprice}, 2)
849 if (!$ref->{assemblyitem}) {
850 $totalsellprice += $onhand * $ref->{sellprice};
851 $totallastcost += $onhand * $ref->{lastcost};
852 $totallistprice += $onhand * $ref->{listprice};
854 $subtotalonhand += $onhand;
855 $subtotalsellprice += $onhand * $ref->{sellprice};
856 $subtotallastcost += $onhand * $ref->{lastcost};
857 $subtotallistprice += $onhand * $ref->{listprice};
862 . $form->format_amount(\%myconfig, $ref->{rop}) . "</td>";
863 $column_data{weight} =
865 . $form->format_amount(\%myconfig, $ref->{weight})
867 $column_data{unit} = "<td>$ref->{unit} </td>";
868 $column_data{bin} = "<td>$ref->{bin} </td>";
869 $column_data{priceupdate} = "<td>$ref->{priceupdate} </td>";
871 $column_data{invnumber} =
872 ($ref->{module} ne 'oe')
873 ? "<td><a href=$ref->{module}.pl?action=edit&type=invoice&id=$ref->{trans_id}&callback=$callback>$ref->{invnumber}</a></td>"
874 : "<td>$ref->{invnumber}</td>";
875 $column_data{ordnumber} =
876 ($ref->{module} eq 'oe')
877 ? "<td><a href=$ref->{module}.pl?action=edit&type=$ref->{type}&id=$ref->{trans_id}&callback=$callback>$ref->{ordnumber}</a></td>"
878 : "<td>$ref->{ordnumber}</td>";
879 $column_data{quonumber} =
880 ($ref->{module} eq 'oe' && !$ref->{ordnumber})
881 ? "<td><a href=$ref->{module}.pl?action=edit&type=$ref->{type}&id=$ref->{trans_id}&callback=$callback>$ref->{quonumber}</a></td>"
882 : "<td>$ref->{quonumber}</td>";
884 $column_data{name} = "<td>$ref->{name}</td>";
886 $column_data{image} =
888 ? "<td><a href=$ref->{image}><img src=$ref->{image} height=32 border=0></a></td>"
890 $column_data{drawing} =
892 ? "<td><a href=$ref->{drawing}>$ref->{drawing}</a></td>"
894 $column_data{microfiche} =
896 ? "<td><a href=$ref->{microfiche}>$ref->{microfiche}</a></td>"
899 $column_data{serialnumber} = "<td>$ref->{serialnumber}</td>";
901 $column_data{soldtotal} = "<td align=right>$ref->{soldtotal}</td>";
905 print "<tr class=listrow$i>";
907 map { print "\n$column_data{$_}" } @column_index;
914 if ($form->{l_subtotal} eq 'Y') {
915 parts_subtotal(\@column_index, \$subtotalonhand, \$subtotalsellprice, \$subtotallastcost, \$subtotallistprice);
918 if ($form->{"l_linetotal"}) {
919 map { $column_data{$_} = "<td> </td>" } @column_index;
920 $column_data{linetotalsellprice} =
921 "<th class=listtotal align=right>"
922 . $form->format_amount(\%myconfig, $totalsellprice, 2)
924 $column_data{linetotallastcost} =
925 "<th class=listtotal align=right>"
926 . $form->format_amount(\%myconfig, $totallastcost, 2)
928 $column_data{linetotallistprice} =
929 "<th class=listtotal align=right>"
930 . $form->format_amount(\%myconfig, $totallistprice, 2)
933 print "<tr class=listtotal>";
935 map { print "\n$column_data{$_}" } @column_index;
942 <tr><td colspan=$colspan><hr size=3 noshade></td></tr>
951 <form method=post action=$form->{script}>
953 <input type=hidden name=itemstatus value="$form->{itemstatus}">
954 <input type=hidden name=l_linetotal value="$form->{l_linetotal}">
955 <input type=hidden name=l_partnumber value="$form->{l_partnumber}">
956 <input type=hidden name=l_description value="$form->{l_description}">
957 <input type=hidden name=l_onhand value="$form->{l_onhand}">
958 <input type=hidden name=l_unit value="$form->{l_unit}">
959 <input type=hidden name=l_sellprice value="$form->{l_sellprice}">
960 <input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
961 <input type=hidden name=sort value="$form->{sort}">
962 <input type=hidden name=revers value="$form->{revers}">
963 <input type=hidden name=lastsort value="$form->{lastsort}">
964 <input type=hidden name=parts value="$form->{parts}">
966 <input type=hidden name=bom value="$form->{bom}">
967 <input type=hidden name=titel value="$form->{titel}">
968 <input type=hidden name=searchitems value="$form->{searchitems}">|;
973 <!-- <input type=hidden name=ndxs_counter value="$form->{ndxs_counter}">-->
975 <input class=submit type=submit name=action value="|
976 . $locale->text('choice') . qq|">
984 $lxdebug->leave_sub();
989 # Warning, deep magic ahead.
990 # This function parses the requested details, sanity checks them, and converts them into a format thats usable for IC->all_parts
992 # flags coming from the form:
994 # searchitems=part revers=0 lastsort=''
997 # partnumber ean description partsgroup serialnumber make model drawing microfiche
998 # transdatefrom transdateto
1001 # itemstatus = active | onhand | short | obsolete | orphaned
1002 # action = continue | top100
1005 # bought sold onorder ordered rfq quoted
1006 # l_partnumber l_description l_serialnumber l_unit l_listprice l_sellprice l_lastcost
1007 # l_linetotal l_priceupdate l_bin l_rop l_weight l_image l_drawing l_microfiche
1008 # l_partsgroup l_subtotal l_soldtotal l_deliverydate
1011 # nextsub revers lastsort sort ndxs_counter
1013 sub generate_report {
1014 $lxdebug->enter_sub();
1016 $auth->assert('part_service_assembly_edit');
1018 my ($revers, $lastsort, $description);
1020 my $cvar_configs = CVar->get_configs('module' => 'IC');
1022 $form->{title} = (ucfirst $form->{searchitems}) . "s";
1023 $form->{title} =~ s/ys$/ies/;
1024 $form->{title} = $locale->text($form->{title});
1027 'bin' => { 'text' => $locale->text('Bin'), },
1028 'deliverydate' => { 'text' => $locale->text('deliverydate'), },
1029 'description' => { 'text' => $locale->text('Part Description'), },
1030 'drawing' => { 'text' => $locale->text('Drawing'), },
1031 'image' => { 'text' => $locale->text('Image'), },
1032 'invnumber' => { 'text' => $locale->text('Invoice Number'), },
1033 'lastcost' => { 'text' => $locale->text('Last Cost'), },
1034 'linetotallastcost' => { 'text' => $locale->text('Extended'), },
1035 'linetotallistprice' => { 'text' => $locale->text('Extended'), },
1036 'linetotalsellprice' => { 'text' => $locale->text('Extended'), },
1037 'listprice' => { 'text' => $locale->text('List Price'), },
1038 'microfiche' => { 'text' => $locale->text('Microfiche'), },
1039 'name' => { 'text' => $locale->text('Name'), },
1040 'onhand' => { 'text' => $locale->text('Qty'), },
1041 'ordnumber' => { 'text' => $locale->text('Order Number'), },
1042 'partnumber' => { 'text' => $locale->text('Part Number'), },
1043 'partsgroup' => { 'text' => $locale->text('Group'), },
1044 'priceupdate' => { 'text' => $locale->text('Updated'), },
1045 'quonumber' => { 'text' => $locale->text('Quotation'), },
1046 'rop' => { 'text' => $locale->text('ROP'), },
1047 'sellprice' => { 'text' => $locale->text('Sell Price'), },
1048 'serialnumber' => { 'text' => $locale->text('Serial Number'), },
1049 'soldtotal' => { 'text' => $locale->text('soldtotal'), },
1050 'transdate' => { 'text' => $locale->text('Transdate'), },
1051 'unit' => { 'text' => $locale->text('Unit'), },
1052 'weight' => { 'text' => $locale->text('Weight'), },
1055 $revers = $form->{revers};
1056 $lastsort = $form->{lastsort};
1058 # sorting and direction of sorting
1059 # ToDO: change this to the simpler field+direction method
1060 if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
1061 $form->{revers} = 0;
1062 $form->{lastsort} = "partnumber";
1063 $form->{sort} = "partnumber";
1065 if ($form->{lastsort} eq $form->{sort}) {
1066 $form->{revers} = 1 - $form->{revers};
1068 $form->{revers} = 0;
1069 $form->{lastsort} = $form->{sort};
1073 # special case if we have a serialnumber limit search
1074 # serialnumbers are only given in invoices and orders,
1075 # so they can only pop up in bought, sold, rfq, and quoted stuff
1076 $form->{no_sn_joins} = 'Y' if ( !$form->{bought} && !$form->{sold}
1077 && !$form->{rfq} && !$form->{quoted}
1078 && ($form->{l_serialnumber} || $form->{serialnumber}));
1080 # special case for any checkbox of bought | sold | onorder | ordered | rfq | quoted.
1081 # if any of these are ticked the behavior changes slightly for lastcost
1082 # since all those are aggregation checks for the legder tables this is an internal switch
1083 # refered to as ledgerchecks
1084 $form->{ledgerchecks} = 'Y' if ( $form->{bought} || $form->{sold} || $form->{onorder}
1085 || $form->{ordered} || $form->{rfq} || $form->{quoted});
1087 # if something should be activated if something else is active, enter it here
1088 my %dependencies = (
1089 onhand => [ qw(l_onhand) ],
1090 short => [ qw(l_onhand) ],
1091 onorder => [ qw(l_ordnumber) ],
1092 ordered => [ qw(l_ordnumber) ],
1093 rfq => [ qw(l_quonumber) ],
1094 quoted => [ qw(l_quonumber) ],
1095 bought => [ qw(l_invnumber) ],
1096 sold => [ qw(l_invnumber) ],
1097 ledgerchecks => [ qw(l_name) ],
1098 serialnumber => [ qw(l_serialnumber) ],
1099 no_sn_joins => [ qw(bought sold) ],
1102 # these strings get displayed at the top of the results to indicate the user which switches were used
1104 active => $locale->text('Active'),
1105 obsolete => $locale->text('Obsolete'),
1106 orphaned => $locale->text('Orphaned'),
1107 onhand => $locale->text('On Hand'),
1108 short => $locale->text('Short'),
1109 onorder => $locale->text('On Order'),
1110 ordered => $locale->text('Ordered'),
1111 rfq => $locale->text('RFQ'),
1112 quoted => $locale->text('Quoted'),
1113 bought => $locale->text('Bought'),
1114 sold => $locale->text('Sold'),
1115 transdatefrom => $locale->text('From') . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1),
1116 transdateto => $locale->text('To (time)') . " " . $locale->date(\%myconfig, $form->{transdateto}, 1),
1117 partnumber => $locale->text('Part Number') . ": '$form->{partnumber}'",
1118 partsgroup => $locale->text('Group') . ": '$form->{partsgroup}'",
1119 serialnumber => $locale->text('Serial Number') . ": '$form->{serialnumber}'",
1120 description => $locale->text('Part Description') . ": '$form->{description}'",
1121 make => $locale->text('Make') . ": '$form->{make}'",
1122 model => $locale->text('Model') . ": '$form->{model}'",
1123 drawing => $locale->text('Drawing') . ": '$form->{drawing}'",
1124 microfiche => $locale->text('Microfiche') . ": '$form->{microfiche}'",
1125 l_soldtotal => $locale->text('soldtotal'),
1126 ean => $locale->text('EAN') . ": '$form->{ean}'",
1129 my @itemstatus_keys = qw(active obsolete orphaned onhand short);
1130 my @callback_keys = qw(onorder ordered rfq quoted bought sold partnumber partsgroup serialnumber description make model
1131 drawing microfiche l_soldtotal l_deliverydate transdatefrom transdateto ean);
1133 # calculate dependencies
1134 for (@itemstatus_keys, @callback_keys) {
1135 next if ($form->{itemstatus} ne $_ && !$form->{$_});
1136 map { $form->{$_} = 'Y' } @{ $dependencies{$_} } if $dependencies{$_};
1139 # generate callback and optionstrings
1141 for my $key (@itemstatus_keys, @callback_keys) {
1142 next if ($form->{itemstatus} ne $key && !$form->{$key});
1143 push @options, $optiontexts{$key};
1146 # special case for lastcost
1147 if ($form->{ledgerchecks}){
1148 # ledgerchecks don't know about sellprice or lastcost. they just return a
1149 # price. so rename sellprice to price, and drop lastcost.
1150 $column_defs{sellprice}{text} = $locale->text('Price');
1151 $form->{l_lastcost} = ""
1154 if ($form->{description}) {
1155 $description = $form->{description};
1156 $description =~ s/\n/<br>/g;
1159 if ($form->{l_linetotal}) {
1160 $form->{l_onhand} = "Y";
1161 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
1162 $form->{l_linetotallastcost} = $form->{searchitems} eq 'assembly' && !$form->{bom} ? "" : 'Y' if $form->{l_lastcost};
1163 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
1166 if ($form->{searchitems} eq 'service') {
1168 # remove bin, weight and rop from list
1169 map { $form->{"l_$_"} = "" } qw(bin weight rop);
1171 $form->{l_onhand} = "";
1173 # qty is irrelevant unless bought or sold
1174 if ( $form->{bought}
1179 || $form->{quoted}) {
1180 $form->{l_onhand} = "Y";
1182 $form->{l_linetotalsellprice} = "";
1183 $form->{l_linetotallastcost} = "";
1187 IC->all_parts(\%myconfig, \%$form);
1190 partnumber description partsgroup bin onhand rop unit listprice
1191 linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
1192 priceupdate weight image drawing microfiche invnumber ordnumber quonumber
1193 transdate name serialnumber soldtotal deliverydate ean
1196 my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
1197 my @searchable_custom_variables = grep { $_->{searchable} } @{ $cvar_configs };
1198 my %column_defs_cvars = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables;
1200 push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
1202 %column_defs = (%column_defs,%column_defs_cvars); # nochmal die cvars als überschrift hinzufügen
1203 map { $column_defs{$_}->{visible} = $form->{"l_$_"} ? 1 : 0 } @columns;
1204 map { $column_defs{$_}->{align} = 'right' } qw(onhand sellprice listprice lastcost linetotalsellprice linetotallastcost linetotallistprice rop weight soldtotal);
1206 my @hidden_variables = (qw(l_subtotal l_linetotal searchitems itemstatus bom), @itemstatus_keys, @callback_keys, @searchable_custom_variables, map { "l_$_" } @columns);
1207 my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
1209 my @sort_full = qw(partnumber description onhand soldtotal deliverydate);
1210 my @sort_no_revers = qw(partsgroup bin priceupdate invnumber ordnumber quonumber name image drawing serialnumber);
1212 foreach my $col (@sort_full) {
1213 $column_defs{$col}->{link} = join '&', $callback, "sort=$col", map { "$_=" . E($form->{$_}) } qw(revers lastsort);
1215 map { $column_defs{$_}->{link} = "${callback}&sort=$_" } @sort_no_revers;
1217 # add order to callback
1218 $form->{callback} = join '&', ($callback, map { "${_}=" . E($form->{$_}) } qw(sort revers));
1220 my $report = SL::ReportGenerator->new(\%myconfig, $form);
1222 my %attachment_basenames = (
1223 'part' => $locale->text('part_list'),
1224 'service' => $locale->text('service_list'),
1225 'assembly' => $locale->text('assembly_list'),
1228 $report->set_options('top_info_text' => $locale->text('Options') . ': ' . join(', ', grep $_, @options),
1229 'raw_bottom_info_text' => $form->parse_html_template('ic/generate_report_bottom'),
1230 'output_format' => 'HTML',
1231 'title' => $form->{title},
1232 'attachment_basename' => $attachment_basenames{$form->{searchitems}} . strftime('_%Y%m%d', localtime time),
1234 $report->set_options_from_form();
1236 $report->set_columns(%column_defs);
1237 $report->set_column_order(@columns);
1239 $report->set_export_options('generate_report', @hidden_variables, qw(sort revers));
1241 $report->set_sort_indicator($form->{sort}, $form->{revers} ? 0 : 1);
1243 CVar->add_custom_variables_to_report('module' => 'IC',
1244 'trans_id_field' => 'id',
1245 'configs' => $cvar_configs,
1246 'column_defs' => \%column_defs,
1247 'data' => $form->{parts});
1249 CVar->add_custom_variables_to_report('module' => 'IC',
1250 'sub_module' => sub { $_[0]->{ioi} },
1251 'trans_id_field' => 'ioi_id',
1252 'configs' => $cvar_configs,
1253 'column_defs' => \%column_defs,
1254 'data' => $form->{parts});
1256 my @subtotal_columns = qw(sellprice listprice lastcost);
1257 my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
1258 my %totals = map { $_ => 0 } @subtotal_columns;
1260 my $same_item = $form->{parts}[0]{ $form->{sort} } if (scalar @{ $form->{parts} });
1262 my $defaults = AM->get_defaults();
1265 foreach my $ref (@{ $form->{parts} }) {
1267 # fresh row, for inserting later
1268 my $row = { map { $_ => { 'data' => $ref->{$_} } } @columns };
1270 $ref->{exchangerate} ||= 1;
1271 $ref->{price_factor} ||= 1;
1272 $ref->{sellprice} *= $ref->{exchangerate} / $ref->{price_factor};
1273 $ref->{listprice} *= $ref->{exchangerate} / $ref->{price_factor};
1274 $ref->{lastcost} *= $ref->{exchangerate} / $ref->{price_factor};
1276 # use this for assemblies
1277 my $onhand = $ref->{onhand};
1279 if ($ref->{assemblyitem}) {
1280 $row->{partnumber}{align} = 'right';
1281 $row->{onhand}{data} = 0;
1282 $onhand = 0 if ($form->{sold});
1285 my $edit_link = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
1286 $row->{partnumber}->{link} = $edit_link;
1287 $row->{description}->{link} = $edit_link;
1289 foreach (qw(sellprice listprice lastcost)) {
1290 $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}, -2);
1291 $row->{"linetotal$_"}{data} = $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{$_}, 2);
1294 map { $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}); } qw(onhand rop weight soldtotal);
1296 $row->{weight}->{data} .= ' ' . $defaults->{weightunit};
1298 if (!$ref->{assemblyitem}) {
1299 foreach my $col (@subtotal_columns) {
1300 $totals{$col} += $onhand * $ref->{$col};
1301 $subtotals{$col} += $onhand * $ref->{$col};
1304 $subtotals{onhand} += $onhand;
1308 if ($ref->{module} eq 'oe') {
1309 my $edit_oe_link = build_std_url("script=oe.pl", 'action=edit', 'type=' . E($ref->{cv} eq 'vendor' ? 'purchase_order' : 'sales_order'), 'id=' . E($ref->{trans_id}), 'callback');
1310 $row->{ordnumber}{link} = $edit_oe_link;
1311 $row->{quonumber}{link} = $edit_oe_link if (!$ref->{ordnumber});
1314 $row->{invnumber}{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'type=invoice', 'id=' . E($ref->{trans_id}), 'callback');
1317 # set properties of images
1318 if ($ref->{image} && (lc $report->{options}->{output_format} eq 'html')) {
1319 $row->{image}{data} = '';
1320 $row->{image}{raw_data} = '<a href="' . H($ref->{image}) . '"><img src="' . H($ref->{image}) . '" height="32" border="0"></a>';
1322 map { $row->{$_}{link} = $ref->{$_} } qw(drawing microfiche);
1324 $report->add_data($row);
1326 my $next_ref = $form->{parts}[$idx + 1];
1328 # insert subtotal rows
1329 if (($form->{l_subtotal} eq 'Y') &&
1331 (!$next_ref->{assemblyitem} && ($same_item ne $next_ref->{ $form->{sort} })))) {
1332 my $row = { map { $_ => { 'class' => 'listsubtotal', } } @columns };
1334 if (($form->{searchitems} ne 'assembly') || !$form->{bom}) {
1335 $row->{onhand}->{data} = $form->format_amount(\%myconfig, $subtotals{onhand});
1338 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $subtotals{$_}, 2) } @subtotal_columns;
1339 map { $subtotals{$_} = 0 } ('onhand', @subtotal_columns);
1341 $report->add_data($row);
1343 $same_item = $next_ref->{ $form->{sort} };
1349 if ($form->{"l_linetotal"}) {
1350 my $row = { map { $_ => { 'class' => 'listtotal', } } @columns };
1352 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $totals{$_}, 2) } @subtotal_columns;
1354 $report->add_separator();
1355 $report->add_data($row);
1358 $report->generate_with_headers();
1360 $lxdebug->leave_sub();
1361 } #end generate_report
1363 sub parts_subtotal {
1364 $lxdebug->enter_sub();
1366 $auth->assert('part_service_assembly_edit');
1369 my ($column_index, $subtotalonhand, $subtotalsellprice, $subtotallastcost, $subtotallistprice) = @_;
1371 map { $column_data{$_} = "<td> </td>" } @{ $column_index };
1372 $$subtotalonhand = 0 if ($form->{searchitems} eq 'assembly' && $form->{bom});
1374 $column_data{onhand} =
1375 "<th class=listsubtotal align=right>"
1376 . $form->format_amount(\%myconfig, $$subtotalonhand)
1379 $column_data{linetotalsellprice} =
1380 "<th class=listsubtotal align=right>"
1381 . $form->format_amount(\%myconfig, $$subtotalsellprice, 2)
1383 $column_data{linetotallistprice} =
1384 "<th class=listsubtotal align=right>"
1385 . $form->format_amount(\%myconfig, $$subtotallistprice, 2)
1387 $column_data{linetotallastcost} =
1388 "<th class=listsubtotal align=right>"
1389 . $form->format_amount(\%myconfig, $$subtotallastcost, 2)
1392 $$subtotalonhand = 0;
1393 $$subtotalsellprice = 0;
1394 $$subtotallistprice = 0;
1395 $$subtotallastcost = 0;
1397 print "<tr class=listsubtotal>";
1399 map { print "\n$column_data{$_}" } @{ $column_index };
1405 $lxdebug->leave_sub();
1409 $lxdebug->enter_sub();
1411 $auth->assert('part_service_assembly_edit');
1413 # show history button
1414 $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
1415 #/show hhistory button
1416 IC->get_part(\%myconfig, \%$form);
1418 $form->{"original_partnumber"} = $form->{"partnumber"};
1420 $form->{title} = $locale->text('Edit ' . ucfirst $form->{item});
1425 $lxdebug->leave_sub();
1429 $lxdebug->enter_sub();
1431 $auth->assert('part_service_assembly_edit');
1433 IC->create_links("IC", \%myconfig, \%$form);
1436 map({ $form->{selectcurrency} .= "<option>$_\n" }
1437 split(/:/, $form->{currencies}));
1439 # parts and assemblies have the same links
1440 my $item = $form->{item};
1441 if ($form->{item} eq 'assembly') {
1445 # build the popup menus
1446 $form->{taxaccounts} = "";
1447 foreach my $key (keys %{ $form->{IC_links} }) {
1448 foreach my $ref (@{ $form->{IC_links}{$key} }) {
1450 # if this is a tax field
1451 if ($key =~ /IC_tax/) {
1452 if ($key =~ /\Q$item\E/) {
1453 $form->{taxaccounts} .= "$ref->{accno} ";
1454 $form->{"IC_tax_$ref->{accno}_description"} =
1455 "$ref->{accno}--$ref->{description}";
1458 if ($form->{amount}{ $ref->{accno} }) {
1459 $form->{"IC_tax_$ref->{accno}"} = "checked";
1462 $form->{"IC_tax_$ref->{accno}"} = "checked";
1467 $form->{"select$key"} .=
1468 "<option $ref->{selected}>$ref->{accno}--$ref->{description}\n";
1469 if ($form->{amount}{$key} eq $ref->{accno}) {
1470 $form->{$key} = "$ref->{accno}--$ref->{description}";
1476 chop $form->{taxaccounts};
1478 if (($form->{item} eq "part") || ($form->{item} eq "assembly")) {
1479 $form->{selectIC_income} = $form->{selectIC_sale};
1480 $form->{selectIC_expense} = $form->{selectIC_cogs};
1481 $form->{IC_income} = $form->{IC_sale};
1482 $form->{IC_expense} = $form->{IC_cogs};
1485 delete $form->{IC_links};
1486 delete $form->{amount};
1488 $form->get_partsgroup(\%myconfig, { all => 1 });
1490 $form->{partsgroup} = "$form->{partsgroup}--$form->{partsgroup_id}";
1492 if (@{ $form->{all_partsgroup} }) {
1493 $form->{selectpartsgroup} = qq|<option>\n|;
1494 map { $form->{selectpartsgroup} .= qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n| } @{ $form->{all_partsgroup} };
1497 if ($form->{item} eq 'assembly') {
1499 foreach my $i (1 .. $form->{assembly_rows}) {
1500 if ($form->{"partsgroup_id_$i"}) {
1501 $form->{"partsgroup_$i"} =
1502 qq|$form->{"partsgroup_$i"}--$form->{"partsgroup_id_$i"}|;
1505 $form->get_partsgroup(\%myconfig);
1507 if (@{ $form->{all_partsgroup} }) {
1508 $form->{selectassemblypartsgroup} = qq|<option>\n|;
1511 $form->{selectassemblypartsgroup} .=
1512 qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n|
1513 } @{ $form->{all_partsgroup} };
1516 $lxdebug->leave_sub();
1520 $lxdebug->enter_sub();
1522 $auth->assert('part_service_assembly_edit');
1524 $form->{eur} = $main::eur; # config dumps into namespace - yuck
1525 $form->{pg_keys} = sub { "$_[0]->{partsgroup}--$_[0]->{id}" };
1526 $form->{description_area} = ($form->{rows} = $form->numtextrows($form->{description}, 40)) > 1;
1527 $form->{notes_rows} = max 4, $form->numtextrows($form->{notes}, 40), $form->numtextrows($form->{formel}, 40);
1529 map { $form->{"is_$_"} = ($form->{item} eq $_) } qw(part service assembly);
1530 map { $form->{$_} =~ s/"/"/g; } qw(unit);
1532 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
1533 'partsgroup' => 'all_partsgroup',
1534 'vendors' => 'ALL_VENDORS',);
1537 IC->retrieve_buchungsgruppen(\%myconfig, $form);
1538 @{ $form->{BUCHUNGSGRUPPEN} } = grep { $_->{id} eq $form->{buchungsgruppen_id} || ($form->{id} && $form->{orphaned}) || !$form->{id} } @{ $form->{BUCHUNGSGRUPPEN} };
1540 # use JavaScript Calendar or not (yes!)
1541 $form->{jsscript} = 1;
1543 my $units = AM->retrieve_units(\%myconfig, $form);
1544 $form->{ALL_UNITS} = [ map +{ name => $_ }, sort { $units->{$a}{sortkey} <=> $units->{$b}{sortkey} } keys %$units ];
1546 $form->{defaults} = AM->get_defaults();
1548 $form->{fokus} = "ic.partnumber";
1550 $form->{CUSTOM_VARIABLES} = CVar->get_custom_variables('module' => 'IC', 'trans_id' => $form->{id});
1552 CVar->render_inputs('variables' => $form->{CUSTOM_VARIABLES}, show_disabled_message => 1)
1553 if (scalar @{ $form->{CUSTOM_VARIABLES} });
1556 #print $form->parse_html_template('ic/form_header', { ALL_PRICE_FACTORS => $form->{ALL_PRICE_FACTORS},
1557 # ALL_UNITS => $form->{ALL_UNITS},
1558 # BUCHUNGSGRUPPEN => $form->{BUCHUNGSGRUPPEN},
1559 # payment_terms => $form->{payment_terms},
1560 # all_partsgroup => $form->{all_partsgroup}});
1561 print $form->parse_html_template('ic/form_header');
1562 $lxdebug->leave_sub();
1566 $lxdebug->enter_sub();
1568 $auth->assert('part_service_assembly_edit');
1570 print $form->parse_html_template('ic/form_footer');
1572 $lxdebug->leave_sub();
1576 $lxdebug->enter_sub();
1579 my @mm_data = grep { any { $_ ne '' } @$_{qw(make model)} } map +{ make => $form->{"make_$_"}, model => $form->{"model_$_"} }, 1 .. $numrows;
1580 delete @{$form}{grep { m/^make_\d+/ || m/^model_\d+/ } keys %{ $form }};
1581 print $form->parse_html_template('ic/makemodel', { MM_DATA => [ @mm_data, {} ], mm_rows => scalar @mm_data + 1 });
1583 $lxdebug->leave_sub();
1587 $lxdebug->enter_sub();
1590 my ($nochange, $callback, $previousform, $linetotal, $line_purchase_price, $href);
1592 @column_index = qw(runningnumber qty unit bom partnumber description partsgroup lastcost total);
1594 if ($form->{previousform}) {
1596 @column_index = qw(qty unit bom partnumber description partsgroup total);
1600 $form->{old_callback} = $form->{callback};
1601 $callback = $form->{callback};
1602 $form->{callback} = "$form->{script}?action=display_form";
1605 map { delete $form->{$_} } qw(action header);
1607 # save form variables in a previousform variable
1608 $previousform = $form->escape($form->escape(join '&', map {
1609 sprintf "%s=%s", Q($_), /^listprice|lastcost|sellprice$/ ? $form->format_amount(\%myconfig, $form->{$_}) : $form->{$_}
1610 } grep { ref $form->{$_} eq '' && $form->{$_} } grep { !/^select/ } sort keys %$form ));
1612 $form->{callback} = $callback;
1613 $form->{assemblytotal} = 0;
1614 $form->{assembly_purchase_price_total} = 0;
1615 $form->{weight} = 0;
1619 runningnumber => { text => $locale->text('No.'), nowrap => 1, width => '5%' },
1620 qty => { text => $locale->text('Qty'), nowrap => 1, width => '10%' },
1621 unit => { text => $locale->text('Unit'), nowrap => 1, width => '5%' },
1622 partnumber => { text => $locale->text('Part Number'), nowrap => 1, width => '20%' },
1623 description => { text => $locale->text('Part Description'), nowrap => 1, width => '50%' },
1624 lastcost => { text => $locale->text('Purchase Prices'), nowrap => 1, width => '50%' },
1625 total => { text => $locale->text('Sale Prices'), nowrap => 1, },
1626 bom => { text => $locale->text('BOM'), },
1627 partsgroup => { text => $locale->text('Group'), },
1632 for my $i (1 .. $numrows) {
1633 my (%row, @row_hiddens);
1635 $form->{"partnumber_$i"} =~ s/\"/"/g;
1637 $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1638 $line_purchase_price = $form->round_amount($form->{"lastcost_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1639 $form->{assemblytotal} += $linetotal;
1640 $form->{assembly_purchase_price_total} += $line_purchase_price;
1641 $form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
1642 $linetotal = $form->format_amount(\%myconfig, $linetotal, 2);
1643 $line_purchase_price = $form->format_amount(\%myconfig, $line_purchase_price, 2);
1644 $href = qq|$form->{script}?action=edit&id=$form->{"id_$i"}&rowcount=$i&previousform=$previousform|;
1645 map { $row{$_}{data} = "" } qw(qty unit partnumber description bom partsgroup runningnumber);
1648 if (($i >= 1) && ($i == $numrows)) {
1649 if (!$form->{previousform}) {
1650 $row{partnumber}{data} = qq|<input name="partnumber_$i" size=15 value="$form->{"partnumber_$i"}">|;
1651 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1652 $row{description}{data} = qq|<input name="description_$i" size=40 value="$form->{"description_$i"}">|;
1653 $row{partsgroup}{data} = qq|<input name="partsgroup_$i" size=10 value="$form->{"partsgroup_$i"}">|;
1657 if ($form->{previousform}) {
1658 push @row_hiddens, qw(qty bom);
1659 $row{partnumber}{data} = $form->{"partnumber_$i"};
1660 $row{qty}{data} = $form->{"qty_$i"};
1661 $row{bom}{data} = $form->{"bom_$i"} ? "x" : " ";
1662 $row{qty}{align} = 'right';
1664 $row{partnumber}{data} = qq|<a href=$href>$form->{"partnumber_$i"}</a>|;
1665 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1666 $row{runningnumber}{data} = qq|<input name="runningnumber_$i" size=3 value="$i">|;
1667 $row{bom}{data} = sprintf qq|<input name="bom_$i" type=checkbox class=checkbox value=1 %s>|,
1668 $form->{"bom_$i"} ? 'checked' : '';
1670 push @row_hiddens, qw(unit description partnumber partsgroup);
1671 $row{unit}{data} = $form->{"unit_$i"};
1672 $row{description}{data} = $form->{"description_$i"};
1673 $row{partsgroup}{data} = $form->{"partsgroup_$i"};
1674 $row{bom}{align} = 'center';
1677 $row{lastcost}{data} = $line_purchase_price;
1678 $row{total}{data} = $linetotal;
1679 $row{lastcost}{align} = 'right';
1680 $row{total}{align} = 'right';
1681 $row{deliverydate}{align} = 'right';
1683 push @row_hiddens, qw(id sellprice lastcost weight price_factor_id price_factor);
1684 $row{hiddens} = [ map +{ name => "${_}_$i", value => $form->{"${_}_$i"} }, @row_hiddens ];
1689 print $form->parse_html_template('ic/assembly_row', { COLUMNS => \@column_index, ROWS => \@ROWS, HEADER => \%header });
1691 $lxdebug->leave_sub();
1695 $lxdebug->enter_sub();
1697 # parse pricegroups. and no, don't rely on check_form for this...
1698 map { $form->{"price_$_"} = $form->parse_amount(\%myconfig, $form->{"price_$_"}) } 1 .. $form->{price_rows};
1700 if ($form->{item} eq "assembly") {
1701 my $i = $form->{assembly_rows};
1703 # if last row is empty check the form otherwise retrieve item
1704 if ( ($form->{"partnumber_$i"} eq "")
1705 && ($form->{"description_$i"} eq "")
1706 && ($form->{"partsgroup_$i"} eq "")) {
1712 IC->assembly_item(\%myconfig, \%$form);
1714 my $rows = scalar @{ $form->{item_list} };
1717 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1720 $form->{makemodel_rows}--;
1724 map { $form->{item_list}[$i]{$_} =~ s/\"/"/g }
1725 qw(partnumber description unit partsgroup);
1726 map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} }
1727 keys %{ $form->{item_list}[0] };
1728 $form->{"runningnumber_$i"} = $form->{assembly_rows};
1729 $form->{assembly_rows}++;
1737 $form->{rowcount} = $i;
1738 $form->{assembly_rows}++;
1745 } elsif (($form->{item} eq 'part') || ($form->{item} eq 'service')) {
1749 $lxdebug->leave_sub();
1753 $lxdebug->enter_sub();
1755 $auth->assert('part_service_assembly_edit');
1757 my ($parts_id, %newform, $previousform, $amount, $callback);
1759 # check if there is a part number - commented out, cause there is an automatic allocation of numbers
1760 # $form->isblank("partnumber", $locale->text(ucfirst $form->{item}." Part Number missing!"));
1762 # check if there is a description
1763 $form->isblank("description", $locale->text("Part Description missing!"));
1765 $form->error($locale->text("Inventory quantity must be zero before you can set this $form->{item} obsolete!"))
1766 if $form->{obsolete} && $form->{onhand} * 1 && $form->{item} ne 'service';
1768 if (!$form->{buchungsgruppen_id}) {
1769 $form->error($locale->text("Parts must have an entry type.") . " " .
1770 $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.")
1774 $form->error($locale->text('Description must not be empty!')) unless $form->{description};
1775 $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
1778 $lxdebug->message($LXDebug::DEBUG1, "ic.pl: sellprice in save = $form->{sellprice}\n");
1779 if (IC->save(\%myconfig, \%$form) == 3) {
1780 $form->error($locale->text('Partnumber not unique!'));
1782 # saving the history
1783 if(!exists $form->{addition}) {
1784 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1785 $form->{addition} = "SAVED";
1786 $form->save_history;
1788 # /saving the history
1789 $parts_id = $form->{id};
1792 # load previous variables
1793 if ($form->{previousform}) {
1795 # save the new form variables before splitting previousform
1796 map { $newform{$_} = $form->{$_} } keys %$form;
1798 $previousform = $form->unescape($form->{previousform});
1800 # don't trample on previous variables
1801 map { delete $form->{$_} } keys %newform;
1803 my $ic_cvar_configs = CVar->get_configs(module => 'IC');
1804 my @ic_cvar_fields = map { "cvar_$_->{name}" } @{ $ic_cvar_configs };
1806 # now take it apart and restore original values
1807 foreach my $item (split /&/, $previousform) {
1808 my ($key, $value) = split m/=/, $item, 2;
1809 $value =~ s/%26/&/g;
1810 $form->{$key} = $value;
1812 $form->{taxaccounts} = $newform{taxaccount2};
1814 if ($form->{item} eq 'assembly') {
1816 # undo number formatting
1817 map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
1818 qw(weight listprice sellprice rop);
1820 $form->{assembly_rows}--;
1821 $i = $newform{rowcount};
1822 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1824 $form->{sellprice} -= $form->{"sellprice_$i"} * $form->{"qty_$i"};
1825 $form->{weight} -= $form->{"weight_$i"} * $form->{"qty_$i"};
1827 # change/add values for assembly item
1828 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit weight listprice sellprice inventory_accno income_accno expense_accno price_factor_id);
1829 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1831 # das ist __voll__ bekloppt, dass so auszurechnen jb 22.5.09
1832 #$form->{sellprice} += $form->{"sellprice_$i"} * $form->{"qty_$i"};
1833 $form->{weight} += $form->{"weight_$i"} * $form->{"qty_$i"};
1837 # set values for last invoice/order item
1838 $i = $form->{rowcount};
1839 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1841 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit listprice inventory_accno income_accno expense_accno sellprice lastcost price_factor_id);
1842 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1844 $form->{"longdescription_$i"} = $newform{notes};
1846 $form->{"sellprice_$i"} = $newform{lastcost} if ($form->{vendor_id});
1848 if ($form->{exchangerate} != 0) {
1849 $form->{"sellprice_$i"} /= $form->{exchangerate};
1852 $lxdebug->message($LXDebug::DEBUG1, qq|sellprice_$i in previousform 2 = | . $form->{"sellprice_$i"} . qq|\n|);
1854 map { $form->{"taxaccounts_$i"} .= "$_ " } split / /, $newform{taxaccount};
1855 chop $form->{"taxaccounts_$i"};
1856 foreach my $item (qw(description rate taxnumber)) {
1857 my $index = $form->{"taxaccounts_$i"} . "_$item";
1858 $form->{$index} = $newform{$index};
1861 # credit remaining calculation
1862 $amount = $form->{"sellprice_$i"} * (1 - $form->{"discount_$i"} / 100) * $form->{"qty_$i"};
1864 map { $form->{"${_}_base"} += $amount } (split / /, $form->{"taxaccounts_$i"});
1865 map { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) } split / /, $form->{"taxaccounts_$i"} if !$form->{taxincluded};
1867 $form->{creditremaining} -= $amount;
1869 # redo number formatting, because invoice parse them!
1870 map { $form->{"${_}_$i"} = $form->format_amount(\%myconfig, $form->{"${_}_$i"}) } qw(weight listprice sellprice lastcost rop);
1873 $form->{"id_$i"} = $parts_id;
1875 # Get the actual price factor (not just the ID) for the marge calculation.
1876 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
1877 foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
1878 next if ($pfac->{id} != $newform{price_factor_id});
1879 $form->{"marge_price_factor_$i"} = $pfac->{factor};
1882 delete $form->{ALL_PRICE_FACTORS};
1884 delete $form->{action};
1886 # restore original callback
1887 $callback = $form->unescape($form->{callback});
1888 $form->{callback} = $form->unescape($form->{old_callback});
1889 delete $form->{old_callback};
1891 $form->{makemodel_rows}--;
1893 # put callback together
1894 foreach my $key (keys %$form) {
1896 # do single escape for Apache 2.0
1897 my $value = $form->escape($form->{$key}, 1);
1898 $callback .= qq|&$key=$value|;
1900 $form->{callback} = $callback;
1902 $lxdebug->message($LXDebug::DEBUG1, qq|ic.pl: sellprice_$i nach sub save = | . $form->{"sellprice_$i"} . qq|\n|);
1907 $lxdebug->leave_sub();
1911 $lxdebug->enter_sub();
1913 $auth->assert('part_service_assembly_edit');
1915 # saving the history
1916 if(!exists $form->{addition}) {
1917 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1918 $form->{addition} = "SAVED AS NEW";
1919 $form->save_history;
1921 # /saving the history
1923 if ($form->{"original_partnumber"} &&
1924 ($form->{"partnumber"} eq $form->{"original_partnumber"})) {
1925 $form->{partnumber} = "";
1928 $lxdebug->leave_sub();
1932 $lxdebug->enter_sub();
1934 $auth->assert('part_service_assembly_edit');
1936 # saving the history
1937 if(!exists $form->{addition}) {
1938 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1939 $form->{addition} = "DELETED";
1940 $form->save_history;
1942 # /saving the history
1943 my $rc = IC->delete(\%myconfig, \%$form);
1946 $form->redirect($locale->text('Item deleted!')) if ($rc > 0);
1947 $form->error($locale->text('Cannot delete item!'));
1949 $lxdebug->leave_sub();
1953 $lxdebug->enter_sub();
1955 $auth->assert('part_service_assembly_edit');
1960 pricegroup => $form->{"pricegroup_$_"},
1961 pricegroup_id => $form->{"pricegroup_id_$_"},
1962 price => $form->{"price_$_"},
1965 print $form->parse_html_template('ic/price_row', { PRICES => \@PRICES });
1967 $lxdebug->leave_sub();
1970 sub parts_language_selection {
1971 $lxdebug->enter_sub();
1973 $auth->assert('part_service_assembly_edit');
1975 my $languages = IC->retrieve_languages(\%myconfig, $form);
1977 if ($form->{language_values} ne "") {
1978 foreach my $item (split(/---\+\+\+---/, $form->{language_values})) {
1979 my ($language_id, $translation, $longdescription) = split(/--\+\+--/, $item);
1981 foreach my $language (@{ $languages }) {
1982 next unless ($language->{id} == $language_id);
1984 $language->{translation} = $translation;
1985 $language->{longdescription} = $longdescription;
1991 my @header_sort = qw(name longdescription);
1992 my %header_title = ( "name" => $locale->text("Name"),
1993 "longdescription" => $locale->text("Long Description"),
1997 map(+{ "column_title" => $header_title{$_},
2002 $form->{"title"} = $locale->text("Language Values");
2004 print $form->parse_html_template("ic/parts_language_selection", { "HEADER" => \@header,
2005 "LANGUAGES" => $languages, });
2007 $lxdebug->leave_sub();
2010 sub ajax_autocomplete {
2011 $main::lxdebug->enter_sub();
2013 my $form = $main::form;
2014 my %myconfig = %main::myconfig;
2016 $form->{column} = 'description' unless $form->{column} =~ /^partnumber|description$/;
2017 $form->{$form->{column}} = $form->{q} || '';
2018 $form->{limit} = ($form->{limit} * 1) || 10;
2019 $form->{searchitems} ||= '';
2021 my @results = IC->all_parts(\%myconfig, $form);
2023 print $form->ajax_response_header(),
2024 $form->parse_html_template('ic/ajax_autocomplete');
2026 $main::lxdebug->leave_sub();
2029 sub continue { call_sub($form->{"nextsub"}); }