TLAHuỳnh Văn Giỏi Em

Yumi Kitchen

Hệ thống quản lý vận hành và lãi lỗ cho một quán ăn bán tại chỗ, trên GrabFood và ShopeeFood, thay thế các file Excel của chủ quán: tồn kho theo công thức món, doanh thu theo kênh, đối soát ca và báo cáo lợi nhuận.

Vai trò
Phát triển độc lập (full-stack)
Thời gian
04/2026 – 05/2026
Công nghệ
Next.js 16React 19TypeScriptPostgreSQL (raw SQL)ExcelJSTailwind CSSPlaywrightHeroku

Điểm chính

  • 6tuần phát triển
  • 3kênh bán hàng trong một báo cáo lợi nhuận
  • 96test end-to-end, gồm một kịch bản vận hành quán hoàn chỉnh
  • Hoàn thành trong sáu tuần cho một quán ăn đang quản lý bằng Excel, đồng thời chuyển toàn bộ số liệu cũ sang hệ thống để lịch sử lãi lỗ liên tục ngay từ ngày đầu.
  • Chuyển quy trình vận hành thực tế của quán thành quy tắc nghiệp vụ: mỗi đơn hàng tự trừ nguyên liệu theo công thức và ghi nhận giá vốn tại thời điểm bán, giúp chủ quán nắm chính xác lợi nhuận theo từng món và từng kênh.
  • Tính đúng các khoản phí thực tế của nền tảng giao đồ ăn, gồm VAT 8% trên hoa hồng GrabFood và phí quảng cáo, để lợi nhuận hiển thị khớp với số tiền thực nhận.
  • Hỗ trợ chủ quán kiểm soát vận hành hằng ngày: đối soát tiền mặt và chuyển khoản theo ca, kiểm kho có thể hoàn tác, theo dõi vốn, import/export Excel cho mọi loại dữ liệu.
  • Kiểm thử trực tiếp số liệu kinh doanh thay vì chỉ giao diện: một kịch bản end-to-end khởi tạo quán từ đầu và kiểm tra tồn kho, giá vốn, doanh thu, biên lợi nhuận sau từng bước.

Bài toán

Một quán đồ chiên nhỏ bán tại quầy, trên GrabFood và ShopeeFood. Mỗi kênh thu một mức hoa hồng khác nhau, các nền tảng còn tính thêm VAT và phí quảng cáo, trong khi giá nguyên liệu thay đổi theo từng lần nhập hàng. Chủ quán biết doanh thu mỗi ngày, nhưng không biết lợi nhuận thực tế, cũng không biết món nào đang bán lỗ.

Yumi Kitchen là một ERP gọn nhẹ xây dựng riêng cho quán: thực đơn, công thức, tồn kho, đơn hàng trên mọi kênh, ca bán hàng và chi phí, tổng hợp thành một báo cáo lãi lỗ chính xác. Tôi phát triển một mình trong sáu tuần. Chủ quán đã chuyển hẳn từ Excel sang, cùng toàn bộ số liệu cũ, và vận hành quán trên hệ thống này cho đến khi ngừng kinh doanh.

Trang P&L tháng 10 của Yumi Kitchen: lợi nhuận trong kỳ, tiến độ hòa vốn và diễn giải từ doanh thu đến doanh thu thuần, lãi góp và chi phí cố định
P&L: từ doanh thu gộp đến lợi nhuận, kèm tiến độ hòa vốn. Dữ liệu demo.

Phạm vi

  • Thực đơn, mỗi món có công thức chi tiết đến từng gram.
  • Nguyên liệu, nhà cung cấp, phiếu nhập; tồn kho tự cập nhật theo từng đơn.
  • Đơn hàng từ quầy và hai ứng dụng giao đồ ăn, cùng trang đặt món cho khách với thông báo đơn mới qua Telegram.
  • Ca bán hàng và tiền mặt, chi phí, import/export Excel cho mọi loại dữ liệu.

Khoảng 30k dòng TypeScript, 48 API endpoint và 20 bảng PostgreSQL.

Kiến trúc

Một ứng dụng Next.js 16: trang render ở server, logic nghiệp vụ nằm trong các route handler dưới /api. Không dùng ORM mà viết SQL thuần qua pg, kèm một migration runner nhỏ do tôi tự viết. Ứng dụng chạy trên Heroku.

