1 package SL::DB::Helper::AttrDuration;
5 use parent qw(Exporter);
6 our @EXPORT = qw(attr_duration attr_duration_minutes);
11 my ($package, @attributes) = @_;
13 _make($package, $_) for @attributes;
16 sub attr_duration_minutes {
17 my ($package, @attributes) = @_;
19 _make_minutes($package, $_) for @attributes;
23 my ($package, $attribute) = @_;
27 *{ $package . '::' . $attribute . '_as_hours' } = sub {
28 my ($self, $value) = @_;
30 $self->$attribute(int($value) + ($self->$attribute - int($self->$attribute))) if @_ > 1;
31 return int($self->$attribute // 0);
34 *{ $package . '::' . $attribute . '_as_minutes' } = sub {
35 my ($self, $value) = @_;
37 $self->$attribute(int($self->$attribute) * 1.0 + ($value // 0) / 60.0) if @_ > 1;
38 return int(($self->$attribute // 0) * 60.0 + 0.5) % 60;
41 *{ $package . '::' . $attribute . '_as_duration_string' } = sub {
42 my ($self, $value) = @_;
44 $self->$attribute(defined($value) ? $::form->parse_amount(\%::myconfig, $value) * 1 : undef) if @_ > 1;
45 return defined($self->$attribute) ? $::form->format_amount(\%::myconfig, $self->$attribute // 0, 2) : undef;
48 *{ $package . '::' . $attribute . '_as_man_days' } = sub {
49 my ($self, $value) = @_;
52 return undef if !defined $value;
53 $self->$attribute($value);
55 $value = $self->$attribute // 0;
56 return $value >= 8.0 ? $value / 8.0 : $value;
59 *{ $package . '::' . $attribute . '_as_man_days_unit' } = sub {
60 my ($self, $unit) = @_;
63 return undef if !defined $unit;
64 croak "Unknown unit '${unit}'" if $unit !~ m/^(?:h|hour|man_day)$/;
65 $self->$attribute(($self->$attribute // 0) * 8.0) if $unit eq 'man_day';
68 return ($self->$attribute // 0) >= 8.0 ? 'man_day' : 'h'
71 *{ $package . '::' . $attribute . '_as_man_days_string' } = sub {
72 my ($self, $value) = @_;
73 my $method = "${attribute}_as_man_days";
76 return undef if !defined $value;
77 $self->$method($::form->parse_amount(\%::myconfig, $value));
80 return $::form->format_amount(\%::myconfig, $self->$method // 0, 2);
85 my ($package, $attribute) = @_;
89 *{ $package . '::' . $attribute . '_as_hours' } = sub {
90 my ($self, $value) = @_;
92 $self->$attribute($value * 60 + ($self->$attribute % 60)) if @_ > 1;
93 return int(($self->$attribute // 0) / 60);
96 *{ $package . '::' . $attribute . '_as_minutes' } = sub {
97 my ($self, $value) = @_;
99 $self->$attribute(int($self->$attribute) - (int($self->$attribute) % 60) + ($value // 0)) if @_ > 1;
100 return ($self->$attribute // 0) % 60;
103 *{ $package . '::' . $attribute . '_as_duration_string' } = sub {
104 my ($self, $value) = @_;
107 if (!defined($value) || ($value eq '')) {
108 $self->$attribute(undef);
110 croak $::locale->text("Invalid duration format") if $value !~ m{^(?:(\d*):)?(\d+)$};
111 $self->$attribute(($1 // 0) * 60 + ($2 // 0));
115 my $as_hours = "${attribute}_as_hours";
116 my $as_minutes = "${attribute}_as_minutes";
117 return defined($self->$attribute) ? sprintf('%d:%02d', $self->$as_hours, $self->$as_minutes) : undef;
130 SL::DB::Helper::AttrDuration - Attribute helper for duration stored in
136 use SL::DB::Helper::AttrDuration;
137 __PACKAGE__->attr_duration('time_estimation');
138 __PACKAGE__->attr_duration_minutes('hours');
141 print "Minutes: " . $obj->time_estimation_as_minutes . " hours: " . $obj->time_estimation_as_hours . "\n";
143 # Use formatted strings in input fields in templates:
146 [% L.input_tag('time_estimation_as_duration_string', SELF.obj.time_estimation_as_duration_string) %]
151 This is a helper for columns that store a duration in one of two formats:
155 =item 1. as a numeric or floating point number representing a number
158 =item 2. as an integer presenting a number of minutes
162 In the first case the value 1.75 would stand for "1 hour, 45
163 minutes". In the second case the value 105 represents the same
166 The helper methods created depend on the mode. Calling
167 C<attr_duration> makes the following methods available:
171 =item C<attribute_as_minutes [$new_value]>
173 Access only the minutes. Return values are in the range [0 - 59].
175 =item C<attribute_as_hours [$new_value]>
177 Access only the hours. Returns an integer value.
179 =item C<attribute_as_duration_string [$new_value]>
181 Access the full value as a formatted string according to the user's
184 =item C<attribute_as_man_days [$new_value]>
186 Access the attribute as a number of man days which are assumed to be 8
187 hours long. If the underlying attribute is less than 8 then the value
188 itself will be returned. Otherwise the value divided by 8 is returned.
190 If used as a setter then the underlying attribute is simply set to
191 C<$new_value>. Intentional use is to set the man days first and the
194 $obj->attribute_as_man_days($::form->{attribute_as_man_days});
195 $obj->attribute_as_man_days_unit($::form->{attribute_as_man_days_unit});
197 Note that L<SL::DB::Object/assign_attributes> is aware of this and
198 handles this case correctly.
200 =item C<attribute_as_man_days_unit [$new_unit]>
202 Returns the unit that the number returned by L</attribute_as_man_days>
203 represents. This can be either C<h> if the underlying attribute is
204 less than 8 and C<man_day> otherwise.
206 If used as a setter then the underlying attribute is multiplied by 8
207 if C<$new_unit> equals C<man_day>. Otherwise the underlying attribute
208 is not modified. Intentional use is to set the man days first and the
211 $obj->attribute_as_man_days($::form->{attribute_as_man_days});
212 $obj->attribute_as_man_days_unit($::form->{attribute_as_man_days_unit});
214 Note that L<SL::DB::Object/assign_attributes> is aware of this and
215 handles this case correctly.
219 With C<attr_duration_minutes> the following methods are available:
223 =item C<attribute_as_minutes [$new_value]>
225 Access only the minutes. Return values are in the range [0 - 59].
227 =item C<attribute_as_hours [$new_value]>
229 Access only the hours. Returns an integer value.
231 =item C<attribute_as_duration_string [$new_value]>
233 Access the full value as a formatted string in the form C<h:mm>,
234 e.g. C<1:30> for the value 90 minutes. Parsing such a string is
243 =item C<attr_duration @attributes>
245 Package method. Call with the names of attributes for which the helper
246 methods should be created.
248 =item C<attr_duration_minutes @attributes>
250 Package method. Call with the names of attributes for which the helper
251 methods should be created.
261 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>