Bug 42997: (QA follow-up) Don't invert the booking period when syncing end dates
Collecting a booking early (within the bookings lead period) with a due date override before the booking start syncs end_date to a date that precedes start_date. Koha::Booking->store has no interval validation and the clash checks' date windows never see the inverted period, so the broken row is stored silently - reproduced via AddIssue on this patchset. - pull start_date back to the checkout date whenever the synced due date precedes it, in both AddIssue and AddRenewal, so the booking window follows the loan instead of inverting - cover both paths in Circulation.t; the AddRenewal case needs the Biblio::check_booking exemption from the previous patch, as the synced window no longer overlaps the stored one Test plan: 1. prove t/db_dependent/Circulation.t 2. Set bookings_lead_period to e.g. 5 for an itemtype and enable SpecifyDueDate 3. Book an item of that itemtype for a patron starting in 3 days 4. Check it out to them today with an explicit due date of tomorrow 5. Without this patch the booking is stored with end_date before start_date; with it both dates follow the checkout period 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
8bd9790e47
commit
90281d5a1f
|
|
@ -1877,7 +1877,15 @@ sub AddIssue {
|
|||
# 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;
|
||||
if ( $datedue->compare($booking_end) != 0 ) {
|
||||
$booking->end_date($datedue);
|
||||
|
||||
# An early collection can be due back before the booked period
|
||||
# even starts; pull the start_date back to the checkout date
|
||||
# rather than storing an inverted booking period
|
||||
my $booking_start = dt_from_string( $booking->start_date );
|
||||
$booking->start_date($issuedate) if $datedue->compare($booking_start) < 0;
|
||||
}
|
||||
|
||||
try {
|
||||
$booking->store;
|
||||
|
|
@ -3750,7 +3758,14 @@ sub AddRenewal {
|
|||
my $booking_end = dt_from_string( $booking->end_date );
|
||||
if ( $datedue->compare($booking_end) != 0 ) {
|
||||
try {
|
||||
$booking->end_date($datedue)->store;
|
||||
$booking->end_date($datedue);
|
||||
|
||||
# As at issue time, guard against inverting the booking period
|
||||
# when the new due date precedes the booking start
|
||||
my $booking_start = dt_from_string( $booking->start_date );
|
||||
$booking->start_date( dt_from_string( $issue->issuedate ) )
|
||||
if $datedue->compare($booking_start) < 0;
|
||||
$booking->store;
|
||||
} catch {
|
||||
my $error = $_;
|
||||
if ( blessed $error && $error->isa('Koha::Exceptions::Booking::Clash') ) {
|
||||
|
|
|
|||
|
|
@ -7539,7 +7539,7 @@ subtest 'AddIssue/AddReturn | booking status handling' => sub {
|
|||
};
|
||||
|
||||
subtest 'AddIssue | booking end_date sync with due date override' => sub {
|
||||
plan tests => 5;
|
||||
plan tests => 8;
|
||||
|
||||
my $schema = Koha::Database->schema;
|
||||
$schema->storage->txn_begin;
|
||||
|
|
@ -7627,6 +7627,45 @@ subtest 'AddIssue | booking end_date sync with due date override' => sub {
|
|||
"Booking end_date kept when override would clash with a subsequent booking"
|
||||
);
|
||||
|
||||
AddReturn( $item->barcode, $pickup_library->branchcode );
|
||||
$booking->delete();
|
||||
$subsequent_booking->delete();
|
||||
|
||||
# Case 4: Early collection due back before the booking starts - the
|
||||
# start_date follows the checkout so the period is not inverted
|
||||
Koha::CirculationRules->set_rule(
|
||||
{
|
||||
branchcode => '*',
|
||||
itemtype => $item->effective_itemtype,
|
||||
rule_name => 'bookings_lead_period',
|
||||
rule_value => 5,
|
||||
}
|
||||
);
|
||||
|
||||
$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()->add( days => 3 ),
|
||||
end_date => dt_from_string()->add( days => 10 ),
|
||||
}
|
||||
)->store();
|
||||
|
||||
my $early_due = dt_from_string()->add( days => 1 )->truncate( to => 'minute' );
|
||||
my $early_issue = AddIssue( $patron, $item->barcode, $early_due->clone );
|
||||
$booking->discard_changes();
|
||||
is( $booking->status, 'issued', "Booking marked issued when collected early" );
|
||||
is(
|
||||
dt_from_string( $booking->end_date )->compare($early_due), 0,
|
||||
"Booking end_date synced to an override before the booking start"
|
||||
);
|
||||
is(
|
||||
$booking->start_date, $early_issue->issuedate,
|
||||
"Booking start_date pulled back to the checkout date instead of storing an inverted period"
|
||||
);
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
|
|
@ -7841,7 +7880,7 @@ subtest 'AddRenewal | booking_id preservation' => sub {
|
|||
};
|
||||
|
||||
subtest 'AddRenewal | booking end_date sync' => sub {
|
||||
plan tests => 4;
|
||||
plan tests => 6;
|
||||
|
||||
my $schema = Koha::Database->schema;
|
||||
$schema->storage->txn_begin;
|
||||
|
|
@ -7938,6 +7977,33 @@ subtest 'AddRenewal | booking end_date sync' => sub {
|
|||
"Booking end_date kept when the renewal clashes with the next booking"
|
||||
);
|
||||
|
||||
# A renewal due before the booking start pulls the start_date back too
|
||||
$booking->set(
|
||||
{
|
||||
start_date => dt_from_string()->add( days => 5 ),
|
||||
end_date => dt_from_string()->add( days => 8 ),
|
||||
}
|
||||
)->store;
|
||||
|
||||
my $short_due_date = dt_from_string()->add( days => 2 )->truncate( to => 'minute' );
|
||||
AddRenewal(
|
||||
{
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
itemnumber => $item->itemnumber,
|
||||
branch => $library->branchcode,
|
||||
datedue => $short_due_date->clone,
|
||||
}
|
||||
);
|
||||
$booking->discard_changes;
|
||||
is(
|
||||
dt_from_string( $booking->end_date )->compare($short_due_date), 0,
|
||||
"Booking end_date synced to a renewal due date before the booking start"
|
||||
);
|
||||
is(
|
||||
$booking->start_date, $issue->get_from_storage->issuedate,
|
||||
"Booking start_date pulled back to the checkout date instead of storing an inverted period"
|
||||
);
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue