Shiro_项目_审核入库订单&&库存预警&&发送邮件

1 进销存模块分类

在这里插入图片描述

1.1 基本模块内容

组织机构模块:公司,部门,员工
系统模块: 角色,权限,菜单-- 使用系统之前的 这些就应该维护到系统
基础数据模块:(数据字典(下拉框) )产品,产品类型,供应商(采购),客户(销售)

1.2 进销存核心模块

采购模块:
录入人员–>采购单–>审核采购单–》入库处理
销售模块
录入人员–>销售单–>审核销售单–>出库处理
库存模块:
入库单,出库单,报表
盘点模块
清点模块 – 清点单(每个月有那么一两天清点)
盘盈盘亏数据 --单据
清点完之后–还有同步数据

2 进销存业务逻辑

2.1 建立入库订单(组合关系、主从表)

2.1.1 仓库
@Entity
@Table(name = "depot")
public class Depot extends BaseDomain {
  private String name;
  private BigDecimal maxCapacity;// 最大数量,参考值
  private BigDecimal currentCapacity;;// 当前数量,参考值
  private BigDecimal totalAmount;// 当前仓库里面的产品值多少钱
}
2.1.2 入库订单:组合关系的一方
@Entity
@Table(name = "stockincomebill")
public class StockIncomeBill extends BaseDomain {
  private Date vdate;// 交易时间
  private BigDecimal totalAmount;
  private BigDecimal totalNum;
  private Date inputTime = new Date();
  private Date auditorTime;//审核时间
  /**
   * 0待审,1已审,-1作废
   */
  private Integer status = 0;
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "supplier_id")
  private Supplier supplier;// 多对一,非空
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "auditor_id")
  private Employee auditor;// 多对一,可以为空
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "inputUser_id")
  private Employee inputUser;// 多对一,非空
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "keeper_id")
  private Employee keeper;// 多对一,非空 //仓管员
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "depot_id")
  private Depot depot;// 多对一,非空
  // 一般组合关系使用List
  @OneToMany(cascade = CascadeType.ALL, mappedBy = "bill", fetch = FetchType.LAZY, orphanRemoval = true)
  private List<StockIncomeBillItem> items = new ArrayList<StockIncomeBillItem>();
}
2.1.3 入库订单明细:组合关系的多方
@Entity
@Table(name = "stockincomebillitem")
public class StockIncomeBillItem extends BaseDomain {
  private BigDecimal price;
  private BigDecimal num;
  private BigDecimal amount;
  private String descs;
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "product_id")
  private Product product;// 多对一,非空
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "bill_id")
  private StockIncomeBill bill;// 组合关系,非空
}
2.1.4 即时库存
@Entity
@Table(name = "productstock")
public class ProductStock extends BaseDomain {
  // 产品id 入库时间 入库数量 价格 小计
  // 100 03 100 10 1000
  // 100 05 200 30 6000
  // 加权平均法=总金额/总数量
  // 100 05 300 (1000+6000)/300 7000
  private BigDecimal num;// 当前仓库的产品的数量
  private BigDecimal amount;// 当前仓库的产品的小计
  private BigDecimal price;// 当前仓库的产品的价格
  private Date incomeDate;// 入库时间
  private Boolean warning = true;// 库存过多,过少自动发出库存预警
  private BigDecimal topNum = new BigDecimal(100);// 最大库存量
  private BigDecimal bottomNum = new BigDecimal(50);// 最小库存量
  // 同时唯一(同一个产品,同一个仓库 -> 才进行累加)
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "product_id")
  private Product product;// 多对一,非空
  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "depot_id")
  private Depot depot;// 多对一,非空
}

2.2 级联保存

2.2.1 导包
<dependency>
    <groupId>javax.el</groupId>
    <artifactId>javax.el-api</artifactId>
    <version>2.2.4</version>
</dependency>
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>javax.el</artifactId>
    <version>2.2.4</version>
</dependency>
2.2.2 保存测试

2.3 审核采购入库单

