Bug 42997: Sync booking end_date with due date override at checkout
When a booked item is checked out, the due date defaults to the booking end_date. Staff may override the due date at checkout time, which previously left the booking end_date out of sync with the checkout, blocking the booked period for longer or shorter than the actual loan. This patch updates C4::Circulation::AddIssue to sync any due date override back to booking.end_date the moment the booking transitions to 'issued', keeping the booking and the checkout aligned from the point of issue. The existing Koha::Booking->store clash detection is used to guard the update: if the overridden due date would clash with a subsequent booking for the same item, the checkout proceeds with the booking's original end_date instead. Test plan: 1) Run t/db_dependent/Circulation.t and confirm the new 'AddIssue | booking end_date sync with due date override' subtest passes 2) Create a booking for a patron on a specific item 3) Check the item out to the patron, overriding the suggested due date 4) Confirm the booking's end_date now matches the overridden due date Sponsored-by: OpenFifth <https://openfifth.co.uk/\> Sponsored-by: Westminster City Council <https://www.westminster.gov.uk/\> Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk> Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de> Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
parent
3ec3c465ba
commit
67e0051e1f
|
|
@ -1856,7 +1856,27 @@ sub AddIssue {
|
|||
if ( $booking->patron_id == $patron->borrowernumber ) {
|
||||
|
||||
# Patron's own booking - mark as issued and link checkout to booking
|
||||
$booking->status('issued')->store;
|
||||
$booking->status('issued');
|
||||
|
||||
# Sync any due date override back to the booking end_date so the
|
||||
# booking and checkout agree from the moment of issue
|
||||
my $booking_end = dt_from_string( $booking->end_date );
|
||||
$booking->end_date($datedue) if $datedue->compare($booking_end) != 0;
|
||||
|
||||
try {
|
||||
$booking->store;
|
||||
} catch {
|
||||
my $error = $_;
|
||||
if ( blessed $error && $error->isa('Koha::Exceptions::Booking::Clash') ) {
|
||||
|
||||
# The overridden due date would clash with a subsequent
|
||||
# booking; proceed with the booking's original end_date
|
||||
$booking->discard_changes;
|
||||
$booking->status('issued')->store;
|
||||
} else {
|
||||
die $error;
|
||||
}
|
||||
};
|
||||
$issue_attributes->{'booking_id'} = $booking->booking_id;
|
||||
} else {
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use Modern::Perl;
|
|||
use utf8;
|
||||
|
||||
use Test::NoWarnings;
|
||||
use Test::More tests => 87;
|
||||
use Test::More tests => 88;
|
||||
use Test::Exception;
|
||||
use Test::MockModule;
|
||||
use Test::Deep qw( cmp_deeply );
|
||||
|
|
@ -7439,6 +7439,98 @@ subtest 'AddIssue/AddReturn | booking status handling' => sub {
|
|||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'AddIssue | booking end_date sync with due date override' => sub {
|
||||
plan tests => 5;
|
||||
|
||||
my $schema = Koha::Database->schema;
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
|
||||
my $patron2 = $builder->build_object( { class => 'Koha::Patrons' } );
|
||||
my $pickup_library = $builder->build_object( { class => 'Koha::Libraries' } );
|
||||
my $item = $builder->build_sample_item( { bookable => 1 } );
|
||||
|
||||
# Case 1: Due date matches booking end_date - no sync needed
|
||||
my $end_date = dt_from_string()->add( days => 7 )->truncate( to => 'minute' );
|
||||
my $booking = Koha::Booking->new(
|
||||
{
|
||||
patron_id => $patron->borrowernumber,
|
||||
pickup_library_id => $pickup_library->branchcode,
|
||||
item_id => $item->itemnumber,
|
||||
biblio_id => $item->biblio->biblionumber,
|
||||
start_date => dt_from_string(),
|
||||
end_date => $end_date,
|
||||
}
|
||||
)->store();
|
||||
|
||||
AddIssue( $patron, $item->barcode, $end_date->clone );
|
||||
$booking->discard_changes();
|
||||
is(
|
||||
dt_from_string( $booking->end_date )->compare($end_date), 0,
|
||||
"Booking end_date unchanged when due date matches"
|
||||
);
|
||||
|
||||
AddReturn( $item->barcode, $pickup_library->branchcode );
|
||||
$booking->delete();
|
||||
|
||||
# Case 2: Due date overridden at checkout - booking end_date follows
|
||||
$booking = Koha::Booking->new(
|
||||
{
|
||||
patron_id => $patron->borrowernumber,
|
||||
pickup_library_id => $pickup_library->branchcode,
|
||||
item_id => $item->itemnumber,
|
||||
biblio_id => $item->biblio->biblionumber,
|
||||
start_date => dt_from_string(),
|
||||
end_date => $end_date,
|
||||
}
|
||||
)->store();
|
||||
|
||||
my $override_due = dt_from_string()->add( days => 10 )->truncate( to => 'minute' );
|
||||
AddIssue( $patron, $item->barcode, $override_due->clone );
|
||||
$booking->discard_changes();
|
||||
is( $booking->status, 'issued', "Booking marked issued on checkout" );
|
||||
is(
|
||||
dt_from_string( $booking->end_date )->compare($override_due), 0,
|
||||
"Booking end_date synced to overridden due date"
|
||||
);
|
||||
|
||||
AddReturn( $item->barcode, $pickup_library->branchcode );
|
||||
$booking->delete();
|
||||
|
||||
# Case 3: Override clashes with a subsequent booking - original end_date kept
|
||||
$booking = Koha::Booking->new(
|
||||
{
|
||||
patron_id => $patron->borrowernumber,
|
||||
pickup_library_id => $pickup_library->branchcode,
|
||||
item_id => $item->itemnumber,
|
||||
biblio_id => $item->biblio->biblionumber,
|
||||
start_date => dt_from_string(),
|
||||
end_date => $end_date,
|
||||
}
|
||||
)->store();
|
||||
|
||||
my $subsequent_booking = Koha::Booking->new(
|
||||
{
|
||||
patron_id => $patron2->borrowernumber,
|
||||
pickup_library_id => $pickup_library->branchcode,
|
||||
item_id => $item->itemnumber,
|
||||
biblio_id => $item->biblio->biblionumber,
|
||||
start_date => dt_from_string()->add( days => 8 ),
|
||||
end_date => dt_from_string()->add( days => 12 ),
|
||||
}
|
||||
)->store();
|
||||
|
||||
AddIssue( $patron, $item->barcode, $override_due->clone );
|
||||
$booking->discard_changes();
|
||||
is( $booking->status, 'issued', "Booking still marked issued when override clashes" );
|
||||
is(
|
||||
dt_from_string( $booking->end_date )->compare($end_date), 0,
|
||||
"Booking end_date kept when override would clash with a subsequent booking"
|
||||
);
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest "Item's onloan value should be set if checked out item is checked out to a different patron" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue