import { BadRequestException, Injectable, NotFoundException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Queue } from './entities/queue.entity'; import { CreateQueueDto } from './dto/create-queue.dto'; import { UpdateQueueDto } from './dto/update-queue.dto'; import { Machine } from '@/machines/entities/machine.entity'; import { Page } from '@/pages/entities/page.entity'; import { Order } from '@/orders/entities/order.entity'; import { Employee } from '@/employees/entities/employee.entity'; @Injectable() export class QueuesService { constructor( @InjectRepository(Queue) private readonly queueRepository: Repository<Queue>, @InjectRepository(Machine) private readonly machineRepository: Repository<Machine>, @InjectRepository(Page) private readonly pageRepository: Repository<Page>, @InjectRepository(Order) private readonly orderRepository: Repository<Order>, @InjectRepository(Employee) private readonly employeeRepository: Repository<Employee>, ) {} async create(createQueueDto: CreateQueueDto) { const { MachineID, PageID, OrderID, EmployeeIds, ...queueData } = createQueueDto; // console.log('📌 Received CreateQueueDto:', createQueueDto); // 🔍 Fetch related entities const machine = await this.machineRepository.findOne({ where: { MachineID }, }); if (!machine) throw new NotFoundException(`Machine with ID ${MachineID} not found`); const page = await this.pageRepository.findOne({ where: { PageID } }); if (!page) throw new NotFoundException(`Page with ID ${PageID} not found`); const order = await this.orderRepository.findOne({ where: { OrderID } }); if (!order) throw new NotFoundException(`Order with ID ${OrderID} not found`); const employees = await this.employeeRepository.findByIds(EmployeeIds); if (employees.length !== EmployeeIds.length) { throw new NotFoundException(`One or more employees not found`); } // console.log('✅ Related Entities Fetched:'); // console.log(' - Machine:', machine); // console.log(' - Page:', page); // console.log(' - Order:', order); // console.log(' - Employees:', employees); // ✅ Create Queue entity and save to DB const newQueue = this.queueRepository.create({ ...queueData, machine, page, order, employees, }); // console.log('🛠️ Preparing to save new Queue:', newQueue); const savedQueue = await this.queueRepository.save(newQueue); // console.log('✅ Queue saved successfully:', savedQueue); // ✅ Return the response with full details return { message: 'Queue created successfully', queue: savedQueue, }; } async createMultiple(createQueueDtos: CreateQueueDto[]) { const newQueues = []; if (!Array.isArray(createQueueDtos)) { throw new BadRequestException('Request body must be an array of queues'); } for (const createQueueDto of createQueueDtos) { const { MachineID, PageID, OrderID, EmployeeIds, ...queueData } = createQueueDto; // console.log('👉 Raw EmployeeIds:', EmployeeIds); // ✅ ตรวจสอบว่า `EmployeeIds` เป็น Array ที่ไม่ว่าง if (!Array.isArray(EmployeeIds) || EmployeeIds.length === 0) { throw new BadRequestException(`EmployeeIds must be a non-empty array`); } // ✅ แปลงค่าให้เป็นตัวเลข และกรองค่าที่ไม่ถูกต้อง const validEmployeeIds = EmployeeIds.map((id) => Number(id)).filter( (id) => !isNaN(id) && id > 0, ); // console.log('✅ Valid EmployeeIds:', validEmployeeIds); if (validEmployeeIds.length !== EmployeeIds.length) { throw new BadRequestException( `Invalid EmployeeIds provided: ${EmployeeIds}`, ); } // ✅ ตรวจสอบและแปลง `MachineID`, `OrderID`, `PageID` const machineId = Number(MachineID); if (isNaN(machineId)) throw new BadRequestException(`Invalid MachineID: ${MachineID}`); const orderId = Number(OrderID); if (isNaN(orderId)) throw new BadRequestException(`Invalid OrderID: ${OrderID}`); let pageId: number | null = null; if (PageID !== null && PageID !== undefined) { pageId = Number(PageID); if (isNaN(pageId)) throw new BadRequestException(`Invalid PageID: ${PageID}`); } // 🔍 ค้นหา Entity ที่เกี่ยวข้อง const machine = await this.machineRepository.findOne({ where: { MachineID: machineId }, }); if (!machine) throw new NotFoundException(`Machine with ID ${machineId} not found`); const page = pageId !== null ? await this.pageRepository.findOne({ where: { PageID: pageId } }) : null; if (pageId !== null && !page) throw new NotFoundException(`Page with ID ${pageId} not found`); const order = await this.orderRepository.findOne({ where: { OrderID: orderId }, }); if (!order) throw new NotFoundException(`Order with ID ${orderId} not found`); // 🔍 ค้นหา Employees ที่มีอยู่ในฐานข้อมูล const employees = await this.employeeRepository.findByIds(validEmployeeIds); const foundIds = employees.map((e) => e.EmployeeID); const missingIds = validEmployeeIds.filter( (id) => !foundIds.includes(id), ); if (missingIds.length > 0) { console.error(`❌ Missing EmployeeIDs: ${missingIds.join(', ')}`); throw new NotFoundException( `Employees not found: ${missingIds.join(', ')}`, ); } // ✅ สร้าง Queue object const newQueue = this.queueRepository.create({ ...queueData, machine, page, order, employees, }); newQueues.push(newQueue); } // ✅ บันทึกทั้งหมดพร้อมกัน const savedQueues = await this.queueRepository.save(newQueues); return { message: `${savedQueues.length} queues created successfully`, queues: savedQueues, }; } // ✅ Fetch all Queues with relationships async findAll() { return await this.queueRepository.find({ relations: ['machine', 'page', 'order', 'employees'], }); } // ✅ Fetch a single Queue by ID async findOne(id: number) { const queue = await this.queueRepository.findOne({ where: { QueueID: id }, relations: ['machine', 'page', 'order', 'employees'], }); if (!queue) { throw new NotFoundException(`Queue with ID ${id} not found`); } return queue; } // ✅ Update Queue async update(id: number, updateQueueDto: UpdateQueueDto) { try { console.log('🔄 Updating Queue ID:', id, updateQueueDto); const { MachineID, PageID, OrderID, EmployeeIds, startTime, finishTime, ...queueData } = updateQueueDto; // 🔍 ค้นหา Queue ที่จะอัปเดต const existingQueue = await this.queueRepository.findOne({ where: { QueueID: id }, relations: ['machine', 'page', 'order', 'employees'], }); if (!existingQueue) { throw new NotFoundException(`Queue with ID ${id} not found`); } // 🔍 Fetch entities if IDs are provided const machine = MachineID ? await this.machineRepository.findOne({ where: { MachineID } }) : existingQueue.machine; if (MachineID && !machine) throw new NotFoundException(`Machine with ID ${MachineID} not found`); const page = PageID ? await this.pageRepository.findOne({ where: { PageID } }) : existingQueue.page; if (PageID && !page) throw new NotFoundException(`Page with ID ${PageID} not found`); const order = OrderID ? await this.orderRepository.findOne({ where: { OrderID } }) : existingQueue.order; if (OrderID && !order) throw new NotFoundException(`Order with ID ${OrderID} not found`); // 🔍 ค้นหา Employees และคำนวณการเชื่อมโยง let employees = existingQueue.employees; if (EmployeeIds) { const fetchedEmployees = await this.employeeRepository.findByIds(EmployeeIds); if (fetchedEmployees.length !== EmployeeIds.length) { throw new NotFoundException(`One or more employees not found`); } employees = fetchedEmployees; } // ✅ Convert timestamps from string to Date const updateData: Partial<Queue> = { ...queueData, machine, page, order, employees, startTime: startTime ? new Date(startTime) : existingQueue.startTime, finishTime: finishTime ? new Date(finishTime) : existingQueue.finishTime, }; // ✅ ใช้ `save()` แทน `update()` เพื่อรองรับ Many-to-Many (employees) const updatedQueue = await this.queueRepository.save({ ...existingQueue, ...updateData, }); console.log('✅ Queue updated successfully:', updatedQueue); return updatedQueue; } catch (error) { console.error('❌ Error in updateQueue:', error); throw new Error('Database update failed'); } } // ✅ Delete Queue async remove(id: number) { const queue = await this.queueRepository.findOne({ where: { QueueID: id }, relations: ['machine', 'page', 'order', 'employees'], }); if (!queue) { throw new NotFoundException(`Queue with ID ${id} not found`); } await this.queueRepository.delete(id); return { message: 'Queue deleted successfully', deletedQueue: queue }; } }