feat: 库存管理系统 MaterialWMS 初始版本

- Flask + SQLAlchemy 物料/入库/出库/BOM/生产订单全模块管理
- PyInstaller 打包为单文件 EXE (双击运行, 自动建库)
- 物料维度: 入库总数量 / 消耗总数量 / 逐次入库流水(含时间)
- BOM 详情展示组成物料的规格型号与单套用量
- 支持 Altium / 嘉立创 BOM 批量导入(文本与 Excel 双通道)
- 内置端到端验证脚本(tools/_exe_util.py 等, 清理进程树防残留)
This commit is contained in:
2026-09-11 15:41:56 +08:00
commit 7d34a481b3
38 changed files with 3601 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
{% extends "base.html" %}
{% block title %}订单 {{ o.order_no }}{% endblock %}
{% block content %}
<div class="toolbar">
<h3 style="margin:0">生产订单 {{ o.order_no }}</h3>
<span class="badge {{ 'ok' if o.status=='picked' else 'warn' }}">{{ '已领料' if o.status=='picked' else '待领料' }}</span>
</div>
<div class="card" style="margin-bottom:16px">
<p>BOM: <b>{{ bom.code if bom else '-' }}</b> ({{ bom.name if bom else '' }}) | 接单量: <b>{{ '%.2f'|format(o.qty) }}</b> | 经手人: {{ o.operator or '-' }}</p>
</div>
<h3>领料需求 (单套用量 × 接单量)</h3>
<table class="tbl">
<thead><tr><th>物料编号</th><th>型号</th><th>需求数量</th><th>当前库存</th><th>缺口</th><th>状态</th></tr></thead>
<tbody>
{% for r in reqs %}
<tr class="{{ 'row-danger' if r.short else ('row-warn' if r.have < (r.m.safety_stock or 0)) }}">
<td>{{ r.m.part_number }}</td>
<td>{{ r.m.manufacturer or '-' }}</td>
<td class="num">{{ '%.2f'|format(r.need) }}</td>
<td class="num">{{ '%.2f'|format(r.have) }}</td>
<td class="num">{{ '%.2f'|format(r.gap) }}</td>
<td><span class="badge {{ 'danger' if r.short else 'ok' }}">{{ '缺料' if r.short else '充足' }}</span></td>
</tr>
{% else %}
<tr><td colspan="6" class="muted">该 BOM 没有组成物料</td></tr>
{% endfor %}
</tbody>
</table>
{% if o.status != 'picked' %}
<form method="post" action="{{ url_for('order_pick', oid=o.id) }}" onsubmit="return confirm('确认按 BOM 生成领料出库? 库存不足将记为负并在看板预警。');">
<div class="row-actions"><button class="primary">确认领料出库</button></div>
</form>
{% else %}
<p class="flash ok">该订单已领料出库。</p>
{% endif %}
{% endblock %}