@company-manager/docs

Supplier Ordering

Procurement workflow, vendor management, and supplier order diagrams

Supplier Ordering

This page covers the procurement process including supplier order creation, automated ordering, and vendor management.

Supplier Order State Machine

stateDiagram-v2
    [*] --> DRAFT: Create Order

    DRAFT --> SENT: Send to Vendor
    DRAFT --> CANCELLED: Cancel

    SENT --> CONFIRMED: Vendor Confirms
    SENT --> DRAFT: Vendor Requests Changes
    SENT --> CANCELLED: Vendor Rejects

    CONFIRMED --> PARTIAL_RECEIVED: Partial Delivery
    CONFIRMED --> RECEIVED: Full Delivery
    CONFIRMED --> CANCELLED: Cancel Before Delivery

    PARTIAL_RECEIVED --> RECEIVED: Remaining Delivered
    PARTIAL_RECEIVED --> CLOSED_PARTIAL: Close with Partial

    RECEIVED --> CLOSED: Close Order
    CLOSED_PARTIAL --> CLOSED: Reconcile

    CLOSED --> [*]
    CANCELLED --> [*]

    note right of SENT
        Email sent to vendor
        with order details
    end note

    note right of PARTIAL_RECEIVED
        Track partial deliveries
        and discrepancies
    end note

Supplier Order Workflow

flowchart TD
    subgraph "Order Calculation"
        TRIGGER[Trigger: Low Stock / Schedule] --> ANALYZE[Analyze Requirements]
        ANALYZE --> FORECAST[Calculate Forecast]
        FORECAST --> CURRENT[Check Current Stock]
        CURRENT --> ORDERS[Check Pending Orders]
        ORDERS --> CALCULATE[Calculate Order Quantity]
    end

    subgraph "Order Creation"
        CALCULATE --> GROUP{Group by Vendor?}
        GROUP -->|Yes| COMBINE[Combine Items per Vendor]
        GROUP -->|No| SINGLE[Single Item Order]

        COMBINE --> CREATE[Create Supplier Order]
        SINGLE --> CREATE
        CREATE --> ITEMS[Create Order Items]
    end

    subgraph "Approval & Sending"
        ITEMS --> REVIEW{Auto-Send?}
        REVIEW -->|Yes| SCHEDULE[Schedule Send]
        REVIEW -->|No| MANUAL[Manual Review]

        MANUAL --> APPROVE{Approved?}
        APPROVE -->|Yes| SCHEDULE
        APPROVE -->|No| EDIT[Edit Order]
        EDIT --> MANUAL

        SCHEDULE --> SEND[Send to Vendor]
    end

    SEND --> AWAIT[Await Confirmation]

    style SEND fill:#e8f5e9

Quantity Calculation Logic

flowchart TD
    START[Calculate Order Quantity] --> GET_ORDERS[Get Orders in Period]
    GET_ORDERS --> SUM[Sum Required Quantities]

    SUM --> MARGIN[Add Safety Margin %]
    MARGIN --> SUGGESTED[Suggested Quantity]

    SUGGESTED --> STOCK[Subtract Current Stock]
    STOCK --> PENDING[Subtract Pending Deliveries]

    PENDING --> NEEDED{Quantity Needed?}
    NEEDED -->|> 0| PACKAGE[Round to Package Size]
    NEEDED -->|<= 0| SKIP[Skip - Sufficient Stock]

    PACKAGE --> FINAL[Final Order Quantity]

    subgraph "Example"
        EX_ORD[Orders: 100 units]
        EX_MARGIN[+ 10% margin = 110]
        EX_STOCK[- Current: 30 = 80]
        EX_PEND[- Pending: 20 = 60]
        EX_PKG[Package size: 24]
        EX_FINAL[Order: 3 packages = 72 units]
    end

    style FINAL fill:#e8f5e9
    style SKIP fill:#fff3e0

Automated Ordering Sequence

sequenceDiagram
    participant Cron as Scheduler
    participant Service as Supplier Order Service
    participant DB as Database
    participant Calc as Calculation Engine
    participant Email as Email Service
    participant Vendor

    Cron->>Service: triggerAutoOrders()

    Service->>DB: Get vendors with autoSend=true
    DB-->>Service: Vendors list

    loop For each vendor
        Service->>DB: Get vendor schedule
        DB-->>Service: Schedule config

        Service->>Service: Check if today is order day

        alt Is Order Day
            Service->>DB: Get products for vendor
            DB-->>Service: Products list

            Service->>Calc: calculateOrderQuantities(products)
            Calc->>DB: Get order forecasts
            Calc->>DB: Get current stock
            Calc->>DB: Get pending orders
            Calc-->>Service: Calculated quantities

            Service->>Service: Filter items needing order

            alt Has Items to Order
                Service->>DB: Create SupplierOrder
                Service->>DB: Create SupplierOrderItems
                DB-->>Service: Order created

                Service->>Email: sendOrderEmail(order, vendor)
                Email->>Vendor: Order email with PDF
                Vendor-->>Email: Received

                Service->>DB: Update emailSentAt
            end
        end
    end

    Service-->>Cron: Auto-orders complete

