Orders Module — Complete Feature List

This document catalogs every feature built in the Orders module across 11 implementation phases, covering the full order lifecycle from ingest to delivery.

Phase 1: Foundation & Ingest Pipeline

The canonical entry point for all order creation. Every source (Shopify, WooCommerce, manual, CSV, API) flows through a single pipeline.

Services

  • OrderIngestServiceingest(), upsert() (idempotent by source_module + external_id), ingestBatch() with chunking
  • OrderEventPublisher — typed wrapper publishing 8 event types via Module Event Bus
  • OrderBusHandler — exposes 10 Module API Bus endpoints for cross-module communication

DTOs

  • IngestOrderDTO — readonly typed DTO with fromArray() factory, numeric casting, and toArray() roundtrip
  • IngestResult — mutable accumulator tracking created, updated, skipped, errors, orderIds

Models Added

  • OrderStatusHistory — tracks who changed what status and when
  • OrderMetadata — key-value metadata scoped by module (avoids cross-module conflicts)
  • ShipmentEvent — carrier tracking events with raw webhook data
  • NdrCase — non-delivery report tracking per shipment

Customer Resolution

Orders can reference customers by:

  • Customer UUID (customer.id)
  • Phone number (customer.phone) — find-or-create
  • Email (customer.email) — find-or-create
  • Creates guest customer if none matched

Bus Integration (10 endpoints)

Method Description
orders.create Create via ingest pipeline
orders.createOrUpdate Idempotent upsert
orders.batchIngest Batch ingest
orders.get Get by ID
orders.updateStatus Update status
orders.getByExternalIds Find by source + external IDs
orders.getStats Statistics
orders.reserveInventory Publish reservation event
orders.processReturn Process return
orders.processRefund Process refund

Events Published (13 total)

order.created, order.status_changed, order.cancelled, order.fulfilled, order.delivered, order.payment_updated, order.refund_processed, order.return_requested, order.return_approved, order.inventory_reserved, order.inventory_released, order.shipment_created, order.import_completed


Phase 2: Database Optimization (PostgreSQL)

PostgreSQL-specific optimizations for large-scale order volumes.

Schema Changes

  • JSON to JSONB conversion on orders.tags, order_items.properties, shipment_events.raw_data, shipments.dimensions
  • Added missing payment_method column (varchar 50)
  • Added ordered_at timestamp

Indexes

  • GIN index on orders.tags — fast @> containment queries
  • Composite indexes: (status, created_at), (payment_status, created_at), (source_module, created_at), (customer_id, created_at)
  • Partial indexes: WHERE status = 'pending', WHERE status = 'ready_to_ship' — smaller, faster for hot status queries
  • BRIN index on created_at — 100x smaller than B-tree for naturally ordered data

New Tables

  • order_activity_logorder_id, actor_type, actor_id, action, description, changes (jsonb), metadata (jsonb)
  • order_imports — tracks bulk import jobs with total_rows, processed_rows, error_count, errors (jsonb)

Models

  • OrderActivityLog
  • OrderImport

Phase 3: Payment Lifecycle

Full payment tracking with multiple providers, partial payments, reconciliation, and refunds.

Tables

  • order_payments — UUID, provider_module, external_payment_id, method, status, amount, payment_link_url, payment_link_expires_at, metadata (jsonb), paid_at
  • order_refunds — UUID, payment_id, external_refund_id, amount, reason, status, processed_at

PaymentService

  • recordPayment() — records payment and auto-reconciles order status
  • createPaymentLink() — generates shareable payment link via provider module
  • processRefund() — creates refund record, updates payment status
  • recordCodCollection() — records cash collected on delivery
  • reconcilePaymentStatus() — auto-sets order to paid, partial, or refunded based on payment sums

Order Accessors

  • $order->total_paid — sum of completed payments
  • $order->balance_duetotal - total_paid

