snow 6 місяців тому
батько
коміт
e49c763384

+ 4 - 0
src/api/invoice.ts

@@ -30,6 +30,10 @@ export const httpPurchaseOrders = (data?: object): postType => {
   return http.request("post", `${yewuApi}InvoiceItem/cgdListByPayNo`, { data });
 };
 
+export const httpSaleOrders = (data?: object): postType => {
+  return http.request("post", `${yewuApi}InvoiceItem/qrdListByInvNo`, { data });
+};
+
 
 export const httpRelation = (data?: object): postType => {
   return http.request("post", `${yewuApi}InvoiceItem/create`, { data });

+ 5 - 0
src/api/purchase/ticketReturn/index.ts

@@ -38,6 +38,11 @@ export const httpBatchimport = (data: object): any => {
   return http.request("post", `${yewuApi}hpbatchimport`, { data });
 };
 
+
+export const httpInvoiceBatch = (data: object): any => {
+  return http.request("post", `${yewuApi}InvoiceItem/importOrder`, { data });
+};
+
 //发票回票批量添加
 export const httpBatchAdd = (data: object): any => {
   return http.request("post", `${yewuApi}invAddBatchByImport`, { data });

+ 124 - 69
src/components/OrderRelation/src/index.vue

@@ -8,9 +8,12 @@ import { ElMessage } from "element-plus"
 import Modal from "./modal.vue"
 import OrderModal from "./order-modal.vue"
 
+
+const emit = defineEmits(['refresh'])
 const props = withDefaults(defineProps<{
   code: string;
   payNo?: string;
+  invNo?: string;
   invNumber: string;
   mode?: 'sale' | 'purchase';
 }>(),
@@ -37,27 +40,21 @@ const currentInvoiceItem = computed(() => {
   const list = (invoiceDetailTask.data || [])
   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,
-    }))
+  if(status == '2' || status == '1'){ refreshOrders(OrderInfo) }
+  return item
+})
 
-    calcTaxAfterAmount()
-  }
 
-  return item
+// 判断是否已经关联完了
+const isRelated = computed(() => {
+  const { mode } = props
+  console.log(mode === 'sale' && currentInvoiceItem.value.status != '0', mode, currentInvoiceItem.value.status)
+  if(mode === 'sale' && currentInvoiceItem.value.status != '0') return true
+  if(mode === 'purchase' && currentInvoiceItem.value.status == '1') return true
+  return false
 })
 
+
 /* 计算差值 = 当前发票明细总金额 - 订单总金额*/
 const difference = computed(() => {
   const money = Number(subtraction(currentInvoiceItem.value.total_amount, state.total)).toFixed(2)
@@ -67,8 +64,28 @@ const difference = computed(() => {
   }
 })
 
+function refreshOrders(orderInfo: any = []) {
+  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,
+      balance_amount: item.balance_amount,
+      open_amount: item.total_amount,
+    }))
+
+  calcTaxAfterAmount()
+}
 
+
+// 创建关联
 const relationTask = useTask<any>()
