项目总结 面向小型店面的餐饮 SaaS 平台
项目来源
2023 年春季学期课程设计项目
-
项目架构选定 完成《云计算与软件服务》课程中本应作为结题作业,但是因为课程安排而废除的 SaaS 项目
-
项目需求选定 顺接 2023 年春季学期《ERP 和 SCM》课程,巩固对于 EPR 系统的理解,小型餐饮店也存在物料管理的需求,借此复习 ERP 系统中 BOM 这一抽象机制
技术选型
课程设计,选用团队最熟悉的技术
-
前端
-
Bootstrap:使用现成组件,减少样式相关代码量
-
jQuery: 引入 Ajax,用于实现与后端的接口交互
-
Vue:引入便利的数据绑定机制和标签逻辑控制机制,方便进行数据展示
-
-
后端
-
Spring:引入便利的依赖注入机制和强大的插件支持机制
-
Spring MVC:引入 RESTful 架构风格,便于实现简洁的接口形式
-
MyBatis:引入便利的数据库持久层框架,减少 JDBC 相关代码
-
MyBatis Plus:引入内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作
-
MySQL:个人最熟悉的关系型数据库,可以支撑小规模用户量软件系统的数据存取需求
-
-
部署
-
Docker:标准化应用发布,可以跨平台和主机使用;节约时间,方便快速部署和启动
-
需求分析
实地调查
调查校内大学生服务中心中的十多家餐饮店,发现店内职员基本上都在 十人以内 ,不同店内分工方式基本一致,可以抽象为:前台员工、后台员工、店主、采购人员
为什么建立一套面向小型店面的餐饮 SaaS 系统是可行的?
平台开发者视角
有着相近的需求,能采用通用的架构抽象是保障建立 SaaS 平台的可行性的关键
小型餐饮店面对于数字化的需求基本一致,可以抽象为以下五大模块
-
提供员工管理功能
-
员工信息管理:能够对员工信息进行录入、修改、查询
-
员工信息展示:以表格形式展示员工信息
-
员工权限管理:能够根据员工权限进行操作限制
-
-
提供库存管理功能
-
库存信息管理:能够对库存信息进行录入、修改、查询
-
库存信息展示:以表格形式展示库存信息
-
-
提供菜单管理功能
-
菜单信息管理:能够对菜单信息进行录入、修改、查询
-
菜单信息展示:以表格形式展示菜单信息
-
BOM 管理:能维护菜单的物料清单(产品结构表)
-
-
提供订单管理功能
-
订单信息管理:能够对订单信息进行录入、修改、查询
-
订单信息展示:以表格形式展示订单信息
-
-
提供流水展示功能:可视化展示近期销售情况,辅助库存管理
平台使用者视角
有数字化需求的小型店面买断并维护软件产品的成本高,而 SaaS 平台无需本地部署也无需维护,随租随用,按需付费,击中 用户期望数字化但是没有能力维护一套数字化系统 这一痛点。小型店面在引入一套 SaaS 平台之后,可以以较低的成本享受到数字化赋能带来的便利。降低用户引入软件系统的门槛,让更多人以更低的成本用上更优质的软件服务,是软件服务系统开发人员的一大职责。
为什么建立一套面向小型店面的餐饮 SaaS 系统是必要的?
软件形态变化趋势视角
服务化是实现软件数字资产有效复用的关键手段,是软件近几年也是未来几年都会流行的新形态
绿色节能视角(社会价值视角)
SaaS 平台可以实现统一管理,绿色高效,将所有店面的数据进行集中管理,避免了数据分散、重复存储等问题,同时还能够实现高效的数据调用和共享,提高了工作效率。
OOD
SaaS 平台视角
领域类图
用例图
用例描述
-
租户通过注册实现 SaaS 应用配置
-
用户通过登录使用 SaaS 应用
SaaS 应用视角
领域类图
用例图
用例描述
-
租户注册界面
-
租户录入注册信息
-
租户跳转至登录界面
-
-
用户登录界面
-
用户录入登录信息
-
用户跳转至注册界面
-
-
新增订单界面
-
店主或前台工作人员录入订单信息
-
-
订单看板界面
-
店主或后台工作人员修改订单、删除订单或查看订单
-
团队分工
按模块进行分工,本人负责 SaaS 基础环境的搭建和订单模块的实现
个人作为团队组长,除了负责上述开发职责以外,额外负责团队工作计划安排的职责
工作计划安排
小组工期
时间 | 任务完成情况 | 成果物 |
---|---|---|
20230530 开题 | 完成项目的需求分析和整体设计,并做好组内分工,以及团队开发环境的建立(GitHub 共享仓库创建、ECS 基础环境搭建) | 任务书 |
20230605 中期 | 完成项目的主要功能(单租户项目) | 本地项目 |
20230609 结题 | 完成项目的 SaaS 化(引入动态生成和绑定数据库表的机制),将项目打包成 Docker 镜像,并将完整的项目部署到阿里云 ECS 上 | 已部署项目 项目源码 |
个人工期
时间 | 任务完成情况 | 成果物 |
---|---|---|
20230530 开题 | 完成项目选题、模块设计、详细设计,组织组内分工,完成 GitHub 共享仓库的创建 | 任务书 |
20230605 中期 | 完成 ECS 环境搭建,完成订单管理模块 | 本地项目 |
20230609 结题 | 完成租户信息管理模块、数据表生成模块,完成项目的打包与部署 | 已部署项目 项目源码 |
系统设计
数据库设计
本人负责 SaaS 基础环境的搭建和订单模块的实现,相关的数据库表包括
-
tenant 表:租户信息表,存储租户信息
-
order 表:订单信息表,存储订单信息
-
order_dish_relation 表:订单菜品关系信息表,存储订单与菜品之间的关联信息
下面针对个人负责部分相关的数据库表进行完整性约束的说明
tenant 表
列名 | 说明 | 数据类型 | 主键 | 唯一性约束 | 非空约束 |
---|---|---|---|---|---|
shop_name | 店面名称 | varchar(255) | 无 | UNIQUE约束 | NOT NULL约束 |
tenant_name | 租户姓名 | varchar(255) | 无 | 无 | NOT NULL约束 |
registration_number | 营业执照注册号 | varchar(255) | PRIMARY KEY | 无 | NOT NULL约束 |
tel | 租户电话 | varchar(255) | 无 | UNIQUE约束 | 可空 |
tenant_pwd | 租户密码 | varchar(255) | 无 | 无 | NOT NULL约束 |
order 表
列名 | 说明 | 数据类型 | 主键 | 唯一性约束 | 非空约束 |
---|---|---|---|---|---|
id | 订单Id | bigint | PRIMARY KEY | 无 | NOT NULL约束 |
custom_name | 客户姓名 | varchar(20) | 无 | 无 | NOT NULL约束 |
custom_phone | 客户电话 | varchar(11) | 无 | 无 | NOT NULL约束 |
payment_mode | 付款模式 | varchar(20) | 无 | 无 | NOT NULL约束 |
cost | 总价 | decimal(10, 2) | 无 | 无 | NOT NULL约束 |
time | 下单时间 | varchar(50) | 无 | 无 | NOT NULL约束 |
state | 订单状态 | int | 无 | 无 | NOT NULL约束,DEFAULT约束(默认值为0) |
order_dish_relation 表
列名 | 说明 | 数据类型 | 主键 | 唯一性约束 | 非空约束 |
---|---|---|---|---|---|
id | 订单菜品关系Id | bigint | PRIMARY KEY | 无 | NOT NULL约束 |
dish_id | 订单Id | varchar(32) | 无 | 无 | NOT NULL约束 |
material_id | 原料Id | varchar(32) | 无 | 无 | NOT NULL约束 |
material_count | 原料数量 | decimal(10, 2) | 无 | 无 | NOT NULL约束 |
数据流图
数据字典
本人负责 SaaS 基础环境的搭建和订单模块的实现,相关的数据库表包括
-
tenant 表:租户信息表,存储租户信息
-
order 表:订单信息表,存储订单信息
-
order_dish_relation 表:订单菜品关系信息表,存储订单与菜品之间的关联信息
下面针对个人负责部分相关的数据库表进行数据字典的说明
tenant 表
字段名 | 数据类型 | 是否为 NULL | 主键 | 唯一约束 | 描述 |
---|---|---|---|---|---|
shop_name | varchar(255) | NOT NULL | - | UNIQUE | 餐饮店店名(唯一) |
tenant_name | varchar(255) | NOT NULL | - | - | 租户姓名 |
registration_number | varchar(255) | NOT NULL | ✓ | - | 营业执照注册号(主键) |
tel | varchar(255) | NULL | - | UNIQUE | 电话号码(唯一) |
tenant_pwd | varchar(255) | NOT NULL | - | - | 租户密码 |
order 表
字段名 | 数据类型 | 是否为 NULL | 主键 | 唯一约束 | 描述 |
---|---|---|---|---|---|
id | bigint | NOT NULL | ✓ | - | 订单编号(主键) |
custom_name | varchar(20) | NOT NULL | - | - | 客户姓名 |
custom_phone | varchar(11) | NOT NULL | - | - | 客户电话 |
payment_mode | varchar(20) | NOT NULL | - | - | 支付方式 |
cost | decimal(10, 2) | NOT NULL | - | - | 订单金额 |
time | varchar(50) | NOT NULL | - | - | 下单时间 |
state | int default 0 | NOT NULL | - | - | 订单状态(默认值为0) |
order_dish_relation 表
字段名 | 数据类型 | 是否为 NULL | 主键 | 唯一约束 | 描述 |
---|---|---|---|---|---|
id | bigint | NOT NULL | ✓ | - | 订单详情编号(主键) |
order_id | varchar(32) | NOT NULL | - | - | 订单编号 |
dish_id | varchar(32) | NOT NULL | - | - | 菜品编号 |
dish_count | int | NOT NULL | - | - | 菜品数量 |
数据库逻辑结构设计
本人负责 SaaS 基础环境的搭建和订单模块的实现,相关的数据库表包括
-
tenant 表:租户信息表,存储租户信息
-
order 表:订单信息表,存储订单信息
-
order_dish_relation 表:订单菜品关系信息表,存储订单与菜品之间的关联信息
下面针对个人负责部分相关的数据库表的数据库逻辑结构设计进行说明
tenant 表
-
实体:租户(Tenant)
-
属性:
-
租户ID(Registration_Number):主键,唯一标识一个租户
-
餐饮店店名(Shop_Name):唯一,一个餐饮店只有一个店名
-
租户姓名(Tenant_Name)
-
电话号码(Tel):唯一,一个电话号码只能对应一个租户
-
租户密码(Tenant_Pwd)
-
因此,租户实体与属性的关系为一对多关系,即一个租户对应一个餐饮店店名、一个租户姓名、一个电话号码和一个租户密码,而一个餐饮店只能对应一个租户。
order 表
-
实体:订单菜品关系(OrderDishRelation)
-
属性:
-
关系ID(ID):主键,唯一标识一个订单菜品关系
-
订单ID(Order_ID):对应订单表中的订单ID
-
菜品ID(Dish_ID):对应菜品表中的菜品ID
-
菜品数量(Dish_Count)
-
因此,订单菜品关系实体与属性的关系为多对一关系,即一个订单菜品关系对应一个订单ID、一个菜品ID和一个菜品数量,而一个订单可以对应多个订单菜品关系。
order_dish_relation 表
-
实体:订单(Order)
-
属性:
-
订单ID(ID):主键,唯一标识一个订单
-
客户姓名(Custom_Name)
-
客户电话(Custom_Phone)
-
支付方式(Payment_Mode)
-
订单金额(Cost)
-
下单时间(Time)
-
订单状态(State):默认为0,表示未处理
-
因此,订单实体与属性的关系为一对多关系,即一个订单对应一个客户姓名、一个客户电话、一个支付方式、一个订单金额、一个下单时间和一个订单状态,而一个客户可以对应多个订单。
完整性约束设计与实现
本人负责 SaaS 基础环境的搭建和订单模块的实现,相关的数据库表包括
-
tenant 表:租户信息表,存储租户信息
-
order 表:订单信息表,存储订单信息
-
order_dish_relation 表:订单菜品关系信息表,存储订单与菜品之间的关联信息
下面针对个人负责部分相关的数据库表的完整性约束的设计与实现进行说明
设计
-
租户表(Tenant):
-
注册号(Registration_Number):作为主键,不能为空值,不能重复
-
餐饮店店名(Shop_Name):不能为空值,不能重复
-
租户姓名(Tenant_Name):不能为空值
-
电话号码(Tel):可以为空值,但若填写则不能重复
-
租户密码(Tenant_Pwd):不能为空值
-
-
订单菜品关系表(OrderDishRelation):
-
关系ID(ID):作为主键,不能为空值
-
订单ID(Order_ID):不能为空值,且必须是订单表中已有的订单ID
-
菜品ID(Dish_ID):不能为空值,且必须是菜品表中已有的菜品ID
-
菜品数量(Dish_Count):不能为空值,且必须大于0
-
-
订单表(Order):
-
订单ID(ID):作为主键,不能为空值
-
客户姓名(Custom_Name):不能为空值
-
客户电话(Custom_Phone):不能为空值
-
支付方式(Payment_Mode):不能为空值
-
订单金额(Cost):不能为空值,且必须大于0
-
下单时间(Time):不能为空值
-
订单状态(State):不能为空值,且只能为0(未处理)或1(已完成)
-
实现
实际实现时,可以通过在建表时添加约束条件的方式来实现上述完整性约束。
-
租户表(Tenant):
create table tenant
(
shop_name varchar(255) not null comment '餐饮店店名(唯一)',
tenant_name varchar(255) not null comment '租户姓名',
registration_number varchar(255) not null comment '营业执照注册号(主键)'
primary key,
tel varchar(255) null comment '电话号码(唯一)',
tenant_pwd varchar(255) not null comment '租户密码',
constraint unique_tel
unique (tel)
);
-
订单菜品关系表(OrderDishRelation):
create table order_dish_relation
(
id bigint not null
primary key,
order_id varchar(32) not null,
dish_id varchar(32) not null,
dish_count int not null,
constraint fk_order
foreign key (order_id) references orders(id),
constraint fk_dish
foreign key (dish_id) references dish(id)
);
-
订单表(Order):
create table orders
(
id bigint not null
primary key,
custom_name varchar(20) not null,
custom_phone varchar(11) not null,
payment_mode varchar(20) not null,
cost decimal(10, 2) not null,
time varchar(50) not null,
state int default 0 not null check (state in (0, 1))
);
模块设计
租户管理模块
租户管理模块的主要功能是
-
实现租户信息的录入
-
利用租户信息生成一组数据库表 表名前缀如下,后缀为租户信息中的企业营业执照注册号
-
dish
-
dish_material_relation
-
material
-
material_buys
-
order_dish_relation
-
orders
-
user
-
-
将租户信息存入新生成的 user 表中
订单管理模块
-
订单信息录入
-
订单信息更改:将订单状态从未完成修改为已完成
-
订单删除
功能模块图
类图
边界类 Controller
控制类 Service
实体类 Entity
租户管理模块相关类图
订单管理模块相关类图
系统体系结构设计
SaaS 系统通用双层架构
SaaS 应用软件体系结构
系统核心模块实现
类别 | 选项 |
---|---|
编程语言 | Java(后端业务实现) JavaScript(前端逻辑实现) |
开发环境 | IDEA(后端代码编写) Visual Studio Code(前端代码编写) |
支撑软件 | Navicat(数据库图形化界面) Git(团队代码管理) Postman(后端接口测试) Docker(提供一套容器化的打包和部署方案) |
核心模块功能描述
租户表生成功能描述
租户注册后,自动为租户生成一套数据库表,以实现 Schema 级别的隔离
订单联动库存更新功能描述
修改订单状态为已完成后,自动更新库存信息,以实现实时可行订单的生成
核心模块工作流程
租户表生成流程
-
判断租户是否存在
-
若租户不存在,继续执行 3,若租户存在,则抛出 BusinessException ,向前端返回错误信息
-
在租户表中插入租户信息
-
利用租户信息,生成一套租户独占的表格 表名前缀如下,后缀为租户信息中的企业营业执照注册号
-
dish
-
dish_material_relation
-
material
-
material_buys
-
order_dish_relation
-
orders
-
user
-
-
在生成的 user 表中存入租户信息(租户本身也是其应用的用户之一)
-
向前端返回租户信息,表示租户注册成功,租户独占表格生成成功
订单联动库存更新流程
-
首先,开始函数,开始处理散客点单全链路服务;
-
接着,根据订单的 ID 直接更新订单状态;
-
然后,获取对应订单 ID 下的菜品和订单关系列表,即 OrderDishRelation 列表;
-
然后,根据每个 OrderDishRelation 中的 dishId 去 DishMaterialRelation 表中查询该菜品所需的原料信息列表,即 DishMaterialRelation 列表;
-
接下来,对于每一个 DishMaterialRelation 条目,从 Material 表中根据其 materialId 获取原有的 count 数量,并将该值记录为oldCount;
-
然后,使用 DishMaterialRelation 和 dish_count 两个参数去修改 Material 的 count 属性,得到新的 count 值,并将该值记录为newCount;
-
最后,使用 updateCountByIdByMyBatis 函数,将新的 count 值保存到 Material 表中,以完成对修改后的材料库存数量的更新。循环执行步骤 4 至步骤 7,直到处理完所有的 DishMaterialRelation 条目。
-
当所有订单处理完毕后,程序结束,整个更新订单的过程也就结束了。
核心模块代码详解
租户表生成代码详解
函数名称:register
输入参数:
-
Tenant tenant:一个Tenant对象,表示待注册的租户信息。
输出结果:
-
Tenant:注册成功后返回注册好的租户对象。
核心算法:
-
判断输入的租户对象是否为空,如果是则抛出空对象异常。
-
向数据库中插入新的租户,如果插入失败则抛出参数错误异常。
-
查询数据库中是否已经存在相同名称的租户,如果存在则抛出参数错误异常,并返回已经存在的租户对象。
-
根据新注册的租户编号,生成对应的数据库表。
-
向新生成的租户表中插入管理员用户信息。
-
返回新注册的租户对象。
关键函数定义代码及注解:
订单联动库存更新代码详解
函数名称:updateOrdersByMyBatis
输入参数:
-
registrationNumber: String类型,表示订单所在的编号
-
orders: List<Order>类型,表示需要更新的订单列表
输出结果:无
函数功能:此函数用于更新指定编号下的订单信息,并修改订单状态为FINISHED。在更新订单状态之后,还需要根据订单关联的菜品和食材信息,更新相应的库存数量。
核心算法:
-
遍历订单列表orders中每一个订单order。
-
根据订单id更新订单状态为FINISHED。
-
根据订单关联的菜品和食材信息,更新相应的库存数量。
-
获取order关联的菜品和订单的关系orderDishRelations,遍历每一个orderDishRelation。
-
获取orderDishRelation关联的菜品和食材关系dishMaterialRelations,遍历每一个dishMaterialRelation。
-
获取dishMaterialRelation关联的食材material,计算新的库存数量newCount,更新material的库存。
-
关键函数定义代码及注解:
//更新订单,用于修改状态 UNFINISHED → FINISHED
//加入事务,保证一组数据库均完成后才完成,否则回滚
主要功能界面截图及对应文字概述
租户注册相关界面
租户注册相关界面包括:租户注册页面
租户注册页面
注册前数据库表
注册后数据库表
对比可以发现,增加了以注册时填写的营业执照注册号为后缀的新表
订单联动库存更新相关界面
订单联动库存更新相关界面包括
-
订单看板界面
-
新建订单界面
新建订单界面(订单时)
订单页面输入客户信息和订单内容,输入完成后点击生成订单
订单看板界面(订单状态修改前)
点击生成订单后,页面会刷新,此时点击左侧菜单栏中的“订单 → 订单看板”,跳转至订单看板,可以看到新建的未完成订单
订单看板界面(订单状态修改后)
点击修改,页面刷新,所有订单均变成已完成状态
新建订单界面(订单状态修改后)
点击左侧菜单栏中的“订单 → 新建订单”,跳转回新建订单页面
可以注意到,珍珠超浓绿茶剩余量由 108 份变为 106 份
运行测试与分析
(要有多组实际测试数据,和测试用例并给出相应运行结果截图。具体: (1)完整性约束测试过程设计,结果验证;(2)能给出软件操作的界面截图来。(3)软件开发调试过程中遇到的问题及解决过程;符合实际情况的数据测试及功能的改进设想等)
本人负责 SaaS 基础环境的搭建(即租户管理模块)和订单模块的实现,故针对这两个模块进行测试与分析
完整性约束测试
主要测试已识别的异常情况
过程设计
按照以下顺序进行
-
注册页面
-
提交空表单
-
输入错误格式的营业执照注册号
-
输入错误格式的电话号码
-
输入与租户密码不一致的确认密码
-
输入已存在的租户信息
-
-
登录页面
-
提交空表单
-
提交不存在的店铺名称
-
提交不匹配的账号密码
-
-
新建订单页面
-
提交空表单
-
提交无效订单
-
点单数大于可行订单量
-
点单数为0
-
-
输入错误格式的电话号码
-
-
订单看板页面
-
执行超卖订单
-
结果验证
按照上述设计的测试过程执行测试,展示过程截图,总结成测试用例表
注册页面 提交空表单
通过弹窗提示错误信息:存在未填项
注册页面 输入错误格式的营业执照注册号
输入时,通过文字提示错误信息:注册号必须为 15 位数字
提交后,通过弹窗提示错误信息:营业执照注册号格式错误
注册页面 输入错误格式的电话号码
输入时,通过文字提示错误信息:请输入正确的手机号格式
提交后,通过弹窗提示错误信息:电话号码格式错误
注册页面 输入与租户密码不一致的确认密码
租户密码输入 123456,确认密码输入 1234567
提交后,通过弹窗提示错误信息:两次输入的密码不一致,请重新输入
注册页面 输入已存在的租户信息
提交后,通过弹窗提示错误信息:请求参数错误,租户已存在:<租户店名> <租户营业执照注册号>
登录页面 提交空表单
通过弹窗提示错误信息:请求数据为空
登录页面 提交不存在的店铺名称
通过弹窗提示错误信息:请求参数错误,店铺不存在
登录页面 提交不匹配的账号密码
通过弹窗提示错误信息:请求参数错误,账号密码不匹配
新建订单页面 提交空表单
不填写点单日期、客户名称、客户电话、支付方式,只填写订单信息
通过弹窗提示错误信息:存在未填项,订单无效
新建订单页面 提交无效订单 点单数大于可行订单量
剩余 30 份珍珠超浓绿茶,但是点了 31 份
通过弹窗提示错误信息:存在超额订单,订单无效
新建订单页面 提交无效订单 点单数为0
填写点单日期、客户名称、客户电话、支付方式,不填写订单信息
通过弹窗提示错误信息:金额为 0,订单无效
订单看板页面 执行超卖订单
业务逻辑:只有在订单变为已完成状态时,库存信息会进行过更新,所以存在超卖的可能
剩余 30 份珍珠超浓绿茶,每次都点 30 份(单次点单恰好不超额),连点两次单(订单量之和超额)
订单看板页面显示两次订单
先修改的订单成功进行,后修改的订单无法进行,弹窗提示错误信息:超过可行订单数
点击确认后,后修改的订单的订单状态仍为未完成状态
回到新增订单页面,可以发现可行订单中不再显示珍珠超浓绿茶的菜品信息
测试用例表
测试页面 | 异常输入 | 预期输出 | 结果 | 结论 |
---|---|---|---|---|
注册页面 | 提交空表单 | 通过弹窗提示错误信息:存在未填项 | 预期输出与实际输出一致 | 测试通过 |
注册页面 | 输入错误格式的营业执照注册号:a | 输入时,通过文字提示错误信息:注册号必须为 15 位数字 提交后,通过弹窗提示错误信息:营业执照注册号格式错误 | 预期输出与实际输出一致 | 测试通过 |
注册页面 | 输入错误格式的电话号码:1 | 输入时,通过文字提示错误信息:请输入正确的手机号格式 提交后,通过弹窗提示错误信息:电话号码格式错误 | 预期输出与实际输出一致 | 测试通过 |
注册页面 | 输入与租户密码不一致的确认密码: 租户密码:123456 确认密码:1234567 | 提交后,通过弹窗提示错误信息:两次输入的密码不一致,请重新输入 | 预期输出与实际输出一致 | 测试通过 |
注册页面 | 输入已存在的租户信息: 店铺名称:工大奶茶店 营业执照注册号:123456789012303 | 提交后,通过弹窗提示错误信息:请求参数错误,租户已存在:<租户店名> <租户营业执照注册号> | 预期输出与实际输出一致 | 测试通过 |
登录页面 | 提交空表单 | 通过弹窗提示错误信息:请求数据为空 | 预期输出与实际输出一致 | 测试通过 |
登录页面 | 提交不存在的店铺名称:山大奶茶店 | 通过弹窗提示错误信息:请求参数错误,店铺不存在 | 预期输出与实际输出一致 | 测试通过 |
登录页面 | 提交不匹配的账号密码: 正确的工号密码:0 123456 输入的工号密码:0 1234567 | 通过弹窗提示错误信息:请求参数错误,账号密码不匹配 | 预期输出与实际输出一致 | 测试通过 |
新建订单页面 | 提交空表单 | 通过弹窗提示错误信息:存在未填项,订单无效 | 预期输出与实际输出一致 | 测试通过 |
新建订单页面 | 提交无效订单:点单数大于可行订单量 | 通过弹窗提示错误信息:存在超额订单,订单无效 | 预期输出与实际输出一致 | 测试通过 |
新建订单页面 | 提交无效订单:点单数为0 | 通过弹窗提示错误信息:金额为 0,订单无效 | 预期输出与实际输出一致 | 测试通过 |
订单看板页面 | 执行超卖订单 | 弹窗提示错误信息:超过可行订单数 点击确认后,后修改的订单的订单状态仍为未完成状态 回到新增订单页面,可以发现可行订单中不再显示珍珠超浓绿茶的菜品信息 | 预期输出与实际输出一致 | 测试通过 |
正常流程展示
过程设计
-
注册新账号
-
数据库展示
-
登录新账号(店主)
-
展示全空页面
-
退出新账号
-
登录旧账号(店主)
-
订单管理功能演示
-
订单看板展示
-
新增订单
-
订单修改
-
新增订单
-
订单删除
-
-
退出旧账号(店主)
-
登录旧账号(前台员工)
-
退出旧账号(前台员工)
-
登录旧账号(后台员工)
-
退出旧账号(后台员工)
-
登录旧账号(采购人员)
-
退出旧账号(采购人员)
结果展示
注册新账号
数据库展示
注册前
注册后
登录新账号(店主)
展示全空页面
退出新账号
登录旧账号(店主)
订单看板展示
订单删除
新增订单
订单修改
修改前
修改后
退出旧账号(店主)
切换旧账号(前台员工)
前台员工权限限制:只能使用订单模块
切换旧账号(后台员工)
后台员工权限限制:只能使用订单模块
切换旧账号(采购人员)
采购人员权限限制:只能使用库存模块
功能的改进设想
用户权限管理机制弱
问题描述
权限管理功能薄弱
-
角色和权限一对一,不可配置
-
用户和角色一对一,不可配置
改进设想
权限原子化,可以自定义角色,各个角色可以拥有数量可选的权限(角色权限一对多)
引入用户和角色的绑定机制,每个用户可以通过设置为多种角色,间接获取操作权限(用户角色一对多)
不带负载均衡的单体系统
问题描述
虽然做了 Schema 级别的数据隔离,但是系统本身仍是单体系统,不是集群,也没做负载均衡
改进设想
集群化,同时引入数据同步机制和负载均衡机制,将单体系统改为集群
项目源码
本项目为课程设计作业且为团队项目,设置为私有仓库,不作公开