|
|
@@ -0,0 +1,735 @@
|
|
|
+<template>
|
|
|
+ <div class="account-detail-table">
|
|
|
+ <el-form ref="detailForm" :model="{ flatList }">
|
|
|
+ <ele-pro-table
|
|
|
+ ref="detailTable"
|
|
|
+ row-key="id"
|
|
|
+ :needPage="false"
|
|
|
+ :columns="columns"
|
|
|
+ max-height="500px"
|
|
|
+ :datasource="flatList"
|
|
|
+ :cache-key="cacheKeyUrl"
|
|
|
+ class="time-form"
|
|
|
+ >
|
|
|
+ <template v-slot:toolbar>
|
|
|
+ <div class="detail-toolbar">
|
|
|
+ <el-button
|
|
|
+ v-if="!isView"
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ @click="batchSetTaxRate"
|
|
|
+ >批量设置税率</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ v-if="!isView"
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ @click="batchSetPrice"
|
|
|
+ >批量设置单价</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ v-if="!isView"
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ @click="batchSetDiscount"
|
|
|
+ >批量设置折让比例</el-button
|
|
|
+ >
|
|
|
+ <!-- <div class="summary-info">
|
|
|
+ <span
|
|
|
+ >本次总对账金额:<b>{{ totalStatementAmount }}</b> 元</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ >本次总对账数量:<b>{{ totalStatementCount }}</b></span
|
|
|
+ >
|
|
|
+ </div> -->
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-slot:statementCount="scope">
|
|
|
+ <el-form-item
|
|
|
+ :prop="'flatList.' + scope.$index + '.statementCount'"
|
|
|
+ :rules="{
|
|
|
+ validator: (rule, value, cb) =>
|
|
|
+ validateStatementCount(rule, value, cb, scope.row),
|
|
|
+ trigger: 'change'
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ v-model="scope.row.statementCount"
|
|
|
+ type="number"
|
|
|
+ :disabled="isView || queryDimension == 1"
|
|
|
+ @input="handleCountChange(scope.row, scope.$index)"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-slot:technologyRouteName="scope">
|
|
|
+ <el-input
|
|
|
+ v-model="scope.row.technologyRouteName"
|
|
|
+ placeholder="请选择"
|
|
|
+ :disabled="isView"
|
|
|
+ @click.native="openVersion(scope.$index)"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-slot:singlePrice="scope">
|
|
|
+ <el-form-item
|
|
|
+ :prop="'flatList.' + scope.$index + '.singlePrice'"
|
|
|
+ :rules="{
|
|
|
+ required: true,
|
|
|
+ message: '请输入单价',
|
|
|
+ trigger: 'change'
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ v-model="scope.row.singlePrice"
|
|
|
+ type="number"
|
|
|
+ :disabled="isView"
|
|
|
+ @input="handlePriceChange(scope.row, scope.$index)"
|
|
|
+ />
|
|
|
+ <!-- <div v-if="isPriceInvalid(scope.row)" class="price-warning">
|
|
|
+ 单价无效,请核对商品价格
|
|
|
+ </div> -->
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-slot:taxRate="scope">
|
|
|
+ <el-form-item
|
|
|
+ :prop="'flatList.' + scope.$index + '.taxRate'"
|
|
|
+ :rules="{
|
|
|
+ required: isTaxRate == 1,
|
|
|
+ message: '请输入税率',
|
|
|
+ trigger: 'change'
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ v-model="scope.row.taxRate"
|
|
|
+ type="number"
|
|
|
+ :disabled="isView"
|
|
|
+ @input="handleTaxChange(scope.row, scope.$index)"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-slot:discountRatio="scope">
|
|
|
+ <el-form-item
|
|
|
+ :prop="'flatList.' + scope.$index + '.discountRatio'"
|
|
|
+ :rules="{
|
|
|
+ required: true,
|
|
|
+ message: '请输入折让比例',
|
|
|
+ trigger: 'change'
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ v-model="scope.row.discountRatio"
|
|
|
+ type="number"
|
|
|
+ :min="0"
|
|
|
+ :max="100"
|
|
|
+ :disabled="isView"
|
|
|
+ @input="handleDiscountChange(scope.row, scope.$index)"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-slot:statementAmount="scope">
|
|
|
+ <span>{{ scope.row.statementAmount }}</span>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-slot:headerRequired="{ column }">
|
|
|
+ <span class="is-required">{{ column.label }}</span>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-slot:action="scope">
|
|
|
+ <el-link
|
|
|
+ v-if="!isView && queryDimension == 2"
|
|
|
+ type="danger"
|
|
|
+ :underline="false"
|
|
|
+ icon="el-icon-delete"
|
|
|
+ @click="removeRow(scope.$index)"
|
|
|
+ >删除</el-link
|
|
|
+ >
|
|
|
+ <span v-else>--</span>
|
|
|
+ </template>
|
|
|
+ </ele-pro-table>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <!-- 批量设置弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ :visible.sync="batchDialogVisible"
|
|
|
+ title="批量设置"
|
|
|
+ width="400px"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <el-form label-width="100px">
|
|
|
+ <el-form-item :label="batchLabel">
|
|
|
+ <el-input v-model="batchValue" type="number" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer">
|
|
|
+ <el-button @click="batchDialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmBatchSet">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 工艺路线选择弹窗 -->
|
|
|
+ <ProductionVersion
|
|
|
+ ref="versionRefs"
|
|
|
+ @changeProduct="changeProduct"
|
|
|
+ ></ProductionVersion>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ import { parameterGetByCode } from '@/api/main/index.js';
|
|
|
+ import { pricingWayList } from '@/enum/dict.js';
|
|
|
+ import ProductionVersion from '@/components/ProductionVersion2/index.vue';
|
|
|
+
|
|
|
+ export default {
|
|
|
+ name: 'accountDetailTable',
|
|
|
+ components: {
|
|
|
+ ProductionVersion
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ datasource: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ },
|
|
|
+ dialogType: {
|
|
|
+ type: String,
|
|
|
+ default: 'add'
|
|
|
+ },
|
|
|
+ queryDimension: {
|
|
|
+ type: Number,
|
|
|
+ default: 1
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ cacheKeyUrl: 'eom-202608171423-account-detail-table',
|
|
|
+ isTaxRate: 0,
|
|
|
+ flatList: [],
|
|
|
+ totalStatementAmount: 0,
|
|
|
+ totalStatementCount: 0,
|
|
|
+ batchDialogVisible: false,
|
|
|
+ batchType: '',
|
|
|
+ batchValue: '',
|
|
|
+ batchLabel: '',
|
|
|
+ columnsVersion: 1,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ isView() {
|
|
|
+ return this.dialogType === 'view';
|
|
|
+ },
|
|
|
+ columns() {
|
|
|
+ let columnsVersion = this.columnsVersion;
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ width: 60,
|
|
|
+ label: '序号',
|
|
|
+ type: 'index',
|
|
|
+ columnKey: 'index',
|
|
|
+ align: 'center',
|
|
|
+ fixed: 'left'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 140,
|
|
|
+ prop: 'orderNo',
|
|
|
+ label: '销售订单编码',
|
|
|
+ align: 'center',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 140,
|
|
|
+ prop: 'statementSubOrderNo',
|
|
|
+ label: this.queryDimension == 1 ? '发货单编码' : '调拨单编码',
|
|
|
+ align: 'center',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'productOperateTime',
|
|
|
+ label: this.queryDimension == 1 ? '发货日期' : '调拨单日期',
|
|
|
+ align: 'center',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'productCode',
|
|
|
+ label: '产品编码',
|
|
|
+ align: 'center',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 140,
|
|
|
+ prop: 'productName',
|
|
|
+ label: '产品名称',
|
|
|
+ align: 'center',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'batchNo',
|
|
|
+ label: '批次号',
|
|
|
+ align: 'center',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ minWidth: 110,
|
|
|
+ prop: 'historicalStatementCount',
|
|
|
+ label: '已对账数量',
|
|
|
+ align: 'center'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 140,
|
|
|
+ headerSlot: 'headerRequired',
|
|
|
+ prop: 'statementCount',
|
|
|
+ label: '本次对账数量',
|
|
|
+ align: 'center',
|
|
|
+ slot: 'statementCount'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ headerSlot: 'headerRequired',
|
|
|
+ prop: 'statementAmount',
|
|
|
+ label: '本次对账金额',
|
|
|
+ align: 'center',
|
|
|
+ slot: 'statementAmount'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'totalCount',
|
|
|
+ label: this.queryDimension == 1 ? '发货数量' : '调拨数量',
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ minWidth: 140,
|
|
|
+ prop: 'technologyRouteName',
|
|
|
+ label: '工艺路线',
|
|
|
+ align: 'center',
|
|
|
+ slot: 'technologyRouteName',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'singlePrice',
|
|
|
+ label: '单价',
|
|
|
+ align: 'center',
|
|
|
+ slot: 'singlePrice'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 100,
|
|
|
+ prop: 'taxRate',
|
|
|
+ label: '税率',
|
|
|
+ align: 'center',
|
|
|
+ slot: 'taxRate'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 100,
|
|
|
+ prop: 'noTaxSinglePrice',
|
|
|
+ label: '不含税单价',
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 100,
|
|
|
+ prop: 'totalPrice',
|
|
|
+ label: '合计',
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ headerSlot: 'headerRequired',
|
|
|
+ prop: 'discountRatio',
|
|
|
+ label: '折让比例',
|
|
|
+ align: 'center',
|
|
|
+ slot: 'discountRatio'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'discountSinglePrice',
|
|
|
+ label: '折让单价',
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'discountTotalPrice',
|
|
|
+ label: '折让合计',
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 100,
|
|
|
+ prop: 'specification',
|
|
|
+ label: '规格',
|
|
|
+ align: 'center',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 100,
|
|
|
+ prop: 'modelType',
|
|
|
+ label: '型号',
|
|
|
+ align: 'center',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 80,
|
|
|
+ prop: 'color',
|
|
|
+ label: '颜色',
|
|
|
+ align: 'center',
|
|
|
+ showOverflowTooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'outInCount',
|
|
|
+ label: '出库数量',
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'measuringUnit',
|
|
|
+ label: '计量单位',
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'sendTotalWeight',
|
|
|
+ label: '出库重量',
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'weightUnit',
|
|
|
+ label: '重量单位',
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ minWidth: 120,
|
|
|
+ prop: 'pricingWay',
|
|
|
+ label: '计价方式',
|
|
|
+ align: 'center',
|
|
|
+ formatter: (row, column) => {
|
|
|
+ return pricingWayList.find((item) => item.id == row.pricingWay)
|
|
|
+ ?.name;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ datasource: {
|
|
|
+ handler(newVal, oldVal) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 直接基于原始 productList 扁平行初始化派生字段(单价/税率/折让比例默认值及本次对账金额)
|
|
|
+ const list = (newVal || []).map((item) => this.buildRow(item, item.orderNo || '', false));
|
|
|
+ this.flatList = list;
|
|
|
+ console.log(this.flatList)
|
|
|
+ this.calcTotals();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
+ },
|
|
|
+ queryDimension() {
|
|
|
+ // this.buildFlatList();
|
|
|
+ this.calcTotals();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ parameterGetByCode({ code: 'eom_saleOrder_order-taxRate' }).then(
|
|
|
+ (res) => {
|
|
|
+ this.isTaxRate = res.value;
|
|
|
+ }
|
|
|
+ );
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ buildRow(item, orderNo, isReturn) {
|
|
|
+ const outboundCount = +item.totalCount || 0;
|
|
|
+ // 退货单数量为负
|
|
|
+ const count = isReturn ? -Math.abs(outboundCount) : outboundCount;
|
|
|
+ const statemented = +item.statementedCount || 0;
|
|
|
+ // 发货单:本次对账数量=出库数量(不可改);调拨单:默认=出库数量(可改)
|
|
|
+ let statementCount = item.statementCount;
|
|
|
+ if (
|
|
|
+ statementCount === undefined ||
|
|
|
+ statementCount === null ||
|
|
|
+ statementCount === ''
|
|
|
+ ) {
|
|
|
+ statementCount = count;
|
|
|
+ }
|
|
|
+ const singlePrice = +item.singlePrice || 0;
|
|
|
+ const discountRatio =
|
|
|
+ item.discountRatio === undefined ||
|
|
|
+ item.discountRatio === null ||
|
|
|
+ item.discountRatio === ''
|
|
|
+ ? 100
|
|
|
+ : +item.discountRatio;
|
|
|
+ const taxRate =
|
|
|
+ item.taxRate === undefined || item.taxRate === null
|
|
|
+ ? 0
|
|
|
+ : +item.taxRate;
|
|
|
+ const amount =
|
|
|
+ Math.round(
|
|
|
+ statementCount * singlePrice * (discountRatio / 100) * 100
|
|
|
+ ) / 100;
|
|
|
+ const noTaxSinglePrice =
|
|
|
+ singlePrice && taxRate
|
|
|
+ ? +((singlePrice / (1 + taxRate / 100)).toFixed(4))
|
|
|
+ : '';
|
|
|
+ const totalPrice = Math.round(statementCount * singlePrice * 100) / 100;
|
|
|
+ const discountSinglePrice =
|
|
|
+ Math.round(singlePrice * (discountRatio / 100) * 100) / 100;
|
|
|
+ const discountTotalPrice =
|
|
|
+ Math.round(totalPrice * (discountRatio / 100) * 100) / 100;
|
|
|
+ // 直接修改原 item,保证编辑同步回 datasource
|
|
|
+ // this.$set(item, 'id', item.id || Math.random().toString(36).slice(2));
|
|
|
+ this.$set(item, 'saleOrderNo', orderNo);
|
|
|
+ this.$set(
|
|
|
+ item,
|
|
|
+ 'statementSubOrderNo',
|
|
|
+ item.statementSubOrderNo || item.subOrderNo || ''
|
|
|
+ );
|
|
|
+ this.$set(
|
|
|
+ item,
|
|
|
+ 'productOperateTime',
|
|
|
+ item.productOperateTime || item.deliveryDate || ''
|
|
|
+ );
|
|
|
+ this.$set(item, 'outboundCount', count);
|
|
|
+ this.$set(item, 'statementedCount', statemented);
|
|
|
+ this.$set(item, 'statementCount', statementCount);
|
|
|
+ this.$set(item, 'singlePrice', singlePrice);
|
|
|
+ this.$set(item, 'taxRate', taxRate);
|
|
|
+ this.$set(item, 'discountRatio', discountRatio);
|
|
|
+ this.$set(item, 'statementAmount', amount);
|
|
|
+ this.$set(item, 'noTaxSinglePrice', noTaxSinglePrice);
|
|
|
+ this.$set(item, 'totalPrice', totalPrice);
|
|
|
+ this.$set(item, 'discountSinglePrice', discountSinglePrice);
|
|
|
+ this.$set(item, 'discountTotalPrice', discountTotalPrice);
|
|
|
+ this.$set(item, 'isReturn', isReturn);
|
|
|
+ this.$set(item, 'processRouteName', item.processRouteName || '');
|
|
|
+ return item;
|
|
|
+ },
|
|
|
+ initDefaultValues() {
|
|
|
+ this.datasource.forEach((item) => {
|
|
|
+ if (item.singlePrice === undefined)
|
|
|
+ this.$set(item, 'singlePrice', 0);
|
|
|
+ if (item.taxRate === undefined) this.$set(item, 'taxRate', 0);
|
|
|
+ if (item.discountRatio === undefined)
|
|
|
+ this.$set(item, 'discountRatio', 100);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ buildFlatList() {
|
|
|
+ const list = [];
|
|
|
+ // this.datasource.forEach((order) => {
|
|
|
+ // const orderNo = order.orderNo || '';
|
|
|
+ // (order.deliveryProducts || []).forEach((item) => {
|
|
|
+ // list.push(this.buildRow(item, orderNo, false));
|
|
|
+ // });
|
|
|
+ // (order.returnProducts || []).forEach((item) => {
|
|
|
+ // list.push(this.buildRow(item, orderNo, true));
|
|
|
+ // });
|
|
|
+ // });
|
|
|
+ // this.flatList = list;
|
|
|
+ },
|
|
|
+ calcTotals() {
|
|
|
+ const amount =
|
|
|
+ this.flatList.reduce(
|
|
|
+ (pre, cur) => pre + Math.round((+cur.statementAmount || 0) * 100),
|
|
|
+ 0
|
|
|
+ ) / 100;
|
|
|
+ const count = this.flatList.reduce(
|
|
|
+ (pre, cur) => pre + (+cur.statementCount || 0),
|
|
|
+ 0
|
|
|
+ );
|
|
|
+ this.totalStatementAmount = amount;
|
|
|
+ this.totalStatementCount = count;
|
|
|
+ this.$emit('totalChange', amount);
|
|
|
+ this.$emit('countChange', count);
|
|
|
+ // 按销售订单编码(saleOrderNo)汇总本次对账金额,供应收信息同步
|
|
|
+ this.emitStatementAmountChange();
|
|
|
+ },
|
|
|
+ // 按销售订单编码汇总本次对账金额并抛出
|
|
|
+ emitStatementAmountChange() {
|
|
|
+ const summaryMap = {};
|
|
|
+ this.flatList.forEach((row) => {
|
|
|
+ const key = row.saleOrderNo;
|
|
|
+ if (!key) return;
|
|
|
+ summaryMap[key] =
|
|
|
+ Math.round(
|
|
|
+ ((summaryMap[key] || 0) + (+row.statementAmount || 0)) * 100
|
|
|
+ ) / 100;
|
|
|
+ });
|
|
|
+ this.$emit('statementAmountChange', summaryMap);
|
|
|
+ },
|
|
|
+ // 重算某一行金额(参考 inventoryTable.vue 价格计算链)
|
|
|
+ calcRow(row) {
|
|
|
+ const count = +row.statementCount || 0;
|
|
|
+ const price = +row.singlePrice || 0;
|
|
|
+ // 折让比例未填写时按 100(不打折)计,避免金额被算成 0
|
|
|
+ const ratio = row.discountRatio === '' ||
|
|
|
+ row.discountRatio === null ||
|
|
|
+ row.discountRatio === undefined ||
|
|
|
+ isNaN(+row.discountRatio)
|
|
|
+ ? 100
|
|
|
+ : +row.discountRatio;
|
|
|
+ const taxRate = +row.taxRate || 0;
|
|
|
+ // 本次对账金额
|
|
|
+ const amount = Math.round(count * price * (ratio / 100) * 100) / 100;
|
|
|
+ this.$set(row, 'statementAmount', amount);
|
|
|
+ // 不含税单价 = 单价 / (1 + 税率/100) (与 inventoryTable.getNotaxSinglePrice 一致)
|
|
|
+ if (price && taxRate) {
|
|
|
+ this.$set(
|
|
|
+ row,
|
|
|
+ 'noTaxSinglePrice',
|
|
|
+ +((price / (1 + taxRate / 100)).toFixed(4))
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ this.$set(row, 'noTaxSinglePrice', '');
|
|
|
+ }
|
|
|
+ // 合计 = 对账数量 * 单价
|
|
|
+ this.$set(row, 'totalPrice', Math.round(count * price * 100) / 100);
|
|
|
+ // 折让单价 = 单价 * 折让比例/100
|
|
|
+ this.$set(
|
|
|
+ row,
|
|
|
+ 'discountSinglePrice',
|
|
|
+ Math.round(price * (ratio / 100) * 100) / 100
|
|
|
+ );
|
|
|
+ // 折让合计 = 合计 * 折让比例/100
|
|
|
+ this.$set(
|
|
|
+ row,
|
|
|
+ 'discountTotalPrice',
|
|
|
+ Math.round(row.totalPrice * (ratio / 100) * 100) / 100
|
|
|
+ );
|
|
|
+ },
|
|
|
+ handleCountChange(row, index) {
|
|
|
+ this.calcRow(row);
|
|
|
+ this.calcTotals();
|
|
|
+ this.emitChange();
|
|
|
+ },
|
|
|
+ handlePriceChange(row, index) {
|
|
|
+ this.calcRow(row);
|
|
|
+ this.calcTotals();
|
|
|
+ this.emitChange();
|
|
|
+ },
|
|
|
+ handleTaxChange(row, index) {
|
|
|
+ // 税率变化需重算不含税单价、合计及折让相关字段
|
|
|
+ this.calcRow(row);
|
|
|
+ this.calcTotals();
|
|
|
+ this.emitChange();
|
|
|
+ },
|
|
|
+ handleDiscountChange(row, index) {
|
|
|
+ this.calcRow(row);
|
|
|
+ this.calcTotals();
|
|
|
+ this.emitChange();
|
|
|
+ },
|
|
|
+ emitChange() {
|
|
|
+ // 表格实际编辑的是 flatList,直接以其为新数据源回写父组件
|
|
|
+ this.$emit('update:datasource', [...this.flatList]);
|
|
|
+ },
|
|
|
+ // 单价校验:单价缺失或为 0 视为无效(需结合商品价目表有效期进一步校验)
|
|
|
+ isPriceInvalid(row) {
|
|
|
+ const price = +row.singlePrice || 0;
|
|
|
+ return price <= 0;
|
|
|
+ },
|
|
|
+ validateStatementCount(rule, value, callback, row) {
|
|
|
+ const val = +value || 0;
|
|
|
+ const max = Math.abs(row.outboundCount || 0);
|
|
|
+ if (Math.abs(val) > max) {
|
|
|
+ callback(new Error('不能超出库数量'));
|
|
|
+ } else if (this.queryDimension == 1 && val != row.outboundCount) {
|
|
|
+ callback(new Error('按发货单查询时不可修改'));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 批量设置
|
|
|
+ batchSetTaxRate() {
|
|
|
+ this.batchType = 'taxRate';
|
|
|
+ this.batchLabel = '税率';
|
|
|
+ this.batchValue = '';
|
|
|
+ this.batchDialogVisible = true;
|
|
|
+ },
|
|
|
+ batchSetPrice() {
|
|
|
+ this.batchType = 'singlePrice';
|
|
|
+ this.batchLabel = '单价';
|
|
|
+ this.batchValue = '';
|
|
|
+ this.batchDialogVisible = true;
|
|
|
+ },
|
|
|
+ batchSetDiscount() {
|
|
|
+ this.batchType = 'discountRatio';
|
|
|
+ this.batchLabel = '折让比例';
|
|
|
+ this.batchValue = '';
|
|
|
+ this.batchDialogVisible = true;
|
|
|
+ },
|
|
|
+ confirmBatchSet() {
|
|
|
+ // flatList 为表格实际渲染的扁平行数据,直接逐行设置并重新计算
|
|
|
+ this.flatList.forEach((item) => {
|
|
|
+ this.$set(item, this.batchType, +this.batchValue);
|
|
|
+ this.calcRow(item);
|
|
|
+ });
|
|
|
+ this.calcTotals();
|
|
|
+ this.batchDialogVisible = false;
|
|
|
+ this.emitChange();
|
|
|
+ },
|
|
|
+ removeRow(index) {
|
|
|
+ // 调拨单模式下允许删除行,基于扁平行数组操作,保持数据格式一致
|
|
|
+ if (index < 0 || index >= this.flatList.length) return;
|
|
|
+ const list = [...this.flatList];
|
|
|
+ list.splice(index, 1);
|
|
|
+ this.flatList = list;
|
|
|
+ this.calcTotals();
|
|
|
+ this.emitChange();
|
|
|
+ },
|
|
|
+ getValidForm() {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ this.$refs.detailForm.validate((valid) => {
|
|
|
+ if (valid) resolve(true);
|
|
|
+ else {
|
|
|
+ this.$message.error('对账明细未填写完整');
|
|
|
+ reject(false);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 打开工艺路线选择弹窗(参考 inventoryTable.openVersion)
|
|
|
+ openVersion(index) {
|
|
|
+ this.$refs.versionRefs.open(index);
|
|
|
+ },
|
|
|
+ // 工艺路线选择回调(参考 inventoryTable.changeProduct)
|
|
|
+ changeProduct(data, index) {
|
|
|
+ if (this.flatList[index]) {
|
|
|
+ this.$set(this.flatList[index], 'technologyRouteName', data.name);
|
|
|
+ this.$set(this.flatList[index], 'technologyRouteId', data.id);
|
|
|
+ this.$set(this.flatList[index], 'technologyRouteVersion', data.version);
|
|
|
+ this.emitChange();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+ .account-detail-table {
|
|
|
+ .detail-toolbar {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-start;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ .summary-info {
|
|
|
+ span {
|
|
|
+ margin-left: 20px;
|
|
|
+ b {
|
|
|
+ color: #f56c6c;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .time-form .el-form-item {
|
|
|
+ margin-bottom: 0 !important;
|
|
|
+ }
|
|
|
+ .price-warning {
|
|
|
+ color: #f56c6c;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 1.4;
|
|
|
+ margin-top: 2px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|