erp系统及时成本预警

  • 时间:
  • 浏览:806
  • 来源:成都艾邦软件开发

1、库存预警报表

1.1、需求及实现思路

1需求统计每种商品的库存数量和待发货数量(库存数量小于待发货数量)

2实现思路运用关联查询、子查询、聚合统计。

1.2、SQL语句的编写

这种带子查询的 SQL 语句相对复杂我们分步完成

1按商品编号和商品名称分组统计各商品的库存合计

select g.uuid,g.name,sum(s.num) storenumfrom goods g,storedetail swhere g.uuids.goodsuuid group by g.uuid,g.name;

 结果如下

但是这样的结果只是显示库存表中存在的商品而库存表中不存在的商品则不
会显示。我们可以通过左外连接的方式来进行查询。

select g.uuid,g.name,nvl(sum(s.num),0) storenumfrom goods g,storedetail swhere g.uuids.goodsuuid() group by g.uuid,g.name;

我们采用 Oracle 的左外连接的语法符号 () 来实现左外连接
另外 nvl 函数用于将空值转换为特定的值
查询结果如下

2按商品编号分组统计各商品的待发货数量

select goodsuuid,sum(num) outnumfrom orderdetail od,orders owhere od.ordersuuido.uuidand od.state0 and o.type2 group by goodsuuid;

结果如下

3按商品查询库存数量与待发货数量(子查询)

select uuid,name,storenum,outnum from(select g.uuid,g.name,nvl(sum(s.num),0) storenumfrom goods g,storedetail swhere g.uuids.goodsuuid() group by g.uuid,g.name) gs,(select goodsuuid,sum(num) outnumfrom orderdetail od,orders owhere od.ordersuuido.uuidand od.state0 and o.type2 group by goodsuuid) odowhere gs.uuidodo.goodsuuid

 查询结果如下

1.3、视图创建

我们上边的语句的查询结果是我们经常要用的每次都写很繁琐所以我们可以把常用的复杂查询直接建立为视图这样可以极大简化我们的开发便于日常维护。 

create view view_storealert as.....(SQL 语句)

建立完视图后我们就可以直接使用这个视图了如下图

1.4、代码书写

1 建立视图 t view_storealert  的实体类 

