Merge remote-tracking branch 'origin/dev_1.0.2' into dev_1.0.2

dev_1.0.2
wangy 2026-06-03 18:15:52 +08:00
commit c246975914
34 changed files with 904 additions and 377 deletions

View File

@ -114,11 +114,11 @@ export function savePurchaseOrderMap(data) {
} }
// 查询采购单SN码列表 // 查询采购单SN码列表
export function purchaseSnList(purchaseNo, orderCode) { export function purchaseSnList(purchaseNo, orderCode, productCode) {
return request({ return request({
url: '/project/order/vue/purchaseSnList', url: '/project/order/vue/purchaseSnList',
method: 'get', method: 'get',
params: { purchaseNo, orderCode } params: { purchaseNo, orderCode, productCode }
}) })
} }

View File

@ -243,6 +243,15 @@
<div class="stocking-product-meta"> <div class="stocking-product-meta">
<span class="stocking-product-meta__label">产品型号</span> <span class="stocking-product-meta__label">产品型号</span>
<span class="stocking-product-meta__value stocking-product-meta__value--strong">{{ item.model || '-' }}</span> <span class="stocking-product-meta__value stocking-product-meta__value--strong">{{ item.model || '-' }}</span>
<el-button
v-if="(item.vendorName && item.vendorName.startsWith('新华三')) || (item.productType != 1 && item.productType != 2)"
type="primary"
plain
icon="el-icon-plus"
size="mini"
style="margin-left: 12px;"
@click="handleGenerateVirtualPurchase(item)"
>生成虚拟采购单</el-button>
</div> </div>
<div class="stocking-product-summary"> <div class="stocking-product-summary">
<div class="stocking-product-summary__item"> <div class="stocking-product-summary__item">
@ -250,32 +259,38 @@
<span class="stocking-product-summary__value">{{ item.orderNum !== undefined && item.orderNum !== null ? item.orderNum : '-' }}</span> <span class="stocking-product-summary__value">{{ item.orderNum !== undefined && item.orderNum !== null ? item.orderNum : '-' }}</span>
</div> </div>
<div class="stocking-product-summary__item"> <div class="stocking-product-summary__item">
<span class="stocking-product-summary__label">已配:</span> <span class="stocking-product-summary__label">已配:</span>
<span class="stocking-product-summary__value stocking-product-summary__value--green">{{ item.phNum !== undefined && item.phNum !== null ? item.phNum : '-' }}</span> <span class="stocking-product-summary__value stocking-product-summary__value--green">{{ calculateCurrentTotalPhNum(item) }}</span>
<span v-if="(item.orderNum !== undefined && item.orderNum !== null ? item.orderNum-(item.phNum||0) : 0) > 0" class="stocking-product-summary__value stocking-product-summary__value--red-bg" style="margin-left: 8px; font-size: 12px; font-weight: normal; padding: 2px 6px;">: {{ item.orderNum !== undefined && item.orderNum !== null ? item.orderNum-(item.phNum||0): '-'}}</span> <span v-if="(item.orderNum !== undefined && item.orderNum !== null ? item.orderNum-calculateCurrentTotalPhNum(item) : 0) > 0" class="stocking-product-summary__value stocking-product-summary__value--red-bg" style="margin-left: 8px; font-size: 12px; font-weight: normal; padding: 2px 6px;">: {{ item.orderNum !== undefined && item.orderNum !== null ? item.orderNum-calculateCurrentTotalPhNum(item): '-'}}</span>
</div> </div>
<div class="stocking-product-summary__item"> <div class="stocking-product-summary__item">
<span class="stocking-product-summary__label">已备货:</span> <span class="stocking-product-summary__label">已备货:</span>
<span class="stocking-product-summary__value stocking-product-summary__value--green">{{ item.bhNum !== undefined && item.bhNum !== null ? item.bhNum : '-' }}</span> <span class="stocking-product-summary__value stocking-product-summary__value--green">{{ item.bhNum !== undefined && item.bhNum !== null ? item.bhNum : '-' }}</span>
<span v-if="(item.orderNum !== undefined && item.orderNum !== null ? item.orderNum-(item.bhNum||0) : 0) > 0" class="stocking-product-summary__value stocking-product-summary__value--red-bg" style="margin-left: 8px; font-size: 12px; font-weight: normal; padding: 2px 6px;">: {{ item.orderNum !== undefined && item.orderNum !== null ? item.orderNum-(item.bhNum||0): '-'}}</span> <span v-if="(item.orderNum !== undefined && item.orderNum !== null ? item.orderNum-(item.bhNum||0) : 0) > 0" class="stocking-product-summary__value stocking-product-summary__value--red-bg" style="margin-left: 8px; font-size: 12px; font-weight: normal; padding: 2px 6px;">: {{ item.orderNum !== undefined && item.orderNum !== null ? item.orderNum-(item.bhNum||0): '-'}}</span>
<span v-if="item.bhNum !== undefined && item.bhNum !== null && item.orderNum !== undefined && item.orderNum !== null && item.bhNum === item.orderNum" class="stocking-product-summary__value" style="margin-left: 8px; font-size: 12px; font-weight: normal; padding: 2px 6px; background: #67c23a; color: #fff; border-radius: 3px;"></span>
</div> </div>
</div> </div>
</div> </div>
<el-table :data="item.bindList || []" class="stocking-product-table"> <el-table :data="item.bindList || []" class="stocking-product-table">
<el-table-column label="采购单号" align="center" prop="purchaseNo" width="200" /> <el-table-column label="采购单号" align="center" prop="purchaseNo" width="250" />
<el-table-column label="制造者" align="center" prop="vendorAddress" width="200" /> <el-table-column label="入库状态" align="center" prop="status" >
<el-table-column label="批次数量" align="center" prop="cgNum" />
<el-table-column label="可用" align="center" prop="kyNum">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ String(scope.row.status) === '0' ? '-' : scope.row.kyNum }}</span> <dict-tag :options="dict.type.purchase_status" :value="String(scope.row.status)"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="配额量" align="center" prop="phNum" width="140"> <el-table-column label="制造者" align="center" prop="vendorAddress" />
<el-table-column label="单价" align="center" prop="price" width="130">
<template slot-scope="scope">
<span style="color: #f05a00;"> {{ formatCurrency(scope.row.price) }}</span>
</template>
</el-table-column>
<el-table-column label="批次数量" align="center" prop="cgNum" />
<el-table-column label="可用" align="center" prop="kyNum" />
<el-table-column label="配额" align="center" prop="phNum" >
<template slot-scope="scope"> <template slot-scope="scope">
<el-input <el-input
v-model="scope.row.phNum" v-model="scope.row.phNum"
type="number" type="number"
:disabled="String(scope.row.status) === '0'"
:min="scope.row.bhNum || 0" :min="scope.row.bhNum || 0"
:max="calculateMaxPhNum(scope.row, item)" :max="calculateMaxPhNum(scope.row, item)"
size="small" size="small"
@ -285,19 +300,14 @@
></el-input> ></el-input>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="入库状态" align="center" prop="status" width="120"> <el-table-column label="已出库" align="center" prop="bhNum" />
<template slot-scope="scope"> <el-table-column label="操作" align="center" width="130" >
<dict-tag :options="dict.type.purchase_status" :value="String(scope.row.status)"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
v-if="['1', '2'].includes(String(scope.row.status))" v-if="['1', '2'].includes(String(scope.row.status))"
type="text" type="text"
icon="el-icon-edit-outline"
@click="handleAssignOuterSnCode(scope.row, item)" @click="handleAssignOuterSnCode(scope.row, item)"
>分配出库SN码</el-button> >查看出库SN码</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -321,7 +331,7 @@
</div> </div>
<div> <div>
<el-button @click="stockingDetailVisible = false"> </el-button> <el-button @click="stockingDetailVisible = false"> </el-button>
<!-- <el-button type="primary" :loading="stockingDetailSaving" @click="handleSaveStockingBind"></el-button>--> <el-button type="primary" :loading="stockingDetailSaving" @click="handleSaveStockingBind"></el-button>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
@ -337,8 +347,8 @@
<div class="stocking-save-confirm__title">本次将保存 {{ stockingSaveChangedList.length }} 条配额量变更是否继续</div> <div class="stocking-save-confirm__title">本次将保存 {{ stockingSaveChangedList.length }} 条配额量变更是否继续</div>
<el-table :data="stockingSaveChangedList" max-height="300" size="mini"> <el-table :data="stockingSaveChangedList" max-height="300" size="mini">
<el-table-column label="采购单号" align="center" prop="purchaseNo" min-width="160" :show-overflow-tooltip="true" /> <el-table-column label="采购单号" align="center" prop="purchaseNo" min-width="160" :show-overflow-tooltip="true" />
<el-table-column label="原配额" align="center" prop="originalBindNum" width="100" /> <el-table-column label="原配额" align="center" prop="originalBindNum" width="100" />
<el-table-column label="新配额" align="center" prop="bindNum" width="100" /> <el-table-column label="新配额" align="center" prop="bindNum" width="100" />
</el-table> </el-table>
</div> </div>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
@ -356,7 +366,7 @@
> >
<div slot="title" class="outer-sn-dialog-title"> <div slot="title" class="outer-sn-dialog-title">
<i class="el-icon-box"></i> <i class="el-icon-box"></i>
<span>分配出库 SN </span> <span>出库 SN </span>
</div> </div>
<div v-loading="outerSnLoading" class="outer-sn-dialog-body"> <div v-loading="outerSnLoading" class="outer-sn-dialog-body">
<div class="outer-sn-header"> <div class="outer-sn-header">
@ -406,22 +416,17 @@
<div class="outer-sn-grid-container"> <div class="outer-sn-grid-container">
<div class="outer-sn-grid-header"> <div class="outer-sn-grid-header">
<el-checkbox <!-- <span class="outer-sn-current-count">当前仓库SN码总数{{ getWarehouseSnCount(outerSnActiveWarehouse) }}</span>-->
v-model="outerSnSelectAll" <pagination
:indeterminate="outerSnSelectIndeterminate" small
@change="handleOuterSnSelectAll" layout="total, sizes, prev, pager, next"
> :total="outerSnPagination.total"
全选 :page.sync="outerSnPagination.pageNum"
</el-checkbox> :limit.sync="outerSnPagination.pageSize"
<span class="outer-sn-current-count">当前仓库SN码总数{{ getWarehouseSnCount(outerSnActiveWarehouse) }}</span> :page-sizes="[100, 200, 500]"
<el-button @pagination="handleOuterSnPageChange"
type="text" style="display: inline-block;"
size="small" />
style="color: #f56c6c;"
@click="handleOuterSnClearSelected"
>
清空已选
</el-button>
</div> </div>
<div class="outer-sn-grid"> <div class="outer-sn-grid">
<div <div
@ -432,27 +437,29 @@
'outer-sn-card--selected': isSnSelected(sn.productSn), 'outer-sn-card--selected': isSnSelected(sn.productSn),
'outer-sn-card--disabled': isSnDisabled(sn) 'outer-sn-card--disabled': isSnDisabled(sn)
}" }"
@click="handleSnCardClick(sn)"
> >
<el-checkbox
:value="isSnSelected(sn.productSn)"
:disabled="isSnDisabled(sn)"
@click.native.stop
@change="handleSnCheckboxChange(sn, $event)"
/>
<span class="outer-sn-card-text">{{ sn.productSn }}</span> <span class="outer-sn-card-text">{{ sn.productSn }}</span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button @click="outerSnDialogVisible = false">取消</el-button> <el-button @click="outerSnDialogVisible = false">关闭</el-button>
<el-button type="primary" @click="handleConfirmSnSelection">
确认分配 {{ outerSnSelectedCount }}
</el-button>
</div> </div>
</el-dialog> </el-dialog>
<!-- 新增采购单弹窗 -->
<el-dialog :title="purchaseTitle" :close-on-click-modal="false" :visible.sync="purchaseOpen" width="80vw" append-to-body>
<purchase-order-detail ref="purchaseOrderDetail" :order-data="currentPurchaseOrderData"
@close="purchaseOpen = false"
@success="handlePurchaseSuccess">
</purchase-order-detail>
<template slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitPurchaseForm"> </el-button>
<el-button @click="cancelPurchase"> </el-button>
</template>
</el-dialog>
</div> </div>
</template> </template>
@ -464,13 +471,15 @@ import { getToken } from "@/utils/auth";
import OrderDetailDrawer from '../../project/order/OrderDetailDrawer.vue'; import OrderDetailDrawer from '../../project/order/OrderDetailDrawer.vue';
import ProjectDetailDrawer from '../../project/info/ProjectDetailDrawer.vue'; import ProjectDetailDrawer from '../../project/info/ProjectDetailDrawer.vue';
import Edit from './edit.vue'; import Edit from './edit.vue';
import PurchaseOrderDetail from '../../purchaseorder/components/PurchaseOrderDetail.vue';
export default { export default {
name: "Execution", name: "Execution",
components: { components: {
ProjectDetailDrawer, ProjectDetailDrawer,
OrderDetailDrawer, OrderDetailDrawer,
Edit // Register the Edit component Edit,
PurchaseOrderDetail
}, },
dicts: ['execution_outer_status', 'execution_delivery_status', 'execution_sign_status', 'purchase_status'], dicts: ['execution_outer_status', 'execution_delivery_status', 'execution_sign_status', 'purchase_status'],
data() { data() {
@ -518,6 +527,16 @@ export default {
outerSnSelectedList: [], outerSnSelectedList: [],
outerSnSelectAll: false, outerSnSelectAll: false,
outerSnSelectIndeterminate: false, outerSnSelectIndeterminate: false,
outerSnPagination: {
pageNum: 1,
pageSize: 100,
total: 0
},
// --- ---
purchaseOpen: false,
purchaseTitle: '',
currentPurchaseOrderData: null,
virtualPurchaseProductInfo: null,
// //
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
@ -550,6 +569,23 @@ export default {
created() { created() {
this.getList(); this.getList();
}, },
watch: {
purchaseOpen(val) {
if (!val) {
this.currentPurchaseOrderData = null;
this.virtualPurchaseProductInfo = null;
this.$refs.purchaseOrderDetail?.resetForm();
} else {
this.$nextTick(() => {
if (this.virtualPurchaseProductInfo) {
this.$refs.purchaseOrderDetail?.initVirtualPurchase(this.virtualPurchaseProductInfo);
} else {
this.$refs.purchaseOrderDetail?.resetForm();
}
});
}
}
},
computed: { computed: {
outerSnSelectedCount() { outerSnSelectedCount() {
return this.outerSnSelectedList.length; return this.outerSnSelectedList.length;
@ -559,7 +595,25 @@ export default {
return Number.isNaN(quotaQuantity) ? 0 : quotaQuantity; return Number.isNaN(quotaQuantity) ? 0 : quotaQuantity;
}, },
stockingTotalCost() { stockingTotalCost() {
return (this.stockingDetailList || []).reduce((total, item) => total + (Number(item.sumCost) || 0), 0); return (this.stockingDetailList || []).reduce((total, item) => {
const baseCost = Number(item.sumCost) || 0;
let additionalCost = 0;
if (item.allBindList) {
item.allBindList.forEach(bindItem => {
const originalPhNum = bindItem.originalPhNum === '' || bindItem.originalPhNum === null || bindItem.originalPhNum === undefined ? 0 : Number(bindItem.originalPhNum);
const key = this.getBindDraftKey(item.productCode, bindItem.purchaseId);
const currentPhNum = this.stockingBindDraftMap[key] !== undefined
? Number(this.stockingBindDraftMap[key])
: (bindItem.phNum === '' || bindItem.phNum === null || bindItem.phNum === undefined ? 0 : Number(bindItem.phNum));
const price = Number(bindItem.price) || 0;
const diff = currentPhNum - originalPhNum;
additionalCost += diff * price;
});
}
return total + baseCost + additionalCost;
}, 0);
}, },
filteredSnList() { filteredSnList() {
let list = this.outerSnDetail.snList || []; let list = this.outerSnDetail.snList || [];
@ -570,7 +624,10 @@ export default {
const keyword = this.outerSnSearchKeyword.toLowerCase(); const keyword = this.outerSnSearchKeyword.toLowerCase();
list = list.filter(sn => (sn.productSn || '').toLowerCase().includes(keyword)); list = list.filter(sn => (sn.productSn || '').toLowerCase().includes(keyword));
} }
return list; this.outerSnPagination.total = list.length;
const start = (this.outerSnPagination.pageNum - 1) * this.outerSnPagination.pageSize;
const end = start + this.outerSnPagination.pageSize;
return list.slice(start, end);
} }
}, },
methods: { methods: {
@ -689,13 +746,22 @@ export default {
this.stockingDetailLoading = true; this.stockingDetailLoading = true;
productMatchList(row.orderCode).then(response => { productMatchList(row.orderCode).then(response => {
const list = response.data || []; const list = response.data || [];
return Promise.all(list.map(item => this.loadBindPageData(row.orderCode, { return Promise.all(list.map(item => this.loadAllBindData(row.orderCode, item).then(allBindList => {
...item, const bindPageNum = 1;
originalTotalPhNum: item.phNum, const bindPageSize = this.stockingBindPageSize;
bindList: [], const startIndex = (bindPageNum - 1) * bindPageSize;
bindTotal: 0, const endIndex = startIndex + bindPageSize;
bindPageNum: 1, const bindList = allBindList.slice(startIndex, endIndex);
bindPageSize: this.stockingBindPageSize
return {
...item,
originalTotalPhNum: item.phNum,
allBindList: allBindList,
bindList: bindList,
bindTotal: allBindList.length,
bindPageNum: bindPageNum,
bindPageSize: bindPageSize
};
}))); })));
}).then(list => { }).then(list => {
this.stockingDetailList = list; this.stockingDetailList = list;
@ -705,9 +771,13 @@ export default {
this.stockingDetailLoading = false; this.stockingDetailLoading = false;
}); });
}, },
getDraftBindNum(purchaseId, defaultValue) { getBindDraftKey(productCode, purchaseId) {
if (this.stockingBindDraftMap[purchaseId] !== undefined) { return `${productCode}_${purchaseId}`;
return this.stockingBindDraftMap[purchaseId]; },
getDraftBindNum(productCode, purchaseId, defaultValue) {
const key = this.getBindDraftKey(productCode, purchaseId);
if (this.stockingBindDraftMap[key] !== undefined) {
return this.stockingBindDraftMap[key];
} }
return defaultValue; return defaultValue;
}, },
@ -719,7 +789,9 @@ export default {
const validValue = Math.max(minValue, Math.min(rawValue, maxValue)); const validValue = Math.max(minValue, Math.min(rawValue, maxValue));
row.phNum = validValue; row.phNum = validValue;
this.$set(this.stockingBindDraftMap, row.purchaseId, validValue); const key = this.getBindDraftKey(item.productCode, row.purchaseId);
this.$set(this.stockingBindDraftMap, key, validValue);
this.updateItemTotalPhNum(item);
}, },
calculateMaxPhNum(row, item) { calculateMaxPhNum(row, item) {
const originalPhNum = row.originalPhNum === '' || row.originalPhNum === null || row.originalPhNum === undefined ? 0 : Number(row.originalPhNum); const originalPhNum = row.originalPhNum === '' || row.originalPhNum === null || row.originalPhNum === undefined ? 0 : Number(row.originalPhNum);
@ -728,58 +800,46 @@ export default {
const maxPhysical = originalPhNum + originalKyNum; const maxPhysical = originalPhNum + originalKyNum;
let otherRowsPhNumSum = 0; const currentTotalPhNum = this.calculateCurrentTotalPhNum(item);
if (item && item.bindList) { const key = this.getBindDraftKey(item.productCode, row.purchaseId);
item.bindList.forEach(b => { const currentRowPhNum = this.stockingBindDraftMap[key] !== undefined
if (b.purchaseId !== row.purchaseId) { ? Number(this.stockingBindDraftMap[key])
const p = Number(b.phNum) || 0; : (row.phNum === '' || row.phNum === null || row.phNum === undefined ? 0 : Number(row.phNum));
otherRowsPhNumSum += p;
}
});
}
const maxAllowedByOrder = orderNum - otherRowsPhNumSum; const maxAllowedByOrder = orderNum - currentTotalPhNum + currentRowPhNum;
return Math.min(maxPhysical, maxAllowedByOrder); return Math.min(maxPhysical, maxAllowedByOrder);
}, },
loadBindPageData(orderCode, item) { loadAllBindData(orderCode, item) {
return productMatchBindList(orderCode, item.productCode, { return productMatchBindList(orderCode, item.productCode, {
pageNum: item.bindPageNum, pageNum: 1,
pageSize: item.bindPageSize, pageSize: 9999,
orderByColumn: 't6.createTime', orderByColumn: 't6.createTime',
isAsc: 'desc' isAsc: 'desc'
}).then(bindResponse => { }).then(bindResponse => {
const bindList = (bindResponse.rows || []).map(bindItem => ({ return (bindResponse.rows || []).map(bindItem => ({
...bindItem, ...bindItem,
phNum: this.getDraftBindNum(bindItem.purchaseId, bindItem.phNum), phNum: this.getDraftBindNum(item.productCode, bindItem.purchaseId, bindItem.phNum),
originalPhNum: bindItem.originalPhNum !== undefined ? bindItem.originalPhNum : bindItem.phNum, originalPhNum: bindItem.originalPhNum !== undefined ? bindItem.originalPhNum : bindItem.phNum,
originalKyNum: bindItem.originalKyNum !== undefined ? bindItem.originalKyNum : bindItem.kyNum originalKyNum: bindItem.originalKyNum !== undefined ? bindItem.originalKyNum : bindItem.kyNum
})); }));
return {
...item,
originalTotalPhNum: item.originalTotalPhNum !== undefined ? item.originalTotalPhNum : item.phNum,
bindList,
bindTotal: bindResponse.total || 0
};
}).catch(() => { }).catch(() => {
return { return [];
...item,
bindList: [],
bindTotal: 0
};
}); });
}, },
handleBindPageChange(item) { handleBindPageChange(item) {
this.stockingDetailLoading = true; const startIndex = (item.bindPageNum - 1) * item.bindPageSize;
this.loadBindPageData(this.stockingDetailRow.orderCode, item).then(updatedItem => { const endIndex = startIndex + item.bindPageSize;
this.stockingDetailList = this.stockingDetailList.map(currentItem => { const bindList = (item.allBindList || []).slice(startIndex, endIndex);
if (currentItem.productCode === updatedItem.productCode) {
return updatedItem; this.stockingDetailList = this.stockingDetailList.map(currentItem => {
} if (currentItem.productCode === item.productCode) {
return currentItem; return {
}); ...currentItem,
}).finally(() => { bindList: bindList
this.stockingDetailLoading = false; };
}
return currentItem;
}); });
}, },
handleBindNumChange(row, item) { handleBindNumChange(row, item) {
@ -796,25 +856,60 @@ export default {
const diff = nextValue - originalPhNum; const diff = nextValue - originalPhNum;
row.kyNum = originalKyNum - diff; row.kyNum = originalKyNum - diff;
this.$set(this.stockingBindDraftMap, row.purchaseId, nextValue); const key = this.getBindDraftKey(item.productCode, row.purchaseId);
this.$set(this.stockingBindDraftMap, key, nextValue);
this.updateItemTotalPhNum(item);
},
calculateCurrentTotalPhNum(item) {
if (!item || !item.productCode || !item.allBindList) return 0;
let total = 0;
item.allBindList.forEach(bindItem => {
const key = this.getBindDraftKey(item.productCode, bindItem.purchaseId);
if (this.stockingBindDraftMap && this.stockingBindDraftMap[key] !== undefined) {
total += Number(this.stockingBindDraftMap[key]);
} else {
const phNum = bindItem.phNum === '' || bindItem.phNum === null || bindItem.phNum === undefined ? 0 : Number(bindItem.phNum);
total += phNum;
}
});
return total;
},
findBindItemByPurchaseId(productCode, purchaseId) {
const product = this.stockingDetailList.find(item => item.productCode === productCode);
if (!product) return null;
return product.allBindList?.find(b => String(b.purchaseId) === String(purchaseId));
},
updateItemTotalPhNum(item) {
if (item) {
this.$set(item, 'phNum', this.calculateCurrentTotalPhNum(item));
}
}, },
handleSaveStockingBind() { handleSaveStockingBind() {
const changedList = []; const changedList = [];
this.stockingDetailList.forEach(item => { this.stockingDetailList.forEach(item => {
(item.bindList || []).forEach(bindItem => { if (item.allBindList) {
this.handleBindNumChange(bindItem, item); item.allBindList.forEach(bindItem => {
const currentPhNum = bindItem.phNum === '' || bindItem.phNum === null || bindItem.phNum === undefined ? 0 : Number(bindItem.phNum); const key = this.getBindDraftKey(item.productCode, bindItem.purchaseId);
const originalPhNum = bindItem.originalPhNum === '' || bindItem.originalPhNum === null || bindItem.originalPhNum === undefined ? 0 : Number(bindItem.originalPhNum); const currentPhNum = this.stockingBindDraftMap[key] !== undefined
if (currentPhNum !== originalPhNum) { ? Number(this.stockingBindDraftMap[key])
changedList.push({ : (bindItem.phNum === '' || bindItem.phNum === null || bindItem.phNum === undefined ? 0 : Number(bindItem.phNum));
orderId: this.stockingDetailRow.id, const originalPhNum = bindItem.originalPhNum === '' || bindItem.originalPhNum === null || bindItem.originalPhNum === undefined ? 0 : Number(bindItem.originalPhNum);
purchaseId: bindItem.purchaseId, if (currentPhNum !== originalPhNum) {
purchaseNo: bindItem.purchaseNo, changedList.push({
originalBindNum: originalPhNum, orderId: this.stockingDetailRow.id,
bindNum: currentPhNum purchaseId: bindItem.purchaseId,
}); purchaseNo: bindItem.purchaseNo,
} productCode: item.productCode,
}); originalBindNum: originalPhNum,
bindNum: currentPhNum
});
}
});
}
}); });
if (!changedList.length) { if (!changedList.length) {
this.$message.warning('暂无变更数据'); this.$message.warning('暂无变更数据');
@ -828,17 +923,40 @@ export default {
Promise.all(this.stockingSaveChangedList.map(item => savePurchaseOrderMap({ Promise.all(this.stockingSaveChangedList.map(item => savePurchaseOrderMap({
orderId: item.orderId, orderId: item.orderId,
purchaseId: item.purchaseId, purchaseId: item.purchaseId,
productCode: item.productCode,
bindNum: item.bindNum bindNum: item.bindNum
}))).then(() => { }))).then(() => {
this.$message.success('保存成功'); this.$message.success('保存成功');
this.stockingDetailList.forEach(item => { this.stockingDetailList.forEach(item => {
item.originalTotalPhNum = item.phNum; item.originalTotalPhNum = this.calculateCurrentTotalPhNum(item);
(item.bindList || []).forEach(bindItem => { if (item.allBindList) {
bindItem.originalPhNum = bindItem.phNum; item.allBindList.forEach(bindItem => {
bindItem.originalKyNum = bindItem.kyNum; const key = this.getBindDraftKey(item.productCode, bindItem.purchaseId);
this.$delete(this.stockingBindDraftMap, bindItem.purchaseId); if (this.stockingBindDraftMap[key] !== undefined) {
}); bindItem.phNum = this.stockingBindDraftMap[key];
bindItem.originalPhNum = bindItem.phNum;
const originalKyNum = bindItem.originalKyNum === '' || bindItem.originalKyNum === null || bindItem.originalKyNum === undefined ? 0 : Number(bindItem.originalKyNum);
const diff = bindItem.phNum - (bindItem.originalPhNum || 0);
bindItem.kyNum = originalKyNum - diff;
bindItem.originalKyNum = bindItem.kyNum;
}
});
}
if (item.bindList) {
item.bindList.forEach(bindItem => {
const key = this.getBindDraftKey(item.productCode, bindItem.purchaseId);
if (this.stockingBindDraftMap[key] !== undefined) {
bindItem.phNum = this.stockingBindDraftMap[key];
bindItem.originalPhNum = bindItem.phNum;
const originalKyNum = bindItem.originalKyNum === '' || bindItem.originalKyNum === null || bindItem.originalKyNum === undefined ? 0 : Number(bindItem.originalKyNum);
const diff = bindItem.phNum - (bindItem.originalPhNum || 0);
bindItem.kyNum = originalKyNum - diff;
bindItem.originalKyNum = bindItem.kyNum;
}
});
}
}); });
this.stockingBindDraftMap = {};
this.stockingSaveConfirmVisible = false; this.stockingSaveConfirmVisible = false;
this.stockingDetailVisible = false; this.stockingDetailVisible = false;
this.stockingSaveChangedList = []; this.stockingSaveChangedList = [];
@ -861,13 +979,14 @@ export default {
this.outerSnSelectedList = []; this.outerSnSelectedList = [];
this.outerSnSelectAll = false; this.outerSnSelectAll = false;
this.outerSnSelectIndeterminate = false; this.outerSnSelectIndeterminate = false;
this.outerSnPagination = { pageNum: 1, pageSize: 100, total: 0 };
if (!row || !row.purchaseNo) { if (!row || !row.purchaseNo) {
this.$message.warning('采购单号为空无法查询SN码'); this.$message.warning('采购单号为空无法查询SN码');
return; return;
} }
this.outerSnDialogVisible = true; this.outerSnDialogVisible = true;
this.outerSnLoading = true; this.outerSnLoading = true;
purchaseSnList(row.purchaseNo, this.stockingDetailRow.orderCode).then(response => { purchaseSnList(row.purchaseNo, this.stockingDetailRow.orderCode, item.productCode).then(response => {
const data = response.data || {}; const data = response.data || {};
this.outerSnDetail = { this.outerSnDetail = {
totalQuantity: data.totalQuantity || 0, totalQuantity: data.totalQuantity || 0,
@ -882,18 +1001,8 @@ export default {
const alreadyBoundSns = this.outerSnDetail.snList const alreadyBoundSns = this.outerSnDetail.snList
.filter(sn => sn.orderCode && sn.orderCode === this.stockingDetailRow.orderCode) .filter(sn => sn.orderCode && sn.orderCode === this.stockingDetailRow.orderCode)
.map(sn => sn.productSn); .map(sn => sn.productSn);
const availableSns = this.outerSnDetail.snList
.filter(sn => !this.isSnDisabled(sn))
.map(sn => sn.productSn);
let initialSelected = [...alreadyBoundSns]; this.outerSnSelectedList = alreadyBoundSns;
if (initialSelected.length < this.outerSnQuotaQuantity) {
const needCount = this.outerSnQuotaQuantity - initialSelected.length;
const remainingToSelect = availableSns.filter(sn => !initialSelected.includes(sn)).slice(0, needCount);
initialSelected = initialSelected.concat(remainingToSelect);
}
this.outerSnSelectedList = initialSelected.slice(0, this.outerSnQuotaQuantity);
this.updateSelectAllState(); this.updateSelectAllState();
}).finally(() => { }).finally(() => {
this.outerSnLoading = false; this.outerSnLoading = false;
@ -907,6 +1016,9 @@ export default {
return this.outerSnSelectedList.includes(productSn); return this.outerSnSelectedList.includes(productSn);
}, },
isSnDisabled(sn) { isSnDisabled(sn) {
if (sn.orderCode && sn.orderCode === (this.stockingDetailRow && this.stockingDetailRow.orderCode)) {
return false;
}
return !!(sn.outerCode || (sn.orderCode && sn.orderCode !== (this.stockingDetailRow && this.stockingDetailRow.orderCode))); return !!(sn.outerCode || (sn.orderCode && sn.orderCode !== (this.stockingDetailRow && this.stockingDetailRow.orderCode)));
}, },
handleSnCardClick(sn) { handleSnCardClick(sn) {
@ -934,36 +1046,6 @@ export default {
} }
this.updateSelectAllState(); this.updateSelectAllState();
}, },
handleOuterSnSelectAll(checked) {
const quotaQuantity = this.outerSnQuotaQuantity;
const availableSns = this.filteredSnList.filter(sn => !this.isSnDisabled(sn)).map(sn => sn.productSn);
if (checked) {
if (quotaQuantity <= 0) {
this.$message.warning('当前配额数量为0不能选择SN码');
this.outerSnSelectAll = false;
this.outerSnSelectIndeterminate = false;
return;
}
const normalizedSelectedList = this.outerSnSelectedList.slice(0, quotaQuantity);
const unselectedSns = availableSns.filter(sn => !normalizedSelectedList.includes(sn));
const remainCount = quotaQuantity - normalizedSelectedList.length;
this.outerSnSelectedList = normalizedSelectedList.concat(unselectedSns.slice(0, Math.max(remainCount, 0)));
if (availableSns.length > this.outerSnSelectedList.filter(sn => availableSns.includes(sn)).length) {
this.$message.warning(`最多只能选择 ${quotaQuantity} 个SN码`);
}
} else {
this.outerSnSelectedList = this.outerSnSelectedList.filter(sn => !availableSns.includes(sn)).slice(0, quotaQuantity);
}
this.updateSelectAllState();
},
handleOuterSnClearSelected() {
const quotaQuantity = this.outerSnQuotaQuantity;
if (this.outerSnSelectedList.length > quotaQuantity) {
this.$message.warning(`已选SN码数量超过配额 ${quotaQuantity},已清空选择`);
}
this.outerSnSelectedList = [];
this.updateSelectAllState();
},
canSelectMoreSn(showMessage = true) { canSelectMoreSn(showMessage = true) {
if (this.outerSnSelectedList.length < this.outerSnQuotaQuantity) { if (this.outerSnSelectedList.length < this.outerSnQuotaQuantity) {
return true; return true;
@ -984,72 +1066,6 @@ export default {
this.outerSnSelectAll = selectedInCurrent === availableSns.length; this.outerSnSelectAll = selectedInCurrent === availableSns.length;
this.outerSnSelectIndeterminate = selectedInCurrent > 0 && selectedInCurrent < availableSns.length; this.outerSnSelectIndeterminate = selectedInCurrent > 0 && selectedInCurrent < availableSns.length;
}, },
handleConfirmSnSelection() {
if (this.outerSnSelectedList.length > this.outerSnQuotaQuantity) {
this.$message.warning(`最多只能选择 ${this.outerSnQuotaQuantity} 个SN码`);
return;
}
this.$confirm(`确认将选中的 ${this.outerSnSelectedList.length} 个SN码分配给当前订单`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const loading = this.$loading({
lock: true,
text: '正在处理中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
//
const changedList = [];
this.stockingDetailList.forEach(item => {
(item.bindList || []).forEach(bindItem => {
const currentPhNum = bindItem.phNum === '' || bindItem.phNum === null || bindItem.phNum === undefined ? 0 : Number(bindItem.phNum);
const originalPhNum = bindItem.originalPhNum === '' || bindItem.originalPhNum === null || bindItem.originalPhNum === undefined ? 0 : Number(bindItem.originalPhNum);
if (currentPhNum !== originalPhNum) {
changedList.push({
orderId: this.stockingDetailRow.id,
purchaseId: bindItem.purchaseId,
purchaseNo: bindItem.purchaseNo,
originalBindNum: originalPhNum,
bindNum: currentPhNum,
bindItem: bindItem
});
}
});
});
let saveQuotaPromise = Promise.resolve();
if (changedList.length > 0) {
saveQuotaPromise = Promise.all(changedList.map(item => savePurchaseOrderMap({
orderId: item.orderId,
purchaseId: item.purchaseId,
bindNum: item.bindNum
})));
}
saveQuotaPromise.then(() => {
return bindOrderSnCodes(this.stockingDetailRow.orderCode, this.outerSnProductRow.productCode, this.outerSnBindRow.purchaseNo, this.stockingDetailRow.id, this.outerSnBindRow.purchaseId, this.outerSnSelectedList);
}).then(response => {
loading.close();
this.$message.success(`成功分配 ${this.outerSnSelectedList.length} 个SN码` + (changedList.length > 0 ? ',并同步保存了配额修改' : ''));
this.outerSnDialogVisible = false;
if (changedList.length > 0) {
changedList.forEach(item => {
item.bindItem.originalPhNum = item.bindNum;
this.$delete(this.stockingBindDraftMap, item.purchaseId);
});
}
this.handleShowStockingDetail(this.stockingDetailRow);
this.getList();
}).catch(() => {
loading.close();
});
}).catch(() => {});
},
/** 格式化备货状态 */ /** 格式化备货状态 */
formatOrderStockingStatus(value) { formatOrderStockingStatus(value) {
const statusMap = { const statusMap = {
@ -1069,6 +1085,64 @@ export default {
BHWC: 'stocking-status--green' BHWC: 'stocking-status--green'
}; };
return classMap[value] || 'stocking-status--yellow'; return classMap[value] || 'stocking-status--yellow';
},
handleGenerateVirtualPurchase(item) {
this.currentPurchaseOrderData = null;
this.virtualPurchaseProductInfo = {
productCode: item.productCode,
model: item.model,
productType: item.productType,
vendorName: item.vendorName,
vendorCode: item.vendorCode,
orderNum: item.orderNum,
orderCode: this.stockingDetailRow.orderCode,
projectName: this.stockingDetailRow.projectName,
projectCode: this.stockingDetailRow.projectCode
};
this.purchaseOpen = true;
this.purchaseTitle = `生成虚拟采购单 - ${item.model || item.productCode}`;
},
submitPurchaseForm() {
this.$refs.purchaseOrderDetail.submitForm();
},
cancelPurchase() {
this.purchaseOpen = false;
},
handleOuterSnPageChange() {
},
handlePurchaseSuccess() {
this.purchaseOpen = false;
this.$message.success('采购单创建成功');
this.getList();
if (this.virtualPurchaseProductInfo && this.stockingDetailVisible) {
this.refreshCurrentProductBindList(this.virtualPurchaseProductInfo.productCode);
}
},
refreshCurrentProductBindList(productCode) {
const targetItem = this.stockingDetailList.find(item => item.productCode === productCode);
if (!targetItem) {
return;
}
this.loadAllBindData(this.stockingDetailRow.orderCode, targetItem).then(allBindList => {
const bindPageNum = targetItem.bindPageNum || 1;
const bindPageSize = targetItem.bindPageSize || this.stockingBindPageSize;
const startIndex = (bindPageNum - 1) * bindPageSize;
const endIndex = startIndex + bindPageSize;
const bindList = allBindList.slice(startIndex, endIndex);
this.stockingDetailList = this.stockingDetailList.map(item => {
if (item.productCode === productCode) {
return {
...item,
allBindList: allBindList,
bindList: bindList,
bindTotal: allBindList.length
};
}
return item;
});
}).catch(() => {
this.$message.error('刷新采购列表失败');
});
} }
} }
}; };
@ -1374,6 +1448,12 @@ export default {
border-bottom: 1px solid #e4e7ed; border-bottom: 1px solid #e4e7ed;
} }
.outer-sn-grid-header .pagination-container {
margin: 0;
padding: 0;
background: transparent;
}
.outer-sn-current-count { .outer-sn-current-count {
flex: 1; flex: 1;
margin-left: 16px; margin-left: 16px;

View File

@ -1,13 +1,13 @@
<template> <template>
<div> <div>
<el-table v-loading="loading" :data="logList"> <el-table v-loading="loading" :data="logList">
<el-table-column label="入库单号" align="center" prop="innerCode" /> <el-table-column label="入库单号" align="center" prop="innerCode" width="150" />
<el-table-column label="产品编码" align="center" prop="productCode" /> <el-table-column label="产品编码" align="center" prop="productCode" width="150" />
<el-table-column label="产品型号" align="center" prop="model" /> <el-table-column label="产品型号" align="center" prop="model" />
<el-table-column label="入库数量" align="center" prop="quantity" /> <el-table-column label="入库数量" align="center" prop="quantity" width="100" />
<el-table-column label="制造商" align="center" prop="vendorName" /> <el-table-column label="制造商" align="center" prop="vendorName" />
<el-table-column label="入库仓" align="center" prop="warehouseName" /> <el-table-column label="入库仓" align="center" prop="warehouseName" width="120" />
<el-table-column label="经办人" align="center" prop="createByName" /> <el-table-column label="经办人" align="center" prop="createByName" width="120" />
<el-table-column label="入库时间" align="center" prop="createTime" width="180"> <el-table-column label="入库时间" align="center" prop="createTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createTime) }}</span>

View File

@ -1,16 +1,16 @@
<template> <template>
<div> <div>
<el-table v-loading="loading" :data="logList"> <el-table v-loading="loading" :data="logList">
<el-table-column label="出库单号" align="center" prop="outerCode" /> <el-table-column label="出库单号" align="center" prop="outerCode" width="150" />
<el-table-column label="合同编号" align="center" prop="orderCode" /> <el-table-column label="合同编号" align="center" prop="orderCode" />
<el-table-column label="项目名称" align="center" prop="projectName" show-overflow-tooltip /> <el-table-column label="项目名称" align="center" prop="projectName" show-overflow-tooltip />
<el-table-column label="数量" align="center" prop="quantity" /> <el-table-column label="数量" align="center" prop="quantity" width="100" />
<el-table-column label="出库状态" align="center" prop="outerStatus"> <el-table-column label="出库状态" align="center" prop="outerStatus" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="outerStatusOptions" :value="scope.row.outerStatus"/> <dict-tag :options="outerStatusOptions" :value="scope.row.outerStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="经办人" align="center" prop="createByName" /> <el-table-column label="经办人" align="center" prop="createByName" width="120" />
<el-table-column label="出库时间" align="center" prop="createTime" width="180"> <el-table-column label="出库时间" align="center" prop="createTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createTime) }}</span>

View File

@ -383,7 +383,7 @@ export default {
return; return;
} }
this.form.inventoryInfoList=[] this.form.inventoryInfoList=[]
let quantity = Number(this.form.quantity); let quantity = Number(this.form.quantity) - Number(this.form.innerQuantity || 0);
let productSn = this.inputSn; let productSn = this.inputSn;
let snPrefix = ""; let snPrefix = "";
let snNumber = ""; let snNumber = "";
@ -548,10 +548,10 @@ export default {
this.$modal.msgWarning("请至少添加一条产品信息"); this.$modal.msgWarning("请至少添加一条产品信息");
return; return;
} }
if (this.form.quantity!==this.form.inventoryInfoList.length && !this.isServiceIn){ // if (this.form.quantity!==this.form.inventoryInfoList.length && !this.isServiceIn){
this.$modal.msgWarning("采购数量与入库数量不一致"); // this.$modal.msgWarning("");
return; // return;
} // }
if (this.form.id != null) { if (this.form.id != null) {
updateInner(this.form).then(response => { updateInner(this.form).then(response => {
this.$modal.msgSuccess("修改成功"); this.$modal.msgSuccess("修改成功");

View File

@ -61,6 +61,11 @@
</el-row> </el-row>
</el-form> </el-form>
<el-tabs v-model="activePurchaseNo" @tab-click="handleTabClick" v-if="filteredPurchaseOrderList.length > 0">
<el-tab-pane v-for="purchase in filteredPurchaseOrderList" :key="purchase.purchaseNo" :label="`${purchase.purchaseNo} (${purchase.phNum}台)`" :name="purchase.purchaseNo">
</el-tab-pane>
</el-tabs>
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleDownloadTemplate"></el-button> <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleDownloadTemplate"></el-button>
@ -100,6 +105,7 @@ import { addDelivery, listProductSn } from '@/api/inventory/delivery';
import {importSnData,exportDownloadTemplate} from '@/api/inventory/outer' import {importSnData,exportDownloadTemplate} from '@/api/inventory/outer'
import PurchaseOrderSelectDialog from '../../../purchaseorder/components/PurchaseOrderSelectDialog.vue'; import PurchaseOrderSelectDialog from '../../../purchaseorder/components/PurchaseOrderSelectDialog.vue';
import {handleTree} from "@/utils/ruoyi"; import {handleTree} from "@/utils/ruoyi";
import { productMatchBindList } from '@/api/project/order';
export default { export default {
name: "GenerateDeliveryForm", name: "GenerateDeliveryForm",
@ -137,7 +143,7 @@ export default {
warehouseId: undefined, warehouseId: undefined,
orderCode: undefined, orderCode: undefined,
}, },
isImported: false, // Flag to track if data is from import isImported: false,
isInitialLoad: false, isInitialLoad: false,
purchaseOrderSelectVisible: false, purchaseOrderSelectVisible: false,
queryProductType: ['1', '2', '99'], queryProductType: ['1', '2', '99'],
@ -145,8 +151,19 @@ export default {
warehouseId: null, warehouseId: null,
taxRate: 0.13, taxRate: 0.13,
warehouseName: '', warehouseName: '',
purchaseOrderList: [],
activePurchaseNo: '',
}; };
}, },
computed: {
filteredPurchaseOrderList() {
return this.purchaseOrderList.filter(purchase => {
const phNum = purchase.phNum || 0;
const bhNum = purchase.bhNum || 0;
return phNum > 0 && phNum > bhNum;
});
}
},
watch: { watch: {
'form.deliveryTimeType'(val) { 'form.deliveryTimeType'(val) {
if (val === '0') { if (val === '0') {
@ -191,11 +208,32 @@ export default {
this.isInitialLoad = true; this.isInitialLoad = true;
this.visible = true; this.visible = true;
this.$nextTick(() => { this.$nextTick(() => {
// resetForm/
this.form.notifierAddress = notifierAddress; this.form.notifierAddress = notifierAddress;
this.getSnList(); this.loadPurchaseOrderList();
}) })
}, },
loadPurchaseOrderList() {
const orderCode = this.queryParams.orderCode;
const productCode = this.queryParams.productCode;
if (!orderCode || !productCode) {
this.getSnList();
return;
}
productMatchBindList(orderCode, productCode).then(response => {
this.purchaseOrderList = response.rows || [];
const filtered = this.filteredPurchaseOrderList;
if (filtered.length > 0) {
this.activePurchaseNo = filtered[0].purchaseNo;
this.queryParams.purchaseNo = this.activePurchaseNo;
} else {
this.activePurchaseNo = '';
this.queryParams.purchaseNo = undefined;
}
this.getSnList();
}).catch(() => {
this.getSnList();
});
},
getSnList() { getSnList() {
listProductSn(this.queryParams).then(response => { listProductSn(this.queryParams).then(response => {
this.snList = response.rows; this.snList = response.rows;
@ -211,6 +249,13 @@ export default {
} }
}); });
}, },
handleTabClick(tab) {
this.activePurchaseNo = tab.name;
this.queryParams.purchaseNo = tab.name;
this.queryParams.pageNum = 1;
this.isInitialLoad = true;
this.getSnList();
},
handleSelectionChange(selection) { handleSelectionChange(selection) {
if (this.isImported && selection.length!=(this.productData.quantity - this.productData.deliveryGenerateQuantity - this.productData.deliveryConfirmQuantity)) { if (this.isImported && selection.length!=(this.productData.quantity - this.productData.deliveryGenerateQuantity - this.productData.deliveryConfirmQuantity)) {
this.$message.error("导入数据不允许取消勾选"); this.$message.error("导入数据不允许取消勾选");
@ -227,12 +272,11 @@ export default {
}); });
}, },
handleSelectPurchaseBeforeImport() { handleSelectPurchaseBeforeImport() {
if (((this.productData.orderType || '1') === '1' ) && !this.outerData.vendorName.startsWith('新华三') ) { // if (((this.productData.orderType || '1') === '1' ) && !this.outerData.vendorName.startsWith('') ) {
this.purchaseOrderSelectVisible = true; this.purchaseOrderSelectVisible = true;
}else{ // }else{
this.handleImport() // this.handleImport()
} // }
}, },
handlePurchaseOrderSelect(order) { handlePurchaseOrderSelect(order) {
this.warehouseId = order.warehouseId; this.warehouseId = order.warehouseId;
@ -304,6 +348,7 @@ export default {
outerCode: this.outerData.outerCode, outerCode: this.outerData.outerCode,
detailId: this.productData.id, detailId: this.productData.id,
productSnDataList: this.isImported ? this.snList : [], productSnDataList: this.isImported ? this.snList : [],
orderCode: this.queryParams.orderCode,
}; };
addDelivery(data).then(() => { addDelivery(data).then(() => {
@ -337,6 +382,7 @@ export default {
productCode: undefined, productCode: undefined,
warehouseId: undefined, warehouseId: undefined,
orderCode: undefined, orderCode: undefined,
purchaseNo: undefined,
}; };
this.isImported = false; this.isImported = false;
this.price = null; this.price = null;
@ -344,6 +390,8 @@ export default {
this.warehouseId = null; this.warehouseId = null;
this.purchaseNo = ''; this.purchaseNo = '';
this.warehouseName = ''; this.warehouseName = '';
this.purchaseOrderList = [];
this.activePurchaseNo = '';
} }
} }
}; };

View File

@ -205,6 +205,7 @@ import SelectProduct from "@/views/system/product/selectProduct";
import FileUpload from "@/components/FileUpload"; import FileUpload from "@/components/FileUpload";
import { getDicts } from "@/api/system/dict/data"; import { getDicts } from "@/api/system/dict/data";
import TaxRateInput from "@/components/TaxRateInput/TaxInput.vue"; import TaxRateInput from "@/components/TaxRateInput/TaxInput.vue";
import { listProduct } from "@/api/project/product";
import request from '@/utils/request' import request from '@/utils/request'
@ -260,6 +261,7 @@ export default {
approveStatus: 0, approveStatus: 0,
approveNode: null, approveNode: null,
confirmStatus: null, confirmStatus: null,
isVirtual: false,
omsPurchaseOrderItemList: [ omsPurchaseOrderItemList: [
{ {
productType: null, productType: null,
@ -488,6 +490,65 @@ export default {
} }
}); });
}, },
initVirtualPurchase(item) {
this.resetForm();
this.form.isVirtual = true;
const applyDefaults = () => {
if (item.vendorCode && this.vendorOptions.length > 0) {
const vendor = this.vendorOptions.find(v => v.vendorCode === item.vendorCode);
if (vendor) {
this.form.vendorId = vendor.vendorId;
this.$nextTick(() => {
this.handleVendorChange(vendor.vendorId);
});
}
}
if (item.productType && this.form.omsPurchaseOrderItemList.length > 0) {
this.$set(this.form.omsPurchaseOrderItemList[0], 'productType', item.productType);
if (item.productCode && item.vendorCode) {
listProduct({
productCode: item.productCode,
vendorCode: item.vendorCode,
type: item.productType,
pageNum: 1,
pageSize: 1
}).then(response => {
if (response.rows && response.rows.length > 0) {
const product = response.rows[0];
const firstItem = this.form.omsPurchaseOrderItemList[0];
this.$set(firstItem, 'productCode', product.productCode);
this.$set(firstItem, 'productModel', product.model);
this.$set(firstItem, 'productDescription', product.description);
this.$set(firstItem, 'quantity', item.orderNum || 1);
this.calculateRowTotal(firstItem);
}
}).catch(() => {
});
}
}
if (item.projectCode && item.projectName) {
this.form.remark = `${item.projectCode} ${item.projectName}`;
}
};
const vendorReady = this.vendorOptions.length > 0
? Promise.resolve()
: this.getVendorList();
const productTypeReady = this.productTypeOptions.length > 0
? Promise.resolve()
: getDicts('product_type').then(response => {
this.productTypeOptions = response.data;
});
Promise.all([vendorReady, productTypeReady]).then(() => {
this.$nextTick(applyDefaults);
});
},
resetForm() { resetForm() {
this.form = { this.form = {
id: null, id: null,
@ -511,6 +572,7 @@ export default {
approveStatus: 0, approveStatus: 0,
approveNode: null, approveNode: null,
confirmStatus: null, confirmStatus: null,
isVirtual: false,
omsPurchaseOrderItemList: [ omsPurchaseOrderItemList: [
{ {
productType: null, productType: null,

View File

@ -2,7 +2,7 @@
<el-dialog :title="title" :close-on-click-modal="false" :visible.sync="visible" width="80%" append-to-body @close="handleClose"> <el-dialog :title="title" :close-on-click-modal="false" :visible.sync="visible" width="80%" append-to-body @close="handleClose">
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="采购单号" prop="purchaseNo"> <el-form-item label="采购单号123" prop="purchaseNo">
<el-input <el-input
v-model="queryParams.purchaseNo" v-model="queryParams.purchaseNo"
placeholder="请输入采购单号" placeholder="请输入采购单号"
@ -55,7 +55,7 @@
<el-table-column label="单价" align="center" prop="price" width="100"/> <el-table-column label="单价" align="center" prop="price" width="100"/>
<el-table-column label="小计" align="center" prop="price" width="100"> <el-table-column label="小计" align="center" prop="price" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.quantity * scope.row.price}} {{ ((Number(scope.row.quantity) || 0) * (Number(scope.row.price) || 0)).toFixed(2) }}
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -129,6 +129,8 @@ export default {
watch: { watch: {
visible(val) { visible(val) {
if (val) { if (val) {
this.queryParams.type = this.type;
this.queryParams.productCode = this.productCode;
this.getList(); this.getList();
} }
} }
@ -155,10 +157,10 @@ export default {
this.handleQuery(); this.handleQuery();
}, },
handleSelect(row) { handleSelect(row) {
if (this.quantity && this.quantity!==row.quantity){ // if (this.quantity && this.quantity!==row.quantity){
this.$message.error("请选择数量为"+this.quantity+"的采购单"); // this.$message.error(""+this.quantity+"");
return // return
} // }
this.$emit("select", row); this.$emit("select", row);
this.handleClose(); this.handleClose();
}, },

View File

@ -189,7 +189,7 @@
>修改 >修改
</el-button> </el-button>
<el-button <el-button
v-if="scope.row.approveStatus === '0' || scope.row.approveStatus === '3'" v-if="(scope.row.approveStatus === '0' || scope.row.approveStatus === '3') && !scope.row.isVirtual"
size="mini" size="mini"
type="text" type="text"
icon="el-icon-s-promotion" icon="el-icon-s-promotion"

View File

@ -191,8 +191,8 @@ public class VueProjectOrderInfoController extends BaseController {
* SN * SN
*/ */
@GetMapping("/purchaseSnList") @GetMapping("/purchaseSnList")
public AjaxResult purchaseSnList(@RequestParam String purchaseNo, @RequestParam String orderCode) { public AjaxResult purchaseSnList(@RequestParam String purchaseNo, @RequestParam String orderCode, @RequestParam(required = false) String productCode) {
return AjaxResult.success(projectOrderInfoService.selectPurchaseSnList(purchaseNo, orderCode)); return AjaxResult.success(projectOrderInfoService.selectPurchaseSnList(purchaseNo, orderCode, productCode));
} }
/** /**

View File

@ -51,6 +51,7 @@ public class InventoryInfo extends BaseEntity
@Excel(name = "出库单号") @Excel(name = "出库单号")
private String outerCode; private String outerCode;
private String orderCode; private String orderCode;
private String purchaseNo;
/** 所属仓库 */ /** 所属仓库 */
@Excel(name = "所属仓库") @Excel(name = "所属仓库")

View File

@ -128,6 +128,9 @@ public class OmsPurchaseOrder extends BaseEntity
@Excel(name = "备注", wrapText = true) @Excel(name = "备注", wrapText = true)
private String remark; private String remark;
/** 是否虚拟采购单 */
private Boolean isVirtual;
/** 删除标志0正常 1删除 */ /** 删除标志0正常 1删除 */
private Integer delFlag; private Integer delFlag;
@ -164,14 +167,12 @@ public class OmsPurchaseOrder extends BaseEntity
this.code = code; this.code = code;
this.value = value; this.value = value;
} }
} }
@Getter @Getter
public enum FlowTypeEnum { public enum FlowTypeEnum {
ONLINE("online", "线上"), ONLINE("online", "线上"),
OFFLINE("offline", "线下"), OFFLINE("offline", "线下"),
; ;
private final String value; private final String value;
@ -181,25 +182,22 @@ public class OmsPurchaseOrder extends BaseEntity
this.code = code; this.code = code;
this.value = value; this.value = value;
} }
} }
@Getter
@Getter
public enum StatusEnum { public enum StatusEnum {
WAIT_COMPLETED(0, "待入库"), WAIT_COMPLETED(0, "待入库"),
PART_COMPLETED(1, "部分入库"), PART_COMPLETED(1, "部分入库"),
COMPLETED(2, "已完成"), COMPLETED(2, "已完成"),
; ;
private final String value; private final String value;
private final Integer code; private final Integer code;
StatusEnum(Integer code, String value) { StatusEnum(Integer code, String value) {
this.code = code; this.code = code;
this.value = value; this.value = value;
} }
} }
} }

View File

@ -83,6 +83,8 @@ public class OmsPurchaseOrderHistory extends BaseEntity
/** 确认状态0待确认 1已确认 */ /** 确认状态0待确认 1已确认 */
private String confirmStatus; private String confirmStatus;
private Boolean isVirtual;
/** 删除标志0正常 1删除 */ /** 删除标志0正常 1删除 */
private Integer delFlag; private Integer delFlag;
private String flowType; private String flowType;

View File

@ -11,5 +11,7 @@ public class OmsPurchaseOrderMap {
private Long purchaseId; private Long purchaseId;
private String productCode;
private Integer bindNum; private Integer bindNum;
} }

View File

@ -0,0 +1,34 @@
package com.ruoyi.sip.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderProductBindAmountDto {
/** 产品编码 */
private String productCode;
/** 成本含税 */
private BigDecimal costWithTax;
/** 成本不含税 */
private BigDecimal costWithoutTax;
/** 不含税收入 */
private BigDecimal amountWithoutTax;
/** 毛利 */
private BigDecimal grossProfit;
/** 毛利率 */
private BigDecimal grossProfitRate;
/** 订单备货状态true: 已备货完成false: 未备货完成) */
private Boolean orderStockingStatus;
}

View File

@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@ -24,6 +26,9 @@ public class OrderProductMatchBindDto {
/** 制造商 */ /** 制造商 */
private String vendorAddress; private String vendorAddress;
/** 单价 */
private Double price;
/** 采购数量 */ /** 采购数量 */
private Integer cgNum; private Integer cgNum;

View File

@ -17,6 +17,15 @@ public class OrderProductMatchDto {
/** 产品型号 */ /** 产品型号 */
private String model; private String model;
/** 产品类型 */
private String productType;
/** 制造商编码 */
private String vendorCode;
/** 制造商名称 */
private String vendorName;
/** 订单数量 */ /** 订单数量 */
private Integer orderNum; private Integer orderNum;

View File

@ -0,0 +1,20 @@
package com.ruoyi.sip.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UnboundPurchaseOrderProductDto {
/** 合同编号 */
private String orderCode;
/** 产品编码 */
private String productCode;
/** 入库单号 */
private String innerCode;
}

View File

@ -12,11 +12,9 @@ import com.ruoyi.sip.domain.OmsReceivableBill;
import com.ruoyi.sip.domain.ProjectInfo; import com.ruoyi.sip.domain.ProjectInfo;
import com.ruoyi.sip.domain.ProjectOrderInfo; import com.ruoyi.sip.domain.ProjectOrderInfo;
import com.ruoyi.sip.domain.ProjectProductInfo; import com.ruoyi.sip.domain.ProjectProductInfo;
import com.ruoyi.sip.dto.OrderProductBindAmountDto;
import com.ruoyi.sip.llm.tools.support.AbstractMcpToolProvider; import com.ruoyi.sip.llm.tools.support.AbstractMcpToolProvider;
import com.ruoyi.sip.mapper.InventoryInfoMapper; import com.ruoyi.sip.mapper.*;
import com.ruoyi.sip.mapper.OmsInventoryInnerMapper;
import com.ruoyi.sip.mapper.OmsPurchaseOrderMapper;
import com.ruoyi.sip.mapper.ProjectInfoMapper;
import com.ruoyi.sip.service.IInventoryInfoService; import com.ruoyi.sip.service.IInventoryInfoService;
import com.ruoyi.sip.service.IInventoryOuterService; import com.ruoyi.sip.service.IInventoryOuterService;
import com.ruoyi.sip.service.IOmsReceivableBillService; import com.ruoyi.sip.service.IOmsReceivableBillService;
@ -43,7 +41,7 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
private static final String INDUSTRY_TYPE_DICT_TYPE = "bg_hysy"; private static final String INDUSTRY_TYPE_DICT_TYPE = "bg_hysy";
private static final String INDUSTRY_TYPE_YYS_DICT_TYPE = "bg_yys"; private static final String INDUSTRY_TYPE_YYS_DICT_TYPE = "bg_yys";
private static final String PROJECT_STAGE_DICT_TYPE = "project_stage"; private static final String PROJECT_STAGE_DICT_TYPE = "project_stage";
private static final String NOT_DELIVERED_TEXT = "未货完成"; private static final String NOT_DELIVERED_TEXT = "未货完成";
@Autowired @Autowired
private IProjectOrderInfoService projectOrderInfoService; private IProjectOrderInfoService projectOrderInfoService;
@ -72,6 +70,9 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
@Autowired @Autowired
private IOmsReceivableBillService omsReceivableBillService; private IOmsReceivableBillService omsReceivableBillService;
@Autowired
private ProjectOrderInfoMapper projectOrderInfoMapper;
@Override @Override
protected String getToolName() { protected String getToolName() {
return "project_order_info"; return "project_order_info";
@ -195,11 +196,11 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
item.put("archiveTime", formatDateTime(orderInfo.getApproveTime())); item.put("archiveTime", formatDateTime(orderInfo.getApproveTime()));
ProductGroupSummary softwareSummary = appendProductFields(item, "software", softwareList, ProductGroupSummary softwareSummary = appendProductFields(item, "software", softwareList,
orderShipmentMap, Collections.emptyMap(), true); orderShipmentMap, Collections.emptyMap(), true, orderInfo.getOrderCode());
ProductGroupSummary hardwareSummary = appendProductFields(item, "hardware", hardwareList, ProductGroupSummary hardwareSummary = appendProductFields(item, "hardware", hardwareList,
orderShipmentMap, Collections.emptyMap(), true); orderShipmentMap, Collections.emptyMap(), true, orderInfo.getOrderCode());
ProductGroupSummary serviceSummary = appendProductFields(item, "service", serviceList, ProductGroupSummary serviceSummary = appendProductFields(item, "service", serviceList,
Collections.emptyMap(), serviceCostMap.getOrDefault(orderInfo.getOrderCode(), Collections.emptyMap()), false); Collections.emptyMap(), serviceCostMap.getOrDefault(orderInfo.getOrderCode(), Collections.emptyMap()), false, orderInfo.getOrderCode());
BigDecimal orderAmountWithTax = defaultValue(orderInfo.getShipmentAmount()); BigDecimal orderAmountWithTax = defaultValue(orderInfo.getShipmentAmount());
BigDecimal discountAmountWithTax = softwareSummary.salesWithTax BigDecimal discountAmountWithTax = softwareSummary.salesWithTax
@ -208,20 +209,21 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
BigDecimal discountAmountWithoutTax = softwareSummary.salesWithoutTax BigDecimal discountAmountWithoutTax = softwareSummary.salesWithoutTax
.add(hardwareSummary.salesWithoutTax) .add(hardwareSummary.salesWithoutTax)
.add(serviceSummary.salesWithoutTax); .add(serviceSummary.salesWithoutTax);
boolean allDelivered = softwareSummary.allDelivered && hardwareSummary.allDelivered && serviceSummary.allDelivered; boolean allStocked = softwareSummary.allStocked && hardwareSummary.allStocked && serviceSummary.allStocked;
BigDecimal costWithTax = softwareSummary.costWithTax.add(hardwareSummary.costWithTax).add(serviceSummary.costWithTax); BigDecimal costWithTax = softwareSummary.costWithTax.add(hardwareSummary.costWithTax).add(serviceSummary.costWithTax);
BigDecimal costWithoutTax = softwareSummary.costWithoutTax.add(hardwareSummary.costWithoutTax).add(serviceSummary.costWithoutTax); BigDecimal costWithoutTax = softwareSummary.costWithoutTax.add(hardwareSummary.costWithoutTax).add(serviceSummary.costWithoutTax);
item.put("orderAmountWithTax", orderAmountWithTax); item.put("orderAmountWithTax", orderAmountWithTax);
item.put("discountedOrderAmountWithTax", discountAmountWithTax); item.put("discountedOrderAmountWithTax", discountAmountWithTax);
item.put("discountedOrderAmountWithoutTax", discountAmountWithoutTax); item.put("discountedOrderAmountWithoutTax", discountAmountWithoutTax);
item.put("costTotalWithTax", allDelivered ? costWithTax : NOT_DELIVERED_TEXT); item.put("costTotalWithTax", allStocked ? costWithTax : NOT_DELIVERED_TEXT);
item.put("costTotalWithoutTax", allDelivered ? costWithoutTax : NOT_DELIVERED_TEXT); item.put("costTotalWithoutTax", allStocked ? costWithoutTax : NOT_DELIVERED_TEXT);
if (allDelivered) { if (allStocked) {
BigDecimal grossProfit = discountAmountWithoutTax.subtract(costWithoutTax); BigDecimal totalGrossProfit = softwareSummary.grossProfit.add(hardwareSummary.grossProfit).add(serviceSummary.grossProfit);
item.put("grossProfit", grossProfit); BigDecimal totalAmountWithoutTax = softwareSummary.amountWithoutTax.add(hardwareSummary.amountWithoutTax).add(serviceSummary.amountWithoutTax);
item.put("grossProfitRate", percentage(grossProfit, costWithoutTax)); item.put("grossProfit", totalGrossProfit);
item.put("grossProfitRate", percentage(totalGrossProfit, totalAmountWithoutTax));
} else { } else {
item.put("grossProfit", NOT_DELIVERED_TEXT); item.put("grossProfit", NOT_DELIVERED_TEXT);
item.put("grossProfitRate", NOT_DELIVERED_TEXT); item.put("grossProfitRate", NOT_DELIVERED_TEXT);
@ -501,7 +503,8 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
List<ProjectProductInfo> productInfos, List<ProjectProductInfo> productInfos,
Map<String, ProductShipmentSummary> shipmentMap, Map<String, ProductShipmentSummary> shipmentMap,
Map<String, ProductCostSummary> serviceCostMap, Map<String, ProductCostSummary> serviceCostMap,
boolean shipmentRequired) { boolean shipmentRequired,
String orderCode) {
ProductGroupSummary summary = new ProductGroupSummary(); ProductGroupSummary summary = new ProductGroupSummary();
if (CollUtil.isEmpty(productInfos)) { if (CollUtil.isEmpty(productInfos)) {
return summary; return summary;
@ -509,9 +512,29 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
for (int i = 0; i < productInfos.size(); i++) { for (int i = 0; i < productInfos.size(); i++) {
int index = i + 1; int index = i + 1;
ProjectProductInfo productInfo = productInfos.get(i); ProjectProductInfo productInfo = productInfos.get(i);
ProductCostDisplay costDisplay = shipmentRequired
? buildShipmentProductCostDisplay(productInfo, shipmentMap.get(productInfo.getProductBomCode())) OrderProductBindAmountDto bindAmountDto = projectOrderInfoMapper.selectOrderProductBindAmount(
: buildServiceProductCostDisplay(serviceCostMap.get(productInfo.getProductBomCode())); orderCode, productInfo.getProductBomCode());
ProductCostDisplay costDisplay = new ProductCostDisplay();
if (bindAmountDto != null) {
costDisplay.delivered = bindAmountDto.getOrderStockingStatus() != null && bindAmountDto.getOrderStockingStatus();
costDisplay.costWithTax = defaultValue(bindAmountDto.getCostWithTax());
costDisplay.costWithoutTax = defaultValue(bindAmountDto.getCostWithoutTax());
costDisplay.displayValue = costDisplay.costWithTax;
summary.amountWithoutTax = summary.amountWithoutTax.add(defaultValue(bindAmountDto.getAmountWithoutTax()));
summary.grossProfit = summary.grossProfit.add(defaultValue(bindAmountDto.getGrossProfit()));
summary.grossProfitRate = defaultValue(bindAmountDto.getGrossProfitRate());
summary.orderStockingStatus = bindAmountDto.getOrderStockingStatus();
if (bindAmountDto.getOrderStockingStatus() == null || !bindAmountDto.getOrderStockingStatus()) {
summary.allStocked = false;
}
} else {
costDisplay.delivered = false;
costDisplay.displayValue = NOT_DELIVERED_TEXT;
summary.allStocked = false;
}
item.put(prefix + "Code" + index, productInfo.getProductBomCode()); item.put(prefix + "Code" + index, productInfo.getProductBomCode());
item.put(prefix + "Level2Type" + index, productInfo.getLevel2Type()); item.put(prefix + "Level2Type" + index, productInfo.getLevel2Type());
@ -520,6 +543,9 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
item.put(prefix + "SalesAmount" + index, defaultValue(productInfo.getAllPrice())); item.put(prefix + "SalesAmount" + index, defaultValue(productInfo.getAllPrice()));
item.put(prefix + "CostAmount" + index, costDisplay.displayValue); item.put(prefix + "CostAmount" + index, costDisplay.displayValue);
item.put(prefix + "TaxRate" + index, productInfo.getTaxRate()); item.put(prefix + "TaxRate" + index, productInfo.getTaxRate());
item.put(prefix + "GrossProfit" + index, bindAmountDto != null ? defaultValue(bindAmountDto.getGrossProfit()) : BigDecimal.ZERO);
item.put(prefix + "GrossProfitRate" + index, bindAmountDto != null ? defaultValue(bindAmountDto.getGrossProfitRate()) : BigDecimal.ZERO);
item.put(prefix + "OrderStockingStatus" + index, bindAmountDto != null ? bindAmountDto.getOrderStockingStatus() : false);
summary.salesWithTax = summary.salesWithTax.add(defaultValue(productInfo.getAllPrice())); summary.salesWithTax = summary.salesWithTax.add(defaultValue(productInfo.getAllPrice()));
summary.salesWithoutTax = summary.salesWithoutTax.add(toOrderAmountWithoutTax(defaultValue(productInfo.getAllPrice()), productInfo.getTaxRate())); summary.salesWithoutTax = summary.salesWithoutTax.add(toOrderAmountWithoutTax(defaultValue(productInfo.getAllPrice()), productInfo.getTaxRate()));
@ -705,7 +731,7 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
"softwareCodeX", "软件产品第 X 行编码,对应 softwareLevel2TypeX/softwareModelX/softwareQuantityX/softwareSalesAmountX/softwareCostAmountX/softwareTaxRateX", "softwareCodeX", "软件产品第 X 行编码,对应 softwareLevel2TypeX/softwareModelX/softwareQuantityX/softwareSalesAmountX/softwareCostAmountX/softwareTaxRateX",
"hardwareCodeX", "硬件产品第 X 行编码,对应 hardwareLevel2TypeX/hardwareModelX/hardwareQuantityX/hardwareSalesAmountX/hardwareCostAmountX/hardwareTaxRateX", "hardwareCodeX", "硬件产品第 X 行编码,对应 hardwareLevel2TypeX/hardwareModelX/hardwareQuantityX/hardwareSalesAmountX/hardwareCostAmountX/hardwareTaxRateX",
"serviceCodeX", "服务产品第 X 行编码,对应 serviceLevel2TypeX/serviceModelX/serviceQuantityX/serviceSalesAmountX/serviceCostAmountX/serviceTaxRateX", "serviceCodeX", "服务产品第 X 行编码,对应 serviceLevel2TypeX/serviceModelX/serviceQuantityX/serviceSalesAmountX/serviceCostAmountX/serviceTaxRateX",
"cost_rule", "软件和硬件未发货完成时成本字段返回“未发货完成”;服务默认视为已完成;订单不含税成本为各产品按各自税率换算后求和" "cost_rule", "所有产品未配货完成时成本字段返回“未配货完成”;订单不含税成本为各产品按各自税率换算后求和"
)); ));
return metadata; return metadata;
} }
@ -813,10 +839,15 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
private static class ProductGroupSummary { private static class ProductGroupSummary {
private boolean allDelivered = true; private boolean allDelivered = true;
private boolean allStocked = true;
private BigDecimal salesWithTax = BigDecimal.ZERO; private BigDecimal salesWithTax = BigDecimal.ZERO;
private BigDecimal salesWithoutTax = BigDecimal.ZERO; private BigDecimal salesWithoutTax = BigDecimal.ZERO;
private BigDecimal amountWithoutTax = BigDecimal.ZERO;
private BigDecimal costWithTax = BigDecimal.ZERO; private BigDecimal costWithTax = BigDecimal.ZERO;
private BigDecimal costWithoutTax = BigDecimal.ZERO; private BigDecimal costWithoutTax = BigDecimal.ZERO;
private BigDecimal grossProfit = BigDecimal.ZERO;
private BigDecimal grossProfitRate = BigDecimal.ZERO;
private Boolean orderStockingStatus = false;
} }
private static class ReceivableSummary { private static class ReceivableSummary {

View File

@ -89,4 +89,6 @@ public interface InventoryInfoMapper
int updateOrderCodeByProductSnList(@Param("productSnList") List<String> productSnList, @Param("orderCode") String orderCode); int updateOrderCodeByProductSnList(@Param("productSnList") List<String> productSnList, @Param("orderCode") String orderCode);
int countByOrderCodeAndPurchaseNo(@Param("orderCode") String orderCode, @Param("purchaseNo") String purchaseNo); int countByOrderCodeAndPurchaseNo(@Param("orderCode") String orderCode, @Param("purchaseNo") String purchaseNo);
void clearOrderCodeByIds(@Param("idList") List<Long> idList);
} }

View File

@ -5,7 +5,9 @@ import org.apache.ibatis.annotations.Param;
public interface OmsPurchaseOrderMapMapper { public interface OmsPurchaseOrderMapMapper {
OmsPurchaseOrderMap selectByOrderIdAndPurchaseId(@Param("orderId") Long orderId, @Param("purchaseId") Long purchaseId); OmsPurchaseOrderMap selectByOrderIdAndPurchaseId(@Param("orderId") Long orderId,
@Param("purchaseId") Long purchaseId,
@Param("productCode") String productCode);
int insertOmsPurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap); int insertOmsPurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap);

View File

@ -5,10 +5,12 @@ import java.util.List;
import com.ruoyi.sip.domain.InventoryDelivery; import com.ruoyi.sip.domain.InventoryDelivery;
import com.ruoyi.sip.domain.ProjectOrderInfo; import com.ruoyi.sip.domain.ProjectOrderInfo;
import com.ruoyi.sip.dto.HomepageQueryDto; import com.ruoyi.sip.dto.HomepageQueryDto;
import com.ruoyi.sip.dto.OrderProductBindAmountDto;
import com.ruoyi.sip.dto.OrderProductMatchBindDto; import com.ruoyi.sip.dto.OrderProductMatchBindDto;
import com.ruoyi.sip.dto.OrderProductMatchDto; import com.ruoyi.sip.dto.OrderProductMatchDto;
import com.ruoyi.sip.dto.OrderProductMatchSnDetailDto; import com.ruoyi.sip.dto.OrderProductMatchSnDetailDto;
import com.ruoyi.sip.dto.StatisticsDetailDto; import com.ruoyi.sip.dto.StatisticsDetailDto;
import com.ruoyi.sip.dto.UnboundPurchaseOrderProductDto;
import com.ruoyi.sip.vo.OrderInfoVo; import com.ruoyi.sip.vo.OrderInfoVo;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -107,8 +109,15 @@ public interface ProjectOrderInfoMapper
int selectProductMatchSnCountlList(@Param("purchaseNo") String purchaseNo); int selectProductMatchSnCountlList(@Param("purchaseNo") String purchaseNo);
int selectPurchaseOrderMapBindNum(@Param("purchaseNo") String purchaseNo, int selectPurchaseOrderMapBindNum(@Param("purchaseNo") String purchaseNo,
@Param("orderCode") String orderCode); @Param("orderCode") String orderCode,
@Param("productCode") String productCode);
List<OrderProductMatchSnDetailDto> selectProductMatchSnDetailList(@Param("purchaseNo") String purchaseNo); List<OrderProductMatchSnDetailDto> selectProductMatchSnDetailList(@Param("purchaseNo") String purchaseNo,
@Param("productCode") String productCode);
OrderProductBindAmountDto selectOrderProductBindAmount(@Param("orderCode") String orderCode,
@Param("productCode") String productCode);
List<UnboundPurchaseOrderProductDto> selectUnboundPurchaseOrderProductList();
} }

View File

@ -101,5 +101,7 @@ public interface IOmsPurchaseOrderService
OmsPurchaseOrder selectOmsPurchaseOrderByNo(String purchaseNo); OmsPurchaseOrder selectOmsPurchaseOrderByNo(String purchaseNo);
List<OmsPurchaseOrderItem> listByItemId(Long itemId);
AddToNexRes addToNex(AddToNexReq addToNexReq); AddToNexRes addToNex(AddToNexReq addToNexReq);
} }

View File

@ -118,8 +118,10 @@ public interface IProjectOrderInfoService
int savePurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap); int savePurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap);
OrderProductMatchSnDto selectPurchaseSnList(String purchaseNo, String orderCode); OrderProductMatchSnDto selectPurchaseSnList(String purchaseNo, String orderCode, String productCode);
int bindOrderSnCodes(BindOrderSnCodesDto params); int bindOrderSnCodes(BindOrderSnCodesDto params);
void refreshOrderStockingStatus(String orderCode);
} }

View File

@ -67,6 +67,8 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
private IProjectOrderInfoRecallService projectOrderInfoRecallService; private IProjectOrderInfoRecallService projectOrderInfoRecallService;
@Autowired @Autowired
private OmsPurchaseOrderMapMapper omsPurchaseOrderMapMapper; private OmsPurchaseOrderMapMapper omsPurchaseOrderMapMapper;
@Autowired
private IInventoryOuterDetailService inventoryOuterDetailService;
@Override @Override
public ExecutionOrderVo selectInfo(Long id) { public ExecutionOrderVo selectInfo(Long id) {
ExecutionOrderVo vo = new ExecutionOrderVo(); ExecutionOrderVo vo = new ExecutionOrderVo();
@ -310,6 +312,10 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
inventoryOuter.setOrderCode(projectOrderInfo.getOrderCode()); inventoryOuter.setOrderCode(projectOrderInfo.getOrderCode());
List<InventoryOuter> inventoryOuters = outerService.selectInventoryOuterList(inventoryOuter); List<InventoryOuter> inventoryOuters = outerService.selectInventoryOuterList(inventoryOuter);
if (CollUtil.isNotEmpty(inventoryOuters)) { if (CollUtil.isNotEmpty(inventoryOuters)) {
List<String> outerCodeList = inventoryOuters.stream()
.map(InventoryOuter::getOuterCode)
.collect(Collectors.toList());
inventoryOuterDetailService.deleteByOuterCode(outerCodeList);
outerService.deleteInventoryOuterByIds(inventoryOuters.stream().map(item -> item.getId().toString()).collect(Collectors.joining(","))); outerService.deleteInventoryOuterByIds(inventoryOuters.stream().map(item -> item.getId().toString()).collect(Collectors.joining(",")));
} }
Map<String, Long> outerSumMap = inventoryOuters.stream().collect(Collectors.toMap(InventoryOuter::getProductCode, InventoryOuter::getQuantity, Long::sum)); Map<String, Long> outerSumMap = inventoryOuters.stream().collect(Collectors.toMap(InventoryOuter::getProductCode, InventoryOuter::getQuantity, Long::sum));

View File

@ -14,8 +14,10 @@ import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.dto.ApiDataQueryDto; import com.ruoyi.sip.dto.ApiDataQueryDto;
import com.ruoyi.sip.dto.inventory.InventoryDeliveryDetailExcelDto; import com.ruoyi.sip.dto.inventory.InventoryDeliveryDetailExcelDto;
import com.ruoyi.sip.mapper.InventoryInfoMapper;
import com.ruoyi.sip.mapper.InventoryOuterDetailMapper; import com.ruoyi.sip.mapper.InventoryOuterDetailMapper;
import com.ruoyi.sip.mapper.InventoryOuterMapper; import com.ruoyi.sip.mapper.InventoryOuterMapper;
import com.ruoyi.sip.mapper.OmsPurchaseOrderMapMapper;
import com.ruoyi.sip.service.*; import com.ruoyi.sip.service.*;
import com.ruoyi.sip.vo.DeliveryApproveVo; import com.ruoyi.sip.vo.DeliveryApproveVo;
import com.ruoyi.sip.vo.DeliveryInfoVo; import com.ruoyi.sip.vo.DeliveryInfoVo;
@ -69,6 +71,12 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
private IOmsPayableBillService payableBillService; private IOmsPayableBillService payableBillService;
@Autowired @Autowired
private IOmsReceivableBillService billService; private IOmsReceivableBillService billService;
@Autowired
private IOmsPurchaseOrderService omsPurchaseOrderService;
@Resource
private OmsPurchaseOrderMapMapper omsPurchaseOrderMapMapper;
@Resource
private InventoryInfoMapper inventoryInfoMapper;
@Value("${oms.inventory.innerTax:0.13}") @Value("${oms.inventory.innerTax:0.13}")
private String defaultTax; private String defaultTax;
@ -104,6 +112,81 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
@Override @Override
public int insertInventoryDelivery(InventoryDelivery inventoryDelivery) { public int insertInventoryDelivery(InventoryDelivery inventoryDelivery) {
List<String> productSnList = inventoryDelivery.getProductSnList();
List<InventoryInfo> productSnDataList = inventoryDelivery.getProductSnDataList();
if (CollUtil.isEmpty(productSnList) && CollUtil.isEmpty(productSnDataList)) {
throw new ServiceException("发货清单为空,保存失败");
}
if (StringUtils.isNotEmpty(inventoryDelivery.getOrderCode())) {
ProjectOrderInfo orderInfo = projectOrderInfoService.selectProjectOrderInfoByOrderCode(inventoryDelivery.getOrderCode());
if (orderInfo == null) {
throw new ServiceException("订单信息不存在");
}
if (StringUtils.isNotEmpty(inventoryDelivery.getPurchaseNo())) {
int newSnCount = CollUtil.isEmpty(productSnList) ? productSnDataList.size() : productSnList.size();
OmsPurchaseOrder purchaseOrder = omsPurchaseOrderService.selectOmsPurchaseOrderByNo(inventoryDelivery.getPurchaseNo());
if (purchaseOrder == null) {
throw new ServiceException("采购单信息不存在");
}
OmsPurchaseOrderMap purchaseOrderMap = omsPurchaseOrderMapMapper.selectByOrderIdAndPurchaseId(orderInfo.getId(), purchaseOrder.getId(), inventoryDelivery.getProductCode());
if (purchaseOrderMap == null || purchaseOrderMap.getBindNum() == null || purchaseOrderMap.getBindNum() <= 0) {
throw new ServiceException("当前订单与采购单未建立绑定关系或绑定数量为0");
}
int totalBindNum = purchaseOrderMap.getBindNum();
int alreadyBindNum = inventoryInfoMapper.countByOrderCodeAndPurchaseNo(inventoryDelivery.getOrderCode(), inventoryDelivery.getPurchaseNo());
int remainingNum = totalBindNum - alreadyBindNum;
if (newSnCount > remainingNum) {
throw new ServiceException(String.format("新增SN码数量(%d)超过剩余可新增数量(%d),总绑定数(%d),已绑定数(%d)", newSnCount, remainingNum, totalBindNum, alreadyBindNum));
}
} else if (CollUtil.isNotEmpty(productSnList)) {
List<InventoryInfo> inventoryInfoList = inventoryInfoMapper.listByProductSnList(productSnList);
if (CollUtil.isEmpty(inventoryInfoList)) {
throw new ServiceException("未找到SN码对应的库存信息");
}
Map<String, List<InventoryInfo>> innerCodeMap = inventoryInfoList.stream()
.filter(info -> StringUtils.isNotEmpty(info.getInnerCode()))
.collect(Collectors.groupingBy(InventoryInfo::getInnerCode));
Map<String, Long> purchaseNoCountMap = new HashMap<>();
for (Map.Entry<String, List<InventoryInfo>> entry : innerCodeMap.entrySet()) {
String innerCode = entry.getKey();
OmsInventoryInner queryInner = new OmsInventoryInner();
queryInner.setInnerCode(innerCode);
List<OmsInventoryInner> innerList = omsInventoryInnerService.selectOmsInventoryInnerList(queryInner);
if (CollUtil.isNotEmpty(innerList) && StringUtils.isNotEmpty(innerList.get(0).getPurchaseNo())) {
String purchaseNo = innerList.get(0).getPurchaseNo();
purchaseNoCountMap.put(purchaseNo, purchaseNoCountMap.getOrDefault(purchaseNo, 0L) + entry.getValue().size());
}
}
for (Map.Entry<String, Long> entry : purchaseNoCountMap.entrySet()) {
String purchaseNo = entry.getKey();
long newSnCount = entry.getValue();
OmsPurchaseOrder purchaseOrder = omsPurchaseOrderService.selectOmsPurchaseOrderByNo(purchaseNo);
if (purchaseOrder == null) {
throw new ServiceException(String.format("采购单[%s]信息不存在", purchaseNo));
}
OmsPurchaseOrderMap purchaseOrderMap = omsPurchaseOrderMapMapper.selectByOrderIdAndPurchaseId(orderInfo.getId(), purchaseOrder.getId(), inventoryDelivery.getProductCode());
if (purchaseOrderMap == null || purchaseOrderMap.getBindNum() == null || purchaseOrderMap.getBindNum() <= 0) {
throw new ServiceException(String.format("订单与采购单[%s]未建立绑定关系或绑定数量为0", purchaseNo));
}
int totalBindNum = purchaseOrderMap.getBindNum();
int alreadyBindNum = inventoryInfoMapper.countByOrderCodeAndPurchaseNo(inventoryDelivery.getOrderCode(), purchaseNo);
int remainingNum = totalBindNum - alreadyBindNum;
if (newSnCount > remainingNum) {
throw new ServiceException(String.format("采购单[%s]新增SN码数量(%d)超过剩余可新增数量(%d),总绑定数(%d),已绑定数(%d)",
purchaseNo, newSnCount, remainingNum, totalBindNum, alreadyBindNum));
}
}
}
}
Date nowDate = DateUtils.getNowDate(); Date nowDate = DateUtils.getNowDate();
inventoryDelivery.setCreateTime(nowDate); inventoryDelivery.setCreateTime(nowDate);
String currentUserId = ShiroUtils.getUserId().toString(); String currentUserId = ShiroUtils.getUserId().toString();
@ -112,12 +195,6 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
inventoryDelivery.setUpdateBy(currentUserId); inventoryDelivery.setUpdateBy(currentUserId);
inventoryDelivery.setUpdateTime(nowDate); inventoryDelivery.setUpdateTime(nowDate);
inventoryDelivery.setDeliveryStatus(InventoryDelivery.DeliveryStatusEnum.WAIT_DELIVERY.getCode()); inventoryDelivery.setDeliveryStatus(InventoryDelivery.DeliveryStatusEnum.WAIT_DELIVERY.getCode());
//处理库存
List<String> productSnList = inventoryDelivery.getProductSnList();
List<InventoryInfo> productSnDataList = inventoryDelivery.getProductSnDataList();
if (CollUtil.isEmpty(productSnList) && CollUtil.isEmpty(productSnDataList)) {
throw new ServiceException("发货清单为空,保存失败");
}
//修改数据的时候同步修改出库价 //修改数据的时候同步修改出库价
BigDecimal bigDecimal = inventoryOuterMapper.selectOutPriceByCode(inventoryDelivery.getOuterCode()); BigDecimal bigDecimal = inventoryOuterMapper.selectOutPriceByCode(inventoryDelivery.getOuterCode());
@ -131,6 +208,7 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
info.setUpdateBy(currentUserId); info.setUpdateBy(currentUserId);
info.setUpdateTime(nowDate); info.setUpdateTime(nowDate);
info.setOuterPrice(bigDecimal); info.setOuterPrice(bigDecimal);
info.setOrderCode(inventoryDelivery.getOrderCode());
OmsInventoryDeliveryDetail detail = new OmsInventoryDeliveryDetail(); OmsInventoryDeliveryDetail detail = new OmsInventoryDeliveryDetail();
detail.setProductSn(item); detail.setProductSn(item);
detailList.add(detail); detailList.add(detail);
@ -149,6 +227,7 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
inventoryInfo.setUpdateBy(currentUserId); inventoryInfo.setUpdateBy(currentUserId);
inventoryInfo.setUpdateTime(nowDate); inventoryInfo.setUpdateTime(nowDate);
inventoryInfo.setOuterPrice(bigDecimal); inventoryInfo.setOuterPrice(bigDecimal);
inventoryInfo.setOrderCode(inventoryDelivery.getOrderCode());
OmsInventoryDeliveryDetail detail = new OmsInventoryDeliveryDetail(); OmsInventoryDeliveryDetail detail = new OmsInventoryDeliveryDetail();
detail.setProductSn(inventoryInfo.getProductSn()); detail.setProductSn(inventoryInfo.getProductSn());
detailList.add(detail); detailList.add(detail);
@ -168,6 +247,7 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
} }
deliveryDetailService.saveBatch(detailList); deliveryDetailService.saveBatch(detailList);
} }
projectOrderInfoService.refreshOrderStockingStatus(inventoryDelivery.getOrderCode());
return i; return i;
} }
@ -417,7 +497,12 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
if (realDelete) { if (realDelete) {
// 原逻辑删除库存表以及sn码的关联 // 原逻辑删除库存表以及sn码的关联
deliveryDetailService.deleteOmsInventoryDeliveryDetailByDeliveryId(id); deliveryDetailService.deleteOmsInventoryDeliveryDetailByDeliveryId(id);
return inventoryDeliveryMapper.deleteInventoryDeliveryById(id); if (CollUtil.isNotEmpty(inventoryInfos)) {
inventoryInfoMapper.clearOrderCodeByIds(inventoryInfos.stream().map(InventoryInfo::getId).collect(Collectors.toList()));
}
int result = inventoryDeliveryMapper.deleteInventoryDeliveryById(id);
projectOrderInfoService.refreshOrderStockingStatus(inventoryDelivery.getOrderCode());
return result;
} else { } else {
// 2026-03-19新逻辑仅修改发货单状态为撤回不删除库存表 // 2026-03-19新逻辑仅修改发货单状态为撤回不删除库存表
InventoryDelivery updateDelivery = new InventoryDelivery(); InventoryDelivery updateDelivery = new InventoryDelivery();
@ -425,6 +510,10 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
updateDelivery.setDeliveryStatus(InventoryDelivery.DeliveryStatusEnum.RECALL_DELIVERY.getCode()); updateDelivery.setDeliveryStatus(InventoryDelivery.DeliveryStatusEnum.RECALL_DELIVERY.getCode());
updateDelivery.setUpdateTime(DateUtils.getNowDate()); updateDelivery.setUpdateTime(DateUtils.getNowDate());
int rows = inventoryDeliveryMapper.updateInventoryDelivery(updateDelivery); int rows = inventoryDeliveryMapper.updateInventoryDelivery(updateDelivery);
if (CollUtil.isNotEmpty(inventoryInfos)) {
inventoryInfoMapper.clearOrderCodeByIds(inventoryInfos.stream().map(InventoryInfo::getId).collect(Collectors.toList()));
}
projectOrderInfoService.refreshOrderStockingStatus(inventoryDelivery.getOrderCode());
return rows; return rows;
} }
} }

View File

@ -144,6 +144,36 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService {
} }
omsInventoryInner.setWarehouseId(warehouseIdList.get(0)); omsInventoryInner.setWarehouseId(warehouseIdList.get(0));
if (omsInventoryInner.getItemId() != null) {
List<OmsPurchaseOrderItem> purchaseOrderItems = purchaseOrderService.listByItemId(omsInventoryInner.getItemId());
if (CollUtil.isNotEmpty(purchaseOrderItems)) {
OmsPurchaseOrderItem purchaseOrderItem = purchaseOrderItems.stream()
.filter(item -> item.getId().equals(omsInventoryInner.getItemId()))
.findFirst()
.orElse(null);
if (purchaseOrderItem != null) {
int purchaseQuantity = purchaseOrderItem.getQuantity() != null ? purchaseOrderItem.getQuantity().intValue() : 0;
int alreadyInnerQuantity = purchaseOrderItem.getInnerQuantity() != null ? purchaseOrderItem.getInnerQuantity().intValue() : 0;
int remainingQuantity = purchaseQuantity - alreadyInnerQuantity;
int currentInnerQuantity = omsInventoryInner.getQuantity() != null ? omsInventoryInner.getQuantity().intValue() : inventoryInfoList.size();
if (currentInnerQuantity > remainingQuantity) {
throw new ServiceException(StrUtil.format("入库数量[{}]超过采购单剩余可入库数量[{}]", currentInnerQuantity, remainingQuantity));
}
BigDecimal purchasePrice = purchaseOrderItem.getPrice();
if (purchasePrice != null) {
for (InventoryInfo inventoryInfo : inventoryInfoList) {
if (inventoryInfo.getInnerPrice() != null && inventoryInfo.getInnerPrice().compareTo(purchasePrice) != 0) {
throw new ServiceException(StrUtil.format("入库价[{}]必须等于采购单单价[{}]", inventoryInfo.getInnerPrice(), purchasePrice));
}
}
}
}
}
}
OmsPayableBill payableBill = new OmsPayableBill(); OmsPayableBill payableBill = new OmsPayableBill();
VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorCode(vendorCode); VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorCode(vendorCode);
if ((vendorInfo != null && VendorInfo.PayTypeEnum.INNER_PAY.getCode().equals(vendorInfo.getPayType())) || !Arrays.asList("1", "2").contains(omsInventoryInner.getProductType())) { if ((vendorInfo != null && VendorInfo.PayTypeEnum.INNER_PAY.getCode().equals(vendorInfo.getPayType())) || !Arrays.asList("1", "2").contains(omsInventoryInner.getProductType())) {

View File

@ -160,7 +160,13 @@ public class OmsPurchaseOrderServiceImpl implements IOmsPurchaseOrderService, To
omsPurchaseOrder.setOwnerName(ShiroUtils.getSysUser().getUserName()); omsPurchaseOrder.setOwnerName(ShiroUtils.getSysUser().getUserName());
} }
omsPurchaseOrder.setCreateTime(DateUtils.getNowDate()); omsPurchaseOrder.setCreateTime(DateUtils.getNowDate());
omsPurchaseOrder.setPurchaseNo(generatePurchaseNo(omsPurchaseOrder.getVendorId())); String purchaseNo = generatePurchaseNo(omsPurchaseOrder.getVendorId(), Boolean.TRUE.equals(omsPurchaseOrder.getIsVirtual()));
if (Boolean.TRUE.equals(omsPurchaseOrder.getIsVirtual())) {
omsPurchaseOrder.setApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
omsPurchaseOrder.setConfirmStatus(OmsPurchaseOrder.ConfirmStatusEnum.CONFIRM.getCode());
omsPurchaseOrder.setFlowType(OmsPurchaseOrder.FlowTypeEnum.ONLINE.getCode());
}
omsPurchaseOrder.setPurchaseNo(purchaseNo);
// 设置初始版本号为 1 // 设置初始版本号为 1
omsPurchaseOrder.setVersion(1); omsPurchaseOrder.setVersion(1);
int rows = omsPurchaseOrderMapper.insertOmsPurchaseOrder(omsPurchaseOrder); int rows = omsPurchaseOrderMapper.insertOmsPurchaseOrder(omsPurchaseOrder);
@ -172,10 +178,11 @@ public class OmsPurchaseOrderServiceImpl implements IOmsPurchaseOrderService, To
* *
* *
* @param vendorId ID * @param vendorId ID
* @param isVirtual
* @return * @return
*/ */
private String generatePurchaseNo(Long vendorId) { private String generatePurchaseNo(Long vendorId, boolean isVirtual) {
VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorId(vendorId); VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorId(vendorId);
if (vendorInfo==null || StringUtils.isEmpty(vendorInfo.getProvince())) { if (vendorInfo==null || StringUtils.isEmpty(vendorInfo.getProvince())) {
throw new ServiceException("制造商所属省为空,无法生成订单编号"); throw new ServiceException("制造商所属省为空,无法生成订单编号");
@ -191,6 +198,9 @@ public class OmsPurchaseOrderServiceImpl implements IOmsPurchaseOrderService, To
} }
String shortCode = cnareas.get(0).getShortCode(); String shortCode = cnareas.get(0).getShortCode();
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
if (isVirtual) {
result.append("XN-");
}
result.append("ZGCV-").append(currentDate).append(shortCode); result.append("ZGCV-").append(currentDate).append(shortCode);
// 查询当天已有的订单数量,用于生成顺序编码 // 查询当天已有的订单数量,用于生成顺序编码
int count = omsPurchaseOrderMapper.selectMaxOrderCode(result.toString()); int count = omsPurchaseOrderMapper.selectMaxOrderCode(result.toString());
@ -222,6 +232,11 @@ public class OmsPurchaseOrderServiceImpl implements IOmsPurchaseOrderService, To
omsPurchaseOrder.setUpdateTime(DateUtils.getNowDate()); omsPurchaseOrder.setUpdateTime(DateUtils.getNowDate());
// 版本号 +1 // 版本号 +1
omsPurchaseOrder.setVersion(oldOrder.getVersion() + 1); omsPurchaseOrder.setVersion(oldOrder.getVersion() + 1);
if (Boolean.TRUE.equals(omsPurchaseOrder.getIsVirtual())) {
omsPurchaseOrder.setApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
omsPurchaseOrder.setConfirmStatus(OmsPurchaseOrder.ConfirmStatusEnum.CONFIRM.getCode());
omsPurchaseOrder.setFlowType(OmsPurchaseOrder.FlowTypeEnum.ONLINE.getCode());
}
omsPurchaseOrderMapper.deleteOmsPurchaseOrderItemByPurchaseId(omsPurchaseOrder.getId()); omsPurchaseOrderMapper.deleteOmsPurchaseOrderItemByPurchaseId(omsPurchaseOrder.getId());
insertOmsPurchaseOrderItem(omsPurchaseOrder); insertOmsPurchaseOrderItem(omsPurchaseOrder);
return omsPurchaseOrderMapper.updateOmsPurchaseOrder(omsPurchaseOrder); return omsPurchaseOrderMapper.updateOmsPurchaseOrder(omsPurchaseOrder);
@ -419,6 +434,11 @@ public class OmsPurchaseOrderServiceImpl implements IOmsPurchaseOrderService, To
return omsPurchaseOrder; return omsPurchaseOrder;
} }
@Override
public List<OmsPurchaseOrderItem> listByItemId(Long itemId) {
return omsPurchaseOrderMapper.listByItemId(itemId);
}
/** /**
* *
@ -497,17 +517,27 @@ public class OmsPurchaseOrderServiceImpl implements IOmsPurchaseOrderService, To
if (omsPurchaseOrder == null) { if (omsPurchaseOrder == null) {
throw new ServiceException("采购订单不存在"); throw new ServiceException("采购订单不存在");
} }
// 只有审批状态为“已通过”(2) 且 供应商确认状态为空或 null 时才能撤回 // 只有审批状态为"已通过"(2) 时才能撤回,虚拟采购单不校验供应商确认状态
if (ApproveStatusEnum.APPROVE_COMPLETE.getCode().equals(omsPurchaseOrder.getApproveStatus()) && boolean isVirtual = Boolean.TRUE.equals(omsPurchaseOrder.getIsVirtual());
(StringUtils.isEmpty(omsPurchaseOrder.getConfirmStatus()) || "".equals(omsPurchaseOrder.getConfirmStatus())|| OmsPurchaseOrder.ConfirmStatusEnum.REJECT.getCode().equals(omsPurchaseOrder.getConfirmStatus()))) { boolean canRecall = false;
if (ApproveStatusEnum.APPROVE_COMPLETE.getCode().equals(omsPurchaseOrder.getApproveStatus())) {
if (isVirtual) {
canRecall = true;
} else {
canRecall = StringUtils.isEmpty(omsPurchaseOrder.getConfirmStatus()) ||
"".equals(omsPurchaseOrder.getConfirmStatus()) ||
OmsPurchaseOrder.ConfirmStatusEnum.REJECT.getCode().equals(omsPurchaseOrder.getConfirmStatus());
}
}
if (canRecall) {
// 保存历史记录 // 保存历史记录
saveOrderHistory(omsPurchaseOrder); saveOrderHistory(omsPurchaseOrder);
omsPurchaseOrder.setApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode()); // 设置为待审批(草稿) omsPurchaseOrder.setApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode());
omsPurchaseOrder.setApproveTime(null); // 清空审批时间 omsPurchaseOrder.setApproveTime(null);
omsPurchaseOrder.setConfirmStatus(null); // 清空审批时间 omsPurchaseOrder.setConfirmStatus(null);
omsPurchaseOrder.setUpdateTime(DateUtils.getNowDate()); omsPurchaseOrder.setUpdateTime(DateUtils.getNowDate());
omsPurchaseOrder.setVersion(omsPurchaseOrder.getVersion() + 1); // 版本号 +1 omsPurchaseOrder.setVersion(omsPurchaseOrder.getVersion() + 1);
return omsPurchaseOrderMapper.recallPurchaseOrder(omsPurchaseOrder); return omsPurchaseOrderMapper.recallPurchaseOrder(omsPurchaseOrder);
} else { } else {
throw new ServiceException("当前订单状态不允许撤回"); throw new ServiceException("当前订单状态不允许撤回");

View File

@ -2879,17 +2879,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
@Override @Override
public List<OrderProductMatchDto> selectProductMatchList(String orderCode) { public List<OrderProductMatchDto> selectProductMatchList(String orderCode) {
List<OrderProductMatchDto> orderProductMatchDtos = projectOrderInfoMapper.selectProductMatchList(orderCode); return projectOrderInfoMapper.selectProductMatchList(orderCode);
List<OrderProductMatchBindDto> orderProductMatchBindDtos = projectOrderInfoMapper.selectProductMatchBindList(orderCode, null);
Map<String, Integer> kyNumMap = orderProductMatchBindDtos.stream().filter(
item -> !item.getStatus().equals("0"))
.collect(Collectors.toMap(OrderProductMatchBindDto::getProductCode, item -> item.getKyNum() != null ? item.getKyNum() : 0, Integer::sum));
for (OrderProductMatchDto orderProductMatchDto : orderProductMatchDtos) {
orderProductMatchDto.setPhNum(orderProductMatchDto.getPhNum()+
(kyNumMap.get(orderProductMatchDto.getProductCode())==null?0:kyNumMap.get(orderProductMatchDto.getProductCode())));
}
return orderProductMatchDtos;
} }
@Override @Override
@ -2899,7 +2889,11 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
@Override @Override
public int savePurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap) { public int savePurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap) {
OmsPurchaseOrderMap exist = omsPurchaseOrderMapMapper.selectByOrderIdAndPurchaseId(omsPurchaseOrderMap.getOrderId(), omsPurchaseOrderMap.getPurchaseId()); OmsPurchaseOrderMap exist = omsPurchaseOrderMapMapper.selectByOrderIdAndPurchaseId(
omsPurchaseOrderMap.getOrderId(),
omsPurchaseOrderMap.getPurchaseId(),
omsPurchaseOrderMap.getProductCode()
);
int result; int result;
if (exist == null) { if (exist == null) {
result = omsPurchaseOrderMapMapper.insertOmsPurchaseOrderMap(omsPurchaseOrderMap); result = omsPurchaseOrderMapMapper.insertOmsPurchaseOrderMap(omsPurchaseOrderMap);
@ -2915,12 +2909,11 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
} }
@Override @Override
public OrderProductMatchSnDto selectPurchaseSnList(String purchaseNo, String orderCode) { public OrderProductMatchSnDto selectPurchaseSnList(String purchaseNo, String orderCode, String productCode) {
OrderProductMatchSnDto result = new OrderProductMatchSnDto(); OrderProductMatchSnDto result = new OrderProductMatchSnDto();
List<OrderProductMatchSnDetailDto> snList = projectOrderInfoMapper.selectProductMatchSnDetailList(purchaseNo); List<OrderProductMatchSnDetailDto> snList = projectOrderInfoMapper.selectProductMatchSnDetailList(purchaseNo, productCode);
// result.setTotalQuantity(projectOrderInfoMapper.selectProductMatchSnCountlList(purchaseNo));
result.setTotalQuantity(snList.size()); result.setTotalQuantity(snList.size());
Integer quotaQuantity = projectOrderInfoMapper.selectPurchaseOrderMapBindNum(purchaseNo, orderCode); Integer quotaQuantity = projectOrderInfoMapper.selectPurchaseOrderMapBindNum(purchaseNo, orderCode, productCode);
result.setQuotaQuantity(quotaQuantity); result.setQuotaQuantity(quotaQuantity);
result.setSnList(snList); result.setSnList(snList);
List<OrderProductMatchWarehouseDto> warehouseList = snList.stream() List<OrderProductMatchWarehouseDto> warehouseList = snList.stream()
@ -2944,21 +2937,6 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
if (CollUtil.isNotEmpty(params.getProductSnList())) { if (CollUtil.isNotEmpty(params.getProductSnList())) {
result = inventoryInfoMapper.updateOrderCodeByProductSnList(params.getProductSnList(), params.getOrderCode()); result = inventoryInfoMapper.updateOrderCodeByProductSnList(params.getProductSnList(), params.getOrderCode());
} }
//根据实际绑定的sn码修改订单与采购单的绑定数
if (params.getOrderId() != null && params.getPurchaseId() != null && StringUtils.isNotEmpty(params.getPurchaseNo())) {
int actualBindNum = inventoryInfoMapper.countByOrderCodeAndPurchaseNo(params.getOrderCode(), params.getPurchaseNo());
OmsPurchaseOrderMap map = omsPurchaseOrderMapMapper.selectByOrderIdAndPurchaseId(params.getOrderId(), params.getPurchaseId());
if (map == null) {
map = new OmsPurchaseOrderMap();
map.setOrderId(params.getOrderId());
map.setPurchaseId(params.getPurchaseId());
map.setBindNum(actualBindNum);
omsPurchaseOrderMapMapper.insertOmsPurchaseOrderMap(map);
} else {
map.setBindNum(actualBindNum);
omsPurchaseOrderMapMapper.updateOmsPurchaseOrderMap(map);
}
}
//更新订单的备货状态 //更新订单的备货状态
this.refreshOrderStockingStatus(params.getOrderCode()); this.refreshOrderStockingStatus(params.getOrderCode());
return result; return result;
@ -2969,7 +2947,8 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
* *
* @param orderCode * @param orderCode
*/ */
private void refreshOrderStockingStatus(String orderCode) { @Override
public void refreshOrderStockingStatus(String orderCode) {
if (StringUtils.isEmpty(orderCode)) { if (StringUtils.isEmpty(orderCode)) {
return; return;
} }

View File

@ -32,7 +32,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</sql> </sql>
<select id="selectInventoryInfoList" parameterType="InventoryInfo" resultMap="InventoryInfoResult"> <select id="selectInventoryInfoList" parameterType="InventoryInfo" resultMap="InventoryInfoResult">
<include refid="selectInventoryInfoVo"/> select t1.id, t1.product_code, t1.product_sn, t1.license_key, t1.inventory_status, t1.inner_code, t1.outer_code, t1.order_code, t1.warehouse_id, t1.inner_price,t1.tax_rate,
t1.outer_price, t1.create_by, t1.create_time, t1.update_by, t1.update_time ,
t2.warehouse_name,t3.description as 'product_desc',t3.model,t3.type as product_type
from oms_inventory_info t1
left join oms_warehouse_info t2 on t1.warehouse_id = t2.id
left join product_info t3 on t1.product_code = t3.product_code
<if test="(orderCode != null and orderCode != '') or (purchaseNo != null and purchaseNo != '')">
left join oms_inventory_inner t4 on t1.inner_code = t4.inner_code
</if>
<if test="orderCode != null and orderCode != ''">
left join oms_purchase_order t5 on t4.purchase_no = t5.purchase_no
left join oms_purchase_order_map t6 on t5.id = t6.purchase_id and t6.product_code = t1.product_code
left join project_order_info t7 on t6.order_id = t7.id and t7.order_code = #{orderCode}
</if>
<where> <where>
<if test="productCode != null and productCode != ''">and t1.product_code = #{productCode}</if> <if test="productCode != null and productCode != ''">and t1.product_code = #{productCode}</if>
<if test="productCodeList != null and productCodeList != ''">and t1.product_code in <if test="productCodeList != null and productCodeList != ''">and t1.product_code in
@ -51,11 +64,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if> </if>
<if test="innerCode != null and innerCode != ''">and t1.inner_code = #{innerCode}</if> <if test="innerCode != null and innerCode != ''">and t1.inner_code = #{innerCode}</if>
<if test="outerCode != null and outerCode != ''">and t1.outer_code = #{outerCode}</if> <if test="outerCode != null and outerCode != ''">and t1.outer_code = #{outerCode}</if>
<if test="orderCode != null and orderCode != ''">and t1.order_code = #{orderCode}</if> <if test="orderCode != null and orderCode != ''">
and t6.bind_num > 0
</if>
<if test="purchaseNo != null and purchaseNo != ''">
and t4.purchase_no = #{purchaseNo}
</if>
<if test="warehouseId != null ">and t1.warehouse_id = #{warehouseId}</if> <if test="warehouseId != null ">and t1.warehouse_id = #{warehouseId}</if>
<if test="innerPrice != null ">and t1.inner_price = #{innerPrice}</if> <if test="innerPrice != null ">and t1.inner_price = #{innerPrice}</if>
<if test="outerPrice != null ">and t1.outer_price = #{outerPrice}</if> <if test="outerPrice != null ">and t1.outer_price = #{outerPrice}</if>
</where> </where>
</select> </select>
@ -166,10 +183,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</insert> </insert>
<insert id="saveBatch"> <insert id="saveBatch">
insert into oms_inventory_info (product_code, product_sn, license_key, inventory_status, inner_code, outer_code insert into oms_inventory_info (product_code, product_sn, license_key, inventory_status, inner_code, outer_code
, warehouse_id, inner_price, outer_price, create_by, create_time, update_by, update_time,payable_bill_code,tax_rate) values , warehouse_id, inner_price, outer_price, create_by, create_time, update_by, update_time,payable_bill_code,tax_rate,order_code) values
<foreach item="item" index="index" collection="list" separator=","> <foreach item="item" index="index" collection="list" separator=",">
(#{item.productCode}, #{item.productSn}, #{item.licenseKey}, #{item.inventoryStatus}, #{item.innerCode}, #{item.outerCode} (#{item.productCode}, #{item.productSn}, #{item.licenseKey}, #{item.inventoryStatus}, #{item.innerCode}, #{item.outerCode}
, #{item.warehouseId}, #{item.innerPrice}, #{item.outerPrice}, #{item.createBy}, #{item.createTime}, #{item.updateBy}, #{item.updateTime},#{item.payableBillCode},#{item.taxRate}) , #{item.warehouseId}, #{item.innerPrice}, #{item.outerPrice}, #{item.createBy}, #{item.createTime}, #{item.updateBy}, #{item.updateTime},#{item.payableBillCode},#{item.taxRate},#{item.orderCode})
</foreach> </foreach>
ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE
license_key = VALUES(license_key), license_key = VALUES(license_key),
@ -177,7 +194,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
outer_code = VALUES(outer_code), outer_code = VALUES(outer_code),
outer_price = VALUES(outer_price), outer_price = VALUES(outer_price),
update_by = VALUES(update_by), update_by = VALUES(update_by),
update_time = now() update_time = now(),
order_code = VALUES(order_code)
</insert> </insert>
<update id="updateInventoryInfo" parameterType="InventoryInfo"> <update id="updateInventoryInfo" parameterType="InventoryInfo">
@ -241,6 +259,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and t2.purchase_no = #{purchaseNo} and t2.purchase_no = #{purchaseNo}
</select> </select>
<update id="clearOrderCodeByIds">
update oms_inventory_info
set order_code = null,
update_time = now()
where id in
<foreach item="id" collection="idList" separator="," open="(" close=")">
#{id}
</foreach>
</update>
<delete id="deleteInventoryInfoById" parameterType="Long"> <delete id="deleteInventoryInfoById" parameterType="Long">
delete from oms_inventory_info where id = #{id} delete from oms_inventory_info where id = #{id}
</delete> </delete>

View File

@ -29,6 +29,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="approveTime" column="approve_time" /> <result property="approveTime" column="approve_time" />
<result property="approveNode" column="approve_node" /> <result property="approveNode" column="approve_node" />
<result property="confirmStatus" column="confirm_status" /> <result property="confirmStatus" column="confirm_status" />
<result property="isVirtual" column="is_virtual" />
<result property="delFlag" column="del_flag" /> <result property="delFlag" column="del_flag" />
<result property="version" column="version" /> <result property="version" column="version" />
<result property="createBy" column="create_by" /> <result property="createBy" column="create_by" />
@ -69,6 +70,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="approveTime != null">approve_time,</if> <if test="approveTime != null">approve_time,</if>
<if test="approveNode != null">approve_node,</if> <if test="approveNode != null">approve_node,</if>
<if test="confirmStatus != null">confirm_status,</if> <if test="confirmStatus != null">confirm_status,</if>
<if test="isVirtual != null">is_virtual,</if>
<if test="delFlag != null">del_flag,</if> <if test="delFlag != null">del_flag,</if>
<if test="version != null">version,</if> <if test="version != null">version,</if>
<if test="createBy != null">create_by,</if> <if test="createBy != null">create_by,</if>
@ -103,6 +105,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="approveTime != null">#{approveTime},</if> <if test="approveTime != null">#{approveTime},</if>
<if test="approveNode != null">#{approveNode},</if> <if test="approveNode != null">#{approveNode},</if>
<if test="confirmStatus != null">#{confirmStatus},</if> <if test="confirmStatus != null">#{confirmStatus},</if>
<if test="isVirtual != null">#{isVirtual},</if>
<if test="delFlag != null">#{delFlag},</if> <if test="delFlag != null">#{delFlag},</if>
<if test="version != null">#{version},</if> <if test="version != null">#{version},</if>
<if test="createBy != null">#{createBy},</if> <if test="createBy != null">#{createBy},</if>

View File

@ -8,20 +8,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="id" column="id"/> <result property="id" column="id"/>
<result property="orderId" column="order_id"/> <result property="orderId" column="order_id"/>
<result property="purchaseId" column="purchase_id"/> <result property="purchaseId" column="purchase_id"/>
<result property="productCode" column="product_code"/>
<result property="bindNum" column="bind_num"/> <result property="bindNum" column="bind_num"/>
</resultMap> </resultMap>
<select id="selectByOrderIdAndPurchaseId" resultMap="OmsPurchaseOrderMapResult"> <select id="selectByOrderIdAndPurchaseId" resultMap="OmsPurchaseOrderMapResult">
select id, order_id, purchase_id, bind_num select id, order_id, purchase_id, product_code, bind_num
from oms_purchase_order_map from oms_purchase_order_map
where order_id = #{orderId} where order_id = #{orderId}
and purchase_id = #{purchaseId} and purchase_id = #{purchaseId}
and product_code = #{productCode}
limit 1 limit 1
</select> </select>
<insert id="insertOmsPurchaseOrderMap" parameterType="OmsPurchaseOrderMap" useGeneratedKeys="true" keyProperty="id"> <insert id="insertOmsPurchaseOrderMap" parameterType="OmsPurchaseOrderMap" useGeneratedKeys="true" keyProperty="id">
insert into oms_purchase_order_map(order_id, purchase_id, bind_num) insert into oms_purchase_order_map(order_id, purchase_id, product_code, bind_num)
values (#{orderId}, #{purchaseId}, #{bindNum}) values (#{orderId}, #{purchaseId}, #{productCode}, #{bindNum})
</insert> </insert>
<update id="updateOmsPurchaseOrderMap" parameterType="OmsPurchaseOrderMap"> <update id="updateOmsPurchaseOrderMap" parameterType="OmsPurchaseOrderMap">

View File

@ -48,7 +48,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectOmsPurchaseOrderVo"> <sql id="selectOmsPurchaseOrderVo">
select t1.id, t1.purchase_no, t1.buyer_name, t1.buyer_address, t1.vendor_id, t1.currency, t1.purchaser_id, t1.purchaser_name select t1.id, t1.purchase_no, t1.buyer_name, t1.buyer_address, t1.vendor_id, t1.currency, t1.purchaser_id, t1.purchaser_name
, t1.purchaser_mobile, t1.purchaser_email, t1.warehouse_id, t1.pay_method, t1.owner_id, t1.owner_name, t1.remark, t1.total_amount , t1.purchaser_mobile, t1.purchaser_email, t1.warehouse_id, t1.pay_method, t1.owner_id, t1.owner_name, t1.remark, t1.total_amount
, t1.status, t1.approve_status, t1.approve_time, t1.approve_node, t1.confirm_status, t1.purchase_date, t1.create_time, t1.update_time, t1.del_flag,t1.version,t1.flow_type , t1.status, t1.approve_status, t1.approve_time, t1.approve_node, t1.confirm_status, t1.is_virtual, t1.purchase_date, t1.create_time, t1.update_time, t1.del_flag,t1.version,t1.flow_type
, t1.file_id , t1.file_id
from oms_purchase_order t1 from oms_purchase_order t1
</sql> </sql>
@ -71,7 +71,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectOmsPurchaseOrderRelationVo"> <sql id="selectOmsPurchaseOrderRelationVo">
select t1.id, t1.purchase_no, t1.buyer_name, t1.buyer_address, t1.vendor_id, t1.currency, t1.purchaser_id, t1.purchaser_name select t1.id, t1.purchase_no, t1.buyer_name, t1.buyer_address, t1.vendor_id, t1.currency, t1.purchaser_id, t1.purchaser_name
, t1.purchaser_mobile, t1.purchaser_email, t1.warehouse_id, t1.pay_method, t1.owner_id, t1.owner_name, t1.remark, t1.total_amount,t1.flow_type , t1.purchaser_mobile, t1.purchaser_email, t1.warehouse_id, t1.pay_method, t1.owner_id, t1.owner_name, t1.remark, t1.total_amount,t1.flow_type
, t1.status, t1.approve_status, t1.approve_time, t1.approve_node, t1.confirm_status, t1.purchase_date, t1.create_time, t1.update_time, t1.del_flag,t1.version , t1.status, t1.approve_status, t1.approve_time, t1.approve_node, t1.confirm_status, t1.is_virtual, t1.purchase_date, t1.create_time, t1.update_time, t1.del_flag,t1.version
, t1.file_id , t1.file_id
,t2.vendor_address,t2.vendor_name,t2.vendor_user,t2.vendor_code,t2.vendor_phone,t2.vendor_email,t3.warehouse_name,t1.remark, ,t2.vendor_address,t2.vendor_name,t2.vendor_user,t2.vendor_code,t2.vendor_phone,t2.vendor_email,t3.warehouse_name,t1.remark,
(select max(tax_rate) from oms_purchase_order_item as it where it.purchase_id = t1.id) as tax_rate (select max(tax_rate) from oms_purchase_order_item as it where it.purchase_id = t1.id) as tax_rate
@ -301,6 +301,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="approveTime != null">approve_time,</if> <if test="approveTime != null">approve_time,</if>
<if test="approveNode != null">approve_node,</if> <if test="approveNode != null">approve_node,</if>
<if test="confirmStatus != null">confirm_status,</if> <if test="confirmStatus != null">confirm_status,</if>
<if test="isVirtual != null">is_virtual,</if>
<if test="purchaseDate != null">purchase_date,</if> <if test="purchaseDate != null">purchase_date,</if>
<if test="createTime != null">create_time,</if> <if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if> <if test="updateTime != null">update_time,</if>
@ -330,6 +331,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="approveTime != null">#{approveTime},</if> <if test="approveTime != null">#{approveTime},</if>
<if test="approveNode != null">#{approveNode},</if> <if test="approveNode != null">#{approveNode},</if>
<if test="confirmStatus != null">#{confirmStatus},</if> <if test="confirmStatus != null">#{confirmStatus},</if>
<if test="isVirtual != null">#{isVirtual},</if>
<if test="purchaseDate != null">#{purchaseDate},</if> <if test="purchaseDate != null">#{purchaseDate},</if>
<if test="createTime != null">#{createTime},</if> <if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if> <if test="updateTime != null">#{updateTime},</if>
@ -363,6 +365,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="approveTime != null">approve_time = #{approveTime},</if> <if test="approveTime != null">approve_time = #{approveTime},</if>
<if test="approveNode != null">approve_node = #{approveNode},</if> <if test="approveNode != null">approve_node = #{approveNode},</if>
<if test="confirmStatus != null">confirm_status = #{confirmStatus},</if> <if test="confirmStatus != null">confirm_status = #{confirmStatus},</if>
<if test="isVirtual != null">is_virtual = #{isVirtual},</if>
<if test="purchaseDate != null">purchase_date = #{purchaseDate},</if> <if test="purchaseDate != null">purchase_date = #{purchaseDate},</if>
<if test="createTime != null">create_time = #{createTime},</if> <if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if> <if test="updateTime != null">update_time = #{updateTime},</if>

View File

@ -931,25 +931,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select select
t3.product_code as product_code, t3.product_code as product_code,
t3.model, t3.model,
t3.type as product_type,
t7.vendor_code,
t7.vendor_name,
t1.quantity as order_num, t1.quantity as order_num,
sum(ifnull(t5.bind_num, 0)) as ph_num, sum(ifnull(t5.bind_num, 0)) as ph_num,
ifnull(t6.bh_num,0) as bh_num,ifnull(t6.sum_cost,0) as sum_cost ifnull(t6.bh_num,0) as bh_num,
sum(ifnull(t5.bind_num, 0) * t4.price) as sum_cost
from project_product_info as t1 from project_product_info as t1
inner join project_order_info as t2 inner join project_order_info as t2 on t1.project_id = t2.project_id
on t1.project_id = t2.project_id inner join product_info as t3 on t1.product_bom_code = t3.product_code
inner join product_info as t3 left join oms_purchase_order_item as t4 on t3.product_code = t4.product_code
on t1.product_bom_code = t3.product_code left join oms_purchase_order_map as t5 on t2.id = t5.order_id and t4.purchase_id = t5.purchase_id and t5.product_code = t4.product_code
left join oms_purchase_order_item as t4 left join (
on t3.product_code = t4.product_code select count(1) bh_num, product_code
left join oms_purchase_order_map as t5 from oms_inventory_info
on t2.id = t5.order_id and t4.purchase_id = t5.purchase_id where order_code = #{orderCode}
left join (select count(1) bh_num, sum(inner_price) sum_cost, product_code group by product_code
from oms_inventory_info ) t6 on t3.product_code = t6.product_code
where order_code = #{orderCode} left join oms_vendor_info as t7 on t3.vendor_code = t7.vendor_code
group by product_code) t6 on t3.product_code = t6.product_code
where t2.order_code = #{orderCode} where t2.order_code = #{orderCode}
and t3.type in (1, 2) group by t3.product_code, t3.model
group by t3.product_code, t3.model, t1.quantity order by t3.type, t3.product_code
</select> </select>
<select id="selectProductMatchBindList" resultType="com.ruoyi.sip.dto.OrderProductMatchBindDto"> <select id="selectProductMatchBindList" resultType="com.ruoyi.sip.dto.OrderProductMatchBindDto">
@ -959,8 +962,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t6.id as purchase_id, t6.id as purchase_id,
t6.purchase_no, t6.purchase_no,
(select vendor_address from oms_vendor_info as tt where tt.vendor_id = t6.vendor_id) as vendor_address, (select vendor_address from oms_vendor_info as tt where tt.vendor_id = t6.vendor_id) as vendor_address,
max(t4.price) as price,
t4.quantity as cg_num, t4.quantity as cg_num,
t4.quantity - ifnull((select sum(bind_num) from oms_purchase_order_map as tt where tt.purchase_id = t4.purchase_id), 0) as ky_num, t4.quantity - ifnull((select sum(bind_num) from oms_purchase_order_map as tt
where tt.order_id = t2.id and tt.purchase_id = t4.purchase_id and tt.product_code = t4.product_code), 0) as ky_num,
t5.bind_num as ph_num, t5.bind_num as ph_num,
t6.status, t6.status,
( (
@ -979,7 +984,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
inner join oms_purchase_order_item as t4 inner join oms_purchase_order_item as t4
on t3.product_code = t4.product_code on t3.product_code = t4.product_code
left join oms_purchase_order_map as t5 left join oms_purchase_order_map as t5
on t2.id = t5.order_id and t4.purchase_id = t5.purchase_id on t2.id = t5.order_id and t4.purchase_id = t5.purchase_id and t4.product_code = t5.product_code
inner join oms_purchase_order as t6 inner join oms_purchase_order as t6
on t6.id = t4.purchase_id on t6.id = t4.purchase_id
where t2.order_code = #{orderCode} where t2.order_code = #{orderCode}
@ -998,7 +1003,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
on t1.inner_code = t2.inner_code on t1.inner_code = t2.inner_code
left join oms_warehouse_info as t3 left join oms_warehouse_info as t3
on t2.warehouse_id = t3.id on t2.warehouse_id = t3.id
where t2.purchase_no = #{purchaseNo} and t1.inventory_status=0 where t2.purchase_no = #{purchaseNo}
</select> </select>
<select id="selectPurchaseOrderMapBindNum" resultType="java.lang.Integer"> <select id="selectPurchaseOrderMapBindNum" resultType="java.lang.Integer">
@ -1008,7 +1013,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
inner join project_order_info as t2 inner join project_order_info as t2
on t2.order_code = #{orderCode} on t2.order_code = #{orderCode}
left join oms_purchase_order_map as t3 left join oms_purchase_order_map as t3
on t2.id = t3.order_id and t1.id = t3.purchase_id on t2.id = t3.order_id and t1.id = t3.purchase_id and t3.product_code = #{productCode}
where t1.purchase_no = #{purchaseNo} where t1.purchase_no = #{purchaseNo}
limit 1 limit 1
</select> </select>
@ -1020,12 +1025,53 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.order_code, t1.order_code,
t1.outer_code t1.outer_code
from oms_inventory_info as t1 from oms_inventory_info as t1
inner join oms_inventory_inner as t2 inner join oms_inventory_inner as t2 on t1.inner_code = t2.inner_code
on t1.inner_code = t2.inner_code left join oms_warehouse_info as t3 on t2.warehouse_id = t3.id
left join oms_warehouse_info as t3 where t2.purchase_no = #{purchaseNo}
on t2.warehouse_id = t3.id and t1.product_code = #{productCode}
where t2.purchase_no = #{purchaseNo} and t1.inventory_status=0
order by t1.product_sn order by t1.product_sn
</select> </select>
<select id="selectOrderProductBindAmount" resultType="com.ruoyi.sip.dto.OrderProductBindAmountDto">
select
product_code,
sum(cost_with_tax) as cost_with_tax,
sum(cost_without_tax) as cost_without_tax,
sum(amount_without_tax) as amount_without_tax,
sum(amount_without_tax) - sum(cost_without_tax) as gross_profit,
cast((sum(amount_without_tax) - sum(t.cost_without_tax)) / sum(amount_without_tax) * 100 as decimal(10,2)) as gross_profit_rate,
(case when sum(bind_num) >= max(quantity) then true else false end) as order_stocking_status
from (
select
t1.project_id,
t2.product_code,
t2.bind_num * t4.price as cost_with_tax,
cast(t2.bind_num * t4.price / (1 + t4.tax_rate) as decimal(10,2)) as cost_without_tax,
cast(t2.bind_num * t5.price / (1 + t5.tax_rate / 100) as decimal(10,2)) as amount_without_tax,
t2.bind_num,
t5.quantity
from project_order_info as t1
inner join oms_purchase_order_map as t2 on t1.id = t2.order_id
inner join oms_purchase_order as t3 on t2.purchase_id = t3.id
inner join oms_purchase_order_item as t4 on t3.id = t4.purchase_id and t2.product_code = t4.product_code
inner join project_product_info as t5 on t1.project_id = t5.project_id and t2.product_code = t5.product_bom_code
where t2.bind_num > 0
and t1.order_code = #{orderCode}
and t2.product_code = #{productCode}
) as t
group by product_code
</select>
<select id="selectUnboundPurchaseOrderProductList" resultType="com.ruoyi.sip.dto.UnboundPurchaseOrderProductDto">
select
t1.order_code,
t1.product_code,
t1.inner_code
from oms_inventory_info as t1
inner join project_order_info as t2
on t1.order_code = t2.order_code
where t2.id not in (select order_id from oms_purchase_order_map)
group by t1.order_code, t1.product_code, t1.inner_code
</select>
</mapper> </mapper>