/** * AssetAssignment Controller * Mecánicas Diesel - ERP Suite * * REST API endpoints for asset assignments. * Module: MMD-013 Asset Management */ import { Router, Request, Response, NextFunction } from 'express'; import { DataSource } from 'typeorm'; import { AssetAssignmentService, AssignmentFilters } from '../services/asset-assignment.service'; import { AssignmentStatus } from '../entities/asset-assignment.entity'; import { AssigneeType } from '../entities/asset.entity'; interface TenantRequest extends Request { tenantId?: string; userId?: string; } export function createAssetAssignmentController(dataSource: DataSource): Router { const router = Router(); const service = new AssetAssignmentService(dataSource); const extractTenant = (req: TenantRequest, res: Response, next: NextFunction) => { const tenantId = req.headers['x-tenant-id'] as string; if (!tenantId) { return res.status(400).json({ error: 'Tenant ID is required' }); } req.tenantId = tenantId; req.userId = req.headers['x-user-id'] as string; next(); }; router.use(extractTenant); /** * Assign an asset * POST /api/assets/assignments */ router.post('/', async (req: TenantRequest, res: Response) => { try { const assignment = await service.assign(req.tenantId!, { ...req.body, assignedBy: req.userId || req.body.assignedBy, }); res.status(201).json(assignment); } catch (error) { res.status(400).json({ error: (error as Error).message }); } }); /** * List assignments with filters * GET /api/assets/assignments */ router.get('/', async (req: TenantRequest, res: Response) => { try { const filters: AssignmentFilters = { assetId: req.query.assetId as string, assigneeId: req.query.assigneeId as string, assigneeType: req.query.assigneeType as AssigneeType, status: req.query.status as AssignmentStatus, incidentId: req.query.incidentId as string, startDate: req.query.startDate ? new Date(req.query.startDate as string) : undefined, endDate: req.query.endDate ? new Date(req.query.endDate as string) : undefined, }; const pagination = { page: parseInt(req.query.page as string, 10) || 1, limit: Math.min(parseInt(req.query.limit as string, 10) || 20, 100), }; const result = await service.findAll(req.tenantId!, filters, pagination); res.json(result); } catch (error) { res.status(500).json({ error: (error as Error).message }); } }); /** * Get overdue assignments * GET /api/assets/assignments/overdue */ router.get('/overdue', async (req: TenantRequest, res: Response) => { try { const assignments = await service.findOverdue(req.tenantId!); res.json(assignments); } catch (error) { res.status(500).json({ error: (error as Error).message }); } }); /** * Validate required assets for assignee * POST /api/assets/assignments/validate */ router.post('/validate', async (req: TenantRequest, res: Response) => { try { const { requiredCategoryIds, assigneeId, assigneeType } = req.body; const result = await service.validateRequiredAssets( req.tenantId!, requiredCategoryIds, assigneeId, assigneeType ); res.json(result); } catch (error) { res.status(400).json({ error: (error as Error).message }); } }); /** * Get assignment history for an asset * GET /api/assets/assignments/asset/:assetId/history */ router.get('/asset/:assetId/history', async (req: TenantRequest, res: Response) => { try { const history = await service.getAssetHistory(req.tenantId!, req.params.assetId); res.json(history); } catch (error) { res.status(500).json({ error: (error as Error).message }); } }); /** * Get assignment history for an assignee * GET /api/assets/assignments/assignee/:assigneeId/history */ router.get('/assignee/:assigneeId/history', async (req: TenantRequest, res: Response) => { try { const assigneeType = req.query.type as AssigneeType || AssigneeType.EMPLOYEE; const history = await service.getAssigneeHistory(req.tenantId!, req.params.assigneeId, assigneeType); res.json(history); } catch (error) { res.status(500).json({ error: (error as Error).message }); } }); /** * Get assignment by ID * GET /api/assets/assignments/:id */ router.get('/:id', async (req: TenantRequest, res: Response) => { try { const assignment = await service.findById(req.tenantId!, req.params.id); if (!assignment) { return res.status(404).json({ error: 'Assignment not found' }); } res.json(assignment); } catch (error) { res.status(500).json({ error: (error as Error).message }); } }); /** * Return an assigned asset * POST /api/assets/assignments/:id/return */ router.post('/:id/return', async (req: TenantRequest, res: Response) => { try { const assignment = await service.return(req.tenantId!, req.params.id, { ...req.body, returnedTo: req.userId || req.body.returnedTo, }); res.json(assignment); } catch (error) { res.status(400).json({ error: (error as Error).message }); } }); /** * Transfer an assignment * POST /api/assets/assignments/:id/transfer */ router.post('/:id/transfer', async (req: TenantRequest, res: Response) => { try { const assignment = await service.transfer(req.tenantId!, req.params.id, { ...req.body, transferredBy: req.userId || req.body.transferredBy, }); res.json(assignment); } catch (error) { res.status(400).json({ error: (error as Error).message }); } }); return router; }