Vendor Configuration

erDiagram
    VENDOR ||--o{ SUPPLIER_ORDER : receives
    VENDOR ||--o{ PRODUCT : supplies
    VENDOR }o--|| EMAIL_TEMPLATE : uses

    VENDOR {
        string id PK
        string tenantId FK
        string name
        string email
        string[] sendEmail
        json sendSchedules
        boolean autoSend
        boolean groupedOrder
        float defaultOveragePercent
        json specificOveragePercent
        int deliveryDays
        string defaultPackagingType
        json vendorLinks
    }

    SUPPLIER_ORDER {
        string id PK
        string vendorId FK
        string tenantId FK
        enum status
        timestamp scheduledSendDate
        timestamp emailSentAt
        string emailSentBy
        timestamp expectedDeliveryDate
        timestamp actualDeliveryDate
        enum supplierDeliveryStatus
        json deliveryDiscrepancies
    }

    SUPPLIER_ORDER_ITEM {
        string id PK
        string orderId FK
        string productId FK
        int quantity
        int currentStock
        int quantityInOrders
        int quantityAdded
        int packageSize
        float marginPercent
    }

Vendor Schedule Configuration

flowchart TD
    subgraph "Schedule Types"
        DAILY[Daily Orders]
        WEEKLY[Weekly Orders]
        BIWEEKLY[Bi-Weekly Orders]
        MONTHLY[Monthly Orders]
    end

    subgraph "Weekly Example"
        CONFIG[sendSchedules: &#91;{day: 1, time: '08:00'}, {day: 4, time: '08:00'}&#93;]
        CONFIG --> MON[Monday 8:00 AM]
        CONFIG --> THU[Thursday 8:00 AM]
    end

    subgraph "Lead Time"
        SEND[Order Sent] --> LEAD[+ deliveryDays]
        LEAD --> EXPECTED[Expected Delivery]
    end

Receiving Delivery Flow

flowchart TD
    ARRIVE[Delivery Arrives] --> FIND[Find Supplier Order]
    FIND --> VERIFY[Verify Items]

    VERIFY --> MATCH{Quantities Match?}

    MATCH -->|Yes| FULL[Mark Full Delivery]
    MATCH -->|No| DISCREPANCY[Record Discrepancy]

    DISCREPANCY --> TYPE{Discrepancy Type}
    TYPE -->|Short| SHORT[Mark as Short]
    TYPE -->|Over| OVER[Mark as Over]
    TYPE -->|Damaged| DAMAGED[Mark as Damaged]
    TYPE -->|Wrong Item| WRONG[Mark as Wrong Item]

    SHORT --> PARTIAL[Mark Partial Received]
    OVER --> FULL
    DAMAGED --> PARTIAL
    WRONG --> PARTIAL

    FULL --> STOCK[Update Stock Levels]
    PARTIAL --> STOCK

    STOCK --> QC{Quality Check?}
    QC -->|Pass| APPROVE[Approve for Sale]
    QC -->|Fail| QUARANTINE[Quarantine Items]

    APPROVE --> COMPLETE[Complete Receiving]
    QUARANTINE --> CONTACT[Contact Vendor]

    style COMPLETE fill:#e8f5e9

Receiving Sequence

sequenceDiagram
    participant Staff
    participant UI as Receiving UI
    participant API as TRPC Router
    participant Service as Supplier Order Service
    participant Inv as Inventory Service
    participant DB as Database

    Staff->>UI: Start receiving
    UI->>API: startReceiving(orderId)
    API->>Service: beginReceiving(orderId)
    Service->>DB: Update status (RECEIVING)

    loop For each item
        Staff->>UI: Enter received quantity
        UI->>API: recordItemReceived(itemId, qty, notes)
        API->>Service: recordReceived(itemId, qty, notes)

        Service->>Service: Compare to ordered qty

        alt Quantity matches
            Service->>DB: Update item (received)
        else Discrepancy
            Service->>DB: Log discrepancy
            Service->>DB: Update item (partial/discrepancy)
        end

        Service->>Inv: incrementStock(productId, qty)
        Inv->>DB: Create StockAction (INCREMENT)
        Inv->>DB: Update stock levels
    end

    Staff->>UI: Complete receiving
    UI->>API: completeReceiving(orderId)
    API->>Service: finalizeReceiving(orderId)

    Service->>Service: Check all items received

    alt All received
        Service->>DB: Update order (RECEIVED)
    else Partial
        Service->>DB: Update order (PARTIAL_RECEIVED)
    end

    Service-->>API: Receiving complete
    API-->>UI: Show summary

Vendor Performance Tracking

flowchart LR
    subgraph "Metrics Collection"
        ORDERS[Orders Placed]
        DELIVERIES[Deliveries Received]
        TIMES[Delivery Times]
        QUALITY[Quality Issues]
    end

    subgraph "KPIs"
        OTD[On-Time Delivery %]
        FILL[Fill Rate %]
        DEFECT[Defect Rate %]
        LEAD[Avg Lead Time]
    end

    subgraph "Scoring"
        SCORE[Vendor Score]
        TIER[Performance Tier]
    end

    ORDERS --> OTD
    DELIVERIES --> OTD
    DELIVERIES --> FILL
    TIMES --> LEAD
    QUALITY --> DEFECT

    OTD --> SCORE
    FILL --> SCORE
    DEFECT --> SCORE
    LEAD --> SCORE

    SCORE --> TIER

Performance Score Calculation

flowchart TD
    START[Calculate Vendor Score] --> OTD[On-Time Delivery Score]
    START --> FILL[Fill Rate Score]
    START --> QUALITY[Quality Score]
    START --> RESPONSE[Response Time Score]

    OTD --> WEIGHT1[Weight: 30%]
    FILL --> WEIGHT2[Weight: 25%]
    QUALITY --> WEIGHT3[Weight: 25%]
    RESPONSE --> WEIGHT4[Weight: 20%]

    WEIGHT1 --> TOTAL[Total Score]
    WEIGHT2 --> TOTAL
    WEIGHT3 --> TOTAL
    WEIGHT4 --> TOTAL

    TOTAL --> TIER{Score Range}
    TIER -->|90-100| GOLD[Gold Tier]
    TIER -->|75-89| SILVER[Silver Tier]
    TIER -->|60-74| BRONZE[Bronze Tier]
    TIER -->|< 60| REVIEW[Under Review]

    style GOLD fill:#ffd700
    style SILVER fill:#c0c0c0
    style BRONZE fill:#cd7f32
    style REVIEW fill:#ffebee

Purchase Order PDF Generation

sequenceDiagram
    participant Service as Order Service
    participant Template as Template Engine
    participant PDF as PDF Generator
    participant Storage as File Storage
    participant Email as Email Service

    Service->>Service: Prepare order data
    Service->>Template: Render order template
    Note over Template: Includes: vendor info, items,<br/>quantities, prices, terms

    Template-->>Service: HTML content

    Service->>PDF: generatePDF(html)
    PDF-->>Service: PDF buffer

    Service->>Storage: uploadFile(pdf, path)
    Storage-->>Service: File URL

    Service->>Email: sendEmail(vendor, attachment)
    Email-->>Service: Sent

    Service->>Service: Update order with PDF URL

Supplier Order Analytics

erDiagram
    SUPPLIER_ORDER_ANALYTICS ||--|| VENDOR : tracks

    SUPPLIER_ORDER_ANALYTICS {
        string id PK
        string vendorId FK
        date periodStart
        date periodEnd
        int totalOrders
        decimal totalValue
        int onTimeDeliveries
        int lateDeliveries
        decimal avgLeadTime
        decimal fillRate
        decimal defectRate
        decimal score
    }

Multi-Vendor Order Optimization

flowchart TD
    PRODUCTS[Products Needing Order] --> ANALYZE[Analyze Vendor Options]

    ANALYZE --> FACTORS{Consider Factors}
    FACTORS --> PRICE[Price]
    FACTORS --> LEAD[Lead Time]
    FACTORS --> MOQ[Minimum Order Qty]
    FACTORS --> SCORE[Vendor Score]
    FACTORS --> STOCK[Vendor Stock]

    PRICE --> OPTIMIZE[Optimization Algorithm]
    LEAD --> OPTIMIZE
    MOQ --> OPTIMIZE
    SCORE --> OPTIMIZE
    STOCK --> OPTIMIZE

    OPTIMIZE --> SPLIT{Split Order?}
    SPLIT -->|Yes| MULTIPLE[Multiple Vendor Orders]
    SPLIT -->|No| SINGLE[Single Vendor Order]

    MULTIPLE --> CREATE[Create Orders]
    SINGLE --> CREATE