/**
     *
     * @param billId  审核单据
     * @param auditor  审核人
     *
     *    审核操作:
     *            1、单据里面 里面审核的时间  审核人  状态
     *            2、仓库变化
     *            3、及时库存表变化
     */
    @Transactional
    public void auditStockincomebill(Long billId, Employee auditor) {
        //需要审核的单据
        Stockincomebill bill = stockincomebillRepository.findOne(billId);
        if (bill == null) {
            throw new RuntimeException("该单据不存在");
        }
        if (bill.getStatus() == 1){
            throw new RuntimeException("该单据已审核");
        }
        if (bill.getStatus() == -1){
            throw new RuntimeException("该单据已作废");
        }
        //单据里面 里面审核的时间  审核人  状态
        bill.setAuditorTime(new Date());
        bill.setAuditor(auditor);
        bill.setStatus(1);

        //更新数据
        stockincomebillRepository.save(bill);

        //仓库变化
        Depot depot = bill.getDepot();
        //当前容量
        depot.setCurrentCapacity(depot.getCurrentCapacity().add(bill.getTotalNum()));
        depot.setTotalAmount(depot.getTotalAmount().add(bill.getTotalAmount()));

        //保存仓库
        depotRepository.save(depot);

        //及时库存表变化
        List<Stockincomebillitem> items = bill.getItems();
        //查询当前产品在及时库存表里面是否存在
        String jpql = "select o from Productstock o where o.product=? and o.depot=?";
        for (Stockincomebillitem item : items) {
            Product product = item.getProduct();
            List productStockList = productstockRepository.findByJpql(jpql,product,depot);
            BigDecimal totalNum = new BigDecimal("0");
            BigDecimal totalAmount = new BigDecimal("0");
            if (productStockList.size() == 0) {
                Productstock productStock = new Productstock();
                productStock.setDepot(depot);//仓库
                productStock.setNum(item.getNum());
                productStock.setPrice(item.getPrice());
                productStock.setAmount(item.getAmount());
                //及时库存时间
                productStock.setIncomeDate(new Date());
                productStock.setProduct(product);
                productstockRepository.save(productStock);
            }else if (productStockList.size() == 1){
                //合并
                Productstock productstock = (Productstock) productStockList.get(0);
                totalNum = productstock.getNum().add(item.getNum());
                totalAmount = productstock.getAmount().add(item.getAmount());
                //总数量
                productstock.setNum(productstock.getNum().add(item.getNum()));
                //总金额
                productstock.setAmount(productstock.getAmount().add(item.getAmount()));

                //平均价格  四舍五入
                productstock.setPrice(totalAmount.divide(totalNum,2,BigDecimal.ROUND_HALF_EVEN));

                productstock.setIncomeDate(new Date());
                //保存
                productstockRepository.save(productstock);
            }else {
                throw new RuntimeException("仓库出问题了");
            }
        }
    }

3 库存预警

3.1 pom.xml添加jar文件

<!-- spring额外集成邮件,任务调度,邮件模版 -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
	<version>${org.springframework.version}</version>
</dependency>

3.2 任务调度/定时调度jar文件

<!-- 任务调度(定时任务) -->
<dependency>
	<groupId>quartz</groupId>
	<artifactId>quartz</artifactId>
	<version>1.5.2</version>
</dependency>

3.3 发出预警的最佳时机

在固定的时间(凌晨2点)先查询即时库存里面的数量大于最大库存量或者小于最小库存量,在发出预警,并且是每天都循环检测

3.4 java.util.Timer

@Test
public void time() throws Exception {
	// 定时器
	Timer timer = new Timer();
	// 开启定时任务(子线程)
	timer.schedule(new TimerTask() {
		@Override
		public void run() {
			System.out.println(new Date().toLocaleString());
		}
	}, 0, 1000);// 0立即执行,1000间隔1秒
	// 让主线程处于运行状态
	Thread.sleep(5000);
}

3.5 使用OpenSymphony Quartz 任务调度

