Skip to content

feat(commera): configure payment and shipping providers from settings - #64

Merged
Rl0007 merged 2 commits into
feat/admin-dashboardfrom
feat/commera-integrations
Sep 4, 2026
Merged

feat(commera): configure payment and shipping providers from settings#64
Rl0007 merged 2 commits into
feat/admin-dashboardfrom
feat/commera-integrations

Conversation

@Rl0007

@Rl0007 Rl0007 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Configures payment gateways and shipping carriers from /commera, so a store owner never opens Desk to connect a provider.

What was there

AppSettingsDialog.vue read paymentGateways and appIntegrations from a hardcoded array in data/integrations.js. Shiprocket was listed with connected: true — a literal in a JS file, not a fact about the site. "Save keys" called toast.success() and set a local flag; nothing reached the server.

The backend already existed and is provider-agnostic — describe_integration derives every field from frappe.get_meta() in Desk layout order, and payments.py / shipping.py are each just a registry plus two whitelisted wrappers. Only the frontend half was missing.

What this adds

IntegrationsPanel takes a store and is mounted twice, once per registry, so payments and shipping are literally the same screen. A third kind of integration is a registry on the server plus one more instance of the component.

  • Field groups come from the settings doctype's own Section Breaks. Add a docfield to a gateway or carrier Single and it appears in the dashboard with no change to this code.
  • A Password renders blank, with "Stored. Leave blank to keep it." when one is already set. Its value never leaves the server.
  • available / enabled / configured / missing are the server's answers, so a card cannot claim a connection the site does not have. available: false reads "Not installed".
  • Enabling a provider with a required field blank is refused by the server, by name — one rule, on the server, for both screens.
  • The webhook URL is shown with a copy button, which is what actually gets pasted into Razorpay's or Shiprocket's own panel.
  • Both registries load when the dialog opens, not when their tab is first shown — an unread registry counts zero, which reads as "nothing connected" rather than "not looked yet".

Docfield descriptions are authored as Desk HTML; SettingsRow interpolates its description as text, so the markup is unwrapped before it is passed (otherwise the owner reads Settings &gt; API and a literal <b>).

Verified in a browser

Against dev.localhost, driving the real dialog with puppeteer:

  • Sidebar reads Payments 1 · Shipping 1 on open, without visiting either tab.
  • Payments lists the four registered gateways — Razorpay (Live), Stripe, Telr, Tabby — not the seven mock ones. PayPal, Paytm, Cashfree and "Cash on delivery" are gone because the server's registry never had them.
  • Shipping lists Shiprocket ("Add keys") and AfterShip ("Live"), matching the site.
  • Shiprocket's screen renders its five field groups with "3 still needed", each field carrying its own doctype description.
  • get_payment_integrations and get_shipping_integrations both 200. No page errors.

ls_shop.tests.test_admin_integrations is unchanged and still 7 pass / 1 pre-existing failure — identical to the base branch, so this diff is backend-neutral.

Note

The mock analytics and accounting rows move to data/mock.js. The two shipping carriers are dropped from that list: they are real now, and leaving them would contradict the Shipping tab.

🤖 Generated with Claude Code

https://claude.ai/code/session_019DwUYNuBnzS6jfri3SQMtt

Rl0007 and others added 2 commits September 2, 2026 13:14
A book has neither axis, but every layer here is keyed on Style Attribute
Variant: Color Size Item.size is reqd, checkout.py drops a cart line whose
item has no "Size" attribute row, and a variant with an empty sizes table
unpublishes itself. So the axes are hidden from the owner rather than
removed - the trick Shopify plays with its "Default Title" variant.

create_product now takes both axes as optional and fills them with
"Standard"/"One Size", creating either attribute on first use so a store
that has never sold a garment can still list a book. A grid where every
option is sizeless is a book; one where only some are is still the owner
forgetting a row, and is still refused.

On the storefront a lone size counts as already chosen - without that,
nothing ever sets ?size= and add_to_cart refused the item forever - and the
picker, the option row and the size list hide themselves.

Also repairs TestCreateProduct, whose six tests had errored in setUp since
the size-attribute guard landed in bd0b693.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013fNrHeRfcK6HnAMJdtEMfH
The settings dialog listed seven gateways and five apps from a hardcoded array in
data/integrations.js, with Shiprocket marked `connected: true` — a literal in a JS
file. "Save keys" toasted and set a local flag. Nothing reached the server, so a
store owner still had to open Desk to connect anything.

The backend for this already existed and is provider-agnostic: `describe_integration`
derives every field from `frappe.get_meta()` in layout order, and payments.py and
shipping.py are each a registry plus two whitelisted wrappers. Only the frontend half
was missing.

IntegrationsPanel takes a store and is mounted twice, once per registry, so payments
and shipping are the same screen. Field groups come from the settings doctype's own
Section Breaks, which means a new docfield on a gateway or carrier Single appears in
the dashboard with no change here. A Password renders blank with "leave blank to keep
it", never its value. `available`, `enabled`, `configured` and `missing` are the
server's answers, so a card cannot claim a connection the site does not have — and
enabling a provider with a required field blank is refused by the server, by name.

Both registries load when the dialog opens rather than when their tab is first shown:
an unread registry counts zero, which reads as "nothing connected" instead of "not
looked yet".

Verified in a browser against dev.localhost: the sidebar reads Payments 1 / Shipping 1,
the payments tab lists the four registered gateways (not the seven mock ones) with
Razorpay Live, the shipping tab lists Shiprocket "Add keys" and AfterShip "Live", and
Shiprocket's screen renders its five field groups with "3 still needed".

The mock analytics and accounting rows move to data/mock.js, minus the shipping
carriers, which are real now and would otherwise contradict the Shipping tab.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019DwUYNuBnzS6jfri3SQMtt
@Rl0007
Rl0007 merged commit 8b4e0c8 into feat/admin-dashboard Sep 4, 2026
2 of 6 checks passed
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