Acoustic office pods and modular workspaces
Calma: a dealer quotation and approval flow built on Shopify
A B2B portal on Shopify where approved dealers see their prices, build quotations, export them to Excel and turn them into draft orders that the brand approves before they become orders — with configurator data carried through to Axapta and the CRM.
- Dealer portal
- Quotation to draft order
- Approval workflow
- 3D configurator
- Axapta/CRM transfer
- Role-based pricing
The situation
Calma makes acoustic pods and modular workspace products — technology-dense items, largely built to order, sold internationally through dealers. The brand, related to Nurus, wanted its dealers to work on a storefront instead of over email: see their prices, configure products, put together a quotation for an end customer, and move it toward an order that the brand controls.
That is not what a standard Shopify store does. Prices are public, carts become orders at checkout, and there is no notion of a dealer awaiting approval or a draft a manager has to sign off. The project was to build those notions on top of Shopify without fighting the platform.
My role
I was the full-stack Shopify developer and consultant on the project, working with the brand’s project team and a project manager. I set up the store from a ready-made theme with a GitHub-connected main/dev workflow, implemented pages and sections from the design team’s files, and built the custom apps that carry the B2B logic. The ERP and CRM side was defined together with the people who run those systems.
The workflow that was built
The whole portal is organized around one chain:
Dealer → Quotation → Draft Order → Approval → Order
Each step maps to something concrete in the store and in the custom app.
Dealer application and authorization. A visitor can browse but sees no prices. After creating an account, they fill in a dealer application. The application reaches the store manager by email and appears in the custom app’s admin page, where it can be approved. Until that happens the account remains unauthorized: no prices, no ordering — only the option to request a quotation for the products in the cart.
Role-based price visibility. Price display on product pages, in the cart and in search is controlled by the account’s role, implemented across Liquid and the app. Unauthorized visitors and pending applicants get the request-a-quote path; approved dealers get their pricing.
Quotation. An approved dealer builds a cart and saves it as a quotation. The quotation is stored in the store and can be downloaded as an Excel file for the dealer’s own customer.
Draft order and approval. When the dealer is ready, the quotation is converted into a Shopify draft order and waits for the brand. The store manager — or the account manager responsible for that dealer’s country — reviews it on the app’s admin page. Approval turns the draft into a real order. There is no Shopify payment step in this flow; payment terms are handled between the brand and the dealer, as they were before.
Account managers by country. The store manager assigns account managers to countries from the app. Each manager then handles the dealer applications and draft orders for their region.
Dealers as organizations. Dealers can add their own staff accounts and their own customers, and place orders on behalf of a customer. Process emails for each step are sent from the brand’s own mail domain.
Configured products
Calma’s products are rarely ordered as they appear in a catalog. A second custom app integrates a pCon configurator, built on Babylon.js, into the product page. The dealer configures the product in 3D; the configurator returns a product definition and a price that do not exist as a Shopify variant. The configured item is added to the cart at that price, flows through quotation and draft order like any other line, and the configuration data is sent with the order to Axapta (the ERP) and the CRM, so production and sales see exactly what was quoted.
What was built, technically
- A custom Shopify app with an embedded admin interface (React) and a Node.js backend with MySQL, holding dealer applications, roles, account-manager assignments, quotations and the approval state of draft orders.
- Storefront integration in Liquid and JavaScript for price visibility, quotation requests and the dealer account area.
- Draft-order creation and conversion through the Shopify Admin API, without the standard checkout.
- A configurator integration app bridging Babylon.js/pCon output to cart lines with custom prices.
- Order and configuration transfer to Axapta and the CRM.
- Email flows for every step of the process, sent from the brand’s own mail domain.
- Documentation so the store team could manage sections and settings without a developer.
Outcome
Dealers apply, get approved, quote, export and order on one portal, with the brand’s managers approving from an admin page instead of reconciling emails. Configured products reach the ERP with their configuration attached. The flow is shaped around how Calma sells, and it stays within what Shopify supports well.
Working on something similar? Most of these projects started with a short email describing the store and the problem.
Discuss your project