1
0

19 Коммитууд 06ed194b3c ... fbda5d7e5a

Эзэн SHA1 Мессеж Огноо
  tzx fbda5d7e5a Merge branch 'dev_03' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-eom into dev 3 өдөр өмнө
  xieyong 910f027f7e feat: 更新应收金额计算逻辑,使用勾选明细的折让合计,并回填已收/未收金额 3 өдөр өмнө
  xieyong 56c973c039 feat: 添加收款专用接口以获取应收单产品列表,并更新相关组件逻辑 3 өдөр өмнө
  xieyong 9b9392fac5 fix: 修正单据金额计算逻辑,优先使用已收总价 3 өдөр өмнө
  xieyong eb2d039ef0 feat: 添加分期付款支持,优化结算月份和收款日期的显示逻辑 3 өдөр өмнө
  xieyong da34b59f44 feat: 优化金额计算逻辑,添加有效金额选择和汇总功能 3 өдөр өмнө
  xieyong ed5503b451 feat: 添加发票管理来源类型,更新相关字段和格式化逻辑 6 өдөр өмнө
  xieyong 7063582642 fix: 移除冗余的订单编码和合同信息字段,优化代码结构 6 өдөр өмнө
  xieyong 3f8e922cd3 fix: 根据查询维度动态设置子订单号字段属性 6 өдөр өмнө
  xieyong 90b74cdd51 fix: 移除冗余的应收总金额计算逻辑,直接使用数据表单中的值 6 өдөр өмнө
  xieyong dc5d7f24ac feat: 优化采购对账单详情弹窗,添加应付信息和对账明细展示逻辑 6 өдөр өмнө
  xieyong 0a6ef0715e fix: 修改应收金额字段名称及计算逻辑 6 өдөр өмнө
  xieyong c4621a5dc4 feat: 在付款弹窗中添加选中行数据的处理逻辑 6 өдөр өмнө
  xieyong 71004010e9 feat:添加采购订单中对账单开收票单据逻辑 6 өдөр өмнө
  xieyong ffb3a2bf50 Merge branch 'feat_sale' into dev_03 1 долоо хоног өмнө
  xieyong a8f95fc64f fix: 更新应付明细表格字段名称和布局 1 долоо хоног өмнө
  xieyong 39167445d3 fix: 修改付款条件和付款计划相关字段名称 1 долоо хоног өмнө
  xieyong e2f19a18a1 fix: 添加 .history 到 .gitignore 1 долоо хоног өмнө
  liujt 074aa80fac feat: 采购对账单 1 долоо хоног өмнө
22 өөрчлөгдсөн 629 нэмэгдсэн , 332 устгасан
  1. 1 1
      .gitignore
  2. 54 21
      src/BIZComponents/inventoryTableDetails.vue
  3. 11 0
      src/BIZComponents/paymentCollectionPlan/Index.vue
  4. 9 0
      src/api/financialManage/receivableManage/index.js
  5. 11 0
      src/enum/dict.js
  6. 2 2
      src/views/financialManage/invoiceManage/components/accountstatementDialog.vue
  7. 4 4
      src/views/financialManage/invoiceManage/components/addOrEditDialogNew.vue
  8. 22 1
      src/views/financialManage/invoiceManage/index.vue
  9. 32 32
      src/views/financialManage/payableManage/index.vue
  10. 1 0
      src/views/financialManage/prepayment/components/payDialog.vue
  11. 41 20
      src/views/financialManage/receivableManage/components/collectionDialog.vue
  12. 32 32
      src/views/financialManage/receivableManage/index.vue
  13. 32 32
      src/views/financialManage/receivedManaged/index.vue
  14. 68 39
      src/views/purchasingManage/purchaseOrder/accountstatement/components/addAccountDialog.vue
  15. 52 48
      src/views/purchasingManage/purchaseOrder/accountstatement/components/detailDialog.vue
  16. 117 37
      src/views/purchasingManage/purchaseOrder/accountstatement/components/payablesInfo.vue
  17. 13 11
      src/views/purchasingManage/purchaseOrder/accountstatement/index.vue
  18. 28 25
      src/views/purchasingManage/purchaseOrder/components/addDialogNew.vue
  19. 2 1
      src/views/saleManage/saleOrder/accountstatement/components/accountDetailTable.vue
  20. 18 19
      src/views/saleManage/saleOrder/accountstatement/components/receivableInfo.vue
  21. 54 5
      src/views/saleManage/saleOrder/components/addDialogNew.vue
  22. 25 2
      src/views/saleManage/saleOrder/components/darwerComponents/saleOrderInfo.vue

+ 1 - 1
.gitignore

@@ -12,7 +12,7 @@ yarn-debug.log*
 yarn-error.log*
 .pnpm-debug.log
 .eslintcache
-
+.history
 # Editor directories and files
 .idea
 .vscode

+ 54 - 21
src/BIZComponents/inventoryTableDetails.vue

@@ -114,7 +114,9 @@
       <template v-slot:toolbar>
         <div class="headbox">
           <div class="pricebox">
-            <span class="amount" v-if="showSummary">数量合计:{{ allQuantity }}</span>
+            <span class="amount" v-if="showSummary"
+              >数量合计:{{ allQuantity }}</span
+            >
             <span class="amount" v-if="isAllPrice">总计:{{ allPrice }}元</span>
             <span class="amount" v-if="isDiscountTotalPrice"
               >优惠后总金额:{{ form.discountTotalPrice }}元</span
@@ -139,7 +141,12 @@
     matchInventoryTotal
   } from '@/api/wms';
   import { getSummaries } from '@/utils/util.js';
-  import { getAllQuantity } from '@/BIZComponents/setProduct.js';
+  import {
+    getAllQuantity,
+    getAllPrice,
+    getAllDiscountPrice,
+    formatPrice
+  } from '@/BIZComponents/setProduct.js';
 
   const dayjs = require('dayjs');
 
@@ -185,7 +192,10 @@
         type: Boolean,
         default: false
       },
