Files
order_system/po_app/templates/order_edit.html
T

202 lines
10 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 body %}
<h1 class="page">编辑订单 · {{ o.order_no }}({{ o.doc_type_text }})</h1>
<div class="card">
<h2>单据信息</h2>
<form method="post" id="orderForm">
<div class="form-grid">
<div><label>采购单号</label><input type="text" value="{{ o.order_no }}" disabled></div>
<div><label>采购日期</label><input type="date" name="order_date" value="{{ o.order_date or '' }}"></div>
<div><label>税点</label><input type="text" name="tax_rate" value="{{ o.tax_rate or '' }}" placeholder="如 13%"></div>
</div>
<h3>供方(供应商)</h3>
<div class="form-grid">
<div>
<label>供应商</label>
<input type="text" name="supplier_name" id="supplier_name" value="{{ o.supplier_name or '' }}">
<select id="supplierPick" style="margin-top:4px;">
<option value="">-- 从供应商库带入 --</option>
{% for s in suppliers %}<option value="{{ s.id }}">{{ s.name }}</option>{% endfor %}
</select>
</div>
<div><label>联系人</label><input type="text" name="supplier_contact" id="supplier_contact" value="{{ o.supplier_contact or '' }}"></div>
<div><label>电话</label><input type="text" name="supplier_phone" id="supplier_phone" value="{{ o.supplier_phone or '' }}"></div>
<div><label>付款方式</label><input type="text" name="payment_terms" id="payment_terms" value="{{ o.payment_terms or '' }}"></div>
<div><label>税号</label><input type="text" name="supplier_tax_no" id="supplier_tax_no" value="{{ o.supplier_tax_no or '' }}"></div>
<div><label>银行帐号</label><input type="text" name="supplier_bank_account" id="supplier_bank_account" value="{{ o.supplier_bank_account or '' }}"></div>
<div><label>开户银行</label><input type="text" name="supplier_bank_name" id="supplier_bank_name" value="{{ o.supplier_bank_name or '' }}"></div>
</div>
<h3>需方(本公司)</h3>
<div class="form-grid">
<div><label>需方名称</label><input type="text" name="our_company" value="{{ o.our_company or '' }}"></div>
<div><label>联系人</label><input type="text" name="our_contact" value="{{ o.our_contact or '' }}"></div>
<div><label>电话</label><input type="text" name="our_phone" value="{{ o.our_phone or '' }}"></div>
<div><label>税号</label><input type="text" name="our_tax_no" value="{{ o.our_tax_no or '' }}"></div>
<div style="grid-column: span 2;">
<label>交货地点</label>
<input type="text" name="delivery_place" value="{{ o.delivery_place or '' }}">
</div>
</div>
<h3>物料明细</h3>
<table class="grid" id="itemTable">
<tr>
<th style="width:38px;">序</th>
<th style="width:150px;">物料代码</th>
<th>物料规格</th>
<th style="width:62px;">单位</th>
<th style="width:78px;">数量</th>
<th style="width:92px;">含税单价</th>
<th style="width:96px;">金额</th>
<th style="width:118px;">交期</th>
<th style="width:130px;">备注</th>
<th style="width:44px;">删</th>
</tr>
{% for it in o.items %}
<tr>
<td class="center seq">{{ loop.index }}</td>
<td><input type="text" name="item_code" value="{{ it.material_code or '' }}">
<select class="matpick" style="margin-top:3px;">
<option value="">-- 物料库 --</option>
{% for m in materials %}<option value="{{ m.id }}" data-code="{{ m.code }}" data-spec="{{ m.spec }}" data-unit="{{ m.unit }}" data-price="{{ m.price }}">{{ m.code }} {{ m.spec }}</option>{% endfor %}
</select>
</td>
<td><input type="text" name="item_spec" value="{{ it.material_spec or '' }}"></td>
<td><input type="text" name="item_unit" value="{{ it.unit or '' }}"></td>
<td><input type="number" step="0.0001" name="item_qty" class="qty" value="{{ it.qty or 0 }}"></td>
<td><input type="number" step="0.0001" name="item_price" class="price" value="{{ it.price or 0 }}"></td>
<td><input type="text" class="amt" value="{{ '%.2f'|format(it.amount or 0) }}" disabled></td>
<td><input type="date" name="item_date" value="{{ it.delivery_date or '' }}"></td>
<td><input type="text" name="item_remark" value="{{ it.remark or '' }}"></td>
<td class="center"><button type="button" class="btn sm danger" onclick="delRow(this)">×</button></td>
</tr>
{% endfor %}
</table>
<template id="rowTpl">
<tr>
<td class="center seq">1</td>
<td><input type="text" name="item_code" value="">
<select class="matpick" style="margin-top:3px;">
<option value="">-- 物料库 --</option>
{% for m in materials %}<option value="{{ m.id }}" data-code="{{ m.code }}" data-spec="{{ m.spec }}" data-unit="{{ m.unit }}" data-price="{{ m.price }}">{{ m.code }} {{ m.spec }}</option>{% endfor %}
</select>
</td>
<td><input type="text" name="item_spec" value=""></td>
<td><input type="text" name="item_unit" value=""></td>
<td><input type="number" step="0.0001" name="item_qty" class="qty" value="0"></td>
<td><input type="number" step="0.0001" name="item_price" class="price" value="0"></td>
<td><input type="text" class="amt" value="0.00" disabled></td>
<td><input type="date" name="item_date" value=""></td>
<td><input type="text" name="item_remark" value=""></td>
<td class="center"><button type="button" class="btn sm danger" onclick="delRow(this)">×</button></td>
</tr>
</template>
<div class="toolbar" style="margin-top:10px;">
<button type="button" class="btn" onclick="addRow()">+ 添加一行</button>
<span class="grow"></span>
<span class="total-bar">合计:<span class="amt" id="totalAmt">{{ '%.2f'|format(o.total_amount) }}</span> 元
<span class="muted" id="totalCn">{{ total_cn }}</span></span>
</div>
<h3>补充说明</h3>
<textarea name="note" placeholder="选填,会打印在 PDF 备注区">{{ o.note or '' }}</textarea>
<div style="margin-top:16px;">
<button class="btn primary" type="submit">保存</button>
<a class="btn" href="{{ url_for('order_view', oid=o.id) }}">查看订单</a>
<a class="btn" href="{{ url_for('order_pdf', oid=o.id) }}" target="_blank">预览 PDF</a>
</div>
</form>
<form method="post" action="{{ url_for('order_submit', oid=o.id) }}" style="margin-top:10px;">
<div class="toolbar">
<input type="text" name="comment" placeholder="提交说明(选填)" style="width:260px;">
<button class="btn ok">提交主管审核</button>
</div>
</form>
</div>
<div class="card">
<h2>从 Excel 导入明细</h2>
<div class="hint">
支持 .xlsx / .xls。系统自动识别表头(物料代码、物料规格、单位、数量、含税单价、交期、备注),
没有表头则按前 7 列顺序读取。行数超出模板也没关系,PDF 会自动分页。
<a href="{{ url_for('import_template') }}">下载导入模板</a>
</div>
<form method="post" action="{{ url_for('import_excel', oid=o.id) }}" enctype="multipart/form-data" class="toolbar">
<input type="file" name="file" accept=".xls,.xlsx" required style="width:280px;">
<select name="mode" style="width:140px;">
<option value="append">追加到现有明细</option>
<option value="replace">替换全部明细</option>
</select>
<button class="btn primary">导入</button>
</form>
</div>
<script>
const MATERIALS = {{ materials|map(attribute='id')|list|tojson }};
function bindRow(tr){
tr.querySelectorAll('.qty, .price').forEach(i => i.addEventListener('input', calc));
const pick = tr.querySelector('.matpick');
if (pick) pick.addEventListener('change', function(){
const opt = this.selectedOptions[0];
if (!opt || !opt.value) return;
tr.querySelector('[name=item_code]').value = opt.dataset.code || '';
tr.querySelector('[name=item_spec]').value = opt.dataset.spec || '';
tr.querySelector('[name=item_unit]').value = opt.dataset.unit || '';
tr.querySelector('.price').value = opt.dataset.price || 0;
calc();
});
}
function calc(){
let total = 0;
document.querySelectorAll('#itemTable tr').forEach((tr, idx) => {
const q = parseFloat(tr.querySelector('.qty')?.value || 0);
const p = parseFloat(tr.querySelector('.price')?.value || 0);
const a = (isNaN(q) ? 0 : q) * (isNaN(p) ? 0 : p);
const amt = tr.querySelector('.amt');
if (amt) amt.value = a.toFixed(2);
total += a;
const seq = tr.querySelector('.seq');
if (seq) seq.textContent = idx;
});
document.getElementById('totalAmt').textContent = total.toFixed(2);
}
function addRow(){
// 从 <template> 克隆,避免"明细为空时没有可复制的行"导致点击无反应
const t = document.getElementById('itemTable');
const tr = document.getElementById('rowTpl').content.firstElementChild.cloneNode(true);
tr.querySelectorAll('input').forEach(i => { if (i.type !== 'date') i.value = ''; });
const q = tr.querySelector('.qty'); if (q) q.value = 0;
const p = tr.querySelector('.price'); if (p) p.value = 0;
const a = tr.querySelector('.amt'); if (a) a.value = '0.00';
const sel = tr.querySelector('.matpick'); if (sel) sel.selectedIndex = 0;
t.appendChild(tr);
bindRow(tr); calc();
}
function delRow(btn){
btn.closest('tr').remove(); calc();
}
document.querySelectorAll('#itemTable tr').forEach(bindRow);
calc();
document.getElementById('supplierPick').addEventListener('change', async function(){
if (!this.value) return;
const r = await fetch('/api/suppliers').then(r => r.json());
const s = r.find(x => String(x.id) === this.value);
if (!s) return;
document.getElementById('supplier_name').value = s.name || '';
document.getElementById('supplier_contact').value = s.contact || '';
document.getElementById('supplier_phone').value = s.phone || '';
document.getElementById('supplier_tax_no').value = s.tax_no || '';
document.getElementById('supplier_bank_name').value = s.bank_name || '';
document.getElementById('supplier_bank_account').value = s.bank_account || '';
document.getElementById('payment_terms').value = s.payment_terms || '';
});
</script>
{% endblock %}