| | |
| | | v-model="formState.no" |
| | | :placeholder="formState.isDefaultNo ? '使用系统编号' : '请输入退料单号'" |
| | | :disabled="formState.isDefaultNo" |
| | | style="width: 240px" |
| | | > |
| | | <template #append> |
| | | <el-checkbox v-model="formState.isDefaultNo" size="large" @change="handleChangeIsDefaultNo" /> |
| | |
| | | :key="item.id" |
| | | :label="item.supplierName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="项目" |
| | | prop="projectId" |
| | | > |
| | | <el-select |
| | | v-model="formState.projectId" |
| | | placeholder="请选择项目" |
| | | style="width: 240px" |
| | | @focus="fetchProjectOptions" |
| | | > |
| | | <el-option |
| | | v-for="item in projectOptions" |
| | | :key="item.id" |
| | | :label="item.name" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | :reserve-keyword="false" |
| | | style="width: 240px" |
| | | @focus="fetchUserOptions" |
| | | @change="formState.preparedUserName = userOptions.find(item => item.userId === formState.preparedUserId)?.nickName || ''" |
| | | > |
| | | <el-option |
| | | v-for="item in userOptions" |
| | |
| | | style="width: 240px" |
| | | :reserve-keyword="false" |
| | | @focus="fetchUserOptions" |
| | | @change="formState.returnUserName = userOptions.find(item => item.userId === formState.returnUserId)?.nickName || ''" |
| | | > |
| | | <el-option |
| | | v-for="item in userOptions" |
| | |
| | | label="备注:" |
| | | prop="remark" |
| | | > |
| | | <el-input v-model="formState.remark" type="textarea" placeholder="请输入备注"/> |
| | | <el-input style="width: 240px" v-model="formState.remark" :rows="1" type="textarea" placeholder="请输入备注"/> |
| | | </el-form-item> |
| | | |
| | | <div style="margin: 20px 0;"> |
| | |
| | | width="70" /> |
| | | <el-table-column label="数量" |
| | | prop="quantity" |
| | | width="70" /> |
| | | width="100" /> |
| | | <el-table-column label="可退货数量" |
| | | prop="availableQuality" |
| | | width="130" /> |
| | | <el-table-column label="退货数量" |
| | | prop="returnQuantity" |
| | | width="180"> |
| | |
| | | <el-input-number v-model="scope.row.returnQuantity" |
| | | controls-position="right" |
| | | :step="1" |
| | | :min="1" |
| | | :max="scope.row.quantity" |
| | | :min="0" |
| | | :max="getReturnQtyMax(scope.row)" |
| | | :disabled="getReturnQtyMax(scope.row) <= 0" |
| | | @change="syncReturnTotal(scope.row)" |
| | | required |
| | | placeholder="请输入退货数量" /> |
| | | </template> |
| | |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="含税总价(元)" |
| | | <el-table-column label="退货总价(元)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="不含税总价(元)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | width="180"> |
| | | <template #default="scope"> |
| | | {{ formatAmount(getReturnTotal(scope.row)) || '--' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="是否质检" |
| | | prop="isChecked" |
| | | width="150"> |
| | |
| | | <el-form-item |
| | | label="成交金额:" |
| | | prop="totalAmount" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请输入成交金额', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-input-number v-model="formState.totalAmount" |
| | | controls-position="right" |
| | | :step="0.01" |
| | | :precision="2" |
| | | style="width: 100%;" |
| | | @change="handleChangeTotalAmount" |
| | | placeholder="请输入成交金额"/> |
| | | </el-form-item> |
| | | <el-form-item label="收款方式" prop="incomeType" :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请选择收款方式', |
| | | trigger: 'change', |
| | | } |
| | | ]"> |
| | | <el-select |
| | | style="width: 240px;" |
| | | v-model="formState.incomeType" |
| | | placeholder="请选择" |
| | | clearable |
| | | |
| | | > |
| | | <el-option :label="item.label" :value="item.value" v-for="(item,index) in payment_methods" :key="index" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, getCurrentInstance} from "vue"; |
| | | import {ref, computed, getCurrentInstance, watch, defineAsyncComponent} from "vue"; |
| | | import {createPurchaseReturnOrder} from "@/api/procurementManagement/purchase_return_order.js"; |
| | | import {getOptions, purchaseList} from "@/api/procurementManagement/procurementLedger.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | const ProductList = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/ProductList.vue")); |
| | | import { |
| | | productList, |
| | | } from "@/api/procurementManagement/procurementLedger.js"; |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | |
| | | } |
| | | }); |
| | | let { proxy } = getCurrentInstance() |
| | | const { payment_methods } = proxy.useDict("payment_methods"); |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | // 响应式数据(替代选项式的 data) |
| | |
| | | no: '', |
| | | isDefaultNo: true, |
| | | returnType: 0, |
| | | incomeType: undefined, |
| | | remark: '', |
| | | supplierId: undefined, |
| | | projectId: undefined, |
| | |
| | | }); |
| | | // 供应商选项 |
| | | const supplierOptions = ref([]) |
| | | // 项目选项 |
| | | const projectOptions = ref([]) |
| | | // 项目阶段选项 |
| | | const projectStageOptions = ref([ |
| | | { |
| | |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | |
| | | const formatAmount = (value) => { |
| | | if (value === null || value === undefined || value === '') { |
| | | return '--' |
| | | } |
| | | const num = Number(value) |
| | | if (Number.isNaN(num)) { |
| | | return '--' |
| | | } |
| | | return num.toFixed(2) |
| | | } |
| | | |
| | | const toNumber = (val) => { |
| | | const num = Number(val) |
| | | return Number.isNaN(num) ? 0 : num |
| | | } |
| | | |
| | | const getReturnTotal = (row) => { |
| | | const qty = toNumber(row?.returnQuantity) |
| | | const unitPrice = toNumber(row?.taxInclusiveUnitPrice) |
| | | const total = qty * unitPrice |
| | | return Number(total.toFixed(2)) |
| | | } |
| | | |
| | | const syncReturnTotal = (row) => { |
| | | if (!row) { |
| | | return |
| | | } |
| | | row.taxInclusiveTotalPrice = getReturnTotal(row) |
| | | } |
| | | |
| | | const getReturnQtyMax = (row) => { |
| | | const max = Number(row?.availableQuality) |
| | | if (Number.isNaN(max) || max < 0) { |
| | | return 0 |
| | | } |
| | | return max |
| | | } |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | |
| | | param, |
| | | [ |
| | | "quantity", |
| | | "availableQuality", |
| | | "returnQuantity", |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | |
| | | { |
| | | quantity: { noDecimal: true }, // 不保留小数 |
| | | returnQuantity: { noDecimal: true }, // 不保留小数 |
| | | availableQuality: { noDecimal: true }, // 不保留小数 |
| | | } |
| | | ); |
| | | }; |
| | | |
| | | const handleChangeTotalDiscountAmount= () => { |
| | | formState.value.totalAmount = formState.value.totalDiscountAmount * -1 |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | const handleChangeTotalAmount= () => { |
| | | formState.value.totalDiscountAmount = formState.value.totalAmount * -1 |
| | | const syncTotalAmount = () => { |
| | | const rows = formState.value.purchaseReturnOrderProductsDtos || [] |
| | | const baseAmount = rows.reduce((sum, item) => { |
| | | return sum + toNumber(item.taxInclusiveTotalPrice) |
| | | }, 0) |
| | | const discount = toNumber(formState.value.totalDiscountAmount) |
| | | // 成交金额 = 产品退货总价合计 - 折扣额 |
| | | formState.value.totalAmount = Number((baseAmount - discount).toFixed(2)) |
| | | } |
| | | |
| | | // 获取供应商选项 |
| | |
| | | }); |
| | | } |
| | | |
| | | // 获取项目选项 |
| | | const fetchProjectOptions = () => { |
| | | if (projectOptions.value.length > 0) { |
| | | return |
| | | } |
| | | // todo 项目选项 |
| | | } |
| | | |
| | | // 获取用户选项 |
| | | const fetchUserOptions = () => { |
| | |
| | | // 处理改变供应商数据 |
| | | const handleChangeSupplierId = () => { |
| | | formState.value.purchaseLedgerId = undefined |
| | | formState.value.supplierName = supplierOptions.value.find(item => item.id === formState.value.supplierId)?.supplierName || '' |
| | | fetchPurchaseLedgerOptions() |
| | | } |
| | | |
| | |
| | | const fetchPurchaseLedgerOptions = () => { |
| | | purchaseLedgerOptions.value = [] |
| | | if (formState.value.supplierId) { |
| | | purchaseList({supplierId: formState.value.supplierId}).then((res) => { |
| | | purchaseList({supplierId: formState.value.supplierId,approvalStatus:3}).then((res) => { |
| | | purchaseLedgerOptions.value = res.rows; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // 处理改变采购台账数据 |
| | | const handleChangePurchaseLedgerId = () => { |
| | | formState.value.purchaseReturnOrderProductsDtos = [] |
| | | const handleChangePurchaseLedgerId = async () => { |
| | | const res = await productList({ salesLedgerId: formState.value.purchaseLedgerId, type: 2 }); |
| | | formState.value.purchaseReturnOrderProductsDtos = res.data.map(item => ({ |
| | | ...item, |
| | | returnQuantity: undefined, |
| | | taxInclusiveTotalPrice: 0, |
| | | salesLedgerProductId: item.id, |
| | | })) |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | // 处理改变是否默认编号 |
| | |
| | | const newProducts = selectedRows.filter(item => !existingIds.has(item.id)).map(item => ({ |
| | | ...item, |
| | | returnQuantity: undefined, |
| | | taxInclusiveTotalPrice: 0, |
| | | salesLedgerProductId: item.id, |
| | | })); |
| | | formState.value.purchaseReturnOrderProductsDtos.push(...newProducts); |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | // 删除单项产品 |
| | | const delProduct = (index) => { |
| | | formState.value.purchaseReturnOrderProductsDtos.splice(index, 1) |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | // 提交表单 |
| | | const handleSubmit = () => { |
| | | // 验证退货数量 |
| | | const hasEmptyReturnQuantity = formState.value.purchaseReturnOrderProductsDtos.some(item => !item.returnQuantity || item.returnQuantity <= 0); |
| | | if (hasEmptyReturnQuantity) { |
| | | proxy.$modal.msgError("请为所有产品填写退货数量"); |
| | | return; |
| | | const productList = formState.value.purchaseReturnOrderProductsDtos || [] |
| | | |
| | | productList.forEach(syncReturnTotal) |
| | | |
| | | if (productList.length === 0) { |
| | | proxy.$modal.msgError("请先选择产品") |
| | | return |
| | | } |
| | | |
| | | // 逐行校验退货数量:任意一行未填/非法/超限都不允许提交 |
| | | const invalidRowIndex = productList.findIndex((item) => { |
| | | const qty = Number(item.returnQuantity) |
| | | const maxQty = Number(item.availableQuality) |
| | | |
| | | if (item.returnQuantity === null || item.returnQuantity === undefined || item.returnQuantity === "") { |
| | | return true |
| | | } |
| | | if (Number.isNaN(qty) || qty <= 0) { |
| | | return true |
| | | } |
| | | if (!Number.isNaN(maxQty) && maxQty > 0 && qty > maxQty) { |
| | | return true |
| | | } |
| | | return false |
| | | }) |
| | | |
| | | if (invalidRowIndex !== -1) { |
| | | proxy.$modal.msgError(`第${invalidRowIndex + 1}行退货数量未填写或不合法`) |
| | | return |
| | | } |
| | | |
| | | proxy.$refs["formRef"].validate(valid => { |
| | |
| | | }) |
| | | }; |
| | | |
| | | watch( |
| | | () => formState.value.purchaseReturnOrderProductsDtos, |
| | | (rows) => { |
| | | (rows || []).forEach(syncReturnTotal) |
| | | syncTotalAmount() |
| | | }, |
| | | { deep: true } |
| | | ) |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |