លំហសិក្សាកម្ពុជា លំហសិក្សាកម្ពុជា V1.0
ចូល ចុះឈ្មោះ

SmartPOS: A Web-Based Point-of-Sale and Inventory Management System

អ្នកចូលរួម
គ្រូដឹកនាំ: សេក សុជាតិ
មូលសង្ខេប / Abstract

Small retail shops such as mini-marts often record sales and stock manually or in disconnected spreadsheets, which makes it difficult to know current stock levels, track daily sales, or stop a cashier from selling an item that is already out of stock. SmartPOS is a web-based Point-of-Sale and Inventory Management System built with Python, Flask, and MySQL that lets store staff manage products, process sales at checkout, and view sales reports, all enforced by a server-side role-based permission system. The system applies Object-Oriented Programming through a layered architecture that separates domain models, business services, and database repositories. The delivered system covers everything proposed and extends it substantially: role-based authentication for four staff roles, full product and stock management with a stock ledger, a checkout workflow that supports cash, KHQR bank-QR, card, and split-tender payment and automatically updates inventory, purchase orders with a supplier workflow, staff shift and cash-drawer accountability, a team task board, analytics with CSV/Excel export, and automated Telegram alerts for store activity. The final output is a working Flask application backed by a 23-table MySQL database, verified by 49 automated test cases and a full manual walkthrough of every role and workflow.

ពាក្យគន្លឹះ

 

Object Oriented Programming II
Advanced OOP with Python

Python + Flask + MySQL

Final Report

SmartPOS: A Web-Based Point-of-Sale and Inventory Management System

Demo: Clone from our github
https://github.com/Cchheanglim/smartpos_withpythonflask.git

Field

Student Input

Project Title

SmartPOS: A Web-Based Point-of-Sale and Inventory Management System

Team Members

Lim Meng Huy, Heng Longmeng, Chhum Chheanglim, Kang Sok sambathratanak

Course / Class

Object Oriented Programming II

Lecturer

SEK SOCHEAT

Semester / Year

Semester 1, Year 2 (2026–2027)

Submission Type

Final Report


 

Table of Contents

Abstract / Summary.........................................................................................................

1. Problem Statement..................................................................................................... 1

2. Objectives (Achieved)............................................................................................... 1

3. Scope of the Delivered System.................................................................................. 2

4. Target Users and Roles.............................................................................................. 3

5. System Features (As Delivered)................................................................................ 4

6. OOP Design............................................................................................................... 5

7. System Architecture................................................................................................... 7

8. Database Design......................................................................................................... 8

9. Implementation........................................................................................................ 11

10. Testing and Results................................................................................................ 20

11. Changes from the Original Proposal...................................................................... 21

12. Challenges and Resolutions................................................................................... 22

13. Conclusion and Future Work................................................................................. 22

Appendix...................................................................................................................... 23

14. References.............................................................................................................. 25


 

Abstract

Small retail shops such as mini-marts often record sales and stock manually or in disconnected spreadsheets, which makes it difficult to know current stock levels, track daily sales, or stop a cashier from selling an item that is already out of stock. SmartPOS is a web-based Point-of-Sale and Inventory Management System built with Python, Flask, and MySQL that lets store staff manage products, process sales at checkout, and view sales reports, all enforced by a server-side role-based permission system. The system applies Object-Oriented Programming through a layered architecture that separates domain models, business services, and database repositories.

The delivered system covers everything proposed and extends it substantially: role-based authentication for four staff roles, full product and stock management with a stock ledger, a checkout workflow that supports cash, KHQR bank-QR, card, and split-tender payment and automatically updates inventory, purchase orders with a supplier workflow, staff shift and cash-drawer accountability, a team task board, analytics with CSV/Excel export, and automated Telegram alerts for store activity. The final output is a working Flask application backed by a 23-table MySQL database, verified by 49 automated test cases and a full manual walkthrough of every role and workflow.


1. Problem Statement

Many small shops track products and sales using paper receipts or basic spreadsheets managed by the shop owner. Cashiers have no quick way to check whether an item is in stock while serving a customer, and owners cannot see accurate, up-to-date stock levels or daily sales totals without manually counting inventory. The current process has no shared system connecting what is sold at checkout to what remains in stock, so stock counts drift out of date and sales figures must be calculated by hand. A web-based POS system was needed so that every sale automatically updates stock and produces an accurate, real-time sales record — and, specific to the local market, one that supports Cambodia's real payment mix of cash, KHQR, and card, sometimes within the same transaction.

Item

Team Answer

Current situation

Sales and stock counts are recorded manually on paper or in separate spreadsheets by shop staff.

