Bug 40134 - Fix and optimise 'Any item' functionality of bookings
Summary: Fix and optimise 'Any item' functionality of bookings
Status: Needs Signoff
Alias: None
Product: Koha
Classification: Unclassified
Component: Circulation (show other bugs)
Version: unspecified
Hardware: All All
: P5 - low normal
Assignee: Martin Renvoize (ashimema)
QA Contact: Nick Clemens (kidclamp)
URL:
Keywords:
Depends on: 39916
Blocks: 39584
  Show dependency treegraph
 
Reported: 2025-06-12 14:45 UTC by Martin Renvoize (ashimema)
Modified: 2025-12-31 17:12 UTC (History)
2 users (show)

See Also:
GIT URL:
Initiative type: ---
Sponsorship status: ---
Comma delimited list of Sponsors:
Crowdfunding goal: 0
Patch complexity: Medium patch
Documentation contact:
Documentation submission:
Text to go in the release notes:
Version(s) released in:
Circulation function: Bookings


Attachments
Bug 40134: Implement dynamic item assignment with smart window maximization (45.99 KB, patch)
2025-06-12 14:54 UTC, Martin Renvoize (ashimema)
Details | Diff | Splinter Review
Bug 40134: Implement dynamic item assignment with smart window maximization (46.05 KB, patch)
2025-09-11 11:39 UTC, Thibaud Guillot (thibaud_g)
Details | Diff | Splinter Review
Bug 40134: Implement optimal item selection for 'any item' bookings (11.30 KB, patch)
2025-12-31 17:12 UTC, Martin Renvoize (ashimema)
Details | Diff | Splinter Review
Bug 40134: Add unit tests for optimal item selection (31.56 KB, patch)
2025-12-31 17:12 UTC, Martin Renvoize (ashimema)
Details | Diff | Splinter Review
Bug 40134: Implement client-side improvements for bookings (36.17 KB, patch)
2025-12-31 17:12 UTC, Martin Renvoize (ashimema)
Details | Diff | Splinter Review
Bug 40134: Add Cypress tests for booking improvements (31.61 KB, patch)
2025-12-31 17:12 UTC, Martin Renvoize (ashimema)
Details | Diff | Splinter Review

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Renvoize (ashimema) 2025-06-12 14:45:25 UTC
The 'Any item' option in the bookings modal is currently not correctly calculating maximum available booking window correctly and we have older code left behind that attempted to allow any item at a biblio level without taking into account item type limitations.

This bug acts to correct that by implementing an optimized algorithm for picking the item at booking time to try and maximize the pool of available items for future bookings.
Comment 1 Martin Renvoize (ashimema) 2025-06-12 14:54:44 UTC
Created attachment 183211 [details] [review]
Bug 40134: Implement dynamic item assignment with smart window maximization

This patch implements smart window maximization for "any item of itemtype X"
bookings using dynamic item pool reduction. The core principle is "never re-add
items to pool" - once an item is removed from the available pool because it
becomes unavailable, it's never re-added even if it becomes available again
later. This ensures optimal resource allocation and maximum booking windows.

Key features:
- Dynamic item pool reduction algorithm in isDateInMaximumWindow()
- Smart itemtype availability calculation in isDateDisabledForItemtype()
- Optimal item selection for booking submission in selectOptimalItem()
- Future availability calculation to choose best items
- Comprehensive JSDoc documentation with detailed examples

The algorithm works by:
1. Starting with items available on the selected start date
2. Walking through each day from start to target end date
3. Removing items from pool when they become unavailable
4. Never re-adding items even if they become available again later
5. Disabling dates when no items remain in pool

This maximizes booking windows while preventing conflicts by being conservative
about item availability.

Test plan:
1. Apply patch and restart services
2. Navigate to a biblio detail page with bookable items of multiple types
3. Click "Place booking" and select a patron and pickup location
4. Select an itemtype (not a specific item) to enable "any item" mode
5. Select a start date - verify end date options are maximized based on
   available items across the booking period
6. Test with complex booking scenarios where items have overlapping bookings
7. Verify that the algorithm correctly reduces the item pool as items become
   unavailable and extends booking windows as far as possible
8. Confirm that items which become available again later in the period are
   not re-added to the pool (key algorithm principle)
9. Submit booking and verify optimal item is selected automatically
Comment 2 Thibaud Guillot (thibaud_g) 2025-09-11 11:39:59 UTC
Created attachment 186371 [details] [review]
Bug 40134: Implement dynamic item assignment with smart window maximization

