លំហសិក្សាកម្ពុជា
V1.0
Small and Medium Enterprises (SMEs) that sell vehicles need an effective way to manage vehicle inventory and sales records. Some businesses may use manual records, spreadsheets, or separate files to manage their daily operations. This can make it difficult to track available and sold vehicles, record stock movements, manage sales, and retrieve important information. This project developed a web-based Vehicle Inventory and Sales Management System for SMEs. The system centralizes vehicle inventory, stock movements, customers, sales, and invoices in one application. It also implements Role-Based Access Control (RBAC) to restrict system functions according to user roles. The system was developed using Python and Flask with MySQL as the database. Object-Oriented Programming principles were applied through domain models, services, repositories, and routes. The resulting system provides an organized platform for managing vehicle inventory and sales operations efficiently.
Advanced Object-Oriented Programming
R&D Project Report
Vehicle Inventory and Sales Management System for SMEs (IGNITE)
Prepared by: Lay Katsrieng, Sour Chansopanha, Heang Sovanara
Lecturer: SEK SOCHEAT
Submission Date: September 25, 2026
Small and medium-sized vehicle-selling enterprise should implement organized software to store records about the sold vehicles, customers, sales, and invoices. Otherwise, the workers should spend a considerable amount of time retrieving information from various file formats and spreadsheets. The application was built to provide a centralized location and reduce the overall amount of time spent on processing the data. IGNITE is a web application that allows its users to manage the vehicle stock, monitor the customers, sales, and invoices in a unified interface. The software was developed with a browser-based Python framework and a relational database. The database is needed to ensure that every car is unique and not sold twice.
Separate entries may become inconsistent if one employee records a sale while another inventory list still shows the vehicle as available. Adding and removing stock may also become hard to track if their histories are not tied to the vehicle. Information regarding customers, sale amounts, and invoices may involve repeated data entry, which could result in errors.
Without controlled accounts, employees may have access to features outside of their responsibilities. A manual sales summary would also need to tie together records that may not necessarily share the same format. The project addresses these problems in linking, accounting, and automating the major aspects of a sale without measuring the decreased processing time or business errors because a before-and-after evaluation was not supplied.
The objectives of this project are to manage individual vehicle records by allowing users to create, list, search, filter, view and edit vehicle information while preserving historical records through deactivation. The system also aims to track stock-in, stock-out and adjustment activities for each vehicle and record the responsible operator. It processes sales by completing the transaction, updating vehicle availability, recording the stock-out movement and generating an invoice within a single database transaction. User access is controlled through authentication and role-based permissions. Finally, the project applies a layered object-oriented design that separates domain models, services, repositories, routes and database connection management.
The IGNITE system is designed for daily use within a single vehicle dealership. The system’s end-users are Admin, Manager, and Sales Staff, each with specific features available based on their permission level. The Manager is responsible for inventory, while Sales Staff handles customers, sales, and invoices.
The project covers vehicle records, inventory, customers, sales, invoices, and reports. The system can complete a sale, update inventory, record a stock-out movement, and generate an invoice showing the amount owed in USD. Features outside the project scope include online payments, instalments, refunds, multiple branches, and full accounting.
The system includes the following functions:
The system provides secure user login and logout functions. Access to system features is controlled using Role-Based Access Control (RBAC). The system uses three main roles:
Admin
Manager
Sales Staff
Users are assigned roles through the User Roles structure. Each role has a set of permissions that determines which system functions the user can access. Permissions are assigned to roles through the Role Permissions structure.
Authorized users can:
Add vehicle records
View vehicle information
Update vehicle information
Delete unused vehicles or deactivate those with transaction history
Search and filter vehicles
Check vehicle status
Vehicle status includes:
Available
Reserved
Sold
Inactive
The system records important inventory movements, including:
Stock In
Stock Out
Inventory Adjustment
Each movement is linked to a vehicle and recorded with relevant details.
The system allows authorized users to:
Add customers
View customer information
Update customer records
Search customer records
Sales Staff can:
Select an available vehicle
Select or add a customer
Create a sales record
Record the sale amount
Complete the sale
When a sale is completed, the system updates the vehicle status and creates a stock-out record.
The system:
Generates invoice records
Assigns invoice numbers
Displays invoice details
Provides a print-friendly invoice page
The system provides:
Available vehicle reports
Sold vehicle reports
Sales summaries
Stock movement history
To keep the project manageable within one term, the first version of the system does not include:
Online payment gateways
GPS vehicle tracking
Mobile applications
Multi-branch synchronization
The system currently runs only on a local server and is not deployed for online access.
Full accounting and tax management
Integration with external government or vehicle registration systems
The system is built utilizing modern web and database technologies:
Python supports the project’s domain records, business services, validation and tests. Flask provides routing, request handling and an explicit application object; its factory pattern supports constructing separate application instances for testing.
IGNITE implements create_app in app/init.py and keeps the local launch entry point in app.py. Jinja renders server-side HTML, while CSS and vanilla JavaScript implement the interface. This stack keeps the project runnable without a separate frontend build process. It also makes the separation between request handling and business operations visible for an Advanced OOP course.
The application uses direct MySQL queries through repositories rather than an object-relational mapper. Consequently, transaction boundaries and SQL mapping are explicit responsibilities of the project code.
MySQL stores ten tables using InnoDB. Foreign keys connect vehicles, customers, operators, sales and invoices; junction tables implement the many-to-many access relationships. Unique constraints prevent duplicate vehicle codes and duplicate sales of the same vehicle. CHECK constraints restrict status values and monetary relationships.
A normal read is not sufficient when two requests may sell the same vehicle. MySQL locking reads using SELECT ... FOR UPDATE lock selected rows within a transaction. IGNITE combines these locks with a unique sales.vehicle_id constraint and rollback handling. The database layer uses READ COMMITTED isolation for service transactions. These mechanisms are verified by the concurrent-sale and rollback tests, rather than assumed from the interface alone.
Used in the presentation layer to create the web interface that users interact with through a browser.
The system relies heavily on advanced OOP concepts to separate responsibilities:
Flask routes process requests, check permissions and call the appropriate services. The service layer applies business rules, such as ensuring that only available vehicles can be sold. The repository layer retrieves and saves records through SQL queries, while the database layer manages connections, transactions and persistent storage.
Domain models—including Vehicle, Customer, Sale, Invoice, StockMovement, User, Role and Permission—support these layers by representing system records. Some read-only routes access repositories directly. During sale completion, the service saves the sale, vehicle status, stock-out movement and invoice within one transaction.
Classes such as Vehicle, Customer, Stock_Movement, Sale, Invoice, User, Role and Permission represent the system’s main entities. The Sale_Amounts value object handles decimal price and discount calculations.
Service classes manage business rules and workflows, Repository classes handle SQL queries and record mapping, and the Database class manages connections and transactions. Flask routes handle web requests, while Jinja templates display the interface.
IGNITE is designed to centralize vehicle inventory and sales operations for a single dealership. The system allows authorized users to manage vehicles and customers, track stock movements, complete sales, generate invoices and view reports.
Its main functional requirements are:
Authenticate users and control access through role-based permissions.
Create, view, search, filter and update vehicle records.
Maintain customer information and related sales history.
Record stock-in, stock-out and adjustment activities.
Sell only available vehicles and prevent duplicate sales.
Generate an invoice for each completed sale.
Provide inventory summaries and sales reports.
Allow administrators to manage accounts and role permissions.
The nonfunctional requirements include persistent storage, accurate monetary calculations, consistent transactions, input validation and maintainable code.
The system has three main user roles. Their default responsibilities are shown below.
Manage accounts and permissions, maintain records and access all operational modules.
Manage vehicles, inventory and customers; complete sales; view invoices and reports.
View vehicles, manage customers, complete sales and access invoices.
One of the key use cases involves closing a car deal. The user selects a customer who is currently active and also an available car. He then verifies the price, discount and sends for the transaction to be completed. The system checks the validity of the data provided, makes the sale, updates the car's status to SOLD, creates a stock out movement and prepares an invoice.
The class diagram shows the main classes Vehicle, Customer, Sale, Invoice, Stock_Movement, User, Role and Permission and their relationships. Service classes manage business rules, while repository classes handle database operations.
Use the dark blue class diagram shown in the report before the ERD.
The Entity Relationship Diagram (ERD) shows the ten database tables and their connections through primary and foreign keys. Sales link vehicles, customers and users; invoices reference sales; and stock movements reference vehicles and users. The user_roles and role_permissions tables connect accounts to their access permission.
Use the MySQL database diagram showing the 10 connected tables.
IGNITE follows a layered architecture that separates the user interface, request handling, business rules and database operations. This structure makes the system easier to maintain, test and extend because each layer has a clear responsibility.
Presentation → Flask Routes → Services → Repositories → MySQL
The presentation layer uses Jinja HTML templates, CSS and JavaScript to show forms, vehicle listings, dashboards and invoices. Flask routes receive browser requests, validate submitted data, verify authentication and permissions, and call the appropriate service.
The service layer handles the rules and steps that the business needs. For instance, SalesService checks if a vehicle is available and works on finishing the sale. The repository layer executes SQL queries and maps database rows into records used by the application. The Database class takes care of the connections and the steps that happen when data is changed while MySQL stores all the information using tables that are connected and follow rules to keep everything correct.
Domain models like Vehicle, Customer, Sale and Invoice are the pieces of data that the system works with. When a sale is completed, the sale record, vehicle status, stock-out movement, and invoice are saved within a single transaction. Either all changes succeed or all are rolled back, keeping the database consistent.
The IGNITE application adopts a layered architecture using a clean Flask directory layout. High-level domain logic, repository data access, web presentation, and database persistence layers are isolated without reliance on an ORM:
vehicle_sales_system/
├── app/
│ ├── init.py
│ ├── models/
│ │ ├── vehicle.py
│ │ ├── customer.py
│ │ ├── sale.py
│ │ ├── invoice.py
│ │ ├── stock_movement.py
│ │ ├── user.py
│ │ ├── role.py
│ │ ├── permission.py
│ │ └── money.py
│ ├── repositories/
│ │ ├── base.py
│ │ ├── mysql.py
│ │ ├── vehicle_repository.py
│ │ ├── customer_repository.py
│ │ ├── sale_repository.py
│ │ ├── invoice_repository.py
│ │ ├── stock_repository.py
│ │ ├── user_repository.py
│ │ ├── role_repository.py
│ │ ├── permission_repository.py
│ │ └── report_repository.py
│ ├── routes/
│ │ ├── init.py
│ │ ├── auth_routes.py
│ │ ├── dashboard_routes.py
│ │ ├── vehicle_routes.py
│ │ ├── customer_routes.py
│ │ ├── inventory_routes.py
│ │ ├── sale_routes.py
│ │ ├── invoice_routes.py
│ │ ├── report_routes.py
│ │ ├── user_routes.py
│ │ ├── role_routes.py
│ │ ├── shared_routes.py
│ │ ├── common.py
│ │ ├── form_helpers.py
│ │ └── resource_config.py
│ ├── services/
│ │ ├── auth_service.py
│ │ ├── user_service.py
│ │ ├── vehicle_service.py
│ │ ├── customer_service.py
│ │ ├── inventory_service.py
│ │ ├── sales_service.py
│ │ ├── report_service.py
│ │ └── vehicle_photo_service.py
│ ├── static/
│ ├── templates/
│ └── database.py
├── database/
└── README.md
We separated the project into routes, services, repositories and models. Each layer has a clear responsibility, making the code easier to understand, test and maintain.
SQL queries are handled by repository classes. Repositories also map database columns, such as vehicle_id, to model attributes such as id.
Completing a sale creates the sale, invoice and stock-out movement and updates vehicle availability within one transaction. If a step fails, all related changes are rolled back.
Row locking and a unique database constraint prevent the same vehicle from being sold twice, including when two users submit a sale at the same time.
Users receive roles through user_roles, and roles receive permissions through role_permissions. The server checks permissions before allowing protected actions.
We use Python’s Decimal type for prices, discounts and totals to avoid floating-point rounding errors. Validation rejects negative amounts and discounts greater than the selling price.
Uploaded photos are checked for supported formats, file size and image content. Replaced photos are removed only after the database update succeeds, helping prevent lost images.
Validation: Check login, inactive accounts and restricted actions.
Result: Passed
Validation: Validate forms, unique fields, searching and filtering.
Result: Passed
Validation: Confirm one sale creates one invoice and stock-out movement.
Result: Passed
Validation: Reject duplicate sales and roll back changes when an operation fails.
Result: Passed
Validation: Verify stock-in, stock-out and adjustment rules.
Result: Passed
Validation: Check file formats, size limits, replacement and safe cleanup.
Result: Passed
The system was tested to verify that the main functions work correctly and consistently. Authentication tests checked login, inactive accounts, and restricted actions. Vehicle and customer tests verified form validation, unique fields, searching, and filtering. Inventory tests covered stock-in, stock-out, and adjustment rules.
Sales and invoice tests confirmed that a completed sale creates one invoice, records a stock-out movement, and changes the vehicle status to SOLD. Transaction tests also verified that duplicate sales are rejected and that all related changes are rolled back if an operation fails.
Vehicle photo tests checked supported file formats, file-size limits, image replacement, preview behavior, and safe file cleanup. These tests helped confirm that the main workflows and validation rules of the system operate as expected.
Several issues were identified and corrected during development and testing. The system prevents duplicate vehicle sales using row locking and database constraints. Sale-related updates are completed within one transaction so incomplete records are not stored if part of the process fails.
An issue where an empty vehicle plate number could display as the text None was corrected so empty values remain blank. Vehicle photo preview handling was also improved so valid JPG, JPEG, PNG, and WebP files are accepted consistently while still applying file-size and image-content validation.
Security measures include password hashing, role-based permissions, CSRF protection, parameterized SQL queries, and server-side validation. Additional checks prevent invalid uploads and protect important administrative accounts. For future online deployment, the system would still require HTTPS, login rate limiting, a restricted database account, and tested backup procedures.
The web-based Vehicle Inventory and Sales Management System was successfully designed and developed. The system centralizes vehicle records, accurately tracks stock movements, and securely processes sales transactions. By implementing a layered architecture with Domain Models, Services, and Repositories, the project successfully applied advanced Object-Oriented Programming principles to create a scalable and maintainable application. Furthermore, the integration of Role-Based Access Control ensures that business data is protected and only accessible to authorized personnel.
The IGNITE project delivered a web-based application that allows for the centralized storage of vehicle inventory, customer data, stock movements, sales, and invoices. The application uses role-based access control and provides varied user permissions for Admin, Manager, and Sales Staff. The system allows completing a sale and updating the vehicle stock, recording a stock-out movement, and generating an invoice in one transaction.
The project also involved designing the application using a layered object-oriented approach, implementing dashboards and reports, and enabling photo upload with validation. The application underwent a comprehensive automated test suite covering core workflows, validation rules, permissions, database transactions, and data accuracy.
To keep the initial project manageable, certain advanced features were excluded from this version. Future improvements for the system could include:
Integrate online payment gateways.
Export monthly and yearly reports to Excel.
Implement GPS vehicle tracking.
Deploy the system for online access.
Develop a companion mobile application.
Add multi-branch synchronization and full accounting/tax management.
Apply AI-based vehicle price predictions.
This is the SQL screenshot showing the access-related tables such as roles, permissions, role_permissions, users and user_roles.
.
Use Python and MySQL 8.0.16 or later, then open a terminal in the project folder.
Create a virtual environment and install requirements.txt. For a fresh clone, copy .env.example to .env.
Configure the MySQL host, port, database name, username, and password through .env according to the local environment.
Then run:
python -m venv .venv
..venv\Scripts\python.exe -m pip install -r requirements.txt
..venv\Scripts\python.exe database/setup.py
..venv\Scripts\python.exe app.py
Open http://127.0.0.1:5000 in the browser and keep the terminal running. Configure the MySQL host, port, database name, username, and password through .env according to the local environment. Normal startup does not reset records.
The team log records each member’s contribution to the IGNITE project.
Vehicles, inventory, sales, invoices, dashboard, reports, system testing
Code, Git commits
Database design, login, users, roles and permissions ERD, SQL files, Git commits
Prepared the final report and presentation slides
មតិយោបល់ 0