目录

一、图书销售管理系统——需求分析初步实现

1.系统概述

2.需求概述 

3. 功能模块分析

3.1 图书管理模块

3.2 用户管理模块

3.3 系统管理模块

3.4 销售系统模块

4.功能流程图

5.原型图的实现

二、系统设计  

1.系统功能设计

 2.数据库设计

2.1 数据库逻辑结构设计

2.2 数据库物理结构设计

2.3 数据库概念结构设计

2.4 创建数据库


一、需求分析

1.系统概述

该系统是一个综合性的图书管理平台,包含图书管理、用户管理、系统管理和销售系统四大功能模块,主要服务于图书零售商或图书馆的日常运营管理。

2.需求概述 

本图书管理系统旨在为书店或图书馆提供一套完整的管理解决方案,涵盖图书管理、用户管理、系统管理和销售管理等核心功能。系统能够实现图书信息的数字化管理,包括新书入库、信息修改、多条件查询、库存调整以及统一折扣设置等功能,确保图书数据准确性和实时性。在用户管理方面,系统支持会员信息的添加、查询、修改和账户充值,同时提供积分管理功能,增强会员服务体验。系统管理模块则负责管理员账户的创建和密码维护,保障系统安全运行。销售模块记录每笔交易详情,自动更新会员积分,并提供历史销售查询功能,帮助管理者掌握经营状况。通过一体化的设计,该系统将显著提升图书管理效率,优化会员服务流程,简化销售操作,并为经营决策提供数据支持,最终实现降低运营成本、提高服务质量的目标。

3. 功能模块分析

3.1 图书管理模块

  • 图书入库:添加新书信息,包括编号、书名、作者、出版社、零售价等基本信息

  • 图书修改:修改已入库图书的各项信息

  • 图书查询:根据条件检索图书信息

  • 图书删除:从系统中移除图书记录

  • 库存修改:调整图书库存数量

  • 图书折扣:设置普通折扣率(适用于所有图书的统一定价策略)

3.2 用户管理模块

  • 会员查询:查看会员信息,包括编号、姓名、积分等

  • 个人信息修改:更新会员的个人资料

  • 会员添加:注册新会员

  • 会员充值:为会员账户充值,并自动对应到会员账户

  • 会员删除:注销会员账户

3.3 系统管理模块

  • 新增管理员:创建新的系统管理员账户

  • 管理员改密码:修改管理员登录密码

3.4 销售系统模块

  • 卖出登记:记录图书销售情况

  • 会员积分修改:根据销售代码自动调整会员积分

  • 查询购买记录:查看历史销售记录

4.功能流程图

总流程图:

流程首先从“开始”进入,随后用户需要进行“登录验证”,输入用户名和密码等凭证。系统会判断登录是否成功,如果成功(“是”),则进入下一步;如果失败,会要求重新登录或终止流程。登录成功后,系统会“显示主菜单”,用户可以在主界面选择不同的服务模块,包括“图书管理”“用户管理”“系统管理”“销售系统”或“退出系统”。其中,图书管理涉及图书的增删改查等,用户管理用于维护用户信息等,系统管理包含系统配置等功能,而销售系统处理订单或交易相关操作。如果用户选择“退出系统”,流程将直接结束。 

图书管理:

该流程图描述了从进入图书管理模块到完成各项操作的全过程。

流程从用户进入图书管理模块开始,系统会提供多个操作选项供用户选择操作,包括图书入库、图书修改、库存修改、图书删除、设置折扣和图书查询。

图书入库:用户选择图书入库,则需要输入图书信息(如书名、作者、ISBN等),系统会将数据保存到数据库,并显示结果,最后返回上级菜单。

图书修改:选择图书修改,用户需先查询目标图书(通过输入查询条件),系统会显示结果,用户可选择图书并修改字段(如书名、价格等),修改完成后系统会更新数据库,并返回上级菜单。

库存修改:用户选择图书并输入新库存数量,系统验证数据后更新数据库,并返回上级菜单。

图书删除:用户选择删除目标(通常通过查询功能找到待删除的图书),系统会要求确认删除,确认后数据将从数据库移除,并返回上级菜单。

设置折扣操作:用户选择图书并输入折扣率,系统验证数据后更新数据库,并返回上级菜单。

图书查询:允许用户输入查询条件(如书名、作者等),系统会显示结果,用户可浏览查询到的图书信息。

用户管理:

当用户进入用户管理模块后,系统会提供多个操作选项,包括会员充值、添加会员、删除会员和会员查询。

会员充值:用户输入会员ID,然后输入金额。系统会更新余额和积分,并将数据保存到数据库,最后返回上级菜单。

会员操作:用户填写会员信息(如姓名、联系方式等),系统生成会员ID并将数据保存到数据库,完成操作后返回上级菜单。

删除会员时:用户先验证身份,然后选择会员并确认删除。系统会更新数据库,删除对应的会员信息,最后返回上级菜单。

会员查询:用户输入查询条件(如会员ID或姓名),系统会显示会员列表供用户查看,之后返回上级菜单。

销售管理:

当工作人员进入销售系统后,系统会提供选择操作界面,包含卖出登记、积分调整和查询记录三个主要功能模块。

卖出登记:

  1. 扫描图书ID或手动输入图书编号

  2. 系统自动计算金额(可能包含会员折扣计算)

  3. 工作人员可选择输入会员ID为会员消费(非会员可跳过此步)

  4. 系统会扣减库存并更新会员积分(如涉及会员消费)

  5. 最后返回上级菜单

积分调整:

  1. 工作人员输入会员ID确认会员身份

  2. 输入新积分数值(可能是增加或扣除积分)

  3. 系统更新数据库中的会员积分信息

  4. 操作完成后返回上级菜单

查询记录:

  1. 工作人员输入查询条件(如日期范围、会员ID等)

  2. 系统显示销售记录明细

  3. 查询结束后返回上级菜单

系统管理:

当管理员用户进入系统管理模块后,系统会显示选择操作界面,提供修改密码和新增管理员两个主要功能选项。

修改密码:

  1. 输入旧密码进行身份验证

  2. 验证通过后输入新密码

  3. 系统更新数据库中的密码信息

  4. 操作完成后返回上级菜单

新增管理员:

  1. 输入管理员信息(包括用户名、联系方式等基本信息)

  2. 为新建账号分配权限(设置相应的系统操作权限)

  3. 系统将新管理员信息保存到数据库

  4. 操作完成后返回上级菜单

5.原型图的实现

登录界面:

主功能界面:

详细功能界面 :

二、系统设计  

1.系统功能设计

这些表共同构成了一个完整的图书销售管理系统,覆盖了从图书管理、会员管理、销售记录到财务和日志追踪的全流程功能。

(1) 管理员 (Administrators)

核心功能

  • 系统账户管理:存储管理员的登录凭证(用户名、密码)

  • 身份验证:用于系统登录和权限验证

  • 操作追踪:记录管理员创建时间,便于审计

  • 联系信息:保存管理员联系电话

关联功能

  • 与销售记录关联(处理销售操作)

  • 与库存变动关联(执行库存操作)

  • 与系统日志关联(记录管理员操作)

(2) 会员 (Members)

核心功能

  • 会员信息管理:存储会员基本信息(姓名、性别、出生日期)

  • 联系方式管理:记录会员联系电话

  • 积分系统:跟踪会员累计积分

  • 会员识别:提供唯一会员ID

关联功能

  • 与销售记录关联(识别购买会员)

  • 支持个性化服务(基于性别、年龄等属性)

(3) 出版社 (Publishers)

核心功能

  • 出版社信息管理:记录出版社名称、联系方式和地址

  • 唯一标识:为每家公司提供唯一ID

  • 图书关联:作为图书的出版方

关联功能

  • 与图书表关联(标识图书的出版社)

(4)图书 (Books)

核心功能

  • 图书信息管理:存储图书基本信息(ISBN、标题、作者)

  • 价格管理:记录零售价、进货价和折扣率

  • 库存管理:跟踪库存数量

  • 采购信息:记录入库时间和采购价格

关联功能

  • 与出版社关联(标识出版来源)

  • 与促销活动关联(特定图书的促销)

  • 与销售记录关联(销售的具体图书)

  • 与库存变动关联(库存变化对应的图书)

(5) 促销活动 (Promotions)

核心功能

  • 促销管理:创建和管理图书促销活动

  • 时间控制:设置促销的开始和结束时间

  • 折扣管理:定义促销折扣率

  • 活动命名:为促销活动提供描述性名称

关联功能

  • 与图书关联(指定促销的图书)

  • 与销售记录关联(应用促销折扣)

(6) 库存变动记录 (Inventory Changes)

核心功能

  • 库存追踪:记录所有库存变动(入库/出库)

  • 操作审计:记录变动时间、操作员和变动数量

  • 关联标识:与相关销售记录关联(出库时)

关联功能

  • 与图书关联(标识变动的图书)

  • 与管理员关联(记录操作人员)

  • 与销售记录关联(出库原因)

(7) 销售记录 (Sales)

核心功能

  • 交易记录:存储每笔销售的详细信息

  • 价格计算:记录单价、数量、折扣率和总金额

  • 关联信息:记录参与销售的管理员和会员

  • 促销应用:记录使用的促销活动

关联功能

  • 与会员关联(识别购买者)

  • 与管理员关联(识别操作员)

  • 与图书关联(识别销售商品)

  • 与促销活动关联(应用折扣)

(8)系统日志 (System Logs)

核心功能

  • 操作审计:记录所有关键系统操作

  • 时间戳记:准确记录操作时间

  • 责任追踪:关联到执行操作的管理员

  • 操作分类:标识操作类型

关联功能

  • 与管理员关联(识别操作人员)

 2.数据库设计

 2.1 数据库概念结构设计

2.2 数据库逻辑结构设计

(1) 管理员 (Administrators)
Administrators(admin_id, username, password, phone, created_at)
  • 主键: admin_id

  • 属性说明:

    • admin_id: INT, 管理员唯一标识,自增长

    • username: VARCHAR(50), 登录用户名,不可重复

    • password: VARCHAR(255), 加密后的密码

    • phone: VARCHAR(20), 联系电话

    • created_at: TIMESTAMP, 账户创建时间,默认当前时间

  • 约束:

    • username 唯一

    • password 非空