Reconciliation Logic

  • Total paid >= order total → status becomes paid
  • Total paid > 0 but < total → status becomes partial
  • Total refunded >= total paid → status becomes refunded

Phase 4: Fulfillment & Shipping

Shipment lifecycle with partial fulfillment, tracking, and carrier integration.

Schema Enhancements

  • order_item_ids (jsonb) on shipments — tracks which items are in which package
  • label_url, pickup_token, estimated_delivery_at, tracking_url, ndr_count

ShippingService

  • createShipment() — creates shipment record, updates order status
  • cancelShipment() — cancels shipment with carrier
  • Rate comparison stubs for multi-carrier support

Partial Fulfillment

  • Orders can have multiple shipments (changed from HasOne to HasMany)
  • Each shipment tracks which order_item_ids it contains
  • Order status reflects overall fulfillment state

Tracking

  • SyncTrackingStatusJob — polls in-transit shipments every 30 minutes
  • ShipmentWebhookController — receives carrier push updates
  • ShipmentEvent model stores tracking history with raw webhook data

Phase 5: Returns & Refunds

Complete return lifecycle with auto-generated return numbers and integrated refund processing.

Return Lifecycle

requested → approved → received → refunded
         → rejected

ReturnService

  • requestReturn() — creates return with auto-generated RET-YYYYMMDD-XXXX number
  • approveReturn() — sets approved status, records approver and refund amount
  • rejectReturn() — sets rejected status with admin notes
  • markReceived() — marks items as received back
  • processRefundForReturn() — calls PaymentService::processRefund() and marks return as refunded

Return Model Fields

  • return_number (auto-generated)
  • reason_category, reason_detail, customer_notes, admin_notes
  • items (jsonb) — which items being returned
  • refund_amount, refund_method
  • approved_by, approved_at, received_at, refunded_at

Phase 6: Inventory Integration

Event-driven stock management with graceful degradation.

Pattern

  • On order created → publishes order.inventory_reserved with item SKUs/quantities
  • On order cancelled → publishes order.inventory_released
  • On shipment created → converts reservation to permanent decrement

Graceful Degradation

  • Works without any inventory module installed
  • Events are published regardless — no subscribers means no action
  • Adding/removing inventory modules doesn't break orders

Listeners

  • OnOrderCreatedReserveStock — self-subscribes to order.created
  • OnOrderCancelledReleaseStock — self-subscribes to order.cancelled

Phase 7: Tax & Invoicing

Indian GST-compliant tax calculation and sequential invoice generation.

TaxService

  • Intra-state: Splits into CGST + SGST (half rate each)
  • Inter-state: Full IGST at combined rate
  • Rate lookup by HSN code via TaxConfiguration model
  • Supports standard GST rates: 0%, 5%, 12%, 18%, 28%
  • Default fallback: 18%

InvoiceService

  • generateInvoice() — auto-populates from order items, calculates tax, generates sequential number
  • generateCreditNote() — creates credit note for refunds
  • Sequential numbering: INV-YYYYMM-NNNN, CN-YYYYMM-NNNN, PI-YYYYMM-NNNN

Invoice Types

  • Invoice (INV-) — standard tax invoice
  • Credit Note (CN-) — issued for refunds/returns
  • Proforma (PI-) — pre-payment invoice

Phase 8: Notifications & Automation

Configurable notification rules triggered by order events.

OrderNotificationService

  • processEvent() — finds all active rules matching the event
  • matchesConditions() — evaluates rule conditions against event payload
  • renderTemplate() — replaces {{placeholder}} tokens, preserves unmatched ones

Supported Channels

  • SMS (via provider module)
  • WhatsApp (via channel module)
  • Email (via email service)
  • In-app notifications

Template Placeholders

{{order_number}}, {{customer_name}}, {{total}}, {{status}}, {{tracking_url}}, {{return_number}}

Conditional Rules

Rules can filter by event payload fields:

{ "conditions": { "new_status": "confirmed", "payment_status": "cod" } }

