1.1. 审核采购入库单
1.1.1. 审核流程(需要事务管理)
判断入库单是否存在,是否可以审核等
修改状态,审核人,审核时间
在循环外面更新仓库总金额、当前数量
添加或者更新即时库存表
1.1.2. 代码实现
@Service
public class StockincomebillServiceImpl extends BaseServiceImpl<Stockincomebill, Long>
implements IStockincomebillService {
@Autowired
private IProductStockService productStockService;
@Autowired
private IDepotService depotService;
// 审核入库单功能(需要事务管理)
@Override
@Transactional
public void auding(Long billId, Employee auditor) {
Stockincomebill bill = findOne(billId);
if (bill == null) {
throw new RuntimeException("此入库单不存在...");
}
// 0待审,1已审,-1作废
if (bill.getStatus() == 1) {
throw new RuntimeException("此入库单已经审核完成");
}
if (bill.getStatus() == -1) {
throw new RuntimeException("此入库单已经作废");
}
// 入库单状态,审核人,审核时间
bill.setStatus(1);
bill.setAuditor(auditor);
bill.setAuditorTime(new Date());
// 显示更新一下
save(bill);
Depot depot = bill.getDepot();
// 仓库总数量,总金额(循环的外面写)
depot.setCurrentCapacity(depot.getCurrentCapacity().add(bill.getTotalNum()));
depot.setTotalAmount(depot.getTotalAmount().add(bill.getTotalAmount()));
depotService.save(depot);
// 添加或者更新即时库存ProductStock
String jpql = "select o from ProductStock o where o.depot=? and o.product=?";
List<Stockincomebillitem> items = bill.getItems();
for (Stockincomebillitem billItem : items) {
Product product = billItem.getProduct();
List<ProductStock> list = findByJpql(jpql, depot, product);
if (list.size() == 0) {// 添加
ProductStock productStock = new ProductStock();
// 小计
productStock.setAmount(billItem.getAmount());
// 仓库
productStock.setDepot(depot);
// 入库时间
productStock.setIncomeDate(new Date());
// 入库数量
productStock.setNum(billItem.getNum());
// 入库价格
productStock.setPrice(billItem.getPrice());
// 入库产品
productStock.setProduct(product);
// 保存
productStockService.save(productStock);
} else if (list.size() == 1) {// 更新
ProductStock productStock = list.get(0);
// 产品id 入库时间 入库数量 价格 小计
// 100 03 100 10 1000
// 100 05 200 30 6000
// 加权平均法
// 100 05 300 (1000+6000)/300 7000
// 总金额(1000+6000)
BigDecimal totalAmount = productStock.getAmount().add(billItem.getAmount());
// 总数量
BigDecimal totalNum = productStock.getNum().add(billItem.getNum());
// 小计
productStock.setAmount(totalAmount);
// 入库数量
productStock.setNum(totalNum);
// 入库价格:保留2位小数点,四舍五入
BigDecimal price = totalAmount.divide(totalNum, 2, BigDecimal.ROUND_HALF_EVEN);
productStock.setPrice(price);
// 入库时间
productStock.setIncomeDate(new Date());
// 修改
productStockService.save(productStock);
} else {// >1即时库存表:业务要求:同一个仓库里面的产品是唯一的
throw new RuntimeException("同一个仓库里面的产品不是唯一的");
}
}
}
}
1.2. 库存预警
1.2.1. 目的
在即时库存表里面如果当前的库存数量大于预设的最大库存数100,或者小于预设的最小库存数50,就要发出预警。
1.2.2. pom.xml添加jar文件
<!-- spring额外集成邮件,任务调度,邮件模版 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
</dependency>
1.2.3. 发出预警的最佳时机
在固定的时间(凌晨2点)先查询即时库存里面的数量大于最大库存量或者小于最小库存量,在发出预警,并且是每天都循环检测
1.2.4. 任务调度/定时调度jar文件
<!-- 任务调度(定时任务) -->
<dependency>
<groupId>quartz</groupId>
<artifactId>quartz</artifactId>
<version>1.5.2</version>
</dependency>
1.2.5. 方案1 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);
}
1.2.6. 方案2使用OpenSymphony Quartz 任务调度
applicationContext.xml
<!-- 引入其他的配置文件 -->
<import resource="classpath:plugin/applicationContext-*.xml"/>
2.Spirng配置
<?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.代码
把预警消息发送给相关人员
@Service("quartzJob")
public class QuartzJobServiceImpl implements IQuartzJobService {
@Autowired
private BaseRepository<ProductStock, Long> baseRepository;
@Override
public void work() {
System.out.println(new Date().toLocaleString());
String jpql = "select o from ProductStock o where (o.num>=o.topNum or o.num<=o.bottomNum) and o.warning=?";
List<ProductStock> list = baseRepository.findByJpql(jpql, true);
for (ProductStock productStock : list) {
System.out.println("需要发出库存预警:" + productStock);
// 邮件:连接互联网,今天讲
// 短信:后面项目讲(阿里大鱼,容联云)
// 添加一张表t_message来发出消息:ERP(人力资源计划),一个公司所有系统都在里面(pss,crm,hr...)
}
}
}
1.2.7. 邮件
pom.xml添加jar文件
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.1</version>
</dependency>
spring配置文件
<?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.163.com" />
<property name="username" value="123456" />
<property name="password" value="xxxxxxx" />
<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>
开启smtp协议
登录qq邮箱,设置qq邮箱独立密码,在获取授权码(百度一下)
简单邮件
public class MailTest extends BaseServiceTest {
@Autowired
MailSender mailSender;
@Test
public void testName() throws Exception {
//JavaMailSenderImpl xxx = (JavaMailSenderImpl)mailSender
// 简单邮件对象
SimpleMailMessage msg = new SimpleMailMessage();
// 发送人:和配置一致
msg.setFrom("admin@163.com");
// 收件人
msg.setTo("xxxx@laomo.com");
// 主题
msg.setSubject("牛皮大学录取通知书");
// 内容
msg.setText("你已经被录取了");
// 设置固定回邮地址
msg.setReplyTo("xxxx@xxx.com");
// 发送
mailSender.send(msg);
}
}