11 KiB
11 KiB
Database Setup Guide - Retail POS Backend
Overview
Complete TypeORM database setup for the Retail POS NestJS backend with PostgreSQL.
Created Files
1. Entity Files (Domain Models)
/src/modules/users/entities/user.entity.ts
- User entity with bcrypt password hashing
- UserRole enum (admin, manager, cashier, user)
- @BeforeInsert/@BeforeUpdate hooks for automatic password hashing
- validatePassword() method for authentication
- Exclude password from JSON responses
- Index on email field
/src/modules/categories/entities/category.entity.ts
- Category entity with unique name constraint
- Fields: name, description, iconPath, color, productCount
- OneToMany relationship with Products
- Index on name field
- Timestamps (createdAt, updatedAt)
/src/modules/products/entities/product.entity.ts
- Product entity with complete product information
- Fields: name, description, price, imageUrl, stockQuantity, isAvailable
- ManyToOne relationship with Category (CASCADE delete)
- OneToMany relationship with TransactionItems
- Composite index on [name, categoryId]
- Individual indexes on name and categoryId
/src/modules/transactions/entities/transaction.entity.ts
- Transaction entity for sales records
- Fields: subtotal, tax, discount, total, paymentMethod
- OneToMany relationship with TransactionItems (CASCADE)
- Index on completedAt for date-based queries
/src/modules/transactions/entities/transaction-item.entity.ts
- Transaction line items
- Fields: productName, price, quantity, lineTotal
- ManyToOne relationships with Transaction and Product
- Indexes on transactionId and productId
- Stores product snapshot at transaction time
2. Configuration Files
/src/config/database.config.ts
- TypeORM configuration using @nestjs/config
- Environment-based settings
- All entities registered
- Migration paths configured
- SSL support for production
- Synchronize always false (use migrations!)
/src/database/data-source.ts
- TypeORM DataSource for CLI operations
- Used by migration and seed commands
- Loads from .env file
- Same configuration as database.config.ts
3. Migration Files
/src/database/migrations/1736518800000-InitialSchema.ts
- Complete initial database schema
- Creates all 5 tables:
- users (with email index)
- categories (with name index)
- products (with name, categoryId, and composite indexes)
- transactions (with completedAt index)
- transaction_items (with transactionId and productId indexes)
- Sets up all foreign key relationships
- Enables uuid-ossp extension
- Proper up/down methods for rollback
4. Seed Files
/src/database/seeds/categories.seed.ts
- Seeds 6 common retail categories:
- Electronics (Blue)
- Clothing (Pink)
- Food & Beverages (Green)
- Home & Garden (Orange)
- Sports & Outdoors (Purple)
- Books & Media (Brown)
- Each with icon path and color
- Checks for existing records
/src/database/seeds/products.seed.ts
- Seeds 14 sample products across all categories
- Realistic prices and stock quantities
- Placeholder images
- Updates category product counts
- Covers all seeded categories
/src/database/seeds/run-seeds.ts
- Main seed runner script
- Runs seeds in correct order (categories → products)
- Proper error handling
- Database connection management
5. Environment Configuration
.env.example
- Complete environment variable template
- Database credentials
- JWT configuration
- Redis settings
- CORS configuration
- Rate limiting settings
Database Schema
Tables Created
users
├── id (uuid, PK)
├── name (varchar 255)
├── email (varchar 255, unique, indexed)
├── password (varchar 255)
├── roles (text array)
├── isActive (boolean)
├── createdAt (timestamp)
└── updatedAt (timestamp)
categories
├── id (uuid, PK)
├── name (varchar 255, unique, indexed)
├── description (text, nullable)
├── iconPath (varchar 255, nullable)
├── color (varchar 50, nullable)
├── productCount (int)
├── createdAt (timestamp)
└── updatedAt (timestamp)
products
├── id (uuid, PK)
├── name (varchar 255, indexed)
├── description (text, nullable)
├── price (decimal 10,2)
├── imageUrl (varchar 500, nullable)
├── categoryId (uuid, FK, indexed)
├── stockQuantity (int)
├── isAvailable (boolean)
├── createdAt (timestamp)
└── updatedAt (timestamp)
└── FK: categories(id) ON DELETE CASCADE
└── Composite Index: (name, categoryId)
transactions
├── id (uuid, PK)
├── subtotal (decimal 10,2)
├── tax (decimal 10,2)
├── discount (decimal 10,2)
├── total (decimal 10,2)
├── paymentMethod (varchar 50)
└── completedAt (timestamp, indexed)
transaction_items
├── id (uuid, PK)
├── transactionId (uuid, FK, indexed)
├── productId (uuid, FK, indexed)
├── productName (varchar 255)
├── price (decimal 10,2)
├── quantity (int)
└── lineTotal (decimal 10,2)
└── FK: transactions(id) ON DELETE CASCADE
└── FK: products(id) ON DELETE RESTRICT
Setup Instructions
1. Prerequisites
# Ensure PostgreSQL is installed and running
psql --version
# Create database
createdb retail_pos
# Or using psql
psql -U postgres
CREATE DATABASE retail_pos;
\q
2. Configure Environment
# Copy example environment file
cp .env.example .env
# Edit .env with your database credentials
# At minimum, update:
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=your_password
DB_DATABASE=retail_pos
3. Run Migrations
# Run all pending migrations
npm run migration:run
# Expected output:
# query: SELECT * FROM "information_schema"."tables" WHERE "table_schema" = 'public' AND "table_name" = 'migrations'
# query: CREATE TABLE "migrations" (...)
# Migration InitialSchema1736518800000 has been executed successfully.
4. Seed Database (Optional)
# Run seed scripts to populate with sample data
npm run seed:run
# Expected output:
# 🌱 Starting database seeding...
# ✓ Database connection established
# 📦 Seeding categories...
# ✓ Created category: Electronics
# ✓ Created category: Clothing
# ... (more categories)
# 📦 Seeding products...
# ✓ Created product: Wireless Mouse
# ... (more products)
# 🎉 Database seeding completed successfully!
5. Verify Setup
# Connect to database
psql -U postgres retail_pos
# Check tables
\dt
# Check products count
SELECT COUNT(*) FROM products;
# Check categories with product counts
SELECT name, "productCount" FROM categories;
# Exit
\q
Available NPM Scripts
# TypeORM CLI operations
npm run typeorm -- <command>
# Generate a new migration (based on entity changes)
npm run migration:generate -- -n MigrationName
# Create an empty migration file
npm run migration:create -- src/database/migrations/MigrationName
# Run all pending migrations
npm run migration:run
# Revert the last migration
npm run migration:revert
# Seed the database
npm run seed:run
Migration Workflow
Creating New Migrations
-
Modify entities (add/remove fields, change relationships)
-
Generate migration:
npm run migration:generate -- -n AddColumnToProduct -
Review generated migration in
src/database/migrations/ -
Run migration:
npm run migration:run -
Test rollback (in development):
npm run migration:revert
Migration Best Practices
- ✅ Always review generated migrations before running
- ✅ Test migrations in development first
- ✅ Keep migrations small and focused
- ✅ Never modify existing migrations that have run in production
- ✅ Always provide up() and down() methods
- ✅ Backup database before running migrations in production
- ❌ Never use synchronize: true in production
Entity Relationships
User (standalone)
Category (1) ----< Products (N)
|
|
v
Transaction (1) ----< TransactionItems (N) >---- Products (N)
Key Features Implemented
1. Password Security
- Bcrypt hashing with 10 rounds
- Automatic hashing on insert/update
- Password excluded from JSON responses
- Validation method for authentication
2. UUID Primary Keys
- All tables use UUID v4
- uuid-ossp extension enabled
- Better for distributed systems
- No sequential ID exposure
3. Proper Indexing
- Email index on users
- Name index on categories
- Multiple indexes on products (name, categoryId, composite)
- Date index on transactions
- Foreign key indexes on transaction_items
4. Data Integrity
- Foreign key constraints
- Cascade deletes where appropriate
- Unique constraints (email, category name)
- Default values for booleans and integers
- Nullable vs required fields clearly defined
5. Timestamps
- Automatic createdAt on insert
- Automatic updatedAt on update
- Custom completedAt for transactions
Troubleshooting
Migration Issues
Problem: Migration fails with "relation already exists"
# Solution: Check if migration already ran
psql -U postgres retail_pos
SELECT * FROM migrations;
\q
Problem: Can't connect to database
# Check PostgreSQL is running
pg_isready
# Check credentials in .env
# Verify database exists
psql -U postgres -c "\l" | grep retail_pos
Seed Issues
Problem: Seeds fail with foreign key constraint
# Solution: Run seeds in correct order (already handled in run-seeds.ts)
# Or clear database and re-seed:
npm run migration:revert
npm run migration:run
npm run seed:run
TypeORM Issues
Problem: Entity not found
# Solution: Ensure entity is:
# 1. Exported from entity file
# 2. Added to data-source.ts entities array
# 3. Added to database.config.ts entities array
Production Considerations
- Environment Variables: Never commit .env to git
- SSL: Enable SSL for production databases
- Connection Pooling: Configure in data-source.ts
- Migrations: Always run migrations manually, never use synchronize
- Backups: Backup database before running migrations
- Monitoring: Log slow queries in production
- Security: Use strong passwords, restrict database access
Next Steps
After database setup:
- ✅ Create repository classes (see CLAUDE.md)
- ✅ Create service classes for business logic
- ✅ Create DTOs for validation
- ✅ Create controllers for REST endpoints
- ✅ Add authentication middleware
- ✅ Implement caching with Redis
- ✅ Add comprehensive tests
Reference
- TypeORM Docs: https://typeorm.io
- NestJS Database: https://docs.nestjs.com/techniques/database
- PostgreSQL Docs: https://www.postgresql.org/docs/
Database Expert: NestJS Database Expert Subagent Created: 2025-10-10 Status: ✅ Complete and Ready for Development