Bug 41898: Update tests for new booking status lifecycle

- Bookings.t: rewrite filter_by_active to verify status-based filtering;
  new/issued are active, cancelled/completed are not; past-window 'new'
  bookings (uncollected) remain active
- Booking.t: checkout relation uses 'issued'; old_checkout uses 'completed';
  clash detection covers issued transition; notice test updated
- Circulation.t: AddIssue sets 'issued'; AddReturn sets 'completed'; plan
  expanded to cover the full checkout → return lifecycle

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:
Martin Renvoize 2026-06-08 15:08:50 +01:00 committed by Pedro Amorim
parent bf8237ae54
commit 40b9c8e29c
No known key found for this signature in database
GPG Key ID: 06B75BA7F3894D55
3 changed files with 44 additions and 85 deletions

View File

@ -7259,8 +7259,8 @@ subtest 'AddIssue records staff who checked out item if appropriate' => sub {
);
};
subtest 'AddIssue | booking status handling' => sub {
plan tests => 5;
subtest 'AddIssue/AddReturn | booking status handling' => sub {
plan tests => 6;
my $schema = Koha::Database->schema;
$schema->storage->txn_begin;
@ -7270,7 +7270,7 @@ subtest 'AddIssue | booking status handling' => sub {
my $pickup_library = $builder->build_object( { class => 'Koha::Libraries' } );
my $item = $builder->build_sample_item( { bookable => 1 } );
# Test 1: Patron checks out item with their own booking - should mark as completed
# Test 1: Patron checks out item with their own booking - should mark as issued
my $booking1 = Koha::Booking->new(
{
patron_id => $patron1->borrowernumber,
@ -7285,10 +7285,13 @@ subtest 'AddIssue | booking status handling' => sub {
my $issue1 = AddIssue( $patron1, $item->barcode, dt_from_string()->add( days => 7 ) );
$booking1->discard_changes();
is( $booking1->status, 'completed', "Patron's own booking marked as completed when item checked out" );
is( $booking1->status, 'issued', "Patron's own booking marked as issued when item checked out" );
# Clean up for next test
# Return the item - booking should now be completed
AddReturn( $item->barcode, $pickup_library->branchcode );
$booking1->discard_changes();
is( $booking1->status, 'completed', "Booking marked as completed when item returned" );
$booking1->delete();
# Test 2: Another patron checks out item with different patron's booking overlapping actual booking period - should cancel booking

View File

@ -138,7 +138,7 @@ subtest 'Relation accessor tests' => sub {
value => {
patron_id => $patron->borrowernumber,
item_id => $item->itemnumber,
status => 'completed'
status => 'issued'
}
}
);
@ -671,7 +671,7 @@ subtest 'store() tests' => sub {
$booking->update(
{
status => 'completed',
status => 'issued',
}
);
@ -1178,7 +1178,7 @@ subtest 'Integration test: Full optimal selection workflow' => sub {
};
subtest 'store() skips clash detection on terminal status transition' => sub {
plan tests => 3;
plan tests => 4;
$schema->storage->txn_begin;
my $patron = $builder->build_object( { class => "Koha::Patrons" } );
@ -1211,13 +1211,17 @@ subtest 'store() skips clash detection on terminal status transition' => sub {
# false clash when there is only one bookable item.
C4::Circulation::AddIssue( $patron, $non_bookable_item->barcode );
# Without the fix, transitioning to 'completed' runs clash
# Without the fix, transitioning to 'issued' runs clash
# detection which sees the non-bookable checkout and throws
# Koha::Exceptions::Booking::Clash → 500 error.
lives_ok { $booking->status('issued')->store() }
'Transition to issued skips clash detection';
# Transition to completed (item returned) also skips clash detection
lives_ok { $booking->status('completed')->store() }
'Transition to completed skips clash detection';
# Cancellation from completed is also a terminal transition
# Cancellation is also a terminal transition
lives_ok { $booking->status('cancelled')->store() }
'Transition to cancelled skips clash detection';

View File

@ -34,113 +34,65 @@ my $builder = t::lib::TestBuilder->new;
subtest 'filter_by_active' => sub {
plan tests => 7;
plan tests => 5;
$schema->storage->txn_begin;
my $biblio = $builder->build_sample_biblio;
my $start_ago = dt_from_string->subtract( hours => 1 );
my $start_hour = dt_from_string->add( hours => 1 );
my $start_day = dt_from_string->add( days => 1 );
my $end_ago = dt_from_string->subtract( minutes => 1 );
my $end_hour = dt_from_string->add( hours => 1 );
my $end_day = dt_from_string->add( days => 1 );
my $biblio = $builder->build_sample_biblio;
my $start_ago = dt_from_string->subtract( days => 5 );
my $end_ago = dt_from_string->subtract( days => 1 );
my $start_day = dt_from_string->add( days => 1 );
my $end_day = dt_from_string->add( days => 5 );
$builder->build_object(
{
class => 'Koha::Bookings',
value => {
biblio_id => $biblio->biblionumber,
start_date => $start_ago,
end_date => $end_hour,
status => 'new'
}
value =>
{ biblio_id => $biblio->biblionumber, start_date => $start_ago, end_date => $end_day, status => 'new' }
}
);
is( $biblio->bookings->filter_by_active->count, 1, 'Booking started in past, ending in future is counted' );
is( $biblio->bookings->filter_by_active->count, 1, 'Active new booking is open' );
$builder->build_object(
{
class => 'Koha::Bookings',
value =>
{ biblio_id => $biblio->biblionumber, start_date => $start_ago, end_date => $end_ago, status => 'new' }
}
);
is( $biblio->bookings->filter_by_active->count, 2, 'Uncollected past-window new booking is still open' );
$builder->build_object(
{
class => 'Koha::Bookings',
value => {
biblio_id => $biblio->biblionumber,
start_date => $start_ago,
end_date => $end_ago,
status => 'new'
biblio_id => $biblio->biblionumber, start_date => $start_ago, end_date => $end_day, status => 'issued'
}
}
);
is( $biblio->bookings->filter_by_active->count, 1, 'Booking started in past, ended now is not counted' );
is( $biblio->bookings->filter_by_active->count, 3, 'Issued booking is open' );
$builder->build_object(
{
class => 'Koha::Bookings',
value => {
biblio_id => $biblio->biblionumber,
start_date => $start_hour,
end_date => $end_hour,
status => 'new'
biblio_id => $biblio->biblionumber, start_date => $start_day, end_date => $end_day,
status => 'cancelled'
}
}
);
is( $biblio->bookings->filter_by_active->count, 2, 'Booking starting soon, ending soon is still counted' );
is( $biblio->bookings->filter_by_active->count, 3, 'Cancelled booking is not open' );
$builder->build_object(
{
class => 'Koha::Bookings',
value => {
biblio_id => $biblio->biblionumber,
start_date => $start_day,
end_date => $end_day,
status => 'new'
biblio_id => $biblio->biblionumber, start_date => $start_ago, end_date => $end_ago,
status => 'completed'
}
}
);
is( $biblio->bookings->filter_by_active->count, 3, 'Booking starting tomorrow, ending tomorrow is counted' );
$builder->build_object(
{
class => 'Koha::Bookings',
value => {
biblio_id => $biblio->biblionumber,
start_date => $start_day,
end_date => $end_ago,
status => 'new'
}
}
);
is(
$biblio->bookings->filter_by_active->count, 3,
'EDGE CASE: Booking starting in future, already ended is not counted - should be impossible, but good check'
);
$builder->build_object(
{
class => 'Koha::Bookings',
value => {
biblio_id => $biblio->biblionumber,
start_date => $start_day,
end_date => $end_day,
status => 'cancelled'
}
}
);
is( $biblio->bookings->filter_by_active->count, 3, 'Cancelled bookings are not counted' );
$builder->build_object(
{
class => 'Koha::Bookings',
value => {
biblio_id => $biblio->biblionumber,
start_date => $start_day,
end_date => $end_day,
status => 'completed'
}
}
);
is( $biblio->bookings->filter_by_active->count, 3, 'Completed bookings are not counted' );
is( $biblio->bookings->filter_by_active->count, 3, 'Completed booking is not open' );
$schema->storage->txn_rollback;
};