import { Request, Response, NextFunction, Router } from 'express'; import { SalesService } from '../services'; import { CreateQuotationDto, UpdateQuotationDto, CreateSalesOrderDto, UpdateSalesOrderDto } from '../dto'; export class QuotationsController { public router: Router; constructor(private readonly salesService: SalesService) { this.router = Router(); this.router.get('/', this.findAll.bind(this)); this.router.get('/:id', this.findOne.bind(this)); this.router.post('/', this.create.bind(this)); this.router.patch('/:id', this.update.bind(this)); this.router.delete('/:id', this.delete.bind(this)); this.router.post('/:id/convert', this.convert.bind(this)); } private async findAll(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const { partnerId, status, userId, limit, offset } = req.query; const result = await this.salesService.findAllQuotations({ tenantId, partnerId: partnerId as string, status: status as string, userId: userId as string, limit: limit ? parseInt(limit as string) : undefined, offset: offset ? parseInt(offset as string) : undefined }); res.json(result); } catch (e) { next(e); } } private async findOne(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const quotation = await this.salesService.findQuotation(req.params.id, tenantId); if (!quotation) { res.status(404).json({ error: 'Not found' }); return; } res.json({ data: quotation }); } catch (e) { next(e); } } private async create(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; const userId = req.headers['x-user-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const quotation = await this.salesService.createQuotation(tenantId, req.body, userId); res.status(201).json({ data: quotation }); } catch (e) { next(e); } } private async update(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; const userId = req.headers['x-user-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const quotation = await this.salesService.updateQuotation(req.params.id, tenantId, req.body, userId); if (!quotation) { res.status(404).json({ error: 'Not found' }); return; } res.json({ data: quotation }); } catch (e) { next(e); } } private async delete(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const deleted = await this.salesService.deleteQuotation(req.params.id, tenantId); if (!deleted) { res.status(404).json({ error: 'Not found' }); return; } res.status(204).send(); } catch (e) { next(e); } } private async convert(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; const userId = req.headers['x-user-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const order = await this.salesService.convertQuotationToOrder(req.params.id, tenantId, userId); res.json({ data: order }); } catch (e) { next(e); } } } export class SalesOrdersController { public router: Router; constructor(private readonly salesService: SalesService) { this.router = Router(); this.router.get('/', this.findAll.bind(this)); this.router.get('/:id', this.findOne.bind(this)); this.router.post('/', this.create.bind(this)); this.router.patch('/:id', this.update.bind(this)); this.router.delete('/:id', this.delete.bind(this)); this.router.post('/:id/confirm', this.confirm.bind(this)); this.router.post('/:id/ship', this.ship.bind(this)); this.router.post('/:id/deliver', this.deliver.bind(this)); } private async findAll(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const { partnerId, status, userId, limit, offset } = req.query; const result = await this.salesService.findAllOrders({ tenantId, partnerId: partnerId as string, status: status as string, userId: userId as string, limit: limit ? parseInt(limit as string) : undefined, offset: offset ? parseInt(offset as string) : undefined }); res.json(result); } catch (e) { next(e); } } private async findOne(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const order = await this.salesService.findOrder(req.params.id, tenantId); if (!order) { res.status(404).json({ error: 'Not found' }); return; } res.json({ data: order }); } catch (e) { next(e); } } private async create(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; const userId = req.headers['x-user-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const order = await this.salesService.createSalesOrder(tenantId, req.body, userId); res.status(201).json({ data: order }); } catch (e) { next(e); } } private async update(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; const userId = req.headers['x-user-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const order = await this.salesService.updateSalesOrder(req.params.id, tenantId, req.body, userId); if (!order) { res.status(404).json({ error: 'Not found' }); return; } res.json({ data: order }); } catch (e) { next(e); } } private async delete(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const deleted = await this.salesService.deleteSalesOrder(req.params.id, tenantId); if (!deleted) { res.status(404).json({ error: 'Not found' }); return; } res.status(204).send(); } catch (e) { next(e); } } private async confirm(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; const userId = req.headers['x-user-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const order = await this.salesService.confirmOrder(req.params.id, tenantId, userId); if (!order) { res.status(400).json({ error: 'Cannot confirm' }); return; } res.json({ data: order }); } catch (e) { next(e); } } private async ship(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; const userId = req.headers['x-user-id'] as string; const { trackingNumber, carrier } = req.body; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const order = await this.salesService.shipOrder(req.params.id, tenantId, trackingNumber, carrier, userId); if (!order) { res.status(400).json({ error: 'Cannot ship' }); return; } res.json({ data: order }); } catch (e) { next(e); } } private async deliver(req: Request, res: Response, next: NextFunction) { try { const tenantId = req.headers['x-tenant-id'] as string; const userId = req.headers['x-user-id'] as string; if (!tenantId) { res.status(400).json({ error: 'Tenant ID required' }); return; } const order = await this.salesService.deliverOrder(req.params.id, tenantId, userId); if (!order) { res.status(400).json({ error: 'Cannot deliver' }); return; } res.json({ data: order }); } catch (e) { next(e); } } }