← BACK
01
Retail Management System
2025Private deployment
LIVE SITE ↗

Replacing manual retail operations with a system staff could trust

This case study shows how I turned disconnected stock checks, pricing decisions, and invoicing into one operational workflow for an electronics store.

Retail OperationsInventory LogicCheckout FlowBusiness Rules
5
Problems
7
Decisions
5
Results
coreNext.jsReactJavaScript (ES6+)
backendMongoDBMongooseZodJWT Authbcrypt
featuresRechartsExcel Export (ExcelJS)Date Handling (date-fns)
systemStyled ComponentsNodemailerSharp
testingJestSupertest
01
THE PROBLEM

What was actually broken

5 pain points identified before writing a single line of code

01

The store relied on manual stock checking inside the storage room

02

Employees had to physically verify product availability multiple times per day

03

Frequent sales errors (selling unavailable products)

04

Slow checkout process due to lack of real-time visibility

05

No clear financial tracking or stock accuracy

POS system with real-time stock visibilityCLICK TO EXPAND
POS system with real-time stock visibility

Real-time product search and stock visibility — no more manual checks

02
BUSINESS IMPACT

What this was costing the business

Real cost — not hypothetical risk

01

Lost sales due to unavailable products going undetected until checkout

02

Wasted time and physical effort for employees on repetitive stock verification

03

Poor customer experience caused by long wait times inside the store

04

Inaccurate understanding of inventory levels and actual revenue

05

Operational chaos affecting daily performance and decision-making

Checkout system with pricing and VAT calculationCLICK TO EXPAND
Checkout system with pricing and VAT calculation

Multi-product checkout with automatic calculations and flexible pricing

03
STRUCTURAL DECISIONS

Why these choices — not others

7 deliberate trade-offs

01

Connected inventory directly to the sales process (real-time sync)

02

Introduced multi-product order system instead of single-product checkout

03

Added stock threshold alerts for better anticipation

04

Implemented flexible pricing (min/max) to support real negotiation

05

Designed invoice system supporting both individuals and companies

06

Made VAT (TVA) optional based on real business scenarios

07

Integrated automatic warranty logic per product

Admin dashboard with sales and stock analyticsCLICK TO EXPAND
Admin dashboard with sales and stock analytics

Full operational visibility with real-time business insights

04
ARCHITECTURE

How the system is structured

The blueprint that holds everything together

01

Separated product entity from stock entity to avoid data duplication

02

Each stock batch has its own purchase price for accurate accounting

03

Implemented FIFO logic for precise profit calculation

04

Used status-based operations for cancel/return with automatic stock recovery

05

Designed system with data consistency and transactional integrity in mind

Product and inventory management systemCLICK TO EXPAND
Product and inventory management system

Structured product and stock separation for accurate data handling

05
RESULTS

What changed after shipping

5 measurable improvements

Stock availability became visible during checkout instead of after a manual trip to storage

Cashiers could process multi-product orders inside one consistent flow

Profit tracking moved from approximation to batch-based calculation

Returns and cancellations restored stock through defined system rules

The owner gained a clearer daily view of sales, stock movement, and invoicing

Invoice generation system with VAT supportCLICK TO EXPAND
Invoice generation system with VAT support

Automatic invoice generation with support for VAT and client types

06
ENGINEERING

Technical Deep Dive

How the system is designed under the hood — architecture, data model, and guarantees.

6.1
DATA MODEL

Data Model

Productcore

Catalog entry with cached stock (synced from FIFO)

InventoryLogcore

FIFO batch — single source of truth for stock & cost

Stock Source of Truth
Saletransaction

Single-product workflow document (UI entry point)

Ordertransaction

Multi-product sale with embedded OrderItems

SalesTransactionItemfinancial

Canonical financial record — immutable after creation

Financial Source of Truth
Invoicefinancial

Legal document (FACTURE / BON DE VENTE) with embedded items

Guaranteefinancial

Warranty document with lifecycle tracking

STIDailySnapshotaudit

Immutable daily aggregates for drift detection

Relationships
Product──1 → N──▸InventoryLogFIFO batches
Product──1 → N──▸Salesold via
Sale──1 → 1──▸SalesTransactionItemdual-write
Order──1 → N──▸SalesTransactionItemper item
Sale──1 → 0..1──▸Invoicegenerates
Invoice──1 → 0..1──▸Guaranteewarranty
6.2
ARCHITECTURE

Core Architecture

