erp-mecanicas-diesel-backen.../src/modules/assets/controllers/asset-assignment.controller.ts
Adrian Flores Cortes 89948663e9 feat(MMD-013): Implement Asset Management module
- 6 entities: Asset, AssetCategory, AssetAssignment, AssetAudit, AssetAuditItem, AssetMaintenance
- 4 services with CRUD, assignment, audit, and maintenance operations
- 4 controllers with REST endpoints
- Integration in main.ts with routes registration
- Multi-tenant support with RLS

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 01:44:58 -06:00

189 lines
5.7 KiB
TypeScript

/**
* 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;
}