|
|
|
|
@ -18,7 +18,7 @@
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
<el-card shadow="never" class="mb-[15px]" header="开票信息">
|
|
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="130px" status-icon>
|
|
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="130px" status-icon :disabled="isFormDisabled">
|
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
<!-- 第一行 -->
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
@ -166,7 +166,6 @@
|
|
|
|
|
prop="ossId"
|
|
|
|
|
v-if="routeParams.type === 'update' || routeParams.type === 'view' || routeParams.type === 'approval'"
|
|
|
|
|
>
|
|
|
|
|
<!-- <el-button type="primary" plain icon="Upload" @click="handleFile">上传合同附件</el-button>-->
|
|
|
|
|
<FileUpload
|
|
|
|
|
v-model="ossIdString"
|
|
|
|
|
:limit="5"
|
|
|
|
|
@ -186,15 +185,29 @@
|
|
|
|
|
<div class="flex justify-between items-center">
|
|
|
|
|
<span class="font-medium">开票明细</span>
|
|
|
|
|
<div>
|
|
|
|
|
<el-button type="primary" plain size="small" icon="Plus" @click="handleAddItem">新增明细</el-button>
|
|
|
|
|
<el-button type="danger" plain size="small" icon="Delete" @click="handleDeleteItems" :disabled="selectedItems.length === 0"
|
|
|
|
|
<el-button type="primary" plain size="small" icon="Plus" @click="handleAddItem" :disabled="isFormDisabled">新增明细</el-button>
|
|
|
|
|
<el-button
|
|
|
|
|
type="danger"
|
|
|
|
|
plain
|
|
|
|
|
size="small"
|
|
|
|
|
icon="Delete"
|
|
|
|
|
@click="handleDeleteItems"
|
|
|
|
|
:disabled="isFormDisabled || selectedItems.length === 0"
|
|
|
|
|
>删除
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<el-table :data="form.erpFinInvoiceDetailList" border stripe @selection-change="handleSelectionChange" max-height="400">
|
|
|
|
|
<el-table
|
|
|
|
|
:data="form.erpFinInvoiceDetailList"
|
|
|
|
|
border
|
|
|
|
|
stripe
|
|
|
|
|
@selection-change="handleSelectionChange"
|
|
|
|
|
max-height="400"
|
|
|
|
|
:header-cell-style="{ textAlign: 'center' }"
|
|
|
|
|
:cell-style="{ textAlign: 'center' }"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="selection" width="55" align="center" />
|
|
|
|
|
<el-table-column label="序号" type="index" width="60" align="center" />
|
|
|
|
|
<el-table-column label="开票内容" prop="billingItems" min-width="160">
|
|
|
|
|
@ -224,30 +237,53 @@
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="税率(%)" prop="taxRate" width="145">
|
|
|
|
|
<el-table-column label="税率(%)" prop="taxRate" width="110">
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<el-input-number v-model="row.taxRate" :min="0" :max="100" :precision="2" controls-position="right" style="width: 120px" />
|
|
|
|
|
<el-select
|
|
|
|
|
v-model="row.taxRate"
|
|
|
|
|
filterable
|
|
|
|
|
allow-create
|
|
|
|
|
default-first-option
|
|
|
|
|
clearable
|
|
|
|
|
placeholder="税率"
|
|
|
|
|
style="width: 80px"
|
|
|
|
|
@change="calculateItemAmount($index)"
|
|
|
|
|
>
|
|
|
|
|
<el-option v-for="rate in taxRateOptions" :key="rate" :label="`${rate}`" :value="rate" />
|
|
|
|
|
</el-select>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<el-table-column label="单价(含税)" prop="unitPrice" width="145">
|
|
|
|
|
<el-table-column label="单价(含税)" prop="unitPrice" width="100">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<span class="text-red-500 font-medium">{{ formatAmount(row.unitPrice) }}</span>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="金额(含税)" prop="totalPrice" width="145">
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<el-input-number
|
|
|
|
|
v-model="row.unitPrice"
|
|
|
|
|
v-model="row.totalPrice"
|
|
|
|
|
:min="0"
|
|
|
|
|
:precision="2"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
@change="calculateItemAmount($index)"
|
|
|
|
|
@change="calculateItemAmountByTotal($index)"
|
|
|
|
|
style="width: 120px"
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="金额(含税)" prop="totalPrice" width="140">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<span class="text-red-500 font-medium">{{ row.totalPrice?.toFixed(2) || '0.00' }}</span>
|
|
|
|
|
<el-table-column label="金额(不含税)" prop="totalPriceNoTax" width="150">
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<el-input-number
|
|
|
|
|
v-model="row.totalPriceNoTax"
|
|
|
|
|
:min="0"
|
|
|
|
|
:precision="2"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
@change="calculateItemAmountByNoTax($index)"
|
|
|
|
|
style="width: 120px"
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="操作" fixed="right" width="80" align="center">
|
|
|
|
|
<el-table-column v-if="!isFormDisabled" label="操作" fixed="right" width="80" align="center">
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<el-button link type="danger" icon="Delete" @click="handleRemoveItem($index, row)" />
|
|
|
|
|
</template>
|
|
|
|
|
@ -311,7 +347,7 @@ import {
|
|
|
|
|
} from '@/api/oa/erp/finInvoiceInfo';
|
|
|
|
|
import { FinInvoiceInfoForm, FinInvoiceInfoQuery } from '@/api/oa/erp/finInvoiceInfo/types';
|
|
|
|
|
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
|
|
|
|
import { FinInvoiceDetailVO } from '@/api/oa/erp/finInvoiceDetail/types';
|
|
|
|
|
import { FinInvoiceDetailForm, FinInvoiceDetailVO } from '@/api/oa/erp/finInvoiceDetail/types';
|
|
|
|
|
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
|
|
|
|
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
|
|
|
|
import { DeptTreeVO } from '@/api/system/dept/types';
|
|
|
|
|
@ -350,13 +386,20 @@ const EARLY_FLAG = reactive({
|
|
|
|
|
NO: '0' //否
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const FLOW_STATUS = reactive({
|
|
|
|
|
DRAFT: 'draft',
|
|
|
|
|
WAITING: 'waiting'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const CONTRACT_FLAG = {
|
|
|
|
|
YES: '1',
|
|
|
|
|
NO: '2'
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const hasInvoiceAttachPer = checkPermi(['oa/erp:finInvoiceInfo:invoiceAttach']);
|
|
|
|
|
console.log(hasInvoiceAttachPer);
|
|
|
|
|
const isFormDisabled = computed(() => {
|
|
|
|
|
return routeParams.value.type === 'view' || routeParams.value.type === 'approval' || form.value.flowStatus === FLOW_STATUS.WAITING;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 弹窗可见性
|
|
|
|
|
const projectSelectDialogVisible = ref(false);
|
|
|
|
|
@ -367,11 +410,19 @@ const userDialogVisible = ref(false);
|
|
|
|
|
const selectedItems = ref<FinInvoiceDetailVO[]>([]);
|
|
|
|
|
|
|
|
|
|
const toDeletedInvoiceDetailIdList = ref([]);
|
|
|
|
|
const taxRateOptions = [0, 3, 9, 13];
|
|
|
|
|
const getTodayDateString = () => {
|
|
|
|
|
const now = new Date();
|
|
|
|
|
const year = now.getFullYear();
|
|
|
|
|
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
|
|
|
const day = String(now.getDate()).padStart(2, '0');
|
|
|
|
|
return `${year}-${month}-${day}`;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const initFormData: FinInvoiceInfoForm = {
|
|
|
|
|
invoiceId: undefined,
|
|
|
|
|
invoiceCode: undefined,
|
|
|
|
|
earlyFlag: undefined,
|
|
|
|
|
earlyFlag: EARLY_FLAG.NO,
|
|
|
|
|
invoiceType: undefined,
|
|
|
|
|
issueAmount: undefined,
|
|
|
|
|
issuancePercentage: undefined,
|
|
|
|
|
@ -398,12 +449,15 @@ const initFormData: FinInvoiceInfoForm = {
|
|
|
|
|
invoiceStatus: undefined,
|
|
|
|
|
remark: undefined,
|
|
|
|
|
earlyReason: undefined,
|
|
|
|
|
issueDate: getTodayDateString(),
|
|
|
|
|
erpFinInvoiceDetailList: []
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const data = reactive<PageData<FinInvoiceInfoForm, FinInvoiceInfoQuery>>({
|
|
|
|
|
form: { ...initFormData },
|
|
|
|
|
queryParams: {
|
|
|
|
|
pageNum: undefined,
|
|
|
|
|
pageSize: undefined,
|
|
|
|
|
params: {}
|
|
|
|
|
},
|
|
|
|
|
rules: {
|
|
|
|
|
@ -434,16 +488,12 @@ watch(
|
|
|
|
|
// 使用 ?? 将 null 和 undefined 都统一为 'empty' 字符串
|
|
|
|
|
|
|
|
|
|
// 如果 ossId 从无到有,或者从有到无,或者值改变 (只在初始化完成后,并且值确实发生变化时才执行)
|
|
|
|
|
if (isInitialized.value) {
|
|
|
|
|
if (isInitialized.value && form.value.invoiceId) {
|
|
|
|
|
const normalizedOld = oldVal ?? 'empty';
|
|
|
|
|
const normalizedNew = newVal ?? 'empty';
|
|
|
|
|
|
|
|
|
|
console.log(normalizedOld + '---' + normalizedNew);
|
|
|
|
|
if (normalizedOld !== normalizedNew) {
|
|
|
|
|
try {
|
|
|
|
|
buttonLoading.value = true;
|
|
|
|
|
console.log('附件发生变化,旧值:', oldVal, '新值:', newVal);
|
|
|
|
|
|
|
|
|
|
// 更新数据库
|
|
|
|
|
const invoiceAttachForm = {
|
|
|
|
|
invoiceId: form.value.invoiceId,
|
|
|
|
|
@ -460,13 +510,19 @@ watch(
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const getUserList = async () => {
|
|
|
|
|
const query = {};
|
|
|
|
|
const query = {} as any;
|
|
|
|
|
const res = await api.getUserList(query);
|
|
|
|
|
userOptions.value = res.data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleUserChange = async (newUserId) => {
|
|
|
|
|
const userOption = userOptions.value.find((item) => item.userId == newUserId);
|
|
|
|
|
if (!userOption) {
|
|
|
|
|
form.value.requestDeptName = undefined;
|
|
|
|
|
form.value.requestDept = undefined;
|
|
|
|
|
form.value.requestByName = undefined;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
form.value.requestDeptName = userOption.deptName;
|
|
|
|
|
form.value.requestDept = userOption.deptId;
|
|
|
|
|
form.value.requestByName = userOption.nickName;
|
|
|
|
|
@ -478,7 +534,7 @@ const getContractPaymentMethods = async (contractId) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const paymentDescription = computed(() => {
|
|
|
|
|
return contractPaymentMethodVoList.value.map((item) => `${item.paymentDescription}`).join('.'); // 使用.连接
|
|
|
|
|
return contractPaymentMethodVoList.value.map((item) => `${item.paymentDescription}`).join('');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/** 查询部门下拉树结构 */
|
|
|
|
|
@ -503,7 +559,7 @@ const filterDisabledDept = (deptList: DeptTreeVO[]) => {
|
|
|
|
|
|
|
|
|
|
// 计算合计金额 - 自动更新 issueAmount 和 issuancePercentage
|
|
|
|
|
const totalInvoiceAmount = computed(() => {
|
|
|
|
|
const total = form.value.erpFinInvoiceDetailList.reduce((sum, item) => sum + (item.totalPrice || 0), 0).toFixed(2);
|
|
|
|
|
const total = Number(form.value.erpFinInvoiceDetailList.reduce((sum, item) => sum + (item.totalPrice || 0), 0).toFixed(2));
|
|
|
|
|
|
|
|
|
|
// 更新开票金额
|
|
|
|
|
form.value.issueAmount = total;
|
|
|
|
|
@ -583,21 +639,22 @@ const initByContractId = async () => {
|
|
|
|
|
const isInitialized = ref(false);
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
nextTick(async () => {
|
|
|
|
|
getUserList(); // 初始化用户数据
|
|
|
|
|
await getUserList(); // 初始化用户数据
|
|
|
|
|
// 获取路由参数
|
|
|
|
|
routeParams.value = route.query;
|
|
|
|
|
console.log(route.query);
|
|
|
|
|
const id = routeParams.value.id as string | number;
|
|
|
|
|
try {
|
|
|
|
|
proxy?.$modal.loading('正在加载数据,请稍后...');
|
|
|
|
|
if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
|
|
|
|
|
const res = await getFinInvoiceInfo(id);
|
|
|
|
|
console.log(res);
|
|
|
|
|
Object.assign(form.value, res.data);
|
|
|
|
|
Object.assign(form.value.erpFinInvoiceDetailList, res.data.erpFinInvoiceDetailVoList);
|
|
|
|
|
form.value.erpFinInvoiceDetailList = res.data.erpFinInvoiceDetailVoList || [];
|
|
|
|
|
form.value.erpFinInvoiceDetailList.forEach((_, index) => calculateItemAmountByTotal(index));
|
|
|
|
|
} else {
|
|
|
|
|
const res = await getBaseInfo();
|
|
|
|
|
Object.assign(form.value, res.data);
|
|
|
|
|
form.value.earlyFlag = form.value.earlyFlag || EARLY_FLAG.NO;
|
|
|
|
|
form.value.issueDate = form.value.issueDate || getTodayDateString();
|
|
|
|
|
await initByContractId();
|
|
|
|
|
handleAddItem();
|
|
|
|
|
}
|
|
|
|
|
@ -690,14 +747,18 @@ const handleUserSelected = () => {
|
|
|
|
|
// 表格操作
|
|
|
|
|
const handleAddItem = () => {
|
|
|
|
|
form.value.erpFinInvoiceDetailList.push({
|
|
|
|
|
invoiceDetailId: undefined,
|
|
|
|
|
invoiceId: undefined,
|
|
|
|
|
billingItems: '',
|
|
|
|
|
specificationModel: '',
|
|
|
|
|
unitName: '',
|
|
|
|
|
quantity: undefined,
|
|
|
|
|
taxRate: undefined,
|
|
|
|
|
unitPrice: undefined,
|
|
|
|
|
totalPrice: 0
|
|
|
|
|
});
|
|
|
|
|
totalPrice: 0,
|
|
|
|
|
totalPriceNoTax: 0,
|
|
|
|
|
taxPrice: undefined
|
|
|
|
|
} as FinInvoiceDetailForm as FinInvoiceDetailVO);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleRemoveItem = (index: number, row: FinInvoiceDetailVO) => {
|
|
|
|
|
@ -725,14 +786,57 @@ const handleSelectionChange = (selection: FinInvoiceDetailVO[]) => {
|
|
|
|
|
selectedItems.value = selection;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 计算单个明细的金额
|
|
|
|
|
const formatAmount = (value?: number) => {
|
|
|
|
|
return value !== undefined && value !== null ? Number(value).toFixed(2) : '0.00';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const roundAmount = (value?: number) => {
|
|
|
|
|
if (value === undefined || value === null || Number.isNaN(Number(value))) {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
return Number(Number(value).toFixed(2));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const calculateTaxAmounts = (item: FinInvoiceDetailVO) => {
|
|
|
|
|
const totalPrice = roundAmount(item.totalPrice) || 0;
|
|
|
|
|
const taxRate = Number(item.taxRate || 0);
|
|
|
|
|
const divisor = 1 + taxRate / 100;
|
|
|
|
|
item.totalPriceNoTax = roundAmount(totalPrice / divisor) || 0;
|
|
|
|
|
item.taxPrice = roundAmount(totalPrice - (item.totalPriceNoTax || 0)) || 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 通过数量和金额(含税)回算单价
|
|
|
|
|
const calculateItemAmount = (index: number) => {
|
|
|
|
|
const item = form.value.erpFinInvoiceDetailList[index];
|
|
|
|
|
if (item.quantity && item.unitPrice) {
|
|
|
|
|
item.totalPrice = Number((item.quantity * item.unitPrice).toFixed(2));
|
|
|
|
|
if (item.quantity && item.totalPrice !== undefined && item.totalPrice !== null) {
|
|
|
|
|
item.unitPrice = roundAmount(item.totalPrice / item.quantity);
|
|
|
|
|
} else {
|
|
|
|
|
item.totalPrice = 0;
|
|
|
|
|
item.unitPrice = undefined;
|
|
|
|
|
}
|
|
|
|
|
calculateTaxAmounts(item);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const calculateItemAmountByTotal = (index: number) => {
|
|
|
|
|
calculateItemAmount(index);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const calculateItemAmountByNoTax = (index: number) => {
|
|
|
|
|
const item = form.value.erpFinInvoiceDetailList[index];
|
|
|
|
|
const noTaxAmount = roundAmount(item.totalPriceNoTax);
|
|
|
|
|
if (noTaxAmount === undefined) {
|
|
|
|
|
item.totalPrice = 0;
|
|
|
|
|
item.unitPrice = undefined;
|
|
|
|
|
item.taxPrice = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const taxRate = Number(item.taxRate || 0);
|
|
|
|
|
item.totalPrice = roundAmount(noTaxAmount * (1 + taxRate / 100)) || 0;
|
|
|
|
|
if (item.quantity && item.quantity > 0) {
|
|
|
|
|
item.unitPrice = roundAmount((item.totalPrice || 0) / item.quantity);
|
|
|
|
|
} else {
|
|
|
|
|
item.unitPrice = undefined;
|
|
|
|
|
}
|
|
|
|
|
item.taxPrice = roundAmount((item.totalPrice || 0) - noTaxAmount) || 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 明细变更时触发计算
|
|
|
|
|
@ -740,6 +844,50 @@ const handleItemChange = (index: number) => {
|
|
|
|
|
calculateItemAmount(index);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const buildInvoiceDetailError = (): string | null => {
|
|
|
|
|
if (!form.value.erpFinInvoiceDetailList.length) {
|
|
|
|
|
return '请至少添加一条开票明细';
|
|
|
|
|
}
|
|
|
|
|
for (let index = 0; index < form.value.erpFinInvoiceDetailList.length; index++) {
|
|
|
|
|
const item = form.value.erpFinInvoiceDetailList[index];
|
|
|
|
|
const rowNo = index + 1;
|
|
|
|
|
if (!item.billingItems) {
|
|
|
|
|
return `第${rowNo}行开票内容不能为空`;
|
|
|
|
|
}
|
|
|
|
|
if (!item.unitName) {
|
|
|
|
|
return `第${rowNo}行单位不能为空`;
|
|
|
|
|
}
|
|
|
|
|
if (item.taxRate === undefined || item.taxRate === null) {
|
|
|
|
|
return `第${rowNo}行税率不能为空`;
|
|
|
|
|
}
|
|
|
|
|
if (!item.quantity || item.quantity <= 0) {
|
|
|
|
|
return `第${rowNo}行数量必须大于0`;
|
|
|
|
|
}
|
|
|
|
|
if (!item.totalPrice || item.totalPrice <= 0) {
|
|
|
|
|
return `第${rowNo}行金额(含税)必须大于0`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const normalizeInvoiceForm = (): FinInvoiceInfoForm => {
|
|
|
|
|
const invoiceForm: FinInvoiceInfoForm = {
|
|
|
|
|
...form.value,
|
|
|
|
|
invoiceStatus: getInvoiceStatus(buttonStatus.value),
|
|
|
|
|
flowStatus: getFlowStatus(buttonStatus.value),
|
|
|
|
|
toDeletedInvoiceDetailIdList: [...toDeletedInvoiceDetailIdList.value]
|
|
|
|
|
};
|
|
|
|
|
if (invoiceForm.earlyFlag === EARLY_FLAG.YES) {
|
|
|
|
|
invoiceForm.acceptanceDate = undefined;
|
|
|
|
|
invoiceForm.deliveryDate = undefined;
|
|
|
|
|
} else {
|
|
|
|
|
invoiceForm.earlyReason = undefined;
|
|
|
|
|
}
|
|
|
|
|
return invoiceForm;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const buttonStatus = ref('draft');
|
|
|
|
|
|
|
|
|
|
// 审批相关组件引用
|
|
|
|
|
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
|
|
|
|
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
|
|
|
|
@ -763,59 +911,35 @@ const approvalVerifyOpen = async () => {
|
|
|
|
|
// 保存
|
|
|
|
|
const handleSave = async (status: string, mode: boolean) => {
|
|
|
|
|
if (!formRef.value) return;
|
|
|
|
|
buttonStatus.value = status;
|
|
|
|
|
try {
|
|
|
|
|
await formRef.value.validate();
|
|
|
|
|
} catch {
|
|
|
|
|
ElMessage.warning('请先完善必填信息后再提交');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const detailError = buildInvoiceDetailError();
|
|
|
|
|
if (detailError) {
|
|
|
|
|
ElMessage.warning(detailError);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (form.value.returnedMoney && form.value.totalPrice && form.value.returnedMoney > form.value.totalPrice) {
|
|
|
|
|
ElMessage.warning('累计回款金额不能大于合同金额');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const invoiceForm = normalizeInvoiceForm();
|
|
|
|
|
try {
|
|
|
|
|
buttonLoading.value = true;
|
|
|
|
|
await formRef.value.validate(async (valid) => {
|
|
|
|
|
if (valid) {
|
|
|
|
|
if (form.value.erpFinInvoiceDetailList.length === 0) {
|
|
|
|
|
ElMessage.warning('请至少添加一条开票明细');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查明细是否有空项
|
|
|
|
|
const hasEmpty = form.value.erpFinInvoiceDetailList.some(
|
|
|
|
|
(item) => !item.billingItems || !item.unitName || !item.taxRate || item.quantity <= 0 || item.unitPrice <= 0
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (hasEmpty) {
|
|
|
|
|
ElMessage.warning('请填写完整的开票明细信息');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验证累计回款金额不能大于合同金额
|
|
|
|
|
if (form.value.returnedMoney && form.value.totalPrice && form.value.returnedMoney > form.value.totalPrice) {
|
|
|
|
|
ElMessage.warning('累计回款金额不能大于合同金额');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (form.value.earlyFlag === EARLY_FLAG.YES) {
|
|
|
|
|
form.value.acceptanceDate = undefined;
|
|
|
|
|
form.value.deliveryDate = undefined;
|
|
|
|
|
} else {
|
|
|
|
|
form.value.earlyReason = undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const invoiceForm = {
|
|
|
|
|
...form.value,
|
|
|
|
|
// 设置状态
|
|
|
|
|
invoiceStatus: getInvoiceStatus(status),
|
|
|
|
|
flowStatus: getFlowStatus(status),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 调用保存接口
|
|
|
|
|
if (form.value.invoiceId) {
|
|
|
|
|
form.value.toDeletedInvoiceDetailIdList = toDeletedInvoiceDetailIdList.value;
|
|
|
|
|
await updateFinInvoiceInfo(invoiceForm);
|
|
|
|
|
} else {
|
|
|
|
|
await addFinInvoiceInfo(invoiceForm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ElMessage.success('保存成功');
|
|
|
|
|
// 返回列表页
|
|
|
|
|
goBack();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (form.value.invoiceId) {
|
|
|
|
|
await updateFinInvoiceInfo(invoiceForm);
|
|
|
|
|
} else {
|
|
|
|
|
await addFinInvoiceInfo(invoiceForm);
|
|
|
|
|
}
|
|
|
|
|
ElMessage.success(status === 'draft' ? '暂存成功' : '提交成功');
|
|
|
|
|
goBack();
|
|
|
|
|
} finally {
|
|
|
|
|
buttonLoading.value = false;
|
|
|
|
|
}
|
|
|
|
|
|