Revert "Bugfix zu manuelle Lieferadresse im Auftrag wird nicht in wiederkehrende...
[kivitendo-erp.git] / SL / CVar.pm
1 package CVar;
2
3 use strict;
4
5 use List::MoreUtils qw(any);
6 use List::Util qw(first);
7 use Scalar::Util qw(blessed);
8 use Data::Dumper;
9
10 use SL::DBUtils;
11 use SL::MoreCommon qw(listify);
12 use SL::Util qw(trim);
13
14 sub get_configs {
15   $main::lxdebug->enter_sub();
16
17   my $self     = shift;
18   my %params   = @_;
19
20   my $myconfig = \%main::myconfig;
21   my $form     = $main::form;
22
23   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
24
25   my ($where, @values);
26   if ($params{module}) {
27     $where = 'WHERE module = ?';
28     push @values, $params{module};
29   }
30
31   my $query    = <<SQL;
32     SELECT *, date_trunc('seconds', localtimestamp) AS current_timestamp
33     FROM custom_variable_configs $where ORDER BY sortkey
34 SQL
35
36   $::form->{CVAR_CONFIGS} = {} unless 'HASH' eq ref $::form->{CVAR_CONFIGS};
37   if (!$::form->{CVAR_CONFIGS}->{$params{module}}) {
38     my $configs  = selectall_hashref_query($form, $dbh, $query, @values);
39
40     foreach my $config (@{ $configs }) {
41       if ($config->{type} eq 'select') {
42         $config->{OPTIONS} = [ map { { 'value' => $_ } } split(m/\#\#/, $config->{options}) ];
43
44       } elsif ($config->{type} eq 'number') {
45         $config->{precision} = $1 if ($config->{options} =~ m/precision=(\d+)/i);
46
47       } elsif ($config->{type} eq 'textfield') {
48         $config->{width}  = 30;
49         $config->{height} =  5;
50         $config->{width}  = $1 if ($config->{options} =~ m/width=(\d+)/i);
51         $config->{height} = $1 if ($config->{options} =~ m/height=(\d+)/i);
52
53       } elsif ($config->{type} eq 'text') {
54         $config->{maxlength} = $1 if ($config->{options} =~ m/maxlength=(\d+)/i);
55
56       }
57
58       $self->_unpack_flags($config);
59
60       my $cvar_config = SL::DB::CustomVariableConfig->new(id => $config->{id})->load;
61       @{$config->{'partsgroups'}} = map {$_->id} @{$cvar_config->partsgroups};
62
63     }
64     $::form->{CVAR_CONFIGS}->{$params{module}} = $configs;
65   }
66
67   $main::lxdebug->leave_sub();
68
69   return $::form->{CVAR_CONFIGS}->{$params{module}};
70 }
71
72 sub _unpack_flags {
73   $main::lxdebug->enter_sub();
74
75   my $self   = shift;
76   my $config = shift;
77
78   foreach my $flag (split m/:/, $config->{flags}) {
79     if ($flag =~ m/(.*?)=(.*)/) {
80       $config->{"flag_${1}"}    = $2;
81     } else {
82       $config->{"flag_${flag}"} = 1;
83     }
84   }
85
86   $main::lxdebug->leave_sub();
87 }
88
89 sub get_custom_variables {
90   $main::lxdebug->enter_sub();
91
92   my $self     = shift;
93   my %params   = @_;
94
95   Common::check_params(\%params, qw(module));
96
97   my $myconfig = \%main::myconfig;
98   my $form     = $main::form;
99
100   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
101
102   my $sub_module = $params{sub_module} ? $params{sub_module} : '';
103
104   my $q_var    =
105     qq|SELECT text_value, timestamp_value, timestamp_value::date AS date_value, number_value, bool_value
106        FROM custom_variables
107        WHERE (config_id = ?) AND (trans_id = ?) AND (sub_module = ?)|;
108   my $h_var    = prepare_query($form, $dbh, $q_var);
109
110   my $custom_variables = $self->get_configs(module => $params{module});
111
112   foreach my $cvar (@{ $custom_variables }) {
113     if ($cvar->{type} eq 'textfield') {
114       $cvar->{width}  = 30;
115       $cvar->{height} =  5;
116
117       $cvar->{width}  = $1 if ($cvar->{options} =~ m/width=(\d+)/i);
118       $cvar->{height} = $1 if ($cvar->{options} =~ m/height=(\d+)/i);
119
120     } elsif ($cvar->{type} eq 'text') {
121       $cvar->{maxlength} = $1 if ($cvar->{options} =~ m/maxlength=(\d+)/i);
122
123     } elsif ($cvar->{type} eq 'number') {
124       $cvar->{precision} = $1 if ($cvar->{options} =~ m/precision=(\d+)/i);
125
126     } elsif ($cvar->{type} eq 'select') {
127       $cvar->{OPTIONS} = [ map { { 'value' => $_ } } split(m/\#\#/, $cvar->{options}) ];
128     }
129
130     my ($act_var, $valid);
131     if ($params{trans_id}) {
132       my @values = (conv_i($cvar->{id}), conv_i($params{trans_id}), $sub_module);
133
134       do_statement($form, $h_var, $q_var, @values);
135       $act_var = $h_var->fetchrow_hashref();
136
137       $valid = $self->get_custom_variables_validity(config_id => $cvar->{id}, trans_id => $params{trans_id});
138     } else {
139       $valid = !$cvar->{flag_defaults_to_invalid};
140     }
141
142     if ($act_var) {
143       $cvar->{value} = $cvar->{type} eq 'date'      ? $act_var->{date_value}
144                      : $cvar->{type} eq 'timestamp' ? $act_var->{timestamp_value}
145                      : $cvar->{type} eq 'number'    ? $act_var->{number_value}
146                      : $cvar->{type} eq 'customer'  ? $act_var->{number_value}
147                      : $cvar->{type} eq 'vendor'    ? $act_var->{number_value}
148                      : $cvar->{type} eq 'part'      ? $act_var->{number_value}
149                      : $cvar->{type} eq 'bool'      ? $act_var->{bool_value}
150                      :                                $act_var->{text_value};
151       $cvar->{valid} = $valid;
152     } else {
153       $cvar->{valid} = $valid // 1;
154
155       if ($cvar->{type} eq 'date') {
156         if ($cvar->{default_value} eq 'NOW') {
157           $cvar->{value} = $cvar->{current_date};
158         } else {
159           $cvar->{value} = $cvar->{default_value};
160         }
161
162       } elsif ($cvar->{type} eq 'timestamp') {
163         if ($cvar->{default_value} eq 'NOW') {
164           $cvar->{value} = $cvar->{current_timestamp};
165         } else {
166           $cvar->{value} = $cvar->{default_value};
167         }
168
169       } elsif ($cvar->{type} eq 'bool') {
170         $cvar->{value} = $cvar->{default_value} * 1;
171
172       } elsif ($cvar->{type} eq 'number') {
173         $cvar->{value} = $cvar->{default_value} * 1 if ($cvar->{default_value} ne '');
174
175       } else {
176         $cvar->{value} = $cvar->{default_value};
177       }
178     }
179
180     if ($cvar->{type} eq 'number') {
181       $cvar->{value} = $form->format_amount($myconfig, $cvar->{value} * 1, $cvar->{precision});
182     } elsif ($cvar->{type} eq 'customer') {
183       require SL::DB::Customer;
184       $cvar->{value} = SL::DB::Manager::Customer->find_by(id => $cvar->{value} * 1);
185     } elsif ($cvar->{type} eq 'vendor') {
186       require SL::DB::Vendor;
187       $cvar->{value} = SL::DB::Manager::Vendor->find_by(id => $cvar->{value} * 1);
188     } elsif ($cvar->{type} eq 'part') {
189       require SL::DB::Part;
190       $cvar->{value} = SL::DB::Manager::Part->find_by(id => $cvar->{value} * 1);
191     }
192   }
193
194   $h_var->finish();
195
196   $main::lxdebug->leave_sub();
197
198   return $custom_variables;
199 }
200
201 sub save_custom_variables {
202   $main::lxdebug->enter_sub();
203
204   my $self     = shift;
205   my %params   = @_;
206
207   Common::check_params(\%params, qw(module trans_id variables));
208
209   my $myconfig = \%main::myconfig;
210   my $form     = $main::form;
211
212   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
213
214   my @configs  = $params{configs} ? @{ $params{configs} } : grep { $_->{module} eq $params{module} } @{ CVar->get_configs() };
215
216   my $query    =
217     qq|DELETE FROM custom_variables
218        WHERE (trans_id  = ?)
219          AND (config_id IN (SELECT DISTINCT id
220                             FROM custom_variable_configs
221                             WHERE module = ?))|;
222   my @values   = (conv_i($params{trans_id}), $params{module});
223
224   if ($params{sub_module}) {
225     $query .= qq| AND (sub_module = ?)|;
226     push @values, $params{sub_module};
227   }
228
229   do_query($form, $dbh, $query, @values);
230
231   $query  =
232     qq|INSERT INTO custom_variables (config_id, sub_module, trans_id, bool_value, timestamp_value, text_value, number_value)
233        VALUES                       (?,         ?,          ?,        ?,          ?,               ?,          ?)|;
234   my $sth = prepare_query($form, $dbh, $query);
235
236   foreach my $config (@configs) {
237     my @values = (conv_i($config->{id}), "$params{sub_module}", conv_i($params{trans_id}));
238
239     my $value  = $params{variables}->{"$params{name_prefix}cvar_$config->{name}$params{name_postfix}"};
240
241     if (($config->{type} eq 'text') || ($config->{type} eq 'textfield') || ($config->{type} eq 'select')) {
242       push @values, undef, undef, $value, undef;
243
244     } elsif (($config->{type} eq 'date') || ($config->{type} eq 'timestamp')) {
245       push @values, undef, conv_date($value), undef, undef;
246
247     } elsif ($config->{type} eq 'number') {
248       push @values, undef, undef, undef, conv_i($form->parse_amount($myconfig, $value));
249
250     } elsif ($config->{type} eq 'bool') {
251       push @values, $value ? 't' : 'f', undef, undef, undef;
252     } elsif (any { $config->{type} eq $_ } qw(customer vendor part)) {
253       push @values, undef, undef, undef, $value * 1;
254     }
255
256     do_statement($form, $sth, $query, @values);
257
258     if ($params{save_validity}) {
259       my $valid_index = "$params{name_prefix}cvar_$config->{name}$params{name_postfix}_valid";
260       $self->save_custom_variables_validity(trans_id  => $params{trans_id},
261                                             config_id => $config->{id},
262                                             validity  => ($params{variables}{$valid_index} || $params{always_valid} ? 1 : 0)
263                                            );
264     }
265   }
266
267   $sth->finish();
268
269   $dbh->commit() unless $params{dbh};
270
271   $main::lxdebug->leave_sub();
272 }
273
274 sub render_inputs {
275   $main::lxdebug->enter_sub(2);
276
277   my $self     = shift;
278   my %params   = @_;
279
280   Common::check_params(\%params, qw(variables));
281
282   my $myconfig = \%main::myconfig;
283   my $form     = $main::form;
284
285   my %options  = ( name_prefix           => "$params{name_prefix}",
286                    name_postfix          => "$params{name_postfix}",
287                    hide_non_editable     => $params{hide_non_editable},
288                    show_disabled_message => $params{show_disabled_message},
289                  );
290
291   # should this cvar be filtered by partsgroups?
292   foreach my $var (@{ $params{variables} }) {
293     if ($var->{flag_partsgroup_filter}) {
294       if (!$params{partsgroup_id} || (!grep {$params{partsgroup_id} == $_} @{ $var->{partsgroups} })) {
295         $var->{partsgroup_filtered} = 1;
296       }
297     }
298
299     $var->{HTML_CODE} = $form->parse_html_template('amcvar/render_inputs',     { var => $var, %options });
300     $var->{VALID_BOX} = $form->parse_html_template('amcvar/render_checkboxes', { var => $var, %options });
301   }
302
303   $main::lxdebug->leave_sub(2);
304 }
305
306 sub render_search_options {
307   $main::lxdebug->enter_sub();
308
309   my $self     = shift;
310   my %params   = @_;
311
312   Common::check_params(\%params, qw(variables));
313
314   my $myconfig = \%main::myconfig;
315   my $form     = $main::form;
316
317   $params{hidden_cvar_filters} = $myconfig->{hide_cvar_search_options};
318
319   $params{include_prefix}   = 'l_' unless defined($params{include_prefix});
320   $params{include_value}  ||= '1';
321   $params{filter_prefix}  ||= '';
322
323   my $filter  = $form->parse_html_template('amcvar/search_filter',  \%params);
324   my $include = $form->parse_html_template('amcvar/search_include', \%params);
325
326   $main::lxdebug->leave_sub();
327
328   return ($filter, $include);
329 }
330
331 sub build_filter_query {
332   $main::lxdebug->enter_sub();
333
334   my $self     = shift;
335   my %params   = @_;
336
337   Common::check_params(\%params, qw(module trans_id_field filter));
338
339   my $myconfig = \%main::myconfig;
340   my $form     = $main::form;
341
342   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
343
344   my $configs  = $self->get_configs(%params);
345
346   my (@where, @values);
347
348   foreach my $config (@{ $configs }) {
349     next unless ($config->{searchable});
350
351     my $name = "cvar_$config->{name}";
352
353     my (@sub_values, @sub_where, $not);
354
355     if (($config->{type} eq 'text') || ($config->{type} eq 'textfield')) {
356       next unless ($params{filter}->{$name});
357
358       push @sub_where,  qq|cvar.text_value ILIKE ?|;
359       push @sub_values, '%' . trim($params{filter}->{$name}) . '%'
360
361     } elsif ($config->{type} eq 'select') {
362       next unless ($params{filter}->{$name});
363
364       push @sub_where,  qq|cvar.text_value = ?|;
365       push @sub_values, $params{filter}->{$name};
366
367     } elsif (($config->{type} eq 'date') || ($config->{type} eq 'timestamp')) {
368       my $name_from = "${name}_from";
369       my $name_to   = "${name}_to";
370
371       if ($params{filter}->{$name_from}) {
372         push @sub_where,  qq|cvar.timestamp_value >= ?|;
373         push @sub_values, conv_date($params{filter}->{$name_from});
374       }
375
376       if ($params{filter}->{$name_to}) {
377         push @sub_where,  qq|cvar.timestamp_value <= ?|;
378         push @sub_values, conv_date($params{filter}->{$name_to});
379       }
380
381     } elsif ($config->{type} eq 'number') {
382       next if ($params{filter}->{$name} eq '');
383
384       my $f_op = $params{filter}->{"${name}_qtyop"};
385
386       my $op;
387       if ($f_op eq '==') {
388         $op  = '=';
389
390       } elsif ($f_op eq '=/=') {
391         $not = 'NOT';
392         $op  = '<>';
393
394       } elsif ($f_op eq '<') {
395         $not = 'NOT';
396         $op  = '>=';
397
398       } elsif ($f_op eq '<=') {
399         $not = 'NOT';
400         $op  = '>';
401
402       } elsif (($f_op eq '>') || ($f_op eq '>=')) {
403         $op  = $f_op;
404
405       } else {
406         $op  = '=';
407       }
408
409       push @sub_where,  qq|cvar.number_value $op ?|;
410       push @sub_values, $form->parse_amount($myconfig, trim($params{filter}->{$name}));
411
412     } elsif ($config->{type} eq 'bool') {
413       next unless ($params{filter}->{$name});
414
415       $not = 'NOT' if ($params{filter}->{$name} eq 'no');
416       push @sub_where,  qq|COALESCE(cvar.bool_value, false) = TRUE|;
417     } elsif (any { $config->{type} eq $_ } qw(customer vendor)) {
418       next unless $params{filter}->{$name};
419
420       my $table = $config->{type};
421       push @sub_where, qq|cvar.number_value * 1 IN (SELECT id FROM $table WHERE name ILIKE ?)|;
422       push @sub_values, "%" . trim($params{filter}->{$name}) . "%";
423     } elsif ($config->{type} eq 'part') {
424       next unless $params{filter}->{$name};
425
426       push @sub_where, qq|cvar.number_value * 1 IN (SELECT id FROM parts WHERE partnumber ILIKE ?)|;
427       push @sub_values, "%" . trim($params{filter}->{$name}) . "%";
428     }
429
430     if (@sub_where) {
431       add_token(\@sub_where, \@sub_values, col => 'cvar.sub_module', val => $params{sub_module} || '');
432
433       push @where,
434         qq|$not EXISTS(
435              SELECT cvar.id
436              FROM custom_variables cvar
437              LEFT JOIN custom_variable_configs cvarcfg ON (cvar.config_id = cvarcfg.id)
438              WHERE (cvarcfg.module = ?)
439                AND (cvarcfg.id     = ?)
440                AND (cvar.trans_id  = $params{trans_id_field})
441                AND | . join(' AND ', map { "($_)" } @sub_where) . qq|)|;
442       push @values, $params{module}, conv_i($config->{id}), @sub_values;
443     }
444   }
445
446   my $query = join ' AND ', @where;
447
448   $main::lxdebug->leave_sub();
449
450   return ($query, @values);
451 }
452
453 sub add_custom_variables_to_report {
454   $main::lxdebug->enter_sub();
455
456   my $self      = shift;
457   my %params    = @_;
458
459   Common::check_params(\%params, qw(module trans_id_field column_defs data configs));
460
461   my $myconfig  = \%main::myconfig;
462   my $form      = $main::form;
463   my $locale    = $main::locale;
464
465   my $dbh       = $params{dbh} || $form->get_standard_dbh($myconfig);
466
467   my $configs   = [ grep { $_->{includeable} && $params{column_defs}->{"cvar_$_->{name}"}->{visible} } @{ $params{configs} } ];
468
469   if (!scalar(@{ $params{data} }) || ! scalar(@{ $configs })) {
470     $main::lxdebug->leave_sub();
471     return;
472   }
473
474   # allow sub_module to be a coderef or a fixed value
475   if (ref $params{sub_module} ne 'CODE') {
476     my $sub_module = "$params{sub_module}";
477     $params{sub_module} = sub { $sub_module };
478   }
479
480   my %cfg_map   = map { $_->{id} => $_ } @{ $configs };
481   my @cfg_ids   = keys %cfg_map;
482
483   my $query     =
484     qq|SELECT text_value, timestamp_value, timestamp_value::date AS date_value, number_value, bool_value, config_id
485        FROM custom_variables
486        WHERE (config_id IN (| . join(', ', ('?') x scalar(@cfg_ids)) . qq|))
487          AND (trans_id = ?)
488          AND (sub_module = ?)|;
489   my $sth       = prepare_query($form, $dbh, $query);
490
491   foreach my $row (@{ $params{data} }) {
492     do_statement($form, $sth, $query, @cfg_ids, conv_i($row->{$params{trans_id_field}}), $params{sub_module}->($row));
493
494     while (my $ref = $sth->fetchrow_hashref()) {
495       my $cfg = $cfg_map{$ref->{config_id}};
496
497       $row->{"cvar_$cfg->{name}"} =
498           $cfg->{type} eq 'date'      ? $ref->{date_value}
499         : $cfg->{type} eq 'timestamp' ? $ref->{timestamp_value}
500         : $cfg->{type} eq 'number'    ? $form->format_amount($myconfig, $ref->{number_value} * 1, $cfg->{precision})
501         : $cfg->{type} eq 'customer'  ? (SL::DB::Manager::Customer->find_by(id => 1*$ref->{number_value}) || SL::DB::Customer->new)->name
502         : $cfg->{type} eq 'vendor'    ? (SL::DB::Manager::Vendor->find_by(id => 1*$ref->{number_value})   || SL::DB::Vendor->new)->name
503         : $cfg->{type} eq 'part'      ? (SL::DB::Manager::Part->find_by(id => 1*$ref->{number_value})     || SL::DB::Part->new)->partnumber
504         : $cfg->{type} eq 'bool'      ? ($ref->{bool_value} ? $locale->text('Yes') : $locale->text('No'))
505         :                               $ref->{text_value};
506     }
507   }
508
509   $sth->finish();
510
511   $main::lxdebug->leave_sub();
512 }
513
514 sub get_field_format_list {
515   $main::lxdebug->enter_sub();
516
517   my $self          = shift;
518   my %params        = @_;
519
520   Common::check_params(\%params, qw(module));
521
522   my $myconfig      = \%main::myconfig;
523   my $form          = $main::form;
524
525   my $dbh           = $params{dbh} || $form->get_standard_dbh($myconfig);
526
527   my $configs       = $self->get_configs(%params);
528
529   my $date_fields   = [];
530   my $number_fields = {};
531
532   foreach my $config (@{ $configs }) {
533     my $name = "$params{prefix}cvar_$config->{name}";
534
535     if ($config->{type} eq 'date') {
536       push @{ $date_fields }, $name;
537
538     } elsif ($config->{type} eq 'number') {
539       $number_fields->{$config->{precision}} ||= [];
540       push @{ $number_fields->{$config->{precision}} }, $name;
541     }
542   }
543
544   $main::lxdebug->leave_sub();
545
546   return ($date_fields, $number_fields);
547 }
548
549 sub save_custom_variables_validity {
550   $main::lxdebug->enter_sub();
551
552   my $self     = shift;
553   my %params   = @_;
554
555   Common::check_params(\%params, qw(config_id trans_id validity));
556
557   my $myconfig = \%main::myconfig;
558   my $form     = $main::form;
559
560   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
561
562   my (@where, @values);
563   add_token(\@where, \@values, col => "config_id", val => $params{config_id}, esc => \&conv_i);
564   add_token(\@where, \@values, col => "trans_id",  val => $params{trans_id},  esc => \&conv_i);
565
566   my $where = scalar @where ? "WHERE " . join ' AND ', @where : '';
567   my $query = qq|DELETE FROM custom_variables_validity $where|;
568
569   do_query($form, $dbh, $query, @values);
570
571   $query  =
572     qq|INSERT INTO custom_variables_validity (config_id, trans_id)
573        VALUES                                (?,         ?       )|;
574   my $sth = prepare_query($form, $dbh, $query);
575
576   unless ($params{validity}) {
577     foreach my $config_id (listify($params{config_id})) {
578       foreach my $trans_id (listify($params{trans_id})) {
579         do_statement($form, $sth, $query, conv_i($config_id), conv_i($trans_id));
580       }
581     }
582   }
583
584   $sth->finish();
585
586   $dbh->commit() unless $params{dbh};
587
588   $main::lxdebug->leave_sub();
589 }
590
591 sub get_custom_variables_validity {
592   $main::lxdebug->enter_sub(2);
593
594   my $self     = shift;
595   my %params   = @_;
596
597   Common::check_params(\%params, qw(config_id trans_id));
598
599   my $myconfig = \%main::myconfig;
600   my $form     = $main::form;
601
602   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
603
604   my $query    = qq|SELECT id FROM custom_variables_validity WHERE config_id = ? AND trans_id = ? LIMIT 1|;
605
606   my ($invalid) = selectfirst_array_query($form, $dbh, $query, conv_i($params{config_id}), conv_i($params{trans_id}));
607
608   $main::lxdebug->leave_sub(2);
609
610   return !$invalid;
611 }
612
613 sub custom_variables_validity_by_trans_id {
614   $main::lxdebug->enter_sub(2);
615
616   my $self     = shift;
617   my %params   = @_;
618
619   return sub { 0 } unless $params{trans_id};
620
621   my $myconfig = \%main::myconfig;
622   my $form     = $main::form;
623
624   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
625
626   my $query    = qq|SELECT DISTINCT config_id FROM custom_variables_validity WHERE trans_id = ?|;
627
628   my %invalids = map { +($_->{config_id} => 1) } selectall_hashref_query($form, $dbh, $query, $params{trans_id});
629
630   $main::lxdebug->leave_sub(2);
631
632   return sub { !$invalids{+shift} };
633 }
634
635 sub parse {
636   my ($self, $value, $config) = @_;
637
638   return $::form->parse_amount(\%::myconfig, $value)          if $config->{type} eq 'number';
639   return DateTime->from_lxoffice($value)                      if $config->{type} eq 'date';
640   return !ref $value ? SL::DB::Manager::Customer->find_by(id => $value * 1) : $value  if $config->{type} eq 'customer';
641   return !ref $value ? SL::DB::Manager::Vendor->find_by(id => $value * 1)   : $value  if $config->{type} eq 'vendor';
642   return !ref $value ? SL::DB::Manager::Part->find_by(id => $value * 1)     : $value  if $config->{type} eq 'part';
643   return $value;
644 }
645
646 sub format_to_template {
647   my ($self, $value, $config) = @_;
648   # stupid template expects everything formated. except objects
649   # do not use outside of print routines for legacy templates
650
651   return $::form->format_amount(\%::myconfig, $value) if $config->{type} eq 'number';
652   return $value->to_lxoffice if $config->{type} eq 'date' && blessed $value && $value->can('to_lxoffice');
653   return $value;
654 }
655
656 sub get_non_editable_ic_cvars {
657   $main::lxdebug->enter_sub(2);
658   my $self     = shift;
659   my %params   = @_;
660
661   Common::check_params(\%params, qw(form dbh row sub_module may_converted_from));
662   my $form               = $params{form};
663   my $dbh                = $params{dbh};
664   my $row                = $params{row};
665   my $sub_module         = $params{sub_module};
666   my $may_converted_from = $params{may_converted_from};
667
668   my $cvars;
669   if (! $form->{"${sub_module}_id_${row}"}) {
670     my $conv_from = 0;
671     foreach (@{ $may_converted_from }) {
672       if ($form->{"converted_from_${_}_id_$row"}) {
673         $cvars = CVar->get_custom_variables(dbh        => $dbh,
674                                             module     => 'IC',
675                                             sub_module => $_,
676                                             trans_id   => $form->{"converted_from_${_}_id_$row"},
677                                            );
678         $conv_from = 1;
679         last;
680       }
681     }
682     # get values for CVars from master data for new items
683     if (!$conv_from) {
684       $cvars = CVar->get_custom_variables(dbh      => $dbh,
685                                           module   => 'IC',
686                                           trans_id => $form->{"id_$row"},
687                                          );
688     }
689   } else {
690     # get values for CVars from custom_variables for existing items
691     $cvars = CVar->get_custom_variables(dbh        => $dbh,
692                                         module     => 'IC',
693                                         sub_module => $sub_module,
694                                         trans_id   => $form->{"${sub_module}_id_${row}"},
695                                        );
696   }
697   # map only non-editable CVars to form
698   foreach (@{ $cvars }) {
699     next if $_->{flag_editable};
700     $form->{"ic_cvar_$_->{name}_$row"} = $_->{value}
701   }
702
703   $main::lxdebug->leave_sub(2);
704 }
705
706 1;
707
708 __END__
709
710 =head1 NAME
711
712 SL::CVar.pm - Custom Variables module
713
714 =head1 SYNOPSIS
715
716   # dealing with configs
717
718   my $all_configs = CVar->get_configs()
719
720   # dealing with custom vars
721
722   CVar->get_custom_variables(module => 'ic')
723
724 =head2 VALIDITY
725
726 Suppose the following scenario:
727
728 You have a lot of parts in your database, and a set of properties configured. Now not every part has every of these properties, some combinations will just make no sense. In order to clean up your inputs a bit, you want to mark certain combinations as invalid, blocking them from modification and possibly display.
729
730 Validity is assumed. If you modify validity, you actually save B<invalidity>.
731 Invalidity is saved as a function of config_id, and the trans_id
732
733 In the naive way, disable an attribute for a specific id (simple)
734
735 =cut