លំហសិក្សាធិការកម្ពុជា
V1.0
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 an Admin manage products and view sales reports, a Cashier process sales at checkout, and a Customer hold a simple account to view their own purchase history. The system applies Object-Oriented Programming through a layered architecture that separates domain models, business services, and database repositories. Core features include role-based authentication, product and stock management, a sales/checkout workflow that automatically updates inventory, product search, and a sales report page. Given a 5-week development window, the team will build the minimum required features first and treat extras such as discounts and customer accounts as optional stretch goals. The expected output is a working Flask application backed by a MySQL database, supported by test cases and a live demonstration of a full sale transaction.
Advanced OOP with Python
Python + Flask + MySQL
Project
Proposal
SmartPOS: A Web-Based Point-of-Sale and Inventory
Management System
|
Field |
Student
Input |
|
Project
Title |
SmartPOS:
A Web-Based Point-of-Sale and Inventory Management System |
|
Team
Members |
Lim
MengHuy, Heng Longmeng, Chhum Chheanglim, Kang
Soksambathratanak |
|
Course /
Class |
Advanced
OOP with Python |
|
Lecturer |
SEK
SOCHEAT |
|
Semester
/ Year |
Semester
1, Year 2 (2026–2027) |
|
Submission
Type |
Proposal |
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 an Admin manage products and view
sales reports, a Cashier process sales at checkout, and a Customer hold a
simple account to view their own purchase history. The system applies
Object-Oriented Programming through a layered architecture that separates
domain models, business services, and database repositories. Core features
include role-based authentication, product and stock management, a
sales/checkout workflow that automatically updates inventory, product search,
and a sales report page. Given a 5-week development window, the team will build
the minimum required features first and treat extras such as discounts and
customer accounts as optional stretch goals. The expected output is a working
Flask application backed by a MySQL database, supported by test cases and a
live demonstration of a full sale transaction.
Many small shops track products and
sales using paper receipts or basic spreadsheets managed by the shop owner.
Cashiers are affected because they have no quick way to check whether an item
is in stock while serving a customer, and owners are affected because they
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 at the end of
the day. A web-based POS system is needed so that every sale automatically
updates stock and produces an accurate, real-time sales record.
|
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 automatically deducts stock at the point of sale and
gives the owner an accurate, real-time sales and inventory report. |
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.
●
Build
a secure authentication and role-based authorization system for Admin, Admin
Assistant, Inventory Manager, Cashier, and Customer roles.
●
Design
and implement product and stock management with full CRUD functionality.
●
Implement
a checkout/sales workflow that records a sale and automatically deducts stock
in real time.
●
Design
a normalized MySQL database supporting products, sales, stock movements, and
users.
●
Apply
a layered OOP architecture (models, services, repositories) and verify core
business rules with test cases within the 5-week timeline.
|
Objective |
Measurable
Success Criterion |
|
Authentication
and role-based access |
Users
can log in/log out; each of the 5 roles (Admin, Admin Assistant, Inventory
Manager, Cashier, Customer) can only access the routes and actions permitted
to that role. |
|
Product
and stock management |
Admin
can create, view, update, and remove products; stock quantity updates
automatically after each sale. |
|
Checkout
/ sales workflow |
Cashier
can create a sale with multiple items, system rejects sales that exceed
available stock. |
|
Clean
OOP layers |
At least
5 domain classes, 3 services, and 3 repositories, each with a single clear
responsibility. |
|
MySQL
database |
ERD, SQL
schema, constraints, and seed data covering users, products, sales, and stock
movements. |
|
Testing |
At least
10 documented test cases covering stock deduction, checkout totals, and
access control. |
●
How
can a sale transaction and stock deduction be updated together so stock counts
never fall out of sync with recorded sales?
●
What
database design best supports products, sales, and stock movements while
preventing a sale from completing when stock is insufficient?
●
How
does separating the system into model, service, and repository layers improve
the maintainability of the checkout workflow compared to a single-file
implementation?
●
Given
only 5 weeks, what minimum feature set proves the OOP design and checkout
workflow work correctly without risking incomplete delivery?
●
Five
user roles: Admin, Admin Assistant, Inventory Manager, Cashier, Customer.
●
Product
management (create, update, remove, view) by Admin.
●
Checkout/sales
workflow by Cashier that records a sale and deducts stock automatically.
●
Stock/inventory
tracking with low-stock visibility.
●
Product
search/filter by name or category.
●
Sales
report/summary page for Admin (daily totals, best-selling items).
●
Percentage
discounts applied at checkout.
●
Customer
accounts with purchase history lookup.
●
Online
payment gateway integration.
●
Barcode
hardware scanning (manual product code entry only).
●
Multi-branch/multi-store
support.
●
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.
|
Role |
Description |
|
Admin |
Full
system access: manages user accounts, products, stock, and views sales
reports. |
|
Admin
Assistant |
Supports
the Admin with day-to-day tasks — views sales reports and manages cashier
accounts, but cannot delete products or change system-wide settings. |
|
Inventory
Manager |
Manages
products and stock levels (add/update/remove products, adjust stock, view
stock reports), but cannot manage user accounts or view overall sales
figures. |
|
Cashier |
Processes
checkout transactions and views current stock while selling. |
|
Customer |
Holds a
basic account to view their own purchase history (stretch goal). |
|
Shop
Owner (stakeholder) |
Reviews
sales reports but does not use the system directly. |
●
User
authentication with password hashing and session management.
●
Role-based
authorization for Admin, Admin Assistant, Inventory Manager, Cashier, and
Customer.
●
Product
management module (create, read, update, delete).
●
Stock/inventory
tracking with automatic deduction on each sale.
●
Checkout
workflow supporting multiple items per sale and total calculation.
●
Product
search and filter by name or category.
●
Sales
report page showing daily totals and stock levels.
●
(Stretch)
Percentage discount at checkout and customer purchase history.
Domain classes represent the core
concepts of the POS system. A base User class holds shared attributes (name,
email, password hash, role) with Admin, Admin Assistant, Inventory Manager,
Cashier, and Customer as specialized subclasses, each exposing only the
permissions relevant to that role. Service classes coordinate business rules
across repositories — most importantly, ensuring a sale and its stock deduction
happen together — and repository classes handle all MySQL access so that no SQL
logic appears in the routes.
●
User
(base class): id, name, email, password_hash, role.
●
Admin,
AdminAssistant, InventoryManager, Cashier, Customer (extend User):
role-specific attributes and permitted actions.
●
Product:
id, name, category, price, quantity_in_stock.
●
Sale:
id, cashier_id, customer_id, total_amount, created_at.
●
SaleItem:
id, sale_id, product_id, quantity, unit_price.
●
StockMovement:
id, product_id, change_amount, reason, created_at.
●
AuthService:
handles login, logout, password verification, and role-permission checks across
all 5 roles.
●
SalesService:
validates stock availability, creates a Sale with its SaleItems, and triggers
stock deduction.
●
InventoryService:
manages product CRUD and records StockMovement entries.
●
ReportService:
aggregates sales data into daily totals and best-selling items.
●
UserRepository,
ProductRepository, SaleRepository, StockMovementRepository — each responsible
only for MySQL queries for its entity.
●
A
Sale has many SaleItems; each SaleItem references one Product.
●
Each
completed Sale generates one or more StockMovement records reducing product
quantity.
●
Admin,
Admin Assistant, Inventory Manager, Cashier, and Customer all inherit shared
identity/authentication behavior from User, differing only in which actions
their role permits.
The system follows a layered
architecture so that each part has a single responsibility:
Browser →
Flask Routes/Blueprints → Services
→ Repositories →
MySQL Database
●
Routes:
receive HTTP requests (e.g. checkout submission), call the appropriate service,
and return a rendered template or JSON response.
●
Services:
apply business rules — for example, SalesService rejects a checkout if
requested quantity exceeds available stock.
●
Repositories:
execute parameterized SQL queries against MySQL and return domain objects.
●
Templates:
Jinja2 pages render product lists, the checkout screen, and reports; no
business logic is placed in templates.
The
database will be normalized, with foreign keys enforcing valid relationships
between users, products, sales, sale items, and stock movements.
|
Table |
Key Fields / Relationship |
|
users |
id (PK), name,
email (unique), password_hash, role (admin / admin_assistant /
inventory_manager / cashier) |
|
roles |
id (PK), name
(admin / admin_assistant / inventory_manager / cashier) |
|
permissions |
id (PK), name
(e.g. manage_users, manage_products, adjust_stock, process_sale,
view_reports, manage_cashier_accounts) |
|
role_permissions |
role_id (FK →
roles.id), permission_id (FK → permissions.id) — junction table defining
which permissions each role holds |
|
products |
id (PK), name,
category, price, quantity_in_stock |
|
sales |
id (PK),
cashier_id (FK → users.id), discount_percent, payment_method, total_amount,
created_at |
|
sale_items |
id (PK), sale_id
(FK → sales.id), product_id (FK → products.id), quantity, unit_price |
|
stock_movements |
id (PK),
product_id (FK → products.id), change_amount, reason, created_at |
Role
Table
|
Role |
Assigned
Permissions |
|
Admin |
manage_users,
manage_products, adjust_stock, process_sale, view_reports,
manage_cashier_accounts (all permissions) |
|
Admin
Assistant |
view_reports,
manage_cashier_accounts |
|
Inventory
Manager |
manage_products,
adjust_stock |
|
Cashier |
process_sale |
An
Entity-Relationship Diagram (ERD) will be produced during development to show
cardinality (one-to-many between sales and sale_items, and between products and
stock_movements). All queries will use parameterized statements to prevent SQL
injection, and no plain-text passwords will be stored.
With
only 5 weeks remaining, the team will follow a compressed sprint schedule and
lock the core feature set from Section 5 by the end of Week 1 to avoid scope
creep.
|
Week |
Planned Task |
|
Week 1 |
Finalize scope,
design ERD and domain classes, set up Git repository, Flask project
structure, and MySQL schema. |
|
Week 2 |
Implement
authentication, role-based access, and Product management (Admin CRUD). |
|
Week 3 |
Implement the
checkout/sales workflow (Cashier) with automatic stock deduction, percentage
discount, and QR code payment display. |
|
Week 4 |
Implement
product search/filter and the sales report page; begin the exportable report
stretch goal if on schedule. |
|
Week 5 |
Write and run
test cases, fix bugs, prepare screenshots, final report, and defense
presentation/demo. |
Testing
approach: core business rules (stock deduction accuracy, checkout total
calculation, and role-based access) will be verified through service-level
tests and documented manual test cases with screenshots.
● A
working Flask web application connected to a MySQL database, deployable and
demonstrable.
● A
normalized database schema with seed data for users, products, sales, and stock
movements.
● At
least 10 documented test cases with evidence and screenshots.
● A
final report describing the design, implementation, and testing process.
● A
live demonstration showing a complete sale transaction and its effect on stock
and reports.
|
Risk / Ethical Concern |
Mitigation |
|
Only 5 weeks
available, high risk of incomplete features. |
Lock the core
scope in Section 5 during Week 1, including discount and QR payment; treat
only the exportable report as an optional stretch goal. |
|
4 distinct roles
increase access-control testing effort within a short timeline. |
Keep Admin
Assistant and Inventory Manager as permission subsets of Admin (no new tables
or features) and reuse a single role-check pattern across all routes. |
|
Incorrect stock
deduction could show false inventory data. |
Wrap sale
creation and stock deduction in a single service-level operation and cover it
with dedicated test cases. |
|
Passwords or
account credentials could be exposed. |
Store only
hashed passwords (e.g., bcrypt) and never log plain-text credentials. |
|
Uneven
contribution among 4 team members under time pressure. |
Assign clear
weekly tasks and track progress through Git commit history and short daily
check-ins. |
● Flask
Documentation — https://flask.palletsprojects.com/
● MySQL
8.0 Reference Manual — https://dev.mysql.com/doc/
● Jinja2
Documentation — https://jinja.palletsprojects.com/