Main pain point

No connection between a recorded sale and the actual stock count, so inventory numbers become inaccurate over time.

Evidence / observation

Team observation of a small retail shop's checkout and stock-taking process, where sales and inventory are tracked in separate, unlinked records.

Need for software

A centralized POS system that automatically deducts stock at the point of sale and gives the owner an accurate, real-time sales and inventory report, in the currencies and payment methods customers actually use.

2. Objectives (Achieved)

General Objective: To design and implement a web-based Point-of-Sale and Inventory Management System using Python, Flask, and MySQL that links every sale directly to stock levels through a clean, layered Object-Oriented design. This objective was fully met.

Specific Objectives

●       Build a secure authentication and role-based authorization system for Super Admin, Admin, Inventory Manager, and Cashier roles, with individually grantable permission overrides.

●       Design and implement product and stock management with full CRUD functionality and a full stock movement ledger.

●       Implement a checkout/sales workflow that records a sale and automatically deducts stock in real time, supporting cash (USD/KHR), KHQR, card, and split-tender payment.

●       Design a normalized MySQL database supporting products, sales, stock movements, purchase orders, staff shifts, and users — 23 tables in total.

●       Apply a layered OOP architecture (models, services, repositories) and verify core business rules with automated test cases.

Objectives and Success Criteria

Objective

Measurable Success Criterion — Result

Authentication and role-based access

Users log in/log out; each of the 4 roles can only access the routes and actions permitted to that role, enforced server-side. Achieved.

Product and stock management

Staff can create, view, update, and deactivate products; stock quantity updates automatically after each sale, refund, and received purchase order. Achieved.

Checkout / sales workflow

Cashier can create a sale with multiple items across four payment methods; the system rejects sales that exceed available stock. Achieved.

Clean OOP layers

60+ domain classes, 20 services, and 19 repositories, each with a single clear responsibility — exceeds the original target of 5/3/3.

MySQL database

ERD, SQL schema, constraints, and seed data covering users, products, sales, stock movements, purchase orders, and shifts. Achieved.

Testing

49 automated test cases plus a documented manual verification pass — exceeds the original target of 10.

3. Scope of the Delivered System

Delivered

●       Four user roles: Super Admin, Admin, Inventory Manager, Cashier — each with a server-enforced permission set, plus individually grantable permission overrides per staff member.

●       Product, category, and supplier management, including a full stock-movement ledger with reason codes (restock, damaged, breakage, count adjustment, supplier return, internal use).

●       Checkout/sales workflow that records a sale and deducts stock automatically, supporting cash (USD and KHR), KHQR bank-QR, card, and split payment across more than one method in the same sale.

●       Purchase orders with a Draft → Ordered → Received/Cancelled workflow that restocks inventory automatically on receipt.

●       Staff shift clock-in/out with cash-drawer reconciliation (Balanced / Overage / Shortage).

●       Loyalty customers with tiered discounts and a points program.

●       A team task board, analytics and reports with CSV/Excel export, and automated Telegram alerts for store activity.

Excluded from Scope

●       A certified bank payment gateway — the KHQR flow produces a real, scannable QR code for demonstration purposes but is not certified with any bank and cannot move real money.

●       Barcode hardware scanning was extended beyond the original plan: the delivered system supports live camera-based barcode scanning in addition to manual/keyboard entry.

●       Multi-branch / multi-store support.

Assumptions

●       The system supports a single shop/branch with one shared product catalog.

●       Users access the system through a standard web browser on desktop or mobile.

4. Target Users and Roles

Role

Description

Super Admin

Full system access, including editing the Roles & Permissions matrix and the Super Admin role itself.

Admin

Manages staff accounts, products, stock, and views full sales reports, but cannot edit the Super Admin role.

Inventory Manager

Manages products and stock levels, adjusts stock with a reason code, and manages purchase orders, but cannot manage user accounts or view overall sales figures.

Cashier

Processes checkout transactions, manages their own shift and cash drawer, and views current stock while selling.

Loyalty Customer (non-login)

A record the cashier can look up by phone number to apply a tier discount and award/redeem points; does not hold a login account.

Shop Owner (stakeholder)

Reviews sales reports but does not use the system directly.

Note: the original proposal planned an Admin Assistant role and a Customer login account. During implementation, the team consolidated Admin Assistant's intended duties into the Admin/Super Admin split (a simpler, equally effective permission boundary), and replaced a Customer login account with a Loyalty Customer record looked up by phone since the core need was letting a cashier recognise a repeat customer and apply their discount, not a public-facing customer portal. Both decisions are discussed further in Section 12.

