Revision 81be8de1
Von Bernd Bleßmann vor mehr als 3 Jahren hinzugefügt
SL/DB/TimeRecording.pm | ||
---|---|---|
5 | 5 |
|
6 | 6 |
use strict; |
7 | 7 |
|
8 |
use SL::Locale::String qw(t8); |
|
9 |
|
|
10 |
use SL::DB::Helper::AttrDuration; |
|
11 |
use SL::DB::Helper::AttrHTML; |
|
12 |
|
|
8 | 13 |
use SL::DB::MetaSetup::TimeRecording; |
9 | 14 |
use SL::DB::Manager::TimeRecording; |
10 | 15 |
|
11 | 16 |
__PACKAGE__->meta->initialize; |
12 | 17 |
|
18 |
__PACKAGE__->attr_duration_minutes(qw(duration)); |
|
19 |
|
|
20 |
__PACKAGE__->attr_html('description'); |
|
21 |
|
|
22 |
__PACKAGE__->before_save('_before_save_check_valid'); |
|
23 |
|
|
24 |
sub _before_save_check_valid { |
|
25 |
my ($self) = @_; |
|
26 |
|
|
27 |
my @errors = $self->validate; |
|
28 |
return (scalar @errors == 0); |
|
29 |
} |
|
30 |
|
|
31 |
sub validate { |
|
32 |
my ($self) = @_; |
|
33 |
|
|
34 |
my @errors; |
|
35 |
|
|
36 |
push @errors, t8('Start time must not be empty.') if !$self->start_time; |
|
37 |
push @errors, t8('Customer must not be empty.') if !$self->customer_id; |
|
38 |
push @errors, t8('Staff member must not be empty.') if !$self->staff_member_id; |
|
39 |
push @errors, t8('Employee must not be empty.') if !$self->employee_id; |
|
40 |
push @errors, t8('Description must not be empty.') if !$self->description; |
|
41 |
push @errors, t8('Start time must be earlier than end time.') if $self->is_time_in_wrong_order; |
|
42 |
|
|
43 |
my $conflict = $self->is_time_overlapping; |
|
44 |
push @errors, t8('Entry overlaps with "#1".', $conflict->displayable_times) if $conflict; |
|
45 |
|
|
46 |
return @errors; |
|
47 |
} |
|
48 |
|
|
49 |
sub is_time_overlapping { |
|
50 |
my ($self) = @_; |
|
51 |
|
|
52 |
# Do not allow overlapping time periods. |
|
53 |
# Start time can be equal to another end time |
|
54 |
# (an end time can be equal to another start time) |
|
55 |
|
|
56 |
# We cannot check if no staff member is given. |
|
57 |
return if !$self->staff_member_id; |
|
58 |
|
|
59 |
# If no start time and no end time are given, there is no overlapping. |
|
60 |
return if !($self->start_time || $self->end_time); |
|
61 |
|
|
62 |
my $conflicting; |
|
63 |
|
|
64 |
# Start time or end time can be undefined. |
|
65 |
if (!$self->start_time) { |
|
66 |
$conflicting = SL::DB::Manager::TimeRecording->get_all(where => [ and => [ '!id' => $self->id, |
|
67 |
staff_member_id => $self->staff_member_id, |
|
68 |
start_time => {lt => $self->end_time}, |
|
69 |
end_time => {ge => $self->end_time} ] ], |
|
70 |
sort_by => 'start_time DESC', |
|
71 |
limit => 1); |
|
72 |
} elsif (!$self->end_time) { |
|
73 |
$conflicting = SL::DB::Manager::TimeRecording->get_all(where => [ and => [ '!id' => $self->id, |
|
74 |
staff_member_id => $self->staff_member_id, |
|
75 |
or => [ and => [start_time => {le => $self->start_time}, |
|
76 |
end_time => {gt => $self->start_time} ], |
|
77 |
start_time => $self->start_time, |
|
78 |
], |
|
79 |
], |
|
80 |
], |
|
81 |
sort_by => 'start_time DESC', |
|
82 |
limit => 1); |
|
83 |
} else { |
|
84 |
$conflicting = SL::DB::Manager::TimeRecording->get_all(where => [ and => [ '!id' => $self->id, |
|
85 |
staff_member_id => $self->staff_member_id, |
|
86 |
or => [ and => [ start_time => {lt => $self->end_time}, |
|
87 |
end_time => {gt => $self->start_time} ] , |
|
88 |
or => [ start_time => $self->start_time, |
|
89 |
end_time => $self->end_time, ], |
|
90 |
] |
|
91 |
] |
|
92 |
], |
|
93 |
sort_by => 'start_time DESC', |
|
94 |
limit => 1); |
|
95 |
} |
|
96 |
|
|
97 |
return $conflicting->[0] if @$conflicting; |
|
98 |
return; |
|
99 |
} |
|
100 |
|
|
101 |
sub is_time_in_wrong_order { |
|
102 |
my ($self) = @_; |
|
103 |
|
|
104 |
if ($self->start_time && $self->end_time |
|
105 |
&& $self->start_time >= $self->end_time) { |
|
106 |
return 1; |
|
107 |
} |
|
108 |
|
|
109 |
return; |
|
110 |
} |
|
111 |
|
|
112 |
sub displayable_times { |
|
113 |
my ($self) = @_; |
|
114 |
|
|
115 |
# placeholder |
|
116 |
my $ph = $::locale->format_date_object(DateTime->new(year => 1111, month => 11, day => 11, hour => 11, minute => 11), precision => 'minute'); |
|
117 |
$ph =~ s{1}{-}g; |
|
118 |
|
|
119 |
return ($self->start_time_as_timestamp||$ph) . ' - ' . ($self->end_time_as_timestamp||$ph); |
|
120 |
} |
|
121 |
|
|
122 |
sub duration { |
|
123 |
my ($self) = @_; |
|
124 |
|
|
125 |
if ($self->start_time && $self->end_time) { |
|
126 |
return ($self->end_time->subtract_datetime_absolute($self->start_time))->seconds/60.0; |
|
127 |
} else { |
|
128 |
return; |
|
129 |
} |
|
130 |
} |
|
131 |
|
|
13 | 132 |
1; |
Auch abrufbar als: Unified diff
Zeiterfassung: Controller