feat: 采购管理税率+分开单价总价列 + 按单出/借库锁定扫描 + 含税法计算
- purchase: 新增tax_rate字段(model+service+frontend), 表格拆分为不含税单价/总价/税率三列 - buy.vue: 含税法计算(含税总价=数量×含税单价), 含税总价自动计算可手动覆盖 - create.vue: 按单出库模式下未选审批单时锁定摄像头和SKU输入 - borrow.vue: 未选审批单时锁定摄像头和SKU输入 - deploy_production.sql: 整合全部数据库变更(表结构+权限码+角色分配)
This commit is contained in:
@ -580,14 +580,18 @@
|
||||
<el-col :span="8">
|
||||
<el-form-item label="含税总价">
|
||||
<el-input-number
|
||||
v-model="form._post_tax_total_price"
|
||||
v-model="postTaxTotalInput"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
style="width:100%"
|
||||
class="total-price-input"
|
||||
placeholder="输入含税总价反算"
|
||||
@change="updatePrices('post_total')"
|
||||
:placeholder="postTaxTotalAuto > 0 ? '自动: ¥' + postTaxTotalAuto.toFixed(2) : '自动计算'"
|
||||
@change="onPostTaxTotalChange"
|
||||
@clear="onPostTaxTotalClear"
|
||||
/>
|
||||
<span v-if="postTaxTotalAuto > 0 && !postTaxTotalManuallySet" style="font-size:11px;color:#909399;">
|
||||
自动计算,点击输入可覆盖
|
||||
</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -1178,8 +1182,7 @@ const form = reactive({
|
||||
supplier_name: '', purchaser: '', purchaser_email: '', source_link: '', detail_link: '',
|
||||
arrival_photo: [] as string[], inspection_report: [] as string[],
|
||||
print_copies: 1,
|
||||
request_id: undefined as number | undefined, // [新增] 关联采购申请单
|
||||
_post_tax_total_price: undefined as number | undefined // 含税总价(仅前端输入用,不提交后端)
|
||||
request_id: undefined as number | undefined // [新增] 关联采购申请单
|
||||
})
|
||||
|
||||
// ------------------------------------
|
||||
@ -1382,15 +1385,49 @@ const handleEntryModeChange = (val: string) => {
|
||||
if(formRef.value) formRef.value.clearValidate('batch_number')
|
||||
}
|
||||
}
|
||||
// 价格联动:含税单价为主输入,不含税价格自动反算
|
||||
// 追踪用户最后编辑的是含税还是不含税('pre' | 'post')
|
||||
const lastPriceEdit = ref<'pre' | 'post'>('post') // 默认以含税为主
|
||||
// 价格联动:含税法计算
|
||||
// 含税总价 = 数量 × 含税单价
|
||||
// 不含税总价 = 含税总价 ÷ (1 + 税率)
|
||||
// 不含税单价 = 不含税总价 ÷ 数量
|
||||
const lastPriceEdit = ref<'pre' | 'post'>('post')
|
||||
|
||||
// 含税总价:自动计算(含税单价 × 数量)+ 支持手动覆盖
|
||||
const postTaxTotalManuallySet = ref(false)
|
||||
const postTaxTotalInput = ref<number | undefined>(undefined)
|
||||
const postTaxTotalAuto = computed(() => {
|
||||
if (form.post_tax_unit_price != null && form.in_quantity > 0) {
|
||||
return Number((form.post_tax_unit_price * form.in_quantity).toFixed(2))
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
const onPostTaxTotalChange = (val: number | undefined) => {
|
||||
if (val != null && val > 0 && form.in_quantity > 0) {
|
||||
postTaxTotalManuallySet.value = true
|
||||
// 含税总价 → 含税单价 → 不含税单价/总价
|
||||
form.post_tax_unit_price = Number((val / form.in_quantity).toFixed(2))
|
||||
const taxMultiplier = 1 + (form.tax_rate || 0) / 100
|
||||
form.unit_price = Number((form.post_tax_unit_price / taxMultiplier).toFixed(4))
|
||||
form.total_price = Number((form.unit_price * form.in_quantity).toFixed(2))
|
||||
}
|
||||
}
|
||||
|
||||
const onPostTaxTotalClear = () => {
|
||||
postTaxTotalManuallySet.value = false
|
||||
postTaxTotalInput.value = undefined
|
||||
// 重新用含税单价反算
|
||||
if (form.post_tax_unit_price != null && form.in_quantity > 0) {
|
||||
const taxMultiplier = 1 + (form.tax_rate || 0) / 100
|
||||
form.unit_price = Number((form.post_tax_unit_price / taxMultiplier).toFixed(4))
|
||||
form.total_price = Number((form.unit_price * form.in_quantity).toFixed(2))
|
||||
}
|
||||
}
|
||||
|
||||
const updatePrices = (source: string) => {
|
||||
const taxMultiplier = 1 + (form.tax_rate || 0) / 100;
|
||||
|
||||
if (source === 'pre') {
|
||||
// 用户编辑了不含税单价 → 反推含税
|
||||
// 编辑了不含税单价 → 反推含税单价
|
||||
lastPriceEdit.value = 'pre'
|
||||
if (form.unit_price != null) {
|
||||
form.post_tax_unit_price = Number((form.unit_price * taxMultiplier).toFixed(2));
|
||||
@ -1398,7 +1435,7 @@ const updatePrices = (source: string) => {
|
||||
form.post_tax_unit_price = undefined;
|
||||
}
|
||||
} else if (source === 'post') {
|
||||
// 用户编辑了含税单价 → 反推不含税
|
||||
// 编辑了含税单价 → 反推不含税
|
||||
lastPriceEdit.value = 'post'
|
||||
if (form.post_tax_unit_price != null) {
|
||||
form.unit_price = Number((form.post_tax_unit_price / taxMultiplier).toFixed(4));
|
||||
@ -1406,43 +1443,51 @@ const updatePrices = (source: string) => {
|
||||
form.unit_price = undefined;
|
||||
}
|
||||
} else if (source === 'tax') {
|
||||
// 税率变化:保持用户最后编辑的那个价格不变,重算另一个
|
||||
// 税率变化:保持最后编辑的价格不变,重算另一个
|
||||
if (lastPriceEdit.value === 'post' && form.post_tax_unit_price != null) {
|
||||
form.unit_price = Number((form.post_tax_unit_price / taxMultiplier).toFixed(4));
|
||||
} else if (form.unit_price != null) {
|
||||
form.post_tax_unit_price = Number((form.unit_price * taxMultiplier).toFixed(2));
|
||||
}
|
||||
} else if (source === 'post_total') {
|
||||
// 用户输入了含税总价 → 反推不含税总价和单价
|
||||
lastPriceEdit.value = 'post'
|
||||
const postTaxTotal = form._post_tax_total_price
|
||||
if (postTaxTotal != null && form.in_quantity > 0) {
|
||||
const preTaxTotal = postTaxTotal / taxMultiplier
|
||||
form.total_price = Number(preTaxTotal.toFixed(2))
|
||||
form.unit_price = Number((preTaxTotal / form.in_quantity).toFixed(4))
|
||||
form.post_tax_unit_price = Number((form.unit_price * taxMultiplier).toFixed(2))
|
||||
}
|
||||
return // 已完整计算,跳过下面的总价逻辑
|
||||
}
|
||||
|
||||
// 计算不含税总价
|
||||
if (form.in_quantity > 0 && form.unit_price != null) {
|
||||
// 含税单价优先计算总价
|
||||
// 不含税总价 = (含税单价 / (1+税率)) × 数量
|
||||
if (form.in_quantity > 0 && form.post_tax_unit_price != null) {
|
||||
const preTax = form.post_tax_unit_price / taxMultiplier
|
||||
form.unit_price = Number(preTax.toFixed(4))
|
||||
form.total_price = Number((preTax * form.in_quantity).toFixed(2))
|
||||
} else if (form.in_quantity > 0 && form.unit_price != null) {
|
||||
form.total_price = Number((form.in_quantity * form.unit_price).toFixed(2));
|
||||
} else {
|
||||
form.total_price = undefined;
|
||||
}
|
||||
|
||||
if (postTaxTotalManuallySet.value && postTaxTotalInput.value != null) {
|
||||
onPostTaxTotalChange(postTaxTotalInput.value)
|
||||
return
|
||||
}
|
||||
if (!postTaxTotalManuallySet.value) {
|
||||
postTaxTotalInput.value = undefined
|
||||
}
|
||||
}
|
||||
|
||||
// 数量或不含税单价变化 → 自动推总价和含税单价
|
||||
watch(() => [form.in_quantity, form.unit_price], () => {
|
||||
if (form.unit_price != null && form.in_quantity > 0) {
|
||||
form.total_price = Number((form.in_quantity * form.unit_price).toFixed(2));
|
||||
const taxMultiplier = 1 + (form.tax_rate || 0) / 100;
|
||||
form.post_tax_unit_price = Number((form.unit_price * taxMultiplier).toFixed(2));
|
||||
// 数量或单价变化 → 以含税单价为主计算
|
||||
watch(() => [form.in_quantity, form.post_tax_unit_price], () => {
|
||||
if (form.post_tax_unit_price != null && form.in_quantity > 0) {
|
||||
const taxMultiplier = 1 + (form.tax_rate || 0) / 100
|
||||
form.unit_price = Number((form.post_tax_unit_price / taxMultiplier).toFixed(4))
|
||||
form.total_price = Number((form.unit_price * form.in_quantity).toFixed(2))
|
||||
} else if (form.unit_price != null && form.in_quantity > 0) {
|
||||
form.total_price = Number((form.in_quantity * form.unit_price).toFixed(2))
|
||||
form.post_tax_unit_price = Number((form.unit_price * (1 + (form.tax_rate || 0) / 100)).toFixed(2))
|
||||
} else {
|
||||
form.total_price = undefined;
|
||||
form.post_tax_unit_price = undefined;
|
||||
}
|
||||
if (!postTaxTotalManuallySet.value) {
|
||||
postTaxTotalInput.value = undefined
|
||||
}
|
||||
})
|
||||
|
||||
// 注意:入库数量和打印份数现在是独立的字段,不再自动同步
|
||||
@ -2046,9 +2091,10 @@ const resetForm = () => {
|
||||
tax_rate: 0,
|
||||
currency: 'CNY', exchange_rate: 1.00, supplier_name: '', purchaser: '', purchaser_email: '', source_link: '', detail_link: '', arrival_photo: [], inspection_report: [],
|
||||
print_copies: 1,
|
||||
request_id: undefined,
|
||||
_post_tax_total_price: undefined
|
||||
request_id: undefined
|
||||
})
|
||||
postTaxTotalInput.value = undefined
|
||||
postTaxTotalManuallySet.value = false
|
||||
}
|
||||
const getStatusType = (status: string) => { const map: any = {'在库': 'success', '出库': 'info', '损耗': 'danger'}; return map[status] || 'warning' }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user