5. System Features (As Delivered)

●       User authentication with salted password hashing and protected sessions.

●       Role-based authorization for Super Admin, Admin, Inventory Manager, and Cashier, plus individual permission overrides.

●       Product management module (create, read, update, deactivate) with barcode support.

●       Stock/inventory tracking with automatic deduction on each sale and a full audit ledger.

●       Checkout workflow supporting multiple items per sale, live camera barcode scanning, loyalty discounts and points, and cash / KHQR / card / split payment.

●       Product search and filter by name, SKU, or barcode.

●       Purchase orders with supplier selection and an automatic restock on receipt.

●       Staff shift clock-in/out with cash-drawer reconciliation.

●       A team task board with priority and due dates.

●       Sales report and analytics page showing daily totals, best sellers, and cashier productivity, with CSV/Excel export.

●       Automated Telegram alerts for new products, low stock, restocks, purchase orders received, new sales, refunds, new staff, new roles, and password resets.

6. OOP Design

Domain classes represent the core concepts of the POS system. Every domain object (Product, Sale, Cart, User, Role, and more) is implemented as a Python dataclass that protects its own state — for example, a Product cannot be saved with a negative price. Service classes coordinate business rules across repositories — most importantly, ensuring a sale and its stock deduction happen together inside one database transaction — and repository classes handle all MySQL access so that no SQL logic appears in the routes.

Domain / Model Classes (selected)

●       User (base identity fields) with role_name/role_id determining permissions; Role and Permission for the RBAC matrix.

●       Product: sku, barcode, name, category, price, cost, quantity_in_stock, low_stock_threshold.

●       Cart, CartLine, Discount, PricingSummary: the checkout pricing engine.

●       Sale, SaleItem, PaymentMethod (an enum): a completed transaction and its line items.

●       StockMovement, MovementReason (an enum with a direction rule per member): the inventory ledger.

●       PurchaseOrder, POStatus (an enum-driven state machine): Draft → Ordered → Received/Cancelled.

●       AttendanceSession, DrawerStatus (an enum): a staff shift and its cash-drawer reconciliation.

Service Classes (selected)

●       AuthService: handles login, logout, password verification, and permission checks across all roles.

●       CheckoutService: validates stock availability, creates a Sale with its SaleItems, and triggers stock deduction, all inside one transaction.

●       ProductService and PurchaseOrderService: manage product CRUD, stock adjustments, and the purchase-order lifecycle.

●       ReportService: aggregates sales data into daily totals, best-selling items, and cashier productivity.

Repository Classes

19 repository classes in total (ProductRepository, SaleRepository, UserRepository, and so on), each responsible only for MySQL queries for its entity. Every repository inherits from one abstract base class, BaseRepository(ABC, Generic[T]), because every repository genuinely performs the same basic operations — find, list, delete — making this the project's one deliberate inheritance relationship.

Key Relationships

●       A Sale has many SaleItems; each SaleItem references one Product.

●       Each completed Sale generates one or more StockMovement records reducing product quantity; each received PurchaseOrder generates StockMovement records increasing it.

●       Every Service is built through composition — constructed from the repositories and helpers it needs through its constructor — rather than through inheritance from a shared base service.

Figure 6.1 — Class relationships (representative slice)

7. System Architecture

The system follows a strict four-layer architecture so that each part has a single responsibility. A request only ever flows downward through the layers, and a response only ever flows back up — no layer is ever skipped.

Browser  →  Flask Routes/Blueprints  →  Services  →  Repositories  →  MySQL Database

●       Routes: receive HTTP requests (e.g. a checkout submission), call exactly one service method, and return a rendered template or redirect. Routes contain no business logic and no SQL.

●       Services: apply business rules — for example, CheckoutService rejects a sale if the requested quantity exceeds available stock, and wraps a sale and its stock deduction in one transaction.

●       Repositories: execute parameterized SQL queries against MySQL and return domain objects built through each model's from_row() classmethod.

●       Templates: Jinja2 pages render product lists, the checkout screen, and reports; no business logic is placed in templates.

Figure 7.1 — Four-layer request/response architecture

8. Database Design

The database is normalized, with foreign keys enforcing valid relationships between users, products, sales, sale items, stock movements, and every other entity. The final schema has 23 tables in total — considerably more than the original plan — to support purchase orders, staff shifts and cash drawers, held orders, tasks, and an audit log alongside the originally planned core tables.

Table

Key Fields / Relationship

users

id (PK), name, email (unique), password_hash, role_id (FK), shift_id (FK), is_active

roles / permissions / role_permissions

Role and permission catalog with a junction table defining which permissions each role holds

