At a Glance
Owner: Product Admin · Table:tb_location· Used by: inventory, GRN, SR, physical count, spot check, PR/PO ·location_type(inventory/direct/consignment) decides posting behaviour.


Locations are the physical or logical places where stock lives or is consumed — main warehouse, kitchen pass, bar, housekeeping cart, supplier-owned consignment shelf. The location_type field decides posting behaviour:
inventory — carries a stock balance, posts to inventory asset GL.direct — bypasses the balance, posts straight to department expense.consignment — holds supplier-owned goods, recognised only when consumed.The same record configures period-end count behaviour (physical_count_type = yes / no) and the default delivery point that ships into this location. Maintained by Product Admin. Read by every inventory posting path.
| Task | Where | Notes |
|---|---|---|
| Add a location | Configuration → Master Data → Location → New | Required: code, name, location_type |
| Tag default delivery point | Location detail | Sets delivery_point_id + denormalised delivery_point_name |
| Set count behaviour | Toggle physical_count_type |
no skips period-end count; spot check still applies |
| Deactivate | Toggle is_active |
Hidden from pickers; historical postings preserved |
Change location_type |
Edit dialog | Blocked after first movement — would corrupt journal history |
| Assign inventory tree | Location detail screen | Restricts which products are visible at this location |
| Symptom / Message | Cause | Action |
|---|---|---|
| "Code already in use" | Duplicate code among active rows |
Pick a different code |
| "Cannot delete — non-zero balance" | Location still holds stock | Issue out or transfer first |
| "Cannot delete — referenced by open SR/GRN" | FK references in open docs | Close documents first |
| "Cannot change location_type" | Edit attempted after first movement | Create a new location and migrate manually |
| Delivery-point name stale | delivery_point_name snapshot wasn't refreshed |
Re-save the location or run a backfill |
location_type is sticky once used — switching inventory → direct retro-actively corrupts journal entries.physical_count_type = no excludes from period count but not from spot checks.delivery_point_name is denormalised, needs refresh on rename.Source: tenant schema.
tb_location| Field | Prisma Type | Nullable | Description |
|---|---|---|---|
id |
String @db.Uuid |
No | Primary key. |
code |
String @db.VarChar |
No | Short code, e.g. INV1, KIT. |
name |
String @db.VarChar |
No | Display name. |
location_type |
enum_location_type |
No | inventory (default), direct, or consignment. |
description |
String? |
Yes | Free text. |
delivery_point_id |
String? @db.Uuid |
Yes | Optional FK to tb_delivery_point. |
delivery_point_name |
String? @db.VarChar |
Yes | Denormalised display copy. |
physical_count_type |
enum_physical_count_type |
No | no (default) — skip; yes — include. |
is_active |
Boolean? |
Yes | Active flag. |
note, info, dimension |
— | Yes | Standard metadata. |
| Audit columns | — | Yes | created_*, updated_*, deleted_*. |
Constraints: primary key on id. FK on delivery_point_id → tb_delivery_point onDelete: NoAction. Uniqueness on code enforced at app layer.
enum_location_type values: inventory, direct, consignment.
enum_physical_count_type values: no, yes.
code unique among active rows (app-enforced).location_type cannot change after first movement.is_active = false hides from pickers; preserves historical postings.physical_count_type = no excludes period count, not spot check.delivery_point_name snapshot on rename.from_location / to_location on every issue/transfer.physical_count_type = yes.../carmen-turborepo-backend-v2/packages/prisma-shared-schema-tenant/prisma/schema.prisma — tb_location (lines ~1294-1393), enum_location_type (lines ~218-222), enum_physical_count_type (lines ~62-65).../carmen-turborepo-frontend/apps/web/app/(app)/configuration/location/.../carmen/docs/settings/locations.md — wireframes.