From 2c6d57c25405545465ecef34c6b96df1f4015bde Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Tue, 13 Jun 2023 14:11:17 +0100 Subject: [PATCH] Bug 29002: Assign item at time of booking This patch updates the logic to ensure we always assign an item at the point of booking instead of assuming we can assign the item at fulfilment time. This makes the logic significantly simpler on the client when trying to calculate available dates. Test plan 1) Attempt to create a new booking using the 'Any item' option in the modal 2) Note that upon placing your booking you are assigned an item for that booking. NOTE: We add a FIXME to the client code to highlight something to test when/if someone decides to have another try and moving the item assigment to just in time as aposed to up front. Signed-off-by: Martin Renvoize Signed-off-by: Janet McGowan Signed-off-by: Caroline Cyr La Rose Signed-off-by: Laurence Rault Signed-off-by: Kyle M Hall Signed-off-by: Tomas Cohen Arazi --- Koha/Biblio.pm | 39 +++++++++++++++++++ Koha/Booking.pm | 26 ++++++++++--- .../prog/js/place_booking_modal.js | 12 ++++++ 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/Koha/Biblio.pm b/Koha/Biblio.pm index 10959879b3..fea47ea986 100644 --- a/Koha/Biblio.pm +++ b/Koha/Biblio.pm @@ -270,6 +270,45 @@ sub check_booking { return ( ( $total_bookable - $booked_count ) > 0 ) ? 1 : 0; } +=head3 assign_item_for_booking + +=cut + +sub assign_item_for_booking { + my ( $self, $params ) = @_; + + my $start_date = dt_from_string( $params->{start_date} ); + my $end_date = dt_from_string( $params->{end_date} ); + + my $dtf = Koha::Database->new->schema->storage->datetime_parser; + my $existing_bookings = $self->bookings( + [ + start_date => { + '-between' => [ + $dtf->format_datetime($start_date), + $dtf->format_datetime($end_date) + ] + }, + end_date => { + '-between' => [ + $dtf->format_datetime($start_date), + $dtf->format_datetime($end_date) + ] + }, + { + start_date => { '<' => $dtf->format_datetime($start_date) }, + end_date => { '>' => $dtf->format_datetime($end_date) } + } + ] + ); + + my $bookable_items = $self->bookable_items->search( + { itemnumber => { '-not_in' => $existing_bookings->_resultset->get_column('item_id')->as_query } }, + { rows => 1 } + ); + return $bookable_items->single->itemnumber; +} + =head3 place_booking my $booking = $biblio->place_booking( diff --git a/Koha/Booking.pm b/Koha/Booking.pm index bb8ff26b30..273d3e9f3f 100644 --- a/Koha/Booking.pm +++ b/Koha/Booking.pm @@ -90,10 +90,10 @@ sub store { ) unless ( $self->item ); $self->biblio_id( $self->item->biblionumber ) - unless $self->biblio_id; + unless $self->biblio_id; Koha::Exceptions::Object::FKConstraint->throw() - unless ( $self->biblio_id == $self->item->biblionumber ); + unless ( $self->biblio_id == $self->item->biblionumber ); } Koha::Exceptions::Object::FKConstraint->throw( @@ -103,23 +103,37 @@ sub store { # Throw exception for item level booking clash Koha::Exceptions::Booking::Clash->throw() - if $self->item_id && !$self->item->check_booking( + if $self->item_id && !$self->item->check_booking( { start_date => $self->start_date, end_date => $self->end_date, booking_id => $self->in_storage ? $self->booking_id : undef } - ); + ); # Throw exception for biblio level booking clash Koha::Exceptions::Booking::Clash->throw() - if !$self->biblio->check_booking( + if !$self->biblio->check_booking( { start_date => $self->start_date, end_date => $self->end_date, booking_id => $self->in_storage ? $self->booking_id : undef } - ); + ); + + # Assign item at booking time + if ( !$self->item_id ) { + $self->item_id( + $self->biblio->assign_item_for_booking( + { + start_date => $self->start_date, + end_date => $self->end_date + } + ) + ); + } + + # FIXME: We should be able to combine the above two functions into one $self = $self->SUPER::store; } diff --git a/koha-tmpl/intranet-tmpl/prog/js/place_booking_modal.js b/koha-tmpl/intranet-tmpl/prog/js/place_booking_modal.js index 58e39264b5..c476d942ee 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/place_booking_modal.js +++ b/koha-tmpl/intranet-tmpl/prog/js/place_booking_modal.js @@ -261,6 +261,18 @@ $('#placeBookingModal').on('show.bs.modal', function(e) { if (booked == bookable) { return true; } + + // FIXME: The above is not intelligent enough to spot + // cases where an item must be used for a biblio level booking + // due to all other items being booking within the biblio level + // booking period... we end up with a clash + // To reproduce: + // * One bib with two bookable items. + // * Add item level booking + // * Add biblio level booking that extends one day beyond the item level booking + // * Try to book the item without an item level booking from the day before the biblio level + // booking is to be returned. Note this is a clash, the only item available for the biblio + // level booking is the item you just booked out overlapping the end date. } } }); -- 2.39.5