products

id (PK), sku, barcode, name, category_id (FK), supplier_id (FK), price, cost, quantity_in_stock

stock_movements

id (PK), product_id (FK), change_amount, reason (ENUM), created_by (FK)

sales / sale_items

sales: id (PK), cashier_id (FK), customer_id (FK), attendance_id (FK), payment_method, total_amount — sale_items: sale_id (FK), product_id (FK), quantity, unit_price

purchase_orders / purchase_order_items

id (PK), supplier_id (FK), status (ENUM: draft/ordered/received/cancelled)

attendance / cash_movements

One row per staff shift with opening_float, expected_cash, counted_cash, cash_difference; cash_movements is an append-only per-shift cash log

customers

id (PK), phone (unique), name, points, total_spent — the loyalty program

 

All queries use parameterized statements to prevent SQL injection, and no plain-text passwords are stored. Guarded UPDATE statements (for example, WHERE quantity_in_stock + %s >= 0) prevent stock from ever going negative even under concurrent sales, without needing an application-level lock.

Figure 8.1 — Simplified entity-relationship diagram (core tables)

9. Implementation

Package Structure

smartpos_minimartsystem/
├── app/
│ ├── __init__.py # create_app() application factory
│ ├── config.py # Config / TestConfig (reads .env)
│ ├── extensions.py # LoginManager, CSRFProtect, get_db() (PyMySQL), transaction()
│ ├── models/ # POPO dataclasses with from_row() — no DB access (60+ classes)
│ │ ├── auth/ inventory/ sales/ staff/ reports/
│ ├── repositories/ # the ONLY place SQL is written (19 classes, one per entity)
│ ├── services/ # business rules and workflows (20 classes)
│ ├── routes/ # thin Flask blueprints — 15 controllers
│ ├── forms/ # request parsing + server-side validation
│ ├── utils/ # decorators, password hasher, image storage, CSV/XLSX/barcode
│ ├── templates/ # 40 Jinja2 pages, violet/lime theme
│ └── static/ # css/style.css, logo, uploads/
├── sql/ # schema.sql (23 tables) and seed.sql (demo data)
├── tests/ # pytest suite with in-memory fake repositories
├── docs/ # architecture.md, database.md, testing.md, user_guide.md
├── scripts/ # reset_demo_passwords.py, backup_db.sh, restore_db.sh
├── .env / .env.example
├── run.py
├── requirements.txt
└── README.md

Security Measures Implemented

●       Passwords are salted and hashed with Werkzeug's PBKDF2 implementation — never stored in plain text.

●       Every state-changing form carries a CSRF token, checked by Flask-WTF.

●       All SQL is parameterized — user input is never concatenated into a query string.

●       Server-side permission checks gate every sensitive route; the interface hiding a button is a convenience, not the security boundary.

Screenshots

Screenshot 1 — Login page

Screenshot 2 — Dashboard

Screenshot 3 — Loyalty Customers — register a member

Screenshot 4 — POS Checkout — product grid, cart, and split payment

Screenshot 5 — KHQR payment pop-up

Screenshot 6 — Printable receipt

Screenshot 7 — Products & Stock

Screenshot 8 — Product categories

Screenshot 9 — Suppliers

Screenshot 10 — Team tasks

Screenshot 11 — Staff Management, with the Telegram alert banner

Screenshot 12 — Roles & Permissions — role management

Screenshot 13 — Roles & Permissions — configuring a role's permissions

Screenshot 14 — Roles & Permissions — bulk permission matrix

Screenshot 15 — Work shifts

Screenshot 16 — Cash drawer audit

Screenshot 17 — My Profile

10. Testing and Results

Testing approach: core business rules (stock deduction accuracy, checkout totals across all four payment methods, and role-based access) were verified through service-level automated tests using in-memory fake repositories, plus documented manual test cases covering every role and workflow end to end.

#

Test Case

Expected Result

Result

1

Create a product with price = 0

Rejected: 'Selling price must be greater than zero.'

Pass

2

Apply a 60% manual discount

Rejected — discount capped at 50%

Pass

3

Complete a cash sale for more than the total

Change calculated correctly in USD or KHR

Pass

4

Split payment: card + QR + cash together

Sale recorded; only the cash share reaches the drawer

Pass

5

Refund part of a split-tender sale

Only the proportional cash share leaves the drawer

Pass

6

Deactivate a staff member with an open shift

Rejected until the shift is closed

Pass

7

Receive the same purchase order twice

Second attempt rejected — already processed

Pass

8

Edit the Super Admin role's permissions as a plain Admin

Rejected — Super Admin only

