10 KiB
10 KiB
Products API Implementation Summary
Overview
Complete implementation of the Products API module for the Retail POS backend, including all DTOs, controllers, services, repositories, and business logic.
Files Created
1. DTOs (src/modules/products/dto/)
create-product.dto.ts
- Fields:
name(required, string, 1-255 characters)description(optional, string, max 1000 characters)price(required, number, min 0, max 2 decimal places)imageUrl(optional, URL)categoryId(required, UUID)stockQuantity(optional, number, min 0, default 0)isAvailable(optional, boolean, default true)
- Validations: class-validator decorators with proper constraints
- Documentation: Full Swagger/OpenAPI annotations
update-product.dto.ts
- Extension: PartialType of CreateProductDto
- All fields are optional for partial updates
get-products.dto.ts
- Extends: PaginationDto (provides page/limit)
- Filters:
categoryId(UUID filter)search(string search in name/description)minPrice(number, min 0)maxPrice(number, min 0)isAvailable(boolean)
- Transform: Boolean query params properly transformed
product-response.dto.ts
- ProductResponseDto: Structured response with @Expose decorators
- CategoryInProductResponseDto: Nested category details
- Fields: All product fields plus populated category relation
index.ts
- Exports all DTOs for easy imports
2. Repository (products.repository.ts)
Features:
- Extends TypeORM Repository
- Custom query methods with QueryBuilder
Methods:
createFilteredQuery(filters)- Apply all filters to query builderfindWithFilters(filters)- Paginated products with filtersfindOneWithCategory(id)- Single product with category relationfindByCategory(categoryId, page, limit)- Products by categorysearchProducts(query, page, limit)- Search by name/descriptionupdateStock(id, quantity)- Update stock quantityincrementStock(id, amount)- Increment stockdecrementStock(id, amount)- Decrement stock
Query Optimizations:
- Left join on category relation
- Efficient WHERE clauses for filters
- LIKE queries with LOWER() for case-insensitive search
- Proper pagination with skip/take
3. Service (products.service.ts)
Features:
- Business logic implementation
- Transaction management with QueryRunner
- Proper error handling with specific exceptions
Methods:
findAll(filters)
- Fetches products with pagination and filters
- Returns [Product[], total count]
findOne(id)
- Get single product by ID with category
- Throws NotFoundException if not found
findByCategory(categoryId, page, limit)
- Validates category exists
- Returns products for specific category
search(query, page, limit)
- Validates search query not empty
- Searches in name and description
create(createProductDto)
- Transaction-based:
- Validate category exists
- Create product
- Increment category product count
- Commit transaction
- Error handling: Rollback on failure
update(id, updateProductDto)
- Transaction-based:
- Find existing product
- If category changed:
- Validate new category exists
- Decrement old category count
- Increment new category count
- Update product
- Commit transaction
- Error handling: Rollback on failure
remove(id)
- Transaction-based:
- Find product with transaction items relation
- Check if product used in transactions
- If used, throw BadRequestException
- Decrement category product count
- Delete product
- Commit transaction
- Business rule: Cannot delete products used in transactions
updateStock(id, quantity)
- Validates quantity not negative
- Updates product stock
4. Controller (products.controller.ts)
Configuration:
@ApiTags('products')- Swagger grouping- Base route:
/products
Endpoints:
GET /products (Public)
- Summary: Get all products with pagination and filters
- Query params: GetProductsDto (page, limit, categoryId, search, minPrice, maxPrice, isAvailable)
- Response: Paginated list with metadata
- Status: 200 OK
GET /products/search?q=query (Public)
- Summary: Search products by name or description
- Query params: q (search query), page, limit
- Response: Paginated search results
- Status: 200 OK, 400 Bad Request
GET /products/category/:categoryId (Public)
- Summary: Get products by category
- Params: categoryId (UUID)
- Query params: page, limit
- Response: Paginated products in category
- Status: 200 OK, 404 Not Found
GET /products/:id (Public)
- Summary: Get single product by ID
- Params: id (UUID)
- Response: Single product with category
- Status: 200 OK, 404 Not Found
POST /products (Admin/Manager)
- Summary: Create new product
- Auth: JWT Bearer token required
- Roles: Admin, Manager
- Body: CreateProductDto
- Response: Created product
- Status: 201 Created, 400 Bad Request, 404 Category Not Found
PUT /products/:id (Admin/Manager)
- Summary: Update product
- Auth: JWT Bearer token required
- Roles: Admin, Manager
- Params: id (UUID)
- Body: UpdateProductDto
- Response: Updated product
- Status: 200 OK, 400 Bad Request, 404 Not Found
DELETE /products/:id (Admin)
- Summary: Delete product
- Auth: JWT Bearer token required
- Roles: Admin only
- Params: id (UUID)
- Response: No content
- Status: 204 No Content, 400 Cannot Delete, 404 Not Found
Features:
- Full Swagger documentation with @ApiOperation, @ApiResponse
- @ParseUUIDPipe for UUID validation
- plainToInstance for DTO transformation
- Consistent ApiResponseDto wrapper
- Proper HTTP status codes
5. Module (products.module.ts)
Configuration:
- Imports TypeOrmModule with Product and Category entities
- Registers ProductsController
- Provides ProductsService and ProductsRepository
- Exports service and repository for use in other modules
Key Features Implemented
1. Authentication & Authorization
- Public endpoints: GET requests (list, search, single)
- Protected endpoints: POST, PUT, DELETE
- Role-based access:
- Admin + Manager: Create, Update
- Admin only: Delete
2. Validation
- Request validation with class-validator
- UUID validation with ParseUUIDPipe
- Query parameter transformation
- Business logic validation (category exists, stock quantity)
3. Business Logic
- Category Product Count: Automatically updated on create/update/delete
- Category Change: Handles count updates when product category changes
- Transaction Safety: Products used in transactions cannot be deleted
- Stock Management: Proper stock quantity validation and updates
4. Error Handling
- NotFoundException: Resource not found
- BadRequestException: Invalid input or business rule violation
- InternalServerErrorException: Unexpected errors
- Transaction rollback on failures
5. Database Optimization
- QueryBuilder for complex queries
- Left joins for relations
- Indexes on name, categoryId
- Composite index on name + categoryId
- Case-insensitive search with LOWER()
6. Response Format
- Consistent ApiResponseDto wrapper
- Success responses with data and message
- Paginated responses with metadata:
- page, limit, total, totalPages
- hasPreviousPage, hasNextPage
- DTO transformation with class-transformer
7. API Documentation
- Complete Swagger/OpenAPI annotations
- Request/response examples
- Parameter descriptions
- Status code documentation
- Bearer auth documentation
API Routes
Public Routes:
GET /products - List all products (paginated, filtered)
GET /products/search?q=query - Search products
GET /products/category/:categoryId - Products by category
GET /products/:id - Single product details
Protected Routes (Admin/Manager):
POST /products - Create product
PUT /products/:id - Update product
Protected Routes (Admin only):
DELETE /products/:id - Delete product
Example API Calls
List Products with Filters
GET /api/products?page=1&limit=20&categoryId=uuid&search=laptop&minPrice=100&maxPrice=1000&isAvailable=true
Search Products
GET /api/products/search?q=gaming&page=1&limit=10
Create Product
POST /api/products
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Gaming Laptop",
"description": "High-performance gaming laptop",
"price": 1299.99,
"imageUrl": "https://example.com/image.jpg",
"categoryId": "uuid",
"stockQuantity": 50,
"isAvailable": true
}
Update Product
PUT /api/products/:id
Authorization: Bearer <token>
Content-Type: application/json
{
"price": 1199.99,
"stockQuantity": 45
}
Delete Product
DELETE /api/products/:id
Authorization: Bearer <token>
Integration
The module is registered in app.module.ts:
import { ProductsModule } from './modules/products/products.module';
@Module({
imports: [
// ...
ProductsModule,
],
})
Testing Recommendations
Unit Tests
- ProductsService methods
- Business logic validation
- Error handling scenarios
- Transaction rollback
Integration Tests
- ProductsRepository queries
- Database operations
- Relations loading
E2E Tests
- All API endpoints
- Authentication/authorization
- Filter combinations
- Error responses
- Edge cases
Next Steps
- Categories Module: Similar structure for category management
- Transactions Module: Transaction processing with products
- Caching: Add Redis caching for frequently accessed products
- Soft Delete: Optional soft delete instead of hard delete
- Audit Trail: Track who created/updated products
- Product Images: File upload functionality
- Bulk Operations: Bulk create/update/delete endpoints
Best Practices Followed
- Separation of concerns (Controller → Service → Repository)
- Transaction management for data consistency
- Proper error handling with specific exceptions
- Input validation at DTO level
- Business validation at service level
- Query optimization with QueryBuilder
- Comprehensive API documentation
- Role-based access control
- Consistent response format
- TypeScript strict mode compliance