const { CattleBatch, IotCattle, Farm, CattleBatchAnimal, User } = require('../models'); const { Op } = require('sequelize'); /** * 批次设置控制器 */ class CattleBatchController { /** * 获取批次列表 */ async getBatches(req, res) { try { const { page = 1, pageSize = 10, search, type, status } = req.query; const offset = (page - 1) * pageSize; console.log('🔍 [后端-批次设置] 搜索请求参数:', { page, pageSize, search, type, status }); // 构建查询条件 const where = {}; if (search) { where[Op.or] = [ { name: { [Op.like]: `%${search}%` } }, { code: { [Op.like]: `%${search}%` } } ]; console.log('🔍 [后端-批次设置] 搜索条件:', where[Op.or]); } if (type) { where.type = type; } if (status) { where.status = status; } const { count, rows } = await CattleBatch.findAndCountAll({ where, include: [ { model: Farm, as: 'farm', attributes: ['id', 'name'] } ], limit: parseInt(pageSize), offset: offset, order: [['created_at', 'DESC']] }); console.log('🔍 [后端-批次设置] 查询结果:', { 总数: count, 当前页数据量: rows.length, 搜索关键词: search, 查询条件: where }); res.json({ success: true, data: { list: rows, total: count, page: parseInt(page), pageSize: parseInt(pageSize) }, message: '获取批次列表成功' }); } catch (error) { console.error('获取批次列表失败:', error); res.status(500).json({ success: false, message: '获取批次列表失败', error: error.message }); } } /** * 获取批次详情 */ async getBatchById(req, res) { try { const { id } = req.params; const batch = await CattleBatch.findByPk(id, { include: [ { model: Farm, as: 'farm', attributes: ['id', 'name'] } ] }); if (!batch) { return res.status(404).json({ success: false, message: '批次不存在' }); } res.json({ success: true, data: batch, message: '获取批次详情成功' }); } catch (error) { console.error('获取批次详情失败:', error); res.status(500).json({ success: false, message: '获取批次详情失败', error: error.message }); } } /** * 创建批次 */ async createBatch(req, res) { try { console.log('🆕 [后端-批次设置] 开始创建操作'); console.log('📋 [后端-批次设置] 请求数据:', req.body); const { name, code, type, startDate, expectedEndDate, actualEndDate, targetCount, currentCount, manager, status, remark, farmId } = req.body; // 验证必填字段 if (!name || !code || !type || !startDate || !targetCount || !manager) { console.log('❌ [后端-批次设置] 必填字段验证失败:', { name: !!name, code: !!code, type: !!type, startDate: !!startDate, targetCount: !!targetCount, manager: !!manager }); return res.status(400).json({ success: false, message: '请填写所有必填字段(批次名称、编号、类型、开始日期、目标数量、负责人)' }); } // 检查批次编号是否已存在 const existingBatch = await CattleBatch.findOne({ where: { code } }); if (existingBatch) { console.log('❌ [后端-批次设置] 批次编号已存在:', code); return res.status(400).json({ success: false, message: '批次编号已存在' }); } // 检查农场是否存在 const farm = await Farm.findByPk(farmId); if (!farm) { console.log('❌ [后端-批次设置] 农场不存在:', farmId); return res.status(400).json({ success: false, message: '农场不存在' }); } // 准备创建数据 const createData = { name, code, type, startDate: new Date(startDate), expectedEndDate: expectedEndDate ? new Date(expectedEndDate) : null, actualEndDate: actualEndDate ? new Date(actualEndDate) : null, targetCount: parseInt(targetCount), currentCount: currentCount ? parseInt(currentCount) : 0, manager, status: status || '进行中', remark: remark || '', farmId: farmId || 1 }; console.log('📝 [后端-批次设置] 准备创建的数据:', createData); const batch = await CattleBatch.create(createData); console.log('✅ [后端-批次设置] 批次创建成功:', batch.id); res.status(201).json({ success: true, data: batch, message: '创建批次成功' }); } catch (error) { console.error('❌ [后端-批次设置] 创建失败:', error); res.status(500).json({ success: false, message: '创建批次失败', error: error.message }); } } /** * 更新批次 */ async updateBatch(req, res) { try { const { id } = req.params; const updateData = req.body; console.log('🔄 [后端-批次设置] 开始更新操作'); console.log('📋 [后端-批次设置] 请求参数:', { batchId: id, updateData: updateData }); const batch = await CattleBatch.findByPk(id); if (!batch) { console.log('❌ [后端-批次设置] 批次不存在,ID:', id); return res.status(404).json({ success: false, message: '批次不存在' }); } console.log('📝 [后端-批次设置] 原始批次数据:', { id: batch.id, name: batch.name, code: batch.code, type: batch.type, description: batch.description, status: batch.status, startDate: batch.startDate, expectedEndDate: batch.expectedEndDate, actualEndDate: batch.actualEndDate, targetCount: batch.targetCount, currentCount: batch.currentCount, manager: batch.manager, remark: batch.remark, farmId: batch.farmId }); // 如果更新编号,检查是否已存在 if (updateData.code && updateData.code !== batch.code) { console.log('🔄 [后端-批次设置] 检测到编号变更,检查是否已存在'); console.log('📝 [后端-批次设置] 编号变更详情:', { oldCode: batch.code, newCode: updateData.code }); const existingBatch = await CattleBatch.findOne({ where: { code: updateData.code, id: { [Op.ne]: id } } }); if (existingBatch) { console.log('❌ [后端-批次设置] 批次编号已存在'); return res.status(400).json({ success: false, message: '批次编号已存在' }); } console.log('✅ [后端-批次设置] 批次编号可用'); } await batch.update(updateData); console.log('✅ [后端-批次设置] 批次更新成功'); res.json({ success: true, data: batch, message: '更新批次成功' }); } catch (error) { console.error('❌ [后端-批次设置] 更新失败:', error); res.status(500).json({ success: false, message: '更新批次失败', error: error.message }); } } /** * 删除批次 */ async deleteBatch(req, res) { try { const { id } = req.params; const batch = await CattleBatch.findByPk(id); if (!batch) { return res.status(404).json({ success: false, message: '批次不存在' }); } // 检查是否有牛只在批次中 const animalCount = await CattleBatchAnimal.count({ where: { batchId: id } }); if (animalCount > 0) { return res.status(400).json({ success: false, message: '批次中还有牛只,无法删除' }); } await batch.destroy(); res.json({ success: true, message: '删除批次成功' }); } catch (error) { console.error('删除批次失败:', error); res.status(500).json({ success: false, message: '删除批次失败', error: error.message }); } } /** * 批量删除批次 */ async batchDeleteBatches(req, res) { try { const { ids } = req.body; if (!ids || !Array.isArray(ids) || ids.length === 0) { return res.status(400).json({ success: false, message: '请选择要删除的批次' }); } // 检查是否有批次包含牛只 const animalCount = await CattleBatchAnimal.count({ where: { batchId: { [Op.in]: ids } } }); if (animalCount > 0) { return res.status(400).json({ success: false, message: '部分批次中还有牛只,无法删除' }); } await CattleBatch.destroy({ where: { id: { [Op.in]: ids } } }); res.json({ success: true, message: `成功删除 ${ids.length} 个批次` }); } catch (error) { console.error('批量删除批次失败:', error); res.status(500).json({ success: false, message: '批量删除批次失败', error: error.message }); } } /** * 获取批次中的牛只 */ async getBatchAnimals(req, res) { try { const { id } = req.params; const { page = 1, pageSize = 10 } = req.query; const offset = (page - 1) * pageSize; // 检查批次是否存在 const batch = await CattleBatch.findByPk(id); if (!batch) { return res.status(404).json({ success: false, message: '批次不存在' }); } // 获取批次中的牛只 const { count, rows } = await IotCattle.findAndCountAll({ include: [ { model: CattleBatchAnimal, as: 'batchAnimals', where: { batchId: id }, attributes: ['id', 'joinDate', 'notes'] }, { model: Farm, as: 'farm', attributes: ['id', 'name'] } ], attributes: ['id', 'earNumber', 'sex', 'strain', 'orgId'], limit: parseInt(pageSize), offset: offset, order: [['earNumber', 'ASC']] }); res.json({ success: true, data: { list: rows, total: count, page: parseInt(page), pageSize: parseInt(pageSize) }, message: '获取批次牛只成功' }); } catch (error) { console.error('获取批次牛只失败:', error); res.status(500).json({ success: false, message: '获取批次牛只失败', error: error.message }); } } /** * 添加牛只到批次 */ async addAnimalsToBatch(req, res) { try { const { id } = req.params; const { animalIds } = req.body; if (!animalIds || !Array.isArray(animalIds) || animalIds.length === 0) { return res.status(400).json({ success: false, message: '请选择要添加的牛只' }); } // 检查批次是否存在 const batch = await CattleBatch.findByPk(id); if (!batch) { return res.status(404).json({ success: false, message: '批次不存在' }); } // 检查牛只是否存在 const animals = await IotCattle.findAll({ where: { id: { [Op.in]: animalIds } } }); if (animals.length !== animalIds.length) { return res.status(400).json({ success: false, message: '部分牛只不存在' }); } // 检查哪些牛只已经在批次中 const existingAssociations = await CattleBatchAnimal.findAll({ where: { batchId: id, animalId: { [Op.in]: animalIds } } }); const existingAnimalIds = existingAssociations.map(assoc => assoc.animalId); const newAnimalIds = animalIds.filter(id => !existingAnimalIds.includes(id)); if (newAnimalIds.length === 0) { return res.status(400).json({ success: false, message: '所有牛只都已在该批次中' }); } // 添加新的关联 const associations = newAnimalIds.map(animalId => ({ batchId: id, animalId: animalId, joinDate: new Date() })); await CattleBatchAnimal.bulkCreate(associations); res.json({ success: true, message: `成功添加 ${newAnimalIds.length} 头牛只到批次`, data: { addedCount: newAnimalIds.length, skippedCount: existingAnimalIds.length } }); } catch (error) { console.error('添加牛只到批次失败:', error); res.status(500).json({ success: false, message: '添加牛只到批次失败', error: error.message }); } } /** * 从批次中移除牛只 */ async removeAnimalFromBatch(req, res) { try { const { id, animalId } = req.params; // 检查批次是否存在 const batch = await CattleBatch.findByPk(id); if (!batch) { return res.status(404).json({ success: false, message: '批次不存在' }); } // 检查关联是否存在 const association = await CattleBatchAnimal.findOne({ where: { batchId: id, animalId } }); if (!association) { return res.status(404).json({ success: false, message: '牛只不在该批次中' }); } await association.destroy(); res.json({ success: true, message: '从批次中移除牛只成功' }); } catch (error) { console.error('从批次中移除牛只失败:', error); res.status(500).json({ success: false, message: '从批次中移除牛只失败', error: error.message }); } } } module.exports = new CattleBatchController();