Workflow

Supplier Procurement

Detect low stock, automatically generate purchase orders, receive goods with batch tracking, and update inventory. Connects reorder rules, suppliers, batches, and stock.

1
Low Stock Alert
2
Select Supplier
3
Create PO
4
Submit & Confirm PO
5
Receive Goods
6
Register Batches
7
Register Serials
8
Update Inventory
9
Audit & Report

Complete Procurement Workflow

Step 1: Detect low stock via reorder alerts

import { createServices } from "commercio";

const services = createServices();

// Check all active reorder rules against current stock
const alerts = await services.reorderService.checkReorderAlerts();

console.log(`Found ${alerts.length} products below reorder point:\n`);
for (const alert of alerts) {
  console.log(`  Product: ${alert.rule.productId}`);
  console.log(`  Warehouse: ${alert.rule.warehouseId}`);
  console.log(`  Current stock: ${alert.currentStock}`);
  console.log(`  Reorder point: ${alert.rule.reorderPoint}`);
  console.log(`  Suggested order qty: ${alert.suggestedQuantity}`);
  console.log(`  Preferred supplier: ${alert.rule.preferredSupplierId ?? "none"}\n`);
}

Step 2: Create and submit a purchase order

// Get or create a supplier
const supplier = await services.supplierService.createSupplier("Lenovo Direct", {
  contactName: "Sales Team",
  email: "b2b@lenovo.com",
  phone: "+49 711 123 4567",
  street: "Lenovo Allee 1",
  city: "Stuttgart",
  postalCode: "70173",
  country: "Germany",
});

// Create purchase order based on alerts
const poItems = alerts.map(alert => ({
  productId: alert.rule.productId,
  quantity: alert.suggestedQuantity,
  unitCost: 85000, // 850.00 EUR wholesale cost
}));

const purchaseOrder = await services.supplierService.createPurchaseOrder(
  supplier.id, poItems,
  {
    expectedDelivery: new Date("2026-05-01"),
    notes: "Auto-generated from reorder alerts",
  }
);

console.log(`PO ${purchaseOrder.id} created (status: ${purchaseOrder.status})`); // DRAFT

// Submit the PO to the supplier
const submitted = await services.supplierService.submitPurchaseOrder(purchaseOrder.id);
console.log(`PO submitted (status: ${submitted.status})`); // SUBMITTED

// Supplier confirms
const confirmed = await services.supplierService.confirmPurchaseOrder(purchaseOrder.id);
console.log(`PO confirmed (status: ${confirmed.status})`); // CONFIRMED

// Audit the PO creation
await services.auditLogService.log("PurchaseOrder", purchaseOrder.id, "CREATE", {
  actor: "procurement-bot",
  newValues: {
    supplierId: supplier.id,
    itemCount: poItems.length,
    totalCost: poItems.reduce((s, i) => s + i.quantity * i.unitCost, 0),
  },
});

Step 3: Receive goods, register batches & serial numbers

// Supplier ships the PO
await services.supplierService.shipPurchaseOrder(purchaseOrder.id);

// ── Goods arrive at warehouse ──────────────────────────

// Mark PO as received
const received = await services.supplierService.receivePurchaseOrder(purchaseOrder.id);
console.log(`PO received (status: ${received.status})`); // RECEIVED

// Register incoming batch
const batch = await services.batchTrackingService.createBatch(
  alerts[0].rule.productId,
  `BATCH-LENOVO-${Date.now()}`,
  alerts[0].rule.warehouseId,
  alerts[0].suggestedQuantity,
  {
    manufacturingDate: new Date("2026-03-15"),
    expiryDate: new Date("2031-03-15"), // 5 year warranty
    supplierId: supplier.id,
  }
);
console.log(`Batch ${batch.batchNumber} registered (${batch.quantity} units)`);

// Register individual serial numbers
const serialNumbers = Array.from(
  { length: alerts[0].suggestedQuantity },
  (_, i) => `SN-X1C-${batch.batchNumber}-${String(i + 1).padStart(4, "0")}`
);

const serials = await services.batchTrackingService.registerSerialNumbers(
  alerts[0].rule.productId,
  serialNumbers,
  alerts[0].rule.warehouseId,
  { batchId: batch.id }
);
console.log(`${serials.length} serial numbers registered`);

Step 4: Update inventory & verify

// Record the receipt as an inventory transaction
for (const alert of alerts) {
  await services.inventoryTransactionService.createTransaction(
    alert.rule.productId,
    alert.rule.warehouseId,
    alert.suggestedQuantity,
    "RECEIPT",
    purchaseOrder.id
  );
}

// Verify stock levels are restored
for (const alert of alerts) {
  const stock = await services.stockService.getStock(
    alert.rule.productId, alert.rule.warehouseId
  );
  console.log(`Product ${alert.rule.productId}: ${stock?.quantity} units in stock`);
}

// Verify reorder alerts are cleared
const remainingAlerts = await services.reorderService.checkReorderAlerts();
console.log(`Remaining alerts: ${remainingAlerts.length}`); // 0

// ── Reporting ──────────────────────────────────────────
const inventory = await services.reportingService.getInventoryReport();
inventory.forEach(item => {
  console.log(`${item.productName}: ${item.totalStock} total`);
  item.warehouseBreakdown.forEach(w => {
    console.log(`  Warehouse ${w.warehouseId}: ${w.quantity}`);
  });
});

// Check near-expiry batches
const expiringSoon = await services.batchTrackingService.getNearExpiryBatches(365);
console.log(`\n${expiringSoon.length} batches expiring within 1 year`);