java开发WMS仓库商品预警需求示例解析

目录
  • 1.预警需求
    • 1. 预警需求分析
  • 2.后端代码实现:
    • 1. 定时器任务
    • 2.优化加入队列
    • 3.注意:关于Mq
    • 4.测试是否成功
  • 3.前端提一嘴
    • 前端展示:

1.预警需求

为了更好的管理商品日期,需要对仓库的商品进行预警管理,对商品的保质期控制在一个范围内提示出来,也可以通过该功能间接的展示出一个商品的的销量程度和对下次进货做个考量!

1. 预警需求分析

  • 前端界面需要设置商品的预警天数
  • 后端保存预警天数
  • 数据库有字段存放商品需要预警的天数
  • 通过定时器运行指点方法算出对应那些商品的批次存低于设置的预警天数
  • 查询出来在wms首页展出

2.数据库表

对于前端界面的开发不做过多的代码分析,本次重点展示商品预警实现思路!!
数据库用到到字段会截取出来,便于理解!

商品表数据:

预警表数据:

商品批次表:

商品批次表中添加预警字段:后续查询对应的预警信息作为标志

Mysql使用到的函数

//查询当前时间
select now();
//获取时间相减 获取到天数 参数是前面-后面
select DATEDIFF("2022-9-10", now()) as day

如:

由此我们就可以通过函数算出商品距离过期的天数

查询语句:

    SELECT bb.id as batchId, bb.product_id as productId, DATEDIFF(bb.ed, now()) as warnDate
    FROM `商品批次表` bb

需要注意: 查询或者修改表数据我们如果只要使用某个字段去修改,尽量查询下该表更新的字段数据是否有重复的数据并且其他字段可能跟我们预想不一致,必须要修改的,我们就应该使用多字段去查询修改

查询重复数据

select * from 表 GROUP BY 字段 HAVING count(*)>1

查询预警批次数量: 因为需要展示出来在前端可以给用户点击查看货物存放的地方,所以查询出来的数据库存数量要大于0

select IFNULL(count(*),0) from  basic_batch bb  LEFT JOIN handle_stock hs on  bb.id=hs.batch_id where bb.is_warn_date=1 and hs.reality_number>0

2.后端代码实现:

1. 定时器任务

使用Scheduled作为定时器,通过cron语法指定运行时间,每3小时运行一次表达式如下

代码详情注释写的也比较清楚

    /**
     * 每3小时运行一次
     */
    @Scheduled(cron = "0 0 0/3 * * ?")
    public void goodsWarn(){
        BasicProductGpExample basicProductGpExample = new BasicProductGpExample();
        List<String> warnBatchIds=new ArrayList<>();
        //查询商品预警表信息 商品的货号是唯一的 (所以现在是全表查询出来)
        // 这里把商品预警信息都查询出来为了以后扩展做库存预警设置
        List<BasicProductGp> basicProductGps = productGpMapper.selectByExample(basicProductGpExample);
        //查询商品批次表:商品批次和天数 商品的批次是唯一的,存在多个商品货号(所以现在是全表查询出来)
        // 以后扩展商品库存预警只要在这个查询里面添加关联库存数量查询出来,然后在过滤里面添加预警数量判断
        List<BasicProductWarn> warnGoodsDay = basicBatchMapper.selectWarnGoodsDay();
        Long start=System.currentTimeMillis();
        for (BasicProductGp basicProductGp : basicProductGps) {
            //商品预警日期
            Integer warnDate = basicProductGp.getWarnDate();
            //商品货号编码
            Integer productId = basicProductGp.getProductId();
            //查询出符合预警的商品批次
            List<String> warnBatchId = warnGoodsDay.stream().filter(warnGood -> warnGood.getProductId().equals(productId) && warnGood.getWarnDate() <= warnDate)
                    .map(BasicProductWarn::getBatchId).collect(Collectors.toList());
            warnBatchIds.addAll(warnBatchId);
        }
        Long end=System.currentTimeMillis();
        log.info("消耗时长:"+(end-start)/1000+"秒");
        //获取出所有需要提醒的批次号
        log.info(Arrays.toString(warnBatchIds.toArray()));
        //数组为空时不更新
        if (CollectionUtils.isEmpty(warnBatchIds)){
            log.info("没有需要预警的商品批次!");
            return;
        }
        //修改批次状态为1标识预警日期已经到达
        //使用boolean类型保存数据库会自动把true转换成1
        int count = basicBatchMapper.updateByBatchWarn(warnBatchIds, true);
        log.info("更新预警数量:{}",count);
    }

这里面还存在一个问题,如果批次被打上预警标识,此时客户更改了商品的预警日期,那么商品的预警可能就没有到达,但是页面查询预警也能被查询出来,解决方案,使用mq来做处理,当客户更改了商品编码预警信息,那么程序就把更改的商品编码存到mq中我们在写个消费方法来消费更改后的商品编码单独走波预警方法

