Просмотр исходного кода

fix:5364【库存台账】拆批操作,计量数量没法除以包装规格,下面的整包分配没法拆分,这里看怎么限制下

mlchen 5 дней назад
Родитель
Сommit
4f294b13ba

+ 0 - 7
src/api/warehouseManagement/stockBatchChange.js

@@ -14,13 +14,6 @@ export default {
   detail: (id) => request.get(`${base}/getById/${id}`).then(unwrap),
   sourceDetails: (stockBatchIds) =>
     request.post(`${base}/sourceDetails`, { stockBatchIds }).then(unwrap),
-  checkSplit: (categoryIds) =>
-    request.post(`${base}/checkSplit`, { categoryIds }).then((res) => {
-      if (res.data.code === 0 || res.data.code === '0') {
-        return res.data.data;
-      }
-      return Promise.reject(new Error(res.data.message || '操作失败'));
-    }),
   save: (data) => request.post(`${base}/save`, data).then(unwrap),
   submit: (data) =>
     request

+ 75 - 139
src/views/warehouseManagement/stockLedger/components/BatchChangeDialog.vue

@@ -180,6 +180,7 @@
         <el-table-column prop="batchNo" label="业务批次" />
         <el-table-column prop="warehouseName" label="仓库" />
         <el-table-column prop="categoryCode" label="物品编码" />
+        <el-table-column prop="packingSpecification" label="包装规格" />
         <el-table-column prop="stockCountBase" label="计量数量" />
         <el-table-column prop="packingQuantity" label="包装数量" />
         <el-table-column prop="weight" label="重量" />
@@ -199,14 +200,16 @@
           <el-table-column label="计量数量">
             <template slot-scope="{ row }">
               <el-input
+                v-if="!hasPacking && !isAutoMeasureTarget(row.target)"
                 v-model="row.target.measureQuantity"
                 maxlength="19"
                 :disabled="Boolean(pendingApproveId)"
                 size="mini"
                 placeholder="请输入"
-                @input="markMeasureQuantityManual(row.target)"
+                @input="handleMeasureQuantityInput(row.target)"
                 @blur="validateTargetLimit(row.target, 'measureQuantity')"
               />
+              <span v-else>{{ row.measureQuantity }}</span>
             </template>
           </el-table-column>
           <el-table-column label="包装数量">
@@ -225,6 +228,7 @@
           <el-table-column label="重量">
             <template slot-scope="{ row }">
               <el-input
+                v-if="!hasPacking"
                 v-model="row.target.weight"
                 maxlength="19"
                 :disabled="Boolean(pendingApproveId)"
@@ -232,6 +236,7 @@
                 placeholder="请输入"
                 @blur="validateTargetLimit(row.target, 'weight')"
               />
+              <span v-else>{{ row.weight }}</span>
             </template>
           </el-table-column>
           <el-table-column prop="lockQuantity" label="锁库数量" />
@@ -284,12 +289,6 @@
             @click="assignSelectedPackingTarget"
             >批量分配</el-button
           >
-          <el-button
-            size="mini"
-            :disabled="Boolean(pendingApproveId)"
-            @click="assignAllPackingTargets"
-            >一键分配</el-button
-          >
           <el-button
             size="mini"
             :disabled="Boolean(pendingApproveId)"
@@ -901,7 +900,6 @@
         return {
           targetDetailId,
           measureQuantity: '0',
-          measureQuantityManual: false,
           packageQuantity: '0',
           weight: '0'
         };
@@ -974,122 +972,35 @@
       handlePackingSelectionChange(rows) {
         this.selectedPackingRows = rows;
       },
-      packingRowSelectable() {
-        if (this.pendingApproveId || !this.batchPackingTargetId) return false;
-        const target = this.targets.find(
-          (item) => item.targetDetailId === this.batchPackingTargetId
+      packingRowSelectable(row) {
+        return (
+          !this.pendingApproveId &&
+          Boolean(this.batchPackingTargetId) &&
+          !row.targetDetailId
+        );
+      },
+      isAutoMeasureTarget(target) {
+        return (
+          this.mode === 'split' &&
+          this.targets.length === 2 &&
+          target.targetDetailId === this.targets[1].targetDetailId
         );
-        return Boolean(target && !isEmptyDecimal(target.measureQuantity));
       },
       /** 将勾选的整包装一次分配到同一目标子批次。 */
       assignSelectedPackingTarget() {
         if (!this.batchPackingTargetId) {
           return this.$message.warning('请选择目标子批次');
         }
-        const target = this.targets.find(
-          (item) => item.targetDetailId === this.batchPackingTargetId
-        );
-        if (!target || isEmptyDecimal(target.measureQuantity)) {
-          return this.$message.warning('请先填写目标子批次的计量数量');
-        }
-        const assignedMeasureQuantity = this.packingRows
-          .filter((row) => row.targetDetailId === target.targetDetailId)
-          .reduce(
-            (sum, row) => sum.plus(decimal(row.measureQuantity)),
-            new BigNumber(0)
-          );
-        const remainingMeasureQuantity = decimal(target.measureQuantity).minus(
-          assignedMeasureQuantity
-        );
-        if (remainingMeasureQuantity.lte(0)) {
-          return this.$message.warning('该目标子批次已按计量数量分配整包装');
+        if (!this.selectedPackingRows.length) {
+          return this.$message.warning('请先选择整包装');
         }
-        const selectedRows = [];
-        let selectedMeasureQuantity = new BigNumber(0);
-        this.packingRows
-          .filter((row) => !row.targetDetailId)
-          .some((packing) => {
-            const packingMeasureQuantity = decimal(packing.measureQuantity);
-            if (
-              selectedMeasureQuantity
-                .plus(packingMeasureQuantity)
-                .gt(remainingMeasureQuantity)
-            ) {
-              return false;
-            }
-            selectedRows.push(packing);
-            selectedMeasureQuantity = selectedMeasureQuantity.plus(
-              packingMeasureQuantity
-            );
-            return selectedMeasureQuantity.eq(remainingMeasureQuantity);
-          });
-        if (!selectedRows.length) {
-          return this.$message.warning('没有可按该计量数量分配的整包装');
-        }
-        selectedRows.forEach((packing) => {
+        this.selectedPackingRows.forEach((packing) => {
           packing.targetDetailId = this.batchPackingTargetId;
           this.assignPackingTarget(packing, this.batchPackingTargetId, false);
         });
         this.syncTargetPackingMinimums();
-        this.selectedPackingRows = selectedRows;
-        this.$refs.packingTable.clearSelection();
-        this.$nextTick(() => {
-          selectedRows.forEach((packing) => {
-            this.$refs.packingTable.toggleRowSelection(packing, true);
-          });
-        });
-      },
-      /** 按所有目标子批次的计量数量依次匹配整包装。 */
-      assignAllPackingTargets() {
-        if (this.pendingApproveId) return;
-        const availableRows = this.packingRows.filter(
-          (row) => !row.targetDetailId
-        );
-        const assignments = [];
-        for (const target of this.targets) {
-          const assignedMeasureQuantity = this.packingRows
-            .filter((row) => row.targetDetailId === target.targetDetailId)
-            .reduce(
-              (sum, row) => sum.plus(decimal(row.measureQuantity)),
-              new BigNumber(0)
-            );
-          const remainingMeasureQuantity = decimal(
-            target.measureQuantity
-          ).minus(assignedMeasureQuantity);
-          if (remainingMeasureQuantity.lte(0)) continue;
-
-          const selectedRows = this.findPackingCombination(
-            availableRows,
-            remainingMeasureQuantity
-          );
-          if (!selectedRows.length) {
-            return this.$message.warning(
-              `${this.targetLabel(
-                target.targetDetailId
-              )}没有可按计量数量分配的整包装`
-            );
-          }
-          assignments.push({
-            target,
-            selectedRows
-          });
-          selectedRows.forEach((packing) => {
-            availableRows.splice(availableRows.indexOf(packing), 1);
-          });
-        }
-
-        assignments.forEach(({ target, selectedRows }) => {
-          selectedRows.forEach((packing) => {
-            packing.targetDetailId = target.targetDetailId;
-            this.assignPackingTarget(packing, target.targetDetailId, false);
-          });
-        });
-        this.syncTargetPackingMinimums();
         this.selectedPackingRows = [];
-        if (this.$refs.packingTable) this.$refs.packingTable.clearSelection();
-        if (assignments.some(({ selectedRows }) => selectedRows.length)) {
-          this.$message.success('已按所有目标计量数量自动分配整包装');
-        }
+        this.$refs.packingTable.clearSelection();
       },
       /** 清除所有包装和锁定单的目标分配,保留目标数量输入。 */
       clearPackingTargets() {
@@ -1102,24 +1013,15 @@
           lock.targetConflict = false;
         });
         this.selectedPackingRows = [];
+        this.targets.forEach((target) => {
+          if (this.hasPacking) {
+            target.measureQuantity = '0';
+            target.weight = '0';
+          }
+        });
         if (this.$refs.packingTable) this.$refs.packingTable.clearSelection();
         this.$message.success('已清空全部分配');
       },
-      findPackingCombination(rows, targetQuantity) {
-        const selected = [];
-        const search = (start, quantity) => {
-          if (quantity.eq(0)) return true;
-          for (let index = start; index < rows.length; index += 1) {
-            const packingQuantity = decimal(rows[index].measureQuantity);
-            if (packingQuantity.gt(quantity)) continue;
-            selected.push(rows[index]);
-            if (search(index + 1, quantity.minus(packingQuantity))) return true;
-            selected.pop();
-          }
-          return false;
-        };
-        return search(0, targetQuantity) ? selected.slice() : [];
-      },
       /** 包装分配变化时,同步其关联锁定单的全部明细和包装。 */
       assignPackingTarget(packing, targetDetailId, shouldSync = true) {
         const relatedLocks = this.lockRows.filter((lock) =>
@@ -1175,28 +1077,45 @@
           }
         });
       },
-      /** 包装变更后同步目标下限,超出包装汇总的部分作为散量。 */
+      /** 包装分配后由最后一个目标承接来源剩余计量和重量。 */
       syncTargetPackingMinimums() {
+        if (!this.hasPacking) return;
+        const source = this.sources[0];
         this.targets.forEach((target) => {
           const packages = this.packingRows.filter(
             (row) => row.targetDetailId === target.targetDetailId
           );
           const measureMinimum = decimal(this.sum(packages, 'measureQuantity'));
           const weightMinimum = decimal(this.sum(packages, 'weight'));
-          if (
-            packages.length &&
-            (!target.measureQuantityManual ||
-              decimal(target.measureQuantity).lt(measureMinimum))
-          ) {
-            target.measureQuantity = measureMinimum.toFixed(6);
-          }
-          if (decimal(target.weight).lt(weightMinimum)) {
-            target.weight = weightMinimum.toFixed(6);
-          }
+          target.measureQuantity = measureMinimum.toFixed(6);
+          target.weight = weightMinimum.toFixed(6);
         });
+        if (this.mode === 'split') {
+          const lastTarget = this.targets[this.targets.length - 1];
+          const assigned = this.targets.slice(0, -1);
+          lastTarget.measureQuantity = decimal(source.stockCountBase)
+            .minus(this.sum(assigned, 'measureQuantity'))
+            .max(0)
+            .toFixed(6);
+          lastTarget.weight = decimal(source.weight)
+            .minus(this.sum(assigned, 'weight'))
+            .max(0)
+            .toFixed(6);
+        }
       },
-      markMeasureQuantityManual(target) {
-        target.measureQuantityManual = true;
+      handleMeasureQuantityInput(target) {
+        if (
+          this.mode !== 'split' ||
+          this.targets.length !== 2 ||
+          this.isAutoMeasureTarget(target) ||
+          !this.sources.length
+        ) {
+          return;
+        }
+        const remainder = decimal(this.sources[0].stockCountBase).minus(
+          decimal(target.measureQuantity)
+        );
+        this.targets[1].measureQuantity = remainder.max(0).toFixed(6);
       },
       validateTargetLimit(target, field) {
         if (this.mode !== 'split' || !this.sources.length) return;
@@ -1465,6 +1384,23 @@
         )
           return '目标计量数量和重量不能小于所选整包装汇总';
         if (this.mode === 'split') {
+          const packedMeasureQuantity = decimal(
+            this.sum(this.packingRows, 'measureQuantity')
+          );
+          const looseMeasureQuantity = decimal(source.stockCountBase).minus(
+            packedMeasureQuantity
+          );
+          if (this.hasPacking && looseMeasureQuantity.gt(0)) {
+            const looseTargetCount = this.targetRows.filter((row) =>
+              decimal(row.measureQuantity).gt(decimal(row.packingMeasureQuantity))
+            ).length;
+            if (looseTargetCount > 1) {
+              return '包装外散量只能分配到一个目标批次';
+            }
+            if (Number(source.isUnpack) !== 1) {
+              return '来源库存存在包装外散量,物品不允许拆包';
+            }
+          }
           if (
             !decimal(this.sum(this.targetRows, 'measureQuantity')).eq(
               decimal(source.stockCountBase)

+ 1 - 14
src/views/warehouseManagement/stockLedger/components/item-list.vue

@@ -304,7 +304,6 @@
   import unlockModal from '@/views/warehouseManagement/unlockApplication/components/unlockModal.vue';
   import lockDetailDialog from './lockDetailDialog.vue';
   import BatchChangeDialog from './BatchChangeDialog.vue';
-  import stockBatchChange from '@/api/warehouseManagement/stockBatchChange';
 
   export default {
     mixins: [tabMixins],
@@ -787,7 +786,7 @@
         }
         this.$refs.unlockModalRef.open('add', this.checkRadioData[0]);
       },
-      async openBatchChange(mode) {
+      openBatchChange(mode) {
         if (mode === 'split' && this.checkRadioData.length !== 1)
           return this.$message.warning('拆批请选择一条库存批次');
         if (mode === 'merge' && this.checkRadioData.length < 2)
@@ -802,18 +801,6 @@
         ) {
           return this.$message.warning('数量为0的库存批次不支持拆批和合批');
         }
-        if (mode === 'split') {
-          try {
-            const isUnpack = await stockBatchChange.checkSplit(
-              this.checkRadioData.map((row) => row.categoryId)
-            );
-            if (isUnpack) {
-              return this.$message.warning('拆包产品不支持拆批');
-            }
-          } catch (error) {
-            return this.$message.error(error.message || '拆批校验失败');
-          }
-        }
         this.$refs.batchChangeRef.open(mode, this.checkRadioData);
       },