新增客户订单未交订单功能
- 在客户订单管理表格中新增已发货和未交订单列 - 根据合同编号和物料名称匹配对账单发货数量 - 添加刷新按钮手动更新未交订单数据 - 订单变化时自动刷新未交订单数量 - 采用物料名称互相包含的灵活匹配策略
This commit is contained in:
parent
92062262a6
commit
49d5dd38a1
@ -12,6 +12,11 @@
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
#customer-order-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -88,8 +93,14 @@
|
||||
<div id="customer-order-page">
|
||||
<div class="page-header">
|
||||
<h1 style="margin: 0; font-size: 24px;">客户订单管理</h1>
|
||||
<div class="page-actions" style="margin-top: 16px;">
|
||||
<div class="page-actions" style="margin-top: 16px; display: flex; gap: 12px;">
|
||||
<button id="add-order-btn" class="btn btn-primary">新增订单</button>
|
||||
<button id="refresh-undelivered-btn" class="btn btn-secondary" title="刷新未交订单数据">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: middle; margin-right: 4px;">
|
||||
<path d="M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2"/>
|
||||
</svg>
|
||||
刷新未交订单
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -103,13 +114,15 @@
|
||||
<th>客户名称</th>
|
||||
<th>物料</th>
|
||||
<th>订单数量</th>
|
||||
<th>已发货</th>
|
||||
<th style="color: #f59e0b; font-weight: 700;">未交订单</th>
|
||||
<th>单价</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="order-list">
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">加载中...</td>
|
||||
<td colspan="9" class="text-center">加载中...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -176,6 +189,19 @@
|
||||
openModal();
|
||||
});
|
||||
}
|
||||
|
||||
const refreshBtn = document.getElementById('refresh-undelivered-btn');
|
||||
if (refreshBtn) {
|
||||
refreshBtn.addEventListener('click', async () => {
|
||||
refreshBtn.disabled = true;
|
||||
refreshBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: middle; margin-right: 4px; animation: spin 1s linear infinite;"><path d="M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2"/></svg>刷新中...';
|
||||
await loadOrders();
|
||||
refreshBtn.disabled = false;
|
||||
refreshBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: middle; margin-right: 4px;"><path d="M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2"/></svg>刷新未交订单';
|
||||
API.toast('未交订单数据已更新', 'success');
|
||||
});
|
||||
}
|
||||
|
||||
loadOrders();
|
||||
}, 100);
|
||||
|
||||
@ -197,30 +223,36 @@
|
||||
}
|
||||
|
||||
if (!data.list || data.list.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="7" class="text-center">暂无数据</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="9" class="text-center">暂无数据</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
tbody.innerHTML = data.list.map(order => `
|
||||
tbody.innerHTML = data.list.map(order => {
|
||||
const undeliveredQty = order.undelivered_qty || 0;
|
||||
const shippedQty = order.shipped_qty || 0;
|
||||
const undeliveredStyle = undeliveredQty > 0 ? 'color: #f59e0b; font-weight: 700;' : 'color: #10b981;';
|
||||
return `
|
||||
<tr>
|
||||
<td>${order.order_date || '—'}</td>
|
||||
<td>${order.order_no || '—'}</td>
|
||||
<td>${order.customer_name || '—'}</td>
|
||||
<td style="white-space: pre-line; word-break: break-word;">${order.material || '—'}</td>
|
||||
<td>${order.quantity || 0}</td>
|
||||
<td style="color: #3b82f6;">${shippedQty}</td>
|
||||
<td style="${undeliveredStyle}">${undeliveredQty}</td>
|
||||
<td>${order.unit_price || 0}</td>
|
||||
<td>
|
||||
<button class="btn-text" onclick="window.CustomerOrder.editOrder(${order.id})">编辑</button>
|
||||
<button class="btn-text btn-danger" onclick="window.CustomerOrder.deleteOrder(${order.id})">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
`}).join('');
|
||||
console.log('订单列表加载完成');
|
||||
} catch (err) {
|
||||
console.error('加载订单失败:', err);
|
||||
const tbody = document.getElementById('order-list');
|
||||
if (tbody) {
|
||||
tbody.innerHTML = '<tr><td colspan="7" class="text-center" style="color: red;">加载失败,请刷新重试</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="9" class="text-center" style="color: red;">加载失败,请刷新重试</td></tr>';
|
||||
}
|
||||
API.toast('加载订单失败', 'error');
|
||||
}
|
||||
|
||||
@ -5049,7 +5049,7 @@ def upload_material_purchase_file():
|
||||
@require_login
|
||||
@require_any_role('superadmin')
|
||||
def get_customer_orders():
|
||||
"""获取客户订单列表"""
|
||||
"""获取客户订单列表,包含未交订单数量"""
|
||||
conn = get_db()
|
||||
c = conn.cursor()
|
||||
c.execute('''SELECT id, order_date, order_no, customer_name, material, quantity, unit_price,
|
||||
@ -5057,10 +5057,49 @@ def get_customer_orders():
|
||||
FROM customer_orders
|
||||
ORDER BY order_date DESC, id DESC''')
|
||||
rows = c.fetchall()
|
||||
conn.close()
|
||||
|
||||
orders = []
|
||||
for row in rows:
|
||||
# 计算未交订单数量
|
||||
# 根据订单编号(合同编号)和物料信息匹配对账单的发货数量
|
||||
order_no = row['order_no']
|
||||
material = row['material'] or ''
|
||||
order_qty = row['quantity'] or 0
|
||||
|
||||
# 解析客户订单物料信息(格式:物料名称\n规格型号)
|
||||
material_lines = material.strip().split('\n')
|
||||
order_material_name = material_lines[0].strip() if len(material_lines) > 0 else ''
|
||||
order_spec_model = material_lines[1].strip() if len(material_lines) > 1 else ''
|
||||
|
||||
# 查询对账单中已发货数量
|
||||
# 匹配策略:根据合同编号,判断物料名称是否互相包含
|
||||
shipped_qty = 0
|
||||
try:
|
||||
if order_material_name:
|
||||
# 获取该合同号下的所有对账单记录
|
||||
c.execute('''SELECT material_name, quantity
|
||||
FROM reconciliations
|
||||
WHERE contract_no = ?''', (order_no,))
|
||||
reconciliation_rows = c.fetchall()
|
||||
|
||||
for rec_row in reconciliation_rows:
|
||||
rec_material = (rec_row['material_name'] or '').strip()
|
||||
rec_qty = rec_row['quantity'] or 0
|
||||
|
||||
# 判断物料名称是否互相包含(忽略大小写)
|
||||
if rec_material and (
|
||||
order_material_name.lower() in rec_material.lower() or
|
||||
rec_material.lower() in order_material_name.lower()
|
||||
):
|
||||
shipped_qty += rec_qty
|
||||
|
||||
except Exception as e:
|
||||
log('calculate_undelivered_error', f'订单ID {row["id"]}: {str(e)}')
|
||||
shipped_qty = 0
|
||||
|
||||
# 计算未交数量
|
||||
undelivered_qty = max(0, order_qty - shipped_qty)
|
||||
|
||||
orders.append({
|
||||
'id': row['id'],
|
||||
'order_date': row['order_date'],
|
||||
@ -5069,11 +5108,14 @@ def get_customer_orders():
|
||||
'material': row['material'],
|
||||
'quantity': row['quantity'],
|
||||
'unit_price': row['unit_price'],
|
||||
'shipped_qty': shipped_qty,
|
||||
'undelivered_qty': undelivered_qty,
|
||||
'created_by': row['created_by'],
|
||||
'created_at': row['created_at'],
|
||||
'updated_at': row['updated_at']
|
||||
})
|
||||
|
||||
conn.close()
|
||||
return jsonify({'list': orders})
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user