- 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>
189 lines
5.7 KiB
TypeScript
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;
|
|
}
|