Skip to content

Inventory Counts & Adjustments

Physical inventory counts and stock adjustments to reconcile actual vs. system quantities.

Purpose

  • Perform physical inventory counts to verify actual stock levels against the system
  • Automatically calculate differences between counted and system quantities
  • Auto-create draft adjustments for variances found during counts
  • Create manual adjustments for damage, expiry, corrections, or other reasons
  • Maintain an audit trail with approval and cancellation workflows

Inventory Counts

Entity Attributes

AttributeTypeDescription
idintegerAuto-incremented primary key
company_idintegerCompany that owns this count
warehouse_idintegerWarehouse being counted
count_numberstringAuto-generated (e.g., CNT-000001)
datedateCount date
statusenumdraft, approved, cancelled
notestextOptional notes
created_byintegerUser who created the count
approved_byintegerUser who finalized the count
approved_atdatetimeWhen the count was finalized

Count Item Attributes

AttributeTypeDescription
idintegerAuto-incremented primary key
inventory_count_idintegerParent count
product_idintegerProduct being counted
product_variant_idintegerOptional variant
unit_idintegerUnit of measure
system_quantitydecimal(15,3)System quantity at time of count
counted_quantitydecimal(15,3)Physically counted quantity
differencedecimal(15,3)counted_quantity - system_quantity
unit_costdecimal(15,3)Average cost from stock balance

Count Workflow

  • Draft — can be edited, updated, or deleted freely
  • Finalize — refreshes system quantities from current stock balances, computes differences, marks as approved, and auto-creates a draft adjustment for items with non-zero differences

Stock Adjustments

Entity Attributes

AttributeTypeDescription
idintegerAuto-incremented primary key
company_idintegerCompany that owns this adjustment
warehouse_idintegerWarehouse being adjusted
adjustment_numberstringAuto-generated (e.g., ADJ-000001)
datedateAdjustment date
statusenumdraft, approved, cancelled
reasonenumcount, damage, expiry, correction, other
inventory_count_idintegerSource count (if created from a count)
notestextOptional notes
total_quantity_increasedecimal(15,3)Sum of increase items
total_quantity_decreasedecimal(15,3)Sum of decrease items
total_value_increasedecimal(15,3)Total cost of increases
total_value_decreasedecimal(15,3)Total cost of decreases

Adjustment Item Attributes

AttributeTypeDescription
idintegerAuto-incremented primary key
inventory_adjustment_idintegerParent adjustment
product_idintegerProduct being adjusted
product_variant_idintegerOptional variant
unit_idintegerUnit of measure
adjustment_typeenumincrease or decrease
quantitydecimal(15,3)Quantity to adjust
unit_costdecimal(15,3)Cost per unit
total_costdecimal(15,3)quantity * unit_cost

Adjustment Workflow

ER Diagram

API Endpoints

Inventory Counts

MethodEndpointDescriptionPermission
GET/api/inventory/countsList counts (paginated)inventory.counts.view
POST/api/inventory/countsCreate a countinventory.counts.create
GET/api/inventory/counts/{id}Get count detailsinventory.counts.view
PUT/api/inventory/counts/{id}Update a draft countinventory.counts.create
DELETE/api/inventory/counts/{id}Delete a draft countinventory.counts.create
POST/api/inventory/counts/{id}/finalizeFinalize a countinventory.counts.finalize

Stock Adjustments

MethodEndpointDescriptionPermission
GET/api/inventory/adjustmentsList adjustments (paginated)inventory.adjustments.view
POST/api/inventory/adjustmentsCreate an adjustmentinventory.adjustments.create
GET/api/inventory/adjustments/{id}Get adjustment detailsinventory.adjustments.view
POST/api/inventory/adjustments/{id}/approveApprove an adjustmentinventory.adjustments.approve
POST/api/inventory/adjustments/{id}/cancelCancel an adjustmentinventory.adjustments.cancel

Query Parameters — Counts

ParameterTypeDescription
statusstringFilter by status (draft, approved, cancelled)
warehouse_idintegerFilter by warehouse
date_fromdateFilter from date
date_todateFilter to date
searchstringSearch by count number

Query Parameters — Adjustments

ParameterTypeDescription
statusstringFilter by status (draft, approved, cancelled)
warehouse_idintegerFilter by warehouse
reasonstringFilter by reason (count, damage, expiry, correction, other)
date_fromdateFilter from date
date_todateFilter to date
searchstringSearch by adjustment number

Examples

Create an Inventory Count

bash
curl -X POST https://moon-erp.elbaset.com/api/inventory/counts \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "warehouse_id": 1,
    "date": "2026-02-23",
    "notes": "Monthly count",
    "items": [
      {
        "product_id": 1,
        "unit_id": 1,
        "counted_quantity": 95
      }
    ]
  }'
dart
final response = await http.post(
  Uri.parse('$baseUrl/api/inventory/counts'),
  headers: {'Authorization': 'Bearer $token', 'Content-Type': 'application/json'},
  body: jsonEncode({
    'warehouse_id': 1,
    'date': '2026-02-23',
    'notes': 'Monthly count',
    'items': [
      {'product_id': 1, 'unit_id': 1, 'counted_quantity': 95},
    ],
  }),
);

Finalize a Count

bash
curl -X POST https://moon-erp.elbaset.com/api/inventory/counts/1/finalize \
  -H "Authorization: Bearer {token}"
dart
final response = await http.post(
  Uri.parse('$baseUrl/api/inventory/counts/1/finalize'),
  headers: {'Authorization': 'Bearer $token'},
);

Create a Manual Adjustment

bash
curl -X POST https://moon-erp.elbaset.com/api/inventory/adjustments \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "warehouse_id": 1,
    "date": "2026-02-23",
    "reason": "damage",
    "notes": "Water damage to stock",
    "items": [
      {
        "product_id": 1,
        "unit_id": 1,
        "adjustment_type": "decrease",
        "quantity": 5,
        "unit_cost": 10
      }
    ]
  }'
dart
final response = await http.post(
  Uri.parse('$baseUrl/api/inventory/adjustments'),
  headers: {'Authorization': 'Bearer $token', 'Content-Type': 'application/json'},
  body: jsonEncode({
    'warehouse_id': 1,
    'date': '2026-02-23',
    'reason': 'damage',
    'notes': 'Water damage to stock',
    'items': [
      {
        'product_id': 1,
        'unit_id': 1,
        'adjustment_type': 'decrease',
        'quantity': 5,
        'unit_cost': 10,
      },
    ],
  }),
);

Approve an Adjustment

bash
curl -X POST https://moon-erp.elbaset.com/api/inventory/adjustments/1/approve \
  -H "Authorization: Bearer {token}"
dart
final response = await http.post(
  Uri.parse('$baseUrl/api/inventory/adjustments/1/approve'),
  headers: {'Authorization': 'Bearer $token'},
);

Business Rules

  1. Counts can only be finalized from draft status
  2. Finalizing a count refreshes system quantities, computes differences, and auto-creates a draft adjustment if any items have non-zero differences
  3. Adjustments can be created manually or auto-created from counts
  4. Approving an adjustment updates stock balances (increase adds stock, decrease removes stock)
  5. Cancelling an approved adjustment reverses all stock changes
  6. Cancelling a draft adjustment has no stock effect
  7. Only draft counts can be edited or deleted
  8. Count and adjustment numbers are auto-generated via the Sequence system
  9. All operations are company-scoped (tenant-isolated)

Moon ERP API Documentation