Repository navigation
Conversation
58a3a14 to
f01ed55
Compare
f01ed55 to
32a1772
Compare
32a1772 to
632a60d
Compare
632a60d to
28a1c2c
Compare
2484e8b to
62759f4
Compare
62759f4 to
8b31eef
Compare
8b31eef to
411cde5
Compare
411cde5 to
614b744
Compare
4541299 to
feceeae
Compare
feceeae to
7d6f42b
Compare
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD — structured payment-term support is incomplete across sibling APIs and still has invalid-input failure paths.
|
7d6f42b to
2fbfb0f
Compare
2fbfb0f to
fca7bfe
Compare
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD —
|
fca7bfe to
969586f
Compare
70890a9 to
051f7a0
Compare
051f7a0 to
5a3f4f2
Compare
5a3f4f2 to
edb8a95
Compare
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD — a structured customer term can make quotes announce different payment terms from the resulting invoices.
|
c2cdb7c to
6ad9cb5
Compare
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD — the organization payment-term source is inconsistent across REST and GraphQL.
|
|
Automated pre-review (advisory, not a required check) — verdict: PASS · CI green PASS — Structured payment terms are validated and synchronized across customer and billing-entity write paths, the legacy alias remains compatible, V1 reads expose the optional field without leaking it into V2 customer payloads, and the new behavior has focused request, service, resolver, and serializer coverage. |
When a write sent both payment_term and net_payment_term, payment_term silently won even if the two disagreed. This was introduced with the GraphQL change but applies to every customer and billing entity write path, so it belongs with the REST write PR where reviewers see it. ValidateService now rejects a payment_term whose integer alias differs from the net_payment_term sent with it, with conflicting_net_payment_term. A null alias alongside a structured term, and an explicit null payment_term, are still accepted. The write services now build the validator arguments with params.slice. Specs cover the full alias matrix, the customer update behaviour change, and the REST customer create rejection.
## Context RawPaymentTermParams copies the raw payment_term past strong params so a wrong-type value reaches the validator, but it only permitted a direct hash. A payment_term sent as an array of objects left unpermitted parameters behind, and converting the params to a hash raised instead of returning invalid_format. ## Description Raw values are permitted recursively, through arrays, before being copied. A request spec sends an array of objects and expects the invalid_format validation error.
…anization BIL-796: GET /organizations returned the organization's own net_payment_term column, which no longer follows the default billing entity. It now mirrors the default entity: net_payment_term (null for the four non-net types) and payment_term.
## Context
net_payment_term keeps main's validation, so "45" and 30.5 are accepted
again and cast by the integer column. The request specs still expected
invalid_format, and the alias check compared the raw value, so "30"
sent with {term_type: "net", days: 30} was reported as conflicting.
## Description
The alias check compares the payment_term alias with the value cast as
the column casts it. The request specs assert that a digit string and a
decimal are stored as integers, with the matching net term.
## Context BIL-805: the dive-in says payment_term always wins when a write sends both fields. The alias check returned 422 conflicting_net_payment_term for any pair that did not describe the same term, null included. ## Description ValidateService no longer compares the two fields. AssignService already assigns payment_term and derives net_payment_term from it, so net 30 with {end_of_month} stores end_of_month with a null alias, and net 30 with a null payment_term clears both.
…default billing entity The REST organization serializer already reads the default billing entity, since its term changes no longer write the organization column. GraphQL still returned the stale organization integer.
…esolver spec The shared membership is a let_it_be record, so its organization is frozen.
…ganization The default user is already a member of the default organization.
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD — malformed legacy payment-term input can silently clear an existing term.
|
The raw copy forwarded an object or array net_payment_term, which Rails casts to nil. allow_nil let it through and AssignService cleared both columns, so a malformed alias erased an existing term. Strong params drop such values, as before payment terms, and the validator no longer reads net_payment_term.
|
Automated pre-review (advisory, not a required check) — verdict: PASS · CI green PASS — The latest fix restores legacy handling for malformed |
Context
Earlier steps in this stack added the structured
payment_termto customers and billing entities, with thenet_payment_terminteger as a compatibility alias. This PR exposes it via the REST API. Before this change, clients could only send the integer.Description
Write path
payment_termis accepted on customer and billing entity create/update.PaymentTerms::ValidateServiceruns in all five write services before any persistence. Invalid input returns a validation error.net_payment_termcolumn writes are removed.PaymentTerms::AssignServiceis now the only term write path.RawPaymentTermParamscontroller concern copies the rawpayment_termandnet_payment_termvalues into the permitted params. Without this concern, invalid input would be dropped silently instead of returning a validation error.PaymentTerms::ValidateServicenormalizes its input, so ActionController::Parameters and plain hashes give the same result.payment_termandnet_payment_termare sent and disagree (e.g.{net, 30}with60, orend_of_monthwith0), the write is rejected withconflicting_net_payment_termonpayment_term. Before,payment_termsilently won. Anullnet_payment_termsent with a structured term, and an explicitpayment_term: null, are still accepted.Read path
payment_termto customer and billing entity serializers.payment_term. For invoices from before this feature, it builds{term_type: "net", days: N}from the invoice's own integer.Stack created with GitHub Stacks CLI • Give Feedback 💬