ResellerOrders Module

The ResellerOrders module handles order flow through the reseller chain, including forwarding, acceptance, fulfillment, and status propagation.

Overview

This module manages:

  • Chain Orders - Orders that flow through the reseller hierarchy
  • Order Forwarding - Moving orders up the chain to fulfillment
  • Status Propagation - Syncing status across all levels
  • Fulfillment Tracking - Who ships and how

Order Flow

Complete Order Lifecycle

┌─────────────────────────────────────────────────────────────┐
│  1. CUSTOMER PLACES ORDER                                   │
│     Customer buys on Sub-Reseller's Shopify store          │
└─────────────────────────────┬───────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│  2. ORDER SYNCED TO AUTOCOM                                 │
│     Shopify webhook → Sub-Reseller's tenant database       │
│     Status: pending_forward                                 │
└─────────────────────────────┬───────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│  3. CHAIN ORDER CREATED                                     │
│     OrderForwardingService creates ChainOrder              │
│     Visible to all tenants in the chain                    │
└─────────────────────────────┬───────────────────────────────┘
                              │
              ┌───────────────┴───────────────┐
              ▼                               ▼
┌─────────────────────────┐     ┌─────────────────────────┐
│  4A. FORWARD UP CHAIN   │     │  4B. FULFILL LOCALLY    │
│  Order moves to parent  │     │  Reseller ships direct  │
│  Status: forwarded      │     │  Status: processing     │
└───────────┬─────────────┘     └───────────┬─────────────┘
            │                               │
            ▼                               │
┌─────────────────────────┐                 │
│  5. ACCEPTED BY PARENT  │                 │
│  Parent claims order    │                 │
│  Status: accepted       │                 │
└───────────┬─────────────┘                 │
            │                               │
            ▼                               │
┌─────────────────────────┐                 │
│  6. FULFILLMENT         │                 │
│  Fulfiller ships order  │◄────────────────┘
│  Status: shipped        │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────────────────────────────────────────┐
│  7. DELIVERED                                               │
│     Courier confirms delivery                               │
│     Status: delivered                                       │
│     → Triggers COD settlement flow                         │
└─────────────────────────────────────────────────────────────┘

Chain Order Model

Status Flow

pending_forward → forwarded → accepted → processing → shipped → delivered
                                    ↘                         ↗
                                      → cancelled / returned ←

Status Definitions

Status Description
pending_forward New order, awaiting forwarding decision
forwarded Sent to parent tenant
accepted Parent accepted responsibility
processing Being prepared for shipment
shipped Handed to courier
out_for_delivery With delivery agent
delivered Successfully delivered
cancelled Order cancelled
returned Returned by customer
rto Return to origin (failed delivery)

ChainOrder Structure

[
    'id' => 'chain-order-uuid',

    // Origin info (where order was placed)
    'origin_tenant_id' => 'sub-reseller-uuid',
    'origin_order_id' => 'local-order-uuid',
    'origin_order_number' => 'ORD-2024-001',

    // Current handler
    'current_tenant_id' => 'distributor-uuid',
    'current_order_id' => 'distributor-local-order-uuid',

    // Fulfiller (who will ship)
    'fulfiller_tenant_id' => 'super-admin-uuid',
    'fulfiller_order_id' => 'super-admin-local-order-uuid',

    // Chain info
    'chain_path' => ['super-admin', 'distributor', 'sub-reseller'],
    'chain_depth' => 3,
    'chain_status' => 'shipped',

    // Pricing
    'origin_total' => 155.00,      // Customer paid
    'fulfiller_total' => 100.00,   // Fulfiller's cost
    'cod_amount' => 155.00,
    'margin_breakdown' => [/* see architecture docs */],

    // Customer info
    'customer_name' => 'John Doe',
    'customer_phone' => '+919876543210',
    'shipping_address' => '123 Main St',
    'shipping_city' => 'Mumbai',
    'shipping_state' => 'Maharashtra',
    'shipping_pincode' => '400001',

    // Payment
    'payment_method' => 'cod',
    'payment_status' => 'pending',

    // Shipping
    'tracking_number' => 'DEL123456789',
    'carrier' => 'delhivery',
    'shipped_at' => '2024-01-15T10:30:00Z',
    'delivered_at' => null,
]