-      cacheKeyUrl: '',
+      cacheKeyUrl: {
+        type: String,
+        default: ''
+      },
       //是否显示订单编码
       isOrderNo: {
         type: Boolean,
@@ -552,7 +562,7 @@
             prop: 'warehouseName',
             label: '仓库名称',
             slot: 'warehouseName',
-            align: 'center',
+            align: 'center'
           },
           {
             minWidth: 160,
@@ -567,7 +577,7 @@
             prop: 'availableCountBase',
             label: this.isWms ? '可用数量' : '库存数量',
             showOverflowTooltip: true,
-            align: 'center',
+            align: 'center'
           },
           {
             minWidth: 140,
@@ -679,8 +689,10 @@
             align: 'center',
             isNone: !this.isDiscount,
             formatter: (_row, _column, cellValue) => {
-              return this.quoteTypeOp.find((item) => item.value == _row.quoteWay)
-                ?.label || '';
+              return (
+                this.quoteTypeOp.find((item) => item.value == _row.quoteWay)
+                  ?.label || ''
+              );
             }
           },
           {
@@ -982,11 +994,7 @@
     },
     methods: {
       getSummaries(param) {
-        return getSummaries(
-          param,
-          ['saleCount'],
-          ' '
-        );
+        return getSummaries(param, ['saleCount'], ' ');
       },
       handleDone() {
         if (this.isSelected) {
@@ -1033,6 +1041,39 @@
       handleMethod(row) {
         this.$refs.timeDialogDialogRef.open(row);
       },
+      /**
+       * 取第一个有效金额,全部无效时回退到 fallback。
+       * 注意不能直接用 ||,否则接口正常返回的 0 会被当成无效值跳过。
+       */
+      pickAmount(candidates, fallback) {
+        const hit = candidates.find(
+          (v) => v !== null && v !== undefined && v !== '' && !isNaN(Number(v))
+        );
+        const num = Number(hit === undefined ? fallback : hit);
+        return isNaN(num) ? 0 : formatPrice(num);
+      },
+      // 汇总:总计 / 数量合计 / 优惠后总金额
+      setAmount(data = {}) {
+        this.allQuantity =
+          getAllQuantity(this.form.datasource, this.countObj) || 0;
+        // 总计:优先用接口返回的总金额,接口未返回时按明细行合计兜底
+        this.allPrice = this.pickAmount(
+          [data.totalAmount, data.totalPrice, data?.contractVO?.totalPrice],
+          getAllPrice(this.form.datasource)
+        );
+        if (this.isDiscountTotalPrice) {
+          // 优惠后总金额:接口未返回时按明细行折让合计兜底,无折让时等于总计
+          this.form.discountTotalPrice = this.pickAmount(
+            [
+              data.payAmount,
+              data.discountTotalPrice,
+              data?.contractVO?.discountTotalPrice
+            ],
+            Number(getAllDiscountPrice(this.form.datasource)) ||
+              Number(this.allPrice)
+          );
+        }
+      },
       setDeliveryDays() {
         console.log(this.form.datasource, 'this.form.datasource');
         this.form.datasource.forEach((item, i) => {
@@ -1090,15 +1131,7 @@
           });
 
           this.form.datasource = productList;
-          this.allPrice =
-            data.totalAmount || data.totalPrice || data?.contractVO?.totalPrice;
-          this.allQuantity = getAllQuantity(this.form.datasource, this.countObj)  
-          if (this.isDiscountTotalPrice) {
-            this.form.discountTotalPrice =
-              data.payAmount ||
-              data.discountTotalPrice ||
-              data?.contractVO?.discountTotalPrice;
-          }
+          this.setAmount(data);
           if (this.isWms) {
             let codeList = this.form.datasource
               .filter((item) => item.productCode)

+ 11 - 0
src/BIZComponents/paymentCollectionPlan/Index.vue

@@ -728,6 +728,17 @@
           console.log('forceUpdate called');
         });
       },
+      // 仅回填「计划收款/付款日期」,不动其它已填字段(比例/款项名称/金额/说明)
+      // 超出日期数组长度的行保持原值,避免覆盖用户手工填写的日期
+      setDeadLineList(dateRange) {
+        if (!dateRange || !dateRange.length) return;
+        if (!this.form.datasource || !this.form.datasource.length) return;
+        this.form.datasource.forEach((item, index) => {
+          if (index < dateRange.length) {
+            this.$set(item, 'deadLine', dateRange[index]);
+          }
+        });
+      },
       // 添加
       handlAdd() {
         let item = JSON.parse(JSON.stringify(this.defaultForm));

+ 9 - 0
src/api/financialManage/receivableManage/index.js

@@ -49,6 +49,15 @@ export async function getFinReceivableInfoAPI(id) {
   return Promise.reject(new Error(res.data.message));
 }
 
+// 收款专用:获取应收单产品列表
+export async function getProductListForReceiptAPI(receivableId) {
+  const res = await request.get(`/eom/finreceivable/getProductListForReceipt/${receivableId}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
 // 删除收款记录
 export async function finReceivableRemoveAPI(data) {
   const res = await request.delete('/eom/finreceivable/deleteDetail', {data});

+ 11 - 0
src/enum/dict.js

@@ -757,3 +757,14 @@ export const dimensionType = [
   { code: 2, label: '批次维度' },
   { code: 3, label: '包装维度' }
 ];
+
+// 发票管理 来源类型(与后端 FinInvoiceSourceTypeEnum 对齐)
+// 1对账单 2合同 3订单 4应付 5应收 99其他无订单无合同
+export const finInvoiceSourceTypeOp = [
+  { value: 1, label: '对账单' },
+  { value: 2, label: '合同' },
+  { value: 3, label: '订单' },
+  { value: 4, label: '应付' },
+  { value: 5, label: '应收' },
+  { value: 99, label: '其他无订单无合同' }
+];

+ 2 - 2
src/views/financialManage/invoiceManage/components/accountstatementDialog.vue

@@ -65,7 +65,7 @@
         }
       },
       type: {
-        type: String,
+        type: Number,
         default: 1
       },
       accountstatementDialogFlag: {
@@ -206,7 +206,7 @@
           size: limit,
           ...where,
           reviewStatus: 2,
-          type: this.type
+          type: String(this.type)
         });
       },
 

+ 4 - 4
src/views/financialManage/invoiceManage/components/addOrEditDialogNew.vue

@@ -29,8 +29,8 @@
               :disabled="!isEditType"
               style="width: 100%"
             >
-              <el-option label="开票" value="1"></el-option>
-              <el-option label="收票" value="2"></el-option>
+              <el-option label="开票" :value="1"></el-option>
+              <el-option label="收票" :value="2"></el-option>
             </el-select>
           </el-form-item>
         </el-col>
@@ -1029,8 +1029,8 @@
       //订单、合同列表
       async createInvoice1(data, type, sourceType) {
         console.log('createInvoice1~~~', data);
-        
-        this.$set(this.form, 'type', type);
+
+        this.$set(this.form, 'type', Number(type));
         this.$set(this.form, 'sourceType', sourceType);
         // this.$set(this.form, 'sourceCode', tempIds);
 

+ 22 - 1
src/views/financialManage/invoiceManage/index.vue

@@ -147,7 +147,7 @@
     invoiceApplyRemoveAPI,
     invoiceApplySubmit
   } from '@/api/financialManage/invoiceManage';
-  import { reviewStatus } from '@/enum/dict';
+  import { reviewStatus, finInvoiceSourceTypeOp } from '@/enum/dict';
   import processSubmitDialog from '@/BIZComponents/processSubmitDialog/processSubmitDialog.vue';
   import tabMixins from '@/mixins/tableColumnsMixin';
   import addOrEditDialogNew from '@/views/financialManage/invoiceManage/components/addOrEditDialogNew.vue'
@@ -219,6 +219,27 @@
             align: 'center',
             showOverflowTooltip: true
           },
+          {
+            minWidth: 120,
+            prop: 'sourceCode',
+            label: '来源单据号',
+            slot: 'sourceCode',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 120,
+            prop: 'sourceType',
+            label: '来源类型',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (_row, _column, cellValue) => {
+              return (
+                finInvoiceSourceTypeOp.find((item) => item.value == cellValue)
+                  ?.label || ''
+              );
+            }
+          },
           {
             minWidth: 140,
             prop: 'applyDeptName',

+ 32 - 32
src/views/financialManage/payableManage/index.vue

@@ -219,38 +219,38 @@
             slot: 'receiptPlanOrderNo',
             showOverflowTooltip: true
           },
-          {
-            minWidth: 160,
-            prop: 'saleOrderNo',
-            label: '订单编码',
-            align: 'center',
-            slot: 'saleOrderNo',
-            showOverflowTooltip: true
-          },
-          {
-            minWidth: 150,
-            prop: 'contractCode',
-            label: '合同编码',
-            align: 'center',
-            slot: 'contractCode',
-            showOverflowTooltip: true
-          },
-          {
-            minWidth: 150,
-            prop: 'contractNo',
-            label: '合同编号',
-            align: 'center',
-            slot: 'contractNo',
-            showOverflowTooltip: true
-          },
-          {
-            minWidth: 150,
-            prop: 'contractName',
-            label: '合同名称',
-            align: 'center',
-            slot: 'contractName',
-            showOverflowTooltip: true
-          },
+          // {
+          //   minWidth: 160,
+          //   prop: 'saleOrderNo',
+          //   label: '订单编码',
+          //   align: 'center',
+          //   slot: 'saleOrderNo',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 150,
+          //   prop: 'contractCode',
+          //   label: '合同编码',
+          //   align: 'center',
+          //   slot: 'contractCode',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 150,
+          //   prop: 'contractNo',
+          //   label: '合同编号',
+          //   align: 'center',
+          //   slot: 'contractNo',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 150,
+          //   prop: 'contractName',
+          //   label: '合同名称',
+          //   align: 'center',
+          //   slot: 'contractName',
+          //   showOverflowTooltip: true
+          // },
           {
             minWidth: 150,
             prop: 'invoiceCode',

+ 1 - 0
src/views/financialManage/prepayment/components/payDialog.vue

@@ -211,6 +211,7 @@
     methods: {
       async open(row) {
         this.visible = true;
+        this.row = row;
         this.info = await getPrepaymentInfo(row.id);
         this.form.tableData = this.info.detailList || [];
       },

+ 41 - 20
src/views/financialManage/receivableManage/components/collectionDialog.vue

@@ -12,7 +12,7 @@
     :resizable="true"
   >
     <div style="margin: 10px 0; font-size: 14px; color: #606266;">
-      <span>应收金额:{{ row.receivableTotalPrice || 0 }} 元</span>
+      <span>应收金额:{{ selectedReceivableAmount }} 元</span>
       <span style="margin-left: 20px;">已收金额:{{ receivedAmount }} 元</span>
       <span style="margin-left: 20px;">未收金额:{{ unreceivedAmount }} 元</span>
     </div>
@@ -113,7 +113,7 @@
 </template>
 <script>
 import { pricingWayList } from '@/enum/dict.js';
-import { finReceivableSaveAPI, getFinReceivableInfoAPI } from "@/api/financialManage/receivableManage";
+import { finReceivableSaveAPI, getProductListForReceiptAPI } from "@/api/financialManage/receivableManage";
 
 export default {
   name: "collectionDialog",
@@ -138,19 +138,21 @@ export default {
     isView() {
       return this.dialogType === 'view';
     },
-    // 已收金额 = 勾选的应收明细「本次对账金额」之和
-    receivedAmount() {
+    // 应收金额 = 勾选的应收明细「折让合计」之和
+    selectedReceivableAmount() {
       const sum = this.selection.reduce((pre, item) => {
         const val = parseFloat(item.statementAmount);
         return pre + (isNaN(val) ? 0 : val);
       }, 0);
       return sum.toFixed(2);
     },
-    // 未收金额 = 应收金额 - 已收金额
+    // 已收金额 = 接口下发的 row.receivedTotalPrice
+    receivedAmount() {
+      return this.row.receivedTotalPrice || 0;
+    },
+    // 未收金额 = 接口下发的 row.unreceiveTotalPrice
     unreceivedAmount() {
-      const total = parseFloat(this.row.receivableTotalPrice) || 0;
-      const received = parseFloat(this.receivedAmount) || 0;
-      return (total - received).toFixed(2);
+      return this.row.unreceiveTotalPrice || 0;
     },
     queryDimension() {
       return this.form.queryDimension != null ? this.form.queryDimension : 1;
@@ -392,18 +394,25 @@ export default {
       this.title = this.dialogType === 'view' ? '收款详情' : '收款';
       await this.getInfo(row.id);
     },
-    // 获取详情
+    // 获取详情(收款专用接口:仅返回产品列表,不带表单主信息)
     async getInfo(id) {
-      const data = await getFinReceivableInfoAPI(id);
-      this.datasource = data.productList || [];
+      const data = await getProductListForReceiptAPI(id);
+      // 新接口只返回产品列表
+      this.datasource = Array.isArray(data) ? data : (data.productList || []);
+      // 把接口返回的已收/未收金额回填到 row,供顶部汇总和表单展示
+      this.row = {
+        ...this.row,
+        receivedTotalPrice: data?.receivedTotalPrice ?? this.row.receivedTotalPrice ?? 0,
+        unreceiveTotalPrice: data?.unreceiveTotalPrice ?? this.row.unreceiveTotalPrice ?? 0
+      };
       this.form = {
         ...this.form,
-        id: data.id || '',
-        queryDimension: data.queryDimension != null ? data.queryDimension : 1,
-        receivedDate: data.receivedDate || '',
-        paymentType: data.paymentType ?? '',
-        files: data.files || [],
-        remark: data.remark || ''
+        id: data?.id || '',
+        queryDimension: data?.queryDimension != null ? data.queryDimension : 1,
+        receivedDate: data?.receivedDate || '',
+        paymentType: data?.paymentType ?? '',
+        files: data?.files || [],
+        remark: data?.remark || ''
       };
     },
 
@@ -441,7 +450,7 @@ export default {
       this.$set(item, 'singlePrice', singlePrice);
       this.$set(item, 'taxRate', taxRate);
       this.$set(item, 'discountRatio', discountRatio);
-      this.$set(item, 'statementAmount', amount);
+      this.$set(item, 'statementAmount', item?.receivedTotalPrice || amount);
       this.$set(item, 'noTaxSinglePrice', noTaxSinglePrice);
       this.$set(item, 'totalPrice', totalPrice);
       this.$set(item, 'discountSinglePrice', discountSinglePrice);
@@ -510,12 +519,24 @@ export default {
 
       this.loading = true;
       // 3. 提交:收款信息 + 勾选的应收明细(已收金额 = 勾选行本次对账金额之和)
+      const statementAmount = this.selection.reduce(
+        (pre, item) => pre + (+item.statementAmount || 0),
+        0
+      );
+      // productList 里每一行需要补一个 receivedTotalPrice 字段(值取本次录入的 statementAmount)
+      const productList = this.selection.map((item) => ({
+        ...item,
+        receivedTotalPrice: +(item.statementAmount || 0)
+      }));
       const params = {
         ...this.form,
-        receivedTotalPrice: this.receivedAmount,
+        statementAmount,
+        receivableTotalPrice: Number(this.selectedReceivableAmount),  // 应收金额(勾选行折让合计之和)
+        receivedTotalPrice: this.row.receivedTotalPrice,      // 历史已收总额(接口下发)
+        unreceiveTotalPrice: this.row.unreceiveTotalPrice,    // 历史未收金额(接口下发)
         receivableId: this.row.id,
         receivableCode: this.row.code,
-        productList: selection
+        productList
       };
       finReceivableSaveAPI(params)
         .then(() => {

+ 32 - 32
src/views/financialManage/receivableManage/index.vue

@@ -242,38 +242,38 @@
             align: 'center',
             showOverflowTooltip: true
           },
-          {
-            minWidth: 160,
-            prop: 'saleOrderNo',
-            label: '订单编码',
-            align: 'center',
-            slot: 'saleOrderNo',
-            showOverflowTooltip: true
-          },
-          {
-            minWidth: 150,
-            prop: 'contractCode',
-            label: '合同编码',
-            align: 'center',
-            slot: 'contractCode',
-            showOverflowTooltip: true
-          },
-          {
-            minWidth: 150,
-            prop: 'contractNo',
-            label: '合同编号',
-            align: 'center',
-            slot: 'contractNo',
-            showOverflowTooltip: true
-          },
-          {
-            minWidth: 150,
-            prop: 'contractName',
-            label: '合同名称',
-            align: 'center',
-            slot: 'contractName',
-            showOverflowTooltip: true
-          },
+          // {
+          //   minWidth: 160,
+          //   prop: 'saleOrderNo',
+          //   label: '订单编码',
+          //   align: 'center',
+          //   slot: 'saleOrderNo',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 150,
+          //   prop: 'contractCode',
+          //   label: '合同编码',
+          //   align: 'center',
+          //   slot: 'contractCode',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 150,
+          //   prop: 'contractNo',
+          //   label: '合同编号',
+          //   align: 'center',
+          //   slot: 'contractNo',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 150,
+          //   prop: 'contractName',
+          //   label: '合同名称',
+          //   align: 'center',
+          //   slot: 'contractName',
+          //   showOverflowTooltip: true
+          // },
           {
             minWidth: 150,
             prop: 'invoiceCode',

+ 32 - 32
src/views/financialManage/receivedManaged/index.vue

@@ -234,38 +234,38 @@
           //   slot: 'receiptPlanOrderNo',
           //   showOverflowTooltip: true
           // },
-          {
-            minWidth: 160,
-            prop: 'saleOrderNo',
-            label: '订单编码',
-            align: 'center',
-            slot: 'saleOrderNo',
-            showOverflowTooltip: true
-          },
-          {
-            minWidth: 150,
-            prop: 'contractCode',
-            label: '合同编码',
-            align: 'center',
-            slot: 'contractCode',
-            showOverflowTooltip: true
-          },
-          {
-            minWidth: 150,
-            prop: 'contractNo',
-            label: '合同编号',
-            align: 'center',
-            slot: 'contractNo',
-            showOverflowTooltip: true
-          },
-          {
-            minWidth: 150,
-            prop: 'contractName',
-            label: '合同名称',
-            align: 'center',
-            slot: 'contractName',
-            showOverflowTooltip: true
-          },
+          // {
+          //   minWidth: 160,
+          //   prop: 'saleOrderNo',
+          //   label: '订单编码',
+          //   align: 'center',
+          //   slot: 'saleOrderNo',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 150,
+          //   prop: 'contractCode',
+          //   label: '合同编码',
+          //   align: 'center',
+          //   slot: 'contractCode',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 150,
+          //   prop: 'contractNo',
+          //   label: '合同编号',
+          //   align: 'center',
+          //   slot: 'contractNo',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 150,
+          //   prop: 'contractName',
+          //   label: '合同名称',
+          //   align: 'center',
+          //   slot: 'contractName',
+          //   showOverflowTooltip: true
+          // },
           {
             minWidth: 150,
             prop: 'invoiceCode',

+ 68 - 39
src/views/purchasingManage/purchaseOrder/accountstatement/components/addAccountDialog.vue

@@ -94,8 +94,10 @@
       return {
         businessId: '',
         fullscreen: false,
+        saveLoading: false,
         datasource: [],
         recorpayList: [],
+        statPayable: null,
         // 应付信息初始明细(查询/编辑回填),由 payablesInfo 本地维护,提交时取回
         payablesList: [],
         dataForm: {
@@ -156,17 +158,26 @@
       async getInfo(row) {
         let data = await accountstatementInfoAPI(row.id);
         // this.recorpayList = data.recorpayList || [];
-        data.orderTotalAmount = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.orderAmount * 100), 0) / 100;
-        data.amountTotalPrice = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.statementAmount * 100), 0) / 100;
-        data.amountCompletePrice = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.statementedAmount * 100), 0) / 100;
-        data.amountUnCompletePrice = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.unStatementAmount * 100), 0) / 100;
-        this.datasource = data.orderList || [];
-        // 编辑详情回填应付信息(兼容 payablesList / statPayable 两种字段)
+        // data.orderTotalAmount = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.orderAmount * 100), 0) / 100;
+        // data.amountTotalPrice = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.statementAmount * 100), 0) / 100;
+        // data.amountCompletePrice = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.statementedAmount * 100), 0) / 100;
+        // data.amountUnCompletePrice = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.unStatementAmount * 100), 0) / 100;
+        // this.datasource = data.orderList || [];
+        // // 编辑详情回填应付信息(兼容 payablesList / statPayable 两种字段)
+        
+        // this.dataForm = data;
+
+         this.datasource = data.productList || [];
+    
         this.payablesList =
-          data.payablesList ||
           (data.statPayable && data.statPayable.statPayableDetailList) ||
           [];
-        this.dataForm = data;
+        // 保存查询到的完整 statPayable 对象,作为提交入参
+        this.statPayable = data.statPayable || null;
+        this.dataForm = {
+          ...this.dataForm,
+          ...data,
+        };
         switch (this.dataForm.dateType) {
           case 1:
             this.$set(this.dataForm,'year',this.dataForm.dateValue)
@@ -210,9 +221,10 @@
         // this.recorpayList = data.recorpayList || [];
         this.datasource = data.productList || [];
         // 查询接口暂未返回预付信息时,先置空(由 payablesInfo 本地维护)
-        this.payablesList = data.payablesList ||
+        this.payablesList = 
           (data.statPayable && data.statPayable.statPayableDetailList) ||
           [];
+        this.statPayable = data.statPayable || null;
         this.dataForm = {
           ...this.dataForm,
           ...data
@@ -226,42 +238,59 @@
           // amountCompletePrice: data.reduce((pre, cur) => pre + Math.round(+cur.statementedAmount * 100), 0) / 100,
           // amountUnCompletePrice: data.reduce((pre, cur) => pre + Math.round(+cur.unStatementAmount * 100), 0) / 100
         };
+        
         // if (!this.datasource.length) this.$message.warning('暂无订单信息');
       },
       //保存
       async save(is) {
-        if (!this.datasource.length && !this.recorpayList.length && !this.payablesList.length)
-        return this.$message.warning('暂无对账信息');
+        if (!this.datasource.length)
+          return this.$message.warning('暂无对账信息');
 
-        let api =
-          this.dialogType == 'add'
-            ? createAccountStatementAPI
-            : accountstatementUpdateAPI;
-        // 提交时一次性取回应付信息(本地明细 + 汇总)
-        const payablesData = this.$refs.payablesInfoRef
-          ? this.$refs.payablesInfoRef.getSubmitData()
-          : { payablesList: [], statementAdvanceTotalPrice: 0, receivedTotalPrice: 0 };
-        let params = {
-          ...this.dataForm,
-          orderList: this.datasource,
-          recorpayList: this.recorpayList,
-          payablesList: payablesData.payablesList,
-          totalAdvanceConfirmAmount: payablesData.statementAdvanceTotalPrice,
-          totalPayableAmount: payablesData.receivedTotalPrice
-        };
-        let data = await api(params);
-        if (is == 'sub') {
-          await this.submit(data);
-          return;
-          // await submitAccountStatementApproveAPI(
-          //   {
-          //     businessId: data,
-          //     type: this.dataForm.type
-          //   }
-          // )
+        try {
+          // 校验明细表与应付信息表单
+          await this.$refs.accountDetailTableRef.getValidForm();
+          await this.$refs.payablesInfoRef.validate();
+
+          let api =
+            this.dialogType == 'add'
+              ? createAccountStatementAPI
+              : accountstatementUpdateAPI;
+          // 提交时一次性取回应付信息(本地明细 + 汇总),不再实时回写
+          const payablesData = this.$refs.payablesInfoRef.getSubmitData();
+          // statPayable 为完整数据容器,保存时以它为基准组装应付明细与汇总
+          const statPayable = {
+            statPayableDetailList: payablesData.payablesList,
+            statementAdvanceTotalPrice:
+              payablesData.statementAdvanceTotalPrice,
+            receivedTotalPrice: payablesData.receivedTotalPrice
+          };
+          this.statPayable = statPayable;
+
+          const statementAdvanceTotalPrice =
+            payablesData.statementAdvanceTotalPrice;
+          const receivedTotalPrice = payablesData.receivedTotalPrice;
+          let params = {
+            ...this.dataForm,
+            statementAdvanceTotalPrice,
+            receivedTotalPrice,
+            totalAdvanceConfirmAmount: statementAdvanceTotalPrice,
+            totalPayableAmount: receivedTotalPrice,
+            productList: this.datasource,
+            statPayable
+          };
+          this.saveLoading = true;
+          let data = await api(params);
+          if (is == 'sub') {
+            await this.submit(data);
+            return;
+          }
+          this.$message.success('操作成功');
+          this.reload();
+          this.saveLoading = false;
+        } catch (error) {
+          console.error('保存失败:', error);
+          this.saveLoading = false;
         }
-        this.$message.success('操作成功');
-        this.reload();
       },
       async submit(res) {
         let data = await accountstatementInfoAPI(this.businessId || res);

+ 52 - 48
src/views/purchasingManage/purchaseOrder/accountstatement/components/detailDialog.vue

@@ -27,43 +27,32 @@
         </div>
       </div>
     </el-card>
-    <div v-if="activeComp === 'main'">
-      <!--采购表单表单-->
+    <div v-show="activeComp === 'main'">
+      <!--采购对账单信息-->
       <purchase-form
         :dataForm.sync="dataForm"
         :datasource.sync="datasource"
         dialogType="view"
       ></purchase-form>
-      <headerTitle title="对账明细" style="margin-top: 30px">
-        <template v-slot>
-          <el-row style="font-weight: 700; color: red">
-            <span>订单总金额:</span>
-            <span>{{ dataForm.orderTotalAmount || 0 }}</span>
-            <el-divider direction="vertical"></el-divider>
-            <span>已对账金额:</span>
-            <span>{{ dataForm.amountCompletePrice || 0 }}</span>
-            <el-divider direction="vertical"></el-divider>
-            <span>未对账金额:</span>
-            <span>{{ dataForm.amountUnCompletePrice || 0 }}</span>
-            <el-divider direction="vertical"></el-divider>
-            <span>本次对账总金额:</span>
-            <span>{{ dataForm.amountTotalPrice || 0 }}</span>
-          </el-row>
-        </template>
-      </headerTitle>
-      <!-- <recorpayTableList
-        ref="recorpayListRef"
-        :dataForm="dataForm"
-        :recorpayList.sync="recorpayList"
-        dialogType="view"
-      ></recorpayTableList> -->
-      <inventoryTable
-        ref="inventoryTableref"
-        :dataForm="dataForm"
+
+      <headerTitle title="应付信息" style="margin-top: 30px"></headerTitle>
+      <payables-info
+        :dataForm.sync="dataForm"
+        :payablesList="payablesList"
+        :dialogType="dialogType"
+        ref="payablesInfoRef"
+      ></payables-info>
+
+      <headerTitle title="对账明细" style="margin-top: 30px"></headerTitle>
+      <account-detail-table
+        ref="accountDetailTableRef"
         :datasource.sync="datasource"
-        dialogType="view"
-        type="purchase"
-      ></inventoryTable>
+        :dialogType="dialogType"
+        :queryDimension="dataForm.queryDimension"
+        @totalChange="handleTotalChange"
+        @countChange="handleCountChange"
+        @statementAmountChange="handleStatementAmountChange"
+      ></account-detail-table>
     </div>
 
     <bpmDetail
@@ -79,19 +68,18 @@
 
 <script>
   import bpmDetail from '@/views/bpm/processInstance/detail.vue';
-  // import InventoryTable from './inventoryTable.vue';
   import { accountstatementInfoAPI } from '@/api/saleManage/accountstatement';
   import purchaseForm from './purchaseForm.vue';
-  import InventoryTable from '@/views/saleManage/saleOrder/accountstatement/components/inventoryTable.vue';
-  // import recorpayTableList from '@/views/saleManage/saleOrder/accountstatement/components/recorpayTableList.vue';
+  import payablesInfo from './payablesInfo.vue';
+  import AccountDetailTable from '@/views/saleManage/saleOrder/accountstatement/components/accountDetailTable.vue';
 
   export default {
     props: ['detailDialogFlag'],
     components: {
       purchaseForm,
-      InventoryTable,
-      bpmDetail,
-      // recorpayTableList
+      payablesInfo,
+      AccountDetailTable,
+      bpmDetail
     },
     data() {
       return {
@@ -104,7 +92,9 @@
         form: {},
         dataForm: {},
         datasource: [],
-        recorpayList:[],
+        payablesList: [],
+        statPayable: null,
+        dialogType: 'view',
         title: '详情',
         fullscreen: false
       };
@@ -115,22 +105,24 @@
         this.dialogType = dialogType;
         this.dataForm.type = type;
         let data = await accountstatementInfoAPI(row.id);
-        data.orderTotalAmount = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.orderAmount * 100), 0) / 100;
-      data.amountTotalPrice = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.statementAmount * 100), 0) / 100;
-      data.amountCompletePrice = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.statementedAmount * 100), 0) / 100;
-      data.amountUnCompletePrice = data.orderList.reduce((pre, cur) => pre + Math.round(+cur.unStatementAmount * 100), 0) / 100;
-        this.datasource = data.orderList||[];
-        this.recorpayList = data.recorpayList || [];
-        this.dataForm = data;
+        this.datasource = data.productList || [];
+        this.payablesList =
+          (data.statPayable && data.statPayable.statPayableDetailList) || [];
+        // 保存查询到的完整 statPayable 对象,提交时回填使用(详情页只读,但保留字段方便编辑场景扩展)
+        this.statPayable = data.statPayable || null;
+        this.dataForm = {
+          ...this.dataForm,
+          ...data
+        };
         switch (this.dataForm.dateType) {
           case 1:
             this.dataForm.year = this.dataForm.dateValue;
             break;
           case 2:
             //2023年-四季度
-            let data = this.dataForm.dateValue.split('年-');
-            this.dataForm.year = data[0];
-            this.dataForm.quarter = data[1];
+            let dateArr = this.dataForm.dateValue.split('年-');
+            this.dataForm.year = dateArr[0];
+            this.dataForm.quarter = dateArr[1];
             break;
           case 3:
             this.dataForm.month = this.dataForm.dateValue;
@@ -143,6 +135,18 @@
             ];
         }
       },
+      handleTotalChange(total) {
+        this.dataForm.amountTotalPrice = total;
+      },
+      handleCountChange(count) {
+        this.dataForm.totalStatementCount = count;
+      },
+      // 对账明细按采购单号汇总本次对账金额,同步到应付信息对应行
+      handleStatementAmountChange(summaryMap) {
+        if (this.$refs.payablesInfoRef) {
+          this.$refs.payablesInfoRef.syncStatementAmount(summaryMap);
+        }
+      },
       cancel() {
         this.$emit('update:detailDialogFlag', false);
       }

+ 117 - 37
src/views/purchasingManage/purchaseOrder/accountstatement/components/payablesInfo.vue

@@ -31,37 +31,47 @@
         class="time-form"
       >
         <template v-slot:fundType="scope">
-          <el-select
-            v-model="scope.row.fundType"
-            placeholder="请选择"
-            class="ele-block"
-            :disabled="isView"
-            @change="(val) => updateRowField(scope.$index, 'fundType', val)"
+          <el-form-item
+            :prop="'payablesList.' + scope.$index + '.fundType'"
+            label-width="0"
           >
-            <el-option
-              v-for="item in paymentTypeOp"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
+            <el-select
+              v-model="scope.row.fundType"
+              placeholder="请选择"
+              class="ele-block"
+              :disabled="isView"
+              @change="(val) => updateRowField(scope.$index, 'fundType', val)"
+            >
+              <el-option
+                v-for="item in paymentTypeOp"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
         </template>
 
         <template v-slot:transactionMode="scope">
-          <el-select
-            v-model="scope.row.transactionMode"
-            placeholder="请选择"
-            class="ele-block"
-            :disabled="isView"
-            @change="(val) => updateRowField(scope.$index, 'transactionMode', val)"
+          <el-form-item
+            :prop="'payablesList.' + scope.$index + '.transactionMode'"
+            label-width="0"
           >
-            <el-option
-              v-for="item in transactionMethodsOp"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
+            <el-select
+              v-model="scope.row.transactionMode"
+              placeholder="请选择"
+              class="ele-block"
+              :disabled="isView"
+              @change="(val) => updateRowField(scope.$index, 'transactionMode', val)"
+            >
+              <el-option
+                v-for="item in transactionMethodsOp"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
         </template>
 
         <template v-slot:paymentConditionName="scope">
@@ -103,6 +113,10 @@
             >删除</el-link
           >
         </template>
+
+        <template v-slot:columnRequired="{ column }">
+          <span class="is-required">{{ column.label }}</span>
+        </template>
       </ele-pro-table>
     </el-form>
     <!-- 付款条件 -->
@@ -177,14 +191,16 @@
             minWidth: 140,
             label: '款项类型',
             align: 'center',
-            slot: 'fundType'
+            slot: 'fundType',
+            headerSlot: 'columnRequired'
           },
           {
             prop: 'transactionMode',
             minWidth: 140,
             label: '交易方式',
             align: 'center',
-            slot: 'transactionMode'
+            slot: 'transactionMode',
+            headerSlot: 'columnRequired'
           },
           {
             prop: 'paymentConditionName',
@@ -194,18 +210,50 @@
             slot: 'paymentConditionName'
           },
           {
-            minWidth: 170,
-            prop: 'unreconciledAdvanceConfirmAmount',
-            label: '未对账预付款确收金额',
+            prop: 'prepayTotalAmt',
+            minWidth: 160,
+            label: '预付合计金额',
+            align: 'center',
+          },
+          {
+            prop: 'confirmedPrepayAmt',
+            minWidth: 160,
+            label: '累计预付确付金额',
             align: 'center',
-            showOverflowTooltip: true
           },
+          {
+            prop: 'unpaidPrepayAmt',
+            minWidth: 160,
+            label: '未付预付余额',
+            align: 'center',
+          },
+          // {
+          //   minWidth: 170,
+          //   prop: 'unreconciledAdvanceConfirmAmount',
+          //   label: '未对账预付款确收金额',
+          //   align: 'center',
+          //   showOverflowTooltip: true
+          // },
+          // {
+          //   minWidth: 190,
+          //   prop: 'statementAdvanceConfirmAmount',
+          //   label: '本次对账预付款确收金额',
+          //   align: 'center',
+          //   // slot: 'statementAdvanceConfirmAmount'
+          // },
           {
             minWidth: 190,
+            headerSlot: 'columnRequired',
             prop: 'statementAdvanceConfirmAmount',
             label: '本次对账预付款确收金额',
             align: 'center',
-            // slot: 'statementAdvanceConfirmAmount'
+            slot: 'statementAdvanceConfirmAmount'
+          },
+          {
+            minWidth: 160,
+            prop: 'lastPayableAmt',
+            label: '上期累计应付金额',
+            align: 'center'
           },
           {
             minWidth: 120,
@@ -220,6 +268,13 @@
             label: '本次应付金额',
             align: 'center',
             showOverflowTooltip: true
+          },
+          {
+            minWidth: 160,
+            prop: 'payableAmt',
+            label: '累计应付金额',
+            align: 'center',
+            showOverflowTooltip: true
           }
         ]
       };
@@ -275,11 +330,12 @@
         this.updateRowField(targetIndex, 'collectionConditionName', row.name);
       },
       // 行内字段修改:仅更新本地副本
+      // 注意:必须用 $set 直接修改原对象属性,保持引用不变,
+      // 否则 ele-pro-table 内部缓存的 tableData 仍引用旧对象,导致表格不更新
       updateRowField(index, key, val) {
         const item = this.localList[index];
         if (!item) return;
-        this.localList[index] = { ...item, [key]: val };
-        this.recalcRow(item);
+        this.$set(item, key, val);
       },
       // 新增一行空白预付
       addRow() {
@@ -293,8 +349,10 @@
           paymentConditionName: '',
           unreconciledAdvanceConfirmAmount: 0,
           statementAdvanceConfirmAmount: 0,
+          lastPayableAmt: 0,
           statementAmount: 0,
-          payablePrice: 0
+          payablePrice: 0,
+          payableAmt: 0
         });
       },
       // 由父组件预付款选择器回调调用:追加一行已映射好的应付明细(本地维护)
@@ -325,18 +383,32 @@
         }
         this.recalcRow(row);
       },
-      // 根据本次对账金额重算单行:确收金额 = min(未对账预付款确收金额, 本次对账金额);应付金额 = 本次对账金额 - 确收金额
+      // 根据本次对账金额重算单行:
+      // 确收金额 = min(未对账预付款确收金额, 本次对账金额)
+      // 本次应付金额 = 本次对账金额 - 确收金额
+      // 累计应付金额 = 本次对账金额 - 累计预付确付金额 + 上期累计应付金额
       recalcRow(row) {
         const statementAmount = +row.statementAmount || 0;
         let val = +row.statementAdvanceConfirmAmount || 0;
         const max = this.getMaxConfirmAmount(row);
         if (val > max) val = max;
         this.$set(row, 'statementAdvanceConfirmAmount', val);
+        // 本次应付金额 = 本次对账金额 - 确收金额
         this.$set(
           row,
           'payablePrice',
           Math.round((statementAmount - val) * 100) / 100
         );
+        // 累计应付金额=本次对账金额-累计预付确付金额+上期累计应付金额
+        const totalPayableAmount =
+          statementAmount -
+          (+row.confirmedPrepayAmt || 0) +
+          (+row.lastPayableAmt || 0);
+        this.$set(
+          row,
+          'payableAmt',
+          Math.round(totalPayableAmount * 100) / 100
+        );
       },
       // 明细表按采购单号汇总本次对账金额后,同步到对应采购单号的应付行
       syncStatementAmount(summaryMap) {
@@ -395,5 +467,13 @@
       justify-content: flex-end;
       margin-bottom: 10px;
     }
+    .el-form-item {
+      margin-bottom: 0 !important;
+    }
+  }
+  ::v-deep .is-required::before {
+    content: '*';
+    color: #f56c6c;
+    margin-right: 4px;
   }
 </style>

+ 13 - 11
src/views/purchasingManage/purchaseOrder/accountstatement/index.vue

@@ -109,7 +109,7 @@
               </template>
             </el-popconfirm>
 
-            <!-- <el-link
+            <el-link
               size="small"
               type="primary"
               :underline="false"
@@ -119,7 +119,7 @@
               @click="handleAddInvoice(row)"
             >
               新增发票
-            </el-link> -->
+            </el-link>
           </template>
         </ele-pro-table>
       </div>
@@ -188,7 +188,7 @@
   import dictMixins from '@/mixins/dictMixins';
   import 'file-saver';
   import AccountInfoDialog from '@/views/financialManage/invoiceManage/components/accountInfoDialog.vue';
-  import addInvoiceDialog from '@/views/financialManage/invoiceManage/components/addOrEditDialog.vue';
+  import addInvoiceDialog from '@/views/financialManage/invoiceManage/components/addOrEditDialogNew.vue';
   import processSubmitDialog from '@/BIZComponents/processSubmitDialog/processSubmitDialog.vue';
   import tabMixins from '@/mixins/tableColumnsMixin';
 
@@ -373,14 +373,16 @@
       /*新增发票*/
       handleAddInvoice(row) {
         this.currentRow = row;
-        this.accountInfoDialogFlag = true;
-        this.$nextTick(() => {
-          this.$refs.accountInfoDialogRef.createInvoice(
-            row,
-            'add',
-            'purchaseOrder'
-          );
-        });
+        setTimeout(() => {
+          this.addInvoiceDialogFlag = true;
+          this.$nextTick(() => {
+            this.$refs.addInvoiceDialogRef.createInvoice1(
+              [row],
+              '2',
+              1
+            );
+          });
+        }, 400);
       },
       /*新增发票选择对账单信息回调*/
       getAccountInfo(row) {

+ 28 - 25
src/views/purchasingManage/purchaseOrder/components/addDialogNew.vue

@@ -253,26 +253,26 @@
             >
             </el-date-picker>
           </el-form-item>
-          <!-- <el-form-item label="付款条件" prop="collectionConditionName">
+          <el-form-item label="付款条件" prop="paymentConditionName">
             <el-input
               clearable
               readonly
-              v-model="form.collectionConditionName"
+              v-model="form.paymentConditionName"
               @click.native="handlePaymentConditionBtn"
               placeholder="请输入"
             />
-          </el-form-item> -->
+          </el-form-item>
           <el-form-item prop="orderFiles" label="附件">
             <fileMain v-model="form.orderFiles"></fileMain>
           </el-form-item>
         </el-col>
         <el-col :span="8">
-          <!-- <el-form-item label="生成付款计划表" prop="isGenerateReceiptPlan">
-            <el-radio-group v-model="form.isGenerateReceiptPlan" @change="generatePlanChange">
+          <el-form-item label="生成付款计划表" prop="isGeneratePaymentPlan">
+            <el-radio-group v-model="form.isGeneratePaymentPlan" @change="generatePlanChange">
               <el-radio :label="1">是</el-radio>
               <el-radio :label="0">否</el-radio>
             </el-radio-group>
-          </el-form-item> -->
+          </el-form-item>
           <el-form-item label="交易方式" prop="transactionMode">
             <el-select
               v-model="form.transactionMode"
@@ -365,7 +365,7 @@
             </el-input>
           </el-form-item>
           <el-form-item
-             v-if="form.isGenerateReceiptPlan != 0"
+             v-if="form.isGeneratePaymentPlan != 0"
             label="期数"
             prop="issueNumber"
           >
@@ -622,7 +622,7 @@
           </el-form-item>
         </el-col>
       </el-row>
-      <div v-if="form.isGenerateReceiptPlan != 0">
+      <div v-if="form.isGeneratePaymentPlan != 0">
         <headerTitle
           title="付款计划"
           style="margin-top: 30px"
@@ -883,7 +883,7 @@
         saleType: '',
         saleTypeName: '',
         totalAmount: '',
-        isGenerateReceiptPlan: 1,
+        isGeneratePaymentPlan: 0,
         settlementMode: '4',
         settlementModeName: '分期付款',
         partaUnifiedSocialCreditCode: '',
@@ -993,13 +993,16 @@
         return this.isUpdate ? this.requirementSourceType : this.requirementSourceType.filter(item => item.value !== '8');
       },
       rules() {
-        let isRequired = this.isRequired;
+        let isRequired = true;
         // console.log(this.isRequired);
 
         return {
           deliveryDate: [
             { required: true, message: '请选择交货日期', trigger: 'change' }
           ],
+          isGeneratePaymentPlan: [
+            { required: true, message: '请选择是否生成付款计划表', trigger: 'change' }
+          ],
           purchasePlanName: [
             {
               required: this.OutValidate.includes(this.form.sourceType),
@@ -1037,8 +1040,8 @@
           partaLinkName: [
             {
               required: isRequired,
-              message: '请选择供应商联系人',
-              trigger: 'change'
+              message: '请输入采购方联系人',
+              trigger: ['change', 'blur']
             }
           ],
           acceptUnpack: [
@@ -1055,7 +1058,7 @@
             {
               required: isRequired,
               pattern: isRequired ? telReg : null,
-              message: '请输入供应商联系电话',
+              message: '请输入采购方电话',
               trigger: 'blur'
             }
           ],
@@ -1066,7 +1069,7 @@
           partbLinkName: [
             {
               required: isRequired,
-              message: '请输入供采购方联系人',
+              message: '请输入供应商联系人',
               trigger: 'change'
             }
           ],
@@ -1074,7 +1077,7 @@
             {
               required: isRequired,
               pattern: isRequired ? telReg : null,
-              message: '请输入供采购方联系电话',
+              message: '请输入供应商联系电话',
               trigger: 'blur'
             }
           ],
@@ -1115,8 +1118,8 @@
     methods: {
       changeReceiveTerms(row, index) {
         console.log('changeReceiveTerms~~~', row)
-        this.form.collectionConditionId = row.id;
-        this.form.collectionConditionName = row.name;
+        this.form.paymentConditionId = row.id;
+        this.form.paymentConditionName = row.name;
         console.log('changeReceiveTerms!!!', this.form)
         this.$forceUpdate()
       },
@@ -2185,7 +2188,7 @@
             })
           }
           this.form.contractStartDate = formatDate(new Date(), 'yyyy-MM-dd');
-          // this.form.isGenerateReceiptPlan = +this.isGenReceiptPlan;
+          // this.form.isGeneratePaymentPlan = +this.isGenReceiptPlan;
         } else {
           this.isUpdate = true;
           await this.getpurchaseorderDetail(row.id);
@@ -2215,7 +2218,7 @@
         this.visible = true;
         this.isUpdate = false;
         this.form.relationType = 4;
-        // this.form.isGenerateReceiptPlan = +this.isGenReceiptPlan;
+        // this.form.isGeneratePaymentPlan = +this.isGenReceiptPlan;
         this.changeContract(row);
       },
       handleGoodsList() {
@@ -2285,7 +2288,7 @@
           }),
         ]
 
-        if(this.form.isGenerateReceiptPlan != 0) {
+        if(this.form.isGeneratePaymentPlan != 0) {
           arr.push(new Promise((resolve, reject) => {
             this.$refs.paymentCollectionPlanRef.validateForm((valid) => {
               if (!valid) {
@@ -2388,14 +2391,14 @@
             sourceTypeName: this.requirementSourceType.find(
               (val) => val.value == this.form.sourceType
             )?.label,
-            receiptPaymentList: this.form.isGenerateReceiptPlan == 0 ? [] : 
+            receiptPaymentList: this.form.isGeneratePaymentPlan == 0 ? [] : 
               this.$refs?.paymentCollectionPlanRef?.getTableValue() || [],
             endSettlementDate: this.form.settlementDate?.length ? this.form.settlementDate[1] : '',
             startSettlementDate: this.form.settlementDate?.length ? this.form.settlementDate[0] : ''
           });
 
 
-          if(this.form.isGenerateReceiptPlan != 0) {
+          if(this.form.isGeneratePaymentPlan != 0) {
             const ratioSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + +cur.ratio, 0);
           // if(+ratioSum != 100){
           //   this.$message.error('比例合计必须为100%');
@@ -2565,12 +2568,12 @@
         let dateRange = [];
         if(this.form.settlementMode == 1) {
           dateRange = this.transformDaysFun(this.form.settlementDate, v);
-          this.$refs.paymentCollectionPlanRef.defaultList(this.form.settlementMode, v, dateRange); 
+          this.$refs.paymentCollectionPlanRef?.defaultList(this.form.settlementMode, v, dateRange); 
         } else if(this.form.settlementMode == 2) {
           dateRange = this.transformMonthFun(this.form.settlementDate, v);
-          this.$refs.paymentCollectionPlanRef.defaultList(this.form.settlementMode, v, dateRange);
+          this.$refs.paymentCollectionPlanRef?.defaultList(this.form.settlementMode, v, dateRange);
         } else {
-          this.$refs.paymentCollectionPlanRef.defaultList(this.form.settlementMode, v);
+          this.$refs.paymentCollectionPlanRef?.defaultList(this.form.settlementMode, v);
         }
       },
       transformDaysFun(date) {

+ 2 - 1
src/views/saleManage/saleOrder/accountstatement/components/accountDetailTable.vue

@@ -260,7 +260,8 @@
           },
           {
             minWidth: 140,
-            prop: 'statementSubOrderNo',
+            // prop: 'statementSubOrderNo',
+            prop: this.queryDimension == 3 ? 'statementSubOrderNo' : this.queryDimension == 1 ? 'statementSubOrderCode' : 'statementSubOrderNo',
             label: this.queryDimension == 3 ? '收货单编码' : this.queryDimension == 1 ? '发货单编码' : '调拨单编码',
             align: 'center',
             showOverflowTooltip: true

+ 18 - 19
src/views/saleManage/saleOrder/accountstatement/components/receivableInfo.vue

@@ -247,13 +247,7 @@
           {
             minWidth: 160,
             prop: 'lastReceivedAmt',
-            label: '上期对账金额',
-            align: 'center'
-          },
-          {
-            minWidth: 160,
-            prop: 'statementAmt',
-            label: '本次对账应收总金额',
+            label: '上期累计应收金额',
             align: 'center'
           },
           {
@@ -263,6 +257,12 @@
             align: 'center',
             showOverflowTooltip: true
           },
+          {
+            minWidth: 160,
+            prop: 'statementAmt',
+            label: '本次对账应收总金额',
+            align: 'center'
+          },
           {
             minWidth: 120,
             prop: 'receivedAmt',
@@ -278,13 +278,14 @@
         return this.dialogType === 'view';
       },
       statementAdvanceTotalPrice() {
-        return (
-          this.localList.reduce(
-            (pre, cur) =>
-              pre + Math.round((+cur.statementAdvanceConfirmAmount || 0) * 100),
-            0
-          ) / 100
-        );
+        // return (
+        //   this.localList.reduce(
+        //     (pre, cur) =>
+        //       pre + Math.round((+cur.statementAdvanceConfirmAmount || 0) * 100),
+        //     0
+        //   ) / 100
+        // );
+        return this.dataForm?.statReceipt?.statementAdvanceTotalPrice || 0;
       },
       receivedTotalPrice() {
         return (
@@ -392,14 +393,12 @@
           'receivedPrice',
           Math.round((statementAmount - val) * 100) / 100
         );
-        // 累计应收金额 = 本次对账应收总金额 - 预收款确收金额 + 上期对账金额
-        // 本次对账应收总金额优先取 statementAmt,为空时回退到 statementAmount
-        const statementAmt = +row.statementAmt || +row.statementAmount || 0;
-        const lastReceivedAmt = +row.lastReceivedAmt || 0;
+        // 累计应收金额=本次对账金额-预收款确认金额+上期累计应收金额
+        const totalReceivableAmount = statementAmount - row.confirmedTotalAmt + (+row.lastReceivedAmt || 0);
         this.$set(
           row,
           'receivedAmt',
-          Math.round((statementAmt - val + lastReceivedAmt) * 100) / 100
+          Math.round(totalReceivableAmount * 100) / 100
         );
       },
       // 明细表按销售单号汇总本次对账金额后,同步到对应销售单号的应收行

+ 54 - 5
src/views/saleManage/saleOrder/components/addDialogNew.vue

@@ -360,8 +360,9 @@
             </el-date-picker>
           </el-form-item>
 
+          <!-- 结算方式=按月结算(2) 时必填;=分期付款 时展示但非必填,仅用于给下方收款计划回填计划收款日期 -->
           <el-form-item
-            v-if="form.settlementMode == 2"
+            v-if="form.settlementMode == 2 || isInstallment"
             label="结算月份范围"
             prop="settlementDate"
           >
@@ -374,7 +375,7 @@
             </el-date-picker> -->
             <el-date-picker
               v-model="form.settlementDate"
-              :clearable="false"
+              :clearable="isInstallment"
               type="monthrange"
               range-separator="至"
               start-placeholder="开始月份"
@@ -386,7 +387,7 @@
             </el-date-picker>
           </el-form-item>
           <el-form-item
-            v-if="form.settlementMode == 2"
+            v-if="form.settlementMode == 2 || isInstallment"
             label="收款日期"
             prop="receiptDate"
           >
@@ -1022,6 +1023,12 @@
       clientEnvironmentId() {
         return this.$store.state.user.info.clientEnvironmentId;
       },
+      // 结算方式是否为「分期付款」
+      isInstallment() {
+        const mode = this.form.settlementMode;
+        if (mode === '' || mode === null || mode === undefined) return false;
+        return mode == 4 || this.form.settlementModeName === '分期付款';
+      },
       rules() {
         let isRequired = this.isRequired;
         return {
@@ -1107,10 +1114,18 @@
             }
           ],
           settlementDate: [
-            { required: true, message: '请选择结算日期', trigger: 'change' }
+            {
+              required: !this.isInstallment,
+              message: '请选择结算日期',
+              trigger: 'change'
+            }
           ],
           receiptDate: [
-            { required: true, message: '请选择收款日期', trigger: 'change' }
+            {
+              required: !this.isInstallment,
+              message: '请选择收款日期',
+              trigger: 'change'
+            }
           ]
         };
       }
@@ -1191,6 +1206,12 @@
       },
       setIssueNumber(len) {
         this.form.issueNumber = len;
+        // 分期付款下手工增删行后,同步回填新行的计划收款日期
+        if (this.isInstallment) {
+          this.$nextTick(() => {
+            this.setInstallmentDeadLine();
+          });
+        }
       },
       setCountAmount(allPrice, discountTotalPrice) {
         this.form.totalAmount = allPrice;
@@ -2309,6 +2330,11 @@
       // 日期范围变化
       settlementDateChange(val) {
         // console.log(val);
+        // 分期付款:期数由用户自行填写,这里只把计划收款日期回填到已有的收款计划行
+        if (this.isInstallment) {
+          this.setInstallmentDeadLine();
+          return;
+        }
         let dateRange = [];
         if (this.form.settlementMode == 1) {
           //   // this.transformDays(val)
@@ -2330,6 +2356,10 @@
       // 收款日变化
       receiptDateChange(v) {
         // this.transformMonth(this.form.settlementDate)
+        if (this.isInstallment) {
+          this.setInstallmentDeadLine();
+          return;
+        }
         if (this.form.settlementDate.length > 0 && this.form.issueNumber) {
           const dateRange = this.transformMonthFun(this.form.settlementDate, v);
           this.$refs.paymentCollectionPlanRef.defaultList(
@@ -2339,6 +2369,16 @@
           );
         }
       },
+      // 分期付款:按「结算月份范围 + 收款日期」给收款计划回填计划收款日期
+      // 结算月份范围/收款日期均非必填,未填时不做任何赋值;只覆盖 deadLine,不影响用户已填的比例/款项名称/金额/说明
+      setInstallmentDeadLine() {
+        const { settlementDate, receiptDate } = this.form;
+        if (!settlementDate || settlementDate.length < 2) return;
+        const day = parseInt(receiptDate, 10);
+        if (!day || day < 1 || day > 31) return;
+        const dateRange = this.transformMonthFun(settlementDate, day);
+        this.$refs.paymentCollectionPlanRef?.setDeadLineList(dateRange);
+      },
       // 期数变化
       issueNumberChange(v) {
         let dateRange = [];
@@ -2356,6 +2396,15 @@
             v,
             dateRange
           );
+        } else if (this.isInstallment) {
+          // 先按期数重建行,再回填计划收款日期
+          this.$refs.paymentCollectionPlanRef.defaultList(
+            this.form.settlementMode,
+            v
+          );
+          this.$nextTick(() => {
+            this.setInstallmentDeadLine();
+          });
         } else {
           this.$refs.paymentCollectionPlanRef.defaultList(
             this.form.settlementMode,

+ 25 - 2
src/views/saleManage/saleOrder/components/darwerComponents/saleOrderInfo.vue

@@ -38,7 +38,11 @@
             </el-date-picker>
           </el-form-item>
 
-          <el-form-item v-if="form.settlementMode == 2" label="结算月份范围" prop="settlementDate">
+          <el-form-item
+            v-if="showSettleMonth"
+            label="结算月份范围"
+            prop="settlementDate"
+          >
             <el-date-picker
               v-model="form.settlementDate"
               type="monthrange"
@@ -51,7 +55,11 @@
             >
             </el-date-picker>
           </el-form-item>
-          <el-form-item  v-if="form.settlementMode == 2" label="收款日期" prop="receiptDate">
+          <el-form-item
+            v-if="showSettleMonth"
+            label="收款日期"
+            prop="receiptDate"
+          >
             <el-input type="number" :min="1" :max="31" disabled placeholder="请输入" v-model="form.receiptDate">
               <template slot="prepend">每月</template>
               <template slot="append">日</template>
@@ -383,6 +391,21 @@
     computed: {
       clientEnvironmentId() {
         return this.$store.state.user.info.clientEnvironmentId;
+      },
+      // 结算方式是否为「分期付款」
+      isInstallment() {
+        const mode = this.form.settlementMode;
+        if (mode === '' || mode === null || mode === undefined) return false;
+        return mode == 4 || this.form.settlementModeName === '分期付款';
+      },
+      // 按月结算固定展示;分期付款下只有填过结算月份范围才展示
+      showSettleMonth() {
+        if (this.form.settlementMode == 2) return true;
+        return !!(
+          this.isInstallment &&
+          this.form.settlementDate &&
+          this.form.settlementDate.length
+        );
       }
     },
     methods: {