2.优化加入队列

先不考虑全局预警设置,只对勾选多个商品进行添加队列

使用了springBoot的rabbitMq模板类RabbitTemplate

pom.xml引入:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

生产者添加消息到队列中

       //存入队列                        routingkey名称  存入的数据
       rabbitTemplate.convertAndSend("warnGoodsQueue",ids);

消费者:

/**
 * 消费预警队列信息
 */
@Configuration
@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "warnGoodsQueue", durable = "true"),
        exchange = @Exchange(value = "warnGoodsExchange",
                ignoreDeclarationExceptions = "true",
                type = ExchangeTypes.TOPIC),
        key = {"warnGoodsQueue"}))
public class WarnGoodsQueue {

    @RabbitHandler
    public void process(List<String> ids) {
        if (ids == null) {
            System.out.println("空");
        }
        System.out.println(ids);
    }
}

3.注意:关于Mq

生产者,生产的数据类型一定要要和消费者获取的类型要一致,否则会无限循环报错

Listener threw exception
No method found for class [B

4.测试是否成功

生产者存入队列:

消费者获取数据:

如果消费方法报错不try/catch的话,队列就会一直重试该条数据

可以看出已经获取到修改预警商品的商品编号,这个时候我们只要写方法做相应的处理就行了
我们也可以去RabbitMq管理界面查看队列信息

消费方法代码:

public void updateWarnGoods(List<Integer> ids){
        if (CollectionUtils.isEmpty(ids)){
            return;
        }
        BasicProductGpExample example = new BasicProductGpExample();
        example.createCriteria().andProductIdIn(ids);
        //查询商品信息 商品的货号是唯一的 (查询变动的商品货号)
        List<BasicProductGp> basicProductGps = productGpMapper.selectByExample(example);

        //商品批次和天数 商品的批次是唯一的,存在多个商品货号(查询变动的商品货号)
        List<BasicProductWarn> warnGoodsDay = basicBatchMapper.selectWarnGoodsDayList(ids);
        //需要预警的集合
        List<String> warnBatchIds=new ArrayList<>();
        //不需要预警的集合
        List<String> notWarnBatchIds=new ArrayList<>();

        Long start=System.currentTimeMillis();
        for (BasicProductGp basicProductGp : basicProductGps) {
            //商品预警日期
            Integer warnDate = basicProductGp.getWarnDate();
            //商品货号编码
            Integer productId = basicProductGp.getProductId();
            //查询出符合预警的商品批次
            List<String> warnBatchId = warnGoodsDay.stream().filter(warnGood -> {
                if (warnGood.getProductId().equals(productId)){
                    //匹配到的商品数据
                    //2种情况:一种要预警另外一种不要预警
                    if (warnGood.getWarnDate() <= warnDate){
                        //预警的返回
                        return true;
                    }
                    //不要预警的添加到不预警集合用于更新
                    notWarnBatchIds.add(warnGood.getBatchId());
                }
                return false;
            }).map(BasicProductWarn::getBatchId).collect(Collectors.toList());

            //把预警集合添加到预警大集合中
            warnBatchIds.addAll(warnBatchId);
        }
        long end=System.currentTimeMillis();
        log.info("更新预警商品耗时:{}秒",(end-start)/1000);
        //结束后会得到2种集合:不预警和要预警集合

        //更新未预警商品
        if (!CollectionUtils.isEmpty(notWarnBatchIds)){
            int count = basicBatchMapper.updateByBatchWarn(notWarnBatchIds, false);
            log.info("更新预警数量:{}",count);
        }
        //更新预警商品
        if (!CollectionUtils.isEmpty(warnBatchIds)){
            int count = basicBatchMapper.updateByBatchWarn(warnBatchIds, true);
            log.info("更新预警数量:{}",count);
        }
    }

关于一些代码存在冗余我们可以提取成一个公共方法进行调用,后续也对全局修改预警Mq队列走波运算预警的商品

重载方法:

/***
     * 重载方法
     * 用于运算全局商品类型
     * 用于更新商品预警时间
     */
    public void updateWarnGoods(){
        BasicProductGpExample example = new BasicProductGpExample();
        //查询商品信息 商品的货号是唯一的 (查询变动的商品货号)
        List<BasicProductGp> basicProductGps = productGpMapper.selectByExample(example);

        //商品批次和天数 商品的批次是唯一的,存在多个商品货号(查询变动的商品货号)
        List<BasicProductWarn> warnGoodsDay = basicBatchMapper.selectWarnGoodsDay();
        //需要预警的集合
        List<String> warnBatchIds=new ArrayList<>();
        //不需要预警的集合
        List<String> notWarnBatchIds=new ArrayList<>();

        Long start=System.currentTimeMillis();
        for (BasicProductGp basicProductGp : basicProductGps) {
            //商品预警日期
            Integer warnDate = basicProductGp.getWarnDate();
            //商品货号编码
            Integer productId = basicProductGp.getProductId();
            //查询出符合预警的商品批次
            List<String> warnBatchId = warnGoodsDay.stream().filter(warnGood -> {
                if (warnGood.getProductId().equals(productId)){
                    //匹配到的商品数据
                    //2种情况:一种要预警另外一种不要预警
                    if (warnGood.getWarnDate() <= warnDate){
                        //预警的返回
                        return true;
                    }
                    //不要预警的添加到不预警集合用于更新
                    notWarnBatchIds.add(warnGood.getBatchId());
                }
                return false;
            }).map(BasicProductWarn::getBatchId).collect(Collectors.toList());

            //把预警集合添加到预警大集合中
            warnBatchIds.addAll(warnBatchId);
        }
        long end=System.currentTimeMillis();
        log.info("更新预警商品耗时:{}秒",(end-start)/1000);
        //结束后会得到2种集合:不预警和要预警集合

        //更新未预警商品
        if (!CollectionUtils.isEmpty(notWarnBatchIds)){
            int count = basicBatchMapper.updateByBatchWarn(notWarnBatchIds, false);
            log.info("更新预警数量:{}",count);
        }
        //更新预警商品
        if (!CollectionUtils.isEmpty(warnBatchIds)){
            int count = basicBatchMapper.updateByBatchWarn(warnBatchIds, true);
            log.info("更新预警数量:{}",count);
        }
    }

3.前端提一嘴

给商品添加预警日期,需要用户提些数据,为了避免出现英文空格等我们需要,对输入的数据进行正则,只能输入数字

效果:

英文:

但是可以输入0,如果预警日期设置成了0你们就意味着废弃该商品预警提示功能

前端展示:

首页:

预警商品列表:

以上就是java开发WMS仓库商品预警需求示例解析的详细内容,更多关于java开发WMS仓库商品预警的资料请关注我们其它相关文章!

(0)

相关推荐

  • 微信开发准备第一步 Maven仓库管理新建WEB项目

    在我们的项目开发中经常会遇到项目周期很长,项目依赖jar包特别多的情况,所以我们经常会在项目中引入Maven插件,建立起Maven项目,今天我就记录一个简单的Maven项目建立的简单流程! (一)Maven基础项目的建立(前提:你的开发工具中已经集成Maven插件) 新建项目-->建立Maven项目-->选择依赖-->项目名称等即可,大致流程如下: 这里要注意的是[第三张图片]和[第四张图片],第四张图片增加一个选项可以将项目名称做到简单修改,参考图[第五张图片],对项目名称有严格要求的

  • Java毕业设计实战项目之仓库管理系统的实现流程

    基于SSM框架的仓库管理系统 功能: 系统操作权限管理.系统提供基本的登入登出功能,同时系统包含两个角色:系统超级管理员和普通管理员,超级管理员具有最高的操作权限,而普通管理员仅具有最基本的操作权限,而且仅能操作自己被指派的仓库. 请求URL鉴权.对于系统使用者登陆后进行操作发送请求的URL,后台会根据当前用户的角色判断是否拥有请求该URL的权限. 基础数据信息管理.对包括:货物信息.供应商信息.客户信息.仓库信息在内的基础数据信息进行管理,提供的操作有:添加.删除.修改.条件查询.导出为Exc

  • Java 实战项目之仓库管理系统的实现流程

    一.项目简述 功能包括: 仓库管理,出入库管理,仓库人员管理,基本信息管理, 供应商信息,系统管理等等. 二.项目运行 环境配置: Jdk1.8 + Tomcat8.5 + mysql + Eclispe (IntelliJ IDEA,Eclispe,MyEclispe,Sts 都支持) 项目技术: JSP +Spring + SpringMVC + MyBatis + html+ css + JavaScript + JQuery + Ajax + layui+ maven等等. 客户信息管理

  • java开发WMS仓库商品预警需求示例解析

    目录 1.预警需求 1. 预警需求分析 2.后端代码实现: 1. 定时器任务 2.优化加入队列 3.注意:关于Mq 4.测试是否成功 3.前端提一嘴 前端展示: 1.预警需求 为了更好的管理商品日期,需要对仓库的商品进行预警管理,对商品的保质期控制在一个范围内提示出来,也可以通过该功能间接的展示出一个商品的的销量程度和对下次进货做个考量! 1. 预警需求分析 前端界面需要设置商品的预警天数 后端保存预警天数 数据库有字段存放商品需要预警的天数 通过定时器运行指点方法算出对应那些商品的批次存低于设

  • java开发ShardingSphere的路由引擎类型示例详解

    目录 ShardingSphere的路由引擎类型 路由引擎类型 标准路由 路由逻辑 总结 ShardingSphere的路由引擎类型 本篇文章源码基于4.0.1版本 上篇文章我们了解到了ShardingSphere在路由流程过程中,根据不同类型的SQL会现在不同的路由引擎,而ShardingSphere支持的路由规则也很多了,包括广播(broadcast)路由.混合(complex)路由.默认数据库(defaultdb)路由.无效(ignore)路由.标准(standard)路由以及单播(uni

  • Java 在PDF中添加骑缝章示例解析

    骑缝章是用于往来业务合同,以确保合同真实.有效的印章加盖方法,是一种防范风险的重要方式.在Java程序中,可以通过使用工具来辅助加盖这种骑缝章. 工具:Free Spire.PDF for Java (免费版) 工具获取及jar文件导入: 方式1:通过官网下载jar包,并解压,手动导入lib文件夹下的Spire.Pdf.jar文件. 方式2:通过创建Maven程序,在pom.xml中配置maven仓库路径并指定Free Spire.PDF for Java 的依赖,配置完成后,在IDEA中,点击

  • SpringBoot开发技巧之使用AOP记录日志示例解析

    目录 为什么要用AOP? 常用的工作场景 必须知道的概念 AOP 的相关术语 Spring 中使用注解创建切面 实战应用-利用AOP记录日志 定义日志信息封装 统一日志处理切面 为什么要用AOP? 答案是解耦! Aspect Oriented Programming 面向切面编程.解耦是程序员编码开发过程中一直追求的.AOP也是为了解耦所诞生. 具体思想是:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回到横向业务流. AOP 主要是利用代理模式的技术来实现的.具体的代理实现可以参考这篇

  • Java开发实现的Socket双向通信功能示例

    本文实例讲述了Java开发实现的Socket双向通信功能.分享给大家供大家参考,具体如下: 服务端 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java

  • Java 8 Stream操作类型及peek示例解析

    简介 java 8 stream作为流式操作有两种操作类型,中间操作和终止操作.这两种有什么区别呢? 我们看一个peek的例子: Stream<String> stream = Stream.of("one", "two", "three","four"); stream.peek(System.out::println); 上面的例子中,我们的本意是打印出Stream的值,但实际上没有任何输出. 为什么呢? 中间

  • Java开发SpringBoot集成接口文档实现示例

    目录 swagger vs smart-doc Swagger的代码侵入性比较强 原生swagger不支持接口的参数分组 简单罗列一下smart-doc的优点 SpringBoot集成 smart-doc 引入依赖,版本选择最新版本 新建配置文件smart-doc.json 通过执行maven 命令生成对应的接口文档 访问接口文档 功能增强 1. 开启调试 2. 通用响应体 3. 自定义Header 4. 参数分组 5. idea配置doc 6. 完整配置 小结 之前我在SpringBoot老鸟

  • Java Spring开发环境搭建及简单入门示例教程

    本文实例讲述了Java Spring开发环境搭建及简单入门示例.分享给大家供大家参考,具体如下: 前言 虽然之前用过Spring,但是今天试着去搭建依然遇到了困难,而且上网找教程,很多写的是在web里使用Spring MVC的示例,官方文档里的getting start一开始就讲原理去了(可能打开的方法不对).没办法,好不容易实验成功了,记下来免得自己以后麻烦. 添加依赖包 进入spring官网,切换到projects下点击 spring framework.官网上写的是以maven依赖的形式写

  • java开发的工厂方法模式及抽象工厂验证示例

    目录 工厂方法模式示例 抽象工厂模式验证 结论 工厂方法模式示例 开发一个数据格式转换工具,将不同数据源如:txt.excel等格式文件,转换为XML格式输出,需考虑今后其他格式的文件也需要转换为xml格式的扩展性,利用设计模式的有关知识进行设计. 解决思路,使用工厂方法模式完成该功能的设计,设计类图如下: 代码结构如下: 代码如下: public interface Creator { Convertor getConvertor(); } public class ExcelConverto

  • Java开发druid数据连接池maven方式简易配置流程示例

    目录 1.pom.xml文件引入druid和数据库连接jar包 2.jdbc.properties配置 3.ibatis-config.xml关于mybatis的参数配置 4.spring-mybatis.xml整合文件配置 5.web.xml配置检测访问 禁止访问的ip 6.根据需要配置各类监控Spring-mvc.xml 7.可选安全的加密操作 数据库加密 8.访问方式 1.pom.xml文件引入druid和数据库连接jar包 <properties> <druid.version&

随机推荐