const { query, transaction } = require('../config/database') const { paginate } = require('../utils/pagination') async function getPurchases(ctx) { let sql = ` SELECT p.*, (SELECT COUNT(*) FROM purchase_items WHERE purchase_id = p.id) as items_count FROM purchases p WHERE 1=1` const params = [] if (ctx.query.keyword) { sql += ' AND (p.supplier_name LIKE ?)' params.push(`%${ctx.query.keyword}%`) } sql += ' ORDER BY p.created_at DESC' const result = await paginate(query, sql, params, ctx.query.page, ctx.query.pageSize) ctx.body = { code: 200, ...result } } async function getPurchaseById(ctx) { const id = parseInt(ctx.params.id) const purchases = await query('SELECT * FROM purchases WHERE id = ?', [id]) if (purchases.length === 0) { ctx.body = { code: 404, message: '采购单不存在' } return } const purchase = purchases[0] const items = await query( `SELECT pi.*, g.name as goods_name FROM purchase_items pi LEFT JOIN goods g ON pi.goods_id = g.id WHERE pi.purchase_id = ?`, [id] ) purchase.items = items purchase.items_count = items.length ctx.body = { code: 200, data: purchase } } async function createPurchase(ctx) { const { supplier_id, items, remarks } = ctx.request.body || {} if (!supplier_id || !Array.isArray(items) || items.length === 0) { ctx.body = { code: 400, message: '请选择供应商和采购商品' } return } const suppliers = await query('SELECT * FROM suppliers WHERE id = ?', [supplier_id]) if (suppliers.length === 0) { ctx.body = { code: 404, message: '供应商不存在' } return } const supplier = suppliers[0] let total = 0 for (const item of items) { const qty = parseInt(item.quantity) || 0 const price = parseFloat(item.purchase_price) || 0 if (qty <= 0 || price < 0) { ctx.body = { code: 400, message: '数量/单价不合法' } return } total += price * qty } const result = await transaction(async (conn) => { const [purchaseResult] = await conn.execute( 'INSERT INTO purchases (supplier_id, supplier_name, total, remarks) VALUES (?, ?, ?, ?)', [supplier_id, supplier.name, total, remarks || ''] ) const purchaseId = purchaseResult.insertId for (const item of items) { const [goods] = await conn.execute('SELECT name FROM goods WHERE id = ?', [item.goods_id]) const goodsName = goods.length > 0 ? goods[0].name : '' await conn.execute( 'INSERT INTO purchase_items (purchase_id, goods_id, goods_name, quantity, purchase_price) VALUES (?, ?, ?, ?, ?)', [purchaseId, item.goods_id, goodsName, item.quantity || 0, item.purchase_price || 0] ) } return purchaseId }) ctx.body = { code: 200, message: '采购单创建成功', data: { id: result } } } async function inboundPurchase(ctx) { const operator = ctx.state.user if (!operator) { ctx.status = 401 ctx.body = { code: 401, message: '未登录' } return } const id = parseInt(ctx.params.id) const purchases = await query('SELECT * FROM purchases WHERE id = ?', [id]) if (purchases.length === 0) { ctx.body = { code: 404, message: '采购单不存在' } return } const purchase = purchases[0] if (purchase.status === 1) { ctx.body = { code: 400, message: '该采购单已入库' } return } const items = await query('SELECT * FROM purchase_items WHERE purchase_id = ?', [id]) if (items.length === 0) { ctx.body = { code: 400, message: '采购单无明细' } return } await transaction(async (conn) => { for (const item of items) { const [goods] = await conn.execute('SELECT id, stock FROM goods WHERE id = ? FOR UPDATE', [item.goods_id]) if (goods.length === 0) { throw new Error(`商品 ${item.goods_id} 不存在,无法入库`) } const [stockRows] = await conn.execute('SELECT quantity FROM stock WHERE goods_id = ? FOR UPDATE', [item.goods_id]) if (stockRows.length > 0) { await conn.execute( 'UPDATE stock SET quantity = quantity + ? WHERE goods_id = ?', [item.quantity, item.goods_id] ) } else { await conn.execute( 'INSERT INTO stock (goods_id, quantity, warehouse) VALUES (?, ?, ?)', [item.goods_id, item.quantity, '默认仓库'] ) } await conn.execute( 'UPDATE goods SET stock = stock + ? WHERE id = ?', [item.quantity, item.goods_id] ) try { await conn.execute( 'INSERT INTO stock_logs (goods_id, change_type, delta, quantity_after, operator_id, remark) VALUES (?, ?, ?, ?, ?, ?)', [item.goods_id, 'purchase', item.quantity, (stockRows[0]?.quantity || 0) + item.quantity, operator.id, `采购入库 #${id}`] ) } catch {} } await conn.execute('UPDATE purchases SET status = 1 WHERE id = ?', [id]) }) ctx.body = { code: 200, message: '入库成功' } } module.exports = { getPurchases, getPurchaseById, createPurchase, inboundPurchase }