0049. A CommerceProvider interface before Sylius, with a Wellms cart adapter
Generated from docs/decisions/0049-commerce-provider-before-sylius.md
- Status: Proposed
- Date: 2026-10-09
- Plan:
docs/plans/leftovers-0-2.md(L2-07)
Context and problem statement
Section titled “Context and problem statement”The builder interview asks free or paid. The spec says pricing goes through the active
CommerceProvider (6.4), and “until then the existing payments package”. Sylius is not built yet.
Considered options
Section titled “Considered options”- Add the small 6.4 interface now (
syncProduct,createCheckout,handleOrderEvent), with aWellmsCartProvideradapter. - Call the cart package directly from the builder.
- Keep builder courses free until 6.4.
Decision
Section titled “Decision”Option 1, in a new commerce package:
- Adapter.
WellmsCartProvidercreates or updates a cartProductwith the course as the productable, through the cart services. - Mapping. The adapter keeps the mapping in
commerce_product_links. - Order events.
handleOrderEventreturns null; access still comes from the cart package’s existing flow. - Selection. The provider is chosen by
commerce.provider. The Sylius adapter replaces it in 6.4.
Consequences
Section titled “Consequences”- Good: the builder can price courses now, and only the adapter changes later.
- Good: entitlements stay in the LMS.
- Bad: the interface may grow when Sylius lands; it is versioned here.
- Default pending #54.
Implementation notes (L2-07)
Section titled “Implementation notes (L2-07)”Pricecarries minor units and an ISO currency; the Wellms cart sells in one currency (PAYMENTS_DEFAULT_CURRENCY) and refuses any other, so the builder skips the product with a note instead of failing the apply.- A product is only created for a paid course with a confirmed amount. The model’s suggested price
(task
price, light) lives in the session state, never in the brief, until the author confirms it. - The applier creates the product inactive (
purchasable = false); publishing the course activates it. An existing single product for the course (made in the admin) is adopted, not duplicated. commerce.sellables.coursecan name the productable class; otherwise the first registered productable that is aUlams\Courses\Models\Courseis used.