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 my $title = 'Add ' . ucfirst $form->{item};
82 $form->{title} = $locale->text($title);
83 $form->{callback} = "$form->{script}?action=add&item=$form->{item}" unless $form->{callback};
84 $form->{unit_changeable} = 1;
86 IC->get_pricegroups(\%myconfig, \%$form);
90 $lxdebug->leave_sub();
94 $lxdebug->enter_sub();
96 $auth->assert('part_service_assembly_edit');
98 $form->{revers} = 0; # switch for backward sorting
99 $form->{lastsort} = ""; # memory for which table was sort at last time
100 $form->{ndxs_counter} = 0; # counter for added entries to top100
102 my %is_xyz = map { +"is_$_" => ($form->{searchitems} eq $_) } qw(part service assembly);
104 $form->{title} = (ucfirst $form->{searchitems}) . "s";
105 $form->{title} = $locale->text($form->{title});
106 $form->{title} = $locale->text('Assemblies') if ($is_xyz{is_assembly});
108 $form->{jsscript} = 1;
110 $form->{CUSTOM_VARIABLES} = CVar->get_configs('module' => 'IC');
111 ($form->{CUSTOM_VARIABLES_FILTER_CODE},
112 $form->{CUSTOM_VARIABLES_INCLUSION_CODE}) = CVar->render_search_options('variables' => $form->{CUSTOM_VARIABLES},
113 'include_prefix' => 'l_',
114 'include_value' => 'Y');
118 print $form->parse_html_template('ic/search', { %is_xyz,
119 dateformat => $myconfig{dateformat}, });
121 $lxdebug->leave_sub();
124 sub search_update_prices {
125 $lxdebug->enter_sub();
127 $auth->assert('part_service_assembly_edit');
129 my $pricegroups = IC->get_pricegroups(\%myconfig, \%$form);
131 $form->{title} = $locale->text('Update Prices');
135 print $form->parse_html_template('ic/search_update_prices', { PRICE_ROWS => $pricegroups });
137 $lxdebug->leave_sub();
140 sub confirm_price_update {
141 $lxdebug->enter_sub();
143 $auth->assert('part_service_assembly_edit');
146 my $value_found = undef;
148 foreach my $idx (qw(sellprice listprice), (1..$form->{price_rows})) {
149 my $name = $idx =~ m/\d/ ? $form->{"pricegroup_${idx}"} : $idx eq 'sellprice' ? $locale->text('Sell Price') : $locale->text('List Price');
150 my $type = $idx =~ m/\d/ ? $form->{"pricegroup_type_${idx}"} : $form->{"${idx}_type"};
151 my $value_idx = $idx =~ m/\d/ ? "price_${idx}" : $idx;
152 my $value = $form->parse_amount(\%myconfig, $form->{$value_idx});
154 if ((0 > $value) && ($type eq 'percent')) {
155 push @errors, $locale->text('You cannot adjust the price for pricegroup "#1" by a negative percentage.', $name);
157 } elsif (!$value && ($form->{$value_idx} ne '')) {
158 push @errors, $locale->text('No valid number entered for pricegroup "#1".', $name);
160 } elsif (0 < $value) {
165 push @errors, $locale->text('No prices will be updated because no prices have been entered.') if (!$value_found);
167 my $num_matches = IC->get_num_matches_for_priceupdate();
172 $form->show_generic_error(join('<br>', @errors), 'back_button' => 1);
175 $form->{nextsub} = "update_prices";
177 map { delete $form->{$_} } qw(action header);
179 print $form->parse_html_template('ic/confirm_price_update', { HIDDENS => [ map { name => $_, value => $form->{$_} }, keys %$form ],
180 num_matches => $num_matches });
182 $lxdebug->leave_sub();
186 $lxdebug->enter_sub();
188 $auth->assert('part_service_assembly_edit');
190 my $num_updated = IC->update_prices(\%myconfig, \%$form);
192 if (-1 != $num_updated) {
193 $form->redirect($locale->text('#1 prices were updated.', $num_updated));
195 $form->error($locale->text('Could not update prices!'));
198 $lxdebug->leave_sub();
202 # $lxdebug->enter_sub();
204 # $auth->assert('part_service_assembly_edit');
206 # our ($j, $lastndx);
209 # $form->{title} = $locale->text('Top 100 hinzufuegen');
213 # push @custom_hiddens, qw(searchitems title bom titel revers lastsort sort ndxs_counter extras);
214 # push @custom_hiddens, qw(itemstatus l_linetotal l_partnumber l_description l_onhand l_unit l_sellprice l_linetotalsellprice);
216 # +{ name => 'row', value => $j },
217 # +{ name => 'nextsub', value => 'item_selected' },
218 # +{ name => 'test', value => 'item_selected' },
219 # +{ name => 'lastndx', value => $lastndx },
220 # map(+{ name => $_, value => $form->{$_} }, @custom_hiddens),
223 # my ($partnumber, $description, $unit, $sellprice, $soldtotal);
224 # # if choice set data
225 ## if ($form->{ndx}) {
226 ## for my $i (0 .. $form->{ndxs_counter}) {
228 ## # insert data into top100
229 ## push @{ $form->{parts} },
231 ## partnumber => $form->{"totop100_partnumber_$j"},
232 ## description => $form->{"totop100_description_$j"},
233 ## unit => $form->{"totop100_unit_$j"},
234 ## sellprice => $form->{"totop100_sellprice_$j"},
235 ## soldtotal => $form->{"totop100_soldtotal_$j"},
242 # # set data for next page
243 # for my $i (1 .. $form->{ndxs_counter}) {
244 # $partnumber = $form->{"totop100_partnumber_$i"};
245 # $description = $form->{"totop100_description_$i"};
246 # $unit = $form->{"totop100_unit_$i"};
247 # $sellprice = $form->{"totop100_sellprice_$i"};
248 # $soldtotal = $form->{"totop100_soldtotal_$i"};
251 # totop100_partnumber => $form->{"totop100_partnumber_$i"},
252 # totop100_description => $form->{"totop100_description_$i"},
253 # totop100_unit => $form->{"totop100_unit_$i"},
254 # totop100_sellprice => $form->{"totop100_sellprice_$i"},
255 # totop100_soldtotal => $form->{"totop100_soldtotal_$i"},
259 ##<input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
260 ##<input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
261 ##<input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
262 ##<input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
263 ##<input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
267 # print $form->parse_html_template('ic/choice', +{ HIDDENS => \@HIDDENS, PARTS => \@PARTS });
269 # $lxdebug->leave_sub();
273 # $lxdebug->enter_sub();
275 # $auth->assert('part_service_assembly_edit');
278 # our ($partnumber, $description, $unit, $sellprice, $soldtotal);
280 # my @sortorders = ("", "partnumber", "description", "all");
281 # my $sortorder = $sortorders[($form->{description} ? 2 : 0) + ($form->{partnumber} ? 1 : 0)];
282 # IC->get_parts(\%myconfig, \%$form, $sortorder);
284 # $form->{title} = $locale->text('Top 100 hinzufuegen');
290 # <form method=post action=ic.pl>
293 # <th class=listtop colspan=6>| . $locale->text('choice part') . qq|</th>
295 # <tr height="5"></tr>
296 # <tr class=listheading>
298 # <th class=listheading>| . $locale->text('Part Number') . qq|</th>
299 # <th class=listheading>| . $locale->text('Part Description') . qq|</th>
300 # <th class=listheading>| . $locale->text('Unit of measure') . qq|</th>
301 # <th class=listheading>| . $locale->text('Sell Price') . qq|</th>
302 # <th class=listheading>| . $locale->text('soldtotal') . qq|</th>
306 # my $i = $form->{rows};
308 # for ($j = 1; $j <= $i; $j++) {
311 # <tr class=listrow| . ($j % 2) . qq|>|;
314 # <td><input name=ndx class=radio type=radio value=$j checked></td>|;
317 # <td><input name=ndx class=radio type=radio value=$j></td>|;
320 # <td><input name="new_partnumber_$j" type=hidden value="$form->{"partnumber_$j"}">$form->{"partnumber_$j"}</td>
321 # <td><input name="new_description_$j" type=hidden value="$form->{"description_$j"}">$form->{"description_$j"}</td>
322 # <td><input name="new_unit_$j" type=hidden value="$form->{"unit_$j"}">$form->{"unit_$j"}</td>
323 # <td><input name="new_sellprice_$j" type=hidden value="$form->{"sellprice_$j"}">$form->{"sellprice_$j"}</td>
324 # <td><input name="new_soldtotal_$j" type=hidden value="$form->{"soldtotal_$j"}">$form->{"soldtotal_$j"}</td>
327 # <input name="new_id_$j" type=hidden value="$form->{"id_$j"}">|;
337 #<input type=hidden name=itemstatus value="$form->{itemstatus}">
338 #<input type=hidden name=l_linetotal value="$form->{l_linetotal}">
339 #<input type=hidden name=l_partnumber value="$form->{l_partnumber}">
340 #<input type=hidden name=l_description value="$form->{l_description}">
341 #<input type=hidden name=l_onhand value="$form->{l_onhand}">
342 #<input type=hidden name=l_unit value="$form->{l_unit}">
343 #<input type=hidden name=l_sellprice value="$form->{l_sellprice}">
344 #<input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
345 #<input type=hidden name=sort value="$form->{sort}">
346 #<input type=hidden name=revers value="$form->{revers}">
347 #<input type=hidden name=lastsort value="$form->{lastsort}">
349 #<input type=hidden name=bom value="$form->{bom}">
350 #<input type=hidden name=titel value="$form->{titel}">
351 #<input type=hidden name=searchitems value="$form->{searchitems}">
353 #<input type=hidden name=row value=$j>
355 #<input type=hidden name=nextsub value=item_selected>
357 #<input name=lastndx type=hidden value=$lastndx>
359 #<input name=ndxs_counter type=hidden value=$form->{ndxs_counter}>|;
363 # if (($form->{ndxs_counter}) > 0) {
364 # for ($i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
366 # $partnumber = $form->{"totop100_partnumber_$i"};
367 # $description = $form->{"totop100_description_$i"};
368 # $unit = $form->{"totop100_unit_$i"};
369 # $sellprice = $form->{"totop100_sellprice_$i"};
370 # $soldtotal = $form->{"totop100_soldtotal_$i"};
373 #<input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
374 #<input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
375 #<input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
376 #<input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
377 #<input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
385 #<input class=submit type=submit name=action value="|
386 # . $locale->text('TOP100') . qq|">
392 # $lxdebug->leave_sub();
396 $lxdebug->enter_sub();
398 $auth->assert('part_service_assembly_edit');
401 $form->{ndxs_counter}++;
403 if ($form->{ndxs_counter} > 0) {
405 my $index = $form->{ndx};
407 $form->{"totop100_partnumber_$form->{ndxs_counter}"} = $form->{"new_partnumber_$index"};
408 $form->{"totop100_description_$form->{ndxs_counter}"} = $form->{"new_description_$index"};
409 $form->{"totop100_unit_$form->{ndxs_counter}"} = $form->{"new_unit_$index"};
410 $form->{"totop100_sellprice_$form->{ndxs_counter}"} = $form->{"new_sellprice_$index"};
411 $form->{"totop100_soldtotal_$form->{ndxs_counter}"} = $form->{"new_soldtotal_$index"};
415 $lxdebug->leave_sub();
419 $lxdebug->enter_sub();
421 $auth->assert('part_service_assembly_edit');
423 my ($revers, $lastsort, $callback, $option, $description, $sameitem,
424 $partnumber, $unit, $sellprice, $soldtotal, $totop100, $onhand, $align);
425 my (@column_index, %column_header, %column_data);
426 my ($totalsellprice, $totallastcost, $totallistprice, $subtotalonhand, $subtotalsellprice, $subtotallastcost, $subtotallistprice);
428 $form->{top100} = "top100";
429 $form->{l_soldtotal} = "Y";
430 $form->{soldtotal} = "soldtotal";
431 $form->{sort} = "soldtotal";
432 $form->{l_qty} = "N";
433 $form->{l_linetotal} = "";
435 $form->{number} = "position";
436 $form->{l_number} = "Y";
440 $form->{title} = $locale->text('Top 100');
442 $revers = $form->{revers};
443 $lastsort = $form->{lastsort};
445 if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
447 $form->{lastsort} = "partnumber";
448 $form->{sort} = "partnumber";
452 "$form->{script}?action=top100&searchitems=$form->{searchitems}&itemstatus=$form->{itemstatus}&bom=$form->{bom}&l_linetotal=$form->{l_linetotal}&title="
453 . $form->escape($form->{title}, 1);
455 # if we have a serialnumber limit search
456 if ($form->{serialnumber} || $form->{l_serialnumber}) {
457 $form->{l_serialnumber} = "Y";
458 unless ( $form->{bought}
461 || $form->{quoted}) {
462 $form->{bought} = $form->{sold} = 1;
465 IC->all_parts(\%myconfig, \%$form);
467 if ($form->{itemstatus} eq 'active') {
468 $option .= $locale->text('Active') . " : ";
470 if ($form->{itemstatus} eq 'obsolete') {
471 $option .= $locale->text('Obsolete') . " : ";
473 if ($form->{itemstatus} eq 'orphaned') {
474 $option .= $locale->text('Orphaned') . " : ";
476 if ($form->{itemstatus} eq 'onhand') {
477 $option .= $locale->text('On Hand') . " : ";
478 $form->{l_onhand} = "Y";
480 if ($form->{itemstatus} eq 'short') {
481 $option .= $locale->text('Short') . " : ";
482 $form->{l_onhand} = "Y";
484 if ($form->{onorder}) {
485 $form->{l_ordnumber} = "Y";
486 $callback .= "&onorder=$form->{onorder}";
487 $option .= $locale->text('On Order') . " : ";
489 if ($form->{ordered}) {
490 $form->{l_ordnumber} = "Y";
491 $callback .= "&ordered=$form->{ordered}";
492 $option .= $locale->text('Ordered') . " : ";
495 $form->{l_quonumber} = "Y";
496 $callback .= "&rfq=$form->{rfq}";
497 $option .= $locale->text('RFQ') . " : ";
499 if ($form->{quoted}) {
500 $form->{l_quonumber} = "Y";
501 $callback .= ""ed=$form->{quoted}";
502 $option .= $locale->text('Quoted') . " : ";
504 if ($form->{bought}) {
505 $form->{l_invnumber} = "Y";
506 $callback .= "&bought=$form->{bought}";
507 $option .= $locale->text('Bought') . " : ";
510 $form->{l_invnumber} = "Y";
511 $callback .= "&sold=$form->{sold}";
512 $option .= $locale->text('Sold') . " : ";
519 || $form->{quoted}) {
521 $form->{l_lastcost} = "";
522 $form->{l_name} = "Y";
523 if ($form->{transdatefrom}) {
524 $callback .= "&transdatefrom=$form->{transdatefrom}";
526 . $locale->text('From')
528 . $locale->date(\%myconfig, $form->{transdatefrom}, 1);
530 if ($form->{transdateto}) {
531 $callback .= "&transdateto=$form->{transdateto}";
533 . $locale->text('To')
535 . $locale->date(\%myconfig, $form->{transdateto}, 1);
541 if ($form->{partnumber}) {
542 $callback .= "&partnumber=$form->{partnumber}";
543 $option .= $locale->text('Part Number') . qq| : $form->{partnumber}<br>|;
546 $callback .= "&partnumber=$form->{ean}";
547 $option .= $locale->text('EAN') . qq| : $form->{ean}<br>|;
549 if ($form->{partsgroup}) {
550 $callback .= "&partsgroup=$form->{partsgroup}";
551 $option .= $locale->text('Group') . qq| : $form->{partsgroup}<br>|;
553 if ($form->{serialnumber}) {
554 $callback .= "&serialnumber=$form->{serialnumber}";
555 $option .= $locale->text('Serial Number') . qq| : $form->{serialnumber}<br>|;
557 if ($form->{description}) {
558 $callback .= "&description=$form->{description}";
559 $description = $form->{description};
560 $description =~ s/\n/<br>/g;
561 $option .= $locale->text('Part Description') . qq| : $form->{description}<br>|;
564 $callback .= "&make=$form->{make}";
565 $option .= $locale->text('Make') . qq| : $form->{make}<br>|;
567 if ($form->{model}) {
568 $callback .= "&model=$form->{model}";
569 $option .= $locale->text('Model') . qq| : $form->{model}<br>|;
571 if ($form->{drawing}) {
572 $callback .= "&drawing=$form->{drawing}";
573 $option .= $locale->text('Drawing') . qq| : $form->{drawing}<br>|;
575 if ($form->{microfiche}) {
576 $callback .= "µfiche=$form->{microfiche}";
577 $option .= $locale->text('Microfiche') . qq| : $form->{microfiche}<br>|;
579 if ($form->{l_soldtotal}) {
580 $callback .= "&soldtotal=$form->{soldtotal}";
581 $option .= $locale->text('soldtotal') . qq| : $form->{soldtotal}<br>|;
584 my @columns = $form->sort_columns(
585 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)
588 if ($form->{l_linetotal}) {
589 $form->{l_onhand} = "Y";
590 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
591 if ($form->{l_lastcost}) {
592 $form->{l_linetotallastcost} = "Y";
593 if (($form->{searchitems} eq 'assembly') && !$form->{bom}) {
594 $form->{l_linetotallastcost} = "";
597 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
600 if ($form->{searchitems} eq 'service') {
602 # remove bin, weight and rop from list
603 map { $form->{"l_$_"} = "" } qw(bin weight rop);
605 $form->{l_onhand} = "";
607 # qty is irrelevant unless bought or sold
613 || $form->{quoted}) {
614 $form->{l_onhand} = "Y";
616 $form->{l_linetotalsellprice} = "";
617 $form->{l_linetotallastcost} = "";
621 foreach my $item (@columns) {
622 if ($form->{"l_$item"} eq "Y") {
623 push @column_index, $item;
625 # add column to callback
626 $callback .= "&l_$item=Y";
630 if ($form->{l_subtotal} eq 'Y') {
631 $callback .= "&l_subtotal=Y";
634 $column_header{number} =
635 qq|<th class=listheading nowrap>| . $locale->text('number') . qq|</th>|;
636 $column_header{partnumber} =
637 qq|<th nowrap><a class=listheading href=$callback&sort=partnumber&revers=$form->{revers}&lastsort=$form->{lastsort}>|
638 . $locale->text('Part Number')
640 $column_header{description} =
641 qq|<th nowrap><a class=listheading href=$callback&sort=description&revers=$form->{revers}&lastsort=$form->{lastsort}>|
642 . $locale->text('Part Description')
644 $column_header{partsgroup} =
645 qq|<th nowrap><a class=listheading href=$callback&sort=partsgroup>|
646 . $locale->text('Group')
648 $column_header{bin} =
649 qq|<th><a class=listheading href=$callback&sort=bin>|
650 . $locale->text('Bin')
652 $column_header{priceupdate} =
653 qq|<th nowrap><a class=listheading href=$callback&sort=priceupdate>|
654 . $locale->text('Updated')
656 $column_header{onhand} =
657 qq|<th nowrap><a class=listheading href=$callback&sort=onhand&revers=$form->{revers}&lastsort=$form->{lastsort}>|
658 . $locale->text('Qty')
660 $column_header{unit} =
661 qq|<th class=listheading nowrap>| . $locale->text('Unit') . qq|</th>|;
662 $column_header{listprice} =
663 qq|<th class=listheading nowrap>|
664 . $locale->text('List Price')
666 $column_header{lastcost} =
667 qq|<th class=listheading nowrap>| . $locale->text('Last Cost') . qq|</th>|;
668 $column_header{rop} =
669 qq|<th class=listheading nowrap>| . $locale->text('ROP') . qq|</th>|;
670 $column_header{weight} =
671 qq|<th class=listheading nowrap>| . $locale->text('Weight') . qq|</th>|;
673 $column_header{invnumber} =
674 qq|<th nowrap><a class=listheading href=$callback&sort=invnumber>|
675 . $locale->text('Invoice Number')
677 $column_header{ordnumber} =
678 qq|<th nowrap><a class=listheading href=$callback&sort=ordnumber>|
679 . $locale->text('Order Number')
681 $column_header{quonumber} =
682 qq|<th nowrap><a class=listheading href=$callback&sort=quonumber>|
683 . $locale->text('Quotation')
686 $column_header{name} =
687 qq|<th nowrap><a class=listheading href=$callback&sort=name>|
688 . $locale->text('Name')
691 $column_header{sellprice} =
692 qq|<th class=listheading nowrap>|
693 . $locale->text('Sell Price')
695 $column_header{linetotalsellprice} =
696 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
697 $column_header{linetotallastcost} =
698 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
699 $column_header{linetotallistprice} =
700 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
702 $column_header{image} =
703 qq|<th class=listheading nowrap>| . $locale->text('Image') . qq|</a></th>|;
704 $column_header{drawing} =
705 qq|<th nowrap><a class=listheading href=$callback&sort=drawing>|
706 . $locale->text('Drawing')
708 $column_header{microfiche} =
709 qq|<th nowrap><a class=listheading href=$callback&sort=microfiche>|
710 . $locale->text('Microfiche')
713 $column_header{serialnumber} =
714 qq|<th nowrap><a class=listheading href=$callback&sort=serialnumber>|
715 . $locale->text('Serial Number')
717 $column_header{soldtotal} =
718 qq|<th nowrap><a class=listheading href=$callback&sort=soldtotal&revers=$form->{revers}&lastsort=$form->{lastsort}>|
719 . $locale->text('soldtotal')
723 my $colspan = $#column_index + 1;
730 <th class=listtop colspan=$colspan>$form->{title}</th>
734 <tr><td colspan=$colspan>$option</td></tr>
736 <tr class=listheading>
739 map { print "\n$column_header{$_}" } @column_index;
745 # add order to callback
746 $form->{callback} = $callback .= "&sort=$form->{sort}";
748 # escape callback for href
749 $callback = $form->escape($callback);
751 if (@{ $form->{parts} }) {
752 $sameitem = $form->{parts}->[0]->{ $form->{sort} };
755 # insert numbers for top100
757 foreach my $ref (@{ $form->{parts} }) {
762 # if avaible -> insert choice here
763 if (($form->{ndxs_counter}) > 0) {
764 for (my $i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
765 $partnumber = $form->{"totop100_partnumber_$i"};
766 $description = $form->{"totop100_description_$i"};
767 $unit = $form->{"totop100_unit_$i"};
768 $sellprice = $form->{"totop100_sellprice_$i"};
769 $soldtotal = $form->{"totop100_soldtotal_$i"};
772 <input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
773 <input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
774 <input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
775 <input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
776 <input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
780 push @{ $form->{parts} },
782 partnumber => "$partnumber",
783 description => "$description",
785 sellprice => "$sellprice",
786 soldtotal => "$soldtotal" };
789 # build data for columns
791 foreach my $ref (@{ $form->{parts} }) {
793 if ($form->{l_subtotal} eq 'Y' && !$ref->{assemblyitem}) {
794 if ($sameitem ne $ref->{ $form->{sort} }) {
795 parts_subtotal(\@column_index, \$subtotalonhand, \$subtotalsellprice, \$subtotallastcost, \$subtotallistprice);
796 $sameitem = $ref->{ $form->{sort} };
800 $ref->{exchangerate} = 1 unless $ref->{exchangerate};
801 $ref->{sellprice} *= $ref->{exchangerate};
802 $ref->{listprice} *= $ref->{exchangerate};
803 $ref->{lastcost} *= $ref->{exchangerate};
805 # use this for assemblies
806 $onhand = $ref->{onhand};
809 if ($ref->{assemblyitem}) {
811 $onhand = 0 if ($form->{sold});
814 $ref->{description} =~ s/\n/<br>/g;
816 $column_data{number} =
818 . $form->format_amount(\%myconfig, $ref->{number})
820 $column_data{partnumber} =
821 "<td align=$align>$ref->{partnumber} </a></td>";
822 $column_data{description} = "<td>$ref->{description} </td>";
823 $column_data{partsgroup} = "<td>$ref->{partsgroup} </td>";
825 $column_data{onhand} =
827 . $form->format_amount(\%myconfig, $ref->{onhand})
829 $column_data{sellprice} =
831 . $form->format_amount(\%myconfig, $ref->{sellprice})
833 $column_data{listprice} =
835 . $form->format_amount(\%myconfig, $ref->{listprice})
837 $column_data{lastcost} =
839 . $form->format_amount(\%myconfig, $ref->{lastcost})
842 $column_data{linetotalsellprice} = "<td align=right>"
843 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{sellprice}, 2)
845 $column_data{linetotallastcost} = "<td align=right>"
846 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{lastcost}, 2)
848 $column_data{linetotallistprice} = "<td align=right>"
849 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{listprice}, 2)
852 if (!$ref->{assemblyitem}) {
853 $totalsellprice += $onhand * $ref->{sellprice};
854 $totallastcost += $onhand * $ref->{lastcost};
855 $totallistprice += $onhand * $ref->{listprice};
857 $subtotalonhand += $onhand;
858 $subtotalsellprice += $onhand * $ref->{sellprice};
859 $subtotallastcost += $onhand * $ref->{lastcost};
860 $subtotallistprice += $onhand * $ref->{listprice};
865 . $form->format_amount(\%myconfig, $ref->{rop}) . "</td>";
866 $column_data{weight} =
868 . $form->format_amount(\%myconfig, $ref->{weight})
870 $column_data{unit} = "<td>$ref->{unit} </td>";
871 $column_data{bin} = "<td>$ref->{bin} </td>";
872 $column_data{priceupdate} = "<td>$ref->{priceupdate} </td>";
874 $column_data{invnumber} =
875 ($ref->{module} ne 'oe')
876 ? "<td><a href=$ref->{module}.pl?action=edit&type=invoice&id=$ref->{trans_id}&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}&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}&callback=$callback>$ref->{quonumber}</a></td>"
885 : "<td>$ref->{quonumber}</td>";
887 $column_data{name} = "<td>$ref->{name}</td>";
889 $column_data{image} =
891 ? "<td><a href=$ref->{image}><img src=$ref->{image} height=32 border=0></a></td>"
893 $column_data{drawing} =
895 ? "<td><a href=$ref->{drawing}>$ref->{drawing}</a></td>"
897 $column_data{microfiche} =
899 ? "<td><a href=$ref->{microfiche}>$ref->{microfiche}</a></td>"
902 $column_data{serialnumber} = "<td>$ref->{serialnumber}</td>";
904 $column_data{soldtotal} = "<td align=right>$ref->{soldtotal}</td>";
908 print "<tr class=listrow$i>";
910 map { print "\n$column_data{$_}" } @column_index;
917 if ($form->{l_subtotal} eq 'Y') {
918 parts_subtotal(\@column_index, \$subtotalonhand, \$subtotalsellprice, \$subtotallastcost, \$subtotallistprice);
921 if ($form->{"l_linetotal"}) {
922 map { $column_data{$_} = "<td> </td>" } @column_index;
923 $column_data{linetotalsellprice} =
924 "<th class=listtotal align=right>"
925 . $form->format_amount(\%myconfig, $totalsellprice, 2)
927 $column_data{linetotallastcost} =
928 "<th class=listtotal align=right>"
929 . $form->format_amount(\%myconfig, $totallastcost, 2)
931 $column_data{linetotallistprice} =
932 "<th class=listtotal align=right>"
933 . $form->format_amount(\%myconfig, $totallistprice, 2)
936 print "<tr class=listtotal>";
938 map { print "\n$column_data{$_}" } @column_index;
945 <tr><td colspan=$colspan><hr size=3 noshade></td></tr>
954 <form method=post action=$form->{script}>
956 <input type=hidden name=itemstatus value="$form->{itemstatus}">
957 <input type=hidden name=l_linetotal value="$form->{l_linetotal}">
958 <input type=hidden name=l_partnumber value="$form->{l_partnumber}">
959 <input type=hidden name=l_description value="$form->{l_description}">
960 <input type=hidden name=l_onhand value="$form->{l_onhand}">
961 <input type=hidden name=l_unit value="$form->{l_unit}">
962 <input type=hidden name=l_sellprice value="$form->{l_sellprice}">
963 <input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
964 <input type=hidden name=sort value="$form->{sort}">
965 <input type=hidden name=revers value="$form->{revers}">
966 <input type=hidden name=lastsort value="$form->{lastsort}">
967 <input type=hidden name=parts value="$form->{parts}">
969 <input type=hidden name=bom value="$form->{bom}">
970 <input type=hidden name=titel value="$form->{titel}">
971 <input type=hidden name=searchitems value="$form->{searchitems}">|;
976 <!-- <input type=hidden name=ndxs_counter value="$form->{ndxs_counter}">-->
978 <input class=submit type=submit name=action value="|
979 . $locale->text('choice') . qq|">
987 $lxdebug->leave_sub();
992 # Warning, deep magic ahead.
993 # This function parses the requested details, sanity checks them, and converts them into a format thats usable for IC->all_parts
995 # flags coming from the form:
997 # searchitems=part revers=0 lastsort=''
1000 # partnumber ean description partsgroup serialnumber make model drawing microfiche
1001 # transdatefrom transdateto
1004 # itemstatus = active | onhand | short | obsolete | orphaned
1005 # action = continue | top100
1008 # bought sold onorder ordered rfq quoted
1009 # l_partnumber l_description l_serialnumber l_unit l_listprice l_sellprice l_lastcost
1010 # l_linetotal l_priceupdate l_bin l_rop l_weight l_image l_drawing l_microfiche
1011 # l_partsgroup l_subtotal l_soldtotal l_deliverydate
1014 # nextsub revers lastsort sort ndxs_counter
1016 sub generate_report {
1017 $lxdebug->enter_sub();
1019 $auth->assert('part_service_assembly_edit');
1021 my ($revers, $lastsort, $description);
1023 my $cvar_configs = CVar->get_configs('module' => 'IC');
1025 $form->{title} = (ucfirst $form->{searchitems}) . "s";
1026 $form->{title} =~ s/ys$/ies/;
1027 $form->{title} = $locale->text($form->{title});
1030 'bin' => { 'text' => $locale->text('Bin'), },
1031 'deliverydate' => { 'text' => $locale->text('deliverydate'), },
1032 'description' => { 'text' => $locale->text('Part Description'), },
1033 'drawing' => { 'text' => $locale->text('Drawing'), },
1034 'image' => { 'text' => $locale->text('Image'), },
1035 'invnumber' => { 'text' => $locale->text('Invoice Number'), },
1036 'lastcost' => { 'text' => $locale->text('Last Cost'), },
1037 'linetotallastcost' => { 'text' => $locale->text('Extended'), },
1038 'linetotallistprice' => { 'text' => $locale->text('Extended'), },
1039 'linetotalsellprice' => { 'text' => $locale->text('Extended'), },
1040 'listprice' => { 'text' => $locale->text('List Price'), },
1041 'microfiche' => { 'text' => $locale->text('Microfiche'), },
1042 'name' => { 'text' => $locale->text('Name'), },
1043 'onhand' => { 'text' => $locale->text('Qty'), },
1044 'ordnumber' => { 'text' => $locale->text('Order Number'), },
1045 'partnumber' => { 'text' => $locale->text('Part Number'), },
1046 'partsgroup' => { 'text' => $locale->text('Group'), },
1047 'priceupdate' => { 'text' => $locale->text('Updated'), },
1048 'quonumber' => { 'text' => $locale->text('Quotation'), },
1049 'rop' => { 'text' => $locale->text('ROP'), },
1050 'sellprice' => { 'text' => $locale->text('Sell Price'), },
1051 'serialnumber' => { 'text' => $locale->text('Serial Number'), },
1052 'soldtotal' => { 'text' => $locale->text('soldtotal'), },
1053 'transdate' => { 'text' => $locale->text('Transdate'), },
1054 'unit' => { 'text' => $locale->text('Unit'), },
1055 'weight' => { 'text' => $locale->text('Weight'), },
1058 $revers = $form->{revers};
1059 $lastsort = $form->{lastsort};
1061 # sorting and direction of sorting
1062 # ToDO: change this to the simpler field+direction method
1063 if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
1064 $form->{revers} = 0;
1065 $form->{lastsort} = "partnumber";
1066 $form->{sort} = "partnumber";
1068 if ($form->{lastsort} eq $form->{sort}) {
1069 $form->{revers} = 1 - $form->{revers};
1071 $form->{revers} = 0;
1072 $form->{lastsort} = $form->{sort};
1076 # special case if we have a serialnumber limit search
1077 # serialnumbers are only given in invoices and orders,
1078 # so they can only pop up in bought, sold, rfq, and quoted stuff
1079 $form->{no_sn_joins} = 'Y' if ( !$form->{bought} && !$form->{sold}
1080 && !$form->{rfq} && !$form->{quoted}
1081 && ($form->{l_serialnumber} || $form->{serialnumber}));
1083 # special case for any checkbox of bought | sold | onorder | ordered | rfq | quoted.
1084 # if any of these are ticked the behavior changes slightly for lastcost
1085 # since all those are aggregation checks for the legder tables this is an internal switch
1086 # refered to as ledgerchecks
1087 $form->{ledgerchecks} = 'Y' if ( $form->{bought} || $form->{sold} || $form->{onorder}
1088 || $form->{ordered} || $form->{rfq} || $form->{quoted});
1090 # if something should be activated if something else is active, enter it here
1091 my %dependencies = (
1092 onhand => [ qw(l_onhand) ],
1093 short => [ qw(l_onhand) ],
1094 onorder => [ qw(l_ordnumber) ],
1095 ordered => [ qw(l_ordnumber) ],
1096 rfq => [ qw(l_quonumber) ],
1097 quoted => [ qw(l_quonumber) ],
1098 bought => [ qw(l_invnumber) ],
1099 sold => [ qw(l_invnumber) ],
1100 ledgerchecks => [ qw(l_name) ],
1101 serialnumber => [ qw(l_serialnumber) ],
1102 no_sn_joins => [ qw(bought sold) ],
1105 # these strings get displayed at the top of the results to indicate the user which switches were used
1107 active => $locale->text('Active'),
1108 obsolete => $locale->text('Obsolete'),
1109 orphaned => $locale->text('Orphaned'),
1110 onhand => $locale->text('On Hand'),
1111 short => $locale->text('Short'),
1112 onorder => $locale->text('On Order'),
1113 ordered => $locale->text('Ordered'),
1114 rfq => $locale->text('RFQ'),
1115 quoted => $locale->text('Quoted'),
1116 bought => $locale->text('Bought'),
1117 sold => $locale->text('Sold'),
1118 transdatefrom => $locale->text('From') . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1),
1119 transdateto => $locale->text('To (time)') . " " . $locale->date(\%myconfig, $form->{transdateto}, 1),
1120 partnumber => $locale->text('Part Number') . ": '$form->{partnumber}'",
1121 partsgroup => $locale->text('Group') . ": '$form->{partsgroup}'",
1122 serialnumber => $locale->text('Serial Number') . ": '$form->{serialnumber}'",
1123 description => $locale->text('Part Description') . ": '$form->{description}'",
1124 make => $locale->text('Make') . ": '$form->{make}'",
1125 model => $locale->text('Model') . ": '$form->{model}'",
1126 drawing => $locale->text('Drawing') . ": '$form->{drawing}'",
1127 microfiche => $locale->text('Microfiche') . ": '$form->{microfiche}'",
1128 l_soldtotal => $locale->text('soldtotal'),
1129 ean => $locale->text('EAN') . ": '$form->{ean}'",
1132 my @itemstatus_keys = qw(active obsolete orphaned onhand short);
1133 my @callback_keys = qw(onorder ordered rfq quoted bought sold partnumber partsgroup serialnumber description make model
1134 drawing microfiche l_soldtotal l_deliverydate transdatefrom transdateto ean);
1136 # calculate dependencies
1137 for (@itemstatus_keys, @callback_keys) {
1138 next if ($form->{itemstatus} ne $_ && !$form->{$_});
1139 map { $form->{$_} = 'Y' } @{ $dependencies{$_} } if $dependencies{$_};
1142 # generate callback and optionstrings
1144 for my $key (@itemstatus_keys, @callback_keys) {
1145 next if ($form->{itemstatus} ne $key && !$form->{$key});
1146 push @options, $optiontexts{$key};
1149 # special case for lastcost
1150 if ($form->{ledgerchecks}){
1151 # ledgerchecks don't know about sellprice or lastcost. they just return a
1152 # price. so rename sellprice to price, and drop lastcost.
1153 $column_defs{sellprice}{text} = $locale->text('Price');
1154 $form->{l_lastcost} = ""
1157 if ($form->{description}) {
1158 $description = $form->{description};
1159 $description =~ s/\n/<br>/g;
1162 if ($form->{l_linetotal}) {
1163 $form->{l_onhand} = "Y";
1164 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
1165 $form->{l_linetotallastcost} = $form->{searchitems} eq 'assembly' && !$form->{bom} ? "" : 'Y' if $form->{l_lastcost};
1166 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
1169 if ($form->{searchitems} eq 'service') {
1171 # remove bin, weight and rop from list
1172 map { $form->{"l_$_"} = "" } qw(bin weight rop);
1174 $form->{l_onhand} = "";
1176 # qty is irrelevant unless bought or sold
1177 if ( $form->{bought}
1182 || $form->{quoted}) {
1183 $form->{l_onhand} = "Y";
1185 $form->{l_linetotalsellprice} = "";
1186 $form->{l_linetotallastcost} = "";
1190 IC->all_parts(\%myconfig, \%$form);
1193 partnumber description partsgroup bin onhand rop unit listprice
1194 linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
1195 priceupdate weight image drawing microfiche invnumber ordnumber quonumber
1196 transdate name serialnumber soldtotal deliverydate ean
1199 my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
1200 my @searchable_custom_variables = grep { $_->{searchable} } @{ $cvar_configs };
1201 my %column_defs_cvars = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables;
1203 push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
1205 %column_defs = (%column_defs,%column_defs_cvars); # nochmal die cvars als überschrift hinzufügen
1206 map { $column_defs{$_}->{visible} = $form->{"l_$_"} ? 1 : 0 } @columns;
1207 map { $column_defs{$_}->{align} = 'right' } qw(onhand sellprice listprice lastcost linetotalsellprice linetotallastcost linetotallistprice rop weight soldtotal);
1209 my @hidden_variables = (qw(l_subtotal l_linetotal searchitems itemstatus bom), @itemstatus_keys, @callback_keys, @searchable_custom_variables, map { "l_$_" } @columns);
1210 my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
1212 my @sort_full = qw(partnumber description onhand soldtotal deliverydate);
1213 my @sort_no_revers = qw(partsgroup bin priceupdate invnumber ordnumber quonumber name image drawing serialnumber);
1215 foreach my $col (@sort_full) {
1216 $column_defs{$col}->{link} = join '&', $callback, "sort=$col", map { "$_=" . E($form->{$_}) } qw(revers lastsort);
1218 map { $column_defs{$_}->{link} = "${callback}&sort=$_" } @sort_no_revers;
1220 # add order to callback
1221 $form->{callback} = join '&', ($callback, map { "${_}=" . E($form->{$_}) } qw(sort revers));
1223 my $report = SL::ReportGenerator->new(\%myconfig, $form);
1225 my %attachment_basenames = (
1226 'part' => $locale->text('part_list'),
1227 'service' => $locale->text('service_list'),
1228 'assembly' => $locale->text('assembly_list'),
1231 $report->set_options('top_info_text' => $locale->text('Options') . ': ' . join(', ', grep $_, @options),
1232 'raw_bottom_info_text' => $form->parse_html_template('ic/generate_report_bottom'),
1233 'output_format' => 'HTML',
1234 'title' => $form->{title},
1235 'attachment_basename' => $attachment_basenames{$form->{searchitems}} . strftime('_%Y%m%d', localtime time),
1237 $report->set_options_from_form();
1238 $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
1240 $report->set_columns(%column_defs);
1241 $report->set_column_order(@columns);
1243 $report->set_export_options('generate_report', @hidden_variables, qw(sort revers));
1245 $report->set_sort_indicator($form->{sort}, $form->{revers} ? 0 : 1);
1247 CVar->add_custom_variables_to_report('module' => 'IC',
1248 'trans_id_field' => 'id',
1249 'configs' => $cvar_configs,
1250 'column_defs' => \%column_defs,
1251 'data' => $form->{parts});
1253 CVar->add_custom_variables_to_report('module' => 'IC',
1254 'sub_module' => sub { $_[0]->{ioi} },
1255 'trans_id_field' => 'ioi_id',
1256 'configs' => $cvar_configs,
1257 'column_defs' => \%column_defs,
1258 'data' => $form->{parts});
1260 my @subtotal_columns = qw(sellprice listprice lastcost);
1261 my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
1262 my %totals = map { $_ => 0 } @subtotal_columns;
1264 my $same_item = $form->{parts}[0]{ $form->{sort} } if (scalar @{ $form->{parts} });
1266 my $defaults = AM->get_defaults();
1269 foreach my $ref (@{ $form->{parts} }) {
1271 # fresh row, for inserting later
1272 my $row = { map { $_ => { 'data' => $ref->{$_} } } @columns };
1274 $ref->{exchangerate} ||= 1;
1275 $ref->{price_factor} ||= 1;
1276 $ref->{sellprice} *= $ref->{exchangerate} / $ref->{price_factor};
1277 $ref->{listprice} *= $ref->{exchangerate} / $ref->{price_factor};
1278 $ref->{lastcost} *= $ref->{exchangerate} / $ref->{price_factor};
1280 # use this for assemblies
1281 my $onhand = $ref->{onhand};
1283 if ($ref->{assemblyitem}) {
1284 $row->{partnumber}{align} = 'right';
1285 $row->{onhand}{data} = 0;
1286 $onhand = 0 if ($form->{sold});
1289 my $edit_link = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
1290 $row->{partnumber}->{link} = $edit_link;
1291 $row->{description}->{link} = $edit_link;
1293 foreach (qw(sellprice listprice lastcost)) {
1294 $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}, -2);
1295 $row->{"linetotal$_"}{data} = $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{$_}, 2);
1298 map { $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}); } qw(onhand rop weight soldtotal);
1300 $row->{weight}->{data} .= ' ' . $defaults->{weightunit};
1302 if (!$ref->{assemblyitem}) {
1303 foreach my $col (@subtotal_columns) {
1304 $totals{$col} += $onhand * $ref->{$col};
1305 $subtotals{$col} += $onhand * $ref->{$col};
1308 $subtotals{onhand} += $onhand;
1312 if ($ref->{module} eq 'oe') {
1313 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');
1314 $row->{ordnumber}{link} = $edit_oe_link;
1315 $row->{quonumber}{link} = $edit_oe_link if (!$ref->{ordnumber});
1318 $row->{invnumber}{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'type=invoice', 'id=' . E($ref->{trans_id}), 'callback');
1321 # set properties of images
1322 if ($ref->{image} && (lc $report->{options}->{output_format} eq 'html')) {
1323 $row->{image}{data} = '';
1324 $row->{image}{raw_data} = '<a href="' . H($ref->{image}) . '"><img src="' . H($ref->{image}) . '" height="32" border="0"></a>';
1326 map { $row->{$_}{link} = $ref->{$_} } qw(drawing microfiche);
1328 $report->add_data($row);
1330 my $next_ref = $form->{parts}[$idx + 1];
1332 # insert subtotal rows
1333 if (($form->{l_subtotal} eq 'Y') &&
1335 (!$next_ref->{assemblyitem} && ($same_item ne $next_ref->{ $form->{sort} })))) {
1336 my $row = { map { $_ => { 'class' => 'listsubtotal', } } @columns };
1338 if (($form->{searchitems} ne 'assembly') || !$form->{bom}) {
1339 $row->{onhand}->{data} = $form->format_amount(\%myconfig, $subtotals{onhand});
1342 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $subtotals{$_}, 2) } @subtotal_columns;
1343 map { $subtotals{$_} = 0 } ('onhand', @subtotal_columns);
1345 $report->add_data($row);
1347 $same_item = $next_ref->{ $form->{sort} };
1353 if ($form->{"l_linetotal"}) {
1354 my $row = { map { $_ => { 'class' => 'listtotal', } } @columns };
1356 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $totals{$_}, 2) } @subtotal_columns;
1358 $report->add_separator();
1359 $report->add_data($row);
1362 $report->generate_with_headers();
1364 $lxdebug->leave_sub();
1365 } #end generate_report
1367 sub parts_subtotal {
1368 $lxdebug->enter_sub();
1370 $auth->assert('part_service_assembly_edit');
1373 my ($column_index, $subtotalonhand, $subtotalsellprice, $subtotallastcost, $subtotallistprice) = @_;
1375 map { $column_data{$_} = "<td> </td>" } @{ $column_index };
1376 $$subtotalonhand = 0 if ($form->{searchitems} eq 'assembly' && $form->{bom});
1378 $column_data{onhand} =
1379 "<th class=listsubtotal align=right>"
1380 . $form->format_amount(\%myconfig, $$subtotalonhand)
1383 $column_data{linetotalsellprice} =
1384 "<th class=listsubtotal align=right>"
1385 . $form->format_amount(\%myconfig, $$subtotalsellprice, 2)
1387 $column_data{linetotallistprice} =
1388 "<th class=listsubtotal align=right>"
1389 . $form->format_amount(\%myconfig, $$subtotallistprice, 2)
1391 $column_data{linetotallastcost} =
1392 "<th class=listsubtotal align=right>"
1393 . $form->format_amount(\%myconfig, $$subtotallastcost, 2)
1396 $$subtotalonhand = 0;
1397 $$subtotalsellprice = 0;
1398 $$subtotallistprice = 0;
1399 $$subtotallastcost = 0;
1401 print "<tr class=listsubtotal>";
1403 map { print "\n$column_data{$_}" } @{ $column_index };
1409 $lxdebug->leave_sub();
1413 $lxdebug->enter_sub();
1415 $auth->assert('part_service_assembly_edit');
1417 # show history button
1418 $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
1419 #/show hhistory button
1420 IC->get_part(\%myconfig, \%$form);
1422 $form->{"original_partnumber"} = $form->{"partnumber"};
1424 my $title = 'Edit ' . ucfirst $form->{item};
1425 $form->{title} = $locale->text($title);
1430 $lxdebug->leave_sub();
1434 $lxdebug->enter_sub();
1436 $auth->assert('part_service_assembly_edit');
1438 IC->create_links("IC", \%myconfig, \%$form);
1441 map({ $form->{selectcurrency} .= "<option>$_\n" }
1442 split(/:/, $form->{currencies}));
1444 # parts and assemblies have the same links
1445 my $item = $form->{item};
1446 if ($form->{item} eq 'assembly') {
1450 # build the popup menus
1451 $form->{taxaccounts} = "";
1452 foreach my $key (keys %{ $form->{IC_links} }) {
1453 foreach my $ref (@{ $form->{IC_links}{$key} }) {
1455 # if this is a tax field
1456 if ($key =~ /IC_tax/) {
1457 if ($key =~ /\Q$item\E/) {
1458 $form->{taxaccounts} .= "$ref->{accno} ";
1459 $form->{"IC_tax_$ref->{accno}_description"} =
1460 "$ref->{accno}--$ref->{description}";
1463 if ($form->{amount}{ $ref->{accno} }) {
1464 $form->{"IC_tax_$ref->{accno}"} = "checked";
1467 $form->{"IC_tax_$ref->{accno}"} = "checked";
1472 $form->{"select$key"} .=
1473 "<option $ref->{selected}>$ref->{accno}--$ref->{description}\n";
1474 if ($form->{amount}{$key} eq $ref->{accno}) {
1475 $form->{$key} = "$ref->{accno}--$ref->{description}";
1481 chop $form->{taxaccounts};
1483 if (($form->{item} eq "part") || ($form->{item} eq "assembly")) {
1484 $form->{selectIC_income} = $form->{selectIC_sale};
1485 $form->{selectIC_expense} = $form->{selectIC_cogs};
1486 $form->{IC_income} = $form->{IC_sale};
1487 $form->{IC_expense} = $form->{IC_cogs};
1490 delete $form->{IC_links};
1491 delete $form->{amount};
1493 $form->get_partsgroup(\%myconfig, { all => 1 });
1495 $form->{partsgroup} = "$form->{partsgroup}--$form->{partsgroup_id}";
1497 if (@{ $form->{all_partsgroup} }) {
1498 $form->{selectpartsgroup} = qq|<option>\n|;
1499 map { $form->{selectpartsgroup} .= qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n| } @{ $form->{all_partsgroup} };
1502 if ($form->{item} eq 'assembly') {
1504 foreach my $i (1 .. $form->{assembly_rows}) {
1505 if ($form->{"partsgroup_id_$i"}) {
1506 $form->{"partsgroup_$i"} =
1507 qq|$form->{"partsgroup_$i"}--$form->{"partsgroup_id_$i"}|;
1510 $form->get_partsgroup(\%myconfig);
1512 if (@{ $form->{all_partsgroup} }) {
1513 $form->{selectassemblypartsgroup} = qq|<option>\n|;
1516 $form->{selectassemblypartsgroup} .=
1517 qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n|
1518 } @{ $form->{all_partsgroup} };
1521 $lxdebug->leave_sub();
1525 $lxdebug->enter_sub();
1527 $auth->assert('part_service_assembly_edit');
1529 $form->{eur} = $main::eur; # config dumps into namespace - yuck
1530 $form->{pg_keys} = sub { "$_[0]->{partsgroup}--$_[0]->{id}" };
1531 $form->{description_area} = ($form->{rows} = $form->numtextrows($form->{description}, 40)) > 1;
1532 $form->{notes_rows} = max 4, $form->numtextrows($form->{notes}, 40), $form->numtextrows($form->{formel}, 40);
1534 map { $form->{"is_$_"} = ($form->{item} eq $_) } qw(part service assembly);
1535 map { $form->{$_} =~ s/"/"/g; } qw(unit);
1537 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
1538 'partsgroup' => 'all_partsgroup',
1539 'vendors' => 'ALL_VENDORS',);
1542 IC->retrieve_buchungsgruppen(\%myconfig, $form);
1543 @{ $form->{BUCHUNGSGRUPPEN} } = grep { $_->{id} eq $form->{buchungsgruppen_id} || ($form->{id} && $form->{orphaned}) || !$form->{id} } @{ $form->{BUCHUNGSGRUPPEN} };
1545 # use JavaScript Calendar or not (yes!)
1546 $form->{jsscript} = 1;
1548 my $units = AM->retrieve_units(\%myconfig, $form);
1549 $form->{ALL_UNITS} = [ map +{ name => $_ }, sort { $units->{$a}{sortkey} <=> $units->{$b}{sortkey} } keys %$units ];
1551 $form->{defaults} = AM->get_defaults();
1553 $form->{fokus} = "ic.partnumber";
1555 $form->{CUSTOM_VARIABLES} = CVar->get_custom_variables('module' => 'IC', 'trans_id' => $form->{id});
1557 CVar->render_inputs('variables' => $form->{CUSTOM_VARIABLES}, show_disabled_message => 1)
1558 if (scalar @{ $form->{CUSTOM_VARIABLES} });
1561 #print $form->parse_html_template('ic/form_header', { ALL_PRICE_FACTORS => $form->{ALL_PRICE_FACTORS},
1562 # ALL_UNITS => $form->{ALL_UNITS},
1563 # BUCHUNGSGRUPPEN => $form->{BUCHUNGSGRUPPEN},
1564 # payment_terms => $form->{payment_terms},
1565 # all_partsgroup => $form->{all_partsgroup}});
1566 print $form->parse_html_template('ic/form_header');
1567 $lxdebug->leave_sub();
1571 $lxdebug->enter_sub();
1573 $auth->assert('part_service_assembly_edit');
1575 print $form->parse_html_template('ic/form_footer');
1577 $lxdebug->leave_sub();
1581 $lxdebug->enter_sub();
1584 my @mm_data = grep { any { $_ ne '' } @$_{qw(make model)} } map +{ make => $form->{"make_$_"}, model => $form->{"model_$_"}, lastcost => $form->{"lastcost_$_"}, lastupdate => $form->{"lastupdate_$_"}, sortorder => $form->{"sortorder_$_"} }, 1 .. $numrows;
1585 delete @{$form}{grep { m/^make_\d+/ || m/^model_\d+/ } keys %{ $form }};
1586 print $form->parse_html_template('ic/makemodel', { MM_DATA => [ @mm_data, {} ], mm_rows => scalar @mm_data + 1 });
1588 $lxdebug->leave_sub();
1592 $lxdebug->enter_sub();
1595 my ($nochange, $callback, $previousform, $linetotal, $line_purchase_price, $href);
1597 @column_index = qw(runningnumber qty unit bom partnumber description partsgroup lastcost total);
1599 if ($form->{previousform}) {
1601 @column_index = qw(qty unit bom partnumber description partsgroup total);
1605 $form->{old_callback} = $form->{callback};
1606 $callback = $form->{callback};
1607 $form->{callback} = "$form->{script}?action=display_form";
1610 map { delete $form->{$_} } qw(action header);
1612 # save form variables in a previousform variable
1613 $previousform = $form->escape($form->escape(join '&', map {
1614 sprintf "%s=%s", Q($_), /^listprice|lastcost|sellprice$/ ? $form->format_amount(\%myconfig, $form->{$_}) : $form->{$_}
1615 } grep { ref $form->{$_} eq '' && $form->{$_} } grep { !/^select/ } sort keys %$form ));
1617 $form->{callback} = $callback;
1618 $form->{assemblytotal} = 0;
1619 $form->{assembly_purchase_price_total} = 0;
1620 $form->{weight} = 0;
1624 runningnumber => { text => $locale->text('No.'), nowrap => 1, width => '5%' },
1625 qty => { text => $locale->text('Qty'), nowrap => 1, width => '10%' },
1626 unit => { text => $locale->text('Unit'), nowrap => 1, width => '5%' },
1627 partnumber => { text => $locale->text('Part Number'), nowrap => 1, width => '20%' },
1628 description => { text => $locale->text('Part Description'), nowrap => 1, width => '50%' },
1629 lastcost => { text => $locale->text('Purchase Prices'), nowrap => 1, width => '50%' },
1630 total => { text => $locale->text('Sale Prices'), nowrap => 1, },
1631 bom => { text => $locale->text('BOM'), },
1632 partsgroup => { text => $locale->text('Group'), },
1637 for my $i (1 .. $numrows) {
1638 my (%row, @row_hiddens);
1640 $form->{"partnumber_$i"} =~ s/\"/"/g;
1642 $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1643 $line_purchase_price = $form->round_amount($form->{"lastcost_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1644 $form->{assemblytotal} += $linetotal;
1645 $form->{assembly_purchase_price_total} += $line_purchase_price;
1646 $form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
1647 $linetotal = $form->format_amount(\%myconfig, $linetotal, 2);
1648 $line_purchase_price = $form->format_amount(\%myconfig, $line_purchase_price, 2);
1649 $href = qq|$form->{script}?action=edit&id=$form->{"id_$i"}&rowcount=$i&previousform=$previousform|;
1650 map { $row{$_}{data} = "" } qw(qty unit partnumber description bom partsgroup runningnumber);
1653 if (($i >= 1) && ($i == $numrows)) {
1654 if (!$form->{previousform}) {
1655 $row{partnumber}{data} = qq|<input name="partnumber_$i" size=15 value="$form->{"partnumber_$i"}">|;
1656 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1657 $row{description}{data} = qq|<input name="description_$i" size=40 value="$form->{"description_$i"}">|;
1658 $row{partsgroup}{data} = qq|<input name="partsgroup_$i" size=10 value="$form->{"partsgroup_$i"}">|;
1662 if ($form->{previousform}) {
1663 push @row_hiddens, qw(qty bom);
1664 $row{partnumber}{data} = $form->{"partnumber_$i"};
1665 $row{qty}{data} = $form->{"qty_$i"};
1666 $row{bom}{data} = $form->{"bom_$i"} ? "x" : " ";
1667 $row{qty}{align} = 'right';
1669 $row{partnumber}{data} = qq|<a href=$href>$form->{"partnumber_$i"}</a>|;
1670 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1671 $row{runningnumber}{data} = qq|<input name="runningnumber_$i" size=3 value="$i">|;
1672 $row{bom}{data} = sprintf qq|<input name="bom_$i" type=checkbox class=checkbox value=1 %s>|,
1673 $form->{"bom_$i"} ? 'checked' : '';
1675 push @row_hiddens, qw(unit description partnumber partsgroup);
1676 $row{unit}{data} = $form->{"unit_$i"};
1677 $row{description}{data} = $form->{"description_$i"};
1678 $row{partsgroup}{data} = $form->{"partsgroup_$i"};
1679 $row{bom}{align} = 'center';
1682 $row{lastcost}{data} = $line_purchase_price;
1683 $row{total}{data} = $linetotal;
1684 $row{lastcost}{align} = 'right';
1685 $row{total}{align} = 'right';
1686 $row{deliverydate}{align} = 'right';
1688 push @row_hiddens, qw(id sellprice lastcost weight price_factor_id price_factor);
1689 $row{hiddens} = [ map +{ name => "${_}_$i", value => $form->{"${_}_$i"} }, @row_hiddens ];
1694 print $form->parse_html_template('ic/assembly_row', { COLUMNS => \@column_index, ROWS => \@ROWS, HEADER => \%header });
1696 $lxdebug->leave_sub();
1700 $lxdebug->enter_sub();
1702 # parse pricegroups. and no, don't rely on check_form for this...
1703 map { $form->{"price_$_"} = $form->parse_amount(\%myconfig, $form->{"price_$_"}) } 1 .. $form->{price_rows};
1705 if ($form->{item} eq "assembly") {
1706 my $i = $form->{assembly_rows};
1708 # if last row is empty check the form otherwise retrieve item
1709 if ( ($form->{"partnumber_$i"} eq "")
1710 && ($form->{"description_$i"} eq "")
1711 && ($form->{"partsgroup_$i"} eq "")) {
1717 IC->assembly_item(\%myconfig, \%$form);
1719 my $rows = scalar @{ $form->{item_list} };
1722 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1725 $form->{makemodel_rows}--;
1729 map { $form->{item_list}[$i]{$_} =~ s/\"/"/g }
1730 qw(partnumber description unit partsgroup);
1731 map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} }
1732 keys %{ $form->{item_list}[0] };
1733 $form->{"runningnumber_$i"} = $form->{assembly_rows};
1734 $form->{assembly_rows}++;
1742 $form->{rowcount} = $i;
1743 $form->{assembly_rows}++;
1750 } elsif (($form->{item} eq 'part') || ($form->{item} eq 'service')) {
1754 $lxdebug->leave_sub();
1758 $lxdebug->enter_sub();
1760 $auth->assert('part_service_assembly_edit');
1762 my ($parts_id, %newform, $previousform, $amount, $callback);
1764 # check if there is a part number - commented out, cause there is an automatic allocation of numbers
1765 # $form->isblank("partnumber", $locale->text(ucfirst $form->{item}." Part Number missing!"));
1767 # check if there is a description
1768 $form->isblank("description", $locale->text("Part Description missing!"));
1770 $form->error($locale->text("Inventory quantity must be zero before you can set this $form->{item} obsolete!"))
1771 if $form->{obsolete} && $form->{onhand} * 1 && $form->{item} ne 'service';
1773 if (!$form->{buchungsgruppen_id}) {
1774 $form->error($locale->text("Parts must have an entry type.") . " " .
1775 $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.")
1779 $form->error($locale->text('Description must not be empty!')) unless $form->{description};
1780 $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
1783 $lxdebug->message($LXDebug::DEBUG1, "ic.pl: sellprice in save = $form->{sellprice}\n");
1784 if (IC->save(\%myconfig, \%$form) == 3) {
1785 $form->error($locale->text('Partnumber not unique!'));
1787 # saving the history
1788 if(!exists $form->{addition}) {
1789 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1790 $form->{addition} = "SAVED";
1791 $form->save_history;
1793 # /saving the history
1794 $parts_id = $form->{id};
1797 # load previous variables
1798 if ($form->{previousform}) {
1800 # save the new form variables before splitting previousform
1801 map { $newform{$_} = $form->{$_} } keys %$form;
1803 $previousform = $form->unescape($form->{previousform});
1805 # don't trample on previous variables
1806 map { delete $form->{$_} } keys %newform;
1808 my $ic_cvar_configs = CVar->get_configs(module => 'IC');
1809 my @ic_cvar_fields = map { "cvar_$_->{name}" } @{ $ic_cvar_configs };
1811 # now take it apart and restore original values
1812 foreach my $item (split /&/, $previousform) {
1813 my ($key, $value) = split m/=/, $item, 2;
1814 $value =~ s/%26/&/g;
1815 $form->{$key} = $value;
1817 $form->{taxaccounts} = $newform{taxaccount2};
1819 if ($form->{item} eq 'assembly') {
1821 # undo number formatting
1822 map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
1823 qw(weight listprice sellprice rop);
1825 $form->{assembly_rows}--;
1826 $i = $newform{rowcount};
1827 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1829 $form->{sellprice} -= $form->{"sellprice_$i"} * $form->{"qty_$i"};
1830 $form->{weight} -= $form->{"weight_$i"} * $form->{"qty_$i"};
1832 # change/add values for assembly item
1833 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit weight listprice sellprice inventory_accno income_accno expense_accno price_factor_id);
1834 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1836 # das ist __voll__ bekloppt, dass so auszurechnen jb 22.5.09
1837 #$form->{sellprice} += $form->{"sellprice_$i"} * $form->{"qty_$i"};
1838 $form->{weight} += $form->{"weight_$i"} * $form->{"qty_$i"};
1842 # set values for last invoice/order item
1843 $i = $form->{rowcount};
1844 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1846 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit listprice inventory_accno income_accno expense_accno sellprice lastcost price_factor_id);
1847 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1849 $form->{"longdescription_$i"} = $newform{notes};
1851 $form->{"sellprice_$i"} = $newform{lastcost} if ($form->{vendor_id});
1853 if ($form->{exchangerate} != 0) {
1854 $form->{"sellprice_$i"} /= $form->{exchangerate};
1857 $lxdebug->message($LXDebug::DEBUG1, qq|sellprice_$i in previousform 2 = | . $form->{"sellprice_$i"} . qq|\n|);
1859 map { $form->{"taxaccounts_$i"} .= "$_ " } split / /, $newform{taxaccount};
1860 chop $form->{"taxaccounts_$i"};
1861 foreach my $item (qw(description rate taxnumber)) {
1862 my $index = $form->{"taxaccounts_$i"} . "_$item";
1863 $form->{$index} = $newform{$index};
1866 # credit remaining calculation
1867 $amount = $form->{"sellprice_$i"} * (1 - $form->{"discount_$i"} / 100) * $form->{"qty_$i"};
1869 map { $form->{"${_}_base"} += $amount } (split / /, $form->{"taxaccounts_$i"});
1870 map { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) } split / /, $form->{"taxaccounts_$i"} if !$form->{taxincluded};
1872 $form->{creditremaining} -= $amount;
1874 # redo number formatting, because invoice parse them!
1875 map { $form->{"${_}_$i"} = $form->format_amount(\%myconfig, $form->{"${_}_$i"}) } qw(weight listprice sellprice lastcost rop);
1878 $form->{"id_$i"} = $parts_id;
1880 # Get the actual price factor (not just the ID) for the marge calculation.
1881 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
1882 foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
1883 next if ($pfac->{id} != $newform{price_factor_id});
1884 $form->{"marge_price_factor_$i"} = $pfac->{factor};
1887 delete $form->{ALL_PRICE_FACTORS};
1889 delete $form->{action};
1891 # restore original callback
1892 $callback = $form->unescape($form->{callback});
1893 $form->{callback} = $form->unescape($form->{old_callback});
1894 delete $form->{old_callback};
1896 $form->{makemodel_rows}--;
1898 # put callback together
1899 foreach my $key (keys %$form) {
1901 # do single escape for Apache 2.0
1902 my $value = $form->escape($form->{$key}, 1);
1903 $callback .= qq|&$key=$value|;
1905 $form->{callback} = $callback;
1907 $lxdebug->message($LXDebug::DEBUG1, qq|ic.pl: sellprice_$i nach sub save = | . $form->{"sellprice_$i"} . qq|\n|);
1912 $lxdebug->leave_sub();
1916 $lxdebug->enter_sub();
1918 $auth->assert('part_service_assembly_edit');
1920 # saving the history
1921 if(!exists $form->{addition}) {
1922 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1923 $form->{addition} = "SAVED AS NEW";
1924 $form->save_history;
1926 # /saving the history
1928 if ($form->{"original_partnumber"} &&
1929 ($form->{"partnumber"} eq $form->{"original_partnumber"})) {
1930 $form->{partnumber} = "";
1933 $lxdebug->leave_sub();
1937 $lxdebug->enter_sub();
1939 $auth->assert('part_service_assembly_edit');
1941 # saving the history
1942 if(!exists $form->{addition}) {
1943 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1944 $form->{addition} = "DELETED";
1945 $form->save_history;
1947 # /saving the history
1948 my $rc = IC->delete(\%myconfig, \%$form);
1951 $form->redirect($locale->text('Item deleted!')) if ($rc > 0);
1952 $form->error($locale->text('Cannot delete item!'));
1954 $lxdebug->leave_sub();
1958 $lxdebug->enter_sub();
1960 $auth->assert('part_service_assembly_edit');
1965 pricegroup => $form->{"pricegroup_$_"},
1966 pricegroup_id => $form->{"pricegroup_id_$_"},
1967 price => $form->{"price_$_"},
1970 print $form->parse_html_template('ic/price_row', { PRICES => \@PRICES });
1972 $lxdebug->leave_sub();
1975 sub parts_language_selection {
1976 $lxdebug->enter_sub();
1978 $auth->assert('part_service_assembly_edit');
1980 my $languages = IC->retrieve_languages(\%myconfig, $form);
1982 if ($form->{language_values} ne "") {
1983 foreach my $item (split(/---\+\+\+---/, $form->{language_values})) {
1984 my ($language_id, $translation, $longdescription) = split(/--\+\+--/, $item);
1986 foreach my $language (@{ $languages }) {
1987 next unless ($language->{id} == $language_id);
1989 $language->{translation} = $translation;
1990 $language->{longdescription} = $longdescription;
1996 my @header_sort = qw(name longdescription);
1997 my %header_title = ( "name" => $locale->text("Name"),
1998 "longdescription" => $locale->text("Long Description"),
2002 map(+{ "column_title" => $header_title{$_},
2007 $form->{"title"} = $locale->text("Language Values");
2009 print $form->parse_html_template("ic/parts_language_selection", { "HEADER" => \@header,
2010 "LANGUAGES" => $languages, });
2012 $lxdebug->leave_sub();
2015 sub ajax_autocomplete {
2016 $main::lxdebug->enter_sub();
2018 my $form = $main::form;
2019 my %myconfig = %main::myconfig;
2021 $form->{column} = 'description' unless $form->{column} =~ /^partnumber|description$/;
2022 $form->{$form->{column}} = $form->{q} || '';
2023 $form->{limit} = ($form->{limit} * 1) || 10;
2024 $form->{searchitems} ||= '';
2026 my @results = IC->all_parts(\%myconfig, $form);
2028 print $form->ajax_response_header(),
2029 $form->parse_html_template('ic/ajax_autocomplete');
2031 $main::lxdebug->leave_sub();
2034 sub continue { call_sub($form->{"nextsub"}); }