# 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](docker-compose.yml). The Supabase migrations under [`supabase/migrations/`](supabase/migrations/) are replayed on first boot by [`server/db/init/01_run_migrations.sh`](server/db/init/01_run_migrations.sh), preceded by an `auth.users` shim ([`00_auth_shim.sql`](server/db/init/00_auth_shim.sql)) so the original `auth.uid()` / RLS policies keep working. - **API:** [`server/src/index.js`](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.(...)` 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`](src/integrations/supabase/client.ts) is **a drop-in shim** over [`src/lib/api.ts`](src/lib/api.ts) — same `.auth`, `.rpc`, `.from(...)` surface, but talks to the Express server. See [CLAUDE.md](CLAUDE.md) for the full design notes and conventions. ## Run it ```bash # 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](docker-compose.yml)): - email: `admin@local.test` - password: `ChangeMe123!` ## 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)