package cn.itcast.erp.entity;/*** 库存警报* author Administrator**/public class StoreAlert {private Long uuid;//商品编号private String name;//商品名称private Long storenum;//库存数量private Long outnum;//待出库数量public Long getUuid() {return uuid;}public void setUuid(Long uuid) {this.uuid  uuid;}public String getName() {return name;}public void setName(String name) {this.name  name;}public Long getStorenum() {return storenum;}public void setStorenum(Long storenum) {this.storenum  storenum;}public Long getOutnum() {return outnum;}public void setOutnum(Long outnum) {this.outnum  outnum;}}

2 编写视图 t view_storealert 

?xml version1.0 encodingutf-8?!DOCTYPE hibernate-mapping PUBLIC -//Hibernate/Hibernate Mapping DTD3.0//EN/hibernate-mapping-3.0.dtdhibernate-mappingclass namecn.itcast.erp.entity.StoreAlerttableview_storealert id nameuuid /idproperty namename /property namestorenum /property nameoutnum //class/hibernate-mapping

3编写数据访问层代码

在 StoredetailDao 和 IStoredetailDao 新增方法查询库存预警列表

4编写业务逻辑层代码

在 StoredetailBiz 和 IStoredetailBiz 新增方法查询库存预警列表

5编写Action层代码

在 StoredetailAction 新增方法查询库存预警列表

6编写页面代码

!DOCTYPE htmlhtmlheadmeta charsetUTF-8title库存预警报表/titlelink relstylesheet typetext/csshrefui/themes/default/easyui.csslink relstylesheet typetext/css hrefui/themes/icon.cssscript typetext/javascript srcui/jquery.min.js/scriptscript typetext/javascript srcui/jquery.easyui.min.js/scriptscript typetext/javascriptsrcui/locale/easyui-lang-zh_CN.js/scriptscript typetext/javascript srcjs/storealert.js/script/headbodytable idgrid/table/body/html

 7编写storealert.js代码

$(function(){$(#grid).datagrid({url:storedetail_storeAlertList.action,columns:[[{field:uuid,title:商品编号,width:100},{field:name,title:商品名称,width:100},{field:storenum,title:库存数量,width:100},{field:outnum,title:待发货数量,width:100}]]});})

2、JavaMail 实现发送预警邮件(扩展)

2.1、需求分析

在上例基础上实现发送邮件预警功能 。点击“发送警报邮件”按钮即可发送库存报警。

如果存在报警商品并成功发送提示发送成功
如果不存在报警商品提示没有库存报警商品

2.2、什么是JavaMail

JavaMail是提供给开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发类库支持常用的邮件协议如 SMTP、POP3、IMAP开发人员使用 JavaMail 编写邮件程序时无需考虑底层的通信细节(Socket)JavaMail 也提供了能够创建出各种复杂 MIME 格式的邮件内容的 API。使用 JavaMail我们可以实现类似 OutLook、FoxMail 的软件。
Spring JavaMailSender 是对 JavaMail 进行封装,简化了开发告别繁琐的 API . 

2.3、入门小Demo

1申请邮箱

我这里申请的是新浪邮箱进入后开通 POP3/SMTP 服务

2创建工程编写pom文件

创建 demo 工程pom.xml 中添加 spring 和 javaMail 的依赖下面是 javaMail 的依赖 

!-- Javamail --dependencygroupIdjavax.mail/groupIdartifactIdmail/artifactIdversion1.4.4/version/dependency

3编写用于发送Email的类

package cn.itcast.demo;import javax.mail.MessagingException;import javax.mail.internet.MimeMessage;import org.springframework.mail.javamail.JavaMailSender;import org.springframework.mail.javamail.MimeMessageHelper;public class TestSend {private JavaMailSender javaMailSender;public void setJavaMailSender(JavaMailSender javaMailSender) {this.javaMailSender  javaMailSender;}public void sendMail() throws MessagingException{MimeMessage mime  javaMailSender.createMimeMessage();MimeMessageHelper helper  new MimeMessageHelper(mime);helper.setFrom(wwwitcastcnsina.com);//发件人helper.setTo(sunwukongsina.com);//收件人helper.setSubject(测试邮件);//主题helper.setText(你要是收到这封邮件你就成功了嘿嘿~~~~);//内容javaMailSender.send(mime);}}

4  编写spring配置文件applicationContext_mail.xml

bean idmailSenderclassorg.springframework.mail.javamail.JavaMailSenderImplproperty nameprotocol valuesmtp/property namehost valuesmtp.sina.com/property nameport value25 /property nameusername valuewwwitcastcnsina.com/property namepassword valueitcast27/property namejavaMailPropertiespropsprop keymail.smtp.authtrue/prop/props/property/beanbean idtestSend classcn.itcast.demo.TestSendproperty namejavaMailSender refmailSender/property/bean

5编写测试代码

ApplicationContext contextnewClassPathXmlApplicationContext(applicationContext_mail.xml);TestSend testSend (TestSend) context.getBean(testSend);testSend.sendMail();

2.4、ERP实现发送库存预警邮件

1在pom中添加依赖

!-- Javamail --dependencygroupIdjavax.mail/groupIdartifactIdmail/artifactIdversion1.4.4/version/dependency

2编写发送邮件的工具类

package util;import javax.mail.MessagingException;import javax.mail.internet.MimeMessage;import org.springframework.mail.javamail.JavaMailSender;import org.springframework.mail.javamail.MimeMessageHelper;/*** 邮件工具类* author Administrator**/public class MailUtil{private JavaMailSender javaMailSender;public void setJavaMailSender(JavaMailSender javaMailSender) {this.javaMailSender  javaMailSender;}private String fromAddress;public void setFromAddress(String fromAddress) {this.fromAddress  fromAddress;}/*** 发送邮件* param toAddress* param subject* param text* throws MessagingException*/public void sendMail(String toAddress,String subject,String text)throws MessagingException{MimeMessage mime  javaMailSender.createMimeMessage();MimeMessageHelper helpernew MimeMessageHelper(mime);helper.setSubject(subject);helper.setFrom(fromAddress);helper.setTo(toAddress);helper.setText(text);javaMailSender.send(mime);}}

3编写spring配置文件

bean idmailSenderclassorg.springframework.mail.javamail.JavaMailSenderImplproperty nameprotocol valuesmtp/property namehost valuesmtp.sina.com/property nameport value25 /property nameusername valuewwwitcastcnsina.com/property namepassword valueitcast/property namejavaMailPropertiespropsprop keymail.smtp.authtrue/prop/props/property/bean!-- Mail 工具类 --bean idmailUtil classutil.MailUtilproperty namejavaMailSender refmailSender/propertyproperty namefromAddressvaluewwwitcastcnsina.com/property/bean

4编写业务逻辑类

在 StoredetailBiz 类和 IStoredetailBiz 接口新增方法

private String toAddress;//收件箱private String subject;//主题private String text;//正文public void setToAddress(String toAddress) {this.toAddress  toAddress;}public void setSubject(String subject) {this.subject  subject;}public void setText(String text) {this.text  text;}/*** 发送库存预警邮件* throws MessagingException*/public void sendStoreAlertMail() throws MessagingException{//得到库存预警列表ListStoreAlert storeAlertList storedetailDao.getStoreAlertList();if(storeAlertList.size()0){mailUtil.sendMail( toAddress,subject.replace([time], new SimpleDateFormat(yyyy-MM-ddhh:mm:ss).format(new Date())),text.replace([count], String.valueOf(storeAlertList.size()) ));}else{throw new ErpException(没有库存预警信息);}}

5修改配置文件applicationContext-biz.xml

!-- 仓库库存 --bean idstoredetailBizclasscn.itcast.erp.biz.impl.StoredetailBizproperty namestoredetailDao refstoredetailDao/property!-- 邮件工具 --property namemailUtil refmailUtil/property!-- 收件人 --property nametoAddress value 收件人邮箱 sina.com/property!-- 邮件主题 --property namesubject value 库存预警邮件 -- 时间[time]/property!-- 邮件内容 --property nametext value 亲目前有 [count] 种商品出现库存预警请登陆系统查询 /property/bean

6编写Action代码

在 StoredetailAction 类新增方法

/*** 发送警报邮件*/public void sendAlertMail(){try {storedetailBiz.sendAlertMail();write(ajaxReturn(true, 发送成功));} catch (MessagingException e) {write(ajaxReturn(false, 无法发送邮件));e.printStackTrace();}catch(ErpException e){write(ajaxReturn(false,e.getMessage()));}}

7编写JS代码

修改 storealert.js 为 datagrid 添加 toolbar 属性

toolbar: [{iconCls: icon-add,text:发送预警邮件,handler: function(){$.ajax({url:storedetail_sendStoreAlertMail.action,dataType:json,success:function(value){$.messager.alert(提示,value.message);}});}}]

点击按钮测试运行。打开邮箱查看是否可以收到发送过来的邮件。

3、Quartz 实现定时发送预警邮件(重点)

3.1、需求及实现思路

定时查询库存预警信息如果存在库存预警信息发送邮件通知给相关工作人员。

3.2、什么是 Quartz 框架

Quartz 是一个开源的作业调度框架它完全由 Java 写成并设计用于 J2SE 和 J2EE 应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。
1Job
表示一个任务工作要执行的具体内容。
2JobDetail
JobDetail 表示一个具体的可执行的调度程序Job 是这个可执行程调度程序所要执行的内容另外 JobDetail 还包含了这个任务调度的方案和策略。
3Trigger 代表一个调度参数的配置什么时候去调。

4Scheduler 代表一个调度容器一个调度容器中可以注册多个 JobDetail 和Trigger。当 Trigger 与 JobDetail 组合就可以被 Scheduler 容器调度了。

3.3、入门小Demo

需求每间隔 10 秒控制台打印输出“调度程序已执行”时间

1创建工程引入Quartz框架

pom.xml 中添加 spring 的依赖 和 quartz 的依赖 和相关插件
spring 的依赖和相关插件参照上边的工程 quartz 的依赖如下

dependencygroupIdorg.quartz-scheduler/groupIdartifactIdquartz/artifactIdversion2.2.3/version/dependency

2编写任务类

package cn.itcast.demo;import java.util.Date;/*** 工作类* author Administrator**/public class JobTest {public void mylogic(){SimpleDateFormat sdfnew SimpleDateFormat(yyyy-MM-dd hh:mm:ss);System.out.println(调度程序已执行sdf.format(new Date()));}}

3编写配置文件

添加配置文件 applicationContext_job.xml

?xml version1.0 encodingUTF-8?beans xmlns/schema/beansxmlns:xsi/2001/XMLSchema-instancexsi:schemaLocation/schema/beans/schema/beans/spring-beans.xsd!-- 定义一个任务类 --bean idjob classcn.itcast.demo.JobTest/bean!-- 任务类描述 --bean idjobDetailclassorg.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBeanproperty nametargetObject refjob/propertyproperty nametargetMethod valuemylogic/property/bean!-- 触发器 --bean idmailTriggerclassorg.springframework.scheduling.quartz.CronTriggerFactoryBeanproperty namejobDetail refjobDetail/property!-- cron 表达式 每 10 秒执行一次--property namecronExpression value0/10 * * * * ?/property/bean!-- 总管理容器 --bean idstartQuartzclassorg.springframework.scheduling.quartz.SchedulerFactoryBean property nametriggerslistref beanmailTrigger//list/property/bean/beans

4编写测试类启动spring容器

ApplicationContext contextnewClassPathXmlApplicationContext(applicationContext_job.xml);

3.4、Crom表达式详解

Cron 表达式是一个字符串字符串以 5 或 6 个空格隔开分为 6 或 7 个域每一个域代表一个含义。

1.  域
Seconds秒可出现, - * /四个字符有效范围为 0-59 的整数
Minutes分钟可出现, - * /四个字符有效范围为 0-59 的整数
Hours小时:可出现, - * /四个字符有效范围为 0-23 的整数
DayofMonth日 of 月:可出现, - * / ? LW C八个字符有效范围为 1-31 的整

Month月:可出现, - * /四个字符有效范围为 1-12 的整数
DayofWeek日 of 星期:可出现, - * / ? L C #八个字符有效范围为 1-7 的整

1 表示星期天2 表示星期一 依次类推
Year年:可出现, - * /四个字符有效范围为 1970-2099 年
. 2.  字符含义
(1) * 表示匹配该域的任意值假如在 Minutes 域使用*, 即表示每分钟都会触发
事件。
(2) ? 表示不指定值。只能用在 DayofMonth 和 DayofWeek 两个域。因为DayofMonth 和 DayofWeek 会相互影响。例如想在每月的 20 日触发调度不管20 日到底是星期几则只能使用如下写法 13 13 15 20 * ?, 其中最后一位只能用而不能使用*如果使用*表示不管星期几都会触发。
(3) - 表示范围例如在 Minutes 域使用 5-20表示从 5 分到 20 分钟每分钟触发
一次
(4) / 表示起始时间开始触发然后每隔固定时间触发一次例如在 Minutes 域使用 5/20,则意味着 5 分钟触发一次而 2545 等分别触发一次.
(5) , 表示列出枚举值值。例如在 Minutes 域使用 5,20则意味着在 5 和 20 分每分钟触发一次。
(6)L 表示最后只能出现在 DayofMonth 和 DayofWeek 域。如果在 DayofMonth写 L 表示这个月的最后一天如果在 DayofWeek 写 L 表示每个星期的最后一天星期六 。如果在 DayofWeek 域使用 5L,意味着在最后的一个星期四触发。
(7)W 表示最近有效工作日(周一到周五),只能出现在 DayofMonth 域系统将在离指定日期的最近的有效工作日触发事件。例如在 DayofMonth 使用 5W如果 5 日是星期六则将在最近的工作日星期五即 4 日触发。如果 5 日是星期
天则在 6 日(周一)触发如果 5 日在星期一到星期五中的一天则就在 5 日触发。另外一点W 的最近寻找不会跨过月份
(8)LW:这两个字符可以连用表示在某个月最后一个工作日即最后一个星期五。
(9)#:用于确定每个月第几个星期几只能出现在 DayofWeek 域。例如在 4#2表示某月的第二个星期三。

3、示例

0 0 12 * * ? 每天中午 12 点触发0 15 10 ? * * 每天上午 10:15 触发0 15 10 * * ? 每天上午 10:15 触发0 15 10 * * ? * 每天上午 10:15 触发0 15 10 * * ? 2005 2005 年的每天上午 10:15 触发0 * 14 * * ? 在每天下午 2 点到下午 2:59 期间的每 1 分钟触发0 0/5 14 * * ? 在每天下午 2 点到下午 2:55 期间的每 5 分钟触发0 0/5 14,18 * * ? 在每天下午 2 点到 2:55 期间和下午 6 点到 6:55 期间的每 5 分钟触发0 0-5 14 * * ? 在每天下午 2 点到下午 2:05 期间的每 1 分钟触发0 10,44 14 ? 3 4 每年三月的星期三的下午 2:10 和 2:44 触发0 15 10 ? * MON-FRI 周一至周五的上午 10:15 触发0 15 10 15 * ? 每月 15 日上午 10:15 触发0 15 10 L * ? 每月最后一日的上午 10:15 触发0 15 10 ? * 6L 每月的最后一个星期五上午 10:15 触发0 15 10 ? * 6L 2002-2005 2002 年至 2005 年的每月的最后一个星期五上午 10:15触发0 15 10 ? * 6#3 每月的第三个星期五上午 10:15 触发

3.5、代码实现

1修改pom.xml文件添加Quartz依赖

!-- 调度框架 Quartz --dependencygroupIdorg.quartz-scheduler/groupIdartifactIdquartz/artifactIdversion2.2.3/version/dependency

2创建任务类执行发送警报邮件的方法

package cn.itcast.erp.job;import javax.mail.MessagingException;import cn.itcast.erp.biz.IStoredetailBiz;/*** 邮件相关任务* author Administrator**/public class MailJob {private IStoredetailBiz storedetailBiz;public void setStoredetailBiz(IStoredetailBiz storedetailBiz) {this.storedetailBiz  storedetailBiz;}/*** 发送库存报警邮件*/public void sendStoreAlertMail(){try {storedetailBiz.sendStoreAlertMail();} catch (MessagingException e) {e.printStackTrace();}}}

3编写配置文件applicationContext-job.xml文件

?xml version1.0 encodingUTF-8?beans xmlns/schema/beansxmlns:xsi/2001/XMLSchema-instancexsi:schemaLocation/schema/beans/schema/beans/spring-beans.xsd!-- 发送邮件任务类 --bean idmailJob classcn.itcast.erp.job.MailJobproperty namestoredetailBiz refstoredetailBiz/property/bean!-- 发送库存报警邮件任务--bean idsendStoreAlertMailJobDetailclassorg.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBeanproperty nametargetObject refmailJob/propertyproperty nametargetMethodvaluesendStoreAlertMail/property/bean!-- 触发器 --bean idmailTriggerclassorg.springframework.scheduling.quartz.CronTriggerFactoryBeanproperty namejobDetailrefsendStoreAlertMailJobDetail/property!-- cron 表达式 (时间点的描述) 每天的 上午 1220 和下午 1620 的时间执行 --property namecronExpression value0 17 12,16 * * ?/property/bean!-- 总管理容器 --bean idstartQuartzclassorg.springframework.scheduling.quartz.SchedulerFactoryBean property nametriggerslistref beanmailTrigger//list/property/bean/beans

启动运行

4、知识点总结

4.1、SQL 查询关联、子查询、聚合统计函数
4.2、视图简化开发。编写实体类和映射文件与表相同
4.3、JavaMail :发送邮件的 API .Spring 封装的 JavaMailSender 简化了开发
4.4、Quartz : 系统调度框架。 定时执行任务。Cron 表达式。 

我从事ERP销售因此对于那些认为ERP销售人员夸大其词的人来说我很容易成为目标。有些可以但我不是其中之一。您无需夸大其词即可证明ERP系统的合理性而且如果您正确地完成工作通常会导致成本降低即每年节省的成本超过成本。

我想指出许多ERP实施未能在销售和购买过程中带来要求或预期的成本收益的部分原因是对策略定义的关注不够。我将以最常见的ERP理由之一减少库存为例。

ERP系统本身不会减少库存。人们必须使用此工具来支持减少库存的目标。但是如果忽略服务水平将库存减少作为一个孤立的目标并不是一个好主意。一种更明智的方法是将目标设定为提高客户服务水平同时减少或优化整个组织的库存。实际上库存优化比减少库存是更好的目标。

这比听起来要难得多而且您可以很快达到客户实际上不知道如何执行此操作的地步。然后如果您将客户的位置缺乏知识或专业知识与大多数ERP系统缺少某些工具想要平衡服务和库存水平相结合的事实您可以理解为什么ERP销售和实施团队会避免问题。也可以说很多ERP销售团队不了解平衡库存的全部含义因此没有意识到他们产品中缺少“解决方案”部分。

通常发生的事情是很正确地客户使用新的ERP系统作为简化业务流程的理由。简单地简化流程通常会产生相同的最终结果但是效率更高这是一个隐藏的陷阱。

那是政策应该但很少会影响或影响新流程的地方。制定将服务水平与库存水平结合在一起的策略需要对流程和实践进行全面的重新思考而这正是成本降低并带来运营收益的原因。

策略定义需要先于需求定义。产生需求规范购买符合规范的系统并决定公司政策是不好的。在此阶段您可能已经购买了错误的系统。

相同的注释/方法可应用于其他一次性ERP系统论据例如减少在制品提高客户满意度等。

为了回答我的博客标题中提出的问题如果对策略进行了清晰智能的定义包括措施并且选择和实施过程集中在策略目标上那么ERP可以而且很可能会降低成本。前提是降低成本是一项政策目标。可能不是。