This patch implements smart window maximization for "any item of itemtype X"
bookings using dynamic item pool reduction. The core principle is "never re-add
items to pool" - once an item is removed from the available pool because it
becomes unavailable, it's never re-added even if it becomes available again
later. This ensures optimal resource allocation and maximum booking windows.

Key features:
- Dynamic item pool reduction algorithm in isDateInMaximumWindow()
- Smart itemtype availability calculation in isDateDisabledForItemtype()
- Optimal item selection for booking submission in selectOptimalItem()
- Future availability calculation to choose best items
- Comprehensive JSDoc documentation with detailed examples

The algorithm works by:
1. Starting with items available on the selected start date
2. Walking through each day from start to target end date
3. Removing items from pool when they become unavailable
4. Never re-adding items even if they become available again later
5. Disabling dates when no items remain in pool

This maximizes booking windows while preventing conflicts by being conservative
about item availability.

Test plan:
1. Apply patch and restart services
2. Navigate to a biblio detail page with bookable items of multiple types
3. Click "Place booking" and select a patron and pickup location
4. Select an itemtype (not a specific item) to enable "any item" mode
5. Select a start date - verify end date options are maximized based on
   available items across the booking period
6. Test with complex booking scenarios where items have overlapping bookings
7. Verify that the algorithm correctly reduces the item pool as items become
   unavailable and extends booking windows as far as possible
8. Confirm that items which become available again later in the period are
   not re-added to the pool (key algorithm principle)
9. Submit booking and verify optimal item is selected automatically

Signed-off-by: Thibaud Guillot <thibaud.guillot@biblibre.com>
Comment 3 Martin Renvoize (ashimema) 2025-12-31 17:12:39 UTC
Created attachment 190800 [details] [review]
Bug 40134: Implement optimal item selection for 'any item' bookings

This patch implements an algorithm for selecting the item that would
leave the largest gap after the proposed booking to maximize the
opportunity for future bookings.

Key Changes:

Koha::Booking:
- Added set_itemtype_filter() method for transient itemtype parameter
- Added _select_optimal_item() method using single aggregated query
  * Groups bookings by item_id with MIN(start_date)
  * Selects items with no future bookings (optimal)
  * Among items with bookings, selects one with latest next booking
  * O(1) complexity - single database query with GROUP BY
- Updated _assign_item_for_booking() to use optimal selection
  * Filters by itemtype when itemtype_id is provided
  * Replaces previous random selection (RAND())

API Changes:
- Added itemtype_id parameter support to add() endpoint
- Added itemtype_id parameter support to update() endpoint
- Validates exactly one of item_id or itemtype_id is provided
- itemtype_id is transient - not persisted to database
- Extracted and applied via set_itemtype_filter() before store()

Architecture:
- itemtype_id is NOT a database column (transient only)
- Used as selection criterion, then discarded

Test plan:
1. Apply patch and restart services
2. Create "any item" booking via staff interface
3. Verify item with longest future availability is selected
4. Test via API with itemtype_id parameter
5. Verify itemtype_id is not persisted to database
6. Run t/db_dependent/Koha/Booking.t
7. Run t/db_dependent/api/v1/bookings.t
Comment 4 Martin Renvoize (ashimema) 2025-12-31 17:12:40 UTC
Created attachment 190801 [details] [review]
Bug 40134: Add unit tests for optimal item selection

This patch adds unit tests for the server-side optimal item selection
functionality.

t/db_dependent/Koha/Booking.t:
- Added subtest for _select_optimal_item() method (7 tests)
  * Tests with no items (returns undef)
  * Tests with single item (returns that item)
  * Tests with multiple items (selects item with longest future availability)
  * Tests optimal selection across items with different booking patterns
  * Tests handling of cancelled bookings (ignored in selection)
  * Tests iterator reset after selection
- Added subtest for _assign_item_for_booking() with itemtype filtering (6 tests)
  * Tests booking without item_id or itemtype_id (selects any available)
  * Tests booking with itemtype_id (filters by type)
  * Tests optimal selection within filtered itemtype
  * Tests exception when no items of specified type available
- Added integration test for full optimal selection workflow (5 tests)
  * Creates 3 items with different future booking patterns
  * Verifies items selected in optimal order (B→C→A)
  * Demonstrates preservation of constrained resources
  * Validates complete algorithm chain
  * Tests booking failure when all items exhausted

t/db_dependent/api/v1/bookings.t:
- Added subtest for itemtype_id parameter validation (16 tests)
  * Tests successful booking creation with itemtype_id
  * Tests that item is automatically assigned
  * Tests validation: cannot specify both item_id and itemtype_id
  * Tests validation: must specify either item_id or itemtype_id
  * Tests clash detection with itemtype-based bookings