Services

OrderForwardingService

Handles order creation and forwarding:

use Modules\ResellerOrders\App\Services\OrderForwardingService;

$service = app(OrderForwardingService::class);

// Create a new chain order
$chainOrder = $service->createChainOrder(
    originTenant: $subReseller,
    localOrderId: 'local-order-uuid',
    orderData: [
        'order_number' => 'ORD-2024-001',
        'total' => 155.00,
        'items' => [...],
        'customer' => [...],
        'shipping_address' => [...],
        'payment_method' => 'cod',
    ]
);

// Forward to parent
$chainOrder = $service->forwardOrder($chainOrder, $subReseller);

// Parent accepts
$chainOrder = $service->acceptOrder($chainOrder, $distributor);

// Someone claims for fulfillment
$chainOrder = $service->claimForFulfillment($chainOrder, $superAdmin);

StatusPropagationService

Syncs status across the chain:

use Modules\ResellerOrders\App\Services\StatusPropagationService;

$service = app(StatusPropagationService::class);

// Mark as shipped
$chainOrder = $service->markShipped(
    chainOrder: $chainOrder,
    fulfiller: $superAdmin,
    trackingNumber: 'DEL123456789',
    carrier: 'delhivery',
    userId: $user->id
);

// Mark as delivered (triggers COD settlement)
$chainOrder = $service->markDelivered($chainOrder, $user->id);

// Cancel order
$chainOrder = $service->cancelOrder(
    chainOrder: $chainOrder,
    reason: 'Customer requested cancellation',
    userId: $user->id
);

API Endpoints

List Orders

GET /api/v1/chain-orders
GET /api/v1/chain-orders/incoming    # From sub-resellers
GET /api/v1/chain-orders/forwarded   # Sent to parent
GET /api/v1/chain-orders/fulfillment # To be fulfilled

Order Details

GET /api/v1/chain-orders/{id}
GET /api/v1/chain-orders/{id}/timeline

Order Actions

POST /api/v1/chain-orders/{id}/forward
POST /api/v1/chain-orders/{id}/accept
POST /api/v1/chain-orders/{id}/ship
POST /api/v1/chain-orders/{id}/deliver
POST /api/v1/chain-orders/{id}/cancel

Statistics

GET /api/v1/chain-orders/stats

Example API Responses

List Incoming Orders

GET /api/v1/chain-orders/incoming
Authorization: Bearer <token>
X-Tenant: distributor-uuid
{
  "orders": [
    {
      "id": "chain-order-uuid",
      "origin_order_number": "ORD-2024-001",
      "from_tenant": {
        "id": "sub-reseller-uuid",
        "name": "Retail Store ABC"
      },
      "customer_name": "John Doe",
      "shipping_city": "Mumbai",
      "total_at_your_cost": 120.00,
      "origin_total": 155.00,
      "your_margin": 18.00,
      "payment_method": "cod",
      "status": "pending_forward",
      "created_at": "2024-01-15T09:00:00Z"
    }
  ],
  "stats": {
    "pending": 5,
    "accepted": 12,
    "shipped": 45
  },
  "pagination": {
    "current_page": 1,
    "total": 62
  }
}

Get Order Details

