Bug 30650: Notify the patron when a new curbside pickup is created
[koha.git] / Koha / CurbsidePickupPolicy.pm
1 package Koha::CurbsidePickupPolicy;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19
20 use Koha::Database;
21 use Koha::Library;
22 use Koha::CurbsidePickupOpeningSlots;
23
24 use Koha::Result::Boolean;
25 use Koha::Exceptions::CurbsidePickup;
26
27 use base qw(Koha::Object);
28
29 =head1 NAME
30
31 Koha::CurbsidePickupPolicy - Koha Curbside Pickup Policy Object class
32
33 =head1 API
34
35 =head2 Class methods
36
37 =head3 library
38
39 Return the branch associated with this policy
40
41 =cut
42
43 sub library {
44     my ( $self ) = @_;
45     my $rs = $self->_result->branchcode;
46     return unless $rs;
47     return Koha::Library->_new_from_dbic( $rs );
48 }
49
50 sub opening_slots {
51     my ( $self ) = @_;
52     my $rs = $self->_result->curbside_pickup_opening_slots;
53     return unless $rs;
54     return Koha::CurbsidePickupOpeningSlots->_new_from_dbic( $rs );
55 }
56
57 sub add_opening_slot {
58     my ( $self, $slot ) = @_;
59
60     my ( $day, $start, $end ) = split '-', $slot;
61     my ( $start_hour, $start_minute ) = split ':', $start;
62     my ( $end_hour,   $end_minute )   = split ':', $end;
63
64     return Koha::CurbsidePickupOpeningSlot->new(
65         {
66             curbside_pickup_policy_id => $self->id,
67             day                       => $day,
68             start_hour                => $start_hour,
69             start_minute              => $start_minute,
70             end_hour                  => $end_hour,
71             end_minute                => $end_minute,
72         }
73     )->store;
74 }
75
76 =head3 is_valid_pickup_datetime
77
78 =cut
79
80 sub is_valid_pickup_datetime {
81     my ( $self, $datetime ) = @_;
82
83     my $opening_slots =
84       $self->opening_slots->search( { day => $datetime->dow % 7 } );
85     my $matching_slot;
86     while ( my $opening_slot = $opening_slots->next ) {
87         my $start = $datetime->clone->set_hour( $opening_slot->start_hour )
88           ->set_minute( $opening_slot->start_minute );
89         my $end = $datetime->clone->set_hour( $opening_slot->end_hour )
90           ->set_minute( $opening_slot->start_minute );
91         my $keep_going = 1;
92         my $slot_start = $start->clone;
93         my $slot_end = $slot_start->clone->add(minutes => $self->pickup_interval);
94         while ($slot_end <= $end) {
95             if ( $slot_start == $datetime ) {
96                 $matching_slot = $slot_start;
97                 last;
98             }
99             $slot_start->add( minutes => $self->pickup_interval);
100             $slot_end->add( minutes => $self->pickup_interval);
101         }
102     }
103
104     return Koha::Result::Boolean->new(0)
105       ->add_message( { message => 'no_matching_slots' } )
106       unless $matching_slot;
107
108     my $dtf  = Koha::Database->new->schema->storage->datetime_parser;
109     # Check too many users for this slot
110     my $existing_pickups = Koha::CurbsidePickups->search(
111         {
112             branchcode                => $self->branchcode,
113             scheduled_pickup_datetime => $dtf->format_datetime($matching_slot),
114         }
115     );
116
117     return Koha::Result::Boolean->new(0)
118       ->add_message( { message => 'no_more_available' } )
119       if $existing_pickups->count >= $self->patrons_per_interval;
120
121     return 1;
122 }
123
124 =head2 Internal methods
125
126 =head3 _type
127
128 =cut
129
130 sub _type {
131     return 'CurbsidePickupPolicy';
132 }
133
134 1;