医药采购系统平台第10天02:按药品分类的统计按供货商统计按医院统计统计数据的导出DWR的配置和应用
如果想要获取相关的源码,笔记,和相关工具,对项目需求的二次开发,可以关注我并私信!!!
一 按药品分类的统计实现
1 按药品分类统计的需求
按药品统计:在指定时间段中采购量、采购金额、入库量、入库金额.................等等,效果图如下:
输入框中的采购时间是指:按照采购单基本信息表的创建时间来统计!
分类统计中需要搞清楚一个问题:分类统计的数据的来源,即:分类统计的原始数据是什么?
统计数据的来源于:交易明细表,在交易明细的基础上进行分类统计。
按药品的分类统计的功能是给医院、供应商、监督单位,这3类角色来使用的,因此sql语句中3个约束条件不能少!
2 dao
2.1 按药品分类统计的查询sql语句
该sql语句的编写是以“交易明细的统计实现”的sql语句为基础,并在其上添加group by分类的条件即可!
按药品分类统计的sql语句之方法一:本系统所使用的sql查询方法(颜色加深加粗为添加的内容)
select business.id, business.bm, business.mc, sum(nvl(business.cgl,0))cgl, sum(nvl(business.cgje,0))cgje, sum(nvl(business.rkl,0))rkl, sum(nvl(business.rkje,0))rkje, sum(nvl(business.thl,0))thl, sum(nvl(business.thje,0))thje, sum(nvl(business.jsl,0))jsl, sum(nvl(business.jsje,0))jsje from ( select useryy.id useryyid, useryy.mc useryymc, yycgd.bm yycgdbm, yycgd.id yycgdid, usergys.id usergysid, usergys.mc usergysmc, yycgdmx.ypxxid, ypxx.id, ypxx.bm, ypxx.mc, ypxx.jx, ypxx.gg, ypxx.zhxs, ypxx.scqymc, ypxx.spmc,
ypxx.jyzt,
(select info from dictinfo where ypxx.jyzt = dictcode and typecode = '003') jyztmc, (select info from dictinfo where typecode = '011' and dictcode = yycgdmx.cgzt) cgztmc, yycgdmx.cgl, yycgdmx.cgje, yycgdmx.rkl, yycgdmx.rkje, yycgdmx.thl, yycgdmx.thje, yycgdmx.jsl, yycgdmx.jsje from yybusiness2018 yycgdmx, yycgd2018 yycgd, useryy, usergys, ypxx where yycgdmx.yycgdid = yycgd.id and yycgd.useryyid = useryy.id and yycgdmx.usergysid = usergys.id and yycgdmx.ypxxid = ypxx.id
--监管单位查询管理地区内医院采购明细信息
and useryy.id in ( --管理地区内医院 select id from useryy where dq like '1.1.%')
--医院查询自己的采购明细信息 and useryy.id = '1f8b098b-067e-11e3-8a3c-0019d2ce5116'
--供货商查询: 与本供货商相关的采购明细信息 and usergys.id = '5197cdd2-08cf-11e3-8a4f-60a44cea4388'
)business
--分类统计之按药品分类统计。思路是:先按照药品的Id(business.id)进行分类统计,统计完之后的结果中如果存在相同的bm(流水号)字段,那么就再按照bm字段进行统计(business.bm)。Mc字段的统计以此类推. group by business.id,business.bm,business.mc |
按药品分类统计的sql语句之方法二(该方法可以自己参考):
select business.*, ypxx.bm, ypxx.mc, ypxx.jx from (select business.id, sum(nvl(business.cgl, 0)) cgl, sum(nvl(business.cgje, 0)) cgje, sum(nvl(business.rkl, 0)) rkl, sum(nvl(business.rkje, 0)) rkje, sum(nvl(business.thl, 0)) thl, sum(nvl(business.thje, 0)) thje, sum(nvl(business.jsl, 0)) jsl, sum(nvl(business.jsje, 0)) jsje from (select useryy.id useryyid, useryy.mc useryymc, yycgd.bm yycgdbm, yycgd.id yycgdid, usergys.id usergysid, usergys.mc usergysmc, yycgdmx.ypxxid, ypxx.id, ypxx.bm, ypxx.mc, ypxx.jx, ypxx.gg, ypxx.zhxs, ypxx.scqymc, ypxx.spmc,
ypxx.jyzt,
(select info from dictinfo where ypxx.jyzt = dictcode and typecode = '003') jyztmc, (select info from dictinfo where typecode = '011' and dictcode = yycgdmx.cgzt) cgztmc, yycgdmx.cgl, yycgdmx.cgje, yycgdmx.rkl, yycgdmx.rkje, yycgdmx.thl, yycgdmx.thje, yycgdmx.jsl, yycgdmx.jsje
from yybusiness2018 yycgdmx, yycgd2018 yycgd, useryy, usergys, ypxx where yycgdmx.yycgdid = yycgd.id and yycgd.useryyid = useryy.id and yycgdmx.usergysid = usergys.id and yycgdmx.ypxxid = ypxx.id
--监管单位查询管理地区内医院采购明细信息
and useryy.id in ( --管理地区内医院 select id from useryy where dq like '1.1.%')
--医院查询自己的采购明细信息 and useryy.id = '1f8b098b-067e-11e3-8a3c-0019d2ce5116'
--供货商查询: 与本供货商相关的采购明细信息 and usergys.id = '5197cdd2-08cf-11e3-8a4f-60a44cea4388'
) business
--分类统计 --按药品统计 group by business.id) business, ypxx where business.id = ypxx.id |
2.2 按药品分类统计的总数查询的sql
看需求可知:因为按药品进行分类统计也需要分页的,所以还需要进行总数查询的sql编写。
注意:下面的sql语句进行了优化,可以把不需要的字段去除掉。因为只需要计算总数,所以group by字句后面只需按照business.id字段进行分类即可!
Sql语句如下:背景颜色加深的部分为添加的语句。
--按药品分类统计列表的总数 select count(*) from ( select business.id from ( select useryy.id useryyid, useryy.mc useryymc, yycgd.bm yycgdbm, yycgd.id yycgdid, usergys.id usergysid, usergys.mc usergysmc, yycgdmx.ypxxid, ypxx.id, ypxx.bm, ypxx.mc, ypxx.jx, ypxx.gg, ypxx.zhxs, ypxx.scqymc, ypxx.spmc,
ypxx.jyzt,
(select info from dictinfo where ypxx.jyzt = dictcode and typecode = '003') jyztmc, (select info from dictinfo where typecode = '011' and dictcode = yycgdmx.cgzt) cgztmc, yycgdmx.cgl, yycgdmx.cgje, yycgdmx.rkl, yycgdmx.rkje, yycgdmx.thl, yycgdmx.thje, yycgdmx.jsl, yycgdmx.jsje from yybusiness2014 yycgdmx, yycgd2014 yycgd, useryy, usergys, ypxx where yycgdmx.yycgdid = yycgd.id and yycgd.useryyid = useryy.id and yycgdmx.usergysid = usergys.id and yycgdmx.ypxxid = ypxx.id
--监管单位查询管理地区内医院采购明细信息
and useryy.id in ( --管理地区内医院 select id from useryy where dq like '1.1.%')
--医院查询自己的采购明细信息 and useryy.id = '1f8b098b-067e-11e3-8a3c-0019d2ce5116'
--供货商查询: 与本供货商相关的采购明细信息 and usergys.id = '5197cdd2-08cf-11e3-8a4f-60a44cea4388'
)business
--分类统计 --按药品统计 group by business.id )
|
2.3 自定义mapper映射文件
因为这两个statement中的sql语句存在相同的部分,并且该sql语句的编写也是以“交易明细查询”的sql语句为基础,所以这里可以把相同的sql语句抽取了出来作为sql片段的方式!至于sql片段的内容可以参考源文件,也可以参考上节中的“交易明细查询”的mapper映射文件中的内容!
在YybusinessMapperCustom.xml映射文件中添加如下两个statement:
2.4 自定义mapper接口
需要在YybusinessMapperCustom.java接口中添加两个方法,如下:
3 service
因为数据的来源都是“交易明细”,因此接口中的条件也是都一样的,参考“交易明细查询的service接口的编写”!
接口功能:医院、监管单位、供货商按药品统计.
分类统计的内容如下:
监管单位:对管理地区内医院采购的药品的信息进行统计。
医院:统计自己的采购的药品的信息进行统计.
供货商:与本供货商相关的采购的药品信息进行统计.
接口参数:年份、查询条件,单位id、用户类型(1:卫生局 2:卫生院 3:卫生室 4:供货商)
BusinessService.java接口中添加如下两个方法:
BusinessServiceImpl实现类中的两个方法,如下:
4 Action
在TjAtion.java中添加两个方法,如下:
5 groupbyypxx.jsp页面
在groupbyypxx.jsp页面中需要注意几个地方:
第1个:url路径,如下:
第2个:这里要暂时的屏蔽掉,如下所示:在讲完DWR之后,这里的注释就可以取消掉了。
第3个:年份,如下:
第4个:采购状态,暂时先这么写,在讲完DWR之后,这里的代码会修改,如下:
6 调试
在menu.json中添加“按药品统计”链接,如下
先使用卫生室(医院)身份登录系统,如下:
查询结果如下:
当然,可以在交易明细列表下面添加一个导出的工具栏!(自己实现)
然后再以卫生局身份登录系统,如下
点击“按药品统计”链接后,应该统计出所有的药品信息!这样测试才算正确!
二 按供货商统计
需求:按供货商统计指定时间段的采购量、采购金额、入库量、入库金额。。。。.
使用卫生局来登录系统的话,原型系统中的页面中所查询出的数据如下:
Sql语句如下:
该sql语句的编写是以“交易明细查询”的sql语句为基础,并在其上添加group by分类的条件即可
select business.usergysid,business.usergysmc, sum(nvl(business.cgl,0))cgl, sum(nvl(business.cgje,0))cgje, sum(nvl(business.rkl,0))rkl, sum(nvl(business.rkje,0))rkje, sum(nvl(business.thl,0))thl, sum(nvl(business.thje,0))thje, sum(nvl(business.jsl,0))jsl, sum(nvl(business.jsje,0))jsje from ( select useryy.id useryyid, useryy.mc useryymc, yycgd.bm yycgdbm, yycgd.id yycgdid, usergys.id usergysid, usergys.mc usergysmc, yycgdmx.ypxxid, ypxx.id, ypxx.bm, ypxx.mc, ypxx.jx, ypxx.gg, ypxx.zhxs, ypxx.scqymc, ypxx.spmc,
ypxx.jyzt,
(select info from dictinfo where ypxx.jyzt = dictcode and typecode = '003') jyztmc, (select info from dictinfo where typecode = '011' and dictcode = yycgdmx.cgzt) cgztmc, yycgdmx.cgl, yycgdmx.cgje, yycgdmx.rkl, yycgdmx.rkje, yycgdmx.thl, yycgdmx.thje, yycgdmx.jsl, yycgdmx.jsje from yybusiness2018 yycgdmx, yycgd2018 yycgd, useryy, usergys, ypxx where yycgdmx.yycgdid = yycgd.id and yycgd.useryyid = useryy.id and yycgdmx.usergysid = usergys.id and yycgdmx.ypxxid = ypxx.id
--监管单位查询管理地区内医院采购明细信息
and useryy.id in ( --管理地区内医院 select id from useryy where dq like '1.1.%')
--医院查询自己的采购明细信息 and useryy.id = '1f8b098b-067e-11e3-8a3c-0019d2ce5116'
--供货商查询: 与本供货商相关的采购明细信息 and usergys.id = '5197cdd2-08cf-11e3-8a4f-60a44cea4388'
)business
--分类统计:按供货商统计 group by business.usergysid,business.usergysmc
|
三 按医院统计
需求:按医院统计指定时间段时采购量、采购金额、入库量、入库金额。。。。
SQL语句如下:
该sql语句的编写是以“交易明细查询”的sql语句为基础,并在其上添加group by分类的条件即可
select business.useryyid, business.useryymc, sum(nvl(business.cgl,0))cgl, sum(nvl(business.cgje,0))cgje, sum(nvl(business.rkl,0))rkl, sum(nvl(business.rkje,0))rkje, sum(nvl(business.thl,0))thl, sum(nvl(business.thje,0))thje, sum(nvl(business.jsl,0))jsl, sum(nvl(business.jsje,0))jsje from ( select useryy.id useryyid, useryy.mc useryymc, yycgd.bm yycgdbm, yycgd.id yycgdid, usergys.id usergysid, usergys.mc usergysmc, yycgdmx.ypxxid, ypxx.id, ypxx.bm, ypxx.mc, ypxx.jx, ypxx.gg, ypxx.zhxs, ypxx.scqymc, ypxx.spmc,
ypxx.jyzt,
(select info from dictinfo where ypxx.jyzt = dictcode and typecode = '003') jyztmc, (select info from dictinfo where typecode = '011' and dictcode = yycgdmx.cgzt) cgztmc, yycgdmx.cgl, yycgdmx.cgje, yycgdmx.rkl, yycgdmx.rkje, yycgdmx.thl, yycgdmx.thje, yycgdmx.jsl, yycgdmx.jsje from yybusiness2018 yycgdmx, yycgd2018 yycgd, useryy, usergys, ypxx where yycgdmx.yycgdid = yycgd.id and yycgd.useryyid = useryy.id and yycgdmx.usergysid = usergys.id and yycgdmx.ypxxid = ypxx.id
--监管单位查询管理地区内医院采购明细信息
and useryy.id in ( --管理地区内医院 select id from useryy where dq like '1.1.%')
--医院查询自己的采购明细信息 and useryy.id = '1f8b098b-067e-11e3-8a3c-0019d2ce5116'
--供货商查询: 与本供货商相关的采购明细信息 and usergys.id = '5197cdd2-08cf-11e3-8a4f-60a44cea4388'
)business
--分类统计 --按医院统计 group by business.useryyid,business.useryymc
|
四 统计数据的导出
建议:所有的统计功能,包括:交易明细查询,分类统计................等等,都可以添加导出功能,来将统计的数据以excel方式导出。
五 DWR的使用
1 什么是DWR
DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站.它可以允许在浏览器里的代码直接调用在WEB服务器上的JAVA方法,就像它就在浏览器里一样。
2 DWR的调用方法
普通ajax调用方法如下:
Dwr调用:
Flex:用于flash编程,实现页面/视图层的开发。它开发出的效果和网页样式不一样,更接近windows桌面的样式,开发的成果就是一个flash文件。
Flex实现了视图层:
3 Dwr的配置
第1步:导入Jar包:
如果是maven工程则需要加入以下依赖:
<!-- dwr -->
<dependency>
<groupId>org.directwebremoting</groupId>
<artifactId>dwr</artifactId>
<version>3.0.M1</version>
</dependency>
如果不是maven工程则需要导入: dwr-3.0.M1.jar
当然,在第一天的配置环境中就已经通过maven工程配置过了,如下图所示:
并且在Maven Dependcecies依赖包中已经导入了该dwr的jar包了,如下图:
第2步:Dwr servlet的配置。
其作用就是把表现层的实现整合到了servlet中,由servlet控制器来实现表现层。
在web.xml中加入:
<servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <!-- 是否允许调试,如果要在浏览器中调试则必须设置为true --> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <!-- 如果允许跨域请求,则必须将此值设置为false,默认值为true --> <init-param> <param-name>crossDomainSessionSecurity</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>allowScriptTagRemoting</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> |
如果访问的URL是:/dwr/,那么就会把请求交给dwr来处理。
第3步:在WEB-INF下配置dwr.xml文件,如下图:
配置dwr服务端中的哪些方法允许前台页面的ajax调用。
简单说,不是所有的后台的service中的方法都可以调用的,必须 是在这里的配置文件中配置的方法才可以调
用!
dwr.xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.ltd.uk/dwr/dwr30.dtd"> <dwr> <allow> <create creator="spring" javascript="dwrService"> <param name="beanName" value="dwrService" /> </create> </allow> </dwr> |
1)其中Creator:
creator属性的值可以是new,struts,spring......因为后台的service方法是通过整合spring来实现的,
所以设置成“spring”;
如果后台的service方法是通过struts来实现的,那么就要设置creator=”struts”;
如果如果后台的service方法中的类是通过new来实现的,即使用的是new来创建的一个类,那么这
里就要设置creator=”new”;
如果creator为new则param为:
<param name=”class” value=”类路径名”/>
2) javascript="dwrService":表示一个JS文件的名称。
作用:如果要调用dwr.xml配置的service(这里配置是名称为:dwrService的bean)的方法,需要在页面中引
入dwrService.js文件。
Js的地址是:
<script type='text/javascript' src='工程路径/dwr/interface/ dwrService.js'></script>.
/dwr/interface/ dwrService.js交给dwr的servlet进行处理,servlet会根据dwr.xml中配置,生成一个js文件 的内容。
<param name="beanName" value="dwrService" />表示:
Spring容器中的名称beanName为:dwrService的bean
4 Dwr测试
调用yycg.base.service.impl.DwrServiceImpl类里面的方法。
由于yycg.base.service.impl.DwrServiceImpl使用spring管理,那么,就要在spring容器中配置,在
applicationContext-base-service.xml文件中配置如下:
在页面中加入dwrService的js引用,可以调用上边dwrService这个bean中的方法。
<script type='text/javascript' src='工程路径/dwr/interface/ dwrService.js'></script>
如果页面中要调用其它bean的方法,则页面中还需要引入:
<script type='text/javascript' src='工程路径/dwr/interface/ XXXXXXXX.js'></script>
都必须引用dwr的引擎配置的js文件:
<script type='text/javascript' src='${baseurl}dwr/engine.js'></script>
<script type='text/javascript' src='${baseurl}dwr/util.js'></script>
测试如下:
调用无参数方法:
//dwrService是加载js的名称
//testdwr是dwrService对应的bean的方法名
//callback:回调方法
dwrService.testdwr({
callback:function(data) {
alert(data);
}});
调用有参数方法:
dwrService.testdwr2('张三',{
callback:function(data) {
alert(data);
}});
5 Dwr在本系统的应用
1)在年份下框显示的数据,通过dwr来获取.
需求:显示近6年的年份。
需要在dwrService写一个方法:
获取近6年的年份
客户端通过dwr调用该方法,得到近6年的年份,在页面向年份下拉框设置6年的年份。
如果通过dwr方法,在action方法中就无需调用service获取数据,再通过model传到页面。
客户端调用上边的方法,dwr会自动将list转成json在客户端解析。
2) 在所有数据字典下拉框, 通过dwr来获取数据字典信息.
针对业务代码:
编写根据typecode获取业务代码及代码对应的名称 .
针对普通配置项:
编写根据typecode获取普通配置项id及对应的名称.
客户端使用固定的三个js方法,解析上边三个方法返回数据,解析完数据,将数据填充到select下拉框。