(2)会员 (Members)
Members(member_id, full_name, gender, birth_date, phone, total_points, balance, registration_date)
  • 主键: member_id

  • 属性说明:

    • member_id: INT, 会员唯一标识,自增长

    • full_name: VARCHAR(50), 会员全名

    • gender: ENUM('男','女'), 性别

    • birth_date: DATE, 出生日期

    • phone: VARCHAR(20), 联系电话,不可重复

    • total_points: INT, 累计积分,默认0

    • balance: DECIMAL(10,2), 账户余额,默认0

    • registration_date: TIMESTAMP, 注册时间,默认当前时间

  • 约束:

    • phone 唯一

    • total_points ≥ 0

    • balance ≥ 0

(3)出版社 (Publishers)
Publishers(publisher_id, publisher_name, contact_phone, address, established_date)
  • 主键: publisher_id

  • 属性说明:

    • publisher_id: INT, 出版社唯一标识,自增长

    • publisher_name: VARCHAR(100), 出版社名称,不可重复

    • contact_phone: VARCHAR(20), 联系电话

    • address: VARCHAR(255), 详细地址

    • established_date: DATE, 成立日期

  • 约束:

    • publisher_name 唯一

(4)图书 (Books)
Books(isbn, title, author, publisher_id, category, retail_price, cost_price, stock_quantity, publish_date, shelf_location)
  • 主键: isbn

  • 属性说明:

    • isbn: VARCHAR(20), 国际标准书号

    • title: VARCHAR(255), 书名

    • author: VARCHAR(100), 作者

    • publisher_id: INT, 出版社ID

    • category: VARCHAR(50), 图书分类

    • retail_price: DECIMAL(10,2), 零售价

    • cost_price: DECIMAL(10,2), 成本价

    • stock_quantity: INT, 库存数量

    • publish_date: DATE, 出版日期

    • shelf_location: VARCHAR(50), 书架位置

  • 约束:

    • retail_price > 0

    • cost_price > 0

    • stock_quantity ≥ 0

    • 外键 publisher_id 关联 Publishers(publisher_id)

(5) 促销活动 (Promotions)
Promotions(promotion_id, promotion_name, book_isbn, start_time, end_time, discount_rate, description)
  • 主键: promotion_id

  • 属性说明:

    • promotion_id: INT, 活动唯一标识,自增长

    • promotion_name: VARCHAR(100), 活动名称

    • book_isbn: VARCHAR(20), 适用图书ISBN

    • start_time: DATETIME, 开始时间

    • end_time: DATETIME, 结束时间

    • discount_rate: DECIMAL(5,2), 折扣率(0.1-1.0)

    • description: TEXT, 活动描述

  • 约束:

    • start_time < end_time

    • 0.1 ≤ discount_rate ≤ 1.0

    • 外键 book_isbn 关联 Books(isbn)

(6) 销售记录 (Sales)
Sales(sale_id, sale_time, member_id, admin_id, total_amount, payment_method, discount_applied, points_earned)
  • 主键: sale_id

  • 属性说明:

    • sale_id: INT, 销售唯一标识,自增长

    • sale_time: DATETIME, 销售时间

    • member_id: INT, 会员ID(可为空)

    • admin_id: INT, 操作员ID

    • total_amount: DECIMAL(10,2), 总金额

    • payment_method: ENUM('现金','银行卡','移动支付'), 支付方式

    • discount_applied: DECIMAL(5,2), 应用折扣率

    • points_earned: INT, 获得积分

  • 约束:

    • total_amount > 0

    • points_earned ≥ 0

    • 外键 member_id 关联 Members(member_id)

    • 外键 admin_id 关联 Administrators(admin_id)

(7)销售明细 (Sale_Details)
Sale_Details(detail_id, sale_id, book_isbn, quantity, unit_price, subtotal)
  • 主键: detail_id

  • 属性说明:

    • detail_id: INT, 明细唯一标识,自增长

    • sale_id: INT, 销售ID

    • book_isbn: VARCHAR(20), 图书ISBN

    • quantity: INT, 数量

    • unit_price: DECIMAL(10,2), 单价

    • subtotal: DECIMAL(10,2), 小计金额

  • 约束:

    • quantity > 0

    • unit_price > 0

    • subtotal = quantity * unit_price

    • 外键 sale_id 关联 Sales(sale_id)

    • 外键 book_isbn 关联 Books(isbn)

(8) 库存变动 (Inventory_Changes)
Inventory_Changes(change_id, book_isbn, change_type, quantity, admin_id, change_time, related_sale_id, notes)
  • 主键: change_id

  • 属性说明:

    • change_id: INT, 变动记录唯一标识,自增长

    • book_isbn: VARCHAR(20), 图书ISBN

    • change_type: ENUM('采购入库','销售出库','库存调整','退货入库'), 变动类型

    • quantity: INT, 变动数量(正数表示入库,负数表示出库)

    • admin_id: INT, 操作员ID

    • change_time: TIMESTAMP, 变动时间

    • related_sale_id: INT, 关联销售ID(可为空)

    • notes: TEXT, 备注

  • 约束:

    • quantity ≠ 0

    • 外键 book_isbn 关联 Books(isbn)

    • 外键 admin_id 关联 Administrators(admin_id)

    • 外键 related_sale_id 关联 Sales(sale_id)

(9) 系统日志 (System_Logs)
System_Logs(log_id, admin_id, action_type, action_details, ip_address, action_time)
  • 主键: log_id

  • 属性说明:

    • log_id: INT, 日志唯一标识,自增长

    • admin_id: INT, 操作员ID(可为空)

    • action_type: VARCHAR(50), 操作类型

    • action_details: TEXT, 操作详情

    • ip_address: VARCHAR(50), 操作IP地址

    • action_time: TIMESTAMP, 操作时间

  • 约束:

    • 外键 admin_id 关联 Administrators(admin_id)

2.3 数据库物理结构设计

图书类数据项 (C1)

