企业从供货商进货,下采购订单;选择商品和仓库入库,管理库存;待销售订单创建时发货出库。用户可以登录系统,按自身权限的不同访问不同的页面,使用不同的功能;管理员可以管理用户信息和基础信息。
根据业务需求分析得知,系统按功能分为分为以下五个模块
(1) 用户管理:包括用户列表
(2) 权限管理:包括权限列表、角色列表
(3) 库存管理:包括入库流水、出库流水、商品库存
(4) 订单管理:包括采购订单,销售订单
(5) 基础信息管理:包括商品列表、商品分类、仓库信息、供货商信息
系统基本功能图如下所示:
图 3‑1 系统功能模块分解图
用户登录系统输入用户名和密码,系统判断应户名和密码是否正确,错误返回对应的提示,正确则判断是管理员或用户。管理员有权限访问用户管理页面,可以修改用户信息;普通用户依照该用户的权限访问对应页面,执行对应的操作。
图 3‑2 用户管理流程图
动态权限菜单可以根据登录用户的不同,在身份验证后返回对应的菜单列表,显示不同的导航栏。
菜单列表抽象化菜单及按钮授权,全部权限分为三级,分别是导航栏,导航菜单和按钮,权限包含url代表本权限访问的网络路径,授权信息用于用户角色验证后的鉴权操作。
角色列表显示角色信息,以及角色和权限的对应关系。通过赋予用户不同的角色来分配权限,不同的访问url可以区分资源访问请求,查询用户否含有权限。管理员可以新建一个角色,编辑角色信息和删除角色。通过下拉菜单查看角色的权限并为角色设置权限。
订单管理模块包括采购订单和销售订单。采购和销售需求产生后,用户可以在系统中新增采购订单,指定采购员、供应商、采购仓库等信息,根据需要选择商品和数量,单个订单支持多个商品,点击商品详情可以查看当前订单的商品。在订单生成后默认状态未审核,待管理员审核后可以继续入库流程。
库存管理模块包括出入库流水记录以及仓库的库存量显示。
出入库流水模块中,用户可以选择入库商品、商品数量、仓库、入库员以及入库时间。流水列表分页查询所有流水信息,可以按照日期、商品等信息排序。顶部的搜索框支持按照编号模糊检索订单。管理员可以编辑、修改订单信息。
商品库存列表支持查询商品在各个仓库中的库存量,统计库存总量,可以按照商品模糊搜索。
保存了仓库商品及其他基础信息,用于维护系统信息健康完整。
商品列表除商品基本信息外还定义了商品的采购价与销售价,支持两位小数。便于接入企业ERP系统分析财务报表。商品分类信息作为商品的属性,与商品对应。
本节确定存储哪些数据,数据元素如何相互关联。抽象出数据实体以及实体应包含的属性,根据其中的关系设计关联表。有了这些信息就可以开始绘制数据库模型,最后建立数据库。
用户管理模块包含三个数据实体。根据数据库设计原则,需要关联表存储角色和菜单的对应信息。角色与菜单是多对多关系,需要一张关联表维护关联关系。
图 3‑3 用户管理数据关系模型图
商品包含商品分类信息,商品和分类是多对一关系,商品包含商品分类外键。采购价格与销售价格支持两位小数。由于所有可以表示货币金额的浮点值都无法保证完全按原样存储在内存中,因此,如果要存储0.1元(10角),则float / double不能保证按原值精确存储。基于以上原因不使用浮点型而使用big int乘100倍存储金额,这样可以保证系统运行时的准确性。
图 3‑4 商品数据库关系模型图
订单管理模块有采购订单表,销售订单表,供应商和客户。
通常情况下系统中使用自增id作为订单的编号,但在高并发的情况下,自增主键的上届会在时成为争抢的对象,本系统采用基于uuid生成的唯一码最为识别标识,同时系统会根据时间生成sn码,便于用户确认订单。
采购订单和商品是多对多关系,建立关联表保存商品详情信息。采购订单与供应商是多对一关系,将供应商id作为采购订单的外键。
图 3‑5 订单管理数据关系模型图
库存管理包括仓库、入库流水、出库流水和库存表。
在出入库流水中关联外键有仓库id、用户(入库员)id、商品id和采购订单id,流水订单表一行代表一次入库操作,统计同一仓库所有入库出库操作就可得到商品库存信息。
库存表用于记录各商品在不同仓库中的库存状态,商品和仓库是多对多的关系,采用复合主键的方式,避免重复存入同一个商品在同一个仓库中的信息,保证了数据库数据的正确性。库存表保存了商品在仓库中的入库、出库总量,结合原先的库存结余可以计算得出出入库操作后的库存总量值。
物理模型图反映了实体间的联系,是设计数据库时的依据。根据模型图可以自动生成建表语句。
图 3‑6 cdm关系模型图
根据功能模块将业务部分分为4个微服务sso-service、data-service、stock-service、order-service。
项目使用Maven父子项目结构,Maven父项目POM用于构建项目,以避免重复使用pom文件之间的继承或重复配置,保持依赖的一致性,有助于长期维护项目。子POM需要使用parent标记并指定groupId/artifactId/version属性来引用父POM 。这个pom文件将从父POM继承所有属性和依赖项,还可以包括子项目特定的依赖项。
图 3‑7 工程目录结构
es为Maven父项目,只包含pom文件,定义了全局版本依赖
pom文件首先定义了springboot的版本
org.springframework.boot
spring-boot-starter-parent
2.2.6.RELEASE
全局版本依赖引入全部开发需要的组件
开发过程中存在很多微服务公用的类,方法以及工具,这些工具定义在每个微服务中会导致代码的重复,同时版本难以控制,在开发过程中造成问题。
es-common为公用模块,pom类型为jar类型,和其他微服务不同,公用模块无法单独运行,在模块内部可以定义为公共依赖,被其他微服务锁依赖,这样所有微服务可以同时使用同一版本的开发工具。这个模块中定义了公用的pojo对象,过滤器,拦截器,全局异常处理方法以及工具类等。
其具体的内容如下:
config:类的方式定义全局配置信息
exception:自定义异常,用于业务发生无法处理的意外情况时,向服务上层返回自定义的包装异常,与系统默认的异常不同,可以快速清楚地显示出问题的所在。
filter:全局过滤器,过滤器由Servlet规范定义,用于访问系统前后进行访问拦截,本系统中使用过滤器验证登录信息。
pojo:对应数据库中的一条数据,在数据持久层中作为数据库中数据读写的规范,也可以暴露给其他类或方法。将这些对象定义在公共组件中使规范化变得简单,微服务使用时也更加方便。
service:feign伪装rpc通信接口时使用的类,需要公开给feign客户端。
util:封装了常用的工具,例如身份验证工具。
vo:值对象,定义了一系列的值包装类,例如分页查询参数,统一的json返回参数等。
web:定义了全局异常处理的解决办法。
微服务的注册发现中心,本项目共运行了两台eureka服务器,保证了高可用,定义了自身的端口号,同时定义eureka集群的url地址,当服务启动后,每隔一次心跳时间后eureka就会试图向集群中的其他服务注册,当一台服务down机后不会影响整体服务的正常运行。
微服务的通用网关,为微服务应用提供统一的对外访问接口。统一的网关可以提高系统的安全性,避免所有微服务接口直接暴露在公网之中,同时基于过滤器的统一身份校验可以拦截大部分非法请求。
用户管理服务,提供三个功能用户管理,角色管理,菜单管理。
用户登录时返回相应的通知,同时做好防注入检测。用户权限查询,批量查询用户名。
角色管理提供角色的增删改查,分页查询。查询角色的权限,支持列表返回和树形返回两种状态,列表返回用于常规的角色列表查询,树形返回支持用子节点挂载的方式返回一个权限树,用于角色的对应权限展示。
菜单管理即权限管理,一级菜单的名称作为首页左侧导航栏的名称;二级菜单的路径作为前端路由导航的依据,点击后可以跳转到不同页面;三级菜单本质是按钮,其路径代表访问资源的url路径,可以指导前端正确的请求资源。
基础信息服务保存了用于系统正常运行所需的数据对象,包括商品,分类,供货商,客户以及仓库信息。数据服务提供每个对象的增删改,分页查询。除此之外,由于在微服务的交流中有很大一部分流量都是查询名称,还要借助缓存提供快速通过id查询名称的接口。
基础信息服务作为feign的服务端,在公共依赖中暴露自己的服务接口,通过feign远程连接为其他微服务提供查询支持。
库存信息管理分为入库、出库管理以及库存量管理。
库存管理维护一张商品-仓库关联表,可以通过商品id查询该商品在各仓库中的分布情况,前端会继续计算得出商品的总库存量。
出入库接口支持新建流水,前端查询数据接口后得到商品、仓库等id,通过预先定义好的数据格式将数据发送到后端,后端服务器根据时间创建流水的sn码,定义状态,查询该商品的实时库存存入流水,便于后续商品盘仓操作。
订单服务提供对出入库订单的支持,包括订单分页查询以及编辑删除订单。新建订单时,后端服务器根据时间生成sn码,并且为了避免高并发状况下主键自增争抢上届的问题,使用随机的uuid作为订单的标识。