Lubili
Engineering work

Store and web form orders into Odoo, without retyping

Retail orders came from Shopify, wholesale orders from a web form, and someone entered both into the ERP by hand. Arya designed and built the integration that receives each order, checks it, maps it to Odoo and creates the records.

Built by Arya Shrimali, founder of Lubili
Type
E-commerce operations system
Role
Backend engineering and systems integration
Stack
Node.js, Express, Fastify, Shopify webhooks, Jotform, Odoo XML-RPC, Odoo Studio, MongoDB, JWT, AWS Lambda, API Gateway
Order integration overviewShopify retail orders and B2B form orders go into a Node.js integration, which creates the records in Odoo. Odoo hands orders to fulfilment. B2B quotes go to a person for review before they are confirmed.ShopifyRetail ordersB2B formWholesale ordersIntegrationNode.jsOdoo ERPOrders, invoicesFulfilmentOrder mgmtPerson reviewsB2B quote
The flow in one picture. The full architecture is further down the page.Scroll sideways or pinch to zoom

Context

The problem: orders retyped into Odoo by hand

Orders arrived through three routes. Retail (B2C) orders came from Shopify. Wholesale (B2B) orders came through a Jotform order form. The sales team also entered some orders directly in Odoo.

Shopify and the form were not connected to the ERP. Staff copied each order into Odoo by hand, then handled confirmation, invoicing and the hand-off to fulfilment.

Why manual order entry did not scale

At production order volume across two sales channels, manual re-entry becomes a daily job, not an occasional task.

Each copy adds delay between the customer ordering and the warehouse acting. Each copy is also a chance for a wrong quantity, a missed order or the same order entered twice.

Arya’s role

Arya designed and built the integration layer from end to end, from receiving events to creating ERP records and handing off to the order management system.

He also moved its hosting when the traffic pattern became clear.

What Arya built

Inside the Shopify and Odoo integration

  • Webhook endpoints

    Node.js endpoints (Express and Fastify) that receive Shopify order events (created, updated, payment status) and form submissions.

  • Validation and processing

    Each request's source is verified. Then the payload is checked and transformed into Odoo's data model.

  • Business logic

    Order mapping, data enrichment, and an idempotency key per source order, so a webhook delivered twice can never create a second order.

  • An Odoo XML-RPC client

    It creates and updates records and handles the responses.

  • ERP workflow automation

    Sales orders for B2C. Quotations for B2B, held for a person to review. Then order confirmation, invoice creation and invoice posting.

  • Hand-off to the order management system

    Invoice and order events are sent on for fulfilment, order tracking and status updates, with an optional status sync back to the ERP.

  • Supporting infrastructure

    MongoDB for event logs, webhook logs and idempotency keys. JWT on internal endpoints. Odoo Studio for custom fields, automation rules and triggers. Logging, retries, dead-letter handling and failure alerts.

  • A move to serverless

    First deployed on Render, then moved to AWS Lambda and API Gateway.

Engineering

Key decisions

  1. Automate the copying, keep the judgement.

    Standard retail orders flow straight through. B2B quotes stop for a person, because wholesale pricing and terms need a decision.

  2. Duplicate protection as a first-class rule.

    Webhook providers can deliver the same event more than once, so every write is keyed to the source order before anything touches the ERP.

  3. Failures are recorded, retried and reported.

    A failed order goes to dead-letter handling and raises an alert, so it is not silently lost.

  4. Compute that matches the traffic.

    Order webhooks arrive in bursts. Serverless functions behind API Gateway run only when an order arrives, so you do not pay for a server sitting idle.

Results

Results of the Shopify to Odoo integration

  • Orders from Shopify and the B2B form reach Odoo without anyone retyping them.
  • The same order can no longer be created twice by a repeated webhook.
  • Wholesale orders still get a human pricing check. Automation does not remove judgement where it matters.
  • Confirmation, invoicing and the hand-off to fulfilment run as one connected flow, not separate manual steps.
  • Integration failures become visible and recoverable, so they are not discovered later by a customer.
  • Hosting cost follows actual order traffic.

Architecture

The full system

For engineering readers. Everything in the drawing is described in the text above.

Order integration architectureRetail orders from Shopify and wholesale orders from a Jotform order form arrive as webhooks at a Node.js integration layer. It verifies each request, validates and maps the payload to the Odoo model, applies an idempotency key per source order, routes B2C and B2B orders, and writes to Odoo over XML-RPC. In Odoo, B2C orders become sales orders and B2B orders become quotations that a person reviews. Both lead to order confirmation, invoice creation and invoice posting. Invoice and order events go on to the order management system for fulfilment, tracking and status updates, with an optional status sync back to the ERP. The sales team can also enter orders directly in Odoo. Supporting infrastructure: MongoDB for logs and idempotency keys, JWT on internal endpoints, AWS Lambda and API Gateway (moved from Render), Odoo Studio, and monitoring with retries, dead-letter handling and failure alerts.ORDER SOURCESShopifyB2C ordersOrder createdOrder updatedPayment statusJotformB2B order formForm submittedOrder detailsManual entrySales teamSales orders madedirectly in the ERPINTEGRATIONNode.jsWebhook endpointsExpress / FastifyReceives order eventsVerifies the sourceValidate + transformPayload checksRejects bad payloadsMaps to the Odoo modelBusiness logicDedupe + routingIdempotency keyRoutes B2C or B2BEnriches order dataOdoo clientXML-RPCCreates, updates recordsHandles errorsWebhooksForm submissionERPOdooQuotationB2BWholesalepricing, termsHuman reviewSales orderB2CRetail ordersgo straight onOrder confirmationInvoice creationInvoice postingXML-RPCDirect in ERPORDER MANAGEMENTReceiveorder dataProcessfor fulfilmentOrder trackingStatus updatesInvoice +order eventOptional status syncSUPPORTING INFRASTRUCTUREMongoDBLogs + keysEvent and webhook logsIdempotency keysJWTInternal authSigned tokens oninternal endpointsAWS Lambda+ API GatewayMoved from RenderScales with order burstsOdoo StudioERP configurationCustom fieldsAutomation rules, triggersMonitoringReliabilityLogging, retriesDead-letter, failure alerts
Orders from two channels reach Odoo without retyping. B2B quotes stop for a person; everything else flows through.Scroll sideways or pinch to zoom

Four columns: order sources, the integration layer, the ERP and order management, over the supporting infrastructure. Moving dashes are live data paths; static dashes are optional or manual paths.

Stack

Technology

  • Node.js
  • Express
  • Fastify
  • Shopify webhooks
  • Jotform
  • Odoo XML-RPC
  • Odoo Studio
  • MongoDB
  • JWT
  • AWS Lambda
  • API Gateway

For your business

Similar problems Lubili can solve

Store to ERP or accounting sync (Odoo, Zoho, Xero), B2B and wholesale order intake, invoice and fulfilment hand-offs, stock sync across channels, and failed-sync alerts with retries.

Built in an earlier software engineering role. Company and client details are kept confidential.

Orders still copied by hand?

Book a free consultation. A short call about how orders move through your business, and a one-page written summary of what is worth automating.

Free. No obligation. You get a one-page written summary.