GET /api/v1/chain-orders/chain-order-uuid
Authorization: Bearer <token>
X-Tenant: distributor-uuid
{
  "order": {
    "id": "chain-order-uuid",
    "origin_order_number": "ORD-2024-001",
    "chain_status": "shipped",
    "chain_path": [
      {
        "tenant_id": "super-admin-uuid",
        "tenant_name": "Super Admin",
        "role": "fulfiller",
        "cost": 100.00
      },
      {
        "tenant_id": "distributor-uuid",
        "tenant_name": "Distributor ABC",
        "role": "current",
        "cost": 120.00,
        "margin": 18.00
      },
      {
        "tenant_id": "sub-reseller-uuid",
        "tenant_name": "Retail Store XYZ",
        "role": "origin",
        "cost": 138.00,
        "margin": 17.00
      }
    ],
    "customer": {
      "name": "John Doe",
      "phone": "+919876543210",
      "email": "john@example.com"
    },
    "shipping_address": {
      "line1": "123 Main Street",
      "city": "Mumbai",
      "state": "Maharashtra",
      "pincode": "400001"
    },
    "items": [
      {
        "product_id": "prod-uuid",
        "name": "Premium Widget",
        "quantity": 2,
        "price_at_origin": 77.50,
        "price_at_your_cost": 60.00
      }
    ],
    "pricing": {
      "origin_total": 155.00,
      "your_cost": 120.00,
      "your_margin": 18.00,
      "cod_amount": 155.00
    },
    "shipping": {
      "carrier": "delhivery",
      "tracking_number": "DEL123456789",
      "shipped_at": "2024-01-15T10:30:00Z",
      "estimated_delivery": "2024-01-18"
    },
    "payment": {
      "method": "cod",
      "status": "pending"
    }
  }
}

Get Order Timeline

GET /api/v1/chain-orders/chain-order-uuid/timeline
{
  "timeline": [
    {
      "id": "history-1",
      "status": "pending_forward",
      "previous_status": null,
      "changed_by_tenant": "Retail Store XYZ",
      "changed_by_user": "store_admin@example.com",
      "notes": "Order received from Shopify",
      "created_at": "2024-01-15T09:00:00Z"
    },
    {
      "id": "history-2",
      "status": "forwarded",
      "previous_status": "pending_forward",
      "changed_by_tenant": "Retail Store XYZ",
      "notes": "Forwarded to parent for fulfillment",
      "created_at": "2024-01-15T09:05:00Z"
    },
    {
      "id": "history-3",
      "status": "accepted",
      "previous_status": "forwarded",
      "changed_by_tenant": "Distributor ABC",
      "notes": "Order accepted",
      "created_at": "2024-01-15T09:30:00Z"
    },
    {
      "id": "history-4",
      "status": "shipped",
      "previous_status": "accepted",
      "changed_by_tenant": "Super Admin",
      "metadata": {
        "tracking_number": "DEL123456789",
        "carrier": "delhivery"
      },
      "created_at": "2024-01-15T10:30:00Z"
    }
  ]
}

Ship Order

POST /api/v1/chain-orders/chain-order-uuid/ship
Authorization: Bearer <token>
X-Tenant: super-admin-uuid
Content-Type: application/json

{
  "tracking_number": "DEL123456789",
  "carrier": "delhivery"
}
{
  "message": "Order marked as shipped",
  "order": {
    "id": "chain-order-uuid",
    "chain_status": "shipped",
    "tracking_number": "DEL123456789",
    "carrier": "delhivery",
    "shipped_at": "2024-01-15T10:30:00Z"
  }
}

Frontend Pages

Chain Orders Dashboard

Route: /reseller-orders

Features:

  • Overview of all chain orders
  • Status breakdown chart
  • Quick filters
  • Recent activity feed

Incoming Orders

Route: /reseller-orders/incoming

Features:

  • Orders from sub-resellers
  • Accept/forward actions
  • Bulk operations
  • Filter by status, date, sub-reseller

Forwarded Orders

Route: /reseller-orders/forwarded

Features:

  • Orders you've sent up the chain
  • Track fulfillment progress
  • Settlement status

Fulfillment Queue

Route: /reseller-orders/fulfillment

Features:

  • Orders you need to ship
  • Generate shipping labels
  • Bulk ship functionality
  • Print packing slips

Database Schema

chain_orders

