[MAE-015] fix: Fix TypeScript errors in assets module
- Fix controllers to use Promise<void> return types - Replace 'return res.status()' with 'res.status(); return;' - Add NextFunction parameter to handlers - Fix enum-style references with string literals - Replace 'deletedAt: null' with 'IsNull()' for TypeORM - Remove unused parameters and imports - Fix grouped object initialization in getByStatus - Remove non-existent 'updatedBy' property from WorkOrderPart Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e441e9c626
commit
f14829d2ce
@ -6,7 +6,7 @@
|
|||||||
* @module Assets (MAE-015)
|
* @module Assets (MAE-015)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Router, Request, Response } from 'express';
|
import { Router, Request, Response, NextFunction } from 'express';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { AssetService } from '../services';
|
import { AssetService } from '../services';
|
||||||
|
|
||||||
@ -20,10 +20,9 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
* GET /
|
* GET /
|
||||||
* Lista activos con filtros y paginación
|
* Lista activos con filtros y paginación
|
||||||
*/
|
*/
|
||||||
router.get('/', async (req: Request, res: Response) => {
|
router.get('/', async (req: Request, res: Response, _next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
|
||||||
|
|
||||||
const filters = {
|
const filters = {
|
||||||
assetType: req.query.assetType as any,
|
assetType: req.query.assetType as any,
|
||||||
@ -81,20 +80,21 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
* GET /search
|
* GET /search
|
||||||
* Búsqueda de activos para autocomplete
|
* Búsqueda de activos para autocomplete
|
||||||
*/
|
*/
|
||||||
router.get('/search', async (req: Request, res: Response) => {
|
router.get('/search', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const query = req.query.q as string;
|
const query = req.query.q as string;
|
||||||
const limit = parseInt(req.query.limit as string) || 10;
|
const limit = parseInt(req.query.limit as string) || 10;
|
||||||
|
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return res.status(400).json({ error: 'Se requiere parámetro de búsqueda (q)' });
|
res.status(400).json({ error: 'Se requiere parámetro de búsqueda (q)' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const assets = await service.search(tenantId, query, limit);
|
const assets = await service.search(tenantId, query, limit);
|
||||||
res.json(assets);
|
res.json(assets);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -102,18 +102,19 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
* GET /by-code/:code
|
* GET /by-code/:code
|
||||||
* Obtiene un activo por código
|
* Obtiene un activo por código
|
||||||
*/
|
*/
|
||||||
router.get('/by-code/:code', async (req: Request, res: Response) => {
|
router.get('/by-code/:code', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const asset = await service.findByCode(tenantId, req.params.code);
|
const asset = await service.findByCode(tenantId, req.params.code);
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
return res.status(404).json({ error: 'Activo no encontrado' });
|
res.status(404).json({ error: 'Activo no encontrado' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(asset);
|
res.json(asset);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -121,18 +122,19 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
* GET /:id
|
* GET /:id
|
||||||
* Obtiene un activo por ID
|
* Obtiene un activo por ID
|
||||||
*/
|
*/
|
||||||
router.get('/:id', async (req: Request, res: Response) => {
|
router.get('/:id', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const asset = await service.findById(tenantId, req.params.id);
|
const asset = await service.findById(tenantId, req.params.id);
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
return res.status(404).json({ error: 'Activo no encontrado' });
|
res.status(404).json({ error: 'Activo no encontrado' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(asset);
|
res.json(asset);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -156,19 +158,20 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
* PUT /:id
|
* PUT /:id
|
||||||
* Actualiza un activo
|
* Actualiza un activo
|
||||||
*/
|
*/
|
||||||
router.put('/:id', async (req: Request, res: Response) => {
|
router.put('/:id', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
|
|
||||||
const asset = await service.update(tenantId, req.params.id, req.body, userId);
|
const asset = await service.update(tenantId, req.params.id, req.body, userId);
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
return res.status(404).json({ error: 'Activo no encontrado' });
|
res.status(404).json({ error: 'Activo no encontrado' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(asset);
|
res.json(asset);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -176,24 +179,26 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
* PATCH /:id/status
|
* PATCH /:id/status
|
||||||
* Actualiza el estado de un activo
|
* Actualiza el estado de un activo
|
||||||
*/
|
*/
|
||||||
router.patch('/:id/status', async (req: Request, res: Response) => {
|
router.patch('/:id/status', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
const { status } = req.body;
|
const { status } = req.body;
|
||||||
|
|
||||||
if (!status) {
|
if (!status) {
|
||||||
return res.status(400).json({ error: 'Se requiere el nuevo estado' });
|
res.status(400).json({ error: 'Se requiere el nuevo estado' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const asset = await service.updateStatus(tenantId, req.params.id, status, userId);
|
const asset = await service.updateStatus(tenantId, req.params.id, status, userId);
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
return res.status(404).json({ error: 'Activo no encontrado' });
|
res.status(404).json({ error: 'Activo no encontrado' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(asset);
|
res.json(asset);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -201,7 +206,7 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
* PATCH /:id/usage
|
* PATCH /:id/usage
|
||||||
* Actualiza métricas de uso (horas/kilómetros)
|
* Actualiza métricas de uso (horas/kilómetros)
|
||||||
*/
|
*/
|
||||||
router.patch('/:id/usage', async (req: Request, res: Response) => {
|
router.patch('/:id/usage', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
@ -209,12 +214,13 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
|
|
||||||
const asset = await service.updateUsage(tenantId, req.params.id, hours, kilometers, userId);
|
const asset = await service.updateUsage(tenantId, req.params.id, hours, kilometers, userId);
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
return res.status(404).json({ error: 'Activo no encontrado' });
|
res.status(404).json({ error: 'Activo no encontrado' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(asset);
|
res.json(asset);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -222,19 +228,20 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
* DELETE /:id
|
* DELETE /:id
|
||||||
* Elimina un activo (soft delete)
|
* Elimina un activo (soft delete)
|
||||||
*/
|
*/
|
||||||
router.delete('/:id', async (req: Request, res: Response) => {
|
router.delete('/:id', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
|
|
||||||
const deleted = await service.delete(tenantId, req.params.id, userId);
|
const deleted = await service.delete(tenantId, req.params.id, userId);
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
return res.status(404).json({ error: 'Activo no encontrado' });
|
res.status(404).json({ error: 'Activo no encontrado' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(204).send();
|
res.status(204).send();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -300,7 +307,7 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
* POST /:id/return
|
* POST /:id/return
|
||||||
* Retorna un activo de un proyecto
|
* Retorna un activo de un proyecto
|
||||||
*/
|
*/
|
||||||
router.post('/:id/return', async (req: Request, res: Response) => {
|
router.post('/:id/return', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
@ -314,12 +321,13 @@ export function createAssetController(dataSource: DataSource): Router {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return res.status(400).json({ error: 'No hay asignación activa para este activo' });
|
res.status(400).json({ error: 'No hay asignación activa para este activo' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json({ success: true, message: 'Activo retornado exitosamente' });
|
res.json({ success: true, message: 'Activo retornado exitosamente' });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
* @module Assets (MAE-015)
|
* @module Assets (MAE-015)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Router, Request, Response } from 'express';
|
import { Router, Request, Response, NextFunction } from 'express';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { FuelLogService } from '../services';
|
import { FuelLogService } from '../services';
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ export function createFuelLogController(dataSource: DataSource): Router {
|
|||||||
* GET /
|
* GET /
|
||||||
* Lista registros de combustible con filtros
|
* Lista registros de combustible con filtros
|
||||||
*/
|
*/
|
||||||
router.get('/', async (req: Request, res: Response) => {
|
router.get('/', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ export function createFuelLogController(dataSource: DataSource): Router {
|
|||||||
const result = await service.findAll(tenantId, filters, pagination);
|
const result = await service.findAll(tenantId, filters, pagination);
|
||||||
res.json(result);
|
res.json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ export function createFuelLogController(dataSource: DataSource): Router {
|
|||||||
* GET /statistics/:assetId
|
* GET /statistics/:assetId
|
||||||
* Obtiene estadísticas de combustible para un activo
|
* Obtiene estadísticas de combustible para un activo
|
||||||
*/
|
*/
|
||||||
router.get('/statistics/:assetId', async (req: Request, res: Response) => {
|
router.get('/statistics/:assetId', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ export function createFuelLogController(dataSource: DataSource): Router {
|
|||||||
const stats = await service.getAssetStatistics(tenantId, req.params.assetId, fromDate, toDate);
|
const stats = await service.getAssetStatistics(tenantId, req.params.assetId, fromDate, toDate);
|
||||||
res.json(stats);
|
res.json(stats);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -64,18 +64,19 @@ export function createFuelLogController(dataSource: DataSource): Router {
|
|||||||
* GET /:id
|
* GET /:id
|
||||||
* Obtiene un registro por ID
|
* Obtiene un registro por ID
|
||||||
*/
|
*/
|
||||||
router.get('/:id', async (req: Request, res: Response) => {
|
router.get('/:id', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const fuelLog = await service.findById(tenantId, req.params.id);
|
const fuelLog = await service.findById(tenantId, req.params.id);
|
||||||
if (!fuelLog) {
|
if (!fuelLog) {
|
||||||
return res.status(404).json({ error: 'Registro de combustible no encontrado' });
|
res.status(404).json({ error: 'Registro de combustible no encontrado' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(fuelLog);
|
res.json(fuelLog);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ export function createFuelLogController(dataSource: DataSource): Router {
|
|||||||
* POST /
|
* POST /
|
||||||
* Crea un nuevo registro de combustible
|
* Crea un nuevo registro de combustible
|
||||||
*/
|
*/
|
||||||
router.post('/', async (req: Request, res: Response) => {
|
router.post('/', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
@ -91,7 +92,7 @@ export function createFuelLogController(dataSource: DataSource): Router {
|
|||||||
const fuelLog = await service.create(tenantId, req.body, userId);
|
const fuelLog = await service.create(tenantId, req.body, userId);
|
||||||
res.status(201).json(fuelLog);
|
res.status(201).json(fuelLog);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -99,18 +100,19 @@ export function createFuelLogController(dataSource: DataSource): Router {
|
|||||||
* DELETE /:id
|
* DELETE /:id
|
||||||
* Elimina un registro de combustible
|
* Elimina un registro de combustible
|
||||||
*/
|
*/
|
||||||
router.delete('/:id', async (req: Request, res: Response) => {
|
router.delete('/:id', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const deleted = await service.delete(tenantId, req.params.id);
|
const deleted = await service.delete(tenantId, req.params.id);
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
return res.status(404).json({ error: 'Registro de combustible no encontrado' });
|
res.status(404).json({ error: 'Registro de combustible no encontrado' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(204).send();
|
res.status(204).send();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
* @module Assets (MAE-015)
|
* @module Assets (MAE-015)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Router, Request, Response } from 'express';
|
import { Router, Request, Response, NextFunction } from 'express';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { WorkOrderService } from '../services';
|
import { WorkOrderService } from '../services';
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* GET /
|
* GET /
|
||||||
* Lista órdenes de trabajo con filtros y paginación
|
* Lista órdenes de trabajo con filtros y paginación
|
||||||
*/
|
*/
|
||||||
router.get('/', async (req: Request, res: Response) => {
|
router.get('/', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
const result = await service.findAll(tenantId, filters, pagination);
|
const result = await service.findAll(tenantId, filters, pagination);
|
||||||
res.json(result);
|
res.json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -52,14 +52,14 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* GET /statistics
|
* GET /statistics
|
||||||
* Obtiene estadísticas de órdenes de trabajo
|
* Obtiene estadísticas de órdenes de trabajo
|
||||||
*/
|
*/
|
||||||
router.get('/statistics', async (req: Request, res: Response) => {
|
router.get('/statistics', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const stats = await service.getStatistics(tenantId);
|
const stats = await service.getStatistics(tenantId);
|
||||||
res.json(stats);
|
res.json(stats);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -67,14 +67,14 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* GET /by-status
|
* GET /by-status
|
||||||
* Obtiene órdenes agrupadas por estado
|
* Obtiene órdenes agrupadas por estado
|
||||||
*/
|
*/
|
||||||
router.get('/by-status', async (req: Request, res: Response) => {
|
router.get('/by-status', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const grouped = await service.getByStatus(tenantId);
|
const grouped = await service.getByStatus(tenantId);
|
||||||
res.json(grouped);
|
res.json(grouped);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -82,18 +82,19 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* GET /by-number/:orderNumber
|
* GET /by-number/:orderNumber
|
||||||
* Obtiene una orden por número
|
* Obtiene una orden por número
|
||||||
*/
|
*/
|
||||||
router.get('/by-number/:orderNumber', async (req: Request, res: Response) => {
|
router.get('/by-number/:orderNumber', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const workOrder = await service.findByNumber(tenantId, req.params.orderNumber);
|
const workOrder = await service.findByNumber(tenantId, req.params.orderNumber);
|
||||||
if (!workOrder) {
|
if (!workOrder) {
|
||||||
return res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(workOrder);
|
res.json(workOrder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -101,14 +102,14 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* GET /overdue
|
* GET /overdue
|
||||||
* Lista órdenes vencidas
|
* Lista órdenes vencidas
|
||||||
*/
|
*/
|
||||||
router.get('/overdue', async (req: Request, res: Response) => {
|
router.get('/overdue', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const orders = await service.getOverdue(tenantId);
|
const orders = await service.getOverdue(tenantId);
|
||||||
res.json(orders);
|
res.json(orders);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -116,18 +117,19 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* GET /:id
|
* GET /:id
|
||||||
* Obtiene una orden de trabajo por ID
|
* Obtiene una orden de trabajo por ID
|
||||||
*/
|
*/
|
||||||
router.get('/:id', async (req: Request, res: Response) => {
|
router.get('/:id', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const workOrder = await service.findById(tenantId, req.params.id);
|
const workOrder = await service.findById(tenantId, req.params.id);
|
||||||
if (!workOrder) {
|
if (!workOrder) {
|
||||||
return res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(workOrder);
|
res.json(workOrder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -135,7 +137,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* POST /
|
* POST /
|
||||||
* Crea una nueva orden de trabajo
|
* Crea una nueva orden de trabajo
|
||||||
*/
|
*/
|
||||||
router.post('/', async (req: Request, res: Response) => {
|
router.post('/', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
@ -143,7 +145,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
const workOrder = await service.create(tenantId, req.body, userId);
|
const workOrder = await service.create(tenantId, req.body, userId);
|
||||||
res.status(201).json(workOrder);
|
res.status(201).json(workOrder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -151,19 +153,20 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* PUT /:id
|
* PUT /:id
|
||||||
* Actualiza una orden de trabajo
|
* Actualiza una orden de trabajo
|
||||||
*/
|
*/
|
||||||
router.put('/:id', async (req: Request, res: Response) => {
|
router.put('/:id', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
|
|
||||||
const workOrder = await service.update(tenantId, req.params.id, req.body, userId);
|
const workOrder = await service.update(tenantId, req.params.id, req.body, userId);
|
||||||
if (!workOrder) {
|
if (!workOrder) {
|
||||||
return res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(workOrder);
|
res.json(workOrder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -171,19 +174,20 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* DELETE /:id
|
* DELETE /:id
|
||||||
* Elimina una orden de trabajo (soft delete)
|
* Elimina una orden de trabajo (soft delete)
|
||||||
*/
|
*/
|
||||||
router.delete('/:id', async (req: Request, res: Response) => {
|
router.delete('/:id', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
|
|
||||||
const deleted = await service.delete(tenantId, req.params.id, userId);
|
const deleted = await service.delete(tenantId, req.params.id, userId);
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
return res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(204).send();
|
res.status(204).send();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -193,19 +197,20 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* POST /:id/start
|
* POST /:id/start
|
||||||
* Inicia una orden de trabajo
|
* Inicia una orden de trabajo
|
||||||
*/
|
*/
|
||||||
router.post('/:id/start', async (req: Request, res: Response) => {
|
router.post('/:id/start', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
|
|
||||||
const workOrder = await service.start(tenantId, req.params.id, userId);
|
const workOrder = await service.start(tenantId, req.params.id, userId);
|
||||||
if (!workOrder) {
|
if (!workOrder) {
|
||||||
return res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(workOrder);
|
res.json(workOrder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -213,7 +218,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* POST /:id/hold
|
* POST /:id/hold
|
||||||
* Pone en espera una orden de trabajo
|
* Pone en espera una orden de trabajo
|
||||||
*/
|
*/
|
||||||
router.post('/:id/hold', async (req: Request, res: Response) => {
|
router.post('/:id/hold', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
@ -221,12 +226,13 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
|
|
||||||
const workOrder = await service.hold(tenantId, req.params.id, reason, userId);
|
const workOrder = await service.hold(tenantId, req.params.id, reason, userId);
|
||||||
if (!workOrder) {
|
if (!workOrder) {
|
||||||
return res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(workOrder);
|
res.json(workOrder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -234,19 +240,20 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* POST /:id/resume
|
* POST /:id/resume
|
||||||
* Reanuda una orden de trabajo en espera
|
* Reanuda una orden de trabajo en espera
|
||||||
*/
|
*/
|
||||||
router.post('/:id/resume', async (req: Request, res: Response) => {
|
router.post('/:id/resume', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
|
|
||||||
const workOrder = await service.resume(tenantId, req.params.id, userId);
|
const workOrder = await service.resume(tenantId, req.params.id, userId);
|
||||||
if (!workOrder) {
|
if (!workOrder) {
|
||||||
return res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(workOrder);
|
res.json(workOrder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -254,19 +261,20 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* POST /:id/complete
|
* POST /:id/complete
|
||||||
* Completa una orden de trabajo
|
* Completa una orden de trabajo
|
||||||
*/
|
*/
|
||||||
router.post('/:id/complete', async (req: Request, res: Response) => {
|
router.post('/:id/complete', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
|
|
||||||
const workOrder = await service.complete(tenantId, req.params.id, req.body, userId);
|
const workOrder = await service.complete(tenantId, req.params.id, req.body, userId);
|
||||||
if (!workOrder) {
|
if (!workOrder) {
|
||||||
return res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(workOrder);
|
res.json(workOrder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -274,7 +282,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* POST /:id/cancel
|
* POST /:id/cancel
|
||||||
* Cancela una orden de trabajo
|
* Cancela una orden de trabajo
|
||||||
*/
|
*/
|
||||||
router.post('/:id/cancel', async (req: Request, res: Response) => {
|
router.post('/:id/cancel', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
@ -282,12 +290,13 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
|
|
||||||
const workOrder = await service.cancel(tenantId, req.params.id, reason, userId);
|
const workOrder = await service.cancel(tenantId, req.params.id, reason, userId);
|
||||||
if (!workOrder) {
|
if (!workOrder) {
|
||||||
return res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
res.status(404).json({ error: 'Orden de trabajo no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(workOrder);
|
res.json(workOrder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -297,14 +306,14 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* GET /:id/parts
|
* GET /:id/parts
|
||||||
* Lista partes usadas en una orden de trabajo
|
* Lista partes usadas en una orden de trabajo
|
||||||
*/
|
*/
|
||||||
router.get('/:id/parts', async (req: Request, res: Response) => {
|
router.get('/:id/parts', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
|
|
||||||
const parts = await service.getParts(tenantId, req.params.id);
|
const parts = await service.getParts(tenantId, req.params.id);
|
||||||
res.json(parts);
|
res.json(parts);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -312,7 +321,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* POST /:id/parts
|
* POST /:id/parts
|
||||||
* Agrega una parte a la orden de trabajo
|
* Agrega una parte a la orden de trabajo
|
||||||
*/
|
*/
|
||||||
router.post('/:id/parts', async (req: Request, res: Response) => {
|
router.post('/:id/parts', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
@ -320,7 +329,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
const part = await service.addPart(tenantId, req.params.id, req.body, userId);
|
const part = await service.addPart(tenantId, req.params.id, req.body, userId);
|
||||||
res.status(201).json(part);
|
res.status(201).json(part);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -328,19 +337,20 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* PUT /:id/parts/:partId
|
* PUT /:id/parts/:partId
|
||||||
* Actualiza una parte de la orden
|
* Actualiza una parte de la orden
|
||||||
*/
|
*/
|
||||||
router.put('/:id/parts/:partId', async (req: Request, res: Response) => {
|
router.put('/:id/parts/:partId', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
|
|
||||||
const part = await service.updatePart(tenantId, req.params.partId, req.body, userId);
|
const part = await service.updatePart(tenantId, req.params.partId, req.body, userId);
|
||||||
if (!part) {
|
if (!part) {
|
||||||
return res.status(404).json({ error: 'Parte no encontrada' });
|
res.status(404).json({ error: 'Parte no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(part);
|
res.json(part);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -348,19 +358,20 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* DELETE /:id/parts/:partId
|
* DELETE /:id/parts/:partId
|
||||||
* Elimina una parte de la orden
|
* Elimina una parte de la orden
|
||||||
*/
|
*/
|
||||||
router.delete('/:id/parts/:partId', async (req: Request, res: Response) => {
|
router.delete('/:id/parts/:partId', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
|
|
||||||
const deleted = await service.removePart(tenantId, req.params.partId, userId);
|
const deleted = await service.removePart(tenantId, req.params.partId, userId);
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
return res.status(404).json({ error: 'Parte no encontrada' });
|
res.status(404).json({ error: 'Parte no encontrada' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(204).send();
|
res.status(204).send();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -370,7 +381,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* GET /plans
|
* GET /plans
|
||||||
* Lista planes de mantenimiento
|
* Lista planes de mantenimiento
|
||||||
*/
|
*/
|
||||||
router.get('/plans/list', async (req: Request, res: Response) => {
|
router.get('/plans/list', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const assetId = req.query.assetId as string;
|
const assetId = req.query.assetId as string;
|
||||||
@ -378,7 +389,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
const plans = await service.getMaintenancePlans(tenantId, assetId);
|
const plans = await service.getMaintenancePlans(tenantId, assetId);
|
||||||
res.json(plans);
|
res.json(plans);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -386,7 +397,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* POST /plans
|
* POST /plans
|
||||||
* Crea un plan de mantenimiento
|
* Crea un plan de mantenimiento
|
||||||
*/
|
*/
|
||||||
router.post('/plans', async (req: Request, res: Response) => {
|
router.post('/plans', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
@ -394,7 +405,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
const plan = await service.createMaintenancePlan(tenantId, req.body, userId);
|
const plan = await service.createMaintenancePlan(tenantId, req.body, userId);
|
||||||
res.status(201).json(plan);
|
res.status(201).json(plan);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -402,7 +413,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
* POST /plans/:planId/generate
|
* POST /plans/:planId/generate
|
||||||
* Genera órdenes de trabajo desde un plan
|
* Genera órdenes de trabajo desde un plan
|
||||||
*/
|
*/
|
||||||
router.post('/plans/:planId/generate', async (req: Request, res: Response) => {
|
router.post('/plans/:planId/generate', async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const tenantId = req.headers['x-tenant-id'] as string;
|
const tenantId = req.headers['x-tenant-id'] as string;
|
||||||
const userId = (req as any).user?.id;
|
const userId = (req as any).user?.id;
|
||||||
@ -410,7 +421,7 @@ export function createWorkOrderController(dataSource: DataSource): Router {
|
|||||||
const orders = await service.generateFromPlan(tenantId, req.params.planId, userId);
|
const orders = await service.generateFromPlan(tenantId, req.params.planId, userId);
|
||||||
res.status(201).json(orders);
|
res.status(201).json(orders);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(400).json({ error: (error as Error).message });
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,23 @@ export type MaintenanceType = 'preventive' | 'corrective' | 'predictive' | 'emer
|
|||||||
export type WorkOrderStatus = 'draft' | 'scheduled' | 'in_progress' | 'on_hold' | 'completed' | 'cancelled';
|
export type WorkOrderStatus = 'draft' | 'scheduled' | 'in_progress' | 'on_hold' | 'completed' | 'cancelled';
|
||||||
export type WorkOrderPriority = 'low' | 'medium' | 'high' | 'critical';
|
export type WorkOrderPriority = 'low' | 'medium' | 'high' | 'critical';
|
||||||
|
|
||||||
|
// Const objects for runtime use
|
||||||
|
export const WorkOrderStatusValues: Record<string, WorkOrderStatus> = {
|
||||||
|
DRAFT: 'draft',
|
||||||
|
SCHEDULED: 'scheduled',
|
||||||
|
IN_PROGRESS: 'in_progress',
|
||||||
|
ON_HOLD: 'on_hold',
|
||||||
|
COMPLETED: 'completed',
|
||||||
|
CANCELLED: 'cancelled',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const WorkOrderPriorityValues: Record<string, WorkOrderPriority> = {
|
||||||
|
LOW: 'low',
|
||||||
|
MEDIUM: 'medium',
|
||||||
|
HIGH: 'high',
|
||||||
|
CRITICAL: 'critical',
|
||||||
|
} as const;
|
||||||
|
|
||||||
@Entity('work_orders', { schema: 'assets' })
|
@Entity('work_orders', { schema: 'assets' })
|
||||||
@Index(['tenantId', 'workOrderNumber'], { unique: true })
|
@Index(['tenantId', 'workOrderNumber'], { unique: true })
|
||||||
@Index(['tenantId', 'assetId'])
|
@Index(['tenantId', 'assetId'])
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* Logica de negocio para gestion de activos fijos y maquinaria.
|
* Logica de negocio para gestion de activos fijos y maquinaria.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Repository, DataSource, ILike } from 'typeorm';
|
import { Repository, DataSource, IsNull } from 'typeorm';
|
||||||
import { Asset, AssetType, AssetStatus, OwnershipType } from '../entities/asset.entity';
|
import { Asset, AssetType, AssetStatus, OwnershipType } from '../entities/asset.entity';
|
||||||
import { AssetCategory } from '../entities/asset-category.entity';
|
import { AssetCategory } from '../entities/asset-category.entity';
|
||||||
import { AssetAssignment } from '../entities/asset-assignment.entity';
|
import { AssetAssignment } from '../entities/asset-assignment.entity';
|
||||||
@ -94,7 +94,7 @@ export class AssetService {
|
|||||||
private categoryRepository: Repository<AssetCategory>;
|
private categoryRepository: Repository<AssetCategory>;
|
||||||
private assignmentRepository: Repository<AssetAssignment>;
|
private assignmentRepository: Repository<AssetAssignment>;
|
||||||
|
|
||||||
constructor(private dataSource: DataSource) {
|
constructor(dataSource: DataSource) {
|
||||||
this.assetRepository = dataSource.getRepository(Asset);
|
this.assetRepository = dataSource.getRepository(Asset);
|
||||||
this.categoryRepository = dataSource.getRepository(AssetCategory);
|
this.categoryRepository = dataSource.getRepository(AssetCategory);
|
||||||
this.assignmentRepository = dataSource.getRepository(AssetAssignment);
|
this.assignmentRepository = dataSource.getRepository(AssetAssignment);
|
||||||
@ -120,8 +120,8 @@ export class AssetService {
|
|||||||
const asset = this.assetRepository.create({
|
const asset = this.assetRepository.create({
|
||||||
tenantId,
|
tenantId,
|
||||||
...dto,
|
...dto,
|
||||||
status: AssetStatus.AVAILABLE,
|
status: 'available' as AssetStatus,
|
||||||
ownershipType: dto.ownershipType || OwnershipType.OWNED,
|
ownershipType: dto.ownershipType || ('owned' as OwnershipType),
|
||||||
currentBookValue: dto.purchasePrice,
|
currentBookValue: dto.purchasePrice,
|
||||||
createdBy: userId,
|
createdBy: userId,
|
||||||
});
|
});
|
||||||
@ -263,7 +263,7 @@ export class AssetService {
|
|||||||
async delete(tenantId: string, id: string, userId?: string): Promise<boolean> {
|
async delete(tenantId: string, id: string, userId?: string): Promise<boolean> {
|
||||||
const result = await this.assetRepository.update(
|
const result = await this.assetRepository.update(
|
||||||
{ id, tenantId },
|
{ id, tenantId },
|
||||||
{ deletedAt: new Date(), status: AssetStatus.RETIRED, updatedBy: userId }
|
{ deletedAt: new Date(), status: 'retired' as AssetStatus, updatedBy: userId }
|
||||||
);
|
);
|
||||||
return (result.affected ?? 0) > 0;
|
return (result.affected ?? 0) > 0;
|
||||||
}
|
}
|
||||||
@ -315,7 +315,7 @@ export class AssetService {
|
|||||||
// Update asset with new project
|
// Update asset with new project
|
||||||
await this.update(tenantId, dto.assetId, {
|
await this.update(tenantId, dto.assetId, {
|
||||||
currentProjectId: dto.projectId,
|
currentProjectId: dto.projectId,
|
||||||
status: AssetStatus.ASSIGNED,
|
status: 'assigned' as AssetStatus,
|
||||||
assignedOperatorId: dto.operatorId,
|
assignedOperatorId: dto.operatorId,
|
||||||
}, userId);
|
}, userId);
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ export class AssetService {
|
|||||||
// Update asset status
|
// Update asset status
|
||||||
await this.update(tenantId, assetId, {
|
await this.update(tenantId, assetId, {
|
||||||
currentProjectId: undefined,
|
currentProjectId: undefined,
|
||||||
status: AssetStatus.AVAILABLE,
|
status: 'available' as AssetStatus,
|
||||||
}, userId);
|
}, userId);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -405,7 +405,7 @@ export class AssetService {
|
|||||||
*/
|
*/
|
||||||
async getCategories(tenantId: string): Promise<AssetCategory[]> {
|
async getCategories(tenantId: string): Promise<AssetCategory[]> {
|
||||||
return this.categoryRepository.find({
|
return this.categoryRepository.find({
|
||||||
where: { tenantId, isActive: true, deletedAt: null },
|
where: { tenantId, isActive: true, deletedAt: IsNull() },
|
||||||
order: { level: 'ASC', name: 'ASC' },
|
order: { level: 'ASC', name: 'ASC' },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -425,7 +425,7 @@ export class AssetService {
|
|||||||
maintenanceDue: number;
|
maintenanceDue: number;
|
||||||
}> {
|
}> {
|
||||||
const [total, byStatusRaw, byTypeRaw, valueResult, maintenanceDue] = await Promise.all([
|
const [total, byStatusRaw, byTypeRaw, valueResult, maintenanceDue] = await Promise.all([
|
||||||
this.assetRepository.count({ where: { tenantId, deletedAt: null } }),
|
this.assetRepository.count({ where: { tenantId, deletedAt: IsNull() } }),
|
||||||
|
|
||||||
this.assetRepository.createQueryBuilder('asset')
|
this.assetRepository.createQueryBuilder('asset')
|
||||||
.select('asset.status', 'status')
|
.select('asset.status', 'status')
|
||||||
@ -484,7 +484,7 @@ export class AssetService {
|
|||||||
return this.assetRepository.createQueryBuilder('asset')
|
return this.assetRepository.createQueryBuilder('asset')
|
||||||
.where('asset.tenant_id = :tenantId', { tenantId })
|
.where('asset.tenant_id = :tenantId', { tenantId })
|
||||||
.andWhere('asset.deleted_at IS NULL')
|
.andWhere('asset.deleted_at IS NULL')
|
||||||
.andWhere('asset.status != :retired', { retired: AssetStatus.RETIRED })
|
.andWhere('asset.status != :retired', { retired: 'retired' })
|
||||||
.andWhere(
|
.andWhere(
|
||||||
'(asset.next_maintenance_date <= :today OR asset.current_hours >= asset.next_maintenance_hours OR asset.current_kilometers >= asset.next_maintenance_kilometers)',
|
'(asset.next_maintenance_date <= :today OR asset.current_hours >= asset.next_maintenance_hours OR asset.current_kilometers >= asset.next_maintenance_kilometers)',
|
||||||
{ today }
|
{ today }
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* Logica de negocio para registro de combustible y calculo de rendimiento.
|
* Logica de negocio para registro de combustible y calculo de rendimiento.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Repository, DataSource, Between } from 'typeorm';
|
import { Repository, DataSource } from 'typeorm';
|
||||||
import { FuelLog } from '../entities/fuel-log.entity';
|
import { FuelLog } from '../entities/fuel-log.entity';
|
||||||
import { Asset } from '../entities/asset.entity';
|
import { Asset } from '../entities/asset.entity';
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ export class FuelLogService {
|
|||||||
private fuelLogRepository: Repository<FuelLog>;
|
private fuelLogRepository: Repository<FuelLog>;
|
||||||
private assetRepository: Repository<Asset>;
|
private assetRepository: Repository<Asset>;
|
||||||
|
|
||||||
constructor(private dataSource: DataSource) {
|
constructor(dataSource: DataSource) {
|
||||||
this.fuelLogRepository = dataSource.getRepository(FuelLog);
|
this.fuelLogRepository = dataSource.getRepository(FuelLog);
|
||||||
this.assetRepository = dataSource.getRepository(Asset);
|
this.assetRepository = dataSource.getRepository(Asset);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
* Logica de negocio para ordenes de trabajo de mantenimiento.
|
* Logica de negocio para ordenes de trabajo de mantenimiento.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Repository, DataSource, LessThanOrEqual, In } from 'typeorm';
|
import { Repository, DataSource, LessThanOrEqual, In, IsNull } from 'typeorm';
|
||||||
import { WorkOrder, WorkOrderStatus, WorkOrderPriority, MaintenanceType } from '../entities/work-order.entity';
|
import { WorkOrder, WorkOrderStatus, WorkOrderPriority, MaintenanceType, WorkOrderStatusValues, WorkOrderPriorityValues } from '../entities/work-order.entity';
|
||||||
import { WorkOrderPart } from '../entities/work-order-part.entity';
|
import { WorkOrderPart } from '../entities/work-order-part.entity';
|
||||||
import { MaintenanceHistory } from '../entities/maintenance-history.entity';
|
import { MaintenanceHistory } from '../entities/maintenance-history.entity';
|
||||||
import { MaintenancePlan } from '../entities/maintenance-plan.entity';
|
import { MaintenancePlan } from '../entities/maintenance-plan.entity';
|
||||||
@ -102,7 +102,7 @@ export class WorkOrderService {
|
|||||||
private planRepository: Repository<MaintenancePlan>;
|
private planRepository: Repository<MaintenancePlan>;
|
||||||
private assetRepository: Repository<Asset>;
|
private assetRepository: Repository<Asset>;
|
||||||
|
|
||||||
constructor(private dataSource: DataSource) {
|
constructor(dataSource: DataSource) {
|
||||||
this.workOrderRepository = dataSource.getRepository(WorkOrder);
|
this.workOrderRepository = dataSource.getRepository(WorkOrder);
|
||||||
this.partRepository = dataSource.getRepository(WorkOrderPart);
|
this.partRepository = dataSource.getRepository(WorkOrderPart);
|
||||||
this.historyRepository = dataSource.getRepository(MaintenanceHistory);
|
this.historyRepository = dataSource.getRepository(MaintenanceHistory);
|
||||||
@ -153,8 +153,8 @@ export class WorkOrderService {
|
|||||||
assetCode: asset.assetCode,
|
assetCode: asset.assetCode,
|
||||||
assetName: asset.name,
|
assetName: asset.name,
|
||||||
maintenanceType: dto.maintenanceType,
|
maintenanceType: dto.maintenanceType,
|
||||||
priority: dto.priority || WorkOrderPriority.MEDIUM,
|
priority: dto.priority || WorkOrderPriorityValues.MEDIUM,
|
||||||
status: WorkOrderStatus.DRAFT,
|
status: WorkOrderStatusValues.DRAFT,
|
||||||
title: dto.title,
|
title: dto.title,
|
||||||
description: dto.description,
|
description: dto.description,
|
||||||
problemReported: dto.problemReported,
|
problemReported: dto.problemReported,
|
||||||
@ -290,15 +290,15 @@ export class WorkOrderService {
|
|||||||
*/
|
*/
|
||||||
private validateStatusTransition(from: WorkOrderStatus, to: WorkOrderStatus): void {
|
private validateStatusTransition(from: WorkOrderStatus, to: WorkOrderStatus): void {
|
||||||
const validTransitions: Record<WorkOrderStatus, WorkOrderStatus[]> = {
|
const validTransitions: Record<WorkOrderStatus, WorkOrderStatus[]> = {
|
||||||
[WorkOrderStatus.DRAFT]: [WorkOrderStatus.SCHEDULED, WorkOrderStatus.IN_PROGRESS, WorkOrderStatus.CANCELLED],
|
draft: ['scheduled', 'in_progress', 'cancelled'],
|
||||||
[WorkOrderStatus.SCHEDULED]: [WorkOrderStatus.IN_PROGRESS, WorkOrderStatus.CANCELLED],
|
scheduled: ['in_progress', 'cancelled'],
|
||||||
[WorkOrderStatus.IN_PROGRESS]: [WorkOrderStatus.ON_HOLD, WorkOrderStatus.COMPLETED, WorkOrderStatus.CANCELLED],
|
in_progress: ['on_hold', 'completed', 'cancelled'],
|
||||||
[WorkOrderStatus.ON_HOLD]: [WorkOrderStatus.IN_PROGRESS, WorkOrderStatus.CANCELLED],
|
on_hold: ['in_progress', 'cancelled'],
|
||||||
[WorkOrderStatus.COMPLETED]: [],
|
completed: [],
|
||||||
[WorkOrderStatus.CANCELLED]: [],
|
cancelled: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!validTransitions[from].includes(to)) {
|
if (!validTransitions[from]?.includes(to)) {
|
||||||
throw new Error(`Invalid status transition from ${from} to ${to}`);
|
throw new Error(`Invalid status transition from ${from} to ${to}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,12 +310,12 @@ export class WorkOrderService {
|
|||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
switch (newStatus) {
|
switch (newStatus) {
|
||||||
case WorkOrderStatus.IN_PROGRESS:
|
case 'in_progress':
|
||||||
if (!workOrder.actualStartDate) {
|
if (!workOrder.actualStartDate) {
|
||||||
workOrder.actualStartDate = now;
|
workOrder.actualStartDate = now;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WorkOrderStatus.COMPLETED:
|
case 'completed':
|
||||||
workOrder.actualEndDate = now;
|
workOrder.actualEndDate = now;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -325,7 +325,7 @@ export class WorkOrderService {
|
|||||||
* Start work order (change to in_progress)
|
* Start work order (change to in_progress)
|
||||||
*/
|
*/
|
||||||
async start(tenantId: string, id: string, userId?: string): Promise<WorkOrder | null> {
|
async start(tenantId: string, id: string, userId?: string): Promise<WorkOrder | null> {
|
||||||
return this.update(tenantId, id, { status: WorkOrderStatus.IN_PROGRESS }, userId);
|
return this.update(tenantId, id, { status: 'in_progress' }, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,7 +336,7 @@ export class WorkOrderService {
|
|||||||
if (!workOrder) return null;
|
if (!workOrder) return null;
|
||||||
|
|
||||||
// Update work order
|
// Update work order
|
||||||
workOrder.status = WorkOrderStatus.COMPLETED;
|
workOrder.status = 'completed';
|
||||||
workOrder.actualEndDate = new Date();
|
workOrder.actualEndDate = new Date();
|
||||||
workOrder.workPerformed = dto.workPerformed;
|
workOrder.workPerformed = dto.workPerformed;
|
||||||
workOrder.findings = dto.findings;
|
workOrder.findings = dto.findings;
|
||||||
@ -454,7 +454,7 @@ export class WorkOrderService {
|
|||||||
|
|
||||||
const [total, byStatusRaw, byTypeRaw, pendingCount, inProgressCount, completedThisMonth, costResult] =
|
const [total, byStatusRaw, byTypeRaw, pendingCount, inProgressCount, completedThisMonth, costResult] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.workOrderRepository.count({ where: { tenantId, deletedAt: null } }),
|
this.workOrderRepository.count({ where: { tenantId, deletedAt: IsNull() } }),
|
||||||
|
|
||||||
this.workOrderRepository.createQueryBuilder('wo')
|
this.workOrderRepository.createQueryBuilder('wo')
|
||||||
.select('wo.status', 'status')
|
.select('wo.status', 'status')
|
||||||
@ -473,23 +473,23 @@ export class WorkOrderService {
|
|||||||
.getRawMany(),
|
.getRawMany(),
|
||||||
|
|
||||||
this.workOrderRepository.count({
|
this.workOrderRepository.count({
|
||||||
where: { tenantId, status: WorkOrderStatus.DRAFT, deletedAt: null },
|
where: { tenantId, status: 'draft' as WorkOrderStatus, deletedAt: IsNull() },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
this.workOrderRepository.count({
|
this.workOrderRepository.count({
|
||||||
where: { tenantId, status: WorkOrderStatus.IN_PROGRESS, deletedAt: null },
|
where: { tenantId, status: 'in_progress' as WorkOrderStatus, deletedAt: IsNull() },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
this.workOrderRepository.createQueryBuilder('wo')
|
this.workOrderRepository.createQueryBuilder('wo')
|
||||||
.where('wo.tenant_id = :tenantId', { tenantId })
|
.where('wo.tenant_id = :tenantId', { tenantId })
|
||||||
.andWhere('wo.status = :status', { status: WorkOrderStatus.COMPLETED })
|
.andWhere('wo.status = :status', { status: 'completed' as WorkOrderStatus })
|
||||||
.andWhere('wo.actual_end_date >= :startOfMonth', { startOfMonth })
|
.andWhere('wo.actual_end_date >= :startOfMonth', { startOfMonth })
|
||||||
.getCount(),
|
.getCount(),
|
||||||
|
|
||||||
this.workOrderRepository.createQueryBuilder('wo')
|
this.workOrderRepository.createQueryBuilder('wo')
|
||||||
.select('SUM(wo.total_cost)', 'total')
|
.select('SUM(wo.total_cost)', 'total')
|
||||||
.where('wo.tenant_id = :tenantId', { tenantId })
|
.where('wo.tenant_id = :tenantId', { tenantId })
|
||||||
.andWhere('wo.status = :status', { status: WorkOrderStatus.COMPLETED })
|
.andWhere('wo.status = :status', { status: 'completed' as WorkOrderStatus })
|
||||||
.andWhere('wo.actual_end_date >= :startOfMonth', { startOfMonth })
|
.andWhere('wo.actual_end_date >= :startOfMonth', { startOfMonth })
|
||||||
.getRawOne(),
|
.getRawOne(),
|
||||||
]);
|
]);
|
||||||
@ -520,18 +520,18 @@ export class WorkOrderService {
|
|||||||
*/
|
*/
|
||||||
async getByStatus(tenantId: string): Promise<Record<WorkOrderStatus, WorkOrder[]>> {
|
async getByStatus(tenantId: string): Promise<Record<WorkOrderStatus, WorkOrder[]>> {
|
||||||
const workOrders = await this.workOrderRepository.find({
|
const workOrders = await this.workOrderRepository.find({
|
||||||
where: { tenantId, deletedAt: null },
|
where: { tenantId, deletedAt: IsNull() },
|
||||||
relations: ['asset'],
|
relations: ['asset'],
|
||||||
order: { requestedDate: 'DESC' },
|
order: { requestedDate: 'DESC' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const grouped: Record<WorkOrderStatus, WorkOrder[]> = {
|
const grouped: Record<WorkOrderStatus, WorkOrder[]> = {
|
||||||
[WorkOrderStatus.DRAFT]: [],
|
draft: [],
|
||||||
[WorkOrderStatus.SCHEDULED]: [],
|
scheduled: [],
|
||||||
[WorkOrderStatus.IN_PROGRESS]: [],
|
in_progress: [],
|
||||||
[WorkOrderStatus.ON_HOLD]: [],
|
on_hold: [],
|
||||||
[WorkOrderStatus.COMPLETED]: [],
|
completed: [],
|
||||||
[WorkOrderStatus.CANCELLED]: [],
|
cancelled: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const wo of workOrders) {
|
for (const wo of workOrders) {
|
||||||
@ -548,9 +548,9 @@ export class WorkOrderService {
|
|||||||
const workOrder = await this.findById(tenantId, id);
|
const workOrder = await this.findById(tenantId, id);
|
||||||
if (!workOrder) return null;
|
if (!workOrder) return null;
|
||||||
|
|
||||||
this.validateStatusTransition(workOrder.status, WorkOrderStatus.ON_HOLD);
|
this.validateStatusTransition(workOrder.status, 'on_hold' as WorkOrderStatus);
|
||||||
|
|
||||||
workOrder.status = WorkOrderStatus.ON_HOLD;
|
workOrder.status = 'on_hold' as WorkOrderStatus;
|
||||||
workOrder.notes = reason ? `${workOrder.notes || ''}\n[ON HOLD] ${reason}` : workOrder.notes;
|
workOrder.notes = reason ? `${workOrder.notes || ''}\n[ON HOLD] ${reason}` : workOrder.notes;
|
||||||
workOrder.updatedBy = userId;
|
workOrder.updatedBy = userId;
|
||||||
|
|
||||||
@ -564,9 +564,9 @@ export class WorkOrderService {
|
|||||||
const workOrder = await this.findById(tenantId, id);
|
const workOrder = await this.findById(tenantId, id);
|
||||||
if (!workOrder) return null;
|
if (!workOrder) return null;
|
||||||
|
|
||||||
this.validateStatusTransition(workOrder.status, WorkOrderStatus.IN_PROGRESS);
|
this.validateStatusTransition(workOrder.status, 'in_progress' as WorkOrderStatus);
|
||||||
|
|
||||||
workOrder.status = WorkOrderStatus.IN_PROGRESS;
|
workOrder.status = 'in_progress' as WorkOrderStatus;
|
||||||
workOrder.updatedBy = userId;
|
workOrder.updatedBy = userId;
|
||||||
|
|
||||||
return this.workOrderRepository.save(workOrder);
|
return this.workOrderRepository.save(workOrder);
|
||||||
@ -579,9 +579,9 @@ export class WorkOrderService {
|
|||||||
const workOrder = await this.findById(tenantId, id);
|
const workOrder = await this.findById(tenantId, id);
|
||||||
if (!workOrder) return null;
|
if (!workOrder) return null;
|
||||||
|
|
||||||
this.validateStatusTransition(workOrder.status, WorkOrderStatus.CANCELLED);
|
this.validateStatusTransition(workOrder.status, 'cancelled' as WorkOrderStatus);
|
||||||
|
|
||||||
workOrder.status = WorkOrderStatus.CANCELLED;
|
workOrder.status = 'cancelled' as WorkOrderStatus;
|
||||||
workOrder.notes = reason ? `${workOrder.notes || ''}\n[CANCELLED] ${reason}` : workOrder.notes;
|
workOrder.notes = reason ? `${workOrder.notes || ''}\n[CANCELLED] ${reason}` : workOrder.notes;
|
||||||
workOrder.updatedBy = userId;
|
workOrder.updatedBy = userId;
|
||||||
|
|
||||||
@ -612,7 +612,7 @@ export class WorkOrderService {
|
|||||||
/**
|
/**
|
||||||
* Update a part
|
* Update a part
|
||||||
*/
|
*/
|
||||||
async updatePart(tenantId: string, partId: string, dto: Partial<AddPartDto>, userId?: string): Promise<WorkOrderPart | null> {
|
async updatePart(tenantId: string, partId: string, dto: Partial<AddPartDto>, _userId?: string): Promise<WorkOrderPart | null> {
|
||||||
const part = await this.partRepository.findOne({ where: { id: partId, tenantId } });
|
const part = await this.partRepository.findOne({ where: { id: partId, tenantId } });
|
||||||
if (!part) return null;
|
if (!part) return null;
|
||||||
|
|
||||||
@ -625,7 +625,6 @@ export class WorkOrderService {
|
|||||||
if (part.unitCost && part.quantityUsed) {
|
if (part.unitCost && part.quantityUsed) {
|
||||||
part.totalCost = part.unitCost * part.quantityUsed;
|
part.totalCost = part.unitCost * part.quantityUsed;
|
||||||
}
|
}
|
||||||
part.updatedBy = userId;
|
|
||||||
|
|
||||||
const savedPart = await this.partRepository.save(part);
|
const savedPart = await this.partRepository.save(part);
|
||||||
await this.recalculatePartsCost(part.workOrderId);
|
await this.recalculatePartsCost(part.workOrderId);
|
||||||
@ -636,7 +635,7 @@ export class WorkOrderService {
|
|||||||
/**
|
/**
|
||||||
* Remove a part from work order
|
* Remove a part from work order
|
||||||
*/
|
*/
|
||||||
async removePart(tenantId: string, partId: string, userId?: string): Promise<boolean> {
|
async removePart(tenantId: string, partId: string, _userId?: string): Promise<boolean> {
|
||||||
const part = await this.partRepository.findOne({ where: { id: partId, tenantId } });
|
const part = await this.partRepository.findOne({ where: { id: partId, tenantId } });
|
||||||
if (!part) return false;
|
if (!part) return false;
|
||||||
|
|
||||||
@ -657,7 +656,7 @@ export class WorkOrderService {
|
|||||||
where: {
|
where: {
|
||||||
tenantId,
|
tenantId,
|
||||||
deletedAt: undefined,
|
deletedAt: undefined,
|
||||||
status: In([WorkOrderStatus.DRAFT, WorkOrderStatus.SCHEDULED, WorkOrderStatus.IN_PROGRESS]),
|
status: In(['draft' as WorkOrderStatus, 'scheduled' as WorkOrderStatus, 'in_progress' as WorkOrderStatus]),
|
||||||
scheduledEndDate: LessThanOrEqual(now),
|
scheduledEndDate: LessThanOrEqual(now),
|
||||||
},
|
},
|
||||||
relations: ['asset'],
|
relations: ['asset'],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user