|
@@ -1,55 +1,168 @@
|
|
|
<script setup lang="ts">
|
|
|
-import { watch, shallowReactive, computed } from "vue"
|
|
|
-import { httpSaleInvoice, httpPurchaseInvoice, httpPurchaseOrders } from "/@/api/invoice"
|
|
|
+import { watch, shallowReactive, computed, reactive, shallowRef, ref } from "vue"
|
|
|
+import { httpInvoiceDetail, httpPurchaseOrders, httpRelation, httpUnRelation } from "/@/api/invoice"
|
|
|
+import { multiplication, addition, subtraction } from "/@/utils/calc";
|
|
|
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
|
|
|
-import { multiplication, addition, division } from "/@/utils/calc";
|
|
|
-import { useTask } from "/@/hooks/core"
|
|
|
+import { useTask, useTasks } from "/@/hooks/core"
|
|
|
+import { ElMessage } from "element-plus"
|
|
|
import Modal from "./modal.vue"
|
|
|
+import OrderModal from "./order-modal.vue"
|
|
|
|
|
|
const props = withDefaults(defineProps<{
|
|
|
code: string;
|
|
|
+ payNo?: string;
|
|
|
invNumber: string;
|
|
|
mode?: 'sale' | 'purchase';
|
|
|
}>(),
|
|
|
{ mode: 'purchase' });
|
|
|
|
|
|
-const state = shallowReactive({
|
|
|
+
|
|
|
+const state = shallowReactive({
|
|
|
index: 0, // 当前修改项索引
|
|
|
count: 0, // 当前发票明细总条数
|
|
|
- visible: false // 修改模态框是否显示
|
|
|
+ total: 0, // 当前订单总金额
|
|
|
+})
|
|
|
+
|
|
|
+const modalState = reactive({
|
|
|
+ visible: false,
|
|
|
+ index: -1,
|
|
|
+ data: {},
|
|
|
})
|
|
|
|
|
|
+
|
|
|
+const orderModalVisible = shallowRef(false)
|
|
|
+const orders = ref([])
|
|
|
+
|
|
|
const currentInvoiceItem = computed(() => {
|
|
|
const list = (invoiceDetailTask.data || [])
|
|
|
- return list[state.index] || {}
|
|
|
+ const item = list[state.index] || {}
|
|
|
+ const { status, OrderInfo } = item
|
|
|
+
|
|
|
+ if(status == '2' || status == '1'){
|
|
|
+ orders.value = OrderInfo.map((item) => ({
|
|
|
+ id: item.id,
|
|
|
+ goodNum: item.num,
|
|
|
+ itemId: item.itemId,
|
|
|
+ goodNo: item.spuCode,
|
|
|
+ sequenceNo: item.code,
|
|
|
+ cat_code: item.cat_code,
|
|
|
+ cat_name: item.cat_name,
|
|
|
+ goodName: item.good_name,
|
|
|
+ goodPrice: item.good_price,
|
|
|
+ totalPrice: item.total_amount,
|
|
|
+ }))
|
|
|
+
|
|
|
+ calcTaxAfterAmount()
|
|
|
+ }
|
|
|
+
|
|
|
+ return item
|
|
|
})
|
|
|
|
|
|
-const orderDetailTask = useTask({ initialData: [], root: false })
|
|
|
-const invoiceDetailTask = useTask({ initialData: [], success(data) {
|
|
|
- const { item_list = [] } = (data || {}) as any
|
|
|
- const invoiceDetail = item_list.map((item) => {
|
|
|
- const { tax_rate = '', amount = 0 } = item;
|
|
|
- const tax = division(tax_rate.replace('%', ''), 100)
|
|
|
- // 总税额
|
|
|
- const taxAmount = Number(multiplication(Number(amount).toFixed(2), tax)).toFixed(2)
|
|
|
- const includeTaxAmount = Number(addition(Number(amount).toFixed(2), taxAmount)).toFixed(2)
|
|
|
- return { ...item, includeTaxAmount, taxAmount }
|
|
|
- })
|
|
|
+/* 计算差值 = 当前发票明细总金额 - 订单总金额*/
|
|
|
+const difference = computed(() => {
|
|
|
+ const money = Number(subtraction(currentInvoiceItem.value.total_amount, state.total)).toFixed(2)
|
|
|
+ return {
|
|
|
+ mode: Number(money) === 0 ? 'ok' : Number(money) > 0 ? 'down' : 'up',
|
|
|
+ money: Number.isNaN(money) || money === 'NaN' ? 0 : Math.abs(Number(money))
|
|
|
+ }
|
|
|
+})
|
|
|
|
|
|
- invoiceDetailTask.data = invoiceDetail
|
|
|
- state.count = invoiceDetail.length
|
|
|
+
|
|
|
+const relationTask = useTask<any>()
|
|
|
+// 订单相关处理
|
|
|
+const orderDetailTask = useTask<any>({ initialData: [], root: false, success({ list = [] } = {}){
|
|
|
+ orderDetailTask.data = list.map(item => {
|
|
|
+ const { goodNum = 0, goodPrice = 0, ...rest } = item
|
|
|
+ return { ...rest, goodNum, goodPrice ,openAmount: Number(multiplication(Number(goodPrice).toFixed(2), goodNum)).toFixed(2) }
|
|
|
+ })
|
|
|
+ calcTaxAfterAmount()
|
|
|
}})
|
|
|
+// 发票明细相关处理
|
|
|
+const invoiceDetailTask = useTask<any>({ initialData: [], success(data = []) { state.count = data.length }})
|
|
|
+
|
|
|
+
|
|
|
+const unRelationTask = useTask({
|
|
|
+ success(){
|
|
|
+ ElMessage.success('解除成功')
|
|
|
+ initialData()
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+const taskState = useTasks(orderDetailTask, invoiceDetailTask, relationTask, unRelationTask)
|
|
|
+
|
|
|
+const initialData = () => { invoiceDetailTask.run(httpInvoiceDetail({ code: props.code })) }
|
|
|
+
|
|
|
+
|
|
|
+/* 计算税后金额 */
|
|
|
+const calcTaxAfterAmount = () => state.total = orders.value.reduce((prev, current) => Number(addition(current.totalPrice, prev)).toFixed(2), 0)
|
|
|
+
|
|
|
+function onUpdate(data: any, index: number){
|
|
|
+ modalState.visible = true
|
|
|
+ modalState.index = index
|
|
|
+ modalState.data = data
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
-function initialData(){
|
|
|
- const invoiceAPI = props.mode === 'purchase' ? httpPurchaseInvoice : httpSaleInvoice
|
|
|
+function handleOrderItemUpdate(openAmount: number, goodNum: number ,index: number){
|
|
|
+ orders.value[index].totalPrice = openAmount
|
|
|
+ orders.value[index].goodNum = goodNum
|
|
|
+ calcTaxAfterAmount()
|
|
|
+}
|
|
|
+function handleOrderUpdate(list: any[] = []){
|
|
|
+ const payNos = orders.value.map(({payNo}) => payNo)
|
|
|
+ const newList = []
|
|
|
+ list.forEach(item => {
|
|
|
+ if(payNos.includes(item.payNo)){ return }
|
|
|
+ newList.push(item)
|
|
|
+ })
|
|
|
+
|
|
|
+ orders.value = [...orders.value, ...newList]
|
|
|
+ console.log(orders.value)
|
|
|
+ calcTaxAfterAmount()
|
|
|
+}
|
|
|
+
|
|
|
+async function toNext(){
|
|
|
+ const { money, mode } = difference.value
|
|
|
+ if(mode !== 'ok' && props.mode !== 'sale'){
|
|
|
+ ElMessage.error(`发票明细税后金额与当前订单税后金额不符,${mode === 'up' ? '超出' : '还差'}:${money} 元`)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // if(currentInvoiceItem.value.status != '2'){
|
|
|
+ const orderArr = orders.value.map(({ goodNo, sequenceNo, goodNum, totalPrice, goodPrice, goodName }) => ({
|
|
|
+ total_amount: totalPrice,
|
|
|
+ good_price: goodPrice,
|
|
|
+ good_name: goodName,
|
|
|
+ code: sequenceNo,
|
|
|
+ spuCode: goodNo,
|
|
|
+ num: goodNum,
|
|
|
+ remark: ''
|
|
|
+ }))
|
|
|
+
|
|
|
+ const itemId = currentInvoiceItem.value.id
|
|
|
+ const result = await relationTask.run(httpRelation({ orderArr, itemId }))
|
|
|
+
|
|
|
+ if(result.code == '0'){
|
|
|
+ orders.value = []
|
|
|
+ state.index = state.index + 1
|
|
|
+ }else{
|
|
|
+ ElMessage.warning(result.message)
|
|
|
+ }
|
|
|
+
|
|
|
+ // }else{
|
|
|
+ // orders.value = []
|
|
|
+ // state.index = state.index + 1
|
|
|
+ // }
|
|
|
+}
|
|
|
+
|
|
|
+function toPrev(){
|
|
|
+ state.index = state.index - 1
|
|
|
const orderAPI = props.mode === 'purchase' ? httpPurchaseOrders : httpPurchaseOrders
|
|
|
- invoiceDetailTask.run(invoiceAPI({ number: props.invNumber }))
|
|
|
orderDetailTask.run(orderAPI({ payNo: props.code }))
|
|
|
}
|
|
|
+
|
|
|
|
|
|
-function onUpdate(){
|
|
|
- state.visible = true
|
|
|
-}
|
|
|
+const onUnRelation = ({ id }) => unRelationTask.run(httpUnRelation({ id }))
|
|
|
|
|
|
watch(() => props.invNumber, () => {
|
|
|
if(!props.invNumber) return
|
|
@@ -60,69 +173,103 @@ watch(() => props.invNumber, () => {
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
- <div class="flex flex-col">
|
|
|
-
|
|
|
+ <div class="flex flex-col" v-loading="taskState.loading">
|
|
|
<div class="flex justify-between mb-[10px]">
|
|
|
<p>发票明细:当前第 {{ state.index + 1 }} 条/共 {{ state.count }} 条</p>
|
|
|
<ElButtonGroup size="small" type="primary">
|
|
|
<ElTooltip content="上一条" placement="top" v-if="state.index !== 0">
|
|
|
- <ElButton :icon="useRenderIcon('arrow-left-s-line')" />
|
|
|
+ <ElButton @click="toPrev" :icon="useRenderIcon('arrow-left-s-line')" />
|
|
|
</ElTooltip>
|
|
|
|
|
|
- <ElTooltip content="下一条" placement="top" v-if="(state.index + 1) !== state.count">
|
|
|
- <ElButton :icon="useRenderIcon('arrow-right-s-line')" />
|
|
|
+ <ElTooltip content="下一条" placement="top">
|
|
|
+ <ElButton @click="toNext" :icon="useRenderIcon('arrow-right-s-line')" />
|
|
|
</ElTooltip>
|
|
|
</ElButtonGroup>
|
|
|
</div>
|
|
|
|
|
|
<ElTable border size="small" :data="[currentInvoiceItem]">
|
|
|
- <ElTableColumn label="货物或应税劳务、服务名称" prop="name" min-width="180px" show-overflow-tooltip />
|
|
|
- <ElTableColumn label="数量" prop="quantity" width="80px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="货物或应税劳务、服务名称" prop="good_name" min-width="180px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="数量" prop="num" width="80px" show-overflow-tooltip />
|
|
|
<ElTableColumn label="单价(含税)" prop="unit_price" width="120px" show-overflow-tooltip />
|
|
|
<ElTableColumn label="金额" prop="amount" width="80px" show-overflow-tooltip />
|
|
|
- <ElTableColumn label="税额" prop="tax_rate" width="80px" show-overflow-tooltip />
|
|
|
- <ElTableColumn label="税额" prop="taxAmount" width="80px" show-overflow-tooltip />
|
|
|
- <ElTableColumn label="税后总额" prop="includeTaxAmount" width="120px" show-overflow-tooltip />
|
|
|
- <ElTableColumn label="发票明细类目名称" min-width="140px" show-overflow-tooltip />
|
|
|
- <ElTableColumn label="发票明细类目编号" min-width="140px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="税率" prop="tax" width="80px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="税额" prop="tax_amount" width="80px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="税后总额" prop="total_amount" width="120px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="发票明细类目名称" prop="cat_code" min-width="140px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="发票明细类目编号" prop="cat_name" min-width="140px" show-overflow-tooltip />
|
|
|
</ElTable>
|
|
|
|
|
|
<div class="flex justify-between my-[10px]">
|
|
|
- <p>当前当前发票明细税后金额为:{{ currentInvoiceItem.includeTaxAmount }} 元,当前订单税后金额为 0 元, 还差 0 元</p>
|
|
|
+ <p>当前发票明细税后金额为:{{ currentInvoiceItem.total_amount }} 元,当前订单税后金额为 {{state.total}} 元,
|
|
|
+ <span :style="`${difference.mode !== 'ok' ? 'color:red' : ''}`">
|
|
|
+ {{ difference.mode === 'up' ? '超出' : '还差' }} {{ difference.money }} 元
|
|
|
+ </span>
|
|
|
+ </p>
|
|
|
</div>
|
|
|
|
|
|
- <ElTable class="mb-[50px]" border size="small" :data="orderDetailTask.data">
|
|
|
- <ElTableColumn label="序号" type="index" width="60px" show-overflow-tooltip />
|
|
|
+ <ElTable class="mb-[50px]" border size="small" :data="orders">
|
|
|
+ <ElTableColumn type="index" label="序号" width="60px" />
|
|
|
<ElTableColumn label="采购单编号" prop="sequenceNo" width="160px" show-overflow-tooltip />
|
|
|
<ElTableColumn label="商品编号" prop="goodNo" width="160px" show-overflow-tooltip />
|
|
|
<ElTableColumn label="商品名称" prop="goodName" min-width="160px" show-overflow-tooltip />
|
|
|
- <ElTableColumn label="订单商品类目编号" min-width="140px" show-overflow-tooltip>
|
|
|
- <template #="{ row }">
|
|
|
- {{ (row.orderTax || {}).merge_code || '--'}}
|
|
|
- </template>
|
|
|
- </ElTableColumn>
|
|
|
- <ElTableColumn label="订单商品类目名称" min-width="140px" show-overflow-tooltip>
|
|
|
- <template #="{ row }">
|
|
|
- {{ (row.orderTax || {}).cat_name || '--'}}
|
|
|
- </template>
|
|
|
- </ElTableColumn>
|
|
|
+ <ElTableColumn label="订单商品类目编号" prop="cat_code" min-width="140px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="订单商品类目名称" prop="cat_name" min-width="140px" show-overflow-tooltip />
|
|
|
<ElTableColumn label="数量" prop="goodNum" width="80px" show-overflow-tooltip />
|
|
|
- <ElTableColumn label="单价" prop="goddPirce" width="80px" show-overflow-tooltip />
|
|
|
- <ElTableColumn label="开票金额" prop="TODO" width="120px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="单价" prop="goodPrice" width="80px" show-overflow-tooltip />
|
|
|
+ <ElTableColumn label="开票金额" prop="totalPrice" width="120px" show-overflow-tooltip />
|
|
|
<ElTableColumn label="操作" width="80px" fixed="right">
|
|
|
- <template #="{ row }">
|
|
|
- <ElTooltip content="解除绑定" placement="top">
|
|
|
- <ElButton type="primary" link :icon="useRenderIcon('close-circle-line')" />
|
|
|
- </ElTooltip>
|
|
|
+ <template #header>
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <p>操作</p>
|
|
|
+ <!-- v-if="currentInvoiceItem.status != '2'" -->
|
|
|
+ <ElTooltip content="添加采购单" placement="top">
|
|
|
+ <ElButton
|
|
|
+ link
|
|
|
+ type="primary"
|
|
|
+ :icon="useRenderIcon('add')"
|
|
|
+ @click="() => orderModalVisible = true"
|
|
|
+ />
|
|
|
+ </ElTooltip>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #="{ row, $index }">
|
|
|
+ <!-- <ElTooltip content="解除关联" placement="top" v-if="currentInvoiceItem.status == '2'">
|
|
|
+ <ElButton type="primary" link :icon="useRenderIcon('delete')" @click="onDelete(row)" />
|
|
|
+ </ElTooltip> -->
|
|
|
+
|
|
|
+ <ElPopconfirm
|
|
|
+ title="是否确认解除关联?"
|
|
|
+ v-if="currentInvoiceItem.status == '2'"
|
|
|
+ @confirm="onUnRelation(row)"
|
|
|
+ >
|
|
|
+ <template #reference>
|
|
|
+ <ElButton type="primary" link :icon="useRenderIcon('delete')" />
|
|
|
+ </template>
|
|
|
+ </ElPopconfirm>
|
|
|
+
|
|
|
|
|
|
- <ElTooltip content="修改" placement="top">
|
|
|
- <ElButton type="primary" link :icon="useRenderIcon('edits')" @click="onUpdate" />
|
|
|
+ <!-- v-if="currentInvoiceItem.status != '2'" -->
|
|
|
+
|
|
|
+ <ElTooltip content="修改" placement="top" >
|
|
|
+ <ElButton type="primary" link :icon="useRenderIcon('edits')" @click="onUpdate(row, $index)" />
|
|
|
</ElTooltip>
|
|
|
</template>
|
|
|
</ElTableColumn>
|
|
|
</ElTable>
|
|
|
|
|
|
|
|
|
- <Modal v-model:visible="state.visible" />
|
|
|
+ <Modal
|
|
|
+ @update="handleOrderItemUpdate"
|
|
|
+ v-model:visible="modalState.visible"
|
|
|
+ :index="modalState.index"
|
|
|
+ :data="modalState.data"
|
|
|
+ />
|
|
|
+
|
|
|
+ <OrderModal
|
|
|
+ v-model:visible="orderModalVisible"
|
|
|
+ @confirm="handleOrderUpdate"
|
|
|
+ :payNo="payNo"
|
|
|
+ />
|
|
|
</div>
|
|
|
</template>
|