Skip to main content

Overview

Items represent the master catalog in SushiGo. Each Item can have multiple ItemVariants that represent different packaging sizes, presentations, or configurations.
Example: Item “Rice” (INSUMO) might have variants: “Rice 1kg Bag”, “Rice 5kg Bag”, “Rice 20kg Sack” — each with different codes, barcodes, and pricing.

Item Structure

Item (Master)

The parent entity that groups related variants.
sku
string
required
Unique SKU code (max 100 chars, auto-uppercase)Example: INS-001, PROD-CALIFORNIA, ACT-COOKER
name
string
required
Item name (max 255 chars)Example: Arroz Sushi Premium, California Roll, Rice Cooker
description
text
Detailed description (optional)
type
enum
required
Item type: INSUMO, PRODUCTO, or ACTIVO
is_stocked
boolean
default:"true"
Whether to track inventory for this item
is_perishable
boolean
default:"false"
Whether item has expiration dates (enables lot tracking)
is_active
boolean
default:"true"
Active status (inactive items hidden from selection)

ItemVariant (SKU Level)

Represents a specific SKU with its own barcode, pricing, and stock tracking.
item_id
integer
required
Parent item ID
uom_id
integer
required
Base unit of measure ID (e.g., kg, unit, liter)
code
string
required
Unique variant code (max 100 chars, auto-uppercase)Example: ARR-KG, ARR-5KG, ROLL-CAL-8PC
barcode
string
Product barcode (EAN, UPC, Code128, etc.)Auto-cleaned: removes spaces and special chars
name
string
required
Variant name (max 255 chars)Example: Arroz Premium 1kg, California Roll 8 piezas
description
text
Variant-specific description
track_lot
boolean
default:"false"
Enable lot number tracking (for batches with expiration)
track_serial
boolean
default:"false"
Enable serial number tracking (for unique assets)
sale_price
decimal
Default sale price (optional)
min_stock
decimal
Minimum stock level (triggers low stock alerts)
max_stock
decimal
Maximum stock level (must be >= min_stock)
is_active
boolean
default:"true"
Active status

Cost Tracking Fields (Auto-Updated)

last_unit_cost
decimal
Most recent purchase cost per base unit
avg_unit_cost
decimal
Weighted average cost per base unit (updated on receipts)

API Endpoints

Create Item

POST /api/v1/items
Authorization: Bearer {token}
Content-Type: application/json

{
  "sku": "INS-ARROZ",
  "name": "Arroz Sushi Premium",
  "description": "Arroz japonés premium para sushi",
  "type": "INSUMO",
  "is_stocked": true,
  "is_perishable": false,
  "is_active": true
}
{
  "status": 201,
  "data": {
    "id": 1,
    "sku": "INS-ARROZ",
    "name": "Arroz Sushi Premium",
    "description": "Arroz japonés premium para sushi",
    "type": "INSUMO",
    "is_stocked": true,
    "is_perishable": false,
    "is_active": true,
    "created_at": "2026-03-06T10:30:00Z",
    "updated_at": "2026-03-06T10:30:00Z"
  }
}

Create Item Variant

POST /api/v1/item-variants
Authorization: Bearer {token}
Content-Type: application/json

{
  "item_id": 1,
  "uom_id": 3,
  "code": "ARR-KG",
  "barcode": "7501234567890",
  "name": "Arroz Premium 1kg",
  "description": "Presentación de 1 kilogramo",
  "track_lot": false,
  "track_serial": false,
  "sale_price": 35.00,
  "min_stock": 10.00,
  "max_stock": 100.00,
  "is_active": true
}
{
  "status": 201,
  "data": {
    "id": 1,
    "item_id": 1,
    "uom_id": 3,
    "code": "ARR-KG",
    "barcode": "7501234567890",
    "name": "Arroz Premium 1kg",
    "description": "Presentación de 1 kilogramo",
    "track_lot": false,
    "track_serial": false,
    "last_unit_cost": 0.0000,
    "avg_unit_cost": 0.0000,
    "sale_price": 35.0000,
    "min_stock": 10.0000,
    "max_stock": 100.0000,
    "is_active": true,
    "uom": {
      "id": 3,
      "code": "KG",
      "name": "Kilogram",
      "symbol": "kg"
    },
    "item": {
      "id": 1,
      "sku": "INS-ARROZ",
      "name": "Arroz Sushi Premium",
      "type": "INSUMO"
    },
    "created_at": "2026-03-06T10:35:00Z",
    "updated_at": "2026-03-06T10:35:00Z"
  }
}

List Items

