423 lines
11 KiB
Markdown
423 lines
11 KiB
Markdown
# 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
|
|
|
|
```sql
|
|
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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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)
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
1. **Modify entities** (add/remove fields, change relationships)
|
|
|
|
2. **Generate migration**:
|
|
```bash
|
|
npm run migration:generate -- -n AddColumnToProduct
|
|
```
|
|
|
|
3. **Review generated migration** in `src/database/migrations/`
|
|
|
|
4. **Run migration**:
|
|
```bash
|
|
npm run migration:run
|
|
```
|
|
|
|
5. **Test rollback** (in development):
|
|
```bash
|
|
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"
|
|
```bash
|
|
# Solution: Check if migration already ran
|
|
psql -U postgres retail_pos
|
|
SELECT * FROM migrations;
|
|
\q
|
|
```
|
|
|
|
**Problem**: Can't connect to database
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
|
|
1. **Environment Variables**: Never commit .env to git
|
|
2. **SSL**: Enable SSL for production databases
|
|
3. **Connection Pooling**: Configure in data-source.ts
|
|
4. **Migrations**: Always run migrations manually, never use synchronize
|
|
5. **Backups**: Backup database before running migrations
|
|
6. **Monitoring**: Log slow queries in production
|
|
7. **Security**: Use strong passwords, restrict database access
|
|
|
|
## Next Steps
|
|
|
|
After database setup:
|
|
1. ✅ Create repository classes (see CLAUDE.md)
|
|
2. ✅ Create service classes for business logic
|
|
3. ✅ Create DTOs for validation
|
|
4. ✅ Create controllers for REST endpoints
|
|
5. ✅ Add authentication middleware
|
|
6. ✅ Implement caching with Redis
|
|
7. ✅ 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
|