A comprehensive Point of Sale (POS) system with inventory management, customer tracking, and sales analytics.
These demo credentials are seeded for the Demo Store and are safe to share in interviews/demos:
- Demo Admin
- Email:
demo.admin@prosale.com - Password:
demoadmin123
- Email:
- Demo Manager
- Email:
demo.manager@prosale.com - Password:
demomgr123
- Email:
- Demo Cashier
- Email:
demo.cashier@prosale.com - Password:
demo123
- Email:
This project uses Sequelize migrations for safe database schema management. Never use destructive syncs in production.
# Apply all pending migrations
npm run migrate
# Undo the last migration
npm run migrate:undo
# Undo all migrations
npm run migrate:undo:all
# Check migration status
npm run migrate:status
# Generate a new migration
npm run migrate:generate migration-name- Update your models in
src/models/ - Generate a migration:
npm run migrate:generate your-change-name - Edit the migration file in
src/database/migrations/to match your model changes - Test the migration:
npm run migrate - Deploy safely: The deployment script includes automatic database backups
This project uses Sequelize CLI for database seeding with safe, reversible operations.
# Seed all data (recommended)
npm run seed:all
# Undo all seeding
npm run seed:undo:all
# Undo last seed
npm run seed:undo
# Generate a new seed file
npm run seed:generate seed-name
# Legacy seeding (for development only)
npm run seed:legacy
# Seed demo-only data (development)
cd server && npm run seed:demo- Use
npm run seed:allfor initial data setup - Generate new seeds:
npm run seed:generate your-seed-name - Edit the seed file in
src/database/seeders/ - Test the seed:
npm run seed:all - Undo if needed:
npm run seed:undo:all
- Database backups are automatically created before each deployment
- Non-destructive syncs in production (only migrations allowed)
- Rollback support for all schema changes
- Backup retention: Last 7 days of backups kept automatically
- Development: Can use
npm run seed:allfor testing - Production: Only migrations allowed, seeding blocked for safety
- πͺ Product Management (multi-unit pricing, stock, categories, suppliers)
- π° Sales Management (orders, dynamic pricing, real-time stock)
- π¨ Modern UI (light/dark mode, Tailwind CSS, Radix UI)
- π Secure Authentication (session-based, role-based, bcrypt)
-
Frontend
- React (Vite)
- TypeScript
- Tailwind CSS
- Radix UI
-
Backend
- Node.js
- Express
- Sequelize ORM
- PostgreSQL
-
Tooling & Infrastructure
- Docker & Docker Compose
- Jest / Vitest and integration/e2e tests (see
tests/directory) - Multer for file uploads
- Optional Cloudinary integration for product images
- Node.js (v20+)
- PostgreSQL (v16+)
- npm
βββ client/ # Frontend (Vite + React)
β βββ src/
β βββ components/
β βββ pages/
β βββ ...
βββ server/ # Backend (Express + Sequelize)
β βββ src/
β βββ migrations/
β βββ seeders/
β βββ ...
βββ tests/ # End-to-end tests
βββ docker-compose.yml
βββ Dockerfile
βββ package.json # Root scripts for monorepo
βββ README.md
-
Clone the repository:
git clone https://github.com/yourusername/ProSaleManager.git cd ProSaleManager -
Install all dependencies:
npm run install:all
-
Set up environment variables:
- Copy
.env.exampleto.envin bothclient/andserver/as needed. - Example for server:
DATABASE_URL=postgresql://username:password@localhost:5432/prosalemanager PORT=5000
- Copy
-
Database setup (run in project root):
npm run db:generate -- <migration-name> # Generate new migration npm run db:migrate # Run migrations npm run db:seed:all # (Optional) Seed demo data
Start both frontend and backend in development mode:
npm run dev- Frontend: Vite dev server (React)
- Backend: Express with hot reload
npm run build- Builds both client and server for production.
Root package.json:
dev- Run both client and server in dev modebuild- Build both client and serverinstall:all- Install dependencies in root, client, and serverdb:generate- Generate a new Sequelize migration (see below)db:migrate- Run all migrationsdb:seed:all- Seed the database
Client package.json:
dev- Start Vite dev serverbuild- Build for productionpreview- Preview production build
Server package.json:
dev- Start Express server with hot reloadbuild- Build server (if using TypeScript)migrate- Run Sequelize migrationsmigrate:undo- Undo last migrationmigrate:undo:all- Undo all migrationsseed:all- Run all seedersseed:undo:all- Undo all seedersgenerate:migration <name>- Generate a new migration
"scripts": {
"dev": "nodemon src/index.js", // or ts-node if using TypeScript
"build": "tsc", // if using TypeScript
"migrate": "npx sequelize-cli db:migrate",
"migrate:undo": "npx sequelize-cli db:migrate:undo",
"migrate:undo:all": "npx sequelize-cli db:migrate:undo:all",
"seed:all": "npx sequelize-cli db:seed:all",
"seed:undo:all": "npx sequelize-cli db:seed:undo:all",
"generate:migration": "npx sequelize-cli migration:generate --name"
}- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
-
Frontend:
- Validates image type (must be image) and size (max 5MB) before upload.
- Shows error messages for invalid files.
- Shows a progress indicator while uploading.
- Sends product data and image as multipart/form-data to the backend.
-
Backend:
- Uses Multer middleware to handle file uploads.
- Validates file type and size server-side.
- If
CLOUDINARY_URLis set in environment variables, uploads images to Cloudinary and stores the URL in the database. - If
CLOUDINARY_URLis not set (e.g., on cPanel), saves images to/uploads/productson the server and stores the relative path in the database. - Serves
/uploadsas static files for local access.
- By default, images will be stored locally in
/uploads/products. - Ensure the
/uploadsdirectory is writable by the server process. - The backend serves
/uploadsas static files, so product images are accessible via URLs likehttps://yourdomain.com/uploads/products/filename.jpg. - If you want to use Cloudinary, set the
CLOUDINARY_URLenvironment variable in your deployment environment. - No code changes are needed to switch between local and Cloudinary storageβjust set or unset the environment variable.