GET /api/v1/items?type=INSUMO&is_active=true&search=arroz&per_page=15
Authorization: Bearer {token}
type
enum
Filter by type: INSUMO, PRODUCTO, or ACTIVO
is_stocked
boolean
Filter stocked items
is_perishable
boolean
Filter perishable items
is_active
boolean
Filter active/inactive items
Search by SKU or name (case-insensitive)
per_page
integer
default:"15"
Results per page
{
  "status": 200,
  "data": [
    {
      "id": 1,
      "sku": "INS-ARROZ",
      "name": "Arroz Sushi Premium",
      "type": "INSUMO",
      "is_stocked": true,
      "is_perishable": false,
      "is_active": true
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 15,
    "total": 1,
    "last_page": 1
  }
}

Show Item

GET /api/v1/items/{id}
Authorization: Bearer {token}
Returns full item details including all variants.

Update Item

PUT /api/v1/items/{id}
Authorization: Bearer {token}
Content-Type: application/json

{
  "name": "Arroz Sushi Premium Plus",
  "description": "Nueva presentación mejorada",
  "is_active": true
}
Cannot change sku or type after creation

Delete Item

DELETE /api/v1/items/{id}
Authorization: Bearer {token}
Soft deletes the item and all its variants.
Cannot delete items with active stock or movement history

Real-World Examples

Example 1: INSUMO with Multiple Variants

Item: Salmon (INSUMO)
{
  "sku": "INS-SALMON",
  "name": "Salmon Atlantic",
  "type": "INSUMO",
  "is_stocked": true,
  "is_perishable": true
}
Variants:
  • SAL-KG - Salmon Atlantic 1kg (base UOM: kg)
  • SAL-200G - Salmon Atlantic 200g (conversion: 1kg = 5 × 200g)
  • SAL-SAKU - Salmon Saku Block 250g (conversion: 1kg = 4 × 250g)

Example 2: PRODUCTO with Single Variant

Item: California Roll (PRODUCTO)
{
  "sku": "PROD-CALIFORNIA",
  "name": "California Roll",
  "type": "PRODUCTO",
  "is_stocked": true,
  "is_perishable": true
}
Variant:
  • ROLL-CAL-8PC - California Roll 8 piezas (base UOM: unit, sale_price: 120.00)
Products typically have 1:1 UOM (base unit only). Multi-unit conversions are for INSUMOs.

Example 3: ACTIVO with Serial Tracking

Item: Rice Cooker (ACTIVO)
{
  "sku": "ACT-COOKER",
  "name": "Rice Cooker Commercial",
  "type": "ACTIVO",
  "is_stocked": true,
  "is_perishable": false
}
Variant:
  • COOKER-ZOJIRUSHI-10CUP - Zojirushi 10 Cup (track_serial: true)

Validation Rules

Item Creation

  • sku (unique, max 100)
  • name (max 255)
  • type (INSUMO, PRODUCTO, ACTIVO)

Variant Creation

  • item_id (must exist)
  • uom_id (must exist)
  • code (unique, max 100)
  • name (max 255)

Business Rules

Type Immutability

Item type cannot be changed after creation

SKU Uniqueness

SKUs and variant codes must be globally unique

Soft Deletion

Deleted items preserved for audit trail

Cost Tracking

Costs updated automatically on stock receipts

UOM Rules by Type

TypeUOM ConversionsTypical Base UOM
INSUMOMultiple allowedkg, L, unit, box
PRODUCTOBase only (1:1)unit, portion, set
ACTIVOBase only (1:1)unit, set

Common Workflows

Workflow 1: Register New Supply

1

Create Item

POST /api/v1/items with type=INSUMO
2

Create Base Variant

POST /api/v1/item-variants with base UOM (e.g., kg)
3

Optional: Create Additional Variants

Add variants for different packaging (e.g., 5kg bag)
4

Set Up UOM Conversions

Define conversions between variant UOMs (see Unit Conversions page)
5

Register Opening Balance

Add initial stock via /api/v1/inventory/opening-balance

Workflow 2: Add Finished Product

1

Create Item

POST /api/v1/items with type=PRODUCTO
2

Create Variant

POST /api/v1/item-variants with sale_price
3

Define Recipe (Future)

Link INSUMOs to PRODUCTO via recipe/BOM
4

Set Stock Levels

Configure min_stock and max_stock for alerts

Database Schema

items Table

ColumnTypeConstraints
idbigintPK, auto-increment
skuvarchar(100)UNIQUE, NOT NULL
namevarchar(255)NOT NULL
descriptiontextNULLABLE
typeenumIN (‘INSUMO’, ‘PRODUCTO’, ‘ACTIVO’)
is_stockedbooleanDEFAULT true
is_perishablebooleanDEFAULT false
is_activebooleanDEFAULT true
metajsonbDEFAULT ''
created_attimestamp
updated_attimestamp
deleted_attimestampNULLABLE

item_variants Table

ColumnTypeConstraints
idbigintPK, auto-increment
item_idbigintFK → items.id
uom_idbigintFK → units_of_measure.id
codevarchar(100)UNIQUE, NOT NULL
barcodevarchar(50)UNIQUE, NULLABLE
namevarchar(255)NOT NULL
descriptiontextNULLABLE
track_lotbooleanDEFAULT false
track_serialbooleanDEFAULT false
last_unit_costdecimal(10,4)DEFAULT 0
avg_unit_costdecimal(10,4)DEFAULT 0
sale_pricedecimal(10,4)NULLABLE
min_stockdecimal(10,4)DEFAULT 0
max_stockdecimal(10,4)DEFAULT 0
is_activebooleanDEFAULT true
metajsonbDEFAULT ''
created_attimestamp
updated_attimestamp
deleted_attimestampNULLABLE

Next Steps

Inventory Locations

Set up locations to hold stock

Unit Conversions

Configure UOM conversions for INSUMOs

Stock Movements

Register opening balances and movements

Build docs developers (and LLMs) love