Pass

9

Sell a product down to 0 stock, then sell one more

Second sale rejected — insufficient stock

Pass

10

Log in with the wrong password

Generic 'Invalid email or password' (no account enumeration)

Pass

Total automated test count: 49 test cases across model, service, and route-level test files. A full manual walkthrough of every role and every workflow was also completed, returning zero server errors on the final pass.

11. Changes from the Original Proposal

Development naturally surfaced a few places where the original plan was adjusted for a cleaner or more realistic result:

Proposed

Delivered Instead

Reason

5 roles including Admin Assistant and Customer login

4 roles (Super Admin, Admin, Inventory Manager, Cashier) plus a non-login Loyalty Customer record

Admin Assistant's intended duties fit naturally inside the Admin/Super Admin permission split; a public customer login was not needed to meet the core requirement of recognising a repeat customer at checkout.

Single cash payment path

Cash (USD/KHR), KHQR, card, and split payment across methods

Reflects Cambodia's real point-of-sale payment mix more accurately than the original single-method plan.

Manual barcode entry only

Manual entry plus live camera barcode scanning

A real camera scanner was a natural, low-cost addition once the checkout flow supported AJAX updates.

Basic sales report page

Full analytics dashboard, CSV/Excel export, and automated Telegram alerts

Store owners asked for visibility into activity without needing to log in and check manually.

12. Challenges and Resolutions

Challenge

Resolution

Ensuring a sale and its stock deduction always happen together, even under concurrent sales

Wrapped sale creation and stock deduction in a single service-level transaction, using a guarded UPDATE so stock can never go negative

Seed data failed to import (foreign-key ordering error)

Reordered the seed script so parent tables (attendance) load before dependent ones (sales)

A split-tender refund initially removed too much cash from the drawer

Refunds on a split sale now return only the proportional cash share

Some pop-up dialogs were briefly hard to read

Traced to a CSS class-name mismatch and corrected it

Uneven contribution risk among 4 team members under time pressure

Assigned clear weekly tasks and tracked progress through Git commit history and short check-ins

13. Conclusion and Future Work

SmartPOS delivers a complete, working, role-based Point-of-Sale and Inventory Management System with a strict four-layer OOP architecture, a 23-table normalized MySQL database, dual-currency and split-tender checkout, live camera barcode scanning, a full staff shift and cash-drawer accountability system, and automated Telegram operational alerts verified by 49 automated tests plus a full manual walkthrough of every workflow. Every objective set out in the original proposal was met, and the delivered scope substantially exceeds the original 5-week minimum plan.

Limitations

●       The KHQR payment flow produces a real, scannable QR code but is a demonstration only — it is not certified with any bank and cannot move real money.

●       The system is designed for a single store; multi-branch stock transfer is not supported.

Future Work

●       Integrate a certified bank KHQR merchant API for real payment confirmation.

●       Add new permission on the UI

●       Add multi-branch inventory with stock transfer between locations.

●       Add a native mobile companion app for stock counts and quick lookups.

Appendix

A. SQL Scripts

·        The full schema (sql/schema.sql, 23 tables with constraints) and seed data (sql/seed.sql) are included in the project submission alongside this report.

B. Sample Data

·        The seed data includes 100 products across 6 categories, 3 suppliers, 4 staff roles, 5 staff accounts, 4 loyalty customers, and 60 sample sales spread across the last 30 days.

C. User Manual

·       A full user guide is included in the project submission (docs/user_guide.md), covering sign-in, running a shift, checkout, refunds, inventory, staff, roles, tasks, and reports.


 

D. Team Contribution

Contributors

Student In

Chhum Chheanglim

Database Design, UI/UX, Report

Kang Soksambathratanak

Coding, Backend, API implementation into the project

Heng Longmeng

 Coding, API Design

Lim Meng Huy

System Demonstration, Coding

 


 

14. References

●       Flask Documentation — https://flask.palletsprojects.com/

●       MySQL 8.0 Reference Manual — https://dev.mysql.com/doc/

●       Jinja2 Documentation — https://jinja.palletsprojects.com/

●       PyMySQL Documentation — https://pymysql.readthedocs.io/

●       Professor Instruction

 

 

OOP_Final_Presentation_Slide.pdf
PDF ឯកសារ
ទាញយក អាន
ចែករំលែក
រក្សាទុក
ការផ្សព្វផ្សាយ
ការផ្សព្វផ្សាយ
មតិយោបល់ 2
ចូលគណនី ដើម្បីបញ្ចេញមតិ
Very convenience, and practical. Love it🫰
1 0
27 Oct 17:05
Nice one
0 0