Phase 9: Bulk Operations

High-volume operations with queued processing and progress tracking.

CSV Import

  • Parse and validate CSV files
  • Process in 500-row chunks via Bus::batch()
  • PostgreSQL INSERT ... ON CONFLICT DO UPDATE for idempotent upserts
  • Real-time progress via Laravel Reverb WebSockets
  • Cancellable — job checks status between chunks

CSV Export

  • Cursor-based streaming for memory efficiency
  • Configurable column selection
  • Filter by status, date range, etc.

Bulk Operations

  • Bulk status update — single SQL UPDATE ... WHERE id IN (...)
  • Bulk ship — create shipments from tracking CSV
  • Bulk cancel — cancel multiple orders with reason

Queue Configuration

  • imports queue — dedicated supervisor, 600s timeout
  • exports queue — dedicated supervisor, 300s timeout

Phase 10: Analytics & Reporting

Real-time analytics with PostgreSQL materialized views for performance.

OrderAnalyticsService

  • getDashboardMetrics() — total orders, revenue, AOV, unique customers, status/payment breakdowns
  • getRevenueTimeSeries() — daily order counts and revenue
  • getSourceBreakdown() — orders and revenue by source module
  • getFulfillmentMetrics() — delivery rate, cancellation rate, RTO rate
  • getCodVsPrepaid() — COD vs prepaid count and revenue split
  • getTopProducts() — products ranked by quantity and revenue

Materialized Views

  • mv_daily_order_stats — pre-aggregated daily metrics
  • mv_order_source_stats — per-source daily metrics
  • Refreshed every 15 minutes via REFRESH MATERIALIZED VIEW CONCURRENTLY
  • Uses unique indexes for non-blocking concurrent refresh

Phase 11: Advanced Features

Outbound webhooks, order amendments, and tenant-definable custom fields.

Outbound Webhooks

  • Register HTTP endpoints to receive order events
  • HMAC-SHA256 signature verification via X-Webhook-Signature header
  • 3 retries with 60-second backoff
  • Auto-disable after 10 consecutive failures
  • Full delivery logging with response status, body, and duration

Order Amendments

  • amendItems() — replace order items, recalculate totals, log activity
  • amendAddress() — update shipping/billing address, log activity
  • syncBackToSource() — push changes back to source store (Shopify, etc.) via bus

Custom Fields

  • Tenant-definable fields stored in custom_fields JSONB column
  • Field types: text, number, select, boolean, date
  • Fields can be marked as is_required and is_filterable
  • CRUD API for field definitions

Infrastructure Summary

Metric Count
API routes 70+
Services 14
Models (new/modified) 12
Migrations 10
Controllers 10
Jobs 6
Listeners 4
DTOs 2
Bus endpoints (provides) 10
Events published 13
Tests 129 (68 unit + 61 feature)

Test Coverage

Category Tests What's Covered
Order Model 14 Status/payment constants, fillable, casts, canShip/canCancel
IngestOrderDTO 7 Creation, defaults, roundtrip, type casting, readonly
IngestResult 8 Counters, error tracking, structure
TaxService 7 CGST/SGST split, IGST, rate variations, rounding
NotificationService 5 Template rendering with placeholders
OutboundWebhookService 4 Failure threshold disabling
OrderEventPublisher 8 All lifecycle event publishing
OrderBusHandler 3 Format structure, stub responses
OrderReturn Model 6 Constants, number generation, casts
OrderInvoice Model 6 Type/status constants, casts
OrderIngestService 9 Ingest, upsert, batch, customer resolution
PaymentService 10 Record, reconcile, refund, COD, payment links
ReturnService 8 Full lifecycle (request to refund)
InvoiceService 9 Generation, numbering, credit notes
OrderAnalyticsService 10 Metrics, revenue, fulfillment, COD/prepaid
OrderService 7 Create, update, bulk status, statistics
Order API 8 HTTP endpoints (CRUD, status, stats)

Related Documentation