TIET Patiala · UCS310 Database Management Systems · Sub Group 2C34 · AY 2025-26
Team: Ishant Mehndiratta (1024030525) · Satyam Tiwari (1024030088) · Anshaj (1024030494)
Guide: Dr. Shashank Singh
- Node.js v18+ → https://nodejs.org
- MySQL Server (Local or Cloud)
Option A: Local Development (Recommended)
- Download & Install MySQL Community Server or use XAMPP.
- Start the MySQL Server service.
- Keep your
rootpassword handy.
Option B: Free Cloud Hosting (No installation required)
- PlanetScale / Railway / Aiven / db4free.net
- Create a database and get your host, user, password, and port.
- Open your MySQL client (MySQL Workbench, DBeaver, or CLI).
- Connect to your MySQL server using your root credentials.
- Execute the provided schema file to create the database, tables, views, procedures, and insert seed data:
Using Bash / macOS / Linux:
mysql -u root -p < /path/to/smartstock/schema.sqlUsing CMD (Windows):
mysql -u root -p < schema.sqlUsing PowerShell (Windows):
Get-Content .\schema.sql | mysql -u root -pAlternatively, in MySQL Workbench: File -> Run SQL Script... -> select schema.sql.
- Copy the example environment file:
Using Bash / macOS / Linux:
cp .env.example .envUsing CMD / PowerShell (Windows):
copy .env.example .env- Edit
.envwith your correct database credentials (leave DB_PASS and JWT_SECRET empty if not using them):
DB_HOST=localhost # Or your cloud DB host
DB_USER=root # Your MySQL username
DB_PASS= # Your MySQL password (leave blank if none)
DB_NAME=smartstock
JWT_SECRET= # Your JWT Secret (leave blank if none)
PORT=3000# Install required Node.js packages (Express, MySQL2, etc.)
npm install
# Start the application in development mode
npm run dev
# OR use: npm startOpen your web browser and navigate to: http://localhost:3000
| Role | Username | Password |
|---|---|---|
| 👑 Owner/Admin | admin_ishant |
admin@123 |
| 👔 Manager | mgr_rajesh |
mgr@1234 |
| 🏪 Cashier | cashier_ramu |
cash@1234 |
| 👤 Customer | cust_001 |
cust@1234 |
3 more accounts exist for each role (see schema.sql seed data)
smartstock/
├── index.html # SPA entry point
├── server.js # Express + MySQL API backend
├── schema.sql # Full MySQL schema with triggers, procedures, views
├── package.json
├── .env # Environment config (create from .env.example)
├── css/
│ └── style.css # Complete design system
└── js/
├── app.js # Core app, routing, auth, helpers
├── landing.js # Public landing + login + register pages
├── cashier.js # Cashier billing POS + orders view
├── dashboard.js # Admin/Manager dashboard, products, analytics, users
└── customer.js # Customer portal
The database architecture of Smart-Stock has been meticulously designed following fundamental DBMS principles to ensure data integrity, optimal performance, and robustness.
The schema has been normalized to eliminate data redundancy and prevent insertion, update, and deletion anomalies.
- First Normal Form (1NF): Every table has a primary key (
product_id,user_id, etc.). All attributes contain atomic, indivisible values. E.g., thewarning_labelinPRODUCTstores a single distinct value, and there are no repeating groups. - Second Normal Form (2NF): The schema meets 1NF, and all non-key attributes are fully functionally dependent on the entire primary key. In
ORDER_ITEMS, theunit_priceis stored as a snapshot to capture the product's price at the exact moment of sale. This preserves historical integrity without violating normalization. - Third Normal Form (3NF): The schema meets 2NF, and all transitive dependencies have been removed. For example, instead of storing
category_namedirectly in thePRODUCTtable (which introducesproduct_id → category_id → category_name), we abstracted it into a separateCATEGORYtable linked via thecategory_idforeign key.
The system strictly enforces ACID properties, particularly during critical operations like billing.
- Atomicity: Operations that modify multiple tables (like checkout) are enclosed within
START TRANSACTIONandCOMMITblocks (seesp_checkout). If a product is out of stock mid-transaction, aROLLBACKis issued. - Consistency: Constraints (
CHECK (price >= 0),CHECK (stock_qty >= 0)) enforce domain integrity. Triggers ensure business rules are maintained automatically (e.g., preventing the sale of expired products). - Isolation: Transactional concurrency is managed using row-level locking. The
SELECT ... FOR UPDATEclause insp_checkoutprevents race conditions, ensuring two cashiers cannot double-sell the last unit. - Durability: Changes are persisted permanently using the MySQL InnoDB storage engine's write-ahead logging (WAL).
- Entity Integrity: Implemented using
PRIMARY KEYwithAUTO_INCREMENT. - Referential Integrity: Implemented using
FOREIGN KEYconstraints (e.g., linkingORDERStoUSER).ON DELETE CASCADEis applied where appropriate (e.g.,ORDER_ITEMS). - Domain/Semantic Integrity: Enforced using
CHECKconstraints (e.g.,phone_no REGEXP '^[0-9]{10}$',qty_sold > 0) andENUMtypes.
sp_checkout(): Handles the entire complex checkout flow (inventory deduction, cart iteration, discount calculation) atomically.sp_restock_product(): Safely updates stock levels while automatically generating a detailed audit log entry.sp_register_customer(): Registers a user with the 'customer' role.sp_analytics_report(): Generates revenue reports by date range.fn_get_discount(): Encapsulates the logic for determining the highest applicable discount dynamically.
trg_block_expired_product: ABEFORE INSERTtrigger preventing the sale of expired products.trg_low_stock_alert: AnAFTER UPDATEtrigger that generates a system notification if stock dips below thereorder_level.trg_product_create_log: Logs initial stock upon product creation.trg_expiry_warning: Flags products nearing expiration.
vw_cashier_products: Filters out inactive or expired products for a clean cashier UI.vw_product_sales_summary&vw_daily_summary: Aggregates data for real-time dashboards.vw_highest_ticket_items: Computes top revenue-generating items.vw_expiry_alerts: Lists items expiring within 30 days.
Secondary indexes were purposefully created to optimize query execution:
idx_product_categoryonPRODUCT(category_id)idx_orders_dateonORDERS(order_date)idx_items_orderonORDER_ITEMS(order_id)
| Feature | Admin | Manager | Cashier | Customer |
|---|---|---|---|---|
| Dashboard & Analytics | ✅ | ✅ | ❌ | ❌ |
| Add/Edit Products | ✅ | ✅ | ❌ | ❌ |
| Restock Inventory | ✅ | ✅ | ❌ | ❌ |
| Billing / POS | ✅ | ✅ | ✅ | ❌ |
| View All Orders | ✅ | ✅ | ✅ | ❌ |
| Manage Users | ✅ | ❌ | ❌ | ❌ |
| View Own Purchases | ❌ | ❌ | ❌ | ✅ |
| Alerts/Notifications | ✅ | ✅ | ❌ | ❌ |
- Railway (recommended): https://railway.app — Free MySQL + Node.js hosting
- Render: https://render.com — Free Node.js + PostgreSQL (change DB driver)
- Cyclic.sh: Free Node.js hosting
- PlanetScale: Free MySQL-compatible, 5GB storage
- db4free.net: Free MySQL, good for dev
- Aiven: Free 1-month trial, then small cost
# Install Railway CLI
npm install -g @railway/cli
railway login
railway init
railway add mysql
railway up-- Highest Ticket Item
SELECT * FROM vw_highest_ticket_items LIMIT 5;
-- Items expiring within 30 days
SELECT * FROM vw_expiry_alerts;
-- Products not sold in last 30 days (clearance)
SELECT p.name, p.stock_qty FROM PRODUCT p
WHERE p.product_id NOT IN (
SELECT DISTINCT oi.product_id FROM ORDER_ITEMS oi
JOIN ORDERS o ON oi.order_id = o.order_id
WHERE o.order_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
) AND p.stock_qty > 0;
-- Revenue by category
SELECT c.category_name, SUM(oi.line_total) AS revenue
FROM ORDER_ITEMS oi JOIN PRODUCT p ON oi.product_id = p.product_id
JOIN CATEGORY c ON p.category_id = c.category_id
JOIN ORDERS o ON oi.order_id = o.order_id
WHERE o.status = 'completed'
GROUP BY c.category_name ORDER BY revenue DESC;TIET Patiala · CSE Department · UCS310 · Sub Group 2C34 · 2025-26