孝感市药品集中采购系统.docx
《孝感市药品集中采购系统.docx》由会员分享,可在线阅读,更多相关《孝感市药品集中采购系统.docx(44页珍藏版)》请在冰点文库上搜索。
孝感市药品集中采购系统
孝感市药品集中采购系统
1项目背景
传统医药采购是医院自己联系供货商购买药品,这样做监督单位无法直接监控医院和供货商的交易情况从而无法控制医药行业秩序,比如药品的价格无法控制,本系统实现了医疗机构上网采购、药品经营企业上网销售、监督单位网上监管,实现了药品交易过程的数字化、网络化、透明化。
本系统依托与省级医药招标采购平台,在省级医药集中采购思想的指导下建立的市级医药采购平台,由市卫生监督单位将省级药品目录应用在市平台上,在市卫生局及下属单位监督下,乡、镇以下的卫生室在市平台药品目录范围内进行集中药品采购。
2用户角色
2.1监管单位
市卫生局(药政科):
负责通过采购平台进行监管,主要监管医院和供货商之间的业务交易情况。
卫生院:
乡镇一级医疗单位,由市卫生局直管。
负责审核医院下的采购单。
2.2医院
卫生室:
最小的医疗单位,村卫生室(卫生所)。
由市卫生局直管。
通过平台上网进行药品采购。
2.3供货商
药品生产企业、企业销售代理(一级代理,二级代理),称为:
药品供货商
接收卫生室药品采购,按时进行药品配送。
通过平台上网进行药品销售(供应药品)。
2.4系统管理员
系统维护、配置、系统备份等。
3业务流程
本系统的核心业务是采购单模块:
4项目配置情况
4.1人员配置
角色
职责
人员
项目经理
项目整体执行控制
1
架构师
系统架构搭建
系统集成
技术预研
1
需求分析
需求调研、需求分析
编写系统需求规格说明书
2(从开发调过来)
开发
系统模块开发编码
单元测试
参与系统集成
配合系统测试,修改bug
配合系统产品化工作
4
测试
编写测试用例
系统集成测试
系统功能测试
系统性能测试
2
产品化
制作系统安装包
制作系统升级包
1
系统维护
系统安装调试
用户培训
后期系统维护
1
4.2开发周期
2016年2月至2016年8月,项目周期6个月
阶段名称
开始时间
结束时间
工期(工作日)
需求阶段
2016年2月
2016年3月
30
开发阶段
2016年3月
2016年5月
60
测试阶段
2016年5月
2016年7月
60
部署上线
2016年7月
2016年8月
30
4.3系统正式运行环境
网络环境:
互联网
硬件平台:
两台服务器:
一台安装数据库
一台安装web服务
操作系统平台:
Centos6.5
数据库平台:
Oracle10G
Java环境:
Jdk1.7
Web服务:
Tomcat7
5系统架构
1、系统是由maven进行管理,通过maven将系统划分为技术架构模块、工具模块,业务模块(主工程)、聚合模块(只需要一个pom.xml即可)
2、系统控制层是通过springmvc3.1.4实现,系统持久层是通过mybatis3.2.3实现,业务层由spring进行管理,系统整体由spring进行整合。
系统数据库是oracle10G。
6用户管理模块
6.1表结构
6.1.1系统用户表SYSUSER:
记录系统中所有用户
Id:
主键
USERID账号
USERNAME名称
GROUPID:
用户类别0:
系统管理员,1:
卫生局2:
卫生院3:
卫生室4:
供货商
SYSID:
系统用户所属的单位
根据GROUPID判断,所对应的单位
6.1.2监督单位表USERJD:
Id:
主键
MC:
单位名称:
DQ:
管理区域
6.1.3医院单位表USERYY:
Id:
主键
MC:
单位名称:
DQ:
所属区域
6.1.4供货商单位表USERGYS:
Id:
主键
Mc:
单位名称:
6.1.5行政区域表BSS_SYS_AREA:
市(一级)、县/乡/镇(二级)、村(三级)
树型结构。
区域id规则:
XX.XX.XX.
使用规则方便:
比如查询某个镇的区域:
select*fromBSS_SYS_AREAtwhereareaidlike'1.1.%'andt.arealevel='3'
管理关系:
市卫生局管理本市所有卫生院
卫生院管理本辖区的卫生室
通过在监督单位和医院单位表中添加DQ(地区)字段,实现行政管理关系。
比如:
查询某镇下的医院
select*fromUSERYYtwheret.dqlike'1.1.%'
6.1.6供货商供货区表USERGYSAREA:
USERGYSID:
供货商id(外键,指向供货商单位表)
AREAID:
区域id(外键,指定区域表BSS_SYS_AREA)
供货关系:
指定供货商供货的区域
6.2用户查询列表
通过jqueryeasyui的datagrid加载数据列表。
6.3数据列表的分页
使用oracle的分页实现。
selectpage_2.*
from(selectpage_1.*,rownumpage_num
from(
--这里可以填入任何查询的SQL
)page_1
whererownum<=${pageQuery.PageQuery_end})page_2
wherepage_2.page_num>=${pageQuery.PageQuery_start}
6.4用户添加
在业务层在要对传入的参数合法性进行校验,比如非空校验,长度校验,账号唯一性校验。
根据用户类型,输入的单位名称必须在对应的单位表中查询到,否则抛出可预知异常。
6.5用户修改
在业务层要对传入的参数合法性进行校验,比如非空校验,修改用户账号不允许占用别人的账号,输入的单位名称必须在对应的单位表中查询到,否则抛出可预知异常。
如果从页面提交的密码值为空说明用户不修改密码,否则就需要对密码进行加密存储。
7药品目录模块
7.1药品目录表
系统数据库中,创建一个张表ypxx(药品目录表):
记录了市级医药平台所使用的所有药品(平台药品总目录)
药品流水号:
省平台和市平台统一使用的号,此流水号在省级招标平台产生
药品通用名:
(行业内对药品的通用称呼)、剂型、规格、转换系数、生产企业、商品名、药品中标价
药品交易状态(业务代码:
1:
正常、2:
暂停)
7.2药品目录导出
7.2.1ApachePOIHSSF和XSSF导出excel方法小结
7.2.1.1HSSF导出excel
HSSF只操作.xls文件(97-03版本excel),一个sheet中行有限制,最大65536行。
第一步:
创建workbook工作簿(excel文档)
Workbookwb=newHSSFWorkbook();
FileOutputStreamfileOut=newFileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
第二步:
创建一个sheet工作表
Sheetsheet3=wb.createSheet(safeName);
第三步:
在sheet中创建row行
Rowrow=sheet.createRow((short)0);
第四步:
在row行中创建cell单元格
Cellcell=row.createCell(0);
第五步:
向cell中写数据
cell.setCellValue
(1);
第六步:
输出excel文件(写文件)
wb.write(fileOut);
fileOut.close();
优点:
编程方便,如果数据量小,速速很快的
缺点:
如果数据量大,会引起内存溢出的问题(HSSF工作原理,将excel中所有数据填充到java对象中,进行文件写操作。
)
7.2.1.2XSSF导出excel
XSSF操作03以上版本(07版本)excel,扩展名.xlsx,工作表行数没有限制
写excel文件步骤:
第一步:
创建一个工作簿
SXSSFWorkbookwb=newSXSSFWorkbook(-1);
-1:
关闭自动刷新
SXSSFWorkbookwb=newSXSSFWorkbook(XXXX);(自动刷新)
XXXX:
保持内存中有XXXX条记录,超过部分写入磁盘
第二步:
创建一个工作表
//创建一个sheet
Sheetsh=wb.createSheet();
第三步:
在sheet中创建行
Rowrow=sh.createRow(rownum);
第四步:
创建单元格
Cellcell=row.createCell(cellnum);
第五步:
向单元格中写数据
cell.setCellValue(address);
第六步:
将内容写入磁盘
由于-1设置关闭自动刷新
需要人工主动刷新
调用:
((SXSSFSheet)sh).flushRows(100);
第七步:
输出文件
wb.write(out);//将临时写的文件合并,输出整个文件
优点:
写大数据量时不会发生内存溢出问题
缺点:
写数据时速度慢
本系统基于以上分析,最终决定使用XSSF导出药品目录信息。
7.2.2药品目录导出流程
第一步:
输入查询条件,查询出药品目录信息
第二步:
点击导出按钮
将符合查询条件的所有记录(不是一页的数据)全部导出。
第三步:
下载导出文件
7.2.3虚拟目录
虚拟目录:
web请求路径
目标:
将excel导出文件写到服务器的某个目录,用户通过客户端远程下载服务器上该目录的内容。
7.3药品目录的导入
7.3.1药品目录导入流程
将线下编辑好的excel导入系统中,从客户端导入服务端。
第一步:
线下编辑导入文件
根据提前定义好的导入文件规则去定义,根据导入模块编写导入文件。
第二步:
登陆系统,执行导入
将本地的文件上传到服务端
第三步:
服务端程序解析导入文件内容
读文件过程。
第四步:
针对导入失败的药品目录提供excel下载,里面记录了导入失败的原因
7.3.2HSSF导入excel
支持97-03版本的excel。
7.3.2.1用户驱动模式
使用HSSF读文件步骤:
第一步:
创建一个workbook
//文件输入流
InputStreamis=newFileInputStream("d:
/test11.xls");
//创建hssf的workbook,将文件流传入workbook
HSSFWorkbookhssfWorkbook=newHSSFWorkbook(is);
第二步:
读sheet
//得到workbook某个的sheet,numSheet是sheet的序号,序号从0开始
HSSFSheethssfSheet=hssfWorkbook.getSheetAt(numSheet);
第三步:
读sheet中的行
//读取每一行数据,rowNum指定行下标从0开始
HSSFRowhssfRow=hssfSheet.getRow(rowNum);
第四步:
读单元格的数据
//读取一行中某个单元格内容,cellNum指定单元格的下标,从0开始
HSSFCellcell=hssfRow.getCell(cellNum);
//调用单元格的get方法
cell.getStringCellValue()
优点:
读取数据量小,读取速度很快
缺点:
读取大数据量时,读取数据很慢,可能导致内存溢出问题(内存溢出的原因是将流中的数据全部加载到内存进行输出)
7.3.2.2事件驱动模式
事件驱动式,类似xml的sax解析。
需要实现HSSFListener接口。
原理:
根据excel底层存储(07以版本采用xml存储,以下版本采用二进制)标签决定事件出发点。
目标:
在解析完一行(row)数据时进行触发。
优点:
读取大数据时,不会导致内存溢出
缺点:
用户在解析数据时比较困难。
读取数据时速度不快的,因为读取数据的同时根据每个标签进行事件触发。
7.3.3药品目录维护
主要包括两个功能:
药品交易状态控制和药品删除
药品交易状态控制:
从省局导入药品目录后,由于某种原因此种药品暂时不宜再流通时,需要更改药品的交易状态,设置为暂停交易
药品删除:
对于可以确定以后不再流通时,可以对药品目录药品执行删除操作(不建议对药品目录进行物理删除,使用上面设置暂停交易就可以,为了本系统的扩展性,添加此功能),此删除需要同时针对三个表操作,药品目录表,供应商药品目录表,供应商药品控制目录表
7.4供货商药品目录维护
供货商需要将自己供应的药品信息添加到供货商药品目录中,药品目录中存在药品说明供货商要供应这些药品,医院按照供货商供应药品去采购。
供货药品添加时暂停交易的药品是不允许添加的。
供货商药品目录添加一条记录同时向供货商药品控制目录添加一个记录,控制状态采用的是从系统参数配置表中查询出来的默认值。
供货商供应药品删除:
供货商不再供货从供货商药品目录表中删除记录,根据供货商id和药品id进行删除。
供货商药品控制目录表中不删除。
7.5供货商药品目录控制
监督单位可以对供货商供应的药品进行控制,允许供货商正常供货,或取消供货商供货。
8采购单模块
8.1创建采购单
8.1.1填写采购单基本信息
采购单基本信息包括:
采购年份、采购单名称、建单时间、提交时间、联系人、联系电话、备注、采购单状态。
采购单编号命名规则:
4位年+6位流水号
6位流水号:
使用oracle序列完成。
采购单编号序列按年划分,
序列名:
yycgdbm+4位年份
Sql:
createsequenceYYCGDBM2014
minvalue1
maxvalue999999
startwith101060
incrementby1
cache20;
序列由动态表的存储过程自动创建。
使用序列生成采购单号:
创建一个自定义mapper。
--采购单号生成-->
select'${value}'||yycgdbm${value}.nextvalbmfromdual
8.1.2添加采购单药品明细及采购量
采购药品添加时,药品的供货状态为取消或者交易状态为暂停交易时不允许添加。
采购药品信息保存时需要填写采购量,并且药品的供货状态需要为正常及交易状态为正常。
提交采购单之前需要先填写采购药品明细信息。
特殊情况:
比如在采购药品信息保存之前监督单位更改了此药品的供货状态为取消或者交易状态为暂停交易,那么该药品在操作保存采购药品信息时是不能保存成功的。
这种情况只有删除此采购药品,才能提交采购单。
8.2采购单维护
采购单状态为未提交或者审核未通过的状态下才可以修改,其他状态只能查看。
在service层也做了校验的,只有采购单状态为未提交或者审核状态未通过才可以修改。
采购单删除:
只有在采购单状态为未提交或者审核通过的状态下才可以删除。
8.3采购单审核
监督单位针对医院提交的采购单进行审核,审核之前查看下采购单,审核内容包括药品的状态(供货状态和交易状态)以及采购量是否合理,依据审核情况给出处理意见,审核通过或者审核不通过。
8.4采购单受理
供货商受理审核通过的采购单,供货商在受理前需要查看下采购单药品的状态及采购量,确认能否供货,依据实际情况提交确认供货和无法供货。
针对发货量少的药品可以采用选择确认发货的的方式,供应商登录系统查询待受理的发货清单,选择要发货的药品进行确认发货。
针对发货量大的药品,供货商要将发货的药品整理成excel文件,通过系统提供的导入发货清单,清单中存在的药品明细系统会自动执行发货操作。
8.5采购单入库
医院依据实际收到的药品数据进行入库操作,需要填写入库量,发票或者入库单号,药品有效期,执行确认入库操作。
9统计分析模块
交易明细查询,通过数据聚合将采购信息、入库信息、退货信息、结算信息聚合在一张交易明细表,避免了多表关联查询,提高了数据库的查询统计性能。
聚合过程如下:
采购信息在采购单审核通过时将采购信息写入交易明细表。
入库信息,在入库信息表通过触发器将入库信息聚合在交易明细表。
退货信息,在退货明细表通过触发器将退货信息聚合在交易明细表。
结算信息,在结算信息表通过触发器将结算信息聚合在交易明细表
9.1按交易明细统计
9.2按药品统计
9.3按区域统计
10权限整合
10.1什么是权限管理
只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。
权限管理包括用户认证和授权两部分。
10.2用户认证
10.2.1概念
用户认证,用户去访问系统,系统要验证用户身份的合法性。
最常用的用户身份验证的方法:
1、用户名密码方式、2、指纹打卡机、3、基于证书验证方法。
。
系统验证用户身份合法,用户方可访问系统的资源。
10.2.2用户认证流程
10.2.3关键对象
subject:
主体,理解为用户,可能是程序,都要去访问系统的资源,系统需要对subject进行身份认证。
principal:
身份信息,通常是唯一的,一个主体还有多个身份信息,但是都有一个主身份信息(primaryprincipal)
credential:
凭证信息,可以是密码、证书、指纹。
总结:
主体在进行身份认证时需要提供身份信息和凭证信息。
10.3用户授权
10.3.1授权概念
用户授权,简单理解为访问控制,在用户认证通过后,系统对用户访问资源进行控制,用户具有资源的访问权限方可访问。
10.3.2授权流程
10.3.3关键对象
授权的过程理解为:
who对what(which)进行how操作。
who:
主体即subject,subject在认证通过后系统进行访问控制。
what(which):
资源(Resource),subject必须具备资源的访问权限才可访问该资源。
资源比如:
系统用户列表页面、商品修改菜单、商品id为001的商品信息。
资源分为资源类型和资源实例:
系统的用户信息就是资源类型,相当于java类。
系统中id为001的用户就是资源实例,相当于new的java对象。
how:
权限/许可(permission),针对资源的权限或许可,subject具有permission访问资源,如何访问/操作需要定义permission,权限比如:
用户添加、用户修改、商品删除。
10.3.4权限模型
主体(账号、密码)
资源(资源名称、访问地址)
权限(权限名称、资源id)
角色(角色名称)
角色和权限关系(角色id、权限id)
主体和角色关系(主体id、角色id)
如下图:
通常企业开发中将资源和权限表合并为一张权限表,如下:
资源(资源名称、访问地址)
权限(权限名称、资源id)
合并为:
权限(权限名称、资源名称、资源访问地址)
上图常被称为权限管理的通用模型,不过企业在开发中根据系统自身的特点还会对上图进行修改,但是用户、角色、权限、用户角色关系、角色权限关系是需要去理解的。
10.3.5分配权限
用户需要分配相应的权限才可访问相应的资源。
权限是对于资源的操作许可。
通常给用户分配资源权限需要将权限信息持久化,比如存储在关系数据库中。
把用户信息、权限管理、用户分配的权限信息写到数据库(权限数据模型)
10.3.6权限控制
10.3.6.1基于角色的访问控制
RBAC(rolebasedaccesscontrol),基于角色的访问控制。
比如:
系统角色包括:
部门经理、总经理。
。
(角色针对用户来划分)
系统代码中实现:
//如果该user是部门经理则可以访问if中的代码
if(user.hasRole('部门经理')){
//系统资源内容
//用户报表查看
}
问题:
角色针对人划分的,人作为用户在系统中属于活动内容,如果该角色可以访问的资源出现变更,需要修改你的代码了,比如:
需要变更为部门经理和总经理都可以进行用户报表查看,代码改为:
if(user.hasRole('部门经理')||user.hasRole('总经理')){
//系统资源内容
//用户报表查看
}
基于角色的访问控制是不利于系统维护(可扩展性不强)。
10.3.6.2基于资源的访问控制
RBAC(Resourcebasedaccesscontrol),基于资源的访问控制。
资源在系统中是不变的,比如资源有:
类中的方法,页面中的按钮。
对资源的访问需要具有permission权限,代码可以写为:
if(user.hasPermission('用户报表查看(权限标识符)')){
//系统资源内容
//用户报表查看
}
上边的方法就可以解决用户角色变更不用修改上边权限控制的代码。
如果需要变更权限只需要在分配权限模块去操作,给部门经理或总经理增或删除权限。
建议使用基于资源的访问控制实现权限管理。
10.3.7权限管理解决方案
10.3.7.1粗粒度和细粒度权限
粗粒度权限管理,对资源类型的权限管理。
资源类型比如:
菜单、url连接、用户添加页面、用户信息、类方法、页面中按钮。
。
粗粒度权限管理比如:
超级管理员可以访问户添加页面、用户信息等全部页面。
部门管理员可以访问用户信息页面包括页面中所有按钮。
细粒度权限管理,对资源实例的权限管理。
资源实例就资源类型的具体化,比如:
用户id为001的修改连接,1110班的用户信息、行政部的员工。
细粒度权限管理就是数据级别的权限管理。
细粒度权限管理比如:
部门经理只可以访问本部门的员工信息,用户只可以看到自己的菜单,大区经理只能查看本辖区的销售订单。
。
粗粒度和细粒度例子:
系统有一个用户列表查询页面,对用户列表查询分权限,如果粗颗粒管理,张三和李四都有用户列表查询的权限,张三和李四都可以访问用户列表查询。
进一步进行细颗粒管理,张三(行政部)和李四(开发部)只可以查询自己本部门的用户信息。
张三只能查看行政部的用户信息,李四只能查看开发部门的用户信息。
细粒度权限管理就是数据级别的权限管理。
10.3.7.2如何使实现粗细粒度的权限管理
如何实现粗粒度权限管理?
粗粒度权限管理比较容易将权限管理的代码抽取出来在系统架构级别统一处理。
比如:
通过springmvc的拦截器实现授权。
如何实现细粒度权限管理?
对细粒度权限管理在数据级别是没有共性可言,针对细粒度权限管理就是系统业务逻辑的一部分,如果在业务层去处理相对比较简单,如果将细粒度权限管理统一在系统架构级别去抽取,比较困难,即使抽取的功能可能也存在扩展不强。
建议细粒度权限管理在业务层去控制。
比如:
部门经理只查询本部门员工信息,在service接口提供一个部门id的参数,controller中根据当前用户的信息得到该用户属于哪个部门,调用service时将部门id传入service,实现该用户只查询本部门的员工。
10.4基于URL的权限管理
10.5本系统权限管理的实现
使用第三方系统管理完成用户授权,通过用户session接入接口,顺利进入第三方系