From e0e8678001ac05135a48fc4b40fef3c7413c7ffe Mon Sep 17 00:00:00 2001 From: tuqiang <437016993@qq.com> Date: Fri, 5 Dec 2025 09:45:10 +0800 Subject: [PATCH] =?UTF-8?q?add:=E9=A1=B5=E9=9D=A2=E5=9B=BD=E9=99=85?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/dao/MdPbStoragevehicleext.java | 93 ++++++ .../wms/sch/task_manage/ForewarningTask.java | 224 +++++++++++++ .../wms/forewarning_management/forewarning.js | 48 +++ .../forewarning_config/AddDialog.vue | 314 ++++++++++++++++++ .../forewarning_config/AddMaterial.vue | 136 ++++++++ .../forewarning_config/index.vue | 189 +++++++++++ .../stIvtForewarningconfig.js | 43 +++ .../overdue_forewarning/index.vue | 191 +++++++++++ .../stIvtOverdueforewarning.js | 35 ++ .../safety_forewarning/index.vue | 191 +++++++++++ .../stIvtSafetyforewarning.js | 34 ++ 11 files changed, 1498 insertions(+) create mode 100644 nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/forewarn/service/dao/MdPbStoragevehicleext.java create mode 100644 nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/ForewarningTask.java create mode 100644 nladmin-ui/src/views/wms/forewarning_management/forewarning.js create mode 100644 nladmin-ui/src/views/wms/forewarning_management/forewarning_config/AddDialog.vue create mode 100644 nladmin-ui/src/views/wms/forewarning_management/forewarning_config/AddMaterial.vue create mode 100644 nladmin-ui/src/views/wms/forewarning_management/forewarning_config/index.vue create mode 100644 nladmin-ui/src/views/wms/forewarning_management/forewarning_config/stIvtForewarningconfig.js create mode 100644 nladmin-ui/src/views/wms/forewarning_management/overdue_forewarning/index.vue create mode 100644 nladmin-ui/src/views/wms/forewarning_management/overdue_forewarning/stIvtOverdueforewarning.js create mode 100644 nladmin-ui/src/views/wms/forewarning_management/safety_forewarning/index.vue create mode 100644 nladmin-ui/src/views/wms/forewarning_management/safety_forewarning/stIvtSafetyforewarning.js diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/forewarn/service/dao/MdPbStoragevehicleext.java b/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/forewarn/service/dao/MdPbStoragevehicleext.java new file mode 100644 index 0000000..c66a491 --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/forewarn/service/dao/MdPbStoragevehicleext.java @@ -0,0 +1,93 @@ +package org.nl.wms.sch.forewarn.service.dao; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + *

+ * 载具扩展属性信息表 + *

