Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save techiier/bd00e82e53ff2e404a1f0884b7121c72 to your computer and use it in GitHub Desktop.

Select an option

Save techiier/bd00e82e53ff2e404a1f0884b7121c72 to your computer and use it in GitHub Desktop.

Here is the technical architectural blueprint summarizing the modern inventory and Kardex system we designed, tailored for enterprise flexibility and high performance. The goal of system is that can handle assets like uniforms with its assignation complexity as the same time its refined design can be used in the future to handle another type of assets like hardware, office elements etc

---

Architecture Blueprint: Flexible Inventory & Kardex System

1. Core Architectural Principles

This architecture abandons the rigid, legacy approach of "wide tables" with dozens of nullable attribute columns. Instead, it adopts a Hybrid Relational-Document Paradigm, strictly separating concerns into three distinct layers:

  1. The Catalog (What exists): A hierarchical definition of items using flexible JSON payloads to support vastly different physical goods (Uniforms vs. IT Hardware) without schema changes.
  2. The Stock Position (What we have): A materialized, highly-optimized snapshot of current availability per physical location.
  3. The Kardex (How we got here): An immutable, append-only ledger inspired by double-entry accounting. It acts as the absolute source of truth for all inventory calculations and audits.

---

2. Product Catalog Topology (Template vs. Variant)

To solve the "Variant Explosion" problem and maintain clean Master Data Management (MDM), products are split into a Parent-Child relationship.

Product Template (The Concept)

Defines the general, abstract item. It holds properties shared across all physical manifestations of the item.

  • Fields: ID, Name, Category, Base Cost, Active Status.
  • Example: "Camisa Polo Reflectiva", "Laptop Dell Rugged".

Product Variant (The Physical Object / SKU)

Defines the lowest trackable unit of inventory. Every variant represents a unique physical footprint and is assigned a unique SKU and Barcode.

  • Fields: ID, Template ID (FK), SKU, Barcode, JSON Attributes.
  • JSON Payload: Stores all variant-specific data (size, color, gender fit, serial numbers, MAC addresses).

Concept Illustration: Catalog Data Model

Layer Entity Identifier JSON Attributes Payload
Template Camisa Polo Reflectiva ID: 10 (None - Abstract Concept)
Variant Polo Reflectiva - Medium SKU: POLO-M {"size": "M", "gender": "F", "color": "Navy"}
Variant Polo Reflectiva - Large SKU: POLO-L {"size": "L", "gender": "F", "color": "Navy"}
Template Multímetro Digital Fluke ID: 11 (None - Abstract Concept)
Variant Fluke 117 - Unit #1 SKU: FLK-001 {"serial": "991A", "cal_date": "2026-10"}

---

3. Organizational & Location Hierarchy

Locations must represent the physical reality of the supply chain, including the end-user holding company assets.

Location Tree

Locations are hierarchical, rolling up from broad regions to specific shelves or people.

  • Regional Node: Master DWH (e.g., Region Occidental).
  • Local Node: Operational DWH (e.g., DWH Santa Ana).
  • Virtual Node (Asset Accountability): Employee Locker.

The Employee as a "Virtual Location"

By treating an Employee as a strictly mapped 1:1 Location ID, the Kardex treats assigning a laptop or uniform identically to transferring stock between two warehouses.

  • Benefit: Instant accountability. Querying current stock where location_id = Employee_X_Locker instantly yields the offboarding/return checklist.

---

4. The Immutable Ledger (Kardex)

The Kardex is an append-only transaction log. Rows are never updated or deleted. Mistakes are corrected via compensating entries (Reversals).

Double-Entry Movement Flow

Every physical movement requires two balanced Kardex entries linked by a shared Document/Transaction ID:

  1. OUT (-1) from the Source Location.
  2. IN (+1) to the Destination Location.

Movement Type Catalog

Movements are strictly typed using an integer-based catalog table (not raw strings) to define the behavior of the transaction.

  • 1 = Purchase Receipt (IN)
  • 2 = Transfer Out (OUT)
  • 3 = Issue to Employee (OUT)
  • 4 = Receive Return (IN)