CREATE TABLE chain_orders (
    id UUID PRIMARY KEY,

    -- Origin
    origin_tenant_id VARCHAR(36) NOT NULL,
    origin_order_id VARCHAR(36),
    origin_order_number VARCHAR(100),

    -- Current handler
    current_tenant_id VARCHAR(36) NOT NULL,
    current_order_id VARCHAR(36),

    -- Fulfiller
    fulfiller_tenant_id VARCHAR(36),
    fulfiller_order_id VARCHAR(36),

    -- Chain info
    chain_path JSONB NOT NULL DEFAULT '[]',
    chain_depth INTEGER DEFAULT 1,
    chain_status VARCHAR(30) DEFAULT 'pending_forward',

    -- Pricing
    origin_total DECIMAL(14,2) NOT NULL,
    fulfiller_total DECIMAL(14,2),
    cod_amount DECIMAL(14,2),
    margin_breakdown JSONB DEFAULT '[]',

    -- Customer
    customer_name VARCHAR(255),
    customer_phone VARCHAR(20),
    customer_email VARCHAR(255),

    -- Shipping
    shipping_address TEXT,
    shipping_city VARCHAR(100),
    shipping_state VARCHAR(100),
    shipping_pincode VARCHAR(10),
    shipping_country VARCHAR(50) DEFAULT 'India',

    -- Payment
    payment_method VARCHAR(20) DEFAULT 'cod',
    payment_status VARCHAR(20) DEFAULT 'pending',

    -- Tracking
    tracking_number VARCHAR(100),
    carrier VARCHAR(50),
    shipped_at TIMESTAMP,
    delivered_at TIMESTAMP,

    -- Items
    items JSONB DEFAULT '[]',

    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

CREATE INDEX idx_chain_orders_origin ON chain_orders(origin_tenant_id);
CREATE INDEX idx_chain_orders_current ON chain_orders(current_tenant_id);
CREATE INDEX idx_chain_orders_fulfiller ON chain_orders(fulfiller_tenant_id);
CREATE INDEX idx_chain_orders_status ON chain_orders(chain_status);

chain_order_status_history

CREATE TABLE chain_order_status_history (
    id UUID PRIMARY KEY,
    chain_order_id UUID NOT NULL REFERENCES chain_orders(id),
    status VARCHAR(30) NOT NULL,
    previous_status VARCHAR(30),
    changed_by_tenant_id VARCHAR(36),
    changed_by_user_id VARCHAR(36),
    notes TEXT,
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMP
);

CREATE INDEX idx_status_history_order ON chain_order_status_history(chain_order_id);

Events

Event When Fired Payload
ChainOrderCreated New chain order order, origin_tenant
ChainOrderForwarded Order forwarded up order, from_tenant, to_tenant
ChainOrderAccepted Order accepted order, accepting_tenant
ChainOrderStatusChanged Any status change order, old_status, new_status
ChainOrderShipped Order shipped order, tracking, carrier
ChainOrderDelivered Order delivered order (triggers settlement)

Permissions

Permission Description
chain_orders.view View orders in the reseller chain
chain_orders.accept Accept incoming orders
chain_orders.fulfill Mark orders as shipped/delivered
chain_orders.forward Forward orders up the chain
chain_orders.cancel Cancel orders

Configuration

// config/reseller-orders.php

return [
    // Auto-forward orders to parent
    'auto_forward' => false,

    // Auto-accept incoming orders
    'auto_accept' => false,

    // Default fulfiller (null = manual selection)
    'default_fulfiller' => null,

    // Days to accept before auto-escalation
    'accept_deadline_days' => 1,

    // Notify on new incoming orders
    'notify_incoming' => true,

    // Supported carriers
    'carriers' => ['delhivery', 'shiprocket', 'bluedart', 'manual'],
];

Best Practices

Order Processing

  1. Process quickly - Set up notifications for incoming orders
  2. Communicate status - Each status change is visible to all chain members
  3. Accurate tracking - Enter tracking numbers promptly
  4. Handle exceptions - Use cancellation/return flows appropriately

Fulfillment Strategy

  1. Centralized fulfillment - Most efficient for COD handling
  2. Local fulfillment - Faster delivery but complex settlements
  3. Hybrid approach - Different strategies by region/product

Next Steps