Skip to content

Supply Chain Flow

This page traces the complete lifecycle of a product from Brand creation to an end-customer purchase, covering every service interaction, event, and data transformation along the way.

End-to-End Flow

Step-by-Step Breakdown

Phase 1: Catalog Setup

StepServiceAction
1BrandBrand creates/updates master catalog
2BrandPublishes new catalog version
3KafkaBrandCatalogUpdated event emitted
4SupplierConsumes event, imports catalog with Supplier pricing
5KafkaSupplierProductPublished event emitted
6RetailerConsumes event, adopts products with retail pricing

Phase 2: Order Placement

StepServiceAction
7RetailerCustomer submits order via storefront
8Supply ChainCreates order record, starts Saga
9PaymentCreates Stripe PaymentIntent, authorises funds
10SupplierRedis lock acquired on inventory
11Supply ChainConfirms all steps succeeded

Phase 3: Payment and Fulfillment

StepServiceAction
12PaymentCaptures payment from Stripe
13Stripe ConnectSplits payment: Brand / Supplier / Retailer / Platform
14KafkaPaymentCapturedOrderConfirmed emitted
15SupplierBegins production
16Notification"Order confirmed" email sent to customer
17SupplierMarks order dispatched, emits OrderDispatched
18Notification"Order dispatched" email with tracking sent to customer

Saga Pattern and Compensation

The Supply Chain Service orchestrates a Saga across multiple services. If any step fails, compensating actions are triggered:

Failure pointCompensation
Payment authorisation failsOrder cancelled, no inventory reserved
Inventory unavailablePayment authorisation voided
Payment capture failsInventory lock released, order cancelled
Supplier rejects orderPayment refunded, order cancelled, customer notified

Compensation events follow the naming convention {Event}Compensated e.g. OrderPlacementCompensated.

Payment Split

Stripe Connect distributes the order value automatically at capture time:

Customer pays retail price
  ├── Retailer margin  = retail_price − supplier_price
  ├── Supplier amount  = supplier_price − brand_trade_price
  ├── Brand amount     = brand_trade_price
  └── Platform fee     = (configurable %, deducted from each party's transfer)

The exact percentages and amounts are recorded in the Payment Service ledger for each order.

Domain Routing During Order Processing

All service-to-service HTTP calls (where used) go through the internal Docker network by service name. The Nginx reverse proxy is only for external traffic. Service discovery uses Docker DNS: http://supply-chain:9000, http://payment:9000, etc.

Cross-service calls within the Saga use Laravel HTTP client with circuit breakers (via Guzzle retry middleware) and a standard timeout of 10 seconds.

Blindstrader Platform Documentation