Skip to content

Bugfix/ogc 3406 surcharges or discounts zeros invoice - #2650

Merged
Tschuppi81 merged 16 commits into
masterfrom
bugfix/ogc-3406-surcharges-or-discounts-zeros-invoice
Aug 24, 2026
Merged

Bugfix/ogc 3406 surcharges or discounts zeros invoice#2650
Tschuppi81 merged 16 commits into
masterfrom
bugfix/ogc-3406-surcharges-or-discounts-zeros-invoice

Conversation

@Tschuppi81

@Tschuppi81 Tschuppi81 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Reservation: Fix pricing snapshot migration that zeroed invoices

The Store pricing settings on reservations migration zeroed the stored price of many reservations, which made refresh_invoice_items (triggered e.g. by adding a surcharge/discount) wipe the invoice line and drop the payment (OGC-3406).

Re-run the corrected migration under a new name so it executes again on already-upgraded databases, fixing three bugs that caused the zeroing:

  • the allocation lookup matched the wrong pricing_method constants (price_per_item/price_per_hour instead of per_item/per_hour),
  • the resource = mirror_of guard was mis-parenthesised (AND bound tighter than the following ORs), and
  • the resource-content fallback read content->'price_per_item', but the resource stores that value under price_per_reservation.

Add an org upgrade task to recompute invoice lines and payments that a post-rollout refresh had already zeroed. Scoped to reservation invoices modified on or after the backfill rollout (2026-08-18) that are tied to a paying reservation — a per_item/per_hour allocation, or a per_item resource and refreshed only when safe (manual, still-open payment).

TYPE: Bugfix
LINK: ogc-3406

@linear

linear Bot commented Aug 24, 2026

Copy link
Copy Markdown

OGC-3406

@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.83%. Comparing base (f702cfc) to head (039f966).
⚠️ Report is 2 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files

see 1 file with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f702cfc...039f966. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Tschuppi81 and others added 3 commits August 24, 2026 08:04
Keeps the price fallback in `CustomReservation.invoice_item` from turning a
stored 0 into None (which would trip the `price_per_item`/`price_per_hour`
asserts and 500 on refresh) by only overriding when a positive price is
recovered.

Makes the org `Refresh reservation invoices zeroed by the pricing backfill`
task explicitly require the reservation `Backfill reservation prices from
invoice lines` task, so the refresh always runs after the data is repaired
regardless of module ordering.

Adds tests covering the refresh task and the full backfill-from-allocation
to refresh recovery chain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D4Jcf1cSmRS3pc9suqpYMc
@Tschuppi81
Tschuppi81 requested a review from Daverball August 24, 2026 06:56
Comment thread src/onegov/reservation/upgrade.py
Comment thread src/onegov/reservation/models/custom_reservation.py Outdated
Comment thread src/onegov/reservation/upgrade.py Outdated
),
'price_per_item',
COALESCE(
res.content->'price_per_reservation',

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the fallback case price lives on the resource content under price_per_reservation

Comment thread src/onegov/reservation/upgrade.py Outdated
Comment on lines +553 to +554
data->>'pricing_method' = 'per_item'
OR data->>'pricing_method' = 'per_hour'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those were wrong

@Tschuppi81

Tschuppi81 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

I also found a few schemas that have reservations that had no pricing stored.

risch: 11417 - per_item Tageskarte, 0 -> 40
stadt_zug 5099 - halls/rooms, 0 -> real price
huenenberg 4369 - per_item recovery
wil/meggen 2 each - per_item recovery

there might be more... still testing

@Tschuppi81

Copy link
Copy Markdown
Contributor Author

Note: We decided to log all touched entries in order to keep track of the applied changes

Comment thread src/onegov/reservation/upgrade.py Outdated
Comment thread src/onegov/reservation/upgrade.py Outdated
Comment thread src/onegov/org/upgrade.py Outdated
Comment thread src/onegov/org/upgrade.py
@Tschuppi81

Copy link
Copy Markdown
Contributor Author

@Daverball I am not sure how it should be: currently a method=='free gets an per_item price. Is this how it should be or not? This confuses me, I would expect a per_item price of 0.0. Technically it does not matter as long a its free...

2026-08-24 14:42:34 - INFO: Stored pricing on reservation 238: method=free, per_item=45.0, per_hour=0.0
2026-08-24 14:42:34 - INFO: Stored pricing on reservation 181: method=free, per_item=45.0, per_hour=0.0

@Daverball

Daverball commented Aug 24, 2026

Copy link
Copy Markdown
Member

@Daverball I am not sure how it should be: currently a method=='free gets an per_item price. Is this how it should be or not? This confuses me, I would expect a per_item price of 0.0. Technically it does not matter as long a its free...

2026-08-24 14:42:34 - INFO: Stored pricing on reservation 238: method=free, per_item=45.0, per_hour=0.0
2026-08-24 14:42:34 - INFO: Stored pricing on reservation 181: method=free, per_item=45.0, per_hour=0.0

This can happen because of how our field dependencies work. If you switch from per_item to free the value in price_per_item does not disappear, so when you switch back to per_item you see the original price you entered once upon a time.

It's harmless for that to be propagated to the reservation, since as soon as the method is free, we ignore all the other settings. The main reason it propagates, is to keep the code simple, there's not much to be gained to propagate different fields based on the value of pricing_method. All it does is make the code more complicated and more likely to contain bugs.

@Tschuppi81

Copy link
Copy Markdown
Contributor Author

I attached a log to the ticket showing that many reservations are being changed with this upgrade

Tschuppi81 and others added 2 commits August 24, 2026 15:01
@Daverball

Copy link
Copy Markdown
Member

Since per_item is the most common pricing method and it's more common for the pricing method to be inherited from the resource, it's unsurprising that a lot of reservations are affected by the misspelled price_per_reservation. (we probably should've migrated when we renamed that property, instead of just pointing the property to a different key in the dictionary)

Luckily it's not very harmful for the pricing information to be incorrect for a little while, since invoices are only refreshed on-demand.

Comment thread src/onegov/org/upgrade.py Outdated
@Tschuppi81
Tschuppi81 force-pushed the bugfix/ogc-3406-surcharges-or-discounts-zeros-invoice branch from bc17a0f to 0d726b4 Compare August 24, 2026 13:38
@Tschuppi81
Tschuppi81 merged commit 6408ca8 into master Aug 24, 2026
16 checks passed
@Tschuppi81
Tschuppi81 deleted the bugfix/ogc-3406-surcharges-or-discounts-zeros-invoice branch August 24, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants