feat(wms): 添加库存保质期管理功能

- 在库存列表中添加保质期天数和保质期状态列
- 实现保质期计算和状态提示功能
- 在入库订单中添加相关参数处理
- 更新API接口定义,增加保质期提醒时间字段
master
zangch@mesnac.com 3 months ago
parent 7e4720c9a3
commit 8770ebe116

@ -304,6 +304,11 @@ export interface BaseMaterialInfoVO {
*/ */
isHighValue: string; isHighValue: string;
/**
* wms
*/
wmsAlarmTime?: number ;
} }
export interface BaseMaterialInfoForm extends BaseEntity { export interface BaseMaterialInfoForm extends BaseEntity {
@ -571,6 +576,11 @@ export interface BaseMaterialInfoForm extends BaseEntity {
*/ */
isHighValue?: string; isHighValue?: string;
/**
* wms
*/
wmsAlarmTime?: number ;
} }
export interface BaseMaterialInfoQuery extends PageQuery { export interface BaseMaterialInfoQuery extends PageQuery {
@ -821,6 +831,11 @@ export interface BaseMaterialInfoQuery extends PageQuery {
*/ */
isHighValue?: string; isHighValue?: string;
/**
* wms
*/
wmsAlarmTime?: number ;
/** /**
* *

@ -58,6 +58,11 @@ export interface InventoryVO {
* *
*/ */
maxParkingTime?: number ; maxParkingTime?: number ;
/**
*
*
*/
wmsAlarmTime?: number ;
} }
@ -126,6 +131,11 @@ export interface InventoryForm extends BaseEntity {
* *
*/ */
maxParkingTime?: number ; maxParkingTime?: number ;
/**
*
*
*/
wmsAlarmTime?: number ;
} }
@ -195,6 +205,11 @@ export interface InventoryQuery extends PageQuery {
* *
*/ */
maxParkingTime?: number ; maxParkingTime?: number ;
/**
*
*
*/
wmsAlarmTime?: number ;
/** /**

@ -5,11 +5,11 @@
<el-form-item label="入库单号"> <el-form-item label="入库单号">
<el-input v-model="queryForm.instockCode" placeholder="输入调拨单号" clearable/> <el-input v-model="queryForm.instockCode" placeholder="输入调拨单号" clearable/>
</el-form-item> </el-form-item>
<el-form-item label="工单类型" prop="instockType"> <!-- <el-form-item label="工单类型" prop="instockType">
<el-select v-model="queryForm.instockType" placeholder="请选择工单类型" clearable > <el-select v-model="queryForm.instockType" placeholder="请选择工单类型" clearable >
<el-option v-for="dict in wms_instock_type" :key="dict.value" :label="dict.label" :value="dict.value"/> <el-option v-for="dict in wms_instock_type" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select> </el-select>
</el-form-item> </el-form-item>-->
<!-- <el-form-item label="入库方式" prop="instockMethond">--> <!-- <el-form-item label="入库方式" prop="instockMethond">-->
<!-- <el-select v-model="queryForm.instockMethond" placeholder="请选择入库方式" clearable >--> <!-- <el-select v-model="queryForm.instockMethond" placeholder="请选择入库方式" clearable >-->
<!-- <el-option v-for="dict in instock_methond" :key="dict.value" :label="dict.label" :value="dict.value"/>--> <!-- <el-option v-for="dict in instock_methond" :key="dict.value" :label="dict.label" :value="dict.value"/>-->
@ -172,7 +172,7 @@
<!-- />--> <!-- />-->
<!-- </el-select>--> <!-- </el-select>-->
<!-- </el-form-item>--> <!-- </el-form-item>-->
<el-form-item label="工单类型" prop="instockType"> <!-- <el-form-item label="工单类型" prop="instockType">
<el-select v-model="dialogForm.instockType" placeholder="请选择工单类型" clearable> <el-select v-model="dialogForm.instockType" placeholder="请选择工单类型" clearable>
<el-option <el-option
v-for="dict in wms_instock_type" v-for="dict in wms_instock_type"
@ -181,7 +181,7 @@
:value="dict.value" :value="dict.value"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>-->
<el-form-item label="订单编号" prop="orderNo"> <el-form-item label="订单编号" prop="orderNo">
<el-input v-model="dialogForm.orderNo" placeholder="请输入订单编号" /> <el-input v-model="dialogForm.orderNo" placeholder="请输入订单编号" />
</el-form-item> </el-form-item>
@ -658,6 +658,21 @@ import { getWmsPurchaseOrderList } from '@/api/wms/wmsPurchaseOrder';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { parseTime } from '@/utils/ruoyi'; import { parseTime } from '@/utils/ruoyi';
//
const route = useRoute();//
//
const getRouteParam = (paramName: string): string => {
const param = route.query[paramName];
if (!param) return '';
return Array.isArray(param) ? param[0] : param;
};
const instockTypeValue = getRouteParam('instockType');
const instockMethondValue = getRouteParam('instockMethond');
// ... ...
const {proxy} = getCurrentInstance() as ComponentInternalInstance; const {proxy} = getCurrentInstance() as ComponentInternalInstance;
const {audit_behave, const {audit_behave,
wms_barcode_if, wms_barcode_if,
@ -688,12 +703,19 @@ const childrenTableInfoVisible = ref(false)
// const childrenTableInfoSubmit = ref(false) // const childrenTableInfoSubmit = ref(false)
const updateDialog = ref(false) const updateDialog = ref(false)
const dialogTitle = ref('添加') const dialogTitle = ref('添加')
const dialogForm = ref<InstockOrderForm>({ instockType: '', orderNo: '', materialCategoryId: '', warehouseId: '' }); const dialogForm = ref<InstockOrderForm>({
instockType: instockTypeValue || '' ,
orderNo: '',
materialCategoryId: '',
warehouseId: '',
instockMethond: instockMethondValue || '' ,
});
const parentTableInfoForm = ref<any>({ const parentTableInfoForm = ref<any>({
materialCategoryId: '', materialCategoryId: '',
instockType: '', instockType: instockTypeValue || '' ,
auditBy: '', auditBy: '',
warehouseCode: '' warehouseCode: '',
instockMethond: instockMethondValue || '' ,
}) })
const parentTableApproveForm = ref<any>({ const parentTableApproveForm = ref<any>({
auditStatus: '', auditStatus: '',
@ -710,6 +732,7 @@ const childrenTableInfoForm = ref<any>({
packageMode: 'average', packageMode: 'average',
batchCode: '', batchCode: '',
createTime: '', createTime: '',
}) })
@ -718,22 +741,21 @@ const queryForm = ref({
materialCategoryId: '', materialCategoryId: '',
materialCategoryName: '', materialCategoryName: '',
warehouseId: '', warehouseId: '',
instockType: '', instockType: instockTypeValue || '' ,
instockMethond: '', instockMethond: instockMethondValue || '' ,
auditStatus: '', auditStatus: '',
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
}) })
//
const route = useRoute();//
// //
let routeInstockMethondValue = ''; let routeInstockMethondValue = '';
if (route.query.instockMethond) { if (route.query.instockMethond) {
// //
const instockMethondValue = Array.isArray(route.query.instockMethond) // const instockMethondValue = Array.isArray(route.query.instockMethond)
? route.query.instockMethond[0] // ? route.query.instockMethond[0]
: route.query.instockMethond; // : route.query.instockMethond;
queryForm.value.instockMethond = instockMethondValue; queryForm.value.instockMethond = instockMethondValue;
routeInstockMethondValue = instockMethondValue; // routeInstockMethondValue = instockMethondValue; //
} }
@ -741,9 +763,9 @@ if (route.query.instockMethond) {
let routeInstockTypeValue = ''; let routeInstockTypeValue = '';
if (route.query.instockType) { if (route.query.instockType) {
// //
const instockTypeValue = Array.isArray(route.query.instockType) // const instockTypeValue = Array.isArray(route.query.instockType)
? route.query.instockType[0] // ? route.query.instockType[0]
: route.query.instockType; // : route.query.instockType;
queryForm.value.instockType = instockTypeValue; queryForm.value.instockType = instockTypeValue;
routeInstockTypeValue = instockTypeValue; // routeInstockTypeValue = instockTypeValue; //
} }
@ -772,7 +794,7 @@ const state = reactive({
productionOrders: [], productionOrders: [],
selectedPurchaseOrder: null, selectedPurchaseOrder: null,
selectedProductionOrder: null, selectedProductionOrder: null,
isPurchaseOrderAssociated: false isPurchaseOrderAssociated: false,
}); });
// //
@ -980,8 +1002,25 @@ const viewDetails = (e) => {
// //
const parentTableAdd = () => { const parentTableAdd = () => {
dialogVisible.value = true; dialogVisible.value = true;
dialogForm.value = { instockType: '', orderNo: '', materialCategoryId: '', warehouseId: '' }; dialogForm.value = {
instockType: instockTypeValue || '',
orderNo: '',
materialCategoryId: '',
warehouseId: '',
instockMethond: instockMethondValue || ''
};
dialogtable.value = []; dialogtable.value = [];
//
if (dialogForm.value.instockType === '1') {
state.showPurchaseOrderSelect = true;
loadPurchaseOrders();
} else if (dialogForm.value.instockType === '2') {
state.showProductionOrderSelect = true;
loadProductionOrders();
}
// //
setTimeout(() => { setTimeout(() => {
if (dialogFormRef.value) { if (dialogFormRef.value) {

@ -91,6 +91,12 @@
{{ calculateDaysToExpire(scope.row) }} {{ calculateDaysToExpire(scope.row) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="保质期天数" align="center" prop="maxParkingTime" v-if="columns[8].visible" />
<el-table-column label="保质期状态" align="center" v-if="columns[9].visible">
<template #default="scope">
<el-tag :type="getExpiryStatusInfo(scope.row).type">{{ getExpiryStatusInfo(scope.row).text }}</el-tag>
</template>
</el-table-column>
<el-table-column label="批次码" align="center" prop="batchCode" v-if="columns[0].visible"/> <el-table-column label="批次码" align="center" prop="batchCode" v-if="columns[0].visible"/>
<!-- <el-table-column label="物料id" align="center" prop="materialId" v-if="columns[3].visible"/> --> <!-- <el-table-column label="物料id" align="center" prop="materialId" v-if="columns[3].visible"/> -->
<el-table-column label="库位编码" align="center" prop="locationCode" v-if="columns[2].visible"/> <el-table-column label="库位编码" align="center" prop="locationCode" v-if="columns[2].visible"/>
@ -219,6 +225,8 @@ const columns = ref<FieldOption[]>([
{ key: 5, label: `库存状态`, visible: true }, { key: 5, label: `库存状态`, visible: true },
{ key: 6, label: `仓库`, visible: true }, { key: 6, label: `仓库`, visible: true },
{ key: 7, label: `距离过期天数`, visible: true }, { key: 7, label: `距离过期天数`, visible: true },
{ key: 8, label: `保质期天数`, visible: true },
{ key: 9, label: `保质期状态`, visible: true },
// { key: 11, label: `${comment}`, visible: true }, // { key: 11, label: `${comment}`, visible: true },
// { key: 12, label: `${comment}`, visible: true }, // { key: 12, label: `${comment}`, visible: true },
// { key: 13, label: `${comment}`, visible: true }, // { key: 13, label: `${comment}`, visible: true },
@ -239,6 +247,7 @@ const initFormData: InventoryForm = {
warehouseName: undefined, warehouseName: undefined,
createTime: undefined, createTime: undefined,
maxParkingTime: undefined, maxParkingTime: undefined,
wmsAlarmTime: undefined,
} }
const data = reactive<PageData<InventoryForm, InventoryQuery>>({ const data = reactive<PageData<InventoryForm, InventoryQuery>>({
form: {...initFormData}, form: {...initFormData},
@ -259,6 +268,7 @@ const data = reactive<PageData<InventoryForm, InventoryQuery>>({
warehouseName: undefined, warehouseName: undefined,
createTime: undefined, createTime: undefined,
maxParkingTime: undefined, maxParkingTime: undefined,
wmsAlarmTime: undefined,
params: { params: {
} }
}, },
@ -398,13 +408,36 @@ const getMaterialCategorySelect = async () => {
}; };
const calculateDaysToExpire = (row: InventoryVO) => { const calculateDaysToExpire = (row: InventoryVO) => {
// (createTime + maxParkingTime) - // (createTime + shelfLifeDays) -
if (!row.createTime || !row.maxParkingTime) return 'N/A'; // shelfLifeDays 使 row.maxParkingTime 30
if (!row.createTime) return 'N/A';
const shelfLifeDays = (row.maxParkingTime ?? 30) as number;
const entryDate = dayjs(row.createTime); const entryDate = dayjs(row.createTime);
const expireDate = entryDate.add(row.maxParkingTime, 'day'); const expireDate = entryDate.add(shelfLifeDays, 'day');
const today = dayjs(); const today = dayjs();
const days = expireDate.diff(today, 'day'); const days = expireDate.diff(today, 'day');
return days >= 0 ? days : days; // return days; //
};
const getExpiryStatusInfo = (row: InventoryVO) => {
const days = calculateDaysToExpire(row);
// 使 row.wmsAlarmTime 15
const warnThreshold = (row.wmsAlarmTime ?? 15) as number;
if (days === 'N/A') {
return { type: 'info', text: 'N/A' };
}
if (typeof days !== 'number') {
return { type: 'info', text: 'N/A' };
}
if (days <= 0) {
//
return { type: 'danger', text: '已失效' };
}
if (days <= warnThreshold) {
// 5 15
return { type: 'warning', text: '即将过期' };
}
return { type: 'success', text: '正常' };
}; };

Loading…
Cancel
Save