// 采购需求清单管理 (() => { let demandList = []; let productList = []; let currentPage = 1; const pageSize = 20; const statusMap = { 'pending': { text: '待处理', color: 'var(--warning)' }, 'ordered': { text: '已下单', color: 'var(--info)' }, 'received': { text: '已收货', color: 'var(--primary)' }, 'completed': { text: '已完成', color: 'var(--success)' }, 'cancelled': { text: '已取消', color: 'var(--text-2)' } }; Router.register('/plan-mgmt/purchase-demand', async () => { const html = `
💡
采购需求计算公式: 客户订单数量 × BOM单机用量 - 期初库存 = 净需求 → 按最小包装向上取整 = 实际采购数量
需求编号 物料编码 物料名称 订单数量 BOM用量 总需求 期初库存 净需求 最小包装 实际采购 单位 供应商 状态 操作
加载中...
`; setTimeout(() => { document.getElementById('calc-demand-btn')?.addEventListener('click', () => openCalcModal()); document.getElementById('calc-from-orders-btn')?.addEventListener('click', () => calcFromOrders()); document.getElementById('batch-delete-btn')?.addEventListener('click', () => batchDelete()); document.getElementById('search-keyword')?.addEventListener('keypress', (e) => { if (e.key === 'Enter') PurchaseDemand.search(); }); loadList(); loadProducts(); }, 100); return html; }); async function loadList() { try { const res = await API.get('/api/purchase-demand'); demandList = res.list || []; renderList(); } catch (e) { console.error('加载采购需求失败:', e); document.getElementById('demand-list').innerHTML = '加载失败'; } } async function loadProducts() { try { const res = await API.get('/api/bom/products'); productList = res.list || []; const select = document.getElementById('product-select'); if (select) { select.innerHTML = '' + productList.map(p => ``).join(''); } } catch (e) { console.error('加载产品列表失败:', e); } } function renderList() { const tbody = document.getElementById('demand-list'); const keyword = (document.getElementById('search-keyword')?.value || '').toLowerCase(); const filterStatus = document.getElementById('filter-status')?.value || ''; let filtered = demandList; if (keyword) { filtered = filtered.filter(item => (item.demand_no || '').toLowerCase().includes(keyword) || (item.material_code || '').toLowerCase().includes(keyword) || (item.material_name || '').toLowerCase().includes(keyword) ); } if (filterStatus) { filtered = filtered.filter(item => item.status === filterStatus); } const totalPages = Math.ceil(filtered.length / pageSize); const start = (currentPage - 1) * pageSize; const pageData = filtered.slice(start, start + pageSize); if (pageData.length === 0) { tbody.innerHTML = '暂无数据'; } else { tbody.innerHTML = pageData.map(item => { const status = statusMap[item.status] || { text: item.status, color: 'var(--text-2)' }; return ` ${escapeHtml(item.demand_no || '')} ${escapeHtml(item.material_code || '')} ${escapeHtml(item.material_name || '')} ${item.order_qty || 0} ${item.bom_unit_qty || 1} ${item.total_demand || 0} ${item.initial_stock || 0} ${item.net_demand || 0} ${item.min_package || 1} ${item.actual_purchase_qty || 0} ${escapeHtml(item.unit || 'pcs')} ${escapeHtml(item.supplier || '-')} ${status.text} `; }).join(''); } renderPagination(totalPages); } function renderPagination(totalPages) { const container = document.getElementById('pagination'); if (totalPages <= 1) { container.innerHTML = ''; return; } let html = ''; html += ``; html += `第 ${currentPage} / ${totalPages} 页`; html += ``; container.innerHTML = html; } function openCalcModal() { document.getElementById('product-select').value = ''; document.getElementById('order-qty').value = 1; document.getElementById('calc-modal').style.display = 'flex'; } function closeCalcModal() { document.getElementById('calc-modal').style.display = 'none'; } async function doCalculate() { const productCode = document.getElementById('product-select').value; const orderQty = parseInt(document.getElementById('order-qty').value) || 0; if (!productCode) { alert('请选择产品'); return; } if (orderQty <= 0) { alert('订单数量必须大于0'); return; } try { const res = await API.post('/api/purchase-demand/calculate', { product_code: productCode, order_qty: orderQty }); closeCalcModal(); alert(res.message || '计算完成'); loadList(); // 显示计算结果摘要 if (res.list && res.list.length > 0) { const totalPurchase = res.list.reduce((sum, item) => sum + (item.actual_purchase_qty || 0), 0); console.log(`采购需求计算完成,需求编号: ${res.demand_no},共 ${res.list.length} 种物料,总采购数量: ${totalPurchase}`); } } catch (e) { alert(e.message || '计算失败'); } } async function calcFromOrders() { if (!confirm('将根据所有客户订单自动计算采购需求,确定继续吗?')) { return; } try { const res = await API.post('/api/purchase-demand/calculate-from-orders', {}); alert(res.message || '计算完成'); loadList(); } catch (e) { alert(e.message || '计算失败'); } } let updatingId = null; function updateStatus(id) { updatingId = id; const item = demandList.find(x => x.id === id); document.getElementById('update-status').value = item?.status || 'pending'; document.getElementById('update-remark').value = item?.remark || ''; document.getElementById('status-modal').style.display = 'flex'; } function closeStatusModal() { document.getElementById('status-modal').style.display = 'none'; updatingId = null; } async function doUpdateStatus() { if (!updatingId) return; const status = document.getElementById('update-status').value; const remark = document.getElementById('update-remark').value.trim(); try { await API.put(`/api/purchase-demand/${updatingId}`, { status, remark }); closeStatusModal(); alert('更新成功'); loadList(); } catch (e) { alert(e.message || '更新失败'); } } async function deleteDemand(id) { if (!confirm('确定要删除这条采购需求吗?')) return; try { await API.delete(`/api/purchase-demand/${id}`); alert('删除成功'); loadList(); } catch (e) { alert(e.message || '删除失败'); } } async function batchDelete() { const checked = document.querySelectorAll('.row-checkbox:checked'); if (checked.length === 0) { alert('请先选择要删除的项'); return; } if (!confirm(`确定要删除选中的 ${checked.length} 条采购需求吗?`)) return; const ids = Array.from(checked).map(cb => parseInt(cb.dataset.id)); try { await API.post('/api/purchase-demand/batch-delete', { ids }); alert('批量删除成功'); loadList(); } catch (e) { alert(e.message || '批量删除失败'); } } function toggleSelectAll(checkbox) { document.querySelectorAll('.row-checkbox').forEach(cb => cb.checked = checkbox.checked); } function search() { currentPage = 1; renderList(); } function resetSearch() { document.getElementById('search-keyword').value = ''; document.getElementById('filter-status').value = ''; currentPage = 1; renderList(); } function goPage(page) { currentPage = page; renderList(); } function escapeHtml(str) { if (!str) return ''; return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } window.PurchaseDemand = { search, resetSearch, delete: deleteDemand, updateStatus, closeCalcModal, closeStatusModal, doCalculate, doUpdateStatus, toggleSelectAll, goPage }; })();