Bug 40625 - Cashup re-submissions on page reload
Summary: Cashup re-submissions on page reload
Status: Signed Off
Alias: None
Product: Koha
Classification: Unclassified
Component: Point of Sale (show other bugs)
Version: Main
Hardware: All All
: P5 - low enhancement
Assignee: Martin Renvoize (ashimema)
QA Contact: Testopia
URL:
Keywords:
Depends on:
Blocks: 40445
  Show dependency treegraph
 
Reported: 2025-08-08 15:14 UTC by Martin Renvoize (ashimema)
Modified: 2025-08-14 16:31 UTC (History)
3 users (show)

See Also:
GIT URL:
Change sponsored?: ---
Patch complexity: Small patch
Documentation contact:
Documentation submission:
Text to go in the release notes:
Version(s) released in:
Circulation function:


Attachments
Bug 40625: Fix duplicate cashup records via POST/REDIRECT/GET pattern (12.55 KB, patch)
2025-08-08 15:36 UTC, Martin Renvoize (ashimema)
Details | Diff | Splinter Review
Bug 40625: Fix duplicate cashup records via POST/REDIRECT/GET pattern (12.61 KB, patch)
2025-08-14 16:31 UTC, Owen Leonard
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-08-08 15:14:41 UTC
The point of sale Cashup submission should use post/redirect/get pattern. We have been seeing duplicate cashup records and have identified that it's after an initial cashup has been performed and the user has left the page open. When they return, they reload the page (or Chrome auto-reloads it) and it performs the post again causing an empty or unexpected cashup to be recorded.
Comment 1 Martin Renvoize (ashimema) 2025-08-08 15:36:06 UTC
Created attachment 185284 [details] [review]
Bug 40625: Fix duplicate cashup records via POST/REDIRECT/GET pattern

The cashup functionality on both /pos/register.pl and /pos/registers.pl
pages was using GET requests via anchor tags, which could cause duplicate
cashup records when users refreshed the page after performing a cashup.

This patch implements proper POST/REDIRECT/GET pattern with CSRF protection:

1. Convert anchor tag buttons to proper HTML forms with submit buttons
2. Add CSRF token protection to all cashup operations
3. Change operation from 'cashup' to 'cud-cashup' for CSRF compliance
4. Implement redirects after successful cashup operations to prevent resubmission
5. Update JavaScript to populate form fields instead of href attributes

This ensures cashup operations follow HTTP semantics properly (POST for
state changes) and prevents duplicate submissions while maintaining the
existing user experience.

Test plan:
1. Apply patch and restart services
2. Go to Point of Sale > Cash registers
3. Click "Record cashup" on any register - should open modal
4. Click "Confirm" - should perform cashup and reload page
5. Refresh the page - should NOT create duplicate cashup record
6. Go to Point of Sale > Register for individual register
7. Click "Record cashup" - should open modal
8. Click "Confirm" - should perform cashup and reload page
9. Refresh the page - should NOT create duplicate cashup record
10. On registers page, try "Cashup all" button - should work correctly
11. Verify all existing functionality (modals, summaries) still works
12. Check browser developer tools - all requests should be POST for cashup operations
Comment 2 Owen Leonard 2025-08-14 16:31:07 UTC
Created attachment 185404 [details] [review]
Bug 40625: Fix duplicate cashup records via POST/REDIRECT/GET pattern

The cashup functionality on both /pos/register.pl and /pos/registers.pl
pages was using GET requests via anchor tags, which could cause
duplicate cashup records when users refreshed the page after performing
a cashup.

This patch implements proper POST/REDIRECT/GET pattern with CSRF
protection:

1. Convert anchor tag buttons to proper HTML forms with submit buttons
2. Add CSRF token protection to all cashup operations
3. Change operation from 'cashup' to 'cud-cashup' for CSRF compliance
4. Implement redirects after successful cashup operations to prevent
   resubmission
5. Update JavaScript to populate form fields instead of href attributes

This ensures cashup operations follow HTTP semantics properly (POST for
state changes) and prevents duplicate submissions while maintaining the
existing user experience.

Test plan:
1. Apply patch and restart services
2. Go to Point of Sale > Cash registers
3. Click "Record cashup" on any register - should open modal
4. Click "Confirm" - should perform cashup and reload page
5. Refresh the page - should NOT create duplicate cashup record
6. Go to Point of Sale > Register for individual register
7. Click "Record cashup" - should open modal
8. Click "Confirm" - should perform cashup and reload page
9. Refresh the page - should NOT create duplicate cashup record
10. On registers page, try "Cashup all" button - should work correctly
11. Verify all existing functionality (modals, summaries) still works
12. Check browser developer tools - all requests should be POST for
    cashup operations

Signed-off-by: Owen Leonard <oleonard@myacpl.org>