01FIFO Cost Engine
Ensures accurate profit per unit sold
IMPACT: Every unit sold carries batch-based purchase cost, which makes margin tracking far more reliable than manual estimation
Each InventoryLog entry = one batch with remainingQty and purchasePrice
On sale: oldest batches consumed first (sort: createdAt ASC)
Atomic guard: $gte check on remainingQty prevents concurrent conflicts
No fallback — FIFO exhaustion hard-rejects the sale
02Dual-Write Pattern
Separates workflow state from financial truth
IMPACT: Analytics and reports stay insulated from most workflow mutations and UI-driven state changes
Sale/Order = workflow documents for UI and process tracking
SalesTransactionItem = canonical financial truth for analytics
STI financial fields are immutable — corrections require cancel + re-sell
Feature flags control migration from Sale-based to STI-based statistics
033-Layer Validation
No invalid data reaches the database — ever
IMPACT: Zero corrupted records in production — every entry passes 3 independent checkpoints
Layer 1: Zod schemas at API boundary (14 validation files)
Layer 2: Service-level business rules (stock, pricing, relationships)
Layer 3: Mongoose schema constraints (required, min/max, enum, unique)
04Snapshot Architecture
Past records stay accurate regardless of future changes
IMPACT: Past invoices remain tied to the product data captured at sale time
Every sale captures a point-in-time product snapshot
Invoice and Guarantee items are fully embedded — immutable after creation
Historical accuracy: product changes never affect past records
6.3
EXECUTION FLOW

Sale Execution Flow

1
Validate inputs
productId, quantity, sellingPrice, cashierId — Zod + business rules
2
Calculate TVA
tvaAmount = priceHT × tvaRate, priceTTC = priceHT × (1 + tvaRate)
3
Start MongoDB transaction
All subsequent operations are atomic — commit or rollback
4
Check stock (cached + FIFO)
Product.stock (cached projection) ≥ qty, then authoritative check: aggregate(InventoryLog.remainingQty) ≥ qty
5
Consume FIFO batches
Loop oldest → decrement remainingQty → accumulate cost with $gte guard
6
Create Sale + STI
Dual-write: Sale (workflow) + SalesTransactionItem (financial truth)
7
Decrement Product.stock
adjustStock(-qty) updates the cached projection — FIFO batches remain the source of truth
8
Commit transaction
All-or-nothing — any failure rolls back every operation
NOTEAll operations between steps 3–8 execute within a single MongoDB transaction. Any failure triggers a full rollback.
6.4
GUARANTEES

System Guarantees

DATA INTEGRITY
No Overselling

3-layer defense: cached stock → FIFO aggregate → atomic batch guard ($gte). Concurrent conflicts return 409.

Consistent State

Cancellation atomically updates Sale + STI + Invoice + Guarantee + FIFO restore in one transaction.

FINANCIAL ACCURACY
Accurate Profit Calculation

Cost comes from FIFO batches (not product-level). Each unit sold carries its exact purchase price.

Immutable Financial Records

STI financial fields and daily snapshots cannot be modified. Corrections create new records.

TRANSACTION SAFETY
Transaction Safety

Every critical operation uses MongoDB transactions. Partial state is impossible — commit or full rollback.

Historical Accuracy

Point-in-time snapshots on every sale so later product edits do not rewrite past invoices or reports.

6.5
DATA FLOW

Data Flow

Stock Truth — System SSOT
1InventoryLog.remainingQty ← SINGLE SOURCE OF TRUTH
2Product.stock = Σ(InventoryLog.remainingQty) // cached
3Sale → FIFO consumption (oldest batch first)
4Cancel → FIFO restoration (new entry at original cost)
Relationship Map
1Product (1) ────── (N) InventoryLog
2Sale (1) ────────── (1) SalesTransactionItem
3Order (1) ───────── (N) SalesTransactionItem
4Invoice (1) ─────── (0..1) Guarantee
Transaction Boundary — Atomicity
1session = mongoose.startSession()
2session.startTransaction()
3 ... all ops with { session } ...
4session.commitTransaction() || abortTransaction()
6.6
TRADE-OFFS

Trade-offs

FIFO costingoverAverage cost pricing

Exact profit per unit — critical for a store where purchase prices fluctuate between batches

Dual-write (Sale + STI)overSingle document

Separates mutable workflow state from immutable financial truth — analytics stay clean

Embedded snapshotsoverReference-only lookups

Historical accuracy without heavy join queries - past invoices stay tied to stored sale snapshots

Cached stock on ProductoverLive aggregation only

Fast reads for UI/POS — FIFO aggregation remains authoritative for all write operations

System Principles
01
Single source of truthInventoryLog.remainingQty owns stock reality; Product.stock is a cached projection
02
Immutable financial recordsSalesTransactionItem cannot be edited; corrections create new records
03
Snapshot-based historical accuracyevery sale freezes product state at point of transaction
04
Atomic operationsno partial state is possible; every critical flow is wrapped in a MongoDB transaction
What's next?

The value was not a prettier dashboard. It was a workflow the store could rely on during real sales.

← ALL PROJECTSSTART A CONVERSATION →