1 # This file has been auto-generated only because it didn't exist.
2 # Feel free to modify it at will; it will not be overwritten automatically.
4 package SL::DB::TimeRecording;
8 use SL::Locale::String qw(t8);
10 use SL::DB::Helper::AttrDuration;
11 use SL::DB::Helper::AttrHTML;
13 use SL::DB::MetaSetup::TimeRecording;
14 use SL::DB::Manager::TimeRecording;
16 __PACKAGE__->meta->initialize;
18 __PACKAGE__->attr_duration_minutes(qw(duration));
20 __PACKAGE__->attr_html('description');
22 __PACKAGE__->before_save('_before_save_check_valid');
24 sub _before_save_check_valid {
27 my @errors = $self->validate;
28 return (scalar @errors == 0);
36 push @errors, t8('Customer must not be empty.') if !$self->customer_id;
37 push @errors, t8('Staff member must not be empty.') if !$self->staff_member_id;
38 push @errors, t8('Employee must not be empty.') if !$self->employee_id;
39 push @errors, t8('Description must not be empty.') if !$self->description;
40 push @errors, t8('Start time must be earlier than end time.') if $self->is_time_in_wrong_order;
42 my $conflict = $self->is_time_overlapping;
43 push @errors, t8('Entry overlaps with "#1".', $conflict->displayable_times) if $conflict;
48 sub is_time_overlapping {
51 # Do not allow overlapping time periods.
52 # Start time can be equal to another end time
53 # (an end time can be equal to another start time)
55 # We cannot check if no staff member is given.
56 return if !$self->staff_member_id;
58 # If no start time and no end time are given, there is no overlapping.
59 return if !($self->start_time || $self->end_time);
63 # Start time or end time can be undefined.
64 if (!$self->start_time) {
65 $conflicting = SL::DB::Manager::TimeRecording->get_all(where => [ and => [ '!id' => $self->id,
66 staff_member_id => $self->staff_member_id,
67 start_time => {lt => $self->end_time},
68 end_time => {ge => $self->end_time} ] ],
69 sort_by => 'start_time DESC',
71 } elsif (!$self->end_time) {
72 $conflicting = SL::DB::Manager::TimeRecording->get_all(where => [ and => [ '!id' => $self->id,
73 staff_member_id => $self->staff_member_id,
74 or => [ and => [start_time => {le => $self->start_time},
75 end_time => {gt => $self->start_time} ],
76 start_time => $self->start_time,
80 sort_by => 'start_time DESC',
83 $conflicting = SL::DB::Manager::TimeRecording->get_all(where => [ and => [ '!id' => $self->id,
84 staff_member_id => $self->staff_member_id,
85 or => [ and => [ start_time => {lt => $self->end_time},
86 end_time => {gt => $self->start_time} ] ,
87 or => [ start_time => $self->start_time,
88 end_time => $self->end_time, ],
92 sort_by => 'start_time DESC',
96 return $conflicting->[0] if @$conflicting;
100 sub is_time_in_wrong_order {
103 if ($self->start_time && $self->end_time
104 && $self->start_time >= $self->end_time) {
111 sub is_duration_used {
112 return !$_[0]->start_time;
115 sub displayable_times {
120 if ($self->is_duration_used) {
121 $text = $self->date_as_date . ': ' . ($self->duration_as_duration_string || '--:--');
125 my $ph = $::locale->format_date_object(DateTime->new(year => 1111, month => 11, day => 11, hour => 11, minute => 11), precision => 'minute');
127 $text = ($self->start_time_as_timestamp||$ph) . ' - ' . ($self->end_time_as_timestamp||$ph);