数据项ID 数据项名称 数据类 数据类型 说明
I1 ISBN C1 VARCHAR(20) 图书的国际标准书号,唯一标识一本书
I2 标题 C1 VARCHAR(255) 图书的名称
I3 作者 C1 VARCHAR(100) 图书的作者姓名
I4 出版社ID C1 INT 出版该书的出版社的唯一标识符
I5 零售价 C1 DECIMAL(10,2) 图书的零售价格
I6 折扣率 C1 DECIMAL(5,2) 图书当前的折扣率(0.1-1.0
I7 库存数量 C1 INT 当前库存的图书数量
I8 进货价 C1 DECIMAL(10,2) 图书的采购价格
I9 入库时间 C1 DATE 图书的入库日期

管理员类数据项 (C2)

管理员的唯一标识符
I11 用户名 C2 VARCHAR(50) 管理员的登录用户名
I12 密码 C2 VARCHAR(255) 管理员的加密密码
I13 电话 C2 VARCHAR(20) 管理员的联系电话
I14 创建时间 C2 TIMESTAMP 管理员账户的创建时间

会员类数据项 (C3)

数据项ID 数据项名称 数据类 数据类型 说明
I15 会员ID C3 INT 会员的唯一标识符
I16 姓名 C3 VARCHAR(20) 会员的姓名
I17 性别 C3 ENUM('男','女') 会员的性别
I18 出生日期 C3 DATE 会员的出生日期
I19 电话 C3 VARCHAR(20) 会员的联系电话
I20 积分 C3 INT 会员当前拥有的积分数量

出版社类数据项 (C4)

数据项ID 数据项名称 数据类 数据类型 说明
I21 出版社ID C4 INT 出版社的唯一标识符
I22 名字 C4 VARCHAR(100) 出版社的名称
I23 电话 C4 VARCHAR(20) 出版社的联系电话
I24 地址 C4 VARCHAR(255) 出版社的地址

销售类数据项 (C5)

数据项ID 数据项名称 数据类 数据类型 说明
I25 销售ID C5 INT 销售交易的唯一标识符
I26 销售日期 C5 DATETIME 销售发生的日期和时间
I27 会员ID C5 INT 参与销售的会员ID
I28 管理员ID C5 INT 处理销售的管理员ID
I29 总金额 C5 DECIMAL(10,2) 销售交易的总金额
I30 ISBN C5 VARCHAR(20) 销售图书的国际标准书号
I31 数量 C5 INT 销售的图书数量
I32 单价 C5 DECIMAL(10,2) 图书的销售单价
I33 折扣率 C5 DECIMAL(5,2) 销售时应用的折扣率

促销活动类数据项 (C6)

数据项ID 数据项名称 数据类 数据类型 说明
I34 活动ID C6 INT 促销活动的唯一标识符
I35 活动名称 C6 VARCHAR(100) 促销活动的名称
I36 开始时间 C6 DATETIME 促销活动的开始时间
I37 结束时间 C6 DATETIME 促销活动的结束时间
I38 折扣率 C6 DECIMAL(5,2) 促销活动的折扣率(0.1-1.0)
I39 ISBN C6 VARCHAR(20) 适用图书的国际标准书号

库存变动类数据项 (C7)

数据项ID 数据项名称 数据类 数据类型 说明
I40 记录ID C7 INT 库存变动的唯一标识符
I41 变动时间 C7 TIMESTAMP 库存变动的时间
I42 ISBN C7 VARCHAR(20) 变动图书的国际标准书号
I43 变动类型 C7 ENUM('采购入库','销售出库') 库存变动的类型
I44 变动数量 C7 INT 库存变动的数量
I45 管理员ID C7 INT 进行库存变动的操作员ID

系统日志类数据项 (C8)

数据项ID 数据项名称 数据类 数据类型 说明
I46 日志ID C8 INT 系统日志的唯一标识符
I47 管理员ID C8 INT 执行操作的管理员ID
I48 操作类型 C8 VARCHAR(50) 系统操作类型
I49 操作时间 C8 TIMESTAMP 操作发生的时间

管理员表 (administrators)

字段名 数据类型 是否为空 默认值 主键 外键 说明
admin_id INT 自动递增 管理员ID
username VARCHAR(50) 用户名(唯一)
password VARCHAR(255) 密码
phone VARCHAR(20) NULL 电话
created_at TIMESTAMP CURRENT_TIMESTAMP 创建时间

 会员表 (members)

字段名 数据类型 是否为空 默认值 主键 外键 说明
member_id INT 自动递增 会员ID
gender ENUM('男','女') NULL 性别
birth_date DATE NULL 出生日期
mname VARCHAR(20) 姓名
phone VARCHAR(20) 电话(唯一)
integral INT 0 积分

 出版社表 (publishers)

字段名 数据类型 是否为空 默认值 主键 外键 说明
publisher_id INT 自动递增 出版社ID
pname VARCHAR(100) 名字(唯一)
phone VARCHAR(20) NULL 电话
address VARCHAR(255) NULL 地址

 图书表 (books)

字段名 数据类型 是否为空 默认值 主键 外键 说明
isbn VARCHAR(20) ISBN国际标准书号
title VARCHAR(255) 标题
author VARCHAR(100) 作者
publisher_id INT 出版社ID
retail_price DECIMAL(10,2) 零售价
discount_rate DECIMAL(5,2) 1.00 折扣率
stock_quantity INT 0 库存数量
purchase_price DECIMAL(10,2) NULL 进货价
purchase_date DATE NULL 入库时间

 促销活动表 (promotions)

字段名 数据类型 是否为空 默认值 主键 外键 说明
promotion_id INT 自动递增 活动ID
isbn VARCHAR(20) ISBN国际标准书号
promotion_name VARCHAR(100) 活动名称
start_time DATETIME 开始时间
end_time DATETIME 结束时间
discount_rate DECIMAL(5,2) 折扣率(0.1到1.0)

 库存变动记录日表 (inventory_changes)

字段名 数据类型 是否为空 默认值 主键 外键 说明
change_time TIMESTAMP CURRENT_TIMESTAMP 是(联合) 变动时间
record_id INT 是(联合) 记录ID
isbn VARCHAR(20) ISBN国际标准书号
change_type ENUM('采购入库','销售出库') 变动类型
quantity INT 变动数量
admin_id INT NULL 管理员ID
related_id INT NULL 关联销售ID

 销售记录日表 (sales)

字段名 数据类型 是否为空 默认值 主键 外键 说明
sale_date DATETIME 是(联合) 销售日期
sale_id INT 是(联合) 销售ID
member_id INT NULL 会员ID
promotion_id INT NULL 活动ID
admin_id INT 管理员ID
total_amount DECIMAL(10,2) 总金额
purchase_price DECIMAL(10,2) NULL 进货价
purchase_date DATE NULL 入库时间
isbn VARCHAR(20) ISBN国际标准书号
quantity INT 数量
unit_price DECIMAL(10,2) 单价
discount_rate DECIMAL(5,2) NULL 折扣率(0.1到1.0)

 系统日志表 (system_logs)

字段名 数据类型 是否为空 默认值 主键 外键 说明
log_id INT 自动递增 日志ID
admin_id INT NULL 管理员ID
action_type VARCHAR(50) 操作类型
action_time TIMESTAMP CURRENT_TIMESTAMP

2.4 创建数据库

CREATE DATABASE book_sales_management;

USE book_sales_management;

-- 创建数据字典表

CREATE TABLE data_dictionary (

    item_id VARCHAR(10) PRIMARY KEY,

    item_name VARCHAR(50) NOT NULL,

    data_class VARCHAR(20) NOT NULL,

    data_type VARCHAR(50) NOT NULL,

    notes VARCHAR(200)

);

-- 图书类数据项 (C1)

INSERT INTO data_dictionary (item_id, item_name, data_class, data_type, notes) VALUES

('I1', 'ISBN', 'C1', 'VARCHAR(20)', 'ISBN国际标准书号'),

('I2', '标题', 'C1', 'VARCHAR(255)', '图书的名称'),

('I3', '作者', 'C1', 'VARCHAR(100)', '图书的作者姓名'),

('I4', '出版社ID', 'C1', 'INT', '出版社表的ID'),

('I5', '零售价', 'C1', 'DECIMAL(10,2)', '图书的零售价格'),

('I6', '进货价', 'C1', 'DECIMAL(10,2)', '图书的采购价格'),

('I7', '入库时间', 'C1', 'DATE', '图书的入库日期');

-- 管理员类数据项 (C2)

INSERT INTO data_dictionary (item_id, item_name, data_class, data_type, notes) VALUES

('A1', '管理员ID', 'C2', 'INT', '管理员的唯一标识'),

('A2', '用户名', 'C2', 'VARCHAR(50)', '管理员的用户名'),

('A3', '密码', 'C2', 'VARCHAR(255)', '管理员的登录密码'),

('A4', '电话', 'C2', 'VARCHAR(20)', '管理员的联系电话'),

('A5', '创建时间', 'C2', 'TIMESTAMP', '管理员账户的创建时间');

-- 会员类数据项 (C3)

INSERT INTO data_dictionary (item_id, item_name, data_class, data_type, notes) VALUES

('M1', '会员ID', 'C3', 'INT', '会员的唯一标识'),

('M2', '性别', 'C3', 'ENUM(''男'', ''女'')', '会员的性别'),

('M3', '出生日期', 'C3', 'DATE', '会员的出生日期'),

('M4', '姓名', 'C3', 'VARCHAR(20)', '会员的姓名'),

('M5', '电话', 'C3', 'VARCHAR(20)', '会员的联系电话'),

('M6', '积分', 'C3', 'INT', '会员的累计积分');

-- 出版社类数据项 (C4)

INSERT INTO data_dictionary (item_id, item_name, data_class, data_type, notes) VALUES

('P1', '出版社ID', 'C4', 'INT', '出版社的唯一标识'),

('P2', '名字', 'C4', 'VARCHAR(100)', '出版社的名称'),

('P3', '电话', 'C4', 'VARCHAR(20)', '出版社的联系电话'),

('P4', '地址', 'C4', 'VARCHAR(255)', '出版社的地址');

-- 销售类数据项 (C5)

INSERT INTO data_dictionary (item_id, item_name, data_class, data_type, notes) VALUES

('S1', '销售日期', 'C5', 'DATETIME', '销售发生的日期和时间'),

('S2', '销售ID', 'C5', 'INT', '销售的唯一标识'),

('S3', '会员ID', 'C5', 'INT', '参与销售的会员ID'),

('S4', '管理员ID', 'C5', 'INT', '处理销售的管理员ID'),

('S5', '总金额', 'C5', 'DECIMAL(10,2)', '销售的总金额'),

('S6', '进货价', 'C5', 'DECIMAL(10,2)', '销售的进货价'),

('S7', '入库时间', 'C5', 'DATE', '相关图书的入库时间'),

('S8', '数量', 'C5', 'INT', '销售的数量'),

('S9', '单价', 'C5', 'DECIMAL(10,2)', '图书的销售单价'),

('S10', '折扣率', 'C5', 'DECIMAL(5,2)', '销售时应用的折扣率');

-- 促销活动类数据项 (C6)

INSERT INTO data_dictionary (item_id, item_name, data_class, data_type, notes) VALUES

('PR1', '活动ID', 'C6', 'INT', '促销活动的唯一标识'),

('PR2', '活动名称', 'C6', 'VARCHAR(100)', '促销活动的名称'),

('PR3', '开始时间', 'C6', 'DATETIME', '促销活动的开始时间'),

('PR4', '结束时间', 'C6', 'DATETIME', '促销活动的结束时间'),

('PR5', '折扣率', 'C6', 'DECIMAL(5,2)', '促销活动的折扣率(0.1-1.0)');

-- 库存变动类数据项 (C7)

INSERT INTO data_dictionary (item_id, item_name, data_class, data_type, notes) VALUES

('IC1', '变动时间', 'C7', 'TIMESTAMP', '库存变动的时间'),

('IC2', '记录ID', 'C7', 'INT', '库存变动的唯一标识'),

('IC3', 'ISBN', 'C7', 'INT', 'ISBN国际标准书号'),

('IC4', '变动类型', 'C7', 'ENUM(''采购入库'', ''销售出库'')', '库存变动的类型'),

('IC5', '变动数量', 'C7', 'INT', '库存变动的数量'),

('IC6', '操作员ID', 'C7', 'INT', '进行库存变动的操作员ID'),

('IC7', '关联销售ID', 'C7', 'INT', '关联的销售记录ID');

-- 系统日志类数据项 (C8)

INSERT INTO data_dictionary (item_id, item_name, data_class, data_type, notes) VALUES

('L1', '日志ID', 'C8', 'INT', '系统日志的唯一标识'),

('L2', '管理员ID', 'C8', 'INT', '执行操作的管理员ID'),

('L3', '操作类型', 'C8', 'VARCHAR(50)', '系统操作类型'),

('L4', '操作时间', 'C8', 'TIMESTAMP', '操作发生的时间');

-- 管理员表

CREATE TABLE administrators (

    admin_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '管理员ID',

    username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',

    password VARCHAR(255) NOT NULL COMMENT '密码',

    phone VARCHAR(20) COMMENT '电话',

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'

) COMMENT '管理员表';

-- 会员表

CREATE TABLE members (

    member_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '会员ID',

gender ENUM('男', '女') COMMENT '性别',    

    birth_date DATE COMMENT '出生日期',

    mname VARCHAR(20) NOT NULL COMMENT '姓名',

    phone VARCHAR(20) NOT NULL UNIQUE COMMENT '电话',

    integral INT DEFAULT 0 COMMENT '积分',

    CHECK (integral >= 0)

) COMMENT '会员表';

-- 出版社表

CREATE TABLE publishers (

    publisher_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '出版社ID',

    pname VARCHAR(100) NOT NULL UNIQUE COMMENT '名字',

    phone VARCHAR(20) COMMENT '电话',

    address VARCHAR(255) COMMENT '地址'

) COMMENT '出版社表';

-- 图书表

CREATE TABLE books (

    isbn VARCHAR(20) PRIMARY KEY COMMENT 'ISBN国际标准书号',

    title VARCHAR(255) NOT NULL COMMENT '标题',

    author VARCHAR(100) NOT NULL COMMENT '作者',

    publisher_id INT NOT NULL COMMENT '出版社ID',

    retail_price DECIMAL(10, 2) NOT NULL COMMENT '零售价',

    discount_rate DECIMAL(5, 2) DEFAULT 1.00 COMMENT '折扣率',

    stock_quantity INT NOT NULL DEFAULT 0 COMMENT '库存数量',

    purchase_price DECIMAL(10, 2) COMMENT '进货价',

    purchase_date DATE COMMENT '入库时间',

    FOREIGN KEY (publisher_id) REFERENCES publishers(publisher_id),

    CHECK (retail_price > 0),

    CHECK (discount_rate BETWEEN 0.1 AND 1.0),

    CHECK (stock_quantity >= 0)

) COMMENT '图书表';

-- 促销活动表

CREATE TABLE promotions (

    promotion_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '活动ID',

    isbn VARCHAR(20) NOT NULL COMMENT 'ISBN国际标准书号',

    promotion_name VARCHAR(100) NOT NULL COMMENT '活动名称',

    start_time DATETIME NOT NULL COMMENT '开始时间',

    end_time DATETIME NOT NULL COMMENT '结束时间',

    discount_rate DECIMAL(5, 2) NOT NULL COMMENT '折扣率 (0.1 到 1.0)',

    CHECK (start_time < end_time),

    CHECK (discount_rate BETWEEN 0.1 AND 1.0),

    FOREIGN KEY (isbn) REFERENCES books(isbn)

) COMMENT '促销活动表';

-- 库存变动记录日表

CREATE TABLE inventory_changes (

    change_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '变动时间',

    record_id INT NOT NULL COMMENT '记录ID',

    isbn VARCHAR(20) NOT NULL COMMENT 'ISBN国际标准书号',

    change_type ENUM('采购入库', '销售出库') NOT NULL COMMENT '变动类型',

    quantity INT NOT NULL COMMENT '变动数量',

    admin_id INT COMMENT '管理员ID',

    related_id INT COMMENT '关联销售ID',

    PRIMARY KEY (change_time, record_id), -- 联合主键

    FOREIGN KEY (isbn) REFERENCES books(isbn),

    FOREIGN KEY (admin_id) REFERENCES administrators(admin_id)

) COMMENT '库存变动记录日表';

-- 销售记录日表

CREATE TABLE sales (

    sale_date DATETIME NOT NULL COMMENT '销售日期',

    sale_id INT NOT NULL COMMENT '销售ID',

    member_id INT COMMENT '会员ID',

    promotion_id INT COMMENT '活动ID',

    admin_id INT NOT NULL COMMENT '管理员ID',

    total_amount DECIMAL(10, 2) NOT NULL COMMENT '总金额',

    purchase_price DECIMAL(10, 2) COMMENT '进货价',

    purchase_date DATE COMMENT '入库时间',

    isbn VARCHAR(20) NOT NULL COMMENT 'ISBN国际标准书号',

    quantity INT NOT NULL COMMENT '数量',

    unit_price DECIMAL(10, 2) NOT NULL COMMENT '单价',

    discount_rate DECIMAL(5, 2) COMMENT '折扣率 (0.1 到 1.0)',

    PRIMARY KEY (sale_date, sale_id), -- 联合主键

    FOREIGN KEY (member_id) REFERENCES members(member_id),

    FOREIGN KEY (admin_id) REFERENCES administrators(admin_id),

    INDEX idx_sale_date (sale_date),

    INDEX idx_member_id (member_id)

) COMMENT '销售记录日表';

-- 系统日志表

CREATE TABLE system_logs (

    log_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '日志ID',

    admin_id INT COMMENT '管理员ID',

    action_type VARCHAR(50) NOT NULL COMMENT '操作类型',

    action_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',

    FOREIGN KEY (admin_id) REFERENCES administrators(admin_id),

    INDEX idx_action_time (action_time)

) COMMENT '系统日志表';

1.图书库存视图

主要功能:

CREATE VIEW vw_book_inventory AS
SELECT 
    b.isbn AS 'ISBN国际标准书号',
    b.title AS '书名',
    b.author AS '作者',
    p.pname AS '出版社',
    b.retail_price AS '零售价',
    b.discount_rate AS '折扣率',
    ROUND(b.retail_price * b.discount_rate, 2) AS '销售价',
    b.stock_quantity AS '库存数量',
    b.purchase_price AS '进货价',
    CASE 
        WHEN b.stock_quantity = 0 THEN '缺货'
        WHEN b.stock_quantity < 5 THEN '低库存'
        ELSE '库存充足'
    END AS '库存状态'
FROM books b
JOIN publishers p ON b.publisher_id = p.publisher_id
WHERE b.discount_rate BETWEEN 0.1 AND 1.0; 

视图 vw_book_inventory 是一个集成了图书库存综合信息的查询视图,它通过关联 books 和 publishers 表,提供了图书ID、书名、作者、出版社名称等基本信息,同时包含了零售价、折扣率以及自动计算得出的实际销售价(零售价×折扣率)。该视图特别设计了库存状态监控功能,根据库存数量自动将图书分类为"缺货"(库存为0)、"低库存"(库存小于5)或"库存充足"三种状态,方便管理人员快速掌握库存情况。 

    2.库存变动汇总视图
CREATE VIEW vw_inventory_changes AS
SELECT 
    ic.record_id AS '记录ID',
    b.isbn AS 'ISBN国际标准书号',
    b.title AS '书名',
    ic.change_type AS '变动类型',
    ic.quantity AS '变动数量',
    DATE_FORMAT(ic.change_time, '%Y-%m-%d %H:%i') AS '变动时间',
    a.username AS '操作人员',
    CASE 
        WHEN ic.related_id IS NOT NULL THEN CONCAT('关联销售:', ic.related_id)
        ELSE NULL 
    END AS '关联信息',
    (SELECT SUM(quantity) 
     FROM inventory_changes 
     WHERE isbn = b.isbn AND record_id <= ic.record_id) AS '累计变动量'
FROM inventory_changes ic
JOIN books b ON ic.isbn = b.isbn
LEFT JOIN administrators a ON ic.admin_id = a.admin_id
ORDER BY ic.change_time DESC;

主要功能:

视图 vw_inventory_changes 是一个用于全面追踪和分析图书库存变动的综合查询视图,它通过关联库存变动记录表、图书表和管理员表,提供了完整的库存流动监控功能。该视图以清晰易读的格式展示每笔库存变动的详细信息,包括记录ID、图书ISBN和书名、变动类型(采购入库或销售出库)、具体变动数量(正数表示入库,负数表示出库)以及格式化的变动时间。视图特别设计了操作人员字段显示执行变动的管理员信息,并智能识别关联销售记录,当变动与销售相关时会显示"关联销售:+销售ID"的提示信息。最具特色的是视图自动计算并显示每本图书的累计变动量,通过子查询实时汇总截至当前记录的各图书总变动量,使库存变化趋势一目了然。所有记录默认按变动时间降序排列,确保最新变动优先显示,便于库存管理人员快速掌握最新动态。该视图不仅满足了日常库存管理的需求,还为库存分析、异常追踪和审计工作提供了完整的数据支持,是图书库存监控和管理的有效工具。

3.会员购买历史视图
CREATE VIEW vw_member_purchases AS
SELECT 
    m.member_id AS '会员ID',
    m.mname AS '会员姓名',
    m.phone AS '联系电话',
    s.sale_id AS '销售单号',
    s.sale_date AS '购买日期',
    b.title AS '图书名称',
    s.quantity AS '购买数量',
    s.unit_price AS '单价',
    s.total_amount AS '总金额',
    FLOOR(s.total_amount / 10) AS '获得积分'
FROM members m
JOIN sales s ON m.member_id = s.member_id
JOIN books b ON s.isbn = b.isbn
ORDER BY m.member_id, s.sale_date DESC;

主要功能:

视图 vw_member_purchases 是一个专门用于分析会员购买行为的综合查询视图,它通过关联 members、sales 和 books 三张表,全面展示了每位会员的详细购买记录。该视图不仅包含会员基本信息(ID、姓名、联系电话),还完整呈现了每笔交易的销售单号、购买日期、所购图书名称、购买数量、单价和总金额等交易细节,并自动计算出每笔交易获得的积分(按总金额每10元1积分计算)。

4.会员积分汇总视图
CREATE VIEW vw_member_points AS
SELECT 
    m.member_id AS '会员ID',
    m.mname AS '会员姓名',
    m.phone AS '联系电话',
    CAST(m.integral AS SIGNED) AS '当前积分',
    COUNT(s.sale_id) AS '购买次数',
    SUM(s.total_amount) AS '消费总额'
FROM members m
LEFT JOIN sales s ON m.member_id = s.member_id
GROUP BY m.member_id, m.mname, m.phone, m.integral
ORDER BY m.integral DESC;

主要功能: 

视图 vw_member_points 是一个专门用于会员积分分析的综合性视图,它通过关联 members 表和 sales 表,全面展示了会员的积分情况和消费行为。该视图首先将会员的字符串类型积分转换为数值类型以便正确排序,然后为每个会员统计总购买次数和消费总额,并按照积分高低降序排列。

5.每日销售报表视图
CREATE VIEW vw_daily_sales_report AS
SELECT 
    DATE(s.sale_date) AS '销售日期',
    a.admin_id AS '管理员ID',
    a.username AS '管理员姓名',
    COUNT(DISTINCT s.sale_id) AS '交易笔数',
    COUNT(DISTINCT s.member_id) AS '服务会员数',
    SUM(s.quantity) AS '销售图书册数',
    SUM(s.total_amount) AS '销售总额',
    AVG(s.total_amount) AS '平均交易金额'
FROM sales s
JOIN administrators a ON s.admin_id = a.admin_id
GROUP BY DATE(s.sale_date), a.admin_id, a.username
ORDER BY DATE(s.sale_date) DESC;

主要功能:

视图 vw_daily_sales_report 是一个面向销售管理的每日业绩分析工具,它通过关联 sales 和 administrators 表,按日期和管理员维度聚合销售数据,生成包含销售日期、管理员信息(ID和姓名)以及关键业绩指标(交易笔数、服务会员数、销售图书册数、销售总额和平均交易金额)的综合性报表。

6.促销活动视图
CREATE VIEW vw_promotion_performance AS
SELECT 
    p.promotion_id AS '活动ID',
    p.promotion_name AS '活动名称',
    DATE_FORMAT(p.start_time, '%Y-%m-%d') AS '开始日期',
    DATE_FORMAT(p.end_time, '%Y-%m-%d') AS '结束日期',
    COUNT(s.sale_id) AS '参与订单数',
    IFNULL(SUM(s.total_amount), 0) AS '活动销售额',
    COUNT(DISTINCT s.member_id) AS '参与会员数',
    CASE 
        WHEN COUNT(s.sale_id) = 0 THEN '效果不佳'
        WHEN COUNT(s.sale_id) > 20 THEN '效果显著'
        ELSE '效果一般'
    END AS '活动效果'
FROM promotions p
LEFT JOIN sales s ON p.promotion_id = s.promotion_id
GROUP BY p.promotion_id, p.promotion_name, p.start_time, p.end_time;

主要功能:

视图 vw_promotion_performance 是一个专门用于评估促销活动效果的综合性分析视图,它通过关联促销活动表和销售记录表,为营销决策提供关键数据支持。该视图从多个维度全面展示每项促销活动的表现情况:首先展示活动的基本信息,包括活动ID、名称以及格式化的起止日期;其次通过统计参与订单数和活动销售额来量化活动成效;同时计算参与会员数以评估活动覆盖范围;最具特色的是视图内置了智能评估功能,根据订单数量自动将活动效果分为"效果显著"(订单>20)、"效果一般"和"效果不佳"(无订单)三个等级,为营销人员提供直观的效果判断。视图采用LEFT JOIN确保所有促销活动都会被统计,即使没有销售记录的活动也会显示(销售额记为0),这种设计保证了分析的完整性,使管理人员能够全面了解每项促销活动的实际表现,为未来的营销策略制定提供数据依据。

2.6数据库存储过程设计

2.6.1图书管理模块

1.图书入库以及折扣设置

-- 图书入库以及折扣设置
DELIMITER //
CREATE PROCEDURE sp_book_add(
    IN p_title VARCHAR(255),
    IN p_author VARCHAR(100),
    IN p_publisher_id INT,
    IN p_retail_price DECIMAL(10,2),
    IN p_discount_rate DECIMAL(5,2),
    IN p_stock_quantity INT,
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_publisher_exists INT;
    
    -- 检查出版社是否存在
    SELECT COUNT(*) INTO v_publisher_exists FROM publishers WHERE publisher_id = p_publisher_id;
    
    IF v_publisher_exists = 0 THEN
        SET p_result = '错误:出版社不存在';
    ELSEIF p_retail_price <= 0 THEN
        SET p_result = '错误:零售价必须大于0';
    ELSEIF p_discount_rate < 0.1 OR p_discount_rate > 1.0 THEN
        SET p_result = '错误:折扣率必须在0.1到1.0之间';
    ELSEIF p_stock_quantity < 0 THEN
        SET p_result = '错误:库存数量不能为负数';
    ELSE
        -- 插入新书
        INSERT INTO books (title, author, publisher_id, retail_price, discount_rate, stock_quantity)
        VALUES (p_title, p_author, p_publisher_id, p_retail_price, p_discount_rate, p_stock_quantity);
        
        SET p_result = CONCAT('成功添加图书:', p_title, ',库存数量:', p_stock_quantity);
    END IF;
END //
DELIMITER ;

功能描述 :

该存储过程 sp_book_add 是一个用于图书入库管理的数据库操作程序,主要功能是向系统中添加新图书并设置相关折扣信息。它通过接收图书标题、作者、出版社ID、零售价、折扣率和库存数量等参数,在执行前会进行严格的业务规则验证:首先检查指定的出版社是否存在,然后验证零售价必须大于0、折扣率必须在0.1到1.0之间(即1折到不打折)、库存数量不能为负数等业务规则。当所有验证通过后,才会将新图书信息插入到books表中,并通过OUT参数返回操作结果。该存储过程封装了完整的图书入库逻辑,包括数据验证和业务处理,确保了数据的一致性和完整性,同时通过明确的错误提示方便调用者了解操作失败的具体原因。执行成功后,会返回包含图书名称和库存数量的确认信息,为图书采购和库存管理提供了标准化的数据操作接口,有效防止了非法数据的录入。

2.图书修改

-- 图书修改
DELIMITER //
CREATE PROCEDURE sp_book_update(
    IN p_book_id INT,
    IN p_title VARCHAR(255),
    IN p_author VARCHAR(100),
    IN p_publisher_id INT,
    IN p_retail_price DECIMAL(10,2),
    IN p_discount_rate DECIMAL(5,2),
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_book_exists INT;
    DECLARE v_publisher_exists INT;
    
    -- 检查图书是否存在
    SELECT COUNT(*) INTO v_book_exists FROM books WHERE book_id = p_book_id;
    
    IF v_book_exists = 0 THEN
        SET p_result = '错误:图书不存在';
    ELSE
        -- 检查出版社是否存在
        SELECT COUNT(*) INTO v_publisher_exists FROM publishers WHERE publisher_id = p_publisher_id;
        
        IF v_publisher_exists = 0 THEN
            SET p_result = '错误:出版社不存在';
        ELSEIF p_retail_price <= 0 THEN
            SET p_result = '错误:零售价必须大于0';
        ELSEIF p_discount_rate < 0.1 OR p_discount_rate > 1.0 THEN
            SET p_result = '错误:折扣率必须在0.1到1.0之间';
        ELSE
            -- 更新图书信息
            UPDATE books 
            SET title = p_title, 
                author = p_author, 
                publisher_id = p_publisher_id, 
                retail_price = p_retail_price, 
                discount_rate = p_discount_rate
            WHERE book_id = p_book_id;
            
            SET p_result = CONCAT('成功更新图书ID:', p_book_id);
        END IF;
    END IF;
END //
DELIMITER ;

功能描述:

此存储过程用于修改已入库图书的各项信息,包括图书标题、作者、出版社ID、零售价和折扣率等。它会先检查图书和出版社是否存在,然后验证零售价和折扣率的有效性,确保数据符合业务规则后才执行更新操作。通过OUT参数返回操作结果,便于调用者了解修改是否成功及失败原因。 

3.图书查询

DELIMITER //
CREATE FUNCTION fn_book_search(
    p_keyword VARCHAR(100),
    p_author VARCHAR(100),
    p_publisher_id INT
) RETURNS TEXT
DETERMINISTIC
BEGIN
    DECLARE v_result TEXT;
    
    SELECT GROUP_CONCAT(
        CONCAT('ID:', book_id, 
               ' 书名:', title, 
               ' 作者:', author, 
               ' 出版社:', (SELECT pname FROM publishers WHERE publisher_id = books.publisher_id),
               ' 价格:', retail_price, 
               ' 折扣:', discount_rate,
               ' 库存:', stock_quantity)
        SEPARATOR '\n'
    ) INTO v_result
    FROM books
    WHERE (p_keyword IS NULL OR title LIKE CONCAT('%', p_keyword, '%'))
      AND (p_author IS NULL OR author LIKE CONCAT('%', p_author, '%'))
      AND (p_publisher_id IS NULL OR publisher_id = p_publisher_id);
    
    IF v_result IS NULL THEN
        SET v_result = '没有找到符合条件的图书';
    END IF;
    
    RETURN v_result;
END //
DELIMITER ;

功能描述:

这是一个返回文本的函数,用于根据关键字、作者或出版社ID等条件检索图书信息。它支持模糊查询和组合条件查询,返回格式化的图书信息列表,包括图书ID、书名、作者、出版社、价格、折扣和库存等信息。当没有找到符合条件的图书时,返回提示信息。 

4.图书删除

-- 图书删除
DELIMITER //
CREATE PROCEDURE sp_book_delete(
    IN p_book_id INT,
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_book_exists INT;
    DECLARE v_has_sales INT;
    
    -- 检查图书是否存在
    SELECT COUNT(*) INTO v_book_exists FROM books WHERE book_id = p_book_id;
    
    IF v_book_exists = 0 THEN
        SET p_result = '错误:图书不存在';
    ELSE
        -- 检查是否有销售记录
        SELECT COUNT(*) INTO v_has_sales FROM sales WHERE book_id = p_book_id;
        
        IF v_has_sales > 0 THEN
            SET p_result = '错误:该图书已有销售记录,不能删除';
        ELSE
            -- 删除图书
            DELETE FROM books WHERE book_id = p_book_id;
            SET p_result = CONCAT('成功删除图书ID:', p_book_id);
        END IF;
    END IF;
END //
DELIMITER ;

功能描述:

该存储过程用于从系统中移除图书记录,但会先检查图书是否存在以及是否有相关的销售记录。如果图书已有销售记录,则不允许删除,防止数据不一致。只有无销售记录的图书才能被成功删除,并通过OUT参数返回操作结果。 

5.库存修改

-- 库存修改
DELIMITER //
CREATE PROCEDURE sp_stock_update(
    IN p_book_id INT,
    IN p_quantity_change INT,
    IN p_admin_id INT,
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_book_exists INT;
    DECLARE v_admin_exists INT;
    DECLARE v_current_stock INT;
    
    -- 检查图书是否存在
    SELECT COUNT(*) INTO v_book_exists FROM books WHERE book_id = p_book_id;
    -- 检查管理员是否存在
    SELECT COUNT(*) INTO v_admin_exists FROM administrators WHERE admin_id = p_admin_id;
    
    IF v_book_exists = 0 THEN
        SET p_result = '错误:图书不存在';
    ELSEIF v_admin_exists = 0 THEN
        SET p_result = '错误:管理员不存在';
    ELSE
        -- 获取当前库存
        SELECT stock_quantity INTO v_current_stock FROM books WHERE book_id = p_book_id;
        
        -- 检查库存是否足够减少
        IF v_current_stock + p_quantity_change < 0 THEN
            SET p_result = CONCAT('错误:库存不足,当前库存:', v_current_stock, ',无法减少:', ABS(p_quantity_change));
        ELSE
            -- 更新库存
            UPDATE books 
            SET stock_quantity = stock_quantity + p_quantity_change
            WHERE book_id = p_book_id;
            
            -- 记录系统日志
            INSERT INTO system_logs (admin_id, action_type)
            VALUES (p_admin_id, CONCAT('修改库存:图书ID=', p_book_id, ',数量变化=', p_quantity_change));
            
            SET p_result = CONCAT('成功更新库存,图书ID:', p_book_id, ',新库存:', v_current_stock + p_quantity_change);
        END IF;
    END IF;
END //
DELIMITER ;

功能描述:

用于调整图书库存数量,接收图书ID、库存变化量和管理员ID作为参数。它会检查图书和管理员是否存在,验证库存变化后的数量是否合法(不能为负数),然后更新库存并记录系统日志。通过OUT参数返回操作结果,包括更新后的库存数量。 

6.每日销售id重置

DELIMITER //
CREATE PROCEDURE sp_get_next_sale_id(OUT p_next_id INT)
BEGIN
    DECLARE v_last_sale_date DATE;
    DECLARE v_current_date DATE;
    DECLARE v_max_sale_id INT;
    
    SET v_current_date = CURDATE();
    
    -- 获取最近一次销售日期
    SELECT MAX(DATE(sale_date)) INTO v_last_sale_date FROM sales;
    
    -- 如果是新的一天,从1开始
    IF v_last_sale_date IS NULL OR v_last_sale_date < v_current_date THEN
        SET p_next_id = 1;
    ELSE
        -- 获取当天的最大sale_id
        SELECT IFNULL(MAX(sale_id), 0) + 1 INTO v_max_sale_id 
        FROM sales 
        WHERE DATE(sale_date) = v_current_date;
        
        SET p_next_id = v_max_sale_id;
    END IF;
END //
DELIMITER ;
功能描述:

存储过程 sp_get_next_sale_id 是一个专门用于生成销售单ID的实用程序,它通过智能判断当前日期和销售记录情况,确保销售ID的连续性和唯一性。该过程首先获取系统当前日期,然后查询数据库中最近一次销售记录的日期进行比对。如果是新的一天(无当日销售记录或上次销售日期早于当前日期),则自动将销售ID重置为1;若当日已有销售记录,则查询当日最大销售ID并加1作为新ID。这种设计完美解决了销售ID按日期重新计数的业务需求,通过OUT参数返回生成的新ID,确保了销售记录主键的准确性和连续性,为销售业务提供了可靠的ID生成机制。

2.6.2用户管理模块

1.会员添加

-- 会员添加
DELIMITER //
CREATE PROCEDURE sp_member_add(
    IN p_mname VARCHAR(20),
    IN p_gender ENUM('男','女','其他'),
    IN p_birth_date DATE,
    IN p_phone VARCHAR(20),
    IN p_admin_id INT,
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_admin_exists INT;
    DECLARE v_phone_exists INT;
    
    -- 检查管理员是否存在
    SELECT COUNT(*) INTO v_admin_exists FROM administrators WHERE admin_id = p_admin_id;
    -- 检查电话是否已存在
    SELECT COUNT(*) INTO v_phone_exists FROM members WHERE phone = p_phone;
    
    IF v_admin_exists = 0 THEN
        SET p_result = '错误:管理员不存在';
    ELSEIF v_phone_exists > 0 THEN
        SET p_result = '错误:该电话号码已注册';
    ELSEIF p_phone IS NULL OR p_phone = '' THEN
        SET p_result = '错误:电话号码不能为空';
    ELSE
        -- 添加新会员
        INSERT INTO members (mname, gender, birth_date, phone, integral, balance)
        VALUES (p_mname, p_gender, p_birth_date, p_phone, '0', '0');
        
        -- 记录系统日志
        INSERT INTO system_logs (admin_id, action_type)
        VALUES (p_admin_id, CONCAT('添加会员:', p_mname, ',电话:', p_phone));
        
        SET p_result = CONCAT('成功添加会员:', p_mname);
    END IF;
END //
DELIMITER ;

功能描述:

此存储过程用于注册新会员,接收会员姓名、性别、出生日期、电话号码和管理员ID等参数。它会检查管理员是否存在、电话号码是否已被注册,确保电话号码不为空后才会创建新会员记录,并记录系统日志。通过OUT参数返回操作结果。 

2.会员信息修改

-- 会员信息修改
DELIMITER //
CREATE PROCEDURE sp_member_update(
    IN p_member_id INT,
    IN p_mname VARCHAR(20),
    IN p_gender ENUM('男','女','其他'),
    IN p_birth_date DATE,
    IN p_phone VARCHAR(20),
    IN p_admin_id INT,
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_member_exists INT;
    DECLARE v_admin_exists INT;
    DECLARE v_phone_exists INT;
    DECLARE v_current_phone VARCHAR(20);
    
    -- 检查会员是否存在
    SELECT COUNT(*) INTO v_member_exists FROM members WHERE member_id = p_member_id;
    -- 检查管理员是否存在
    SELECT COUNT(*) INTO v_admin_exists FROM administrators WHERE admin_id = p_admin_id;
    
    IF v_member_exists = 0 THEN
        SET p_result = '错误:会员不存在';
    ELSEIF v_admin_exists = 0 THEN
        SET p_result = '错误:管理员不存在';
    ELSE
        -- 获取当前电话号码
        SELECT phone INTO v_current_phone FROM members WHERE member_id = p_member_id;
        
        -- 检查新电话号码是否已被其他会员使用
        IF p_phone <> v_current_phone THEN
            SELECT COUNT(*) INTO v_phone_exists FROM members WHERE phone = p_phone;
            IF v_phone_exists > 0 THEN
                SET p_result = '错误:该电话号码已被其他会员使用';
            ELSE
                -- 更新会员信息
                UPDATE members 
                SET mname = p_mname, 
                    gender = p_gender, 
                    birth_date = p_birth_date, 
                    phone = p_phone
                WHERE member_id = p_member_id;
                
                -- 记录系统日志
                INSERT INTO system_logs (admin_id, action_type)
                VALUES (p_admin_id, CONCAT('修改会员信息:会员ID=', p_member_id));
                
                SET p_result = CONCAT('成功更新会员信息,会员ID:', p_member_id);
            END IF;
        ELSE
            -- 更新会员信息(电话号码未改变)
            UPDATE members 
            SET mname = p_mname, 
                gender = p_gender, 
                birth_date = p_birth_date
            WHERE member_id = p_member_id;
            
            -- 记录系统日志
            INSERT INTO system_logs (admin_id, action_type)
            VALUES (p_admin_id, CONCAT('修改会员信息:会员ID=', p_member_id));
            
            SET p_result = CONCAT('成功更新会员信息,会员ID:', p_member_id);
        END IF;
    END IF;
END //
DELIMITER ;

功能描述:

用于更新会员的个人资料,包括姓名、性别、出生日期和电话号码等。它会检查会员和管理员是否存在,验证新电话号码是否已被其他会员使用,确保数据唯一性。更新成功后记录系统日志,通过OUT参数返回操作结果。 

3.会员充值

-- 会员充值
DELIMITER //
CREATE PROCEDURE sp_member_recharge(
    IN p_member_id INT,
    IN p_amount DECIMAL(10,2),
    IN p_admin_id INT,
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_member_exists INT;
    DECLARE v_admin_exists INT;
    DECLARE v_current_balance DECIMAL(10,2);
    
    -- 检查会员是否存在
    SELECT COUNT(*) INTO v_member_exists FROM members WHERE member_id = p_member_id;
    -- 检查管理员是否存在
    SELECT COUNT(*) INTO v_admin_exists FROM administrators WHERE admin_id = p_admin_id;
    
    IF v_member_exists = 0 THEN
        SET p_result = '错误:会员不存在';
    ELSEIF v_admin_exists = 0 THEN
        SET p_result = '错误:管理员不存在';
    ELSEIF p_amount <= 0 THEN
        SET p_result = '错误:充值金额必须大于0';
    ELSE
        -- 获取当前余额
        SELECT CAST(balance AS DECIMAL(10,2)) INTO v_current_balance FROM members WHERE member_id = p_member_id;
        
        -- 更新会员余额
        UPDATE members 
        SET balance = CAST((v_current_balance + p_amount) AS CHAR) 
        WHERE member_id = p_member_id;
        
        -- 记录交易
        INSERT INTO member_transactions (member_id, amount, transaction_balance, admin_id)
        VALUES (p_member_id, CAST(p_amount AS CHAR), CAST((v_current_balance + p_amount) AS CHAR), p_admin_id);
        
        -- 记录系统日志
        INSERT INTO system_logs (admin_id, action_type)
        VALUES (p_admin_id, CONCAT('会员充值:会员ID=', p_member_id, ',金额=', p_amount));
        
        SET p_result = CONCAT('成功为会员ID:', p_member_id, '充值:', p_amount, ',新余额:', v_current_balance + p_amount);
    END IF;
END //
DELIMITER ;

功能描述:

该存储过程用于为会员账户充值,接收会员ID、充值金额和管理员ID作为参数。它会验证会员和管理员是否存在,充值金额必须大于0,然后更新会员余额并记录交易流水和系统日志。通过OUT参数返回充值后的新余额。 

4.会员删除

-- 会员删除
DELIMITER //
CREATE PROCEDURE sp_member_delete(
    IN p_member_id INT,
    IN p_admin_id INT,
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_member_exists INT;
    DECLARE v_admin_exists INT;
    DECLARE v_has_transactions INT;
    
    -- 检查会员是否存在
    SELECT COUNT(*) INTO v_member_exists FROM members WHERE member_id = p_member_id;
    -- 检查管理员是否存在
    SELECT COUNT(*) INTO v_admin_exists FROM administrators WHERE admin_id = p_admin_id;
    
    IF v_member_exists = 0 THEN
        SET p_result = '错误:会员不存在';
    ELSEIF v_admin_exists = 0 THEN
        SET p_result = '错误:管理员不存在';
    ELSE
        -- 检查是否有交易记录
        SELECT COUNT(*) INTO v_has_transactions FROM sales WHERE member_id = p_member_id;
        
        IF v_has_transactions > 0 THEN
            SET p_result = '错误:该会员有交易记录,不能删除';
        ELSE
            -- 删除会员积分记录
            DELETE FROM member_points WHERE member_id = p_member_id;
            -- 删除会员交易记录
            DELETE FROM member_transactions WHERE member_id = p_member_id;
            -- 删除会员
            DELETE FROM members WHERE member_id = p_member_id;
            
            -- 记录系统日志
            INSERT INTO system_logs (admin_id, action_type)
            VALUES (p_admin_id, CONCAT('删除会员:会员ID=', p_member_id));
            
            SET p_result = CONCAT('成功删除会员ID:', p_member_id);
        END IF;
    END IF;
END //
DELIMITER ;

功能描述:

用于注销会员账户,但会先检查会员是否存在、是否有交易记录。只有无交易记录的会员才能被删除,同时会清理相关的积分和交易记录,并记录系统日志。通过OUT参数返回操作结果。 

2.6.3销售模块

1.图书销售

-- 图书销售
DELIMITER //
CREATE PROCEDURE sp_sale_record(
    IN p_member_id INT,
    IN p_admin_id INT,
    IN p_book_id INT,
    IN p_quantity INT,
    OUT p_result VARCHAR(200)
)
proc_label: BEGIN
    DECLARE v_member_exists INT;
    DECLARE v_admin_exists INT;
    DECLARE v_book_exists INT;
    DECLARE v_current_stock INT;
    DECLARE v_book_price DECIMAL(10,2);
    DECLARE v_book_discount DECIMAL(5,2);
    DECLARE v_sale_price DECIMAL(10,2);
    DECLARE v_total_amount DECIMAL(10,2);
    DECLARE v_points_earned INT;
    
    -- 检查会员是否存在(如果提供了会员ID)
    IF p_member_id IS NOT NULL THEN
        SELECT COUNT(*) INTO v_member_exists FROM members WHERE member_id = p_member_id;
        IF v_member_exists = 0 THEN
            SET p_result = '错误:会员不存在';
            LEAVE proc_label;
        END IF;
    END IF;
    
    -- 检查管理员是否存在
    SELECT COUNT(*) INTO v_admin_exists FROM administrators WHERE admin_id = p_admin_id;
    IF v_admin_exists = 0 THEN
        SET p_result = '错误:管理员不存在';
        LEAVE proc_label;
    END IF;
    
    -- 检查图书是否存在
    SELECT COUNT(*) INTO v_book_exists FROM books WHERE book_id = p_book_id;
    IF v_book_exists = 0 THEN
        SET p_result = '错误:图书不存在';
        LEAVE proc_label;
    END IF;
    
    -- 检查购买数量
    IF p_quantity <= 0 THEN
        SET p_result = '错误:购买数量必须大于0';
        LEAVE proc_label;
    END IF;
    
    -- 检查库存
    SELECT stock_quantity, retail_price, discount_rate 
    INTO v_current_stock, v_book_price, v_book_discount
    FROM books WHERE book_id = p_book_id;
    
    IF v_current_stock < p_quantity THEN
        SET p_result = CONCAT('错误:库存不足,当前库存:', v_current_stock, ',请求数量:', p_quantity);
        LEAVE proc_label;
    END IF;
    
    -- 计算销售价格和总金额
    SET v_sale_price = v_book_price * v_book_discount;
    SET v_total_amount = v_sale_price * p_quantity;
    
    -- 计算积分(每10元1积分)
    IF p_member_id IS NOT NULL THEN
        SET v_points_earned = FLOOR(v_total_amount / 10);
    ELSE
        SET v_points_earned = 0;
    END IF;
    END //
DELIMITER ;

功能描述:

这是核心的销售处理存储过程,用于记录图书销售情况并自动调整会员积分。它会验证会员(如提供)、管理员和图书是否存在,检查购买数量和库存是否充足,计算销售价格、总金额和应得积分(每10元1积分)。在事务中完成销售记录、库存更新、积分调整和日志记录等操作,确保数据一致性。通过OUT参数返回销售结果和获得的积分。 

2.销售记录查询

-- 销售记录查询
DELIMITER //
CREATE FUNCTION fn_sales_search(
    p_start_date DATE,
    p_end_date DATE,
    p_member_id INT,
    p_book_id INT
) RETURNS TEXT
DETERMINISTIC
BEGIN
    DECLARE v_result TEXT;
    
    SELECT GROUP_CONCAT(
        CONCAT('销售ID: ', sale_id, 
               ' 会员: ', IFNULL((SELECT mname FROM members WHERE member_id = s.member_id), '非会员'), 
               ' 图书: ', (SELECT title FROM books WHERE book_id = s.book_id), 
               ' 数量: ', quantity, 
               ' 单价: ', unit_price,
               ' 总金额: ', total_amount, 
               ' 时间: ', DATE_FORMAT(sale_date, '%Y-%m-%d %H:%i:%s'))
        SEPARATOR '\n'
    ) INTO v_result
    FROM sales s
    WHERE (p_start_date IS NULL OR DATE(sale_date) >= p_start_date)
      AND (p_end_date IS NULL OR DATE(sale_date) <= p_end_date)
      AND (p_member_id IS NULL OR member_id = p_member_id)
      AND (p_book_id IS NULL OR book_id = p_book_id)
    ORDER BY sale_date DESC;
    
    IF v_result IS NULL THEN
        SET v_result = '没有找到符合条件的销售记录';
    END IF;
    
    RETURN v_result;
END //
DELIMITER ;

功能描述:

这是一个返回文本的函数,用于查询历史销售记录。它支持按日期范围、会员ID和图书ID等条件筛选,返回格式化的销售信息列表,包括销售ID、会员信息、图书信息、数量、单价、总金额和时间等。当没有符合条件的记录时返回提示信息。 

2.6.4系统管理模块

1.管理员增加

-- 增加管理员
DELIMITER //
CREATE PROCEDURE sp_admin_add(
    IN p_username VARCHAR(50),
    IN p_password VARCHAR(255),
    IN p_phone VARCHAR(20),
    IN p_creator_id INT,
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_creator_exists INT;
    DECLARE v_username_exists INT;
    
    -- 检查创建者是否存在
    SELECT COUNT(*) INTO v_creator_exists FROM administrators WHERE admin_id = p_creator_id;
    -- 检查用户名是否已存在
    SELECT COUNT(*) INTO v_username_exists FROM administrators WHERE username = p_username;
    
    IF v_creator_exists = 0 THEN
        SET p_result = '错误:创建者不存在';
    ELSEIF v_username_exists > 0 THEN
        SET p_result = '错误:用户名已存在';
    ELSEIF p_username IS NULL OR p_username = '' THEN
        SET p_result = '错误:用户名不能为空';
    ELSEIF p_password IS NULL OR p_password = '' THEN
        SET p_result = '错误:密码不能为空';
    ELSE
        -- 添加新管理员
        INSERT INTO administrators (username, password, phone)
        VALUES (p_username, p_password, p_phone);
        
        -- 记录系统日志
        INSERT INTO system_logs (admin_id, action_type)
        VALUES (p_creator_id, CONCAT('添加管理员:', p_username));
        
        SET p_result = CONCAT('成功添加管理员:', p_username);
    END IF;
END //
DELIMITER ;

功能描述:

用于创建新的系统管理员账户,接收用户名、密码、电话号码和创建者ID等参数。它会检查创建者是否存在、用户名是否已存在,确保用户名和密码不为空后才会创建新管理员,并记录系统日志。通过OUT参数返回操作结果。 

2.修改密码

-- 修改密码
DELIMITER //
CREATE PROCEDURE sp_admin_change_password(
    IN p_admin_id INT,
    IN p_old_password VARCHAR(255),
    IN p_new_password VARCHAR(255),
    OUT p_result VARCHAR(200)
)
BEGIN
    DECLARE v_password_match INT;
    
    -- 检查旧密码是否正确
    SELECT COUNT(*) INTO v_password_match 
    FROM administrators 
    WHERE admin_id = p_admin_id AND password = p_old_password;
    
    IF v_password_match = 0 THEN
        SET p_result = '错误:旧密码不正确';
    ELSEIF p_new_password IS NULL OR p_new_password = '' THEN
        SET p_result = '错误:新密码不能为空';
    ELSE
        -- 更新密码
        UPDATE administrators 
        SET password = p_new_password 
        WHERE admin_id = p_admin_id;
        
        -- 记录系统日志
        INSERT INTO system_logs (admin_id, action_type)
        VALUES (p_admin_id, '修改密码');
        
        SET p_result = '密码修改成功';
    END IF;
END //
DELIMITER ;

功能描述:

该存储过程用于修改管理员登录密码,接收管理员ID、旧密码和新密码作为参数。它会验证旧密码是否正确,确保新密码不为空后才执行密码更新,并记录系统日志。通过OUT参数返回密码修改结果。 

2.7数据库触发器设计

1.销售后更新库存
DELIMITER //

CREATE TRIGGER trg_after_sale_update_stock
AFTER INSERT ON sales
FOR EACH ROW
BEGIN
    -- 减少库存数量
    UPDATE books 
    SET stock_quantity = stock_quantity - NEW.quantity 
    WHERE isbn = NEW.isbn;
    
    -- 记录库存变动
    INSERT INTO inventory_changes (record_id, isbn, change_type, quantity, admin_id, related_id)
    VALUES (
        (SELECT IFNULL(MAX(record_id), 0) + 1 FROM inventory_changes WHERE isbn = NEW.isbn),
        NEW.isbn, 
        '销售出库', 
        -NEW.quantity, 
        NEW.admin_id, 
        NEW.sale_id
    );
END //

DELIMITER ;
-- 在每次插入销售记录后自动触发
-- 更新对应图书的库存数量
-- 记录库存变动历史,包括操作管理员和关联的销售ID
-- 使用子查询确保record_id自增且不重复

功能概述

此触发器在销售记录表(sales)中插入新记录后自动执行,用于实时更新图书库存并记录库存变动情况。当一笔销售交易完成时,系统会执行两个关键操作:首先减少对应图书的库存量,确保库存数据与实际销售情况保持同步;同时记录详细的库存变动信息,为库存管理提供完整的审计追踪。

工作流程

  1. 监听销售表(sales)的INSERT操作

  2. 当有新的销售记录插入时,自动触发执行

  3. 根据新销售记录中的图书ISBN(isbn)和销售数量(quantity)

  4. 在图书表(books)中更新对应图书的库存数量(stock_quantity)

    • 更新公式为:当前库存 = 当前库存 - 销售数量

  5. 在库存变动表(inventory_changes)中新增一条出库记录

    • 自动生成新的记录ID(当前最大ID+1)

    • 记录变动类型为"销售出库"

    • 记录负数的变动数量(表示出库)

    • 关联操作管理员和销售单号

业务价值

  1. 库存实时同步:确保销售后库存立即更新,避免超卖情况

  2. 自动化管理:减少人工维护库存的工作量,提高数据准确性

  3. 完整审计追踪:记录每笔销售的库存变动详情,支持事后核查

  4. 数据一致性:通过事务保证库存更新和变动记录的原子性

  5. 库存分析基础:为库存周转率分析提供准确的基础数据

2.会员积分自动更新
DELIMITER //

CREATE TRIGGER trg_after_sale_update_points
AFTER INSERT ON sales
FOR EACH ROW
BEGIN
    -- 如果是有会员的销售,则更新会员积分
    IF NEW.member_id IS NOT NULL THEN
        UPDATE members 
        SET integral = integral + FLOOR(NEW.total_amount / 10)
        WHERE member_id = NEW.member_id;
    END IF;
END //

DELIMITER ;
-- 每笔销售如果是会员购买,则按总金额的10%计算积分
-- 使用FLOOR函数确保积分为整数
-- 只对有member_id的销售记录进行处理
  • 仅对关联会员的销售记录进行处理(非会员消费不累积积分)

  • 积分值取整数部分(消费99元得9积分)

业务价值

  1. 提升会员体验:自动即时累积积分,增强会员获得感

  2. 激励消费:通过积分奖励机制促进会员重复消费

  3. 减少人工操作:自动化积分管理,降低运营成本

  4. 数据准确性:确保积分计算和累积的精确性

  5. 营销基础:为会员等级、促销活动等提供数据支持

3.检查库存不足时 

DELIMITER //

CREATE TRIGGER trg_before_sale_check_stock
BEFORE INSERT ON sales
FOR EACH ROW
BEGIN
    DECLARE current_stock INT;
    
    -- 获取当前库存
    SELECT stock_quantity INTO current_stock 
    FROM books 
    WHERE isbn = NEW.isbn;
    
    -- 检查库存是否足够
    IF current_stock < NEW.quantity THEN
        SIGNAL SQLSTATE '45000' 
        SET MESSAGE_TEXT = '库存不足,无法完成销售';
    END IF;
END //

DELIMITER ;
-- 在插入销售记录前检查库存
-- 如果库存不足则抛出错误阻止销售
-- 使用SIGNAL SQLSTATE返回自定义错误信息

核心功能

  1. 库存实时验证

    • 在销售记录实际写入数据库前进行库存检查

    • 根据销售数量验证图书库存可用性

  2. 交易安全控制

    • 建立销售业务的前置验证机制

    • 对不符合库存条件的交易自动拦截

执行流程

  1. 监听触发:捕获销售表(sales)的INSERT操作请求

  2. 库存查询:获取待售图书(isbn)的当前库存量(stock_quantity)

  3. 数量比对:将库存量与销售数量(quantity)进行对比验证

  4. 结果处理

    • 库存充足:允许继续执行销售记录插入

    • 库存不足:抛出业务异常(错误代码45000),终止当前交易

业务规则

  • 库存阈值:销售数量必须≤当前库存量

  • 错误提示:库存不足时返回明确错误信息("库存不足,无法完成销售")

  • 执行时机:在数据写入前完成所有验证

业务价值

  1. 交易可靠性:确保每笔销售都可实际履行

  2. 库存准确性:保持库存数据的实时一致性

  3. 风险防控:从系统层面杜绝超卖风险

  4. 操作规范性:强制执行业务规则,避免人为疏忽

  5. 问题可溯性:通过明确错误信息快速定位问题原因

4.促销活动触发器

DELIMITER //
CREATE TRIGGER trg_promotion_discount
BEFORE INSERT ON promotions
FOR EACH ROW
BEGIN
    -- 检查时间有效性
    IF NEW.start_time >= NEW.end_time THEN
        SIGNAL SQLSTATE '45000' 
        SET MESSAGE_TEXT = '结束时间必须晚于开始时间';
    END IF;
    
    -- 检查折扣率有效性
    IF NEW.discount_rate < 0.1 OR NEW.discount_rate > 1.0 THEN
        SIGNAL SQLSTATE '45000' 
        SET MESSAGE_TEXT = '折扣率必须在0.1到1.0之间';
    END IF;
END //

CREATE TRIGGER trg_apply_promotion_discount
AFTER INSERT ON promotions
FOR EACH ROW
BEGIN
    -- 应用促销折扣
    UPDATE books 
    SET discount_rate = NEW.discount_rate 
    WHERE isbn = NEW.isbn;
END //

CREATE TRIGGER trg_remove_promotion_discount
AFTER UPDATE ON promotions
FOR EACH ROW
BEGIN
    -- 如果活动结束时间被更新为过去时间,恢复原价
    IF NEW.end_time < NOW() AND OLD.end_time >= NOW() THEN
        UPDATE books 
        SET discount_rate = 1.0 
        WHERE isbn = NEW.isbn;
    END IF;
END //
DELIMITER ;

1. 促销活动验证触发器 (trg_promotion_discount)

功能概述
在促销活动创建前执行数据有效性验证,确保促销参数符合业务规则。

执行规则

  • 时间有效性:检查开始时间必须早于结束时间

  • 折扣率范围:验证折扣率在0.1(1折)到1.0(原价)之间

  • 错误拦截:对不符合规则的数据抛出明确错误信息

业务价值

  • 维护促销活动的数据质量

  • 防止设置无效的促销时间范围

  • 避免不合规的折扣率设置

2. 促销折扣应用触发器 (trg_apply_promotion_discount)

功能概述
在促销活动创建成功后,自动将折扣率应用到对应图书。

执行流程

  1. 监听promotions表的INSERT操作完成

  2. 获取新促销活动的isbn和discount_rate

  3. 更新books表中对应图书的折扣率

业务价值

  • 实现促销折扣的即时生效

  • 确保促销活动与实际商品价格同步更新

  • 减少人工操作环节

3. 促销终止处理触发器 (trg_remove_promotion_discount)

功能概述
当促销活动结束时间被更新为过去时间时,自动恢复图书原价。

执行条件

  • 仅当end_time从未来时间修改为过去时间时触发

  • 检查新旧end_time与当前时间的相对关系

业务处理

  • 将对应图书的discount_rate恢复为1.0(原价)

  • 仅对实际结束的促销活动进行处理

业务价值

  • 实现促销活动的自动终止

  • 确保过期促销及时失效

  • 保持价格状态的准确性

整体业务价值

  1. 全生命周期管理:覆盖促销活动的创建、应用和终止全过程

  2. 业务规则自动化:自动执行折扣率应用和恢复逻辑

  3. 数据一致性:确保图书价格与促销状态实时同步

  4. 操作安全性:前置验证防止错误数据进入系统

  5. 管理效率:减少人工干预,降低运营成本

三.系统实现

1.主界面框架

class MainWindow : public QMainWindow {

    Q_OBJECT

public:

    // 核心组件

    QTabWidget *mainTabs;  // 多标签导航

    BookManager *bookWidget;  // 图书管理子模块

    SalesPanel *salesPanel;   // 销售终端面板

    ReportGenerator *reportTool; // 报表工具

    

    // 状态栏组件

    QLabel *dbStatusLabel;  // 数据库连接状态

QLabel *inventoryAlert;

};

2.​​​​​​​关键功能实现

数据库连接模块

bool DBConnector::initialize() {

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");

    db.setDatabaseName("bookstore.db");

    if(!db.open()) {

        QMessageBox::critical(nullptr,

            QObject::tr("Database Error"),

            db.lastError().text());

        return false;

    }

    // 启用外键约束

    QSqlQuery("PRAGMA foreign_keys = ON");

    return true;}

销售事务处理

多线程库存同步

class InventorySyncThread : public QThread {

    void run() override {

        while(!isInterruptionRequested()) {

            QMap<QString, int> remoteData = fetchRemoteInventory();

            foreach (QString isbn, remoteData.keys()) {

                updateLocalInventory(isbn, remoteData[isbn]);

            }

            sleep(300); // 每5分钟同步

        }

    }};

 3.​​​​​​​界面设计规范

布局管理

样式控制

/* Qt样式表 */QHeaderView::section {

    background-color: #3498db;

    color: white;

    padding: 4px;}QStatusBar::item {

    border: none; }

4.​​​​​​异常处理机制

try {

    // 业务操作} catch (SQLException &e) {

    logger.logError(QString("DB Error: %1").arg(e.what()));

    QMessageBox::warning(this, tr("Error"),

        tr("Database operation failed"));} catch (PaymentException &e) {

    paymentSystem.retry();} catch (...) {

    qFatal("Unhandled exception");}

5.​​​​​​​安全设计

用户权限RBAC模型:

收银员:仅销售模块

管理员:全权限

数据加密:

使用QCryptographicHash进行密码哈希

敏感数据AES-256加密存储

四.系统测试

根据系统界面分析,主要测试以下核心模块:

  1. 用户登录与权限管理
  2. 图书入库管理
  3. 图书查询功能
  4. 会员管理
  5. 销售促销活动

. 用户管理模块测试用例

管理员登录

用例编号:USER-001

测试场景:验证管理员账号登录功能

测试步骤:

输入用户名"admin"

输入正确密码

点击登录按钮

预期结果:成功跳转到系统主界面

异常情况:

密码错误时显示提示信息

用户不存在时显示提示信息

添加管理员

用例编号:USER-002

测试场景:验证添加新管理员功能

测试数据:

用户名:test_admin

密码:Test@1234

电话:13800138000

预期结果:新管理员成功添加到系统,可在管理员列表中查询到

图书管理模块测试用例

图书入库

用例编号:BOOK-001

测试场景:验证图书入库功能

测试数据:

ISBN:9787115484578

书名:测试图书

作者:测试作者

出版社:测试出版社

零售价:59.90

进货价:35.00

库存数量:100

预期结果:图书信息成功入库,库存数量更新

图书查询

用例编号:BOOK-002

测试场景:验证多条件图书查询功能

测试数据:

查询条件1:书名包含"计算机"

查询条件2:出版社为"高等教育出版社"

预期结果:返回符合条件的所有图书记录

会员管理模块测试用例

会员添加

用例编号:MEMBER-001

测试场景:验证会员信息添加功能

测试数据:

姓名:测试会员

性别:男

出生日期:1990-01-01

电话:13900139000

预期结果:会员信息成功添加,生成唯一会员ID

会员信息修改

用例编号:MEMBER-002

测试场景:验证会员信息修改功能

测试步骤:

查询会员ID为1的记录

修改联系电话为新的号码

保存修改

预期结果:会员信息更新成功,数据库中记录同步更新

销售管理模块测试用例

促销活动创建

用例编号:SALE-001

测试场景:验证促销活动创建功能

测试数据:

活动名称:暑期特惠

图书ISBN:9787040545180

开始日期:2025-07-01

结束日期:2025-08-31

折扣率:0.75

预期结果:促销活动创建成功,图书销售时自动应用折扣

促销活动查询

用例编号:SALE-002

测试场景:验证促销活动查询功能

测试数据:

查询条件:活动名称包含"618"

预期结果:返回所有符合条件的促销活动记录

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