+
 // 订单相关处理
 const orderDetailTask = useTask<any>({ initialData: [], root: false, success({ list = [] } = {}){
   orderDetailTask.data = list.map(item => {
@@ -77,37 +94,45 @@ const orderDetailTask = useTask<any>({ initialData: [], root: false, success({ l
   })
   calcTaxAfterAmount()
 }})
+
+
 // 发票明细相关处理
 const invoiceDetailTask  = useTask<any>({ initialData: [], success(data = []) { state.count = data.length }})
 
-
+// 解除关联
 const unRelationTask = useTask({
-  success(){
+  success: async () => {
     ElMessage.success('解除成功')
-    initialData()
+    // 刷新发票明细
+    await refreshInvoiceDetail()
+    // 刷新绑定的订单信息
+    const item = ((invoiceDetailTask.data || [])[state.index]) || {}
+    const { OrderInfo } = item
+    refreshOrders(OrderInfo)
   }
 })
 
-const taskState = useTasks(orderDetailTask, invoiceDetailTask, relationTask, unRelationTask)
 
-const initialData = () => { invoiceDetailTask.run(httpInvoiceDetail({ code: props.code  })) }
+const refreshInvoiceDetail = () => invoiceDetailTask.run(httpInvoiceDetail({ code: props.code  }))
+const taskState = useTasks(orderDetailTask, invoiceDetailTask, relationTask, unRelationTask)
 
 
 /* 计算税后金额 */
-const calcTaxAfterAmount = () =>  state.total = orders.value.reduce((prev, current) => Number(addition(current.totalPrice, prev)).toFixed(2), 0)
-
+const calcTaxAfterAmount = () =>  state.total = orders.value.reduce((prev, current) => Number(addition(current.open_amount, prev)).toFixed(2), 0)
 function onUpdate(data: any, index: number){
   modalState.visible = true
   modalState.index = index
   modalState.data = data
 }
 
-
-function handleOrderItemUpdate(openAmount: number, goodNum: number ,index: number){
-  orders.value[index].totalPrice = openAmount
+/** 修改订单项 */
+function handleOrderItemUpdate(open_amount: number, goodNum: number ,index: number){
+  orders.value[index].open_amount = open_amount
   orders.value[index].goodNum = goodNum
   calcTaxAfterAmount()
 }
+
+/** 添加订单项 */
 function handleOrderUpdate(list: any[] = []){
   const payNos = orders.value.map(({payNo}) => payNo)
   const newList = []
@@ -117,20 +142,31 @@ function handleOrderUpdate(list: any[] = []){
   })
 
   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} 元`)
+  if(orders.value.length === 0){
+    ElMessage.error(`至少添加一条数据!`)
+    return
+  }
+
+  if(state.total <= 0){
+    ElMessage.error(`金额不能为零!`)
     return
   }
 
-  // if(currentInvoiceItem.value.status != '2'){
-    const orderArr = orders.value.map(({ goodNo, sequenceNo, goodNum, totalPrice, goodPrice, goodName }) => ({
-      total_amount: totalPrice,
+  if(mode !== 'ok' && props.mode !== 'sale' && currentInvoiceItem.value.status != '1'){
+    ElMessage.error(`发票明细税后金额与当前订单税后金额不符,${mode === 'up' ? '超出' : '还差'} ${money} 元`)
+    return
+  }
+
+  if(!isRelated.value){
+    const orderArr = orders.value.map(({ goodNo, sequenceNo, goodNum, open_amount, goodPrice, goodName }) => ({
+      total_amount: open_amount,
       good_price: goodPrice,
       good_name: goodName,
       code: sequenceNo,
@@ -140,34 +176,50 @@ async function toNext(){
     }))
 
     const itemId = currentInvoiceItem.value.id
-    const result = await relationTask.run(httpRelation({ orderArr, itemId }))
+    const result: any = await relationTask.run(httpRelation({ orderArr, itemId }))
 
     if(result.code == '0'){
-      orders.value = []
-      state.index = state.index + 1
+      if(state.index + 1 === invoiceDetailTask.data.length){
+        emit('refresh')
+      }else{
+        state.total = 0
+        orders.value = []
+        state.index = state.index + 1
+      }
     }else{
       ElMessage.warning(result.message)
     }
-
-  // }else{
-  //   orders.value = []
-  //   state.index = state.index + 1
-  // }
+  }else{
+    if(state.index + 1 === invoiceDetailTask.data.length){
+      emit('refresh')
+    }else{
+      state.total = 0
+      orders.value = []
+      state.index = state.index + 1
+    }
+  }
 }
 
-function toPrev(){
+
+// 
+async function toPrev(){
   state.index = state.index - 1
-  const orderAPI = props.mode === 'purchase' ? httpPurchaseOrders : httpPurchaseOrders
-  orderDetailTask.run(orderAPI({ payNo: props.code }))
+ // 刷新发票明细
+ await refreshInvoiceDetail()
+ // 刷新绑定的订单信息
+ const item = ((invoiceDetailTask.data || [])[state.index]) || {}
+ const { OrderInfo } = item
+ refreshOrders(OrderInfo)
 }
   
 
 const onUnRelation = ({ id }) => unRelationTask.run(httpUnRelation({ id }))
 
-watch(() => props.invNumber, () => {
-  if(!props.invNumber) return
-  initialData()
-}, {
+
+watch(() => props.code, () => {
+  if(!props.code) return
+  refreshInvoiceDetail()
+},{
   immediate: true
 })
 </script>
@@ -181,9 +233,11 @@ watch(() => props.invNumber, () => {
           <ElButton @click="toPrev" :icon="useRenderIcon('arrow-left-s-line')" />
         </ElTooltip>      
 
-        <ElTooltip content="下一条" placement="top">
+        <ElTooltip content="下一条" placement="top" v-if="state.index + 1 !== invoiceDetailTask.data.length">
           <ElButton @click="toNext" :icon="useRenderIcon('arrow-right-s-line')" />
-        </ElTooltip>  
+        </ElTooltip>
+
+        <ElButton v-else @click="toNext">提交</ElButton>
       </ElButtonGroup>
     </div>
 
@@ -195,34 +249,40 @@ watch(() => props.invNumber, () => {
       <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 />
+      <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.total_amount }} 元,当前订单税后金额为 {{state.total}} 元, 
-        <span :style="`${difference.mode !== 'ok' ? 'color:red' : ''}`"> 
-          {{ difference.mode === 'up' ? '超出' : '还差' }} {{ difference.money }} 元
-        </span>
+      <p>当前发票明细税后金额为:{{ currentInvoiceItem.total_amount }} 元,
+        <template v-if="!isRelated">
+          当前订单税后金额为 {{state.total}} 元, 
+          <span :style="`${difference.mode !== 'ok' ? 'color:red' : ''}`"> 
+            {{ difference.mode === 'up' ? '超出' : '还差' }} {{ difference.money }} 元
+          </span>
+        </template>
+        <template v-else>
+          已关联完成。
+        </template>
       </p>
     </div>
 
     <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="`${mode === 'sale' ? '采购单' : '销售单'}编号`" 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="订单商品类目编号" 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="goodPrice"  width="80px" show-overflow-tooltip />
-      <ElTableColumn label="开票金额" prop="totalPrice"  width="120px" show-overflow-tooltip />
+      <ElTableColumn label="未关联金额" prop="balance_amount"  width="80px" show-overflow-tooltip />
+      <ElTableColumn label="开票金额" prop="open_amount"  width="120px" show-overflow-tooltip />
       <ElTableColumn label="操作" width="80px" fixed="right">
         <template #header>
           <div class="flex justify-between items-center">
             <p>操作</p>
-            <!-- v-if="currentInvoiceItem.status != '2'" -->
-            <ElTooltip content="添加采购单" placement="top">
+            <ElTooltip content="添加采购单" placement="top" v-if="!isRelated">
               <ElButton
                 link 
                 type="primary" 
@@ -234,24 +294,17 @@ watch(() => props.invNumber, () => {
         </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)"
+              v-if="isRelated"
             >
               <template #reference>
                 <ElButton type="primary" link :icon="useRenderIcon('delete')" />
               </template>
           </ElPopconfirm>
     
-
-          <!-- v-if="currentInvoiceItem.status != '2'" -->
-
-          <ElTooltip content="修改" placement="top" >
+          <ElTooltip content="修改" placement="top" v-if="!isRelated">
             <ElButton type="primary" link :icon="useRenderIcon('edits')" @click="onUpdate(row, $index)" />
           </ElTooltip>
         </template>
@@ -270,6 +323,8 @@ watch(() => props.invNumber, () => {
       v-model:visible="orderModalVisible"
       @confirm="handleOrderUpdate"
       :payNo="payNo"
+      :invNo="invNo"
+      :mode="mode"
     />
   </div>
 </template>

+ 14 - 3
src/components/OrderRelation/src/modal.vue

@@ -5,13 +5,18 @@ import BasicDescriptions from "/@/components/BasicDescriptions";
 import { createTooltip } from "/@/utils/tootip";
 import { useVModel } from "@vueuse/core"
 
+import { division } from "/@/utils/calc";
+
 
 const emit = defineEmits(['update'])
 const props = defineProps<{ visible: boolean, data: any, index: number, mode: 'sale' | 'purchase' }>()
 
 const visible  = useVModel(props, 'visible')
 const openAmount = shallowRef(0)
+const goodPrice = shallowRef(0)
 const goodNum = shallowRef(0)
+
+
 const detail = ref({})
 
 const columns = [
@@ -35,7 +40,8 @@ const columns = [
   {
     field: 'goodPrice',
     label: '单价',
-    span: 8
+    span: 8,
+    render:() => goodPrice.value
   },
   {
     field: 'goodNum',
@@ -45,7 +51,6 @@ const columns = [
       return h(ElInputNumber, {
         size: 'small',
         modelValue: goodNum.value,
-        // max: props.data.goodNum,
         min: 0,
         'onUpdate:modelValue': value => goodNum.value = value,
         controlsPosition: 'right',
@@ -62,7 +67,7 @@ const columns = [
       return h(ElInputNumber, {
         size: 'small',
         modelValue: openAmount.value,
-        // max: props.data.totalPrice,
+        max: props.data.balance_amount,
         min: 0,
         'onUpdate:modelValue': value => openAmount.value = value,
         controlsPosition: 'right',
@@ -78,6 +83,7 @@ watch(() => visible.value, () => {
   if(!visible.value) return
   nextTick(() => {
     detail.value = props.data
+    goodPrice.value = props.data.goodPrice
     openAmount.value = props.data.totalPrice
     goodNum.value = props.data.goodNum
   })
@@ -86,6 +92,11 @@ watch(() => visible.value, () => {
 })
 
 
+watch(() => [openAmount.value, goodNum.value], () => {
+  goodPrice.value = Number(division(openAmount.value, goodNum.value)).toFixed(2)
+})
+
+
 function confirm(){
   emit('update', openAmount.value, goodNum.value ,props.index )
   visible.value = false

+ 59 - 7
src/components/OrderRelation/src/order-modal.vue

@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import { watch, ref } from "vue"
-import { httpPurchaseOrders } from "/@/api/invoice"
+import { httpPurchaseOrders, httpSaleOrders } from "/@/api/invoice"
 import { useVModel } from "@vueuse/core"
 import { useTask } from "/@/hooks/core"
 
@@ -8,7 +8,19 @@ import { ElMessage } from "element-plus"
 
 
 const emit = defineEmits(['confirm'])
-const props = defineProps<{ visible: boolean, mode: 'sale' | 'purchase', payNo: string }>()
+const props = defineProps<{ 
+  visible: boolean, 
+  mode: 'sale' | 'purchase', 
+  payNo: string,
+  invNo: string
+}>()
+
+
+const parameter = ref({
+  merge_code: '',
+  inv_good_name: '',
+})
+
 
 const visible = useVModel(props, 'visible')
 const orderTask = useTask<any>({ initialData: [],  root: true })
@@ -22,21 +34,61 @@ function onConfirm(){
   }
 
 
-  emit('confirm', selected.value)
+  emit('confirm', selected.value.map((item) => ({
+    ...item,
+    open_amount: item.balance_amount
+  })))
+  visible.value = false
+}
+
+
+const onSearch = () =>  {
+  const api = props.mode === 'sale' ? httpSaleOrders : httpPurchaseOrders;
+  const prop = props.mode === 'sale' ? 'invNo' : 'payNo'
+  orderTask.run(api({ [prop]: props[prop], ...parameter.value }))
+}
+
+function handleClose(){
+  parameter.value = {
+    merge_code: '',
+    inv_good_name: '',
+  }
   visible.value = false
 }
 
 
 watch(() => props.visible, () => {
   if(!props.visible) return
-  orderTask.run(httpPurchaseOrders({ payNo: props.payNo }))
+  onSearch()
 }, {
   immediate: true
 })
 </script>
 
 <template>
-  <ElDialog v-model="visible" center :title="`选择${props.mode === 'sale' ? '销售订单' : '采购订单'}`" @close="visible = false">
+  <ElDialog v-model="visible" center :title="`选择${props.mode === 'sale' ? '销售订单' : '采购订单'}`" @close="handleClose">
+    <ElRow class="mb-[10px]" :gutter="10">
+      <ElCol :span="8">
+        <ElInput 
+          v-model="parameter.merge_code" 
+          size="small" 
+          placeholder="商品类目编号" 
+          clearable
+          @change="onSearch" 
+        />
+      </ElCol>
+
+      <ElCol :span="8">
+        <ElInput 
+          v-model="parameter.inv_good_name" 
+          size="small" 
+          placeholder="开票商品名称" 
+          @change="onSearch"
+          clearable
+        />
+      </ElCol>
+    </ElRow>
+
     <ElTable 
       border 
       size="small" 
@@ -45,14 +97,14 @@ watch(() => props.visible, () => {
       @selection-change="list => selected = list"
     >
       <ElTableColumn type="selection" width="40px" />
-      <ElTableColumn label="采购单编号" prop="sequenceNo" width="160px" show-overflow-tooltip />
+      <ElTableColumn :label="`${mode === 'sale' ? '采购单' : '销售单'}编号`" 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="订单商品类目编号" 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="goodPrice"  width="80px" show-overflow-tooltip />
-      <ElTableColumn label="开票金额" prop="openAmount"  width="120px" show-overflow-tooltip />
+      <ElTableColumn label="未关联金额" prop="balance_amount"  width="120px" show-overflow-tooltip />
     </ElTable>
 
     <div class="flex justify-end pt-[10px]">

+ 2 - 0
src/components/OrderRelationApproval/index.ts

@@ -0,0 +1,2 @@
+import OrderRelationApproval from "./src/index.vue"
+export default OrderRelationApproval

+ 138 - 0
src/components/OrderRelationApproval/src/index.vue

@@ -0,0 +1,138 @@
+<script setup lang="ts">
+import { ref, computed, watch } from "vue"
+import { ElForm } from "element-plus" 
+import { httpInvoiceDetail } from "/@/api/invoice"
+import { useTask } from "/@/hooks/core"
+
+
+const emit = defineEmits(['submit'])
+const props = withDefaults(defineProps<{
+  code: string;
+  successCode?: string;
+  rejectCode?: string;
+  mode?: 'sale' | 'purchase';
+}>(),
+{ mode: 'purchase', rejectCode: '0', successCode: '1' });
+
+const formRef = ref<InstanceType<typeof ElForm> | null>(null)
+
+const rules = computed(() => ({
+  status: [{ required: true, message: '请选择审核状态', trigger: 'change' }],
+  remark: [{ required: isRequiredRemark.value || formData.value.status == props.rejectCode, message: '请输入备注', trigger: 'change' }],
+}))
+
+const orders = ref([])
+const isRequiredRemark = ref(false)
+
+const formData = ref({
+  status: '',
+  remark: '',
+})
+
+// 发票明细相关处理
+const invoiceDetailTask  = useTask<any>({ initialData: [], success(data = []) {
+  const list = []
+
+  const map:Map<string, string> = new Map()
+
+  data.forEach(({ OrderInfo = [] }) => {
+    OrderInfo.forEach(item => {
+      
+      if(item.cat_diff == '2' || item.cat_diff == '2'){ isRequiredRemark.value = true }
+      const { diff_info = {}, code = '' } = item
+      const { tax_diff, cat_diff } = diff_info
+      const symbol = `${code}-${tax_diff}-${cat_diff}`
+      console.log(symbol)
+
+      if(!map.has(symbol)){
+        map.set(symbol, '')
+        list.push(item)
+      }
+    })
+  })
+
+  orders.value = list
+}})
+
+const refreshInvoiceDetail = () => invoiceDetailTask.run(httpInvoiceDetail({ code: props.code  }))
+
+async function onSubmit(){
+  try{
+    await formRef.value.validate()
+    emit('submit', formData.value)
+  }catch(err){
+    console.log(err)
+  }
+}
+
+watch(() => props.code, () => {
+  if(!props.code) return
+  refreshInvoiceDetail()
+},{
+  immediate: true
+})
+</script>
+
+<template>
+  <div class="flex flex-col">
+    <ElTable border size="small" :data="orders">
+      <ElTableColumn width="60px" label="序号" type="index" />
+      <ElTableColumn label="订单编号" min-width="160px" prop="code" show-overflow-tooltip />
+      <ElTableColumn label="商品名称" min-width="160px" prop="good_name" show-overflow-tooltip />
+      <ElTableColumn label="预计类目编号" min-width="160px" show-overflow-tooltip>
+        <template #="{ row }">
+          {{ row.diff_info?.cat_code.order_cat_code }}
+        </template>
+      </ElTableColumn>
+
+      <ElTableColumn label="实开类目编号" min-width="160px" show-overflow-tooltip>
+        <template #="{ row }">
+          {{ row.diff_info?.cat_code.inv_cat_code }}
+        </template>
+      </ElTableColumn>
+      
+      <ElTableColumn label="预计与实开类目编号状态" width="150px" show-overflow-tooltip>
+        <template #="{ row }">
+          <ElTag size="small" :type="row.cat_diff == '2' ? 'danger' : 'success'">{{ row.cat_diff == '2' ? '不一致' : '一致' }}</ElTag>
+        </template>
+      </ElTableColumn>
+      
+      <ElTableColumn label="预计类目税率" width="100px" show-overflow-tooltip>
+        <template #="{ row }">
+          {{ row.diff_info?.tax.order_tax }}
+        </template>
+      </ElTableColumn>
+      
+      <ElTableColumn label="实开类目税率" width="100px" show-overflow-tooltip>
+        <template #="{ row }">
+          {{ row.diff_info?.tax.inv_tax }}
+        </template>
+      </ElTableColumn>
+
+      <ElTableColumn label="预计与实开税率状态" min-width="160px" show-overflow-tooltip>
+        <template #="{ row }">
+          <ElTag size="small" :type="row.cat_diff == '2' ? 'danger' : 'success'">{{ row.tax_diff == '2' ? '不一致' : '一致' }}</ElTag>
+        </template>
+      </ElTableColumn>
+    </ElTable>
+
+    <ElForm ref="formRef" :model="formData" :rules="rules" class="mt-[10px]" label-width="80px" style="width:400px">
+      <ElFormItem label="审核结果" prop="status">
+        <ElSelect v-model="formData.status" style="width:100%" placeholder="审核结果">
+          <ElOption :value="successCode" label="通过" />
+          <ElOption :value="rejectCode" label="驳回" />
+        </ElSelect>
+      </ElFormItem>
+
+      <ElFormItem label="备注" prop="remark">
+        <ElInput v-model="formData.remark" placeholder="备注" type="textarea" />
+      </ElFormItem>
+
+      <ElFormItem>
+        <div style="width:100%;display:flex;justify-content: flex-end;">
+          <ElButton type="primary" @click="onSubmit">保存</ElButton>
+        </div>
+      </ElFormItem>
+    </ElForm>
+  </div>
+</template>

+ 2 - 0
src/plugins/globalComponent/index.ts

@@ -3,6 +3,7 @@ import { BasicForm } from "/@/components/BasicForm";
 import { PageAuth } from "/@/components/PageAuth";
 import { PageContainer } from "/@/components/PageContainer";
 import OrderRelation from "/@/components/OrderRelation";
+import OrderRelationApproval from "/@/components/OrderRelationApproval";
 
 
 export function setupPageComponent(app: App) {
@@ -16,4 +17,5 @@ export function setupPageComponent(app: App) {
   app.component("PageAuth", PageAuth);
 
   app.component("OrderRelation", OrderRelation);
+  app.component("OrderRelationApproval", OrderRelationApproval);
 }

+ 4 - 1
src/utils/details/inv-open.ts

@@ -39,12 +39,15 @@ export const INV_OPEN_STATUS = [
   { value: "1", label: "待财务审核", type: "warning" },
   { value: "2", label: "待上传发票", type: "warning" },
   { value: "3", label: "开票验票中", type: "warning" },
+  { value: "10", label: "验票成功,待关联订单", type: "warning" },
+  { value: "11", label: "待财务审批关联信息", type: "warning" },
   { value: "4", label: "开票完成", type: "warning" },
   { value: "5", label: "开票异常 ", type: "warning" },
   { value: "6", label: "已退票或已作废", type: "warning" },
   { value: "7", label: "已取消申请", type: "warning" },
   { value: "8", label: "财务驳回", type: "warning" },
-  { value: "9", label: "验票失败", type: "warning" }
+  { value: "9", label: "验票失败", type: "warning" },
+  { value: "9", label: "发票关联订单财务驳回", type: "warning" }
 ];
 
 export const INV_OPEN_COLUMNS: DescriptionColumns = [

+ 4 - 1
src/utils/status.ts

@@ -279,12 +279,15 @@ export const invoiceApplyStatusOptions = [
   { value: "1", label: "待财务审核", type: "warning" },
   { value: "2", label: "待上传发票", type: "warning" },
   { value: "3", label: "开票验票中", type: "warning" },
+  { value: "10", label: "验票成功,待关联订单", type: "warning" },
+  { value: "11", label: "待财务审批关联信息", type: "warning" },
   { value: "4", label: "开票完成", type: "warning" },
   { value: "5", label: "开票异常 ", type: "warning" },
   { value: "6", label: "已退票或已作废", type: "warning" },
   { value: "7", label: "已取消申请", type: "warning" },
   { value: "8", label: "财务驳回", type: "warning" },
-  { value: "9", label: "验票失败", type: "warning" }
+  { value: "9", label: "验票失败", type: "warning" },
+  { value: "9", label: "发票关联订单财务驳回", type: "warning" }
 ];
 
 // 资金认领状态

+ 36 - 15
src/views/InvoiceSales/invoiceApply/detail.vue

@@ -36,7 +36,7 @@ const { hasPermissionWithCode } = usePermission(PageName);
 const isSupport = shallowRef(false);
 const examCode = shallowRef("");
 const activeName = computed(() => (isCreate.value ? "0" : "1"));
-const collapseItem = ref(["0", "1", "2", "3", "4"]);
+const collapseItem = ref(["0", "1", "2", "3", "4", '10', '11']);
 
 const id = computed(() => query.id);
 const isCreate = computed(() => !id.value);
@@ -113,13 +113,13 @@ const currentProcess = computed(() => {
 //设置状态/物流
 async function handleChangeStatus({ status, ...otherParmas }) {
   let response: any;
-  if (!status) {
-    //设置物流
+  
+  if (!status) { //设置物流
     response = await httpSetPost({ invNo: id.value, ...otherParmas });
-  } else {
-    //设置状态
-    response = await httpStatus({ invNo: id.value, status, ...otherParams });
+  } else {  //设置状态
+    response = await httpStatus({ invNo: id.value, status, ...otherParmas });
   }
+
   const { code, message } = response;
   responseHandle({
     code,
@@ -128,6 +128,18 @@ async function handleChangeStatus({ status, ...otherParmas }) {
   });
 }
 
+async function onStatusChange(parameter) {
+  let response: any;
+  response = await httpStatus({ invNo: id.value, ...parameter });
+
+  const { code, message } = response;
+  responseHandle({
+    code,
+    message,
+    handler: () => requestInvoiceDetail()
+  });
+}
+
 const requestList = () => {
   listRun(httpList({ invNo: id.value }));
 };
@@ -154,7 +166,6 @@ onMounted(() => {
           <ElRadio label="通用订单" />
         </ElRadioGroup>
 
-
         <AddEditForm v-if="isOtherOrder" />
         <CurrentcyFormWanyu v-else-if="isWanyu" />
         <CurrentcyForm v-else  />
@@ -169,12 +180,22 @@ onMounted(() => {
             <InvoiceDetailVue v-loading="loading" :detail="invoiceDetail" />
           </el-collapse-item>
 
-          <ElCollapseItem
-            v-if="list.length > 0 && list[0].inv_number"
-            title="待发票与订单关联"
-            name="8"
-          >
-              <OrderRelation mode="sale" :invNumber="list[0].inv_number" :code="invoiceDetail.invNo" />
+          <ElCollapseItem title="待发票与订单关联" name="10" v-if="invoiceDetail.status == '10'">
+            <OrderRelation 
+              mode="sale" 
+              :code="invoiceDetail.invNo"  
+              :invNo="invoiceDetail.invNo"
+              @refresh="requestInvoiceDetail" 
+            />
+          </ElCollapseItem>
+
+          <ElCollapseItem title="待财务审批关联信息" name="11" v-if="invoiceDetail.status == '11'">
+              <OrderRelationApproval 
+                rejectCode="12" 
+                successCode="4" 
+                :code="invoiceDetail.invNo" 
+                @submit="onStatusChange"
+              />
           </ElCollapseItem>
 
           <el-collapse-item
@@ -185,7 +206,7 @@ onMounted(() => {
             <Invoice :inv-number="list[0].inv_number" type="sale" />
           </el-collapse-item>
 
-          <!-- <template v-if="!isSuperUser"> -->
+          <template v-if="!isSuperUser">
             <el-collapse-item
               name="4"
               :title="currentProcess.title"
@@ -201,7 +222,7 @@ onMounted(() => {
                 @change-status="handleChangeStatus"
               />
             </el-collapse-item>
-          <!-- </template> -->
+          </template>
         </el-collapse>
       </el-tab-pane>
     </el-tabs>

+ 1 - 1
src/views/InvoiceSales/invoiceApply/index.vue

@@ -140,7 +140,7 @@ function onDownloadTemplate() {
         >
       </template>
 
-      <template #content_action="{ status, post_code, invNo, inv_type,inv_number }">
+      <template #content_action="{ status, post_code, invNo, inv_type, inv_number }">
         <ElTooltip
           content="填写物流"
           placement="top"

+ 24 - 21
src/views/purchase/ticketReturn/components/excel-files-upload-relation/columns-config.ts

@@ -2,6 +2,7 @@ const initheaders = [
   "发票明细ID",
   "对账回票编码",
   "对账编码",
+  "采购单编号",
   "发票号码",
   "发票类型",
   "开票日期",
@@ -9,27 +10,28 @@ const initheaders = [
   "买入方公司名称",
   "货物或应税劳务、服务名称",
   "货物或应税劳务编号",
-  "发票明细商品数量",
   "发票明细税后金额",
-  "采购单编号",
+  "商品数量",
+  "商品单价",
   "采购单关联金额"
 ];
 
 export const mapProp = {
-  value0: "id",
+  value0: "itemId",
   value1: "hpNo",
   value2: "payNo",
-  value3: "inv_number",
-  value4: "inv_type",
-  value5: "open_date",
-  value6: "companyNo",
-  value7: "companyName",
-  value8: "cat_name",
-  value9: "cat_code",
-  value10: "good_num",
-  value11: "amount",
-  value12: "cgdNo",
-  value13: "relationAmount",
+  value3: "code",
+  value4: "inv_number",
+  value5: "inv_type",
+  value6: "open_date",
+  value7: "companyNo",
+  value8: "companyName",
+  value9: "cat_name",
+  value10: "cat_code",
+  value11: "beforeTax",
+  value12: "num",
+  value13: "good_price",
+  value14: "total_amount"
 };
 
 
@@ -39,18 +41,19 @@ export const mapWidth = {
   value2: "160px",
   value3: "160px",
   value4: "160px",
-  value5: "120px",
-  value6: "140px",
+  value5: "160px",
+  value6: "120px",
   value7: "140px",
-  value8: "220px",
-  value9: "140px",
-  value10: "160px",
+  value8: "140px",
+  value9: "220px",
+  value10: "140px",
   value11: "160px",
   value12: "160px",
-  value13: "140px",
+  value13: "160px",
+  value14: "140px",
 };
 
-export const requireHeaders = ["id", "hpNo", "payNo", "inv_number","open_date","companyNo", "cat_code","good_num","amount","cgdNo", "relationAmount"];
+export const requireHeaders = ["itemId", "code", "num", "good_price","total_amount", "companyNo"];
 
 const columns = () => {
   const list: any[] = [{ type: "index", width: "50", fixed: "left", label: "序号" }];

+ 15 - 9
src/views/purchase/ticketReturn/components/excel-files-upload-relation/index.vue

@@ -2,10 +2,13 @@
 import { ref } from "vue";
 import { ElMessage } from "element-plus";
 import { execlUpload } from "/@/components/execlUpload";
-import { httpBatchimport } from "/@/api/purchase/ticketReturn";
+import { httpInvoiceBatch } from "/@/api/purchase/ticketReturn";
 import { useResponseHandle } from "/@/hooks";
 import { useCompany } from "/@/hooks/core/useCompany";
 
+import { division } from "/@/utils/calc";
+
+
 import {
   initheaders,
   columns,
@@ -79,7 +82,7 @@ const handleSubmit = async () => {
 
   tableData.value.forEach((key, index) => {
     const obj: Record<string, string> = {};
-
+    
     for (let i in key) {
       const prop = mapProp[i];
       const value = key[i];
@@ -94,6 +97,7 @@ const handleSubmit = async () => {
         obj[prop] = value;
       }
     }
+
     data.push(obj);
   });
 
@@ -126,16 +130,18 @@ const handleSubmit = async () => {
     return;
   }
 
-  data.forEach(item => {
-    delete item["payNo"];
-    delete item["companyNo"];
-  });
 
-  const { code, message } = await httpBatchimport({
-    list: data
+  loading.value = false;
+
+
+  let list = []
+  data.forEach(item => {
+    const { itemId, code, num, total_amount } = item
+    const good_price = Number(division(total_amount, num)).toFixed(2)
+    list.push({ itemId, code, num, good_price , total_amount, remark: '' })
   });
 
-  loading.value = false;
+  const { code, message } = await httpInvoiceBatch({ order_type: '2', list });
 
   responseHandle({
     code,

+ 20 - 2
src/views/purchase/ticketReturn/config/xls-template.ts

@@ -11,6 +11,7 @@ export const relationTemplate = {
   发票明细ID: '1',
   对账回票编码: 'hp2312221654022669',
   对账编码: 'PAY2312251007285234',
+  采购单编号: '',
   发票号码: '24332000000199944864',
   发票类型: '电子发票(增值税专用发票)',
   开票日期: '2024-06-26',
@@ -18,8 +19,25 @@ export const relationTemplate = {
   买入方公司名称: '北京万宇恒通国际科贸有限公司',
   '货物或应税劳务、服务名称': '*家用音视频设备*sanag塞那挂耳式蓝牙耳机',
   货物或应税劳务编号: 'XXXXXXXX',
-  发票明细商品数量: 'XXXXXXXX',
   发票明细税后金额: '339',
-  采购单编号: '',
+  商品数量: "",
+  商品单价: "",
   采购单关联金额: '',
 }
+
+
+// "发票明细ID",
+// "对账回票编码",
+// "对账编码",
+// "采购单编号",
+// "发票号码",
+// "发票类型",
+// "开票日期",
+// "买入方公司编码",
+// "买入方公司名称",
+// "货物或应税劳务、服务名称",
+// "货物或应税劳务编号",
+// "发票明细税后金额",
+// "商品数量",
+// "商品单价",
+// "采购单关联金额"

+ 6 - 50
src/views/purchase/ticketReturn/detail.vue

@@ -13,19 +13,12 @@ import { useUserInfo } from "/@/hooks/core/useUser";
 import { usePermission } from "/@/hooks/core/usePermission";
 import { ticketReturnColumns } from "/@/utils/details/_purchase";
 import OrderRelation from "/@/components/OrderRelation/src/index.vue";
-import { ElForm } from "element-plus" 
 
 
 const pageName = "ticketReturnDetail";
 const { hasPermissionWithCode } = usePermission(pageName);
 
-const approvalData = ref({ status: '', remark: '' })
-const approvalFormRef = ref<InstanceType<typeof ElForm> | null>(null)
-
-const rules = computed(() => ({
-  status: [{ required: true, message: '请选择状态', trigger: 'change' }],
-  remark: [{ required: true, message: '请输入备注', trigger: 'change' }],
-}))
+// const approvalData = ref({ status: '', remark: '' })
 
 const { push } = useRouter();
 const formRef = ref<InstanceType<typeof ReconciliationForm> | null>(null);
@@ -44,7 +37,7 @@ const { run: create } = useAsync({
   success: () => push("/purchase/ticketReturn")
 });
 
-const { run: approval } = useAsync({
+const { run: approval, loading: approvalLoading } = useAsync({
   success: () => refresh()
 });
 
@@ -53,14 +46,6 @@ function refresh() {
   formRef.value && formRef.value.refresh();
 }
 
-async function onApproval(){
-  try{
-    await approvalFormRef.value.validate()
-  }catch(err){
-    console.log(err)
-  }
-}
-
 const requestDetail = () => detail(httpDetail({ hpNo: id.value }));
 const handleCreate = data => create(httpAdd(data));
 
@@ -99,41 +84,12 @@ if (isDetail.value) requestDetail();
 
             <!-- 审批节点 -->
             <template v-if="!isSuperUser">
-              <ElCollapseItem title="待发票与订单关联" name="8" v-if="data.status == '11'">
-                <OrderRelation  :invNumber="data.invoiceNumber" :code="data.hpNo" :payNo="data.payNo" />
+              <ElCollapseItem title="待发票与订单关联" name="8" v-if="data && data.status == '11'">
+                <OrderRelation :code="data.hpNo" :payNo="data.payNo" @refresh="requestDetail" />
               </ElCollapseItem>
 
-              <ElCollapseItem title="待财务审批关联信息" name="9" v-if="data.status == '12'">
-                <ElTable border size="small">
-                  <ElTableColumn width="80px" label="序号" />
-                  <ElTableColumn label="订单编号" min-width="160px" show-overflow-tooltip />
-                  <ElTableColumn label="商品名称" min-width="160px" show-overflow-tooltip />
-                  <ElTableColumn label="预计类目编号" min-width="140px" show-overflow-tooltip />
-                  <ElTableColumn label="实开类目编号" min-width="140px" show-overflow-tooltip />
-                  <ElTableColumn label="实开类目编号状态" min-width="160px" show-overflow-tooltip />
-                  <ElTableColumn label="预计类目税率" min-width="120px" show-overflow-tooltip />
-                  <ElTableColumn label="实开类目税率" min-width="120px" show-overflow-tooltip />
-                  <ElTableColumn label="预计与实开税率状态" min-width="160px" show-overflow-tooltip />
-                </ElTable>
-
-                <ElForm ref="approvalFormRef" :model="approvalData" :rules="rules" class="mt-[10px]" label-width="80px" style="width:400px">
-                  <ElFormItem label="审核结果" prop="status">
-                    <ElSelect v-model="approvalData.status" style="width:100%" placeholder="审核结果">
-                      <ElOption value="1" label="通过" />
-                      <ElOption value="0" label="驳回" />
-                    </ElSelect>
-                  </ElFormItem>
-
-                  <ElFormItem label="备注" prop="remark">
-                    <ElInput v-model="approvalData.remark" placeholder="备注" type="textarea" />
-                  </ElFormItem>
-
-                  <ElFormItem>
-                    <div style="width:100%;display:flex;justify-content: flex-end;">
-                      <ElButton type="primary" @click="onApproval">保存</ElButton>
-                    </div>
-                  </ElFormItem>
-                </ElForm>
+              <ElCollapseItem title="待财务审批关联信息" name="9" v-if="data.status == '12'" v-loading="approvalLoading">
+                <OrderRelationApproval :rejectCode="13" :successCode="2" :code="data.hpNo" @submit="handleApproval" />
               </ElCollapseItem>
 
               <ElCollapseItem

+ 1 - 2
src/views/purchase/ticketReturn/index.vue

@@ -19,7 +19,6 @@ import { useUserInfo } from "/@/hooks/core/useUser";
 import ExcelUploadInv from "./components/execl-files-upload-inv/index.vue";
 import ExcelUploadRelation from "./components/excel-files-upload-relation/index.vue"
 
-
 const PageName = "ticketReturn";
 const baseUrl = "/purchase/ticketReturnDetail";
 const invStatus = ['2','3',"4", '6','7', "10"];
@@ -188,6 +187,6 @@ function onDownloadRelationTemplate() {
     <ExcelUpload ref="excelUploadRef" />
 
     <ExcelUploadInv ref="excelUploadInvRef"  @on-success="() => (pageContentRef as any).onSearch()" />
-    <ExcelUploadRelation ref="excelUploadRelationRef" />
+    <ExcelUploadRelation ref="excelUploadRelationRef" @on-success="() => (pageContentRef as any).onSearch()" />
   </PageAuth>
 </template>