]> wagnertech.de Git - mfinanz.git/blob - SL/Presenter/ReclamationFilter.pm
restart apache2 in postinst
[mfinanz.git] / SL / Presenter / ReclamationFilter.pm
1 package SL::Presenter::ReclamationFilter;
2
3 use strict;
4
5 use SL::Presenter::EscapedText qw(escape is_escaped);
6 use SL::Presenter::Tag qw(html_tag input_tag select_tag date_tag checkbox_tag);
7 use SL::Locale::String qw(t8);
8
9 use Exporter qw(import);
10 our @EXPORT_OK = qw(
11 filter
12 );
13
14 use Carp;
15
16 sub filter {
17   my ($filter, $reclamation_type, %params) = @_;
18
19   $filter ||= undef; #filter should not be '' (empty string);
20   my %default_filter_elements = ( # {{{
21     'reason_names' => {
22       'position' => 1,
23       'text' => t8("Reclamation Reason"),
24       'input_type' => 'input_tag',
25       'input_name' => 'filter.reclamation_items.reason.name:substr::ilike',
26       'input_default' => $filter->{reclamation_items}->{reason}->{'name:substr::ilike'},
27       'active' => 1,
28     },
29     'id' => {
30       'position' => 2,
31       'text' => t8("Reclamation ID"),
32       'input_type' => 'input_tag',
33       'input_name' => 'filter.id:number',
34       'input_default' =>$filter->{'id:number'},
35       'report_id' => 'id',
36       'active' => 0,
37     },
38     'record_number' => {
39       'position' => 3,
40       'text' => t8("Reclamation Number"),
41       'input_type' => 'input_tag',
42       'input_name' => 'filter.record_number:substr::ilike',
43       'input_default' =>$filter->{'record_number:substr::ilike'},
44       'report_id' => 'record_number',
45       'active' => 1,
46     },
47     'employee' => {
48       'position' => 4,
49       'text' => t8("Employee Name"),
50       'input_type' => 'input_tag',
51       'input_name' => 'filter.employee.name:substr::ilike',
52       'input_default' =>$filter->{employee}->{'name:substr::ilike'},
53       'report_id' => 'employee',
54       'active' => 1,
55     },
56     'salesman' => {
57       'position' => 5,
58       'text' => t8("Salesman Name"),
59       'input_type' => 'input_tag',
60       'input_name' => 'filter.salesman.name:substr::ilike',
61       'input_default' =>$filter->{salesman}->{'name:substr::ilike'},
62       'report_id' => 'salesman',
63       'active' => 1,
64     },
65     # 6,7 for Customer/Vendor
66     'customer' => {
67       'position' => 6,
68       'text' => t8("Customer Name"),
69       'input_type' => 'input_tag',
70       'input_name' => 'filter.customer.name:substr::ilike',
71       'input_default' => $filter->{customer}->{'name:substr::ilike'},
72       'report_id' => 'customer',
73       'active' => ($reclamation_type eq 'sales_reclamation' ? 1 : 0),
74     },
75     'vendor' => {
76       'position' => 6,
77       'text' => t8("Vendor Name"),
78       'input_type' => 'input_tag',
79       'input_name' => 'filter.vendor.name:substr::ilike',
80       'input_default' => $filter->{vendor}->{'name:substr::ilike'},
81       'report_id' => 'vendor',
82       'active' => ($reclamation_type eq 'purchase_reclamation' ? 1 : 0),
83     },
84     'customer_number' => {
85       'position' => 7,
86       'text' => t8("Customer Number"),
87       'input_type' => 'input_tag',
88       'input_name' => 'filter.customer.customernumber:substr::ilike',
89       'input_default' => $filter->{customer}->{'customernumber:substr::ilike'},
90       'active' => ($reclamation_type eq 'sales_reclamation' ? 1 : 0),
91     },
92     'vendor_number' => {
93       'position' => 7,
94       'text' => t8("Vendor Number"),
95       'input_type' => 'input_tag',
96       'input_name' => 'filter.vendor.vendornumber:substr::ilike',
97       'input_default' => $filter->{vendor}->{'vendornumber:substr::ilike'},
98       'active' => ($reclamation_type eq 'purchase_reclamation' ? 1 : 0),
99     },
100     'contact_name' => {
101       'position' => 8,
102       'text' => t8("Contact Name"),
103       'input_type' => 'input_tag',
104       'input_name' => 'filter.contact.cp_name:substr::ilike',
105       'input_default' =>$filter->{contact}->{'cp_name:substr::ilike'},
106       'report_id' => 'contact',
107       'active' => 1,
108     },
109     'language_code' => {
110       'position' => 9,
111       'text' => t8("Language Code"),
112       'input_type' => 'input_tag',
113       'input_name' => 'filter.language.article_code:substr::ilike',
114       'input_default' =>$filter->{language}->{'article_code:substr::ilike'},
115       'report_id' => 'language',
116       'active' => 1,
117     },
118     'department_description' => {
119       'position' => 10,
120       'text' => t8("Department Description"),
121       'input_type' => 'input_tag',
122       'input_name' => 'filter.department.description:substr::ilike',
123       'input_default' =>$filter->{department}->{'description:substr::ilike'},
124       'report_id' => 'department',
125       'active' => 1,
126     },
127     'globalproject_projectnumber' => {
128       'position' => 11,
129       'text' => t8("Project Number"),
130       'input_type' => 'input_tag',
131       'input_name' => 'filter.globalproject.projectnumber:substr::ilike',
132       'input_default' =>$filter->{globalproject}->{'projectnumber:substr::ilike'},
133       'report_id' => 'globalproject',
134       'active' => 1,
135     },
136     'globalproject_description' => {
137       'position' => 12,
138       'text' => t8("Project Description"),
139       'input_type' => 'input_tag',
140       'input_name' => 'filter.globalproject.description:substr::ilike',
141       'input_default' =>$filter->{globalproject}->{'description:substr::ilike'},
142       'active' => 1,
143     },
144     'cv_record_number' => {
145       'position' => 13,
146       'text' => ($reclamation_type eq 'sales_reclamation'
147                   ? t8("Customer Record Number")
148                   : t8("Vendor Record Number")
149                 ),
150       'input_type' => 'input_tag',
151       'input_name' => 'filter.cv_record_number:substr::ilike',
152       'input_default' => $filter->{'cv_record_number:substr::ilike'},
153       'report_id' => 'cv_record_number',
154       'active' => 1,
155     },
156     'transaction_description' => {
157       'position' => 14,
158       'text' => t8("Description"),
159       'input_type' => 'input_tag',
160       'input_name' => 'filter.transaction_description:substr::ilike',
161       'input_default' =>$filter->{'transaction_description:substr::ilike'},
162       'report_id' => 'transaction_description',
163       'active' => 1,
164     },
165     'notes' => {
166       'position' => 15,
167       'text' => t8("Notes"),
168       'input_type' => 'input_tag',
169       'input_name' => 'filter.notes:substr::ilike',
170       'input_default' =>$filter->{'notes:substr::ilike'},
171       'report_id' => 'notes',
172       'active' => 1,
173     },
174     'intnotes' => {
175       'position' => 16,
176       'text' => t8("Internal Notes"),
177       'input_type' => 'input_tag',
178       'input_name' => 'filter.intnotes:substr::ilike',
179       'input_default' =>$filter->{'intnotes:substr::ilike'},
180       'report_id' => 'intnotes',
181       'active' => 1,
182     },
183     'shippingpoint' => {
184       'position' => 17,
185       'text' => t8("Shipping Point"),
186       'input_type' => 'input_tag',
187       'input_name' => 'filter.shippingpoint:substr::ilike',
188       'input_default' =>$filter->{'shippingpoint:substr::ilike'},
189       'report_id' => 'shippingpoint',
190       'active' => 1,
191     },
192     'shipvia' => {
193       'position' => 18,
194       'text' => t8("Ship via"),
195       'input_type' => 'input_tag',
196       'input_name' => 'filter.shipvia:substr::ilike',
197       'input_default' =>$filter->{'shipvia:substr::ilike'},
198       'report_id' => 'shipvia',
199       'active' => 1,
200     },
201     'amount' => {
202       'position' => 19,
203       'text' => t8("Total"),
204       'input_type' => 'input_tag',
205       'input_name' => 'filter.amount:number',
206       'input_default' =>$filter->{'amount:number'},
207       'report_id' => 'amount',
208       'active' => 1,
209     },
210     'netamount' => {
211       'position' => 20,
212       'text' => t8("Subtotal"),
213       'input_type' => 'input_tag',
214       'input_name' => 'filter.netamount:number',
215       'input_default' =>$filter->{'netamount:number'},
216       'report_id' => 'netamount',
217       'active' => 1,
218     },
219     'delivery_term_description' => {
220       'position' => 21,
221       'text' => t8("Delivery Terms"),
222       'input_type' => 'input_tag',
223       'input_name' => 'filter.delivery_term.description:substr::ilike',
224       'input_default' =>$filter->{delivery_term}->{'description:substr::ilike'},
225       'report_id' => 'delivery_term',
226       'active' => 1,
227     },
228     'payment_description' => {
229       'position' => 22,
230       'text' => t8("Payment Terms"),
231       'input_type' => 'input_tag',
232       'input_name' => 'filter.payment.description:substr::ilike',
233       'input_default' =>$filter->{payment}->{'description:substr::ilike'},
234       'report_id' => 'payment',
235       'active' => 1,
236     },
237     'currency_name' => {
238       'position' => 23,
239       'text' => t8("Currency"),
240       'input_type' => 'input_tag',
241       'input_name' => 'filter.currency.name:substr::ilike',
242       'input_default' =>$filter->{currency}->{'name:substr::ilike'},
243       'report_id' => 'currency',
244       'active' => 1,
245     },
246     'exchangerate' => {
247       'position' => 24,
248       'text' => t8("Exchangerate"),
249       'input_type' => 'input_tag',
250       'input_name' => 'filter.exchangerate:number',
251       'input_default' =>$filter->{'exchangerate:number'},
252       'report_id' => 'exchangerate',
253       'active' => 1,
254     },
255     'taxincluded' => {
256       'position' => 25,
257       'text' => t8("Tax Included"),
258       'input_type' => 'yes_no_tag',
259       'input_name' => 'filter.taxincluded',
260       'input_default' =>$filter->{taxincluded},
261       'report_id' => 'taxincluded',
262       'active' => 1,
263     },
264     'taxzone_description' => {
265       'position' => 26,
266       'text' => t8("Tax zone"),
267       'input_type' => 'input_tag',
268       'input_name' => 'filter.taxzone.description:substr::ilike',
269       'input_default' =>$filter->{taxzone}->{'description:substr::ilike'},
270       'report_id' => 'taxzone',
271       'active' => 1,
272     },
273     'tax_point' => {
274       'position' => 27,
275       'text' => t8("Tax point"),
276       'input_type' => 'date_tag',
277       'input_name' => 'tax_point',
278       'input_default_ge' => $filter->{'tax_pont' . ':date::ge'},
279       'input_default_le' => $filter->{'tax_pont' . ':date::le'},
280       'report_id' => 'tax_point',
281       'active' => 1,
282     },
283     'reqdate' => {
284       'position' => 28,
285       'text' => t8("Deadline"),
286       'input_type' => 'date_tag',
287       'input_name' => 'reqdate',
288       'input_default_ge' => $filter->{'reqdate' . ':date::ge'},
289       'input_default_le' => $filter->{'reqdate' . ':date::le'},
290       'report_id' => 'reqdate',
291       'active' => 1,
292     },
293     'transdate' => {
294       'position' => 29,
295       'text' => t8("Booking Date"),
296       'input_type' => 'date_tag',
297       'input_name' => 'transdate',
298       'input_default_ge' => $filter->{'transdate' . ':date::ge'},
299       'input_default_le' => $filter->{'transdate' . ':date::le'},
300       'report_id' => 'transdate',
301       'active' => 1,
302     },
303     'itime' => {
304       'position' => 30,
305       'text' => t8("Creation Time"),
306       'input_type' => 'date_tag',
307       'input_name' => 'itime',
308       'input_default_ge' => $filter->{'itime' . ':date::ge'},
309       'input_default_le' => $filter->{'itime' . ':date::le'},
310       'report_id' => 'itime',
311       'active' => 1,
312     },
313     'mtime' => {
314       'position' => 31,
315       'text' => t8("Last modification Time"),
316       'input_type' => 'date_tag',
317       'input_name' => 'mtime',
318       'input_default_ge' => $filter->{'mtime' . ':date::ge'},
319       'input_default_le' => $filter->{'mtime' . ':date::le'},
320       'report_id' => 'mtime',
321       'active' => 1,
322     },
323     'delivered' => {
324       'position' => 32,
325       'text' => t8("Delivered"),
326       'input_type' => 'yes_no_tag',
327       'input_name' => 'filter.delivered',
328       'input_default' =>$filter->{delivered},
329       'report_id' => 'delivered',
330       'active' => 1,
331     },
332     'closed' => {
333       'position' => 33,
334       'text' => t8("Closed"),
335       'input_type' => 'yes_no_tag',
336       'input_name' => 'filter.closed',
337       'input_default' =>$filter->{closed},
338       'report_id' => 'closed',
339       'active' => 1,
340     },
341   ); # }}}
342
343   # combine default and param values for filter_element,
344   # only replace the lowest occurrence
345   my %filter_elements = %default_filter_elements;
346   while(my ($key, $value) = each (%{$params{filter_elements}})) {
347     if(exists $filter_elements{$key}) {
348       $filter_elements{$key} = ({
349         %{$filter_elements{$key}},
350         %{$value},
351       });
352     } else {
353       $filter_elements{$key} = $value;
354     }
355   }
356
357   my @filter_element_params =
358     sort { $a->{position} <=> $b->{position} }
359     grep { $_->{active} }
360     values %filter_elements;
361
362   my @filter_elements;
363   for my $filter_element_param (@filter_element_params) {
364     unless($filter_element_param->{active}) {
365       next;
366     }
367
368     my $filter_element = _create_input_element($filter_element_param, %params);
369
370     push @filter_elements, $filter_element;
371   }
372
373   my $filter_form_div = _create_filter_form(\@filter_elements, %params);
374
375   is_escaped($filter_form_div);
376 }
377
378 sub _create_input_element {
379   my ($element_param, %params) = @_;
380
381   my $element_th =  html_tag('th', $element_param->{text}, align => 'right');
382
383   my $element_input = '';
384
385   if($element_param->{input_type} eq 'input_tag') {
386
387     $element_input = input_tag($element_param->{input_name}, $element_param->{input_default});
388
389   } elsif ($element_param->{input_type} eq 'yes_no_tag') {
390
391     $element_input = select_tag($element_param->{input_name}, [ [ 1 => t8('Yes') ], [ 0 => t8('No') ] ], default => $element_param->{input_default}, with_empty => 1)
392
393   } elsif($element_param->{input_type} eq 'date_tag') {
394
395     my $after_input =
396       html_tag('th', t8("After"), align => 'right') .
397       html_tag('td',
398         date_tag("filter." . $element_param->{input_name} . ":date::ge", $element_param->{input_default_ge})
399       )
400     ;
401     my $before_input =
402       html_tag('th', t8("Before"), align => 'right') .
403       html_tag('td',
404         date_tag("filter." . $element_param->{input_name} . ":date::le", $element_param->{input_default_le})
405       )
406     ;
407
408     $element_input =
409       html_tag('table',
410         html_tag('tr', $after_input)
411         .
412         html_tag('tr', $before_input)
413       )
414     ;
415   }
416
417   my $element_input_td =  html_tag('td',
418     $element_input,
419     nowrap => 1,
420   );
421
422   my $element_checkbox_td =  '';
423   unless($params{no_show} || $element_param->{report_id} eq '') {
424     my $checkbox =  checkbox_tag('active_in_report.' . $element_param->{report_id}, checked => $params{active_in_report}->{$element_param->{report_id}}, for_submit => 1);
425     $element_checkbox_td = html_tag('td', $checkbox);
426   }
427
428   return $element_th . $element_input_td . $element_checkbox_td;
429 }
430
431 sub _create_filter_form {
432   my ($ref_elements, %params) = @_;
433
434   my $filter_table = _create_input_div($ref_elements, %params);
435
436   my $filter_form = html_tag('form', $filter_table, method => 'post', action => 'controller.pl', id => 'search_form');
437
438   return $filter_form;
439 }
440
441 sub _create_input_div {
442   my ($ref_elements, %params) = @_;
443   my @elements = @{$ref_elements};
444
445   my $div_columns = "";
446
447   $params{count_columns} ||= 4;
448   my $elements_per_column = (int((scalar(@{$ref_elements}) - 1) / $params{count_columns}) + 1);
449   for my $i (0 .. ($params{count_columns} - 1)) {
450
451     my $rows = "";
452     for my $j (0 .. ($elements_per_column - 1) ) {
453       my $idx = $elements_per_column * $i + $j;
454       my $element = $elements[$idx];
455       $rows .= html_tag('tr', $element);
456
457     }
458     $div_columns .= html_tag('div',
459       html_tag('table',
460         html_tag('tr',
461           html_tag('td')
462           . html_tag('th', t8('Filter'))
463           . ( $params{no_show} ? '' : html_tag('th', t8('Show')) )
464         )
465         . $rows
466       ),
467       style => "flex:1");
468   }
469
470   my $input_div = html_tag('div', $div_columns, style => "display:flex;flex-wrap:wrap");
471
472   return $input_div;
473 }
474
475 1;
476
477 __END__
478
479 =pod
480
481 =encoding utf8
482
483 =head1 NAME
484
485 SL::Presenter::ReclamationFilter - Presenter module for a generic Filter on
486 Reclamation.
487
488 =head1 SYNOPSIS
489
490   # in Reclamation Controller
491   my $filter_html = SL::Presenter::ReclamationFilter::filter(
492     $::form->{filter}, $self->type, active_in_report => $::form->{active_in_report}
493   );
494
495
496 =head1 FUNCTIONS
497
498 =over 4
499
500 =item C<filter $filter, $reclamation_type, %params>
501
502 Returns a rendered version (actually an instance of
503 L<SL::Presenter::EscapedText>) of a filter form for reclamations of type
504 C<$reclamation_type>.
505
506 C<$filter> should be the C<filter> value of the last C<$::form>. This is used to
507 get the previous values of the input fields.
508
509 C<%params> can include:
510
511 =over 2
512
513 =item * no_show
514
515 If falsish (the default) then a check box is added after the input field. Which
516 specifies whether the corresponding column appears in the report. The value of
517 the check box can be changed by the user.
518
519 =item * active_in_report
520
521 If C<$params{no_show}> is falsish, this is used to set the values of the check
522 boxes, after the input fields. This can be set to the C<active_in_report> value
523 of the last C<$::form>.
524
525 =item * filter_elements
526
527 Is combined with the default filter elements. This can be used to override
528 default values of the filter elements or to add a new ones.
529
530   #deactivate the id and record_number fields
531   $params{filter_elements} = ({
532     id => {active => 0},
533     record_number => {active => 0}
534   });
535
536 =back
537
538 =back
539
540 =head1 FILTER ELEMENTS
541
542 A filter element is stored in and as a hash map. Each filter has a unique key
543 and should have entries for:
544
545 =over 4
546
547 =item * position
548
549 Is a number after which the elements are ordered. This can be a float.
550
551 =item * text
552
553 Is shown before the input field.
554
555 =item * input_type
556
557 This must be C<input_tag>, C<yes_no_tag> or C<date_tag>. It sets the input type
558 for the filter.
559
560 =over 2
561
562 =item * input_tag
563
564 Creates a text input field. The default value of this field is set to the
565 C<input_default> entry of the filter element. C<input_name> is used to set the
566 name of the field, which should match the filter syntax.
567
568 =item * yes_no_tag
569
570 Creates a yes/no input field. The default value of this field is set to the
571 C<input_default> entry of the filter element. C<input_name> is used to set the
572 name of the field, which should match the filter syntax.
573
574 =item * date_tag
575
576 Creates two date input fields. One filters for after the date and the other
577 filters for before the date. The default values of these fields are set to the
578 C<input_default_ge> and C<input_default_le> entries of the filter element.
579 C<input_name> is used to set the names of these fields, which should match the
580 filter syntax. For the first field ":date::ge" and for the second ":date::le" is
581 added to the end of C<input_name>.
582
583 =back
584
585 =item * report_id
586
587 Is used to generate the id of the check box after the input field. The value of
588 the check box can be found in the form under
589 C<$::form-E<gt>{'active_in_report'}-E<gt>{report_id}>.
590
591 =item * active
592
593 If falsish the element is ignored.
594
595 =item * input_name, input_default, input_default_ge, input_default_le
596
597 Look at I<input_tag> to see how they are used.
598
599 =back
600
601 =head1 BUGS
602
603 Nothing here yet.
604
605 =head1 AUTHOR
606
607 Tamino Steinert E<lt>tamino.steinert@tamino.stE<gt>
608
609 =cut