3.5.1 ApplicationContext-qz.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
				http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- cron表达式:在每天早上8点到晚上8点期间每1分钟触发一次 -->
    <!--value>0 0/1 8-20 * * ?</value -->
    <!-- cron表达式:每5分钟触发一次 -->
    <!-- <value>0 0/5 * * * ?</value> -->
    <task:scheduled-tasks>
        <!-- 执行quartzJob里面的work方法,执行频率是cron表达式 -->
        <task:scheduled ref="quartzJob" method="work" cron="0 0/1 * * * ?"/>
    </task:scheduled-tasks>
</beans>
3.5.2 applicationContext.xml配置
<!-- 引入其他的配置文件 -->
<import resource="classpath:plugin/applicationContext-*.xml"/>
3.5.3 代码部分
@Service("QzJob")
public class QuartzJobServiceImpl implements IQuartzJobService {
    @Autowired
    private IProductstockService productstockService;
    @Override
    public void work() {
        System.out.println(productstockService);
        System.out.println("---------------------------------");
        String jpql ="select o from Productstock o where o.id = ?";
        List list = productstockService.findByJpql(jpql, 1L);
        if(list.size() > 0 ){
            System.out.println("库存不足");
        }else{
            System.out.println("库存很足...");
        }
    }
}

4 邮件

4.1 pom.xml添加jar文件

<dependency>
	<groupId>javax.mail</groupId>
	<artifactId>mail</artifactId>
	<version>1.4.1</version>
</dependency>

4.2 ApplicationContext-email.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <!-- 163邮箱,smtp.163.com -->
        <!-- admin@163.com 用户名:admin 密码:xxx -->
        <!-- smtp邮件发送协议 -->
        <!-- pop3收邮件协议 -->
        <property name="host" value="smtp.126.com" />
        <property name="username" value="ainideren674899@126.com" />
        <property name="password" value="wubinshi008" />
        <property name="javaMailProperties">
            <props>
                <!-- 必须进行授权认证,它的目的就是阻止他人任意乱发邮件 -->
                <prop key="mail.smtp.auth">true</prop>
                <!-- SMTP加密方式:连接到一个TLS保护连接 -->
                <prop key="mail.smtp.starttls.enable">true</prop>
            </props>
        </property>
    </bean>
</beans>

4.3 开启smtp协议

在这里插入图片描述

4.4 简单邮件和复杂邮件

4.4.1 简单邮件
//注入一个对象
@Autowired
JavaMailSender mailSender;
//简单发送邮件
@Test
public void testName() throws Exception {
    //JavaMailSenderImpl xxx = (JavaMailSenderImpl)mailSender
    // 简单邮件对象
    SimpleMailMessage msg = new SimpleMailMessage();
    // 发送人:和配置一致
    msg.setFrom("ainideren674899@126.com");
    // 收件人
    msg.setTo("872610153@qq.com");
    // 主题
    msg.setSubject("皮皮虾要下锅油炸了");
    // 内容
    msg.setText("就问你疼不疼");
    // 设置固定回邮地址
    //msg.setReplyTo("xxxx@xxx.com");
    // 发送
    mailSender.send(msg);
}
4.4.2 复杂邮件 ,支持附件形式(图片或者文档)
/**
 * 发送复杂邮件
 */
@Test
public void testSendMsg2() throws MessagingException {
    //创建复杂的邮件发送
    MimeMessage mimeMessage = mailSender.createMimeMessage();
    //复杂邮件的工具类 设置编码格式
    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
    // 发送人:和配置一致
    helper.setFrom("ainideren674899@126.com");
    // 收件人
    helper.setTo("872610153@qq.com");
    helper.setSubject("测试小姐姐的表白");
    helper.setText("<h1>来呀,快活呀</h1>", true);
    //发送附件
    helper.addAttachment("小姐姐.jpg", new File("F:\\图片\\2.jpg"));
    helper.addAttachment("java.txt", new File("C:\\Users\\Shinelon\\Desktop\\新建文本文档.txt"));
    mailSender.send(mimeMessage);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值