Skip to content

TWO-24751/feat: Payment terms chip selector and offset pricing fee#323

Open
dgjlindsay wants to merge 3 commits into
doug/TWO-24747-dev-harnessfrom
doug/TWO-24751-terms-chips
Open

TWO-24751/feat: Payment terms chip selector and offset pricing fee#323
dgjlindsay wants to merge 3 commits into
doug/TWO-24747-dev-harnessfrom
doug/TWO-24751-terms-chips

Conversation

@dgjlindsay

Copy link
Copy Markdown

What

Buyer-selectable invoice terms at checkout (chip selector, Magento parity) + optional offset pricing: the merchant's service fee passed to the buyer as a separate line, in three variants (simple 100%, partial percentage, incremental vs a reference term).

Design

  • No plugin-side fee arithmetic. Offset settings post to POST /v1/pricing/order/fee as a buyer_fee_share block; the backend's answer is charged verbatim (mirrors Magento's SurchargeCalculator pattern).
  • Business logic in PHP, JS renders only (TWO-24751 checkout-type separation requirement; Gutenberg port needs only a new presentation layer). New WC_Twoinc_Payment_Terms class owns term resolution, selection validation, fee quoting, the cart fee, and payload terms. twoinc.js renders chips from two wc-ajax endpoints (two_term_fees, two_select_term).
  • Term availability behind a single seam. get_available_terms() = brand available_terms (new key, 14/30/60/90 for Two) ∩ merchant admin subset. The planned backend term-availability surface replaces only this method — see the design-constraint comment on TWO-24751. Deliberate divergence from the ticket text: the admin day list is constrained to the brand set rather than free-form, so the future backend swap can't widen what a brand allows.
  • Fee enters the cart as a native WC fee (taxed by store tax handling → order-internal net+tax=gross stays consistent; same posture as Magento's store-configured surcharge tax rate). It flows into the Two payload via the existing fee line-item path. Cart changes re-trigger quote + render on updated_checkout.
  • Fail-soft quotes: a failed fee fetch renders chips without labels; checkout never blocks. Single term renders one non-interactive chip.
  • Selected term + offered set ride the create-order payload as terms / available_terms; selection also posts with the checkout form (hidden field) so order-pay-page flows work sessionless.

Tests

6 new unit specs (PHP 8.2 via make test-unit, all green): brand∩admin resolution, default fallback, the three buyer_fee_share shapes + malformed-percentage fallback, payload terms presence/absence, invalid-POST fallback.

🤖 Generated with Claude Code

Buyer-selectable invoice terms at checkout (chip per term, Magento
parity) plus optional pass-through of the service fee as a buyer-facing
line, computed by POST /v1/pricing/order/fee - the plugin does no fee
arithmetic, it posts the offset settings as a buyer_fee_share block and
charges exactly the backend's answer (simple / partial / incremental
reference-terms variants).

Architecture per TWO-24751's checkout-type separation requirement: all
business logic (term resolution, selection validation, fee quoting,
cart fee, payload terms) lives in WC_Twoinc_Payment_Terms; twoinc.js
renders chips from the wc-ajax endpoints and posts selections back, so
the Gutenberg port (TWO-24767) only needs a new presentation layer.

Term availability resolves brand config (available_terms, new key:
14/30/60/90 for Two) intersected with the merchant's admin subset,
behind a single seam method - the planned backend term-availability
surface replaces only that method (see the TWO-24751 design-constraint
comment; no scattered term-grid reads).

The fee enters the cart as a native WC fee (taxed by the store's tax
handling, keeping net + tax = gross internally consistent - same
posture as Magento's store-configured surcharge tax rate) and flows
into the order payload through the existing fee line-item path. The
selected term + offered set ride the create-order payload as
terms/available_terms.

Failed fee quotes are fail-soft: chips render without labels, checkout
never blocks. Single-term sets render one non-interactive chip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

🖌 Pre-commit success 🏆

Details
Downloading virtualenv (7.3MiB)
 Downloaded virtualenv
Installed 11 packages in 21ms
prettier.................................................................Passed

Exit code: 0

Author ✍️@dgjlindsay

dgjlindsay and others added 2 commits June 12, 2026 09:25
Replace all references to a specific partner brand name with generic
"brand overlay" terminology in comments across the plugin.
WC_Twoinc_Payment_Terms::fetch_term_fee calls $gateway->make_request()
from outside the gateway class; with the method private that path fatals
the moment a fee quote runs against the real gateway (the unit-test stub
masked it by declaring its own public override).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant