Inventory Management
Ezvento provides a complete inventory management system for retail, wholesale, and restaurant businesses. Track products with variants, serial numbers, batch numbers, and expiry dates. Manage stock across multiple stores, locations, and warehouses with full audit trails.
Product Catalog
The Product model is the foundation of the inventory system. Each product has a unique SKU within the tenant, an optional barcode, GST rate, pricing (MRP, cost price, selling price), and configurable tracking flags for variants, serial numbers, batch numbers, and expiry dates.
ProductType Enum
STANDARD products have a single SKU with direct inventory tracking.VARIANT products delegate inventory to ProductVariant children.BOM (Bill of Materials) products are restaurant combos that decompose into ingredient products at the time of KOT creation.
Categories
Categories in Ezvento are self-referential, supporting unlimited hierarchy depth. Each category can have an HSN code and a default GST rate that is auto-applied to new products created within that category. This simplifies catalog setup for businesses with large product ranges.
Example Hierarchy
Product Variants
When a product has hasVariants: true, inventory and pricing are tracked at the ProductVariant level rather than the parent product. Each variant has its own SKU, barcode, MRP, cost price, and selling price. The attributesfield stores flexible key-value pairs (e.g., color, size, material) as JSON.
Inventory Implications
For variant products, InventoryStock records are keyed byproductId + variantId. When billing, the cashier scans the variant barcode or selects the variant from the product detail page. The parent product's hasVariantsflag prevents direct inventory changes at the parent level, ensuring all stock movements go through the variant records.
Serial Numbers
For high-value items like electronics and appliances, each unit can have a unique serial number. When hasSerialNumber: true is set on the product, the system requires serial number input at the time of sale. Serial numbers are stored as an array onSalesInvoiceItem.serialNumbers and returned during the return process for full traceability.
Batch / Expiry Tracking
Products that require batch or expiry tracking (pharmaceuticals, food, cosmetics) havehasBatchNumber and hasExpiry flags. At the time of purchase (from vendor) or stock receipt, batch numbers and expiry dates are captured. At the time of sale, the cashier selects the batch or the system auto-selects FIFO (First-In-First-Out) batch.
FIFO / FEFO Selection
By default, the system uses FIFO (First-In-First-Out) for batch selection during sales. For expiry-sensitive products, FEFO (First-Expired-First-Out) can be enabled at the tenant level to automatically pick the batch closest to expiry, reducing wastage.
Inventory Stock
InventoryStock is the central model for tracking available quantity at every store and location. It uses a compound unique key of[productId, variantId, storeId, locationId] to ensure precise tracking. The quantity field represents available stock, while reservedQtytracks stock held for pending orders or transfers.
Compound Key
The unique constraint @@unique([productId, variantId, storeId, locationId])ensures that each product/variant combination has exactly one stock record per store location. For products without variants, variantIdis empty string. This design allows atomic updates with Prisma's upsert without race conditions.
Stock Movements
Every change to inventory quantity is recorded as a StockMovement row. This forms a complete audit trail of where stock came from and where it went. ThemovementType enum covers all possible stock flows in the system.
StockMovementType Enum
Stock Adjustments
When physical stock differs from system stock, an inventory user creates a StockAdjustmentrecord. The adjustment captures the reason, quantity before, and quantity after. A correspondingStockMovement is automatically created with type ADJUSTMENT_INor ADJUSTMENT_OUT.
AdjustmentReason Enum
Stock Transfers
Stock can be transferred between stores, locations, or from warehouse to store using theStockTransfer model. The transfer workflow supports partial receipt, allowing the receiving store to confirm only the quantity actually received (e.g., if some items were damaged in transit).
StockTransferItem
Each line in a transfer is a StockTransferItem with productId,variantId, quantity (sent), andreceivedQuantity (confirmed by receiver). If receivedQuantityis less than quantity, the difference is flagged as a shortage for investigation.
Transfer Lifecycle
Low Stock Alerts
Each product has a reorderLevel field. When the available quantity (quantity - reservedQty) falls below this threshold, the system flags the product as low stock. Alerts are configurable at the tenant level via TenantSettings.lowStockAlertDaysand lowStockEmailAlerts. The dashboard shows a "Low Stock" widget, and inventory staff receive email notifications if enabled.
Stock Audit
Stock audits reconcile physical inventory counts against system records. An auditor (or store manager) performs a physical count, enters the actual quantities, and the system computes variances. Large variances trigger STOCK_AUDIT permission checks and are logged inActivityLog with severity WARN or CRITICAL.
Damage Recording
When stock is damaged (broken packaging, expired goods, physical damage), it is removed from available inventory via a StockAdjustment with reason DAMAGE. This requires the STOCK_DAMAGE_RECORD permission. The damaged quantity is recorded in StockMovement with type DAMAGE and creates a permanent audit trail for insurance or vendor claim purposes.
Purchase Orders
Purchase orders are created to request stock from vendors. The PurchaseOrdermodel tracks the order lifecycle from draft to sent to received. Each order has line items with expected quantities, unit prices, and GST rates.
PurchaseOrderItem
Each line specifies the product, expected quantity, unit price, and GST rate. When goods are received, receivedQty is updated. Partial receipts are supported — a PO can be received in multiple batches. If the received quantity differs from ordered quantity, the difference is flagged for follow-up with the vendor.
Purchase Invoices
A PurchaseInvoice records the actual vendor bill for goods received. It can be created from a purchase order or independently. When a purchase invoice is approved, stock is added to inventory and a StockMovement of type PURCHASEis created.
Purchase Permissions
PURCHASE_CREATE allows creating new purchase invoices.PURCHASE_EDIT allows modifying draft invoices.PURCHASE_APPROVE approves the invoice for payment and stock entry.PURCHASE_RECEIVE marks goods as received and updates inventory.
Vendors
The Vendor model stores supplier information including GSTIN, PAN, bank details, and credit terms. Vendors are tenant-scoped and linked to purchase orders and purchase invoices. The creditPeriodDays field defines the payment window for credit-based purchases.
Warehouse Management
Warehouses are organization-level inventory locations distinct from store locations. A warehouse has multiple Locationchildren (e.g., "Cold Storage A", "Bulk Rack 1"). Stock transfers between warehouse and stores are handled via the standard StockTransferworkflow.
Warehouse Permissions
Barcode Labels
Ezvento supports printing barcode labels for products and variants. The BarcodeLabelcomponent generates a printable label with the product name, SKU, barcode (Code 128 or EAN-13), MRP, and selling price. The PrintLabelSheet component arranges multiple labels in a grid layout for A4 sheet printing or continuous roll printing.