fix(validation): reject inverted date ranges and oversized payment amounts #236

Merged
David merged 1 commit from fix/PMS-306-validation-date-range-money-overflow into main 2026-06-14 18:37:56 +02:00
Owner

Add cross-field and magnitude validation at the request layer so logically invalid create payloads return 422 instead of being persisted or surfacing as a 500 (PMS-306).

  • Contract create: reject end_date before start_date (open-ended and same-day ranges still allowed) via a struct-level schema validator.
  • Invoice create: reject due_date before invoice_date (same-day allowed) via a struct-level schema validator.
  • Payment create: bound amount to the DECIMAL(12, 2) column magnitude (|amount| < 10_000_000_000) so an oversized value (e.g. 1e15) returns a 422 rather than overflowing the column and surfacing as a 500 DATABASE_ERROR, same class as PMS-297. The new validate_money_amount helper lives in utils::validation alongside validate_contract_type.
  • Sign policy: payment amount and invoice line quantity / unit_price are intentionally signed (refunds, credits, discounts); documented in field docs and only the magnitude is constrained.

Adds DB-free unit tests covering each rule.

#PMS-306

Add cross-field and magnitude validation at the request layer so logically invalid create payloads return 422 instead of being persisted or surfacing as a 500 (PMS-306). - Contract create: reject end_date before start_date (open-ended and same-day ranges still allowed) via a struct-level schema validator. - Invoice create: reject due_date before invoice_date (same-day allowed) via a struct-level schema validator. - Payment create: bound amount to the DECIMAL(12, 2) column magnitude (|amount| < 10_000_000_000) so an oversized value (e.g. 1e15) returns a 422 rather than overflowing the column and surfacing as a 500 DATABASE_ERROR, same class as PMS-297. The new validate_money_amount helper lives in utils::validation alongside validate_contract_type. - Sign policy: payment amount and invoice line quantity / unit_price are intentionally signed (refunds, credits, discounts); documented in field docs and only the magnitude is constrained. Adds DB-free unit tests covering each rule. #PMS-306
fix(validation): reject inverted date ranges and oversized payment amounts
All checks were successful
E2E / Playwright against staging (pull_request) Successful in 1m6s
Check / fmt + clippy + compile + unit/doc tests (pull_request) Successful in 1m41s
Create release / Create release from merged PR (pull_request) Has been skipped
Integration / integration tests (pull_request) Successful in 8m41s
8b5b99fb5b
Add cross-field and magnitude validation at the request layer so logically invalid create payloads return 422 instead of being persisted or surfacing as a 500 (PMS-306).

- Contract create: reject end_date before start_date (open-ended and same-day ranges still allowed) via a struct-level schema validator.
- Invoice create: reject due_date before invoice_date (same-day allowed) via a struct-level schema validator.
- Payment create: bound amount to the DECIMAL(12, 2) column magnitude (|amount| < 10_000_000_000) so an oversized value (e.g. 1e15) returns a 422 rather than overflowing the column and surfacing as a 500 DATABASE_ERROR, same class as PMS-297. The new validate_money_amount helper lives in utils::validation alongside validate_contract_type.
- Sign policy: payment amount and invoice line quantity / unit_price are intentionally signed (refunds, credits, discounts); documented in field docs and only the magnitude is constrained.

Adds DB-free unit tests covering each rule.

#PMS-306
David merged commit 008e46750e into main 2026-06-14 18:37:56 +02:00
David deleted branch fix/PMS-306-validation-date-range-money-overflow 2026-06-14 18:37:56 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!236
No description provided.