6f2dd55e264ee1c92e05b7a0bf60b819be17daeb
[kivitendo-erp.git] / SL / DB / Helper / Attr.pm
1 package SL::DB::Helper::Attr;
2
3 use strict;
4
5 sub auto_make {
6   my ($package, %params) = @_;
7
8   for my $col ($package->meta->columns) {
9     next if $col->primary_key_position; # don't make attr helper for primary keys
10     _make_by_type($package, $col->name, $col->type);
11   }
12
13   return $package;
14 }
15
16 sub make {
17   my ($package, %params) = @_;
18
19   for my $name (keys %params) {
20     my @types = ref $params{$name} eq 'ARRAY' ? @{ $params{$name} } : ($params{$name});
21     for my $type (@types) {
22       _make_by_type($package, $name, $type);
23     }
24   }
25   return $package;
26 }
27
28
29
30 sub _make_by_type {
31   my ($package, $name, $type) = @_;
32   _as_number ($package, $name, places => -2) if $type =~ /numeric | real | float/xi;
33   _as_percent($package, $name, places =>  2) if $type =~ /numeric | real | float/xi;
34   _as_number ($package, $name, places =>  0) if $type =~ /int/xi;
35   _as_date   ($package, $name)               if $type =~ /date | timestamp/xi;
36   _as_timestamp($package, $name)             if $type =~ /timestamp/xi;
37   _as_bool_yn($package, $name)               if $type =~ /bool/xi;
38 }
39
40 sub _as_number {
41   my $package     = shift;
42   my $attribute   = shift;
43   my %params      = @_;
44
45   $params{places} = 2 if !defined($params{places});
46
47   no strict 'refs';
48   *{ $package . '::' . $attribute . '_as_number' } = sub {
49     my ($self, $string) = @_;
50
51     $self->$attribute($::form->parse_amount(\%::myconfig, $string)) if @_ > 1;
52
53     return $::form->format_amount(\%::myconfig, $self->$attribute, $params{places});
54   };
55 }
56
57 sub _as_percent {
58   my $package     = shift;
59   my $attribute   = shift;
60   my %params      = @_;
61
62   $params{places} = 2 if !defined($params{places});
63
64   no strict 'refs';
65   *{ $package . '::' . $attribute . '_as_percent' } = sub {
66     my ($self, $string) = @_;
67
68     $self->$attribute($::form->parse_amount(\%::myconfig, $string) / 100) if @_ > 1;
69
70     return $::form->format_amount(\%::myconfig, 100 * $self->$attribute, $params{places});
71   };
72
73   return 1;
74 }
75
76 sub _as_date {
77   my $package     = shift;
78   my $attribute   = shift;
79   my %params      = @_;
80
81   no strict 'refs';
82   *{ $package . '::' . $attribute . '_as_date' } = sub {
83     my ($self, $string) = @_;
84
85     if (@_ > 1) {
86       if ($string) {
87         my ($yy, $mm, $dd) = $::locale->parse_date(\%::myconfig, $string);
88         $self->$attribute(DateTime->new(year => $yy, month => $mm, day => $dd));
89       } else {
90         $self->$attribute(undef);
91       }
92     }
93
94     return $self->$attribute
95       ? $::locale->reformat_date(
96           { dateformat => 'yy-mm-dd' },
97           ( ($self->$attribute eq 'now' || $self->$attribute eq 'now()')
98              ? DateTime->now
99              : $self->$attribute
100           )->ymd,
101           $::myconfig{dateformat}
102         )
103       : undef;
104   };
105
106   return 1;
107 }
108
109 sub _as_timestamp {
110   my $package     = shift;
111   my $attribute   = shift;
112   my %params      = @_;
113
114   my $accessor    = sub {
115     my ($precision, $self, $string) = @_;
116
117     $self->$attribute($string ? $::locale->parse_date_to_object($string) : undef) if @_ > 2;
118
119     my $dt = $self->$attribute;
120     return undef unless $dt;
121
122     $dt = DateTime->now if !ref($dt) && ($dt eq 'now');
123
124     return $::locale->format_date_object($dt, precision => $precision);
125   };
126
127   no strict 'refs';
128   *{ $package . '::' . $attribute . '_as_timestamp'    } = sub { $accessor->('minute',      @_) };
129   *{ $package . '::' . $attribute . '_as_timestamp_s'  } = sub { $accessor->('second',      @_) };
130   *{ $package . '::' . $attribute . '_as_timestamp_ms' } = sub { $accessor->('millisecond', @_) };
131
132   return 1;
133 }
134
135 sub _as_bool_yn {
136   my ($package, $attribute, %params) = @_;
137
138   no strict 'refs';
139   *{ $package . '::' . $attribute . '_as_bool_yn' } = sub {
140     my ($self) = @_;
141
142     if (@_ > 1) {
143       die 'not an accessor';
144     }
145
146     return !defined $self->$attribute ? ''
147          :          $self->$attribute ? $::locale->text('Yes')
148          :                              $::locale->text('No');
149   }
150 }
151
152 1;
153
154
155 1;
156
157 __END__
158
159 =encoding utf-8
160
161 =head1 NAME
162
163 SL::DB::Helper::Attr - attribute helpers
164
165 =head1 SYNOPSIS
166
167   use SL::DB::Helper::Attr;
168   SL::DB::Helper::Attr::make($class,
169     method_name => 'numeric(15,5)',
170     datemethod  => 'date'
171   );
172   SL::DB::Helper::Attr::auto_make($class);
173
174 =head1 DESCRIPTION
175
176 Makes attribute helpers.
177
178 =head1 FUNCTIONS
179
180 see for yourself.
181
182 =head1 BUGS
183
184 None yet.
185
186 =head1 AUTHOR
187
188 Sven Schöling <s.schoeling@linet-services.de>,
189 Moritz Bunkus <m.bunkus@linet-services.de>
190
191 =cut