- Fixed duplicate booking_id test to use different dates
  * Prevents clash detection from masking duplicate ID constraint
- Updated test count from 3 to 8 subtests in Booking.t
- Updated test count to match actual assertions (16 not 18)

Test Coverage:
- Internal method testing: _select_optimal_item()
- Integration testing: _assign_item_for_booking()
- API endpoint testing: add() with itemtype_id
- End-to-end workflow validation
- Edge cases: empty sets, single items, ties, cancelled bookings

Test plan:
1. prove t/db_dependent/Koha/Booking.t
2. prove t/db_dependent/api/v1/bookings.t
3. Verify all tests pass
Comment 5 Martin Renvoize (ashimema) 2025-12-31 17:12:42 UTC
Created attachment 190802 [details] [review]
Bug 40134: Implement client-side improvements for bookings

This patch implements client-side improvements for the bookings modal,
including smart window maximization and hybrid submission logic that
delegates optimal item selection to the server.

Smart Window Maximization:
- Implements "never re-add items to pool" algorithm
- Dynamic item pool reduction based on availability
- isDateDisabledForItemtype() calculates available dates
- isDateInMaximumWindow() validates end dates against item pool
- Provides real-time calendar feedback to users

Hybrid Submission Logic:
For "any item" bookings, the client now uses a smart hybrid approach:
1. Filters items by selected itemtype
2. Checks availability for the booking period
3. If 0 items available: Shows error (no suitable item)
4. If 1 item available: Sends item_id (optimization - skips server)
5. If 2+ items available: Sends itemtype_id (delegates to server)

This minimizes server round-trips while delegating complex optimal
selection logic to the server when multiple choices exist.

Test plan:
1. Navigate to biblio detail page with bookable items
2. Click "Place booking" and select patron/pickup location
3. Select itemtype (not specific item) - "any item" mode
4. Select start date - verify end dates are maximized
5. Verify calendar disables dates when no items available
6. Submit booking - verify it succeeds
7. Check that optimal item was selected (server-side)
8. Test edit mode with "any item" selection
9. Verify both create and edit use same logic
Comment 6 Martin Renvoize (ashimema) 2025-12-31 17:12:43 UTC
Created attachment 190803 [details] [review]
Bug 40134: Add Cypress tests for booking improvements

This patch adds end-to-end Cypress tests for the booking modal improvements,
including smart window maximization and server-side optimal item selection.

New Tests:

1. "should successfully submit an 'Any item' booking with server-side optimal item selection"
   - Tests the complete "any item" booking workflow
   - Selects itemtype and "Any item" option (item_id = 0)
   - Submits booking form
   - Verifies modal closes without errors
   - Validates booking created in database
   - Confirms item was assigned by server
   - Verifies server-side optimal selection completed
   - Test status: PASSING

2. "should maximize booking window by dynamically reducing available items during overlaps"
   - Creates 4 items with strategic booking patterns
   - Tests "never re-add items to pool" algorithm
   - Validates 5 scenarios:
     a) Full window when all items available
     b) Reduced window when Item 1 becomes unavailable
     c) Further reduction when Items 1&2 unavailable
     d) Minimal window with Items 1,2,3 unavailable
     e) No availability when all items booked
   - Demonstrates smart window maximization
   - Test status: PASSING

3. "should handle edit mode date initialization correctly"
   - Tests fix for edit mode race condition
   - Verifies dates populate correctly when editing booking
   - Ensures itemtype is set before date initialization
   - Tests that flatpickr dates are set properly
   - Test status: PASSING

Updated Tests:

- "should successfully submit a booking"
  * Updated to use day+5 start date (accounts for 3-day lead period)
  * Ensures test doesn't fail on past-date constraint

- Updated test comments and log messages to reflect server-side selection
  * Changed from "client-side selectOptimalItem()" references
  * Updated to "server-side optimal item selection"
  * Clarified that server performs the optimal selection

Test Coverage:
- End-to-end "any item" booking submission
- Smart window maximization algorithm
- Edit mode date initialization
- Server-side optimal selection validation
- Database verification of assigned items
- Modal interaction and form submission

Test plan:
1. Start KTD environment
2. Ensure Cypress is installed: yarn install
3. Run: npx cypress run --spec "t/cypress/integration/Circulation/bookingsModalBasic_spec.ts"
4. Verify all 11 tests pass
5. Optionally run in interactive mode: npx cypress open