Files
Inventory-Management-System/templates/factory_workbench.html
T
star 5060d027e5 feat: 多工厂/厂间调拨/替代料/流水台账折叠 + 重写 README
- 多工厂(factory 表) + 顶栏工厂下拉过滤, 库存按厂聚合
- 厂间调拨(transfer): 源厂减+目标厂加, 总库存不变, 双向流水对账
- 替代料关系(substitute): 出库/BOM领料/生产领料缺料时提示可替代料
- 流水台账(ledger): 入出按日期合并折叠, 按日期导出同一 Excel
- 生产订单增强: 编辑/删除(级联清关联流水)/调入数量/确认调入=厂间调拨
- 入库新增送货日期字段; 出库物料编码扫码定位
- 重写 README 补全全部模块; .gitignore 排除 dist_pkg/build_pkg/*.db
- 停止跟踪 instance/app.db(运行时自动生成)
2026-09-29 11:17:48 +08:00

105 lines
5.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}工厂工作台 · {{ f.code }}{% endblock %}
{% block content %}
<div class="toolbar">
<h3 style="margin:0">工厂工作台:{{ f.code }} · {{ f.name or '' }}
<span class="badge {{ 'ok' if f.enabled else 'warn' }}">{{ '启用' if f.enabled else '停用' }}</span>
</h3>
<a class="btn" href="{{ url_for('factories') }}">← 返回工厂列表</a>
</div>
<div class="tabs">
<button class="tab active" onclick="switchTab('kanban')">📊 物料看板</button>
<button class="tab" onclick="switchTab('bom')">🧩 BOM 齐套</button>
<button class="tab" onclick="switchTab('import')">⊞ 批量导入</button>
</div>
<!-- 物料看板 -->
<div id="tab-kanban" class="tab-pane">
<div class="stat-row" style="margin:12px 0">
<div class="stat"><div class="num">{{ rows|length }}</div><div class="lbl">有库存物料</div></div>
<div class="stat warn"><div class="num">{{ low }}</div><div class="lbl">低于安全库存</div></div>
<div class="stat danger"><div class="num">{{ negative }}</div><div class="lbl">库存为负</div></div>
</div>
<table class="tbl">
<thead><tr><th>物料编号</th><th>型号/规格</th><th>单位</th><th>安全库存</th><th>在厂库存</th><th>状态</th></tr></thead>
<tbody>
{% for r in rows %}
<tr class="{{ 'row-danger' if r.status=='danger' else ('row-warn' if r.status=='warn' else '') }}">
<td>{{ r.m.part_number }}</td>
<td>{{ r.m.manufacturer or '-' }}</td>
<td>{{ r.m.unit or '-' }}</td>
<td class="num">{{ r.m.safety_stock or 0 }}</td>
<td class="num">{{ '%.2f'|format(r.stock) }}</td>
<td><span class="badge {{ 'danger' if r.status=='danger' else ('warn' if r.status=='warn' else 'ok') }}">{{ '负库存' if r.status=='danger' else ('低于安全库存' if r.status=='warn' else '正常') }}</span></td>
</tr>
{% else %}
<tr><td colspan="6" class="muted">该厂暂无库存数据</td></tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- BOM 齐套 -->
<div id="tab-bom" class="tab-pane" style="display:none">
{% for bd in bom_data %}
<div class="card" style="margin-bottom:16px">
<h3 style="margin-top:0">{{ bd.b.code }} ({{ bd.b.name or '-' }})
<span class="small muted">· 单套用量 × 该厂库存</span></h3>
{% if bd.comps %}
<table class="tbl">
<thead><tr><th>物料编号</th><th>型号/规格</th><th>单套用量</th><th>该厂库存</th><th>状态</th></tr></thead>
<tbody>
{% for c in bd.comps %}
<tr class="{{ 'row-danger' if c.status=='danger' else ('row-warn' if c.status=='warn' else '') }}">
<td>{{ c.m.part_number }}</td>
<td>{{ c.m.manufacturer or '-' }}</td>
<td class="num">{{ '%.3f'|format(c.qty) }}</td>
<td class="num">{{ '%.2f'|format(c.stock) }}</td>
<td><span class="badge {{ 'danger' if c.status=='danger' else ('warn' if c.status=='warn' else 'ok') }}">{{ '负库存' if c.status=='danger' else ('低于安全库存' if c.status=='warn' else '正常') }}</span></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="small muted">该 BOM 没有组成物料</p>
{% endif %}
</div>
{% else %}
<p class="muted">暂无 BOM</p>
{% endfor %}
</div>
<!-- 批量导入 -->
<div id="tab-import" class="tab-pane" style="display:none">
<div class="card" style="margin-bottom:16px">
<h3 style="margin-top:0">导入入库流水到 {{ f.code }}</h3>
<p class="small muted">上传 Excel/CSV(列:物料编号 / 数量 / 批次 / 日期 / 备注),将生成归属 {{ f.code }} 的入库流水。</p>
<form method="post" action="{{ url_for('factory_import_inbound', fid=f.id) }}" enctype="multipart/form-data" style="display:flex;gap:10px;align-items:center;flex-wrap:wrap">
<input type="file" name="file" accept=".xlsx,.csv" required>
<button class="primary" type="submit">上传并导入入库</button>
<a class="btn" href="{{ url_for('download_template', kind='transactions') }}">⬇ 下载模板</a>
</form>
</div>
<div class="card">
<h3 style="margin-top:0">导入物料主数据(期初库存归属 {{ f.code }})</h3>
<p class="small muted">上传物料 Excel(列:物料编号 / 型号 / 单位 / 安全库存 / 期初库存),期初库存将写入 {{ f.code }}。</p>
<form method="post" action="{{ url_for('factory_import_materials', fid=f.id) }}" enctype="multipart/form-data" style="display:flex;gap:10px;align-items:center;flex-wrap:wrap">
<input type="file" name="file" accept=".xlsx,.csv" required>
<button class="primary" type="submit">上传并导入物料</button>
<a class="btn" href="{{ url_for('download_template', kind='materials') }}">⬇ 下载模板</a>
</form>
</div>
</div>
<script>
function switchTab(name){
document.querySelectorAll('.tab').forEach(b=>b.classList.remove('active'));
document.querySelectorAll('.tab-pane').forEach(p=>p.style.display='none');
event.target.classList.add('active');
document.getElementById('tab-'+name).style.display='block';
}
</script>
{% endblock %}