+ * + * @author Liuxy + * @since 2025-05-23 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("md_pb_storagevehicleext") +public class MdPbStoragevehicleext implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 载具扩展标识 + */ + @TableId(value = "storagevehicleext_id") + private String storagevehicleext_id; + + /** + * 载具编码 + */ + private String storagevehicle_code; + + /** + * 物料标识 + */ + private String material_id; + + /** + * 批次 + */ + private String pcsn; + + /** + * 数量计量单位标识 + */ + private String qty_unit_id; + + /** + * 数量计量单位名称 + */ + private String qty_unit_name; + + /** + * 可用数 + */ + private BigDecimal canuse_qty; + + /** + * 冻结数 + */ + private BigDecimal frozen_qty; + + /** + * 备注 + */ + private String remark; + + /** + * 修改人 + */ + private String update_optid; + + /** + * 修改人姓名 + */ + private String update_optname; + + /** + * 修改时间 + */ + private String update_time; + + /** + * 入库时间 + */ + private String insert_time; + + +} diff --git a/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/ForewarningTask.java b/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/ForewarningTask.java new file mode 100644 index 0000000..67b5a86 --- /dev/null +++ b/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/ForewarningTask.java @@ -0,0 +1,224 @@ +package org.nl.wms.sch.task_manage; + + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.nl.wms.sch.forewarn.service.dao.StIvtOverdueforewarning; +import org.nl.wms.sch.forewarn.service.dto.MdPbStoragevehicleextDto; +import org.nl.wms.sch.forewarn.service.IStIvtForewarningconfigService; +import org.nl.wms.sch.forewarn.service.IStIvtForewarningmaterialService; +import org.nl.wms.sch.forewarn.service.IStIvtOverdueforewarningService; +import org.nl.wms.sch.forewarn.service.IStIvtSafetyforewarningService; +import org.nl.wms.sch.forewarn.service.dao.StIvtForewarningconfig; +import org.nl.wms.sch.forewarn.service.dao.StIvtForewarningmaterial; +import org.nl.wms.sch.forewarn.service.dao.StIvtSafetyforewarning; +import org.nl.wms.sch.forewarn.service.dto.MdPbStoragevehicleextDto; +import org.nl.wms.sch.group.service.dao.mapper.MdPbGroupplateMapper; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +@Slf4j +@Component +@RequiredArgsConstructor +public class ForewarningTask { + + @Autowired + private IStIvtOverdueforewarningService stIvtOverdueforewarningService; + + @Autowired + private IStIvtSafetyforewarningService stIvtSafetyforewarningService; + + @Autowired + private IStIvtForewarningconfigService forewarningconfigService; + + @Autowired + private IStIvtForewarningmaterialService stIvtForewarningmaterialService; + + + @Autowired + private final RedissonClient redissonClient; + @Autowired + private MdPbGroupplateMapper mdPbGroupplateMapper; + + //定时任务 + @SneakyThrows + public void run() { + RLock lock = redissonClient.getLock(this.getClass().getName()); + boolean tryLock = lock.tryLock(2, TimeUnit.SECONDS); + try { + if (tryLock) { + runTask(); + } + lock.unlock(); + } catch (Exception e) { + if (tryLock) { + lock.unlock(); + } + } + } + + /** + * 预警数据生成 + *

+ * 1、查询st_ivt_forewarningconfig,获取正在启用的、未删除的配置 + * 2、通过st_ivt_forewarningconfig表的id字段,匹配上st_ivt_forewarningmaterial表的config_id字段,获取对应的物料。赋值给 + * StIvtForewarningconfigDto的tableData + * 3、循环,判断每条数据下的对应物料的安全库存数量、入库时间(以组盘时间为准) + * 其中库存表:md_pb_groupplate,实体类:GroupPlate,组盘时间create_time,物料编码id material_id + * 4、 分别生成st_ivt_safetyforewarning(安全库存数量超期) 和 st_ivt_overdueforewarning(超期天数超期) ,插入到对应数据库中 + */ + private void runTask() { + // 1. 删除st_ivt_overdueforewarning、st_ivt_safetyforewarning表中的全部数据 + // stIvtOverdueforewarningService.deleteAllNoParam(); + // stIvtSafetyforewarningService.deleteAllNoParam(); + + // 2. 查询st_ivt_forewarningconfig,获取正在启用的、未删除的配置 + List configList = forewarningconfigService.list(new LambdaQueryWrapper() + .eq(StIvtForewarningconfig::getIs_active, true) + .eq(StIvtForewarningconfig::getIs_delete, false)); + if (CollectionUtil.isEmpty(configList)) { + return; + } + + List configStringList = configList.stream().map(StIvtForewarningconfig::getId).collect(Collectors.toList()); + + // 获取配置文件下的所有物料 + List materialList = stIvtForewarningmaterialService.list(new LambdaQueryWrapper() + .eq(StIvtForewarningmaterial::getIs_active, true) + .eq(StIvtForewarningmaterial::getIs_delete, false) + .in(StIvtForewarningmaterial::getConfig_id, configStringList)); + + Set materialCodeList = materialList.stream().map(StIvtForewarningmaterial::getMaterial_code).collect(Collectors.toSet()); + Set storCodeList = configList.stream().map(StIvtForewarningconfig::getStor_code).collect(Collectors.toSet()); + // 查询库存信息 + Map queryMap = new HashMap(); + queryMap.put("stor_code_list", storCodeList); + queryMap.put("material_code_list", materialCodeList); + List mdPbStoragevehicleextDtos = mdPbGroupplateMapper.queryAll(queryMap); + if (CollectionUtil.isEmpty(mdPbStoragevehicleextDtos)) { + return; + } + + for (StIvtForewarningconfig config : configList) { + //3. 通过st_ivt_forewarningconfig表的id字段,匹配上st_ivt_forewarningmaterial表的config_id字段,获取对应的物料 + List configMaterialList = materialList.stream(). + filter(a -> config.getId().equals(a.getConfig_id())).collect(Collectors.toList()); + + // 按照struct_code对mdPbStoragevehicleextDtos进行分组 + Map> structCodeGroupMap = mdPbStoragevehicleextDtos.stream() + .filter(a->config.getStor_code().equals(a.getStor_code())) + .collect(Collectors.groupingBy(MdPbStoragevehicleextDto::getStruct_code)); + + // 4. 循环,判断每条数据下的对应物料的安全库存数量、入库时间(以组盘时间为准) + for (StIvtForewarningmaterial material : configMaterialList) { + + // 遍历structCodeGroupMap,获取每个struct_code下的mdPbStoragevehicleextDtos + for (Map.Entry> entry : structCodeGroupMap.entrySet()) { + List mdPbStoragevehicleextDtoStructs = entry.getValue(); + + + // 计算安全库存数量 + BigDecimal totalQty = mdPbStoragevehicleextDtoStructs.stream() + .filter(a -> config.getStor_code().equals(a.getStor_code()) + && material.getMaterial_id().equals(a.getMaterial_id())) + .map(MdPbStoragevehicleextDto::getQty) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + // 计算最早的组盘时间 + LocalDateTime earliestPlate = null; + try { + earliestPlate = mdPbStoragevehicleextDtoStructs.stream() + .filter(a -> config.getStor_code().equals(a.getStor_code()) + && material.getMaterial_id().equals(a.getMaterial_id())) + .map(a -> { + try { + String createTimeStr = a.getCreate_time(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return LocalDateTime.parse(createTimeStr, formatter); + } catch (Exception ex) { + // 解析失败,返回null + return null; + } + }) + .filter(Objects::nonNull) + .min(LocalDateTime::compareTo) + .orElse(null); + } catch (Exception ex) { + // 处理整体异常 + earliestPlate = null; + } + // 计算 earliestPlate 与当前时间的天数差,返回int类型 + BigDecimal daysDiff = BigDecimal.ZERO; + if (earliestPlate != null) { + long millis = java.time.Duration.between(earliestPlate, LocalDateTime.now()).toMillis(); + daysDiff = new BigDecimal(millis) + .divide(new BigDecimal(1000 * 60 * 60 * 24), 4, BigDecimal.ROUND_HALF_UP); + } + + + // 5. 分别生成st_ivt_safetyforewarning(安全库存数量超期) 和 st_ivt_overdueforewarning(超期天数超期) + // 安全库存数量超限 + if ((config.getSafe_qty_lower_limit() != null && totalQty.compareTo(config.getSafe_qty_lower_limit()) < 0) + || (config.getSafe_qty_upper_limit() != null && totalQty.compareTo(config.getSafe_qty_upper_limit()) > 0)) { + StIvtSafetyforewarning safety = new StIvtSafetyforewarning(); + safety.setId(IdUtil.getSnowflake(1, 1).nextIdStr()); + safety.setConfig_id(config.getId()); + safety.setMaterial_code(material.getMaterial_code()); + safety.setMaterial_name(material.getMaterial_name()); + safety.setSect_code(mdPbStoragevehicleextDtoStructs.get(0).getSect_code()); + safety.setSect_name(mdPbStoragevehicleextDtoStructs.get(0).getSect_name()); + safety.setStruct_code(mdPbStoragevehicleextDtoStructs.get(0).getStruct_code()); + safety.setStruct_name(mdPbStoragevehicleextDtoStructs.get(0).getStruct_name()); + safety.setSafe_qty_lower_limit(config.getSafe_qty_lower_limit()); + safety.setSafe_qty_upper_limit(config.getSafe_qty_upper_limit()); + safety.setStor_code(config.getStor_code()); + safety.setCurrent_qty(totalQty); + safety.setCreate_name("JOB"); + safety.setCreate_time(DateUtil.now()); + stIvtSafetyforewarningService.save(safety); + } + + // 超期天数超期 + + if (config.getSafe_days() != null && daysDiff.compareTo(config.getSafe_days()) > 0) { + // 将 earliestPlate 转化成 yyyy-MM-dd HH:mm:ss 的String 类型 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String earliestPlateStr = earliestPlate.format(formatter); + + StIvtOverdueforewarning overdue = new StIvtOverdueforewarning(); + overdue.setId(IdUtil.getSnowflake(1, 1).nextIdStr()); + overdue.setConfig_id(config.getId()); + overdue.setMaterial_code(material.getMaterial_code()); + overdue.setMaterial_name(material.getMaterial_name()); + overdue.setOverdue_days(daysDiff); + overdue.setStor_code(config.getStor_code()); + overdue.setSect_code(mdPbStoragevehicleextDtoStructs.get(0).getSect_code()); + overdue.setSect_name(mdPbStoragevehicleextDtoStructs.get(0).getSect_name()); + overdue.setStruct_code(mdPbStoragevehicleextDtoStructs.get(0).getStruct_code()); + overdue.setStruct_name(mdPbStoragevehicleextDtoStructs.get(0).getStruct_name()); + overdue.setSafe_days(config.getSafe_days()); + overdue.setInsert_time(earliestPlateStr); + overdue.setCreate_name("JOB"); + overdue.setCreate_time(DateUtil.now()); + stIvtOverdueforewarningService.save(overdue); + } + } + } + } + } +} diff --git a/nladmin-ui/src/views/wms/forewarning_management/forewarning.js b/nladmin-ui/src/views/wms/forewarning_management/forewarning.js new file mode 100644 index 0000000..7ee8f81 --- /dev/null +++ b/nladmin-ui/src/views/wms/forewarning_management/forewarning.js @@ -0,0 +1,48 @@ +import request from '@/utils/request' + +// 安全库存配置 +export function getSafeStockConfigs() { + return request({ + url: '/api/safeStockConfig', + method: 'get' + }) +} + +export function saveSafeStockConfig(data) { + return request({ + url: '/api/safeStockConfig', + method: 'post', + data + }) +} + +export function updateSafeStockConfig(data) { + return request({ + url: '/api/safeStockConfig', + method: 'put', + data + }) +} + +export function deleteSafeStockConfig(id) { + return request({ + url: `/api/safeStockConfig/${id}`, + method: 'delete' + }) +} + +// 安全库存预警结果 +export function getSafetyStockWarningResults() { + return request({ + url: '/api/safetyStockWarningResult', + method: 'get' + }) +} + +// 库存超期预警结果 +export function getOverdueStockWarningResults() { + return request({ + url: '/api/overdueStockWarningResult', + method: 'get' + }) +} diff --git a/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/AddDialog.vue b/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/AddDialog.vue new file mode 100644 index 0000000..e7a8140 --- /dev/null +++ b/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/AddDialog.vue @@ -0,0 +1,314 @@ + + + + + diff --git a/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/AddMaterial.vue b/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/AddMaterial.vue new file mode 100644 index 0000000..758f76d --- /dev/null +++ b/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/AddMaterial.vue @@ -0,0 +1,136 @@ + + + + diff --git a/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/index.vue b/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/index.vue new file mode 100644 index 0000000..18cafb2 --- /dev/null +++ b/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/index.vue @@ -0,0 +1,189 @@ + + + + + diff --git a/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/stIvtForewarningconfig.js b/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/stIvtForewarningconfig.js new file mode 100644 index 0000000..aa958b2 --- /dev/null +++ b/nladmin-ui/src/views/wms/forewarning_management/forewarning_config/stIvtForewarningconfig.js @@ -0,0 +1,43 @@ +import request from '@/utils/request' + +export function add(data) { + return request({ + url: 'api/stIvtForewarningconfig', + method: 'post', + data + }) +} + +export function del(ids) { + return request({ + url: 'api/stIvtForewarningconfig/', + method: 'delete', + data: ids + }) +} + +export function edit(data) { + return request({ + url: 'api/stIvtForewarningconfig', + method: 'put', + data + }) +} + +export function getWarningMaterial(params) { + return request({ + url: '/api/stIvtForewarningconfig/getWarningMaterial', + method: 'get', + params + }) +} + +export function changeActive(data) { + return request({ + url: 'api/stIvtForewarningconfig/changeActive', + method: 'put', + data + }) +} + +export default { add, edit, del, getWarningMaterial, changeActive } diff --git a/nladmin-ui/src/views/wms/forewarning_management/overdue_forewarning/index.vue b/nladmin-ui/src/views/wms/forewarning_management/overdue_forewarning/index.vue new file mode 100644 index 0000000..7aa142b --- /dev/null +++ b/nladmin-ui/src/views/wms/forewarning_management/overdue_forewarning/index.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/nladmin-ui/src/views/wms/forewarning_management/overdue_forewarning/stIvtOverdueforewarning.js b/nladmin-ui/src/views/wms/forewarning_management/overdue_forewarning/stIvtOverdueforewarning.js new file mode 100644 index 0000000..0c40978 --- /dev/null +++ b/nladmin-ui/src/views/wms/forewarning_management/overdue_forewarning/stIvtOverdueforewarning.js @@ -0,0 +1,35 @@ +import request from '@/utils/request' + +export function add(data) { + return request({ + url: 'api/stIvtOverdueforewarning', + method: 'post', + data + }) +} + +export function del(ids) { + return request({ + url: 'api/stIvtOverdueforewarning/', + method: 'delete', + data: ids + }) +} + +export function edit(data) { + return request({ + url: 'api/stIvtOverdueforewarning', + method: 'put', + data + }) +} + +export function read(data) { + return request({ + url: 'api/stIvtOverdueforewarning/read', + method: 'post', + data + }) +} + +export default { add, edit, del, read } diff --git a/nladmin-ui/src/views/wms/forewarning_management/safety_forewarning/index.vue b/nladmin-ui/src/views/wms/forewarning_management/safety_forewarning/index.vue new file mode 100644 index 0000000..b26fffd --- /dev/null +++ b/nladmin-ui/src/views/wms/forewarning_management/safety_forewarning/index.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/nladmin-ui/src/views/wms/forewarning_management/safety_forewarning/stIvtSafetyforewarning.js b/nladmin-ui/src/views/wms/forewarning_management/safety_forewarning/stIvtSafetyforewarning.js new file mode 100644 index 0000000..034197f --- /dev/null +++ b/nladmin-ui/src/views/wms/forewarning_management/safety_forewarning/stIvtSafetyforewarning.js @@ -0,0 +1,34 @@ +import request from '@/utils/request' + +export function add(data) { + return request({ + url: 'api/stIvtSafetyforewarning', + method: 'post', + data + }) +} + +export function del(ids) { + return request({ + url: 'api/stIvtSafetyforewarning/', + method: 'delete', + data: ids + }) +} + +export function edit(data) { + return request({ + url: 'api/stIvtSafetyforewarning', + method: 'put', + data + }) +} +export function read(data) { + return request({ + url: 'api/stIvtSafetyforewarning/read', + method: 'post', + data + }) +} + +export default { add, edit, del, read }