| | |
| | | width="100px" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | v-if="scope.row.approveStatus === 1 && scope.row.noQuantity !== 0" |
| | | <el-tag v-if="scope.row.approveStatus === 1 " |
| | | type="success">充足 |
| | | </el-tag> |
| | | <el-tag |
| | | v-else-if="scope.row.approveStatus === 0 && scope.row.noQuantity === 0" |
| | | <el-tag v-else-if="scope.row.approveStatus === 0 && scope.row.noQuantity === 0" |
| | | type="success">已出库 |
| | | </el-tag> |
| | | <el-tag v-else |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="销售合同号:" |
| | | prop="salesContractNo"> |
| | | <div style="display: flex; align-items: center; gap: 12px;width: 100%;"> |
| | | <el-checkbox v-model="form.autoGenerateContractNo" v-if="operationType === 'add'">自动生成 |
| | | </el-checkbox> |
| | | <el-input v-model="form.salesContractNo" |
| | | placeholder="自动生成" |
| | | :placeholder="form.autoGenerateContractNo ? '自动生成' : '请输入'" |
| | | clearable |
| | | disabled/> |
| | | :disabled="form.autoGenerateContractNo" /> |
| | | |
| | | </div> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="calculateFromTaxRate"> |
| | | <el-option |
| | | v-for="dict in tax_rate" |
| | | <el-option v-for="dict in tax_rate" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | :value="dict.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </FormDialog> |
| | | <!-- // todo 附件预览相关 --> |
| | | <!-- 附件列表弹窗 --> |
| | | <FileList v-if="fileDialogVisible" v-model:visible="fileDialogVisible" record-type="sales_ledger" |
| | | <FileList v-if="fileDialogVisible" |
| | | v-model:visible="fileDialogVisible" |
| | | record-type="sales_ledger" |
| | | :record-id="recordId"/> |
| | | <!-- 打印预览弹窗 --> |
| | | <el-dialog v-model="printPreviewVisible" |
| | |
| | | prop="type"> |
| | | <el-select v-model="deliveryForm.type" |
| | | placeholder="请选择发货类型" |
| | | style="width: 100%"> |
| | | style="width: 100%" |
| | | @change="handleDeliveryTypeChange"> |
| | | <el-option label="货车" |
| | | value="货车"/> |
| | | <el-option label="快递" |
| | | value="快递"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="待发货数量:"> |
| | | <el-input :model-value="currentDeliveryRow?.noQuantity" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24" v-if="deliveryForm.type === '货车'"> |
| | | <el-form-item label="发货车牌号:" |
| | | prop="shippingCarNumber"> |
| | | <el-input v-model="deliveryForm.shippingCarNumber" |
| | | placeholder="请输入发货车牌号" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24" v-else> |
| | | <el-form-item label="快递公司:" |
| | | prop="expressCompany"> |
| | | <el-input v-model="deliveryForm.expressCompany" |
| | | placeholder="请输入快递公司" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30" v-if="deliveryForm.type === '快递'"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="快递单号:" |
| | | prop="expressNumber"> |
| | | <el-input v-model="deliveryForm.expressNumber" |
| | | placeholder="请输入快递单号" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="发货图片:"> |
| | | <ImageUpload v-model:file-list="deliveryFileList" :limit="9" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-table-column label="批号" |
| | | prop="batchNo" |
| | | min-width="180"/> |
| | | <el-table-column label="数量" |
| | | <el-table-column label="库存数量" |
| | | min-width="120" |
| | | align="center"> |
| | | <template #default="scope"> |
| | |
| | | import useFormData from "@/hooks/useFormData.js"; |
| | | import dayjs from "dayjs"; |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | import ImageUpload from "@/components/AttachmentUpload/image/index.vue"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import {listCustomer} from "@/api/basicData/customer.js"; |
| | | |
| | | const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue")); |
| | | const FileList = defineAsyncComponent(() => |
| | | import("@/components/Dialog/FileList.vue") |
| | | ); |
| | | |
| | | const router = useRouter(); |
| | | const route = useRoute(); |
| | |
| | | }); |
| | | const total = ref(0); |
| | | const fileList = ref([]); |
| | | const deliveryFileList = ref([]); |
| | | |
| | | // 用户信息表单弹框数据 |
| | | const operationType = ref(""); |
| | |
| | | }, |
| | | form: { |
| | | salesContractNo: "", |
| | | autoGenerateContractNo: true, |
| | | salesman: "", |
| | | customerId: "", |
| | | entryPerson: "", |
| | |
| | | const deliveryFormVisible = ref(false); |
| | | const currentDeliveryRow = ref(null); |
| | | const getDeliveryBatchQuantity = item => { |
| | | const quantity = item?.qualitity |
| | | ?? item?.quantity |
| | | ?? item?.unLockedQuantity |
| | | ?? item?.qualifiedUnLockedQuantity |
| | | ?? item?.qualifiedQuantity |
| | | ?? item?.stockQuantity; |
| | | const quantity = |
| | | item?.qualitity ?? |
| | | item?.quantity ?? |
| | | item?.unLockedQuantity ?? |
| | | item?.qualifiedUnLockedQuantity ?? |
| | | item?.qualifiedQuantity ?? |
| | | item?.stockQuantity; |
| | | return quantity ?? 0; |
| | | }; |
| | | const getCurrentDeliveryRowQuantity = () => { |
| | |
| | | return Math.max(0, Math.min(batchQuantity, remainingProductQuantity)); |
| | | }; |
| | | const handleDeliveryBatchQuantityChange = row => { |
| | | const max = getDeliveryBatchDeliveryMax(row); |
| | | const productQuantity = getCurrentDeliveryRowQuantity(); |
| | | const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0); |
| | | const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce( |
| | | (sum, item) => { |
| | | if (item?.id === row?.id) return sum; |
| | | return sum + Number(item?.deliveryQuantity || 0); |
| | | }, |
| | | 0 |
| | | ); |
| | | const remainingProductQuantity = Math.max( |
| | | 0, |
| | | productQuantity - otherBatchTotal |
| | | ); |
| | | const currentValue = Number(row?.deliveryQuantity || 0); |
| | | if (currentValue > max) { |
| | | row.deliveryQuantity = max; |
| | | proxy.$modal.msgWarning("发货数量不能超过这个产品的数量"); |
| | | |
| | | if (currentValue > batchQuantity) { |
| | | row.deliveryQuantity = batchQuantity; |
| | | proxy.$modal.msgWarning("发货数量不能大于库存数量"); |
| | | } else if (currentValue > remainingProductQuantity) { |
| | | row.deliveryQuantity = remainingProductQuantity; |
| | | proxy.$modal.msgWarning("所有批次发货数量之和不能大于待发货数量"); |
| | | } |
| | | }; |
| | | const getSelectedDeliveryBatchRows = () => { |
| | |
| | | ? res.data |
| | | : res?.data?.records || res?.data?.rows || []; |
| | | const seenIds = new Set(); |
| | | return rawList.filter(item => { |
| | | return rawList |
| | | .filter(item => { |
| | | if (!item?.id || !item?.batchNo || seenIds.has(item.id)) { |
| | | return false; |
| | | } |
| | | seenIds.add(item.id); |
| | | return true; |
| | | }).map(item => ({ |
| | | }) |
| | | .map(item => ({ |
| | | ...item, |
| | | deliveryQuantity: 0, |
| | | })); |
| | | }; |
| | | const validateDeliveryShippingCarNumber = (_rule, value, callback) => { |
| | | if (deliveryForm.value.type === "货车" && !value) { |
| | | return callback(new Error("请输入发货车牌号")); |
| | | } |
| | | callback(); |
| | | }; |
| | | const validateDeliveryExpressCompany = (_rule, value, callback) => { |
| | | if (deliveryForm.value.type === "快递" && !value) { |
| | | return callback(new Error("请输入快递公司")); |
| | | } |
| | | callback(); |
| | | }; |
| | | const deliveryFormData = reactive({ |
| | | deliveryForm: { |
| | | shippingCarNumber: "", |
| | | expressCompany: "", |
| | | expressNumber: "", |
| | | type: "货车", // 货车, 快递 |
| | | }, |
| | | deliveryRules: { |
| | | shippingCarNumber: [ |
| | | { validator: validateDeliveryShippingCarNumber, trigger: "blur" }, |
| | | ], |
| | | expressCompany: [{ validator: validateDeliveryExpressCompany, trigger: "blur" }], |
| | | type: [{required: true, message: "请选择发货类型", trigger: "change"}], |
| | | }, |
| | | }); |
| | |
| | | selectedQuotation.value = null; |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | listCustomer({current: -1, size: -1}).then(res => { |
| | | listCustomer({ current: -1, size: -1, type: 0 }).then(res => { |
| | | customerOption.value = res.data.records; |
| | | }); |
| | | form.value.entryPerson = userStore.id; |
| | |
| | | form.value.entryDate = getCurrentDate(); |
| | | // 签订日期默认为当天 |
| | | form.value.executionDate = getCurrentDate(); |
| | | // 默认自动生成销售合同号 |
| | | form.value.autoGenerateContractNo = true; |
| | | } else { |
| | | currentId.value = row.id; |
| | | getSalesLedgerWithProducts({id: row.id, type: 1}).then(res => { |
| | |
| | | form.value.entryPerson = Number(res.entryPerson); |
| | | productData.value = form.value.productData; |
| | | fileList.value = form.value.storageBlobVOs; |
| | | // 编辑时设置自动生成为false,允许手动修改 |
| | | form.value.autoGenerateContractNo = false; |
| | | }); |
| | | } |
| | | // let userAll = await userStore.getInfo() |
| | |
| | | taxExclusiveTotalPrice: taxExclusiveTotalPrice, |
| | | invoiceType: "增普票", |
| | | isProduction: true, |
| | | productId: p.productId, |
| | | productModelId: p.productModelId |
| | | }; |
| | | }); |
| | | |
| | |
| | | } |
| | | form.value.storageBlobDTOs = fileList; |
| | | form.value.type = 1; |
| | | if (form.value.autoGenerateContractNo) { |
| | | form.value.salesContractNo = ''; |
| | | } |
| | | addOrUpdateSalesLedger(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | |
| | | <tbody> |
| | | ${ |
| | | item.products && |
| | | item.products |
| | | .length > 0 |
| | | item |
| | | .products |
| | | .length > |
| | | 0 |
| | | ? item.products |
| | | .map( |
| | | product => ` |
| | |
| | | </tr> |
| | | ` |
| | | ) |
| | | .join("") |
| | | .join( |
| | | "" |
| | | ) |
| | | : '<tr><td colspan="6" style="text-align: center; color: #999;">暂无产品数据</td></tr>' |
| | | } |
| | | </tbody> |
| | |
| | | 审核拒绝: "审核拒绝", |
| | | 审核通过: "审核通过", |
| | | 已发货: "已发货", |
| | | 部分发货: "部分发货", |
| | | }; |
| | | return statusTextMap[statusStr] || "待发货"; |
| | | }; |
| | |
| | | 审核拒绝: "danger", |
| | | 审核通过: "success", |
| | | 已发货: "success", |
| | | 部分发货: "warning", |
| | | }; |
| | | return typeTextMap[statusStr] || "info"; |
| | | }; |
| | |
| | | |
| | | // 发货状态必须是"待发货"或"审核拒绝" |
| | | const statusStr = shippingStatus ? String(shippingStatus).trim() : ""; |
| | | return statusStr === "待发货" || statusStr === "审核拒绝"; |
| | | return statusStr === "待发货" || statusStr === "审核拒绝" || statusStr === "部分发货"; |
| | | }; |
| | | |
| | | // 打开附件弹窗 |
| | | const recordId = ref(0) |
| | | const fileDialogVisible = ref(false) |
| | | const recordId = ref(0); |
| | | const fileDialogVisible = ref(false); |
| | | |
| | | // 打开附件弹框 |
| | | const openFileDialog = async (row) => { |
| | | recordId.value = row.id |
| | | fileDialogVisible.value = true |
| | | } |
| | | const openFileDialog = async row => { |
| | | recordId.value = row.id; |
| | | fileDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 打开发货弹框 |
| | | const openDeliveryForm = async row => { |
| | |
| | | row.productModelId || row.modelId |
| | | ); |
| | | deliveryForm.value = { |
| | | shippingCarNumber: "", |
| | | expressCompany: "", |
| | | expressNumber: "", |
| | | type: "货车", |
| | | batchNo: [], |
| | | batchNoList, |
| | | }; |
| | | deliveryFileList.value = []; |
| | | deliveryFormVisible.value = true; |
| | | }; |
| | | |
| | |
| | | (sum, item) => sum + Number(item.deliveryQuantity || 0), |
| | | 0 |
| | | ); |
| | | const currentRowQuantity = Number(currentDeliveryRow.value?.quantity || 0); |
| | | if (currentRowQuantity > 0 && totalDeliveryQuantity > currentRowQuantity) { |
| | | proxy.$modal.msgWarning("批号发货总数不能超过当前产品数量"); |
| | | const currentRowNoQuantity = Number( |
| | | currentDeliveryRow.value?.noQuantity || 0 |
| | | ); |
| | | if ( |
| | | currentRowNoQuantity > 0 && |
| | | totalDeliveryQuantity > currentRowNoQuantity |
| | | ) { |
| | | proxy.$modal.msgWarning("批号发货总数不能超过待发货数量"); |
| | | return; |
| | | } |
| | | // 保存当前展开的行ID,以便发货后重新加载子表格数据 |
| | | const currentExpandedKeys = [...expandedRowKeys.value]; |
| | | const salesLedgerId = currentDeliveryRow.value.salesLedgerId; |
| | | deliveryForm.value.batchNo = selectedBatchRows.map(item => item.id); |
| | | const productModelId = currentDeliveryRow.value.productModelId || currentDeliveryRow.value.modelId; |
| | | const productModelId = |
| | | currentDeliveryRow.value.productModelId || |
| | | currentDeliveryRow.value.modelId; |
| | | addShippingInfo({ |
| | | salesLedgerId: salesLedgerId, |
| | | salesLedgerProductId: currentDeliveryRow.value.id, |
| | | type: deliveryForm.value.type, |
| | | shippingCarNumber: |
| | | deliveryForm.value.type === "货车" |
| | | ? deliveryForm.value.shippingCarNumber |
| | | : "", |
| | | expressCompany: |
| | | deliveryForm.value.type === "快递" |
| | | ? deliveryForm.value.expressCompany |
| | | : "", |
| | | expressNumber: |
| | | deliveryForm.value.type === "快递" |
| | | ? deliveryForm.value.expressNumber |
| | | : "", |
| | | storageBlobDTOs: deliveryFileList.value || [], |
| | | batchNo: deliveryForm.value.batchNo, |
| | | batchNoDetailList: selectedBatchRows.map(item => ({ |
| | | stockInventoryId: item.id, |
| | |
| | | }; |
| | | |
| | | // 关闭发货弹框 |
| | | const handleDeliveryTypeChange = val => { |
| | | if (val === "货车") { |
| | | deliveryForm.value.expressCompany = ""; |
| | | deliveryForm.value.expressNumber = ""; |
| | | } else { |
| | | deliveryForm.value.shippingCarNumber = ""; |
| | | } |
| | | }; |
| | | |
| | | const closeDeliveryDia = () => { |
| | | proxy.resetForm("deliveryFormRef"); |
| | | deliveryFileList.value = []; |
| | | deliveryFormVisible.value = false; |
| | | currentDeliveryRow.value = null; |
| | | }; |