Commerce Module (Products, Cart, Orders)
Overview
The Commerce Module handles the complete e-commerce functionality of the IWM Platform, including product catalog management, shopping cart operations, checkout process, order fulfillment, payment processing, and shipping integration. It integrates with the MLM Module for referral attribution and commission triggering.
Responsibilities
- Product catalog and category management
- Inventory tracking and stock management
- Shopping cart (guest and authenticated)
- Multi-step checkout process
- Order lifecycle management
- Payment processing (Stripe, YooKassa)
- Shipping integration (CDEK, DHL)
- Returns and refund handling
- Referral attribution for orders
Domain Entities
Product
Core product entity for the catalog.
| Field | Type | Description |
|---|---|---|
| id | UUID | Product identifier |
| category_id | UUID | Category reference |
| sku | VARCHAR(50) | Stock keeping unit (unique) |
| name | VARCHAR(200) | Product name |
| slug | VARCHAR(200) | URL-friendly identifier |
| short_description | VARCHAR(500) | Brief description |
| description | TEXT | Full description |
| base_price | DECIMAL | Regular price |
| sale_price | DECIMAL | Discounted price |
| cost_price | DECIMAL | Internal cost |
| currency | VARCHAR(3) | Price currency |
| status | ENUM | Product status |
| stock_quantity | INT | Available stock |
| low_stock_threshold | INT | Alert threshold |
| weight_grams | INT | Product weight |
| dimensions | JSONB | Length, width, height |
| career_points_value | DECIMAL | MLM points per purchase |
| is_featured | BOOLEAN | Featured flag |
Category
Product category with hierarchical structure.
| Field | Type | Description |
|---|---|---|
| id | UUID | Category identifier |
| name | VARCHAR(100) | Category name |
| slug | VARCHAR(100) | URL-friendly identifier |
| description | TEXT | Category description |
| parent_id | UUID | Parent category |
| path | LTREE | Materialized path for hierarchy |
| image_url | VARCHAR(500) | Category image |
| sort_order | INT | Display order |
| is_active | BOOLEAN | Active status |
Cart
Shopping cart for users and guests.
| Field | Type | Description |
|---|---|---|
| id | UUID | Cart identifier |
| user_id | UUID | User reference (optional) |
| session_id | VARCHAR(100) | Guest session ID |
| referring_partner_id | UUID | MLM attribution |
| status | ENUM | Cart status |
| subtotal | DECIMAL | Items total |
| discount_total | DECIMAL | Applied discounts |
| total | DECIMAL | Final total |
| currency | VARCHAR(3) | Cart currency |
| expires_at | TIMESTAMP | Cart expiration |
CartItem
Individual items in a cart.
| Field | Type | Description |
|---|---|---|
| id | UUID | Item identifier |
| cart_id | UUID | Cart reference |
| product_id | UUID | Product reference |
| quantity | INT | Item quantity |
| unit_price | DECIMAL | Price per unit |
| total_price | DECIMAL | Line total |
| added_at | TIMESTAMP | Addition time |
Order
Customer order record.
| Field | Type | Description |
|---|---|---|
| id | UUID | Order identifier |
| order_number | VARCHAR(20) | Human-readable number |
| user_id | UUID | Customer reference |
| status | ENUM | Order status |
| subtotal | DECIMAL | Items total |
| discount_total | DECIMAL | Applied discounts |
| shipping_cost | DECIMAL | Shipping charge |
| tax_amount | DECIMAL | Applicable taxes |
| total | DECIMAL | Final total |
| currency | VARCHAR(3) | Order currency |
| shipping_address_id | UUID | Delivery address |
| billing_address_id | UUID | Billing address |
| shipping_method_id | UUID | Delivery method |
| referring_partner_id | UUID | MLM attribution |
| notes | TEXT | Customer notes |
OrderItem
Line items in an order (snapshot of product at purchase time).
| Field | Type | Description |
|---|---|---|
| id | UUID | Item identifier |
| order_id | UUID | Order reference |
| product_id | UUID | Product reference |
| sku | VARCHAR(50) | SKU snapshot |
| name | VARCHAR(200) | Name snapshot |
| quantity | INT | Item quantity |
| unit_price | DECIMAL | Price per unit |
| total_price | DECIMAL | Line total |
| career_points_value | DECIMAL | MLM points earned |
Payment
Payment transaction for an order.
| Field | Type | Description |
|---|---|---|
| id | UUID | Payment identifier |
| order_id | UUID | Order reference |
| amount | DECIMAL | Payment amount |
| currency | VARCHAR(3) | Payment currency |
| method | ENUM | CARD, EWALLET, BANK_TRANSFER |
| provider | ENUM | STRIPE, YOOKASSA |
| status | ENUM | Payment status |
| provider_reference | VARCHAR(255) | External transaction ID |
| provider_response | JSONB | Full provider response |
| paid_at | TIMESTAMP | Successful payment time |
| failed_at | TIMESTAMP | Failure time |
| refunded_at | TIMESTAMP | Refund time |
Shipment
Shipment tracking for an order.
| Field | Type | Description |
|---|---|---|
| id | UUID | Shipment identifier |
| order_id | UUID | Order reference |
| carrier | VARCHAR(50) | CDEK, DHL, etc. |
| tracking_number | VARCHAR(100) | Carrier tracking number |
| status | ENUM | Shipment status |
| shipped_at | TIMESTAMP | Ship date |
| estimated_delivery | DATE | Expected delivery |
| delivered_at | TIMESTAMP | Actual delivery |
| tracking_events | JSONB | Tracking history |
Address
Customer addresses for shipping/billing.
| Field | Type | Description |
|---|---|---|
| id | UUID | Address identifier |
| user_id | UUID | User reference |
| type | ENUM | SHIPPING, BILLING |
| first_name | VARCHAR(100) | Recipient first name |
| last_name | VARCHAR(100) | Recipient last name |
| company | VARCHAR(200) | Company name |
| address_line1 | VARCHAR(255) | Street address |
| address_line2 | VARCHAR(255) | Apt, suite, etc. |
| city | VARCHAR(100) | City |
| state | VARCHAR(100) | State/province |
| postal_code | VARCHAR(20) | Postal/ZIP code |
| country | VARCHAR(3) | ISO 3166-1 alpha-3 |
| phone | VARCHAR(20) | Contact phone |
| is_default | BOOLEAN | Default address flag |
Product Catalog
Category Hierarchy (LTREE)
Categories use PostgreSQL LTREE for efficient hierarchical queries:
Key LTREE Queries:
-- Get all products in "Health" and subcategories
SELECT p.* FROM products p
JOIN categories c ON p.category_id = c.id
WHERE c.path <@ 'health';
-- Get direct children of a category
SELECT * FROM categories
WHERE path ~ 'health.*{1}';
-- Get all ancestors of a category
SELECT * FROM categories
WHERE 'health.vitamins.multivitamins' <@ path;Product Attributes
Products support dynamic attributes via JSONB:
{
"color": "Blue",
"size": "Large",
"material": "Organic Cotton",
"weight_net": "500g",
"ingredients": ["Vitamin C", "Zinc", "Elderberry"]
}Product Images
Multiple images per product with ordering:
| Field | Description |
|---|---|
| url | CDN URL to image |
| alt_text | Accessibility text |
| sort_order | Display order |
| is_primary | Main product image |
Inventory Management
Stock Tracking
Stock Operations
| Operation | Trigger | Effect |
|---|---|---|
| Reserve | Add to cart | Temporarily holds stock |
| Release | Cart expires, item removed | Returns reserved stock |
| Commit | Order confirmed | Permanently allocates stock |
| Deduct | Order shipped | Removes from inventory |
| Restore | Order cancelled/refunded | Returns committed stock |
Low Stock Alerts
When stock_quantity <= low_stock_threshold:
- Admin notification sent
- Product marked for reorder
- Optional: Auto-hide if stock = 0
Stock Reservation Rules
- Cart reservation: 30 minutes
- Checkout reservation: 15 minutes
- Order confirmation: Permanent until shipped/cancelled
- Failed payment: Stock released after 1 hour
Cart System
Guest vs User Carts
Guest Carts
- Identified by
session_id(UUID stored in cookie) - Expire after 7 days of inactivity
- Referral attribution stored on cart
User Carts
- Linked to
user_id - Persist indefinitely
- Auto-restore on login
Cart Merge on Login
When a guest with items logs in:
- Find existing user cart (if any)
- For each guest cart item:
- If product exists in user cart: Update quantity
- If product not in user cart: Add item
- Recalculate totals
- Delete guest cart
- Preserve referral attribution (most recent wins)
Cart Expiry
Checkout Process
Multi-Step Checkout
Step 1: Cart Validation
- Verify all items still in stock
- Check product availability (not discontinued)
- Recalculate prices (may have changed)
- Apply any automatic discounts
Step 2: Shipping Selection
- User selects/adds shipping address
- Available shipping methods calculated
- Shipping cost displayed
- Estimated delivery dates shown
Step 3: Payment
- Select payment method
- Enter payment details
- Apply promo codes
- Calculate final total with taxes
Step 4: Confirmation
- Order summary review
- Terms acceptance
- Final order placement
- Payment processing
Order State Machine
State Diagram
Valid Transitions
| From | To | Trigger | Conditions |
|---|---|---|---|
| PENDING | CONFIRMED | payment_success | Payment completed |
| PENDING | CANCELLED | cancel | Payment failed or user cancels |
| CONFIRMED | PROCESSING | start_processing | Fulfillment begins |
| CONFIRMED | CANCELLED | cancel | Before shipping only |
| PROCESSING | SHIPPED | ship | Tracking number assigned |
| PROCESSING | CANCELLED | cancel | Stock unavailable |
| SHIPPED | DELIVERED | deliver | Carrier confirmation |
| DELIVERED | REFUNDED | refund | Within 14-day window |
Order Timestamps
| Status | Timestamp Field |
|---|---|
| CONFIRMED | confirmed_at |
| SHIPPED | shipped_at |
| DELIVERED | delivered_at |
| CANCELLED | cancelled_at |
| REFUNDED | refunded_at |
Payment Integration
Supported Providers
| Provider | Markets | Methods |
|---|---|---|
| Stripe | International | Card, Apple Pay, Google Pay |
| YooKassa | Russia/CIS | Card, SberPay, YooMoney |
Payment Flow
Webhook Handling
Idempotency
- Each payment has unique
idempotency_key - Prevents duplicate charges on retry
- Key format:
order_{orderId}_{timestamp}
Payment Statuses
| Status | Description |
|---|---|
| PENDING | Payment initiated |
| PROCESSING | Being processed by provider |
| COMPLETED | Successfully charged |
| FAILED | Payment failed |
| REFUNDED | Fully refunded |
Shipping Integration
Supported Carriers
| Carrier | Coverage | Features |
|---|---|---|
| CDEK | Russia, CIS | Door-to-door, pickup points |
| DHL | International | Express, standard |
Shipping Flow
Shipment Statuses
| Status | Description |
|---|---|
| PREPARING | Order being packed |
| SHIPPED | Handed to carrier |
| IN_TRANSIT | With carrier, moving |
| OUT_FOR_DELIVERY | Last mile |
| DELIVERED | Successfully delivered |
| RETURNED | Returned to sender |
Tracking Events
Stored as JSONB array:
[
{
"timestamp": "2024-01-15T10:30:00Z",
"status": "SHIPPED",
"location": "Moscow, Russia",
"description": "Shipment picked up"
},
{
"timestamp": "2024-01-16T14:20:00Z",
"status": "IN_TRANSIT",
"location": "Novosibirsk, Russia",
"description": "In transit to destination"
}
]Returns and Refunds
Refund Window
- Standard: 14 days from delivery
- Extended (VIP): 30 days
- No refund: Digital products, opened supplements
Refund Flow
Partial Refunds
- Supported for multi-item orders
- Individual items can be refunded
- Shipping cost refund optional
- Pro-rata discount adjustment
Refund Impact on MLM
When an order is refunded:
- Related commissions are reversed
- If commissions were paid, clawback created
- Career points deducted
- Partner balances adjusted
Events Published
| Event | Trigger | Payload |
|---|---|---|
| ProductCreated | New product added | productId, sku, categoryId |
| ProductUpdated | Product modified | productId, changedFields |
| ProductStatusChanged | Status transition | productId, fromStatus, toStatus |
| StockLevelChanged | Inventory change | productId, previousQty, newQty |
| LowStockAlert | Below threshold | productId, currentQty, threshold |
| CartCreated | New cart | cartId, userId/sessionId |
| CartItemAdded | Item added to cart | cartId, productId, quantity |
| CartItemRemoved | Item removed from cart | cartId, productId |
| CartAbandoned | Cart expired | cartId, userId, items |
| OrderCreated | Order placed | orderId, userId, total |
| OrderConfirmed | Payment successful | orderId, paymentId |
| OrderStatusChanged | Status transition | orderId, fromStatus, toStatus |
| OrderCancelled | Order cancelled | orderId, reason |
| OrderShipped | Shipment created | orderId, trackingNumber |
| OrderDelivered | Delivery confirmed | orderId, deliveredAt |
| PaymentReceived | Payment successful | paymentId, orderId, amount |
| PaymentFailed | Payment failed | paymentId, orderId, reason |
| RefundInitiated | Refund started | orderId, amount, reason |
| RefundCompleted | Refund processed | orderId, refundId, amount |
| ShipmentUpdated | Tracking update | shipmentId, status, location |
Events Consumed
| Event | Source | Handler |
|---|---|---|
| UserRegistered | Core | Merge guest cart if exists |
| UserLoggedIn | Core | Restore/merge user cart |
| ReferralAttributed | MLM | Store attribution on cart |
Business Rules and Invariants
Product Rules
- SKU must be unique across all products
- Sale price cannot exceed base price
- Stock quantity cannot be negative
- Discontinued products cannot be added to cart
- Products with 0 stock shown as "Out of Stock"
Cart Rules
- Maximum 50 unique items per cart
- Maximum quantity per item: 99
- Cart total cannot exceed platform limits
- Guest carts expire after 7 days
- Referral attribution preserved through checkout
Order Rules
- Order number format: IWM-{YYYYMMDD}-
- Status transitions must follow state machine
- Cannot cancel after shipping
- Refund window: 14 days from delivery
- Minimum order value may apply
Payment Rules
- Single successful payment per order
- Idempotency key prevents duplicate charges
- Webhook signature must be verified
- Failed payments retry up to 3 times
Inventory Rules
- Stock reserved on cart add
- Reserved stock released on cart expiry
- Stock committed on order confirmation
- Stock restored on order cancellation
Integration Points
Provides to Other Modules
| Interface | Consumers | Purpose |
|---|---|---|
| IOrderService | MLM | Get order details for commission |
| IProductService | MLM | Get product career points value |
Consumes from Other Modules
| Interface | Provider | Purpose |
|---|---|---|
| IUserLookupService | Core | Get customer details |
| IPartnerLookupService | MLM | Validate referral attribution |
| IAttributionService | MLM | Get referral partner for order |