epic-ts
[kivitendo-erp.git] / bin / mozilla / common.pl
1 #=====================================================================
2 # LX-Office ERP
3 # Copyright (C) 2004
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
6 ######################################################################
7 #
8 # Stuff that can be used from other modules
9 #
10 ######################################################################
11
12 use SL::Common;
13 use SL::DB::Helper::Mappings;
14 use SL::DBUtils;
15 use SL::Form;
16 use SL::MoreCommon;
17 use SL::Helper::Flash;
18
19 use strict;
20
21 sub build_std_url {
22   $main::lxdebug->enter_sub(2);
23
24   my $form     = $main::form;
25
26   my $script = $form->{script};
27
28   my @parts;
29
30   foreach my $key (@_) {
31     next unless ($key);
32
33     if ($key =~ /(.*?)=(.*)/) {
34       if ($1 eq 'script') {
35         $script = $2;
36       } else {
37         push @parts, $key;
38       }
39
40     } else {
41       foreach my $var ($form->flatten_variables($key)) {
42         push @parts, E($var->{key}) . '=' . E($var->{value});
43       }
44     }
45   }
46
47   my $url = "${script}?" . join('&', @parts);
48
49   $main::lxdebug->leave_sub(2);
50
51   return $url;
52 }
53
54 # -------------------------------------------------------------------------
55
56 sub select_part {
57   $main::lxdebug->enter_sub();
58
59   my ($callback_sub, @parts) = @_;
60
61   my $form     = $main::form;
62   my $locale   = $main::locale;
63
64   my $remap_parts_id = 0;
65   if (defined($parts[0]->{parts_id}) && !defined($parts[0]->{id})) {
66     $remap_parts_id = 1;
67     map { $_->{id} = $_->{parts_id}; } @parts;
68   }
69
70   my $remap_partnumber = 0;
71   if (defined($parts[0]->{partnumber}) && !defined($parts[0]->{number})) {
72     $remap_partnumber = 1;
73     map { $_->{number} = $_->{partnumber}; } @parts;
74   }
75
76   my $has_charge = 0;
77   if (defined($parts[0]->{chargenumber})) {
78     $has_charge = 1;
79     map { $_->{has_charge} = 1; } @parts;
80   }
81   my $has_bestbefore = 0;
82   if (defined($parts[0]->{bestbefore})) {
83     $has_bestbefore = 1;
84     map { $_->{has_bestbefore} = 1; } @parts;
85   }
86   my $has_ean = 0;
87   if (defined($parts[0]->{ean})) {
88     $has_ean = 1;
89     map { $_->{has_ean} = 1; } @parts;
90   }
91
92   my $old_form = save_form();
93
94   $form->header();
95   print $form->parse_html_template("generic/select_part",
96                                    { "PARTS"            => \@parts,
97                                      "old_form"         => $old_form,
98                                      "title"            => $locale->text("Select a part"),
99                                      "nextsub"          => "select_part_internal",
100                                      "callback_sub"     => $callback_sub,
101                                      "has_charge"       => $has_charge,
102                                      "has_bestbefore"   => $has_bestbefore,
103                                      "has_ean"          => $has_ean,
104                                      "remap_parts_id"   => $remap_parts_id,
105                                      "remap_partnumber" => $remap_partnumber });
106
107   $main::lxdebug->leave_sub();
108 }
109
110 sub select_part_internal {
111   $main::lxdebug->enter_sub();
112
113   my $form     = $main::form;
114
115   my ($new_item, $callback_sub);
116
117   my $re = "^new_.*_$form->{selection}\$";
118
119   foreach (grep /$re/, keys %{ $form }) {
120     my $new_key           =  $_;
121     $new_key              =~ s/^new_//;
122     $new_key              =~ s/_\d+$//;
123     $new_item->{$new_key} =  $form->{$_};
124   }
125
126   if ($form->{remap_parts_id}) {
127     $new_item->{parts_id} = $new_item->{id};
128     delete $new_item->{id};
129   }
130
131   if ($form->{remap_partnumber}) {
132     $new_item->{partnumber} = $new_item->{number};
133     delete $new_item->{number};
134   }
135
136   $callback_sub = $form->{callback_sub};
137
138   restore_form($form->{old_form});
139
140   call_sub($callback_sub, $new_item);
141
142   $main::lxdebug->leave_sub();
143 }
144
145 sub part_selection_internal {
146   $main::lxdebug->enter_sub();
147
148   my $form     = $main::form;
149   my %myconfig = %main::myconfig;
150   my $locale   = $main::locale;
151
152   my $order_by  = "description";
153   $order_by  = $form->{"order_by"} if (defined($form->{"order_by"}));
154   my $order_dir = 1;
155   $order_dir = $form->{"order_dir"} if (defined($form->{"order_dir"}));
156
157   my %options;
158
159   foreach my $opt (split m/:/, $form->{options}) {
160     if ($opt =~ /=/) {
161       my ($key, $value) = split m/=/, $opt, 2;
162       $options{$key} = $value;
163
164     } else {
165       $options{$opt} = 1;
166     }
167   }
168
169   map { $form->{$_} = $options{$_} if ($options{$_}) } qw(no_services no_assemblies assemblies click_button);
170
171   my $parts = Common->retrieve_parts(\%myconfig, $form, $order_by, $order_dir);
172
173   if (0 == scalar(@{$parts})) {
174     $form->show_generic_information($locale->text("No part was found matching the search parameters."));
175   } elsif (1 == scalar(@{$parts})) {
176     $::request->{layout}->add_javascripts_inline("part_selected('1')");
177   }
178
179   map { $parts->[$_]->{selected} = $_ ? 0 : 1; } (0..$#{$parts});
180
181   my $callback = build_std_url('action=part_selection_internal', qw(partnumber description input_partnumber input_description input_partsid),
182                                grep({ /^[fl]_/ } keys %{ $form }));
183
184   my @header_sort  = qw(partnumber description);
185   my %header_title = ( "partnumber"  => $locale->text("Part Number"),
186                        "description" => $locale->text("Part Description"),
187                        );
188
189   my @header =
190     map(+{ "column_title" => $header_title{$_},
191            "column"       => $_,
192            "callback"     => $callback . "order_by=${_}&order_dir=" . ($order_by eq $_ ? 1 - $order_dir : $order_dir),
193          },
194         @header_sort);
195
196   $form->{formname} ||= 'Form';
197
198   $form->{title} = $locale->text("Select a part");
199   $form->header(no_layout => 1);
200   print $form->parse_html_template("generic/part_selection", { "HEADER" => \@header,
201                                                                "PARTS"  => $parts, });
202
203   $main::lxdebug->leave_sub();
204 }
205
206 # -------------------------------------------------------------------------
207
208 sub delivery_customer_selection {
209   $main::lxdebug->enter_sub();
210
211   my $form     = $main::form;
212   my %myconfig = %main::myconfig;
213   my $locale   = $main::locale;
214
215   my $order_by = "name";
216   $order_by = $form->{"order_by"} if (defined($form->{"order_by"}));
217   my $order_dir = 1;
218   $order_dir = $form->{"order_dir"} if (defined($form->{"order_dir"}));
219
220   my $delivery = Common->retrieve_delivery_customer(\%myconfig, $form, $order_by, $order_dir);
221   map({ $delivery->[$_]->{"selected"} = $_ ? 0 : 1; } (0..$#{$delivery}));
222
223   if (0 == scalar(@{$delivery})) {
224     $form->show_generic_information($locale->text("No Customer was found matching the search parameters."));
225   } elsif (1 == scalar(@{$delivery})) {
226     $::request->{layout}->add_javascripts_inline("customer_selected('1')");
227   }
228
229   my $callback = "$form->{script}?action=delivery_customer_selection&";
230   map({ $callback .= "$_=" . $form->escape($form->{$_}) . "&" }
231       (qw(name input_name input_id), grep({ /^[fl]_/ } keys %$form)));
232
233   my @header_sort = qw(name customernumber address);
234   my %header_title = ( "name" => $locale->text("Name"),
235                        "customernumber" => $locale->text("Customer Number"),
236                        "address" => $locale->text("Address"),
237                      );
238
239   my @header =
240     map(+{ "column_title" => $header_title{$_},
241            "column" => $_,
242            "callback" => $callback . "order_by=${_}&order_dir=" . ($order_by eq $_ ? 1 - $order_dir : $order_dir),
243          },
244         @header_sort);
245
246   $form->{"title"} = $locale->text("Select a Customer");
247   $form->header(no_layout => 1);
248   print $form->parse_html_template("generic/select_delivery_customer", { "HEADER"   => \@header,
249                                                                          "DELIVERY" => $delivery, });
250
251   $main::lxdebug->leave_sub();
252 }
253
254 # -------------------------------------------------------------------------
255
256 sub vendor_selection {
257   $main::lxdebug->enter_sub();
258
259   my $form     = $main::form;
260   my %myconfig = %main::myconfig;
261   my $locale   = $main::locale;
262
263   my $order_by = "name";
264   $order_by = $form->{"order_by"} if (defined($form->{"order_by"}));
265   my $order_dir = 1;
266   $order_dir = $form->{"order_dir"} if (defined($form->{"order_dir"}));
267
268   my $vendor = Common->retrieve_vendor(\%myconfig, $form, $order_by, $order_dir);
269   map({ $vendor->[$_]->{"selected"} = $_ ? 0 : 1; } (0..$#{$vendor}));
270
271   if (0 == scalar(@{$vendor})) {
272     $form->show_generic_information($locale->text("No Vendor was found matching the search parameters."));
273   } elsif (1 == scalar(@{$vendor})) {
274     $::request->{layout}->add_javascripts_inline("vendor_selected('1')");
275   }
276
277   my $callback = "$form->{script}?action=vendor_selection&";
278   map({ $callback .= "$_=" . $form->escape($form->{$_}) . "&" }
279       (qw(name input_name input_id), grep({ /^[fl]_/ } keys %$form)));
280
281   my @header_sort = qw(name customernumber address);
282   my %header_title = ( "name" => $locale->text("Name"),
283                        "customernumber" => $locale->text("Customer Number"),
284                        "address" => $locale->text("Address"),
285                      );
286
287   my @header =
288     map(+{ "column_title" => $header_title{$_},
289            "column" => $_,
290            "callback" => $callback . "order_by=${_}&order_dir=" . ($order_by eq $_ ? 1 - $order_dir : $order_dir),
291          },
292         @header_sort);
293
294   $form->{"title"} = $locale->text("Select a Customer");
295   $form->header(no_layout => 1);
296   print $form->parse_html_template("generic/select_vendor", { "HEADER" => \@header,
297                                                               "VENDOR" => $vendor, });
298
299   $main::lxdebug->leave_sub();
300 }
301
302 # -------------------------------------------------------------------------
303
304 sub calculate_qty {
305   $main::lxdebug->enter_sub();
306
307   my $form     = $main::form;
308   my $locale   = $main::locale;
309
310   $form->{formel} =~ s/\r\n//g;
311
312   my ($variable_string, $formel) = split /###/,$form->{formel};
313   my @variable;
314
315   foreach my $item (split m/;/, $variable_string) {
316     next unless $item =~ m/^ \s* (\w+) \s* = \s* (\w+) \s* (\w+) \s* $/x;
317     push @variable, {
318       description => $1,
319       name        => $2,
320       unit        => $3,
321     };
322   }
323
324   my @header_sort = qw(variable value unit);
325   my %header_title = (
326     variable => $locale->text("Variable"),
327     value    => $locale->text("Value"),
328     unit     => $locale->text("Unit"),
329   );
330   my @header = map +{
331     column_title => $header_title{$_},
332     column       => $_,
333   }, @header_sort;
334
335   $form->{formel} = $formel;
336   $form->{title}  = $locale->text("Please enter values");
337   $form->header(no_layout => 1);
338   print $form->parse_html_template("generic/calculate_qty", { "HEADER"    => \@header,
339                                                               "VARIABLES" => \@variable, });
340
341   $main::lxdebug->leave_sub();
342 }
343
344 # -------------------------------------------------------------------------
345
346 sub H {
347   return $main::locale->quote_special_chars('HTML', $_[0]);
348 }
349
350 sub Q {
351   return $main::locale->quote_special_chars('URL@HTML', $_[0]);
352 }
353
354 sub E {
355   return $main::form->escape($_[0]);
356 }
357
358 sub NTI {
359   my ($element) = @_;
360
361   $element =~ s/tabindex\s*=\s*"\d+"//;
362   return $element;
363 }
364
365 sub format_dates {
366   return $::form->format_dates(@_);
367 }
368
369 sub reformat_numbers {
370   return $::form->reformat_numbers(@_);
371 }
372
373 # -------------------------------------------------------------------------
374
375 sub show_history {
376   $main::lxdebug->enter_sub();
377
378   my $form     = $main::form;
379   my %myconfig = %main::myconfig;
380   my $locale   = $main::locale;
381
382   my $dbh = $form->dbconnect(\%myconfig);
383   my ($sort, $sortby) = split(/\-\-/, $form->{order});
384   $sort =~ s/.*\.(.*)/$1/;
385
386   $form->{title} = $locale->text("History");
387   $form->header(no_layout => 1);
388
389   my $restriction;
390   if ( $form->{trans_id_type} eq 'glid' ) {
391     $restriction = "AND ( snumbers LIKE 'invnumber%' OR what_done LIKE '%Buchungsnummer%' OR snumbers LIKE 'gltransaction%' ) ";
392   } elsif ( $form->{trans_id_type} eq 'id' ) {
393     $restriction = " AND ( snumbers NOT LIKE 'invnumber_%' AND snumbers NOT LIKE 'gltransaction%' AND (what_done NOT LIKE '%Buchungsnummer%' OR what_done IS null))";
394   } else {
395     $restriction = '';
396   };
397
398   print $form->parse_html_template( "common/show_history", {
399     "DATEN"        => $form->get_history($dbh,$form->{input_name},$restriction,$form->{order}),
400     "SUCCESS"      => ($form->get_history($dbh,$form->{input_name}) ne "0"),
401     uc($sort)      => 1,
402     uc($sort)."BY" => $sortby,
403   } );
404
405   $dbh->disconnect();
406   $main::lxdebug->leave_sub();
407 }
408
409 # -------------------------------------------------------------------------
410
411 sub call_sub {
412   $main::lxdebug->enter_sub();
413
414   my $name = shift;
415
416   my $form     = $main::form;
417   my $locale   = $main::locale;
418
419   if (!$name) {
420     $form->error($locale->text("Trying to call a sub without a name"));
421   }
422
423   $name =~ s/[^a-zA-Z0-9_]//g;
424
425   if (!defined(&{ $name })) {
426     $form->error(sprintf($locale->text("Attempt to call an undefined sub named '%s'"), $name));
427   }
428
429   {
430     no strict "refs";
431     &{ $name }(@_);
432   }
433
434   $main::lxdebug->leave_sub();
435 }
436
437 # -------------------------------------------------------------------------
438
439 sub show_vc_details {
440   $main::lxdebug->enter_sub();
441
442   my $form     = $main::form;
443   my %myconfig = %main::myconfig;
444   my $locale   = $main::locale;
445
446   $form->{vc} = $form->{vc} eq "customer" ? "customer" : "vendor";
447   $form->isblank("vc_id",
448                  $form->{vc} eq "customer" ?
449                  $locale->text("No customer has been selected yet.") :
450                  $locale->text("No vendor has been selected yet."));
451
452   Common->get_vc_details(\%myconfig, $form, $form->{vc}, $form->{vc_id});
453   $form->{discount_as_percent} = $form->format_amount(\%::myconfig, $form->parse_amount(\%::myconfig, $form->{discount}) * 100, 2);
454
455   $form->{title} = $form->{vc} eq "customer" ?
456     $locale->text("Customer details") : $locale->text("Vendor details");
457   $form->header(no_layout => 1);
458   print $form->parse_html_template("common/show_vc_details", { "is_customer" => $form->{vc} eq "customer" });
459
460   $main::lxdebug->leave_sub();
461 }
462
463 # -------------------------------------------------------------------------
464
465 sub retrieve_partunits {
466   $main::lxdebug->enter_sub();
467
468   my $form     = $main::form;
469
470   my @part_ids = grep { $_ } map { $form->{"id_${_}"} } (1..$form->{rowcount});
471
472   if (@part_ids) {
473     my %partunits = IO->retrieve_partunits('part_ids' => \@part_ids);
474
475     foreach my $i (1..$form->{rowcount}) {
476       next unless ($form->{"id_${i}"});
477       $form->{"partunit_${i}"} = $partunits{$form->{"id_${i}"}};
478     }
479   }
480
481   $main::lxdebug->leave_sub();
482 }
483
484 # -------------------------------------------------------------------------
485
486 sub mark_as_paid_common {
487   $main::lxdebug->enter_sub();
488
489   my ($myconfig, $db_name) = @_;
490
491   my $form     = $main::form;
492   my $locale   = $main::locale;
493
494   if($form->{mark_as_paid}) {
495     my $dbh ||= $form->get_standard_dbh($myconfig);
496     my $query = qq|UPDATE $db_name SET paid = amount, datepaid = current_date WHERE id = ?|;
497     do_query($form, $dbh, $query, $form->{id});
498     $dbh->commit();
499     $form->redirect($locale->text("Marked as paid"));
500
501   } else {
502     my $referer = $ENV{HTTP_REFERER};
503     my $script;
504     my $callback;
505     if ($referer =~ /action/) {
506       $referer =~ /^(.*)\?action\=[^\&]*(\&.*)$/;
507       $script = $1;
508       $callback = $2;
509     } elsif ($referer =~ /RESTORE_FORM_FROM_SESSION_ID/){
510       $referer =~ /^(.*)\?RESTORE_FORM_FROM_SESSION_ID\=(.*)$/;
511       $script = $1;
512       $callback = "";
513     } else {
514       $script = $referer;
515       $callback = "";
516     }
517     $referer = $script . "?action=mark_as_paid&mark_as_paid=1&id=$form->{id}" . $callback;
518     $form->header();
519     print qq|<p><b>|.$locale->text('Mark as paid?').qq|</b></p>|;
520     print qq|<input type="button" value="|.$locale->text('yes').qq|" onclick="document.location.href='|.$referer.qq|'">&nbsp;|;
521     print qq|<input type="button" value="|.$locale->text('no').qq|" onclick="javascript:history.back();">|;
522   }
523
524   $main::lxdebug->leave_sub();
525 }
526
527 sub cov_selection_internal {
528   $main::lxdebug->enter_sub();
529
530   my $form     = $main::form;
531   my %myconfig = %main::myconfig;
532   my $locale   = $main::locale;
533
534   my $order_by = "name";
535   $order_by = $form->{"order_by"} if (defined($form->{"order_by"}));
536   my $order_dir = 1;
537   $order_dir = $form->{"order_dir"} if (defined($form->{"order_dir"}));
538
539   my $type = $form->{"is_vendor"} ? $locale->text("vendor") : $locale->text("customer");
540
541   my $covs = Common->retrieve_customers_or_vendors(\%myconfig, $form, $order_by, $order_dir, $form->{"is_vendor"}, $form->{"allow_both"});
542   map({ $covs->[$_]->{"selected"} = $_ ? 0 : 1; } (0..$#{$covs}));
543
544   if (0 == scalar(@{$covs})) {
545     $form->show_generic_information(sprintf($locale->text("No %s was found matching the search parameters."), $type));
546   } elsif (1 == scalar(@{$covs})) {
547     $::request->{layout}->add_javascripts_inline("cov_selected('1')");
548   }
549
550   my $callback = "$form->{script}?action=cov_selection_internal&";
551   map({ $callback .= "$_=" . $form->escape($form->{$_}) . "&" }
552       (qw(name input_name input_id is_vendor allow_both), grep({ /^[fl]_/ } keys %$form)));
553
554   my @header_sort = qw(name address contact);
555   my %header_title = ( "name" => $locale->text("Name"),
556                        "address" => $locale->text("Address"),
557                        "contact" => $locale->text("Contact"),
558                        );
559
560   my @header =
561     map(+{ "column_title" => $header_title{$_},
562            "column" => $_,
563            "callback" => $callback . "order_by=${_}&order_dir=" . ($order_by eq $_ ? 1 - $order_dir : $order_dir),
564          },
565         @header_sort);
566
567   foreach my $cov (@{ $covs }) {
568     $cov->{address} = "$cov->{street}, $cov->{zipcode} $cov->{city}";
569     $cov->{address} =~ s{^,}{}x;
570     $cov->{address} =~ s{\ +}{\ }gx;
571
572     $cov->{contact} = join " ", map { $cov->{$_} } qw(cp_gender cp_title cp_givenname cp_name);
573     $cov->{contact} =~ s{\ +}{\ }gx;
574   }
575
576   $form->{"title"} = $form->{is_vendor} ? $locale->text("Select a vendor") : $locale->text("Select a customer");
577   $form->header();
578   print($form->parse_html_template("generic/cov_selection", { "HEADER" => \@header,
579                                                               "COVS" => $covs, }));
580
581   $main::lxdebug->leave_sub();
582 }
583
584
585 # Functions to call add routines beneath different reports
586
587 sub sales_invoice {
588   $main::lxdebug->enter_sub();
589
590   print $::form->redirect_header('is.pl?action=add&type=invoice');
591
592   $main::lxdebug->leave_sub();
593 }
594
595 sub ar_transaction {
596   $main::lxdebug->enter_sub();
597
598   print $::form->redirect_header('ar.pl?action=add');
599
600   $main::lxdebug->leave_sub();
601 }
602
603 sub vendor_invoice {
604   $main::lxdebug->enter_sub();
605
606   print $::form->redirect_header('ir.pl?action=add&type=invoice');
607
608   $main::lxdebug->leave_sub();
609 }
610
611 sub ap_transaction {
612   $main::lxdebug->enter_sub();
613
614   print $::form->redirect_header('ap.pl?action=add');
615
616   $main::lxdebug->leave_sub();
617 }
618
619 sub gl_transaction {
620   $main::lxdebug->enter_sub();
621
622   print $::form->redirect_header('gl.pl?action=add');
623
624   $main::lxdebug->leave_sub();
625 }
626
627 sub db {
628   goto &SL::DB::Helper::Mappings::db;
629 }
630
631 1;