Next.js 16 (App Router)
├── /menu, /checkout, /order     khách đặt món
├── /admin/*                     trang quản trị của chủ quán
└── /api/*  route handlers  ──►  raw SQL (pg)  ──►  PostgreSQL
                                  giá vốn · tồn kho · quy tắc P&L
Trang tổng quan admin của Yumi Kitchen: số đơn hôm nay, doanh thu, tỷ lệ hoàn thành, cảnh báo tồn kho và danh sách đơn gần đây theo kênh
Tổng quan: đơn hôm nay, doanh thu và cảnh báo tồn kho; mỗi đơn ghi rõ kênh bán và số tiền thực nhận. Dữ liệu demo.

Các quyết định kỹ thuật chính

Tồn kho trừ theo công thức, giá vốn chốt ngay lúc bán

Mỗi đơn hàng tự trừ nguyên liệu theo công thức và ghi nhận giá vốn tại đúng thời điểm bán. Nhờ vậy, giá vốn của tuần trước vẫn chính xác dù nhà cung cấp tăng giá sau đó, và khi hủy đơn, kho được hoàn lại đúng phần đã trừ.

Tỷ lệ và biên lợi nhuận tính bằng số nguyên

Các tỷ lệ được lưu dưới dạng basis point số nguyên (5500 = 55,00%), và mọi phép làm tròn đều đi qua một hàm duy nhất, nên sai số dấu phẩy động không lọt vào con số lợi nhuận.

Tính đúng theo cách các nền tảng thu phí

Báo cáo lãi lỗ bám sát cách từng nền tảng thanh toán cho quán: hoa hồng riêng của từng kênh, VAT 8% trên hoa hồng GrabFood và phí quảng cáo. Nếu nền tảng thu khác với mức hệ thống tính, chủ quán có thể nhập số liệu thực tế cho từng đơn.

Trang thực đơn của Yumi Kitchen: danh sách món với giá bán, giá vốn theo công thức và phần trăm biên lợi nhuận tô màu theo ngưỡng
Thực đơn: giá vốn và biên lợi nhuận từng món, tự tính lại khi giá nguyên liệu thay đổi. Dữ liệu demo.

Thiết kế cho người chủ quen làm việc với Excel

Khi chốt ca, hệ thống đối chiếu số tiền mặt theo sổ sách với số tiền kiểm đếm thực tế và ghi nhận phần chênh lệch. Các file Excel mẫu cho phép chủ quán đưa dữ liệu sẵn có vào hệ thống mà không cần nhập lại thủ công.

Trang tồn kho nguyên liệu của Yumi Kitchen: tổng giá trị tồn, các nguyên liệu dưới ngưỡng và bảng gồm số lượng tồn, ngưỡng cảnh báo, giá nhập gần nhất và giá trị
Tồn kho: số lượng tồn, ngưỡng cảnh báo và giá trị theo giá nhập gần nhất. Dữ liệu demo.

Test kiểm tra con số, không chỉ status code

Playwright chạy trọn một vòng vận hành của quán (nhập hàng, bán trên mọi kênh, hủy đơn, chốt ca) và kiểm tra tồn kho, giá vốn, doanh thu, biên lợi nhuận sau từng bước. Test chỉ pass khi các con số đều đúng.

Những điều học được từ quán thật

  • Mỗi nền tảng thu phí theo cách riêng. Chỉ GrabFood tính VAT trên phí, nên chỉ đơn GrabFood được cộng VAT.
  • Giảm giá có hai dạng, số tiền cố định hoặc phần trăm, và đơn hàng hỗ trợ cả hai.
  • Ngày phải tính theo giờ của quán. Khi còn tính theo UTC, các khoản chi định kỳ bị ghi sớm một ngày. Hiện toàn bộ hệ thống chạy theo giờ Việt Nam, và một migration đã sửa dữ liệu cũ mà không ảnh hưởng đến những bản ghi chủ quán đã chỉnh sửa thủ công.
  • Chủ quán nghĩ theo món ăn, không theo bảng dữ liệu, nên có thể nhân bản món và kéo thả để sắp xếp lại các dòng trong công thức.

Những gì tôi sẽ làm tiếp

Chuyển admin token từ localStorage sang cookie httpOnly, không cho ứng dụng khởi động khi thiếu session secret, và chuyển rate limiter từ bộ nhớ sang PostgreSQL trước khi mở rộng lên nhiều instance.

← Tất cả dự án