Workflow: E-commerce Fulfillment — From Online Order to Delivery
Modules involved: OmniSales · WooCommerce / Shopify · Warehouse · Innoship · Couriers · Invoices · eInvoice · Returns · Clients · Price Lists
Who uses it: Order operator, Warehouse, Logistics, Finance, E-commerce Manager
Typical duration: Hours – 1-2 business days (from online order placement to courier handover)
Overview
The e-commerce fulfillment workflow covers the entire lifecycle of an order placed on an online store integrated with CRMConnect. Orders arrive automatically from WooCommerce or Shopify via webhook or cron sync, are processed in OmniSales, the warehouse executes picking and packing, the courier receives the parcel via automatically generated AWB (via Innoship or direct Cargus/FanCourier), and the customer receives the invoice and shipping notification. Returns are handled through a dedicated sub-flow.
The difference from OmniSales Fulfillment — the generic order workflow — is the bidirectional integration with the e-commerce platform: statuses are updated back in WooCommerce/Shopify, customers are synced automatically, and channel prices are controlled through Price Lists.
Flow Diagram (ASCII)
[ONLINE ORDER (WooCommerce / Shopify)]
│ webhook → OmniSales → New Order
│ or cron sync (at configured interval)
│ sync: client, products, address, payment method
│ OmniSales status: 0 - Draft → 1 - New
│
↓
[ORDER VALIDATION]
│ status: 2 - Processing
│ stock check: qty_available vs qty_ordered
│ client check: created/matched in Clients
│ ├── Stock OK → continue
│ └── Insufficient stock → operator alert → hold (9) or partial order
│
↓
[PICKING & PACKING]
│ Goods Delivery Note generated automatically
│ Packing List created from delivery note
│ warehouse operator: confirms each item (scanned or manually ticked)
│ warehouse status: wh_ready_to_deliver
│
↓
[SHIPPING — AWB]
│ AWB generated via Innoship (recommended) or direct Couriers
│ label printed → affixed to parcel
│ OmniSales status: 4 - Shipping · warehouse status: wh_in_transit
│ tracking number sent back to WooCommerce/Shopify (automatic sync)
│
↓
[INVOICING]
│ invoice generated automatically on Shipping (if create_invoice = on)
│ email with PDF invoice + AWB number → customer
│ eInvoice → ANAF if B2B customer with valid VAT number (automatic)
│
↓
[DELIVERY CONFIRMED]
│ Innoship/Courier tracking → packing list status: wh_delivered
│ OmniSales status: 5 - Delivered/Completed
│ status updated in WooCommerce/Shopify: Completed
│
├── [RETURN (if applicable)]
│ │ customer requests return within allowed window
│ │ operator creates Goods Return Receipt
│ │ returned stock entered back into warehouse (or quarantine)
│ │ credit note issued or voucher / refund
│
[ORDER COMPLETED ✓]
Step by Step
1. Syncing the order from the e-commerce platform
Where: /admin/omni_sales/order_list · /admin/woocommerce · /admin/myshopify
Orders from the online store arrive in the CRM in two ways:
| Method | WooCommerce | Shopify | Frequency |
|---|---|---|---|
| Webhook (recommended) | On order placement — automatic push | On order placement — automatic push | Real-time |
| Cron sync (fallback) | Runs periodically; fetches new orders | Runs periodically; fetches new orders | Configured (e.g. 15 min) |
| Manual sync | Button in /admin/woocommerce/stores |
Button in /admin/myshopify |
On demand |
What is synced automatically:
- Order data: products, quantities, prices, discounts, payment method, shipping address
- Customer: if exists in CRM by email → matched; if not → created automatically in Clients
- Order status from the online platform maps to OmniSales status (configurable per channel)
Channel configuration: /admin/omni_sales/omni_sales_channel → Edit channel → set:
create_invoice: on/off (automatic invoice on shipping)- E-commerce ↔ OmniSales status mapping
- Price List associated with the e-commerce channel
- Default source warehouse
Key fields on the OmniSales order:
| Field | Description |
|---|---|
id_contact |
Link to the customer record in Clients |
channel_id |
Sales channel (WooCommerce/Shopify/manual) |
external_order_id |
Order ID in the external platform (for bidirectional sync) |
| Products + quantities + prices | Copied from the online order |
| Shipping address | Stored on the order |
| Payment method | Online card, cash on delivery, transfer, etc. |
2. Order validation and stock check
Where: /admin/omni_sales/order_list → open the order
OmniSales order statuses:
| Code | Status | Description | Action required |
|---|---|---|---|
| 0 | Draft | New unconfirmed order | Operator review |
| 1 | New | Entered in system, awaiting processing | — |
| 2 | Processing | Under stock check and confirmation | Operator validates |
| 3 | Confirmed | Confirmed, ready for warehouse | Delivery note auto-generated |
| 4 | Shipping | Parcel collected by courier | AWB issued |
| 5 | Delivered | Delivered and completed | — |
| 8 | Cancelled | Cancelled | Stock released |
| 9 | On Hold | Temporarily suspended | Manual intervention |
| 14 | Paid | Paid (useful for upfront card payment) | — |
| 15 | Ready | Ready for delivery | Warehouse confirms |
Stock check:
The system checks availability for each product line before creating the delivery note:
if inventory_manage.inventory_number < ordered_quantity:
flag_export_warehouse = 0 → delivery note blocked, operator alert
If stock is insufficient:
- Order moves to On Hold (9) status
- Operator sees the warning in the UI
- Options: partial delivery (
type_of_delivery = 'partial'), urgent procurement, or cancellation
Order approval (optional):
If enabled on the channel: approve_status → 0 (pending) → 1 (approved) → -1 (rejected). Useful for high-value orders or new customers without order history.
3. Picking and Packing — parcel preparation
Where: /admin/warehouse/manage_delivery · /admin/warehouse/manage_packing_list
3.1 Goods Delivery Note
Creation:
- Automatic — when the order reaches Confirmed (3) or Shipping (4) status (if the option is enabled on the channel)
- Manual — from the confirmed order → Generate Delivery Note button
Delivery note statuses:
| Status | Description |
|---|---|
ready_for_packing |
Created, awaiting picking in warehouse |
packed |
Products packed, packing list created |
Delivery types:
total— complete delivery in one gopartial— if not all products available; a second delivery note/packing list is generated later
3.2 Packing List
Creation: From the delivery note → Create Packing List button
The warehouse operator:
- Takes the product pick list
- Physically confirms each item (barcode scan or manual tick)
- Packs the parcel and fills in the dimensions
Mandatory fields for AWB generation:
| Field | Where to fill in | Notes |
|---|---|---|
| Weight (kg) | Packing List → edit | Mandatory for any courier |
| Length (cm) | Packing List → edit | Mandatory Innoship/Cargus/FanCourier |
| Width (cm) | Packing List → edit | Mandatory |
| Height (cm) | Packing List → edit | Mandatory |
| Courier service | Packing List → select | Standard, Express, Sameday, etc. |
| Delivery address | Copied from order | Editable if customer communicates a different address |
Packing list statuses:
| Status | Description |
|---|---|
wh_ready_to_deliver |
Created, awaiting AWB |
wh_in_transit |
AWB generated, parcel collected by courier |
wh_delivered |
Confirmed delivered by courier |
Partial packing: type_of_packing_list = 'partial' — deliver what is available now, the rest follows. Customer receives a separate notification for each parcel.
4. Generating the shipping AWB
Where: Generate AWB button from the approved packing list
Option A — Innoship (aggregator)
Configuration URL: /admin/innoship/settings
Couriers supported through Innoship: Fan Courier, DPD, Cargus, Sameday, GLS, DHL and others (per active Innoship contracts).
Prerequisites:
innoship_api_keyandinnoship_external_idconfigured- Courier and service selected in packing list
- Dimensions and weight filled in
- Valid delivery address in the Innoship database (recognised locality)
What happens when AWB is generated:
- CRM sends a request to the Innoship API with parcel data
- Innoship returns: AWB number + tracking code
- CRM creates a record in
wh_omni_shipments - Packing list status →
wh_in_transit - OmniSales order status →
Shipping (4) - Status updated in WooCommerce/Shopify automatically (bidirectional sync)
- AWB available for printing as A4 PDF or 100×150mm thermal label
- Log created in
innoship_audit_log
Option B — Direct Couriers (without aggregator)
URL: /admin/couriers
| Courier | Requirement |
|---|---|
| Cargus | Direct contract + configured Cargus API key |
| Fan Courier | Direct contract + FanCourier API credentials |
Advantage: no aggregator commission. Disadvantage: fewer couriers available, each configured separately.
| Solution | Available couriers | When to use |
|---|---|---|
| Innoship | Fan Courier, DPD, Cargus, Sameday, GLS, DHL + others | You have an Innoship contract and want multi-courier flexibility |
| Direct Couriers | Cargus, Fan Courier | You have direct contracts and don't want an intermediary |
Tracking: From the AWB list (/admin/innoship/awb or /admin/couriers/awb) the status is updated automatically via periodic polling.
5. Invoicing — issuing the fiscal document
Where: /admin/invoices
Invoice generation modes:
| Mode | When | Configuration |
|---|---|---|
| Automatic on Shipping | When OmniSales order reaches status 4 | create_invoice = on on channel |
| Automatic on payment confirmation | At status Paid (14) | Useful for upfront online card payment |
| Manual | Operator generates from order | Create Invoice button |
Invoice content:
- Product lines with quantities and prices from order
- Applicable discounts (from Price List or manual)
- VAT per product configuration
- Customer data (billing address from customer profile)
Customer notification: On invoice issue: automatic email with PDF invoice attached + AWB number for tracking.
eInvoice (B2B with VAT number)
If the customer is a legal entity with a valid VAT number:
- eInvoice automatically generated in XML format per ANAF
- Automatically transmitted to ANAF through the eInvoice module
- ANAF registration number returned and stored on the invoice
Where to check: /admin/invoices → invoice → eInvoice tab → transmission status
6. Delivery confirmation
Automatic tracking: Innoship or the direct courier confirms delivery via API → statuses updated automatically:
| Document | Previous status | Final status |
|---|---|---|
| Packing List | wh_in_transit |
wh_delivered |
| OmniSales Order | Shipping (4) |
Delivered (5) |
| WooCommerce/Shopify Order | Processing/Shipped | Completed |
Stock is definitively decremented from the warehouse when the delivery note is approved (not on physical delivery). On courier confirmation → only status updates, not stock.
7. Returns — the Goods Return sub-flow
Where: /admin/warehouse/manage_order_return_receipt
Return window: configurable per channel (default 30 days from delivery).
Return flow steps:
| Step | Action | Who |
|---|---|---|
| 1 | Customer requests return (email, phone, portal) | Customer |
| 2 | Operator checks eligibility (within window, unused product) | Order operator |
| 3 | Goods Return Receipt created in CRM (linked to original order) | Operator |
| 4 | Customer sends parcel back (return AWB if applicable) | Customer |
| 5 | Warehouse receives returned goods | Warehouse |
| 6 | Returned stock entered into warehouse (or quarantine) | Automatic on approval |
| 7 | Credit Note issued OR voucher/refund processed | Finance |
Return types:
| Type | Description |
|---|---|
fully |
Entire order returned |
partially |
Part of products returned |
manual |
Manual adjustment (e.g. defective product without physical return) |
Relevant table: wh_order_returns → original_order_id (link to OmniSales order)
Credit Note: Issued automatically or manually from the Goods Return Receipt → appears in the customer's financial history.
What gets created automatically
| Trigger event | Automatically created document | Condition |
|---|---|---|
| Order placed in WooCommerce/Shopify | OmniSales Order + Customer (if new) | Active webhook or cron sync |
| Order → Confirmed (3) status | Delivery Note with order lines | Auto-create option enabled on channel |
| Packing List approved + Generate AWB | wh_omni_shipments, Innoship log, AWB label |
Innoship/Courier API configured |
| AWB generated | Order status → Shipping (4), sync in WooCommerce/Shopify | — |
Order → Shipping (4) status with create_invoice = on |
Invoice with order lines | create_invoice = on on channel |
| Invoice issued + B2B customer with VAT number | eInvoice XML sent to ANAF | eInvoice module active |
| Courier confirms delivery | Status → Delivered (5); sync in online platform | Innoship tracking polling |
| Goods Return Receipt approved | Stock credited back in warehouse | Manual approval |
Where the flow can stall
| Problem | Probable cause | Solution |
|---|---|---|
| Order not appearing from WooCommerce | Webhook not configured or cron stopped | Check /admin/woocommerce/stores → webhook URL; restart cron |
| Order not appearing from Shopify | API credentials expired or Shopify webhook inactive | Reconnect store from /admin/myshopify |
| Customer not created automatically | Duplicate email or missing required field | Check field mapping in channel settings |
| Delivery note not generated | Auto-create option disabled on channel | Enable from /admin/omni_sales/omni_sales_channel → Edit |
| Delivery note blocked (stock 0) | Insufficient stock in warehouse | Check pending receipt notes; make stock adjustment or partial delivery |
| Innoship AWB error — unknown locality | Customer address misspelled | Edit address; check if locality is in Innoship database |
| AWB error — dimensions missing | Weight/length/width/height fields not filled in | Fill in all 4 fields mandatory in packing list |
| Invoice not generated automatically | create_invoice = off on channel |
Enable from /admin/omni_sales/omni_sales_channel → Edit channel |
| eInvoice rejected by ANAF | Invalid VAT number, malformed XML, duplicate | Check customer VAT number; manual resubmission from eInvoice tab |
| Status not syncing back to WooCommerce | WooCommerce API credentials expired or WordPress updated | Reconnect store; check WooCommerce API key permissions |
| Partial packing list — second parcel forgotten | No internal process for two-tranche deliveries | Filter orders with type_of_packing_list = 'partial' and status wh_ready_to_deliver |
Relevant reports
| Report | URL | What to monitor |
|---|---|---|
| OmniSales orders per channel | /admin/omni_sales/report |
Volume per WooCommerce/Shopify, statuses, period |
| Sync audit | /admin/omni_sales/diary_sync |
Full WooCommerce/Shopify sync log, errors |
| AWBs in transit | /admin/innoship/awb |
Live courier status; undelivered AWBs |
| Innoship Audit Log | /admin/innoship/audit |
All AWB operations, API errors |
| Invoices generated from online orders | /admin/invoices filtered by channel |
E-commerce financial reconciliation |
| Stock movement history | /admin/warehouse/warehouse_history |
Movements generated by online orders |
| Blocked delivery notes | /admin/warehouse/manage_delivery filter flag_export_warehouse = 0 |
Orders with insufficient stock |
| Returns | /admin/warehouse/manage_order_return_receipt |
Return rate by period, per channel |
Modules involved — detailed documentation
E-commerce & Orders: Omni Sales Orders · Sales Channels · WooCommerce · Shopify
Warehouse: Delivery Notes · Packing Lists · Delivery Returns · Inventory History
Courier: Innoship Couriers
Finance: Invoices · Price Lists
Customers: Clients
Related workflows: OmniSales Fulfillment · Purchase to Pay · Warehouse Inbound → Outbound
Configure auto-invoice to trigger automatically when a WooCommerce or Shopify order reaches a specific status — this creates a draft CRM invoice without manual intervention and starts the fulfilment queue immediately.
AWB generation requires correct package weight and dimensions. If the picking team does not complete these fields on the delivery note, the AWB cannot be generated and the shipment is blocked at the labelling station.