Concept Illustration: Kardex Ledger

Txn ID Date Movement Type (FK) Dir Location (FK) Variant (FK / SKU) Qty Qty Before Qty After
501 03-01 (2) Transfer Out -1 DWH Santa Ana POLO-M 2 20 18
501 03-01 (3) Receive Uniform +1 Emp: Maria L. POLO-M 2 0 2

Note: Qty Before and Qty After are denormalized snapshots taken at the exact millisecond of the transaction. This guarantees instant UI rendering of historical Kardex views without recalculating years of data.

---

5. Uniform Allocation Rules Engine

To automate what an employee should receive based on HR data, a bridging matrix dictates inventory requirements.

  • Inputs: Employee Position (e.g., Mecánico), Employee Sex (e.g., F).
  • Outputs: Required Product Templates & Default Quantities.

Concept Illustration: Allocation Matrix

Position (FK) Sex Required Template (FK) Default Qty
Personal Lab. M Camisa Manga Larga Admin 2
Personal Lab. M Gabacha Blanca 1
Mecánicos F Pantalón Jeans Reflectivo 3

When HR triggers an onboarding event, the system queries this matrix, prompts the warehouse worker for the specific Sizes (Variants) matching those Templates, and generates the Kardex movements.
This allocation rules engines comes from this diagram that shows how uniforms distribution works based on employees’s department/position:


6. Technical & Performance Considerations

JSON Query Performance (The "Full Table Scan" Problem)

Storing attributes in JSON provides infinite flexibility but destroys read performance if queried directly. Solution: Indexed Computed Columns (Persisted).

  • The database engine is instructed to extract heavily queried JSON keys (e.g., size, color, serial_number) into virtual columns.
  • These virtual columns are strictly typed (cast to small strings) and physically saved (Persisted) to disk alongside the row.
  • Standard B-Tree indexes are applied to these computed columns.
  • Result: Queries like "Find all Size M shirts" hit the B-Tree index instantly (O(log N) complexity), never parsing the raw JSON during the search phase.

The system is consider to be develop in sql server 2019 engine

Denormalization in JSON vs. Relational Integrity

  • Relational Core: Entities that change state, location, or quantity (Stock Position, Locations, Kardex, Employees) rely exclusively on strict Integer Foreign Keys.
  • Denormalized JSON: Physical properties of a SKU that never mutate once created (e.g., the fact that a boot is Size 38, or a Laptop is a Dell) are stamped as raw text into the JSON payload.
  • Why? This prevents massive, costly SQL JOIN operations to dozens of arbitrary attribute catalogs during routine Kardex reads. Input validation (ensuring the user selects "Dell" and not "Del") is handled by the Application/UI layer during variant creation via standardized frontend catalogs.

Transactional Boundaries (ACID)

Updates to the Stock Position (materialized view) and inserts into the Kardex (ledger) must always occur within the same strict database Transaction (BEGIN TRAN / COMMIT). If the Kardex insert succeeds but the Stock Position update fails, the entire transaction rolls back to prevent phantom inventory discrepancies.

---

System Entity Relationship Overview

erDiagram
LOCATION ||--o{ EMPLOYEE : "Assigns Virtual Locker"
EMPLOYEE }o--|| POSITION : "Holds"
POSITION ||--o{ UNIFORM_RULE : "Requires"
UNIFORM_RULE }o--|| PRODUCT_TEMPLATE : "Dictates Template"

`PRODUCT_TEMPLATE ||--|{ PRODUCT_VARIANT : "Generates SKUs"`  
  
`PRODUCT_VARIANT ||--o{ STOCK_POSITION : "Tracked In"`  
`LOCATION ||--o{ STOCK_POSITION : "Holds Stock"`  
  
`PRODUCT_VARIANT ||--o{ KARDEX_LEDGER : "Moves"`  
`LOCATION ||--o{ KARDEX_LEDGER : "Source/Dest"`  
`MOVEMENT_CATALOG ||--o{ KARDEX_LEDGER : "Defines Txn"`  
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment