| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="æ°å¢éè´éè´§" |
| | | width="70%" |
| | | top="3vh" |
| | | @close="closeModal" |
| | | class="purchase-return-dialog" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef" :inline="true"> |
| | | <div class="section-title"> |
| | | <span class="title-dot"></span> |
| | | <span class="title-text">åºæ¬ä¿¡æ¯</span> |
| | | </div> |
| | | <el-form-item |
| | | label="éæåå·" |
| | | prop="no" |
| | | :rules="[ |
| | | { |
| | | required: !formState.isDefaultNo, |
| | | message: '请è¾å
¥éæåå·', |
| | | trigger: 'blur', |
| | | } |
| | | ]" |
| | | > |
| | | <el-input |
| | | 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" /> |
| | | </template> |
| | | </el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="éè´§æ¹å¼" |
| | | prop="returnType" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©éè´§æ¹å¼', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-select |
| | | v-model="formState.returnType" |
| | | placeholder="è¯·éæ©éè´§æ¹å¼" |
| | | style="width: 240px" |
| | | > |
| | | <el-option label="éè´§éæ¬¾" :value="0" /> |
| | | <el-option label="ææ¶" :value="1" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="ä¾åºååç§°" |
| | | prop="supplierId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©ä¾åºå', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-select |
| | | v-model="formState.supplierId" |
| | | placeholder="è¯·éæ©ä¾åºå" |
| | | style="width: 240px" |
| | | filterable |
| | | @focus="fetchSupplierOptions" |
| | | @change="handleChangeSupplierId" |
| | | > |
| | | <el-option |
| | | v-for="item in supplierOptions" |
| | | :key="item.id" |
| | | :label="item.supplierName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="项ç®é¶æ®µ" |
| | | prop="projectPhase" |
| | | > |
| | | <el-select |
| | | v-model="formState.projectPhase" |
| | | placeholder="è¯·éæ©é¡¹ç®é¶æ®µ" |
| | | style="width: 240px" |
| | | > |
| | | <el-option |
| | | v-for="item in projectStageOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="å¶ä½æ¥æ" |
| | | prop="preparedAt" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©å¶ä½æ¥æ', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-date-picker |
| | | v-model="formState.preparedAt" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©å¶ä½æ¥æ" |
| | | style="width: 240px" |
| | | clearable /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="å¶å人ï¼" |
| | | prop="preparedUserId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©å¶å人', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-select |
| | | v-model="formState.preparedUserId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | filterable |
| | | default-first-option |
| | | :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" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="éæäººï¼" |
| | | prop="returnUserId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©éæäºº', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-select |
| | | v-model="formState.returnUserId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | filterable |
| | | default-first-option |
| | | 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" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="éè´ååå·ï¼" |
| | | prop="purchaseLedgerId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©éè´ååå·', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-select |
| | | v-model="formState.purchaseLedgerId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | filterable |
| | | default-first-option |
| | | style="width: 240px" |
| | | :reserve-keyword="false" |
| | | @change="handleChangePurchaseLedgerId" |
| | | > |
| | | <el-option |
| | | v-for="item in purchaseLedgerOptions" |
| | | :key="item.id" |
| | | :label="item.purchaseContractNumber" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="夿³¨ï¼" |
| | | prop="remark" |
| | | > |
| | | <el-input style="width: 240px" v-model="formState.remark" :rows="1" type="textarea" placeholder="请è¾å
¥å¤æ³¨"/> |
| | | </el-form-item> |
| | | |
| | | <div style="margin:20px 0;min-width:0;"> |
| | | <div class="section-title"> |
| | | <span class="title-dot"></span> |
| | | <span class="title-text">产åå表</span> |
| | | </div> |
| | | <el-button type="primary" size="small" style="margin-bottom:20px" @click="isShowProductsModal = true" :disabled="!formState.purchaseLedgerId">æ·»å 产å</el-button> |
| | | <el-table |
| | | :data="formState.purchaseReturnOrderProductsDtos" |
| | | border |
| | | max-height="400" |
| | | show-summary |
| | | :summary-method="summarizeChildrenTable" |
| | | style="width:100%;min-width:0;"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55" /> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="å
¥åºåå·" |
| | | prop="inboundBatches" |
| | | width="150" /> |
| | | <el-table-column label="æ¹æ¬¡å·" |
| | | prop="batchNo" |
| | | width="150" /> |
| | | <el-table-column label="产å大类" |
| | | prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="specificationModel" /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | width="70" /> |
| | | <el-table-column label="æ°é" |
| | | prop="stockInNum" |
| | | width="100" /> |
| | | <el-table-column label="å¯éè´§æ°é" |
| | | prop="unQuantity" |
| | | width="130" /> |
| | | <el-table-column label="å·²éè´§æ°é" |
| | | width="130"> |
| | | <template #default="scope"> |
| | | {{ calcAlreadyReturned(scope.row) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="éè´§æ°é" |
| | | prop="returnQuantity" |
| | | width="180"> |
| | | <template #default="scope"> |
| | | <el-input-number v-model="scope.row.returnQuantity" |
| | | controls-position="right" |
| | | :step="1" |
| | | :min="0" |
| | | :max="getReturnQtyMax(scope.row)" |
| | | :disabled="getReturnQtyMax(scope.row) <= 0" |
| | | @change="syncReturnTotal(scope.row)" |
| | | required |
| | | placeholder="请è¾å
¥éè´§æ°é" /> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column label="åºåé¢è¦æ°é" |
| | | prop="warnNum" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ç¨ç(%)" |
| | | prop="taxRate" |
| | | width="80" /> --> |
| | | <el-table-column label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="120" /> |
| | | <el-table-column label="éè´§æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | width="120"> |
| | | <template #default="scope"> |
| | | {{ formatAmount(getReturnTotal(scope.row)) || '--' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¯å¦è´¨æ£" |
| | | prop="isChecked" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.isChecked ? 'success' : 'info'"> |
| | | {{ scope.row.isChecked ? 'æ¯' : 'å¦' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column fixed="right" |
| | | label="æä½" |
| | | width="100" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | size="small" |
| | | @click="delProduct(scope.$index)" |
| | | > |
| | | å é¤ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div class="section-title"> |
| | | <span class="title-dot"></span> |
| | | <span class="title-text">è´¹ç¨ä¿¡æ¯</span> |
| | | </div> |
| | | |
| | | <el-form-item |
| | | label="æ´åææ£é¢ï¼" |
| | | prop="totalDiscountAmount" |
| | | > |
| | | <el-input-number v-model="formState.totalDiscountAmount" |
| | | controls-position="right" |
| | | :step="0.01" |
| | | :precision="2" |
| | | style="width: 100%;" |
| | | @change="handleChangeTotalDiscountAmount" |
| | | placeholder="请è¾å
¥æ´åææ£é¢"/> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="æ´åææ£çï¼" |
| | | prop="totalDiscountAmount" |
| | | > |
| | | <el-input v-model="formState.totalDiscountRate" |
| | | controls-position="right" |
| | | :step="0.01" |
| | | :precision="2" |
| | | style="width: 100%;" |
| | | @change="totalDiscount" |
| | | placeholder="请è¾å
¥æ´åææ£ç"> |
| | | <template #append> |
| | | % |
| | | </template> |
| | | </el-input> |
| | | </el-form-item> |
| | | |
| | | <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%;" |
| | | 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"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <ProductList |
| | | v-if="isShowProductsModal" |
| | | v-model:visible="isShowProductsModal" |
| | | :purchase-ledger-id="formState.purchaseLedgerId" |
| | | @completed="handleAddProduct" |
| | | /> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | 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")); |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | } |
| | | }); |
| | | let { proxy } = getCurrentInstance() |
| | | const payment_methods = [ |
| | | { |
| | | "label": "ç°é", |
| | | "value": "0", |
| | | }, |
| | | { |
| | | "label": "æ¯ç¥¨", |
| | | "value": "1", |
| | | }, |
| | | { |
| | | "label": "é¶è¡è½¬è´¦", |
| | | "value": "2", |
| | | }, |
| | | { |
| | | "label": "å
¶ä»", |
| | | "value": "3", |
| | | }, |
| | | ] |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | no: '', |
| | | isDefaultNo: true, |
| | | returnType: 0, |
| | | incomeType: undefined, |
| | | remark: '', |
| | | supplierId: undefined, |
| | | projectId: undefined, |
| | | projectPhase: undefined, |
| | | preparedAt: undefined, |
| | | preparedUserId: undefined, |
| | | returnUserId: undefined, |
| | | purchaseLedgerId: undefined, |
| | | purchaseReturnOrderProductsDtos: [], |
| | | totalDiscountAmount: 0, |
| | | totalDiscountRate: undefined, |
| | | totalAmount: 0, |
| | | }); |
| | | // ä¾åºåé项 |
| | | const supplierOptions = ref([]) |
| | | // 项ç®é¶æ®µé项 |
| | | const projectStageOptions = ref([ |
| | | { |
| | | label: 'ç«é¡¹', |
| | | value: 0, |
| | | }, |
| | | { |
| | | label: '设计', |
| | | value: 1, |
| | | }, |
| | | { |
| | | label: 'éè´', |
| | | value: 2, |
| | | }, |
| | | { |
| | | label: 'ç产', |
| | | value: 3, |
| | | }, |
| | | { |
| | | label: 'åºè´§', |
| | | value: 4, |
| | | } |
| | | ]) |
| | | // ç¨æ·é项 |
| | | const userOptions = ref([]) |
| | | // éè´å°è´¦é项 |
| | | const purchaseLedgerOptions = ref([]) |
| | | // æ¯å¦å±ç¤ºäº§ååè¡¨æ°æ® |
| | | const isShowProductsModal = ref(false) |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | 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 calcAlreadyReturned = (row) => { |
| | | const total = Number(row?.stockInNum ?? row?.totalQuantity ?? row?.quantity ?? 0) |
| | | const un = Number(row?.unQuantity ?? 0) |
| | | if (!Number.isFinite(total) || !Number.isFinite(un)) return 0 |
| | | return Math.max(total - un, 0) |
| | | } |
| | | |
| | | 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 getBaseAmount = () => { |
| | | const rows = formState.value.purchaseReturnOrderProductsDtos || [] |
| | | return rows.reduce((sum, item) => { |
| | | return sum + toNumber(item.taxInclusiveTotalPrice) |
| | | }, 0) |
| | | } |
| | | |
| | | // åæ¥ææ£é¢ |
| | | const totalDiscount = () => { |
| | | const discountRate = toNumber(formState.value.totalDiscountRate) |
| | | if (discountRate < 0 || discountRate > 100) { |
| | | proxy.$modal.msgError("请è¾å
¥0-100ä¹é´çææ£ç") |
| | | return |
| | | } |
| | | const baseAmount = getBaseAmount() |
| | | // ææ£é¢ = 产åéè´§æ»ä»·å计 * ææ£ç |
| | | formState.value.totalDiscountAmount = Number((baseAmount * (discountRate / 100)).toFixed(2)) |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | const getReturnQtyMax = (row) => { |
| | | const max = Number(row?.unQuantity) |
| | | if (Number.isNaN(max) || max < 0) { |
| | | return 0 |
| | | } |
| | | return max |
| | | } |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const summarizeChildrenTable = (param) => { |
| | | return proxy.summarizeTable( |
| | | param, |
| | | [ |
| | | "stockInNum", |
| | | "unQuantity", |
| | | "returnQuantity", |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ], |
| | | { |
| | | stockInNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | returnQuantity: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | unQuantity: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | } |
| | | ); |
| | | }; |
| | | |
| | | const handleChangeTotalDiscountAmount= () => { |
| | | const discountAmount = toNumber(formState.value.totalDiscountAmount) |
| | | if (discountAmount < 0) { |
| | | proxy.$modal.msgError("æ´åææ£é¢ä¸è½å°äº0") |
| | | formState.value.totalDiscountAmount = 0 |
| | | } |
| | | |
| | | const baseAmount = getBaseAmount() |
| | | const normalizedAmount = toNumber(formState.value.totalDiscountAmount) |
| | | if (baseAmount <= 0) { |
| | | formState.value.totalDiscountRate = 0 |
| | | syncTotalAmount() |
| | | return |
| | | } |
| | | |
| | | if (normalizedAmount > baseAmount) { |
| | | proxy.$modal.msgError("æ´åææ£é¢ä¸è½å¤§äºäº§åéè´§æ»ä»·å计") |
| | | formState.value.totalDiscountAmount = Number(baseAmount.toFixed(2)) |
| | | } |
| | | |
| | | const discountRate = (toNumber(formState.value.totalDiscountAmount) / baseAmount) * 100 |
| | | formState.value.totalDiscountRate = Number(discountRate.toFixed(2)) |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | const resetFeeInfo = () => { |
| | | formState.value.totalDiscountAmount = 0 |
| | | formState.value.totalDiscountRate = undefined |
| | | formState.value.totalAmount = 0 |
| | | formState.value.incomeType = undefined |
| | | } |
| | | |
| | | const syncTotalAmount = () => { |
| | | const baseAmount = getBaseAmount() |
| | | const discount = toNumber(formState.value.totalDiscountAmount) |
| | | // æäº¤éé¢ = 产åéè´§æ»ä»·å计 - ææ£é¢ |
| | | formState.value.totalAmount = Number((baseAmount - discount).toFixed(2)) |
| | | } |
| | | |
| | | // è·åä¾åºåé项 |
| | | const fetchSupplierOptions = () => { |
| | | if (supplierOptions.value.length > 0) { |
| | | return |
| | | } |
| | | getOptions().then((res) => { |
| | | supplierOptions.value = res.data; |
| | | }); |
| | | } |
| | | |
| | | |
| | | // è·åç¨æ·é项 |
| | | const fetchUserOptions = () => { |
| | | if (userOptions.value.length > 0) { |
| | | return |
| | | } |
| | | userListNoPageByTenantId().then((res) => { |
| | | userOptions.value = res.data; |
| | | }); |
| | | } |
| | | |
| | | // å¤çæ¹åä¾åºåæ°æ® |
| | | 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,approvalStatus:3}).then((res) => { |
| | | purchaseLedgerOptions.value = res.rows; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // å¤çæ¹åéè´å°è´¦æ°æ®ï¼ä¸è¯·æ±æ¥å£åæ¾äº§åï¼äº§åä»
å¨ãæ·»å 产åãå¼¹çªå¾éååå
¥ï¼ |
| | | const handleChangePurchaseLedgerId = () => { |
| | | resetFeeInfo() |
| | | formState.value.purchaseReturnOrderProductsDtos = [] |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | // å¤çæ¹åæ¯å¦é»è®¤ç¼å· |
| | | const handleChangeIsDefaultNo = (checked) => { |
| | | if (checked) { |
| | | formState.value.no = '' |
| | | } |
| | | } |
| | | |
| | | // å¢å 产å |
| | | const handleAddProduct = (selectedRows) => { |
| | | const existingIds = new Set(formState.value.purchaseReturnOrderProductsDtos.map(item => item.id)); |
| | | const newProducts = selectedRows.filter(item => !existingIds.has(item.id)).map(item => ({ |
| | | ...item, |
| | | returnQuantity: undefined, |
| | | taxInclusiveTotalPrice: 0, |
| | | // salesLedgerProductId: item.salesLedgerProductId, |
| | | })); |
| | | formState.value.purchaseReturnOrderProductsDtos.push(...newProducts); |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | // å é¤å项产å |
| | | const delProduct = (index) => { |
| | | formState.value.purchaseReturnOrderProductsDtos.splice(index, 1) |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = () => { |
| | | 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.unQuantity) |
| | | |
| | | 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 => { |
| | | if (valid) { |
| | | console.log(productList) |
| | | const submitPayload = { |
| | | ...formState.value, |
| | | purchaseReturnOrderProductsDtos: productList.map((row) => ({ |
| | | ...row, |
| | | stockInRecordId: row.id, |
| | | })), |
| | | } |
| | | createPurchaseReturnOrder(submitPayload).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | watch( |
| | | () => formState.value.purchaseReturnOrderProductsDtos, |
| | | (rows) => { |
| | | (rows || []).forEach(syncReturnTotal) |
| | | syncTotalAmount() |
| | | }, |
| | | { deep: true } |
| | | ) |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .section-title { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | width: 100%; |
| | | clear: both; |
| | | } |
| | | |
| | | .title-dot { |
| | | display: inline-block; |
| | | width: 8px; |
| | | height: 8px; |
| | | background-color: #409EFF; |
| | | border-radius: 50%; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | |
| | | </style> |