Files
OMT-SM/README.md
T

5.0 KiB

CRM OMT — Cash Collection Management System

A multi-shop POS / cash control / reconciliation web app for the typical Lebanese cell-phone or mixed-retail shop that also runs an OMT and/or Whish counter alongside repair and item sales.

The problem

Most Lebanese cell shops don't just sell phones and do repairs — they also act as OMT and/or Whish agents, sell Alfa / Touch / Ogero recharges, take EDL bill payments, and swap between USD and LBP. All of that money flows through one drawer, in two currencies, across multiple employees and shifts, mixed with goods and repair income.

The result for the owner is the recurring "incompatible cash" pain: at the end of the day the drawer doesn't match what the system should hold, and there is no clear accountability per cashier or per shift.

What this app gives the owner

  • Per-employee, per-shift accountability with a blind close: the cashier declares the cash count, the system computes what was expected, and any variance is recorded against that exact shift.
  • Live variance panel at end-of-shift (Expected / Counted / Δ in USD and LBP).
  • Owner overview tab — open shifts, open alerts, today's gross, recent closed-shift variances, and a 30-day cashier scorecard.
  • All money streams in one ledger — OMT send/receive, Whish, Alfa/Touch/Ogero recharge, EDL bill, FX swap, deposits/withdrawals, refunds, voids, mid-day safe drops, repair, goods sale.
  • DB-enforced accounting: atomic sale coupling, cash-movement sign guards, voids reverse movements, idempotency keys, RLS by shop and role.
  • Alerts pipeline for chronic shorts, void spikes, override spikes, reconciliation backlog, after-hours activity, voucher write-offs, stock shrinkage.

Architecture

The schema started life on Supabase but the app no longer uses Supabase at runtime. It runs against a self-hosted Postgres + a thin Express API:

  • DB: postgres:16-alpine via docker-compose.yml. The Supabase migrations under supabase/migrations/ are replayed on first boot by server/db/init/01_run_migrations.sh, preceded by an auth.users shim (00_auth_shim.sql) so the original auth.uid() / RLS policies keep working.
  • API: server/src/index.js — Express. Issues JWTs with bcrypt + jsonwebtoken, opens a pooled connection per request, sets request.jwt.claim.* and SET LOCAL ROLE authenticated so RLS evaluates against the caller. Generic /rpc/:fn route forwards to app.<fn>(...) SQL functions; /from/:view exposes an allow-listed set of read views.
  • Frontend: Vite + React 18 + TypeScript + shadcn/ui + Tailwind. The module at src/integrations/supabase/client.ts is a drop-in shim over src/lib/api.ts — same .auth, .rpc, .from(...) surface, but talks to the Express server.

See CLAUDE.md for the full design notes and conventions.

Run it

# one-time
cp server/.env.example server/.env   # set JWT_SECRET, etc.
npm install
npm --prefix server install

# day-to-day (DB + API + Web all together)
npm run dev:all
#   DB   → docker container crm_omt_db on :5432
#   API  → node server on :4000
#   WEB  → vite on :5173

# build the frontend
npm run build

# wipe & rebuild the DB (reruns migrations + reseeds the admin)
npm run db:reset

Default seed admin (override via env in docker-compose.yml):

  • email: admin@local.test
  • password: ChangeMe123!

Shop deployment quickstart

For a machine in the shop, use the full guide at docs/SHOP_SETUP.md.

Fast path:

git clone https://github.com/Krikorios/OMT-SM.git
cd OMT-SM

cp .env.example .env
cp server/.env.example server/.env

npm install
npm --prefix server install

./scripts/start_prod.sh

Important:

  • Set strong secrets in .env and server/.env before first production use.
  • Match POSTGRES_PASSWORD in .env with the password inside server/.env DATABASE_URL.

Tech stack

React 18, TypeScript, Vite, shadcn/ui, Tailwind, TanStack Query, react-hook-form, zod · Express 4, pg, bcrypt, jsonwebtoken · PostgreSQL 16 · Docker Compose. 💼 Employee Payment Reconciliation Dashboard A mini web application built with React and Supabase that tracks daily collection vs deposit transactions for employees and enforces a carry-forward balance logic. If an employee's deposit on a given day is less than the collection amount, the shortfall is rolled over and must be cleared by future deposits. The app processes transaction data, maintains a running balance, and generates an intuitive dashboard to visualize employee payment behavior.

Key Features:

Fetch and display employee-wise transaction data

Calculate running outstanding balances per employee

Apply deposit payments to past shortfalls based on business rules

Built using React, TypeScript, and Supabase (PostgreSQL backend)