trEN
in progress

Web app

Esnaf Stok

Stock and profitability tracking for small shop owners. It matches products from e-invoices automatically, calculates cost down to the cent, and is verified by 357 tests.

ReactTypeScriptSupabaseVitest
  • Solo

What it does

A web-based stock and profitability tracker for small shop owners, with separate roles for the owner and the cashier. In development since October 2026.

Why

I noticed that small shop owners, like local grocery stores, often don’t know whether they make or lose money on a given product. Revenue shows up at the till, but since a product’s cost changes with every new invoice, working out per-product profit by hand is close to impossible. Esnaf Stok exists to answer that question: upload the invoice, make the sale, and see what each product earns or loses.

How

  • Products from uploaded e-invoices (UBL-TR XML) are matched automatically and stock entries are created.
  • Weighted average cost is calculated to the kuruş (decimal.js).
  • Multi-tenant: each business’s data is separated at the database level with Row Level Security; owner and cashier have different permissions.
  • An immutable (append-only) stock ledger; concurrency is controlled with row locks and advisory locks.
  • 260 unit tests, 97 integration/security tests, plus a parity test checking that the cost calculation gives the same result in TypeScript and SQL.

Stack: React, TypeScript, Vite, Supabase (PostgreSQL, Auth, RLS), decimal.js, Vitest.

Where I used AI

Built with Claude Code. Product design, business rules, architecture decisions and code review are mine.

screenshots

Reports screen with test data, in Turkish: this month's profit calculation. After sales excluding VAT, cost of goods sold and cancellations, gross profit is −134.40 ₺, marked with a red Loss label.
profit/loss, product by product. a loss here!
Invoices screen with test data, in Turkish: a list of uploaded e-invoices with supplier, date, invoice number, amount and an Approved or Draft label; an Upload invoice button at the top right.
upload the e-invoice, products match themselves
Sales screen, in Turkish: a field to scan a barcode or type a product name, with a Camera button next to it; on the right, the total and Cash, Card and Bank transfer payment buttons.
sell by barcode, the camera works too

The hardest part

Not the code, the accounting. My knowledge of the domain was very thin at first; I had to learn concepts like weighted average cost, sales excluding VAT, how a cancelled sale affects cost, and the Turkish e-invoice format (UBL-TR) from scratch.

The second challenge was working with AI itself. Explaining clearly to Claude Code what I wanted, and verifying its code every time with tests and code review, took its own kind of discipline. That is one reason there are 357 tests.