TWO-24746/feat: PrestaShop brand config foundation#32
Open
dgjlindsay wants to merge 7 commits into
Open
Conversation
Lay the brand-config foundation so partner editions can rebrand the
module without forking it.
- brands/two.php: default brand config (identity strings, payment
option defaults, support links, payload identity). Keys land with
their consumers.
- Twopayment::getTwoBrand(): lazy loader, available from every entry
point including the test harness (which skips the module
constructor). Constructor assigns author/displayName/description
from it.
- Smarty: $two_brand assigned at the front-controller setMedia hook
and in the payment-option render, so templates can read
{$two_brand.product_name} etc. Template {l s='...'} literals are
deliberately untouched until the translations pass (TWO-24760) so
existing dictionaries keep matching.
- applyTwoBrandPayloadIdentity(): vendor_name/brand_tag added to the
create, intent AND update order bodies — symmetric across the order
lifecycle — and only when the brand sets them, so the Two brand's
payloads are byte-identical to before.
- Tests: brand loads and is accessible from module methods; payload
identity omitted for the Two brand; applied when a brand sets it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
Contributor
Author
|
Adversarial review round 1 applied (3 Opus reviewers). Key correction: |
Review findings (adversarial round 1):
- Drop brand_tag from the order payload: it is not an order-body field
anywhere in the Two ecosystem — the Magento plugin uses it solely as
a checkout-URL query param and the WooCommerce plugin sends only
vendor_name. A partner setting it would have sent an unrecognised
key on every create/intent/update. The key leaves the brand file too
(no consumer) and lands with the checkout-URL code that reads it.
- Implement the partner substitution seam the file header promised but
the code lacked: PS_TWO_BRAND_CODE configuration resolves to
brands/{code}.php (basename-confined) and merges over the Two
defaults, mirroring the WooCommerce mechanism.
- getTwoBrand() no longer fatals checkout when brands/two.php is
briefly absent mid-deploy: is_file guard with inline Two defaults.
- Tools::safeOutput on brand-derived admin HTML (brand files are now
an external-ish input surface); locals hoisted in the help panel.
- brands/two.php header gains a consumer map (which key feeds what).
- Tests: a REAL built payload is pinned to omit vendor_name/brand_tag
for the Two brand (the wrapper test alone could not catch a builder
regression); partner-brand test asserts brand_tag stays out.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 tasks
Standard branding-framework element, now at parity: a brand may declare ['min_order_amount', 'currency', 'billing_countries'] and the payment option hides when unmet. Compares the NET basket (the funding partner's server-side risk rule compares net); baskets in other currencies convert via PrestaShop's own currency rates (cross rate = target/source against the shop default), failing closed without a usable rate — matching the Magento gate's posture. Country mismatch and below-minimum both log why the option hid. The Two brand sets no gate, so behaviour is unchanged until a partner edition declares one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mirror of the Magento/WooCommerce changes (Doug's minimum-order review): - availability_gate is a four-part config: amount + currency + basis (net|gross, explicit — ABN's funding-partner rule compares net, the platform's defaults are gross) + billing countries. The gate compares the cart total on the declared basis (getOrderTotal with or without taxes) and the shared compare helper converts via PrestaShop rates, failing closed without one. - Merchant-set Minimum Order Value in Other Settings: the dynamic description shows the brand minimum it must exceed; validation rejects values at or below that floor; the gate enforces brand AND merchant minima (the merchant value rides the brand currency/basis when a gate exists, else shop default currency, gross). Configured value cleaned up at uninstall. - No decline hint here yet: no PrestaShop brand carries a minimum and the module has no REJECTED-status message path to hang it on — recorded in the parity plan for PS-brand onboarding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The merchant-set Minimum Order Value is now interpreted in the shop
default currency rather than the brand minimum's currency:
- Save validation converts the brand floor into the shop default
currency via PrestaShop's rates before comparing; without a usable
rate the floor check is skipped on save (checkout gate enforces both
minima independently and fails closed).
- Settings description shows the converted floor with the native value
in brackets ('Platform minimum £215.73 (€250.00), excluding tax'),
via the locale price formatter when available.
- getTwoMerchantMinimumOrder builds the tuple with the shop default
currency; the gate's shared compare helper already converts
cross-currency carts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mirror of the WooCommerce/Magento decline hint (base-plugin parity): when a Two decline is attributable to the brand minimum order value, tell the buyer the minimum instead of a generic failure. - New getTwoMinimumOrderDeclineHint(): keyed primarily on the API's machine-readable reason (decline_reason on intents and rejected orders, error_code on order-create 400s) with a strictly-below- minimum fallback; the minimum is shown converted into the cart currency via PrestaShop's rates, failing soft (no hint) without a usable rate. - Wired at three decline surfaces: the authoritative intent check at payment submit, order-create 400 with ORDER_BELOW_MIN_INVOICE_AMOUNT, and 201-without-payment_url (REJECTED orders now get a 'not available for this order' message rather than implying a technical redirect fault). - Shared convertTwoAmount() helper replaces the inline conversion in getTwoPlatformMinimumInDefaultCurrency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ncy label
Mirrors tonight's Magento and WooCommerce changes so all three plugins
read the same single source of truth:
- getTwoPlatformMinimumOrder() resolves min_order_amount/currency/basis
from GET /v1/merchant/{id} (the value checkout-api enforces at order
create/intent), Configuration-cached for 15 minutes; the no-minimum
outcome is cached too, and a fetch failure resolves to no minimum
(the server still enforces).
- The availability gate, settings description, save-time floor
validation and decline hint all read the API tuple; the brand
config's availability_gate shrinks to a billing-country restriction.
- New 'Minimum Order Value Tax Basis' select (gross/net, default gross)
feeding the merchant minimum; the value field's label carries the
shop default currency ('Minimum Order Value, EUR').
(The version display this propagation round added to WooCommerce
already exists here: the config page footer shows plugin + PrestaShop
versions.)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
C3 of the plugin parity plan (TWO-24739 → TWO-24746): introduce a brand-config layer in the PrestaShop module so partner editions can rebrand without forking. No behaviour change for the Two brand.
Stacked on #31 (TWO-24741) — merge that first; base retargets when it lands.
How
brands/two.php— default brand config: provider, display/product names, payment-option title/subtitle defaults, support email + docs URL, logo path, and payload identity (vendor_name,brand_tag— empty for Two).Twopayment::getTwoBrand()— lazy loader so every entry point (module ctor, AJAX controllers, test harness) gets the config. Constructor readsauthor/displayName/descriptionfrom it, per the ticket's "PHP-accessible, not Smarty-only" requirement.$two_brandassigned at theactionFrontControllerSetMediahook (checkout pages) and in the payment-option render. Template{l s='...'}literals deliberately untouched: swapping them changes translation keys, which is TWO-24760's scope.applyTwoBrandPayloadIdentity()— injectsvendor_name/brand_taginto create, intent and update order bodies (symmetric across the lifecycle — lesson from the WC #320 review where the create/edit asymmetry was a bug). Keys only sent when non-empty, so Two-brand payloads are byte-identical to today.Test plan
php tests/run.php— all green (incl. 3 new)php -l🤖 Generated with Claude Code