书店销售管理管理子系统
一、设 计 总 说 明
现在社会随着计算机技术迅速发展与技术的逐渐成熟,信息技术已经使人们的生活发生深刻的变化。生活中的各种服务系统也使人们在生活中的联系日常销售活动方式发生了很大的变化,让效率较低的手工操作成为过去,而换成信息化自动化的计算机操作。本系统是针对某一小型书店而设计的书店管理信息系统,本 系统的后台数据库选择 SQL SERVER 2014 数据库,前台开发工具选择 PyCharm, QT 。
系统设计整个系统以满足用户需求为主旨,操作简便,界面友好、灵活、高效。安全性从多个设计层面得到了保障。本系统划分了三种不同权限的身份:管理员,销售员,顾客,对进行书店的销售管理,涵盖书店销售的基本运作规则。本文设计的书店销售管理系统可以帮助书店提高效率,进行调度管理,同时本系统为餐饮企业提供了一种新的经济理念,完善企业运作模式,从而从根本上推动国家第三产业的发展。
本文是严格按照数据库系统开发的原理,对书店销售管理系统进行系统需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库实施、系统运行维护等作了详细的阐述.
关键词:书店;管理;系统;python;mssql; QT
二、绪论
2.1 开发背景及目的意义
世纪是一个信息高速发展的时代,随着计算机技术的发展 , 人们的日常工作及生活已经离不开它了。数字化、网络化、电子化、自动化将成为未来社会人们的生活和工作的主节奏,人类也必将越来越依赖于数字技术。计算机的发展历程以及目前的应用状况和发展趋势 , 可以充分地相信电子科技将极大的改变我们的生活和工作方式,它带来的信息 技术革新所掀起的社会各领域的管理革命已波及到图书销售管理,信息化的管理系统将给图书销售带来更大的社会效益与经济效益。
本次课程设计不仅考察了我综合运用这一学期所学的相关知识的能力,也锻炼了我的实际动手能力,对于我以后工作能力的培养有着重要的意义;同时通过该题目的开发实施,可以掌握系统的设计与实现全过程,巩固我的专业理论知识与实际应用的结合,提高分析问题,解决问题的能力。
2.2 国内外现状
2.2.1 国内现状
现在有些书店的图书销售仍采用传统的手工操作,这样的操作方式具有诸多不便之处,并且原始的手工人力操作已经过时,这样的流程已不能满足日趋激烈的图书销售市场的需求。随着书店消费产品数量和种类的多样化,必须通过建立有效的销售管理信息系统,对所销售的书店的大量相关信息进行数据的录入和合理分类,方便工作人员的及时调用以及掌握不断更新的信息,也为消费者提供便利的消费氛围。
2.2.2 国外现状
很多书店均已采用一体化信息销售手段,对所销售的书店的相关信息进行数据的录入和合理分类,方便书店的销售管理
2.3 开发工具、语言及环境
2.3.1 pyCharm 简介
PyCharm 是一种 Python IDE,带有一整套可以帮助用户在使用 Python 语言开发时提高其效率的工具,比如调试、语法高亮、Project 管理、代码跳转、智能提示、自动完成、单元测试、版本控制等 。是 python 开发的首选。
2.3.2 ms SQL 简介
ms SQL 是指微软的 SQLServer 数据库服务器,它是一个数据库平台,提供数据库的从服务器到终端的完整的解决方案,其中数据库服务器部分,是一个数据库管理系统,用于建立、使用和维护数据库。SQL Server 一开始并不是微软自己研发的产品,而是当时为了要和 IBM 竞争时,与 Sybase 合作所产生的,其最早的发展者是 Sybase,同时微软也和 Sybase 合作过 SQL Server 4.2 版本的研发,微软亦将 SQL Server 4.2 移植到 Windows NT(当时为 3.1 版),在与 Sybase 终止合作关系后,自力开发出 SQL Server 6.0 版,往后的 SQL Server 即均由微软自行研发。
2.3.3 开发语言 python
本系统开发所用的开发语言是 python, 因为 python 有以下的特点:
面向对象:拥有大量的通用 API 支持,使得利用 python 开发各种应用程序,可以说是易如反掌.此外,在程序除错、修改、升级和增加新功能等方面,因其面向对象的特性,使得这些维护也变得非常容易.
异常处理机制:为了使 python 程式更稳定、更安全,python 引入了异常处理机制.能够在程序中产生异常情况的地方,执行相对应的处理,不至于因突发或意外的错误造成执行中断或是死机.通过这种异常处理,不仅能够清晰地掌握整个程序执行的流程,也使得程序的设计更为严谨.
多线程:可以免去后端通信的建立,通过创建新的线程实现对数据库数据更新的监视。
三、系统分析
3.1 系统需求分析
本次课程设计的题目是:书店销售管理子系统,其具体内容如下:
书店希望借助一个销售管理子系统实现对现有业务的管理。该书店目前采用会员制,顾客购买书籍累积达到一定金额后,凭购书发票可填表申请成为正式会员,会员在购书时享有一定折扣,折扣额度可变化。该书店不定期地会推出促销活动,要求图书的价格是可变更的。系统主要功能如下:
- 图书入库管理:维护入库图书信息(如图书编号、书名、作者、价格、图书分类、出版社等),自动计算库存。
- 图书查询统计:按图书分类,出版社、书名、作者等条件查询图书的详细信息。
- 销售管理:销售过的图书都记录在销售列表中,方便统计收入。图书销售后,实时记录图书库存,按每天统计销售额、按每个月或季度统计销售额并生成报表,并能根据销售数量统计生成畅销书名单。
- 书店会员管理:提供会员信息的维护功能,可设置会员等级,不同级别的会员享受不同的折扣,可以变更折扣额度。
- 系统管理:包括参数设置、权限设置、更改密码等。用户包括系统管理员和销售人员。系统管理员维护整个系统的数据
3.2 系统目标
本系统要实现书店销售管理,实现书店销售的系统化,自动化和高效率。能够实现,图书管理,图书销售,销售统计,管理员对销售人员的管理,等功能,以及各角色的交互等。
3.3 系统功能
书店销售管理子系统的开发主要包括应用程序系统和后台数据库,应用程序系统要求界面友好,功能完备,易使用等特点.而后台数据库的数据要具有一致性、完整性、安全性.
3.3.1 前台应用程序
前台应用程序重在实现用户和系统的交互,在功能强大的同时,也要简洁和操作方便。目的是让调度环节更高效,在保证操作正确性的情况下,免去不必要的操作。
3.3.2 后台数据库
后台数据库在考虑前台访问操作简便的同时,提供强大的管理模式。数据库结构合理,完整,权限设计符合实际,安全性良好。
3.4 可行性分析
3.4.1 经济可行性分析
系统的经济可行性分析是指对组织的经济状况和投资能力进行分析,对系统的建设运营和维护费用进行估算,对系统建成后可能取得的社会及经济效益进行估计.
由于本系统作为平时的课程设计,所以在资金上几乎没有任何需求。
所以说在经济方面本系统的开发是完全可行的.
3.4.2 技术可行性分析
随着互联网和信息技术的发展,信息技术从根本上改变了人类社会的生产方式和生活方式,计算机的应用随处可见.书店销售管理子系统主要是对书店信息进行管理,实现增、删、改、查等功能。既然利用计算机管理是大势所趋,而开发一个书店销售管理又能够获得事半功倍的效果.并且,随着数据库管理系统的广泛应用以及可视化编程工具的出现,本系统便使用了 pyCharm 集成开发环境以及 PyQt5, QT 进行前台的开发,由于可视化模块比较强大,所以在系统的设计过程中不会有太大问题,同时本系统使用 ms SQL 对后台的数据进行操作,使得数据完整性得以保证,同时数据操作简单化.
以上这些都为开发一个餐饮管理系统提供了技术上的支持,所以说开发一个书店销售管理子系统在技术方面来讲是完全可行的.
3.4.3 操作可行性分析
本系统直观易懂,本身不是很复杂,使用非常方便,测试完毕后即可用于实际的管理.管理员经过简单的培训就可以熟练的使用,当进行数据修改时都有适当的提示,和消息确认,增加了人工错误的容错性。
综上所述,开发一个书店销售管理系统,在一定程度优化了书店的销售管理,因此开发这个书店销售管理系统是完全可行的.
3.5 数据流图
以下为本系统的数据流图
图 2-1 书店销售管理子系统数据流图
3.6 数据字典
数据字典是关于数据的信息的集合,也就是对数据流图中包含的所有元素的定义的集合,一般说来,数据字典应该由下列四类元素构成:数据元素,数据流,数据存储和数据处理.
3.6.1 数据元素
数据元素是不可再分的数据单位,一般而言,包括如下内容:数据项描述 ={数据项名,数据项含义说明,别名,数据类型,长度,取值范围,取值含义,与其他数据项的逻辑关系,数据项之间的联系}.其中,后两项定义了数据的完整性约束条件,用于数据校验.
本系统的数据元素具体见下文的数据库表.
3.6.2 数据存储
数据存储是数据结构停留或保存的地方.也是数据流的来源和去向之一,可以是手工文档或手工凭单,也可以是计算及文档.一般而言,应包括如下内容:{数据存储名,说明,编号,输入的数据流,输出的数据流,组成(数据结构),数据量,存取频度,存取方式}.
图 2-2 图书信息数据存储图
图 2-3 顾客信息数据存储图
图 2-4 销售人员信息数据存储图
图 2-5 管理员信息数据存储图
图 2-6 销售信息数据存储图
图 2-7 服务信息数据存储图
图 2-8 入库信息数据存储图
图 2-9 出库信息数据存储图
3.6.3 数据流
数据流是数据结构在系统内传输的路径.对数据流的描述通常包括如下内容:{数据流名,说明,编号,数据流来源,数据流去向,组成(数据结构)}.
3.6.4 数据处理
处理过程的具体处理逻辑通常在详细设计过程中用判定表或判定树来描述.在数据字典中,只无原则描述处理过程的说明性信息,通常包括以下内容:{处理过程名,说明,输入数据流,输出数据流,处理}.
图 2-10 图书管理数据处理图
图 2-11 销售人员管理数据处理图
图 2-12 图书销售、退货模块数据处理图
图 2-13 入库、出库模块数据处理图
图 2-14 顾客管理数据处理图
图 2-15 厨师分配数据处理图
图 2-16 厨师分配数据处理图
四、开发技术介绍
4.1 pymssql 介绍
python 在使用嵌入式 SQL 语言时,必须与数据库进行连接,如果不进行连接的话,嵌入在 python 中的 SQL 语句无法执行的,而 python 又不能自动与数据库相连,它需要在 pymssql 的帮助下与数据库建立连接.另外使用 pymssql 可以不用深入的了解所访问的数据库系统,而只是需要所访问的数据库名字,数据表名和字段即可对数据库进行访问 pymssql 是用于执行 SQL 的 python API。
4.1.1 配置环境
Pip install pymssql
4.1.2 连接 MSSQL
代码如下:
import pymssql
conn = pymssql.connect(
host='127.0.0.1',
user='123',
password='123',
database='s1',
)
cursor = conn.cursor()
cursor.execute(SQL)
cursor.close()
conn.commit()
conn.close()
4.2 PyQt5 介绍
PyQt5 是对 Qt 所有类的 Python 封装,即可以利用 Qt 的强大功能,也可以利用 Python 丰富的生态,同时能够结合 Python 简洁的语法进行操作,其结果就是使用 PyQt5 可以高效简单地开发出自己想要的程序
4.2.1 配置环境
Pip install PyQt5
五、系统设计
5.1 系统目标
本书店销售管理子系统基于 B/S 结构,可以做到信息的规范管理和快速查询,实现书店现代化销售、管理.本系统通过进入身份不同,实现不同的功能
5.2 系统功能划分
图 4-1 整体功能图
5.3 模块简介及功能
5.3.1 图书管理模块
管理员使用,能够实现图书的增、删、改、查,对图书进行批量操作,
图 4-2 图书管理
5.3.2 顾客管理模块
销售人员使用,添加临时顾客信息,会员信息添加、修改,查看
图 4-2 顾客管理
5.3.3 销售模块
对销售、退货的信息进行记录
5.3.4 图书查询模块
在此模块中,定义了不同的图书查询模块.
图 4-2 图书查询
图 4-2 销售记录查看
5.3.5 人员信息管理
管理员对销售人员进行管理(增、删、改、查),管理员修改密码,销售人员修改自己的密码
5.3.6 销售统计模块
对销售记录进行统计.
5.4 业务流程图
图 4-9 系统业务流程图
六、数据库设计
6.1 数据库概要设计
6.1.1 系统 E-R 图
系统 E-R 图可以将各个实体之间的关系显示出来,将各个实体间的属性依赖表示明白.
6.2 数据库逻辑设计
数据库的逻辑设计决定了数据库与其应用的整体性能和调优位置.根据上面的 E-R 图,进一步规范设计,得到本系统的关系模式,如下.
- 图书(图书编号,书名,作者,价格,种类,出版社,库存量)
- 顾客(顾客编号,姓名,性别,电话号码,出生日期,积分)
- 售货员(售货员编号,姓名,性别,密码)
- 管理员(管理员编号,姓名,性别,密码)
- 售货记录(日期,单号,书号,会员号,售货员号,价格,数量,时间)
- 退货记录(日期,单号,书号,会员号,售货员号,价格,数量,时间)
- 入库记录(管理员号,书号,时间日期,数量)
- 出库记录(管理员号,书号,时间日期,数量)
6.3 数据库物理设计
综合以上分析,要实现上面的所有功能模块,共需要设计八个表,它们分别是:图书信息表,顾客信息表,售货员信息表,管理员信息表,售货记录表,退货记录表,入库信息表,出库记录表
表 5-1 图书信息表(Book)
字段名 | 描述 | 数据类型 | 数据长度 | NULL | Primarykey |
---|---|---|---|---|---|
Bno | 图书编号 | char | 10 | N | Y |
Bname | 书名 | varchar | 20 | N | N |
Bauthor | 作者 | varchar | 20 | N | N |
Bprice | 价格 | money | N | N | |
Btype | 种类 | varchar | 10 | Y | N |
Bpublish | 出版社 | varchar | 20 | Y | N |
Bnum | 库存量 | int | Y | N |
表 5-2 顾客信息表(Menber)
字段名 | 描述 | 数据类型 | 数据长度 | NUL | Primarykey |
---|---|---|---|---|---|
Mno | 会员编号 | char | 15 | N | Y |
Mname | 姓名 | varchar | 20 | Y | N |
Msex | 性别 | char | 2 | Y | N |
Mtel | 电话号码 | varchar | 11 | Y | N |
Mbir | 出生日期 | Date | Y | N | |
Mintegration | 积分 | Int | Y | N |
表 5-3 销售员表(SalesMan)
字段名 | 描述 | 数据类型 | 数据长度 | NULL | Primarykey |
---|---|---|---|---|---|
SMno | 售货员编号 | char | 10 | N | Y |
SMname | 姓名 | varchar | 20 | N | N |
SMsex | 性别 | char | 2 | Y | N |
SMpassword | 密码 | varchar | 13 | Y | N |
表 5-4 管理员表(Admonistrator)
字段名 | 描述 | 数据类型 | 数据长度 | NULL | Primarykey |
---|---|---|---|---|---|
Ano | 管理员编号 | char | 10 | N | Y |
Aname | 姓名 | varchar | 20 | N | N |
Asex | 性别 | char | 2 | Y | N |
Apassword | 密码 | varchar | 13 | Y | N |
表 5-5 销售表(SalesRecords)
字段名 | 描述 | 数据类型 | 数据长度 | NULL | Primarykey |
---|---|---|---|---|---|
SRdate | 日期 | date | N | Y | |
SRno | 单号 | char | 10 | N | Y |
Bno | 书号 | char | 10 | N | Y and F |
Mno | 会员号 | char | 15 | N | Y and F |
SMno | 售货员号 | char | 10 | N | Y and F |
SRprice | 价格 | money | Y | N | |
SRnum | 数量 | int | Y | N | |
SRtime | 时间 | time | Y | N |
表 5-6 退货表(cook)
字段名 | 描述 | 数据类型 | 数据长度 | NULL | Primarykey |
---|---|---|---|---|---|
BRdate | 日期 | date | N | Y | |
BRno | 单号 | char | 10 | N | Y |
Bno | 书号 | char | 10 | N | Y and F |
Mno | 会员号 | char | 15 | N | Y and F |
SMno | 售货员号 | char | 10 | N | Y and F |
BRprice | 价格 | money | Y | N | |
BRnum | 数量 | int | Y | N | |
BRtime | 时间 | time | Y | N |
表 5-7 图书入库表(ManageStockRecords)
字段名 | 描述 | 数据类型 | 数据长度 | NULL | Primarykey |
---|---|---|---|---|---|
MSdatetime | 时间日期 | smalldatetime | N | Y | |
Ano | 管理员号 | char | 10 | N | Y and F |
Bno | 书号 | date | 10 | N | Y and F |
MSnum | 数量 | int | Y | N |
表 5-8 图书退货表(ManageBackRecords)
字段名 | 描述 | 数据类型 | 数据长度 | NULL | Primarykey |
---|---|---|---|---|---|
MBdatetime | 时间日期 | smalldatetime | N | Y | |
Ano | 管理员号 | char | 10 | N | Y and F |
Bno | 书号 | date | 10 | N | Y and F |
MBnum | 数量 | int | Y | N |
七、数据库实施
7.1 数据库构建
7.1.1 数据说明表
表 6-1 数据说明表
编号 | 数据表名称 | 类型 | 内容 |
---|---|---|---|
1 | Book | 主表 | 图书信息 |
2 | Member | 主表 | 顾客信息 |
3 | SalesMan | 主表 | 销售人员信息 |
4 | Administrator | 主表 | 管理员信息 |
5 | SalesRecords | 主表 | 销售信息 |
6 | BackRecords | 主表 | 退货信息 |
7 | ManageStockRecords | 主表 | 入库信息 |
8 | ManageBackRecords | 主表 | 出库信息 |
7.1.2 数据库创建(使用 SQL 语句的数据库模型)
USE BookStore
CREATE TABLE Book(
Bno CHAR(10) NOT NULL PRIMARY KEY,
Bname NVARCHAR(20) NOT NULL,
Bauthor VARCHAR(20) NOT NULL,
Bprice MONEY NOT NULL,
Btype VARCHAR(10),
Bpublish VARCHAR(20),
Bnum INT,
)
CREATE TABLE Member(
Mno CHAR(15) NOT NULL PRIMARY KEY,
Mname VARCHAR(20),
Msex CHAR(2) CHECK (Msex IN('男','女')),
Mtel VARCHAR(11),
Mbir DATE,
Mintegration INT,
)
CREATE TABLE SalesMan(
SMno CHAR(10) NOT NULL PRIMARY KEY,
SMname VARCHAR(20) NOT NULL,
SMsex CHAR(2) CHECK (SMsex IN('男','女')),
SMpassword VARCHAR(13),
)
CREATE TABLE Administrator(
Ano CHAR(10) NOT NULL PRIMARY KEY,
Aname VARCHAR(20) NOT NULL,
Asex CHAR(2) CHECK (Asex IN('男','女')),
Apassword VARCHAR(13),
)
CREATE TABLE SalesRecords(
SRdate DATE NOT NULL,
SRno CHAR(10) NOT NULL,
Bno CHAR(10) NOT NULL,
Mno CHAR(15) NOT NULL,
SMno CHAR(10) NOT NULL,
SRprice MONEY,
SRnum INT,
SRtime TIME,
PRIMARY KEY(SRdate, SRno, Bno, Mno, SMno),
CONSTRAINT FK_SR_Bno FOREIGN KEY(Bno) REFERENCES Book(Bno),
CONSTRAINT FK_SR_Mno FOREIGN KEY(Mno) REFERENCES Member(Mno),
CONSTRAINT FK_SR_SMno FOREIGN KEY(SMno) REFERENCES SalesMan(SMno),
)
CREATE TABLE BackRecords(
BRdate DATE NOT NULL,
BRno CHAR(10) NOT NULL,
Bno CHAR(10) NOT NULL,
Mno CHAR(15) NOT NULL,
SMno CHAR(10) NOT NULL,
BRprice MONEY,
BRnum INT,
BRtime TIME,
PRIMARY KEY(SRdate, BRno, Bno, Mno, SMno),
CONSTRAINT FK_BR_Bno FOREIGN KEY(Bno) REFERENCES Book(Bno),
CONSTRAINT FK_BR_Mno FOREIGN KEY(Mno) REFERENCES Member(Mno),
CONSTRAINT FK_BR_SMno FOREIGN KEY(SMno) REFERENCES SalesMan(SMno),
)
CREATE TABLE ManageStockRecords(
MSdatetime SMALLDATETIME NOT NULL,
Ano CHAR(10) NOT NULL,
Bno CHAR(10) NOT NULL,
MSnum INT,
PRIMARY KEY( MSdatetime,Ano, Bno),
CONSTRAINT FK_MS_Ano FOREIGN KEY(Ano) REFERENCES Administrator(Ano),
CONSTRAINT FK_MS_Bno FOREIGN KEY(Bno) REFERENCES Book(Bno),
)
CREATE TABLE ManageBackRecords(
MBdatetime SMALLDATETIME NOT NULL,
Ano CHAR(10) NOT NULL,
Bno CHAR(10) NOT NULL,
MBnum INT,
PRIMARY KEY(Mbdatetime, Ano, Bno),
CONSTRAINT FK_MB_Ano FOREIGN KEY(Ano) REFERENCES Administrator(Ano),
CONSTRAINT FK_MB_Bno FOREIGN KEY(Bno) REFERENCES Book(Bno),
)
-- book
CREATE INDEX IX_Book_Bno ON Book(Bno)
CREATE INDEX IX_Book_Bname ON Book(Bname)
CREATE INDEX IX_Book_Bauthor ON Book(Bauthor)
CREATE INDEX IX_Book_Btype ON Book(Btype)
CREATE INDEX IX_Book_Bpublish ON Book(Bpublish)
-- member
CREATE INDEX IX_Member_Mno ON Member(Mno)
CREATE INDEX IX_Member_Mname ON Member(Mname)
CREATE INDEX IX_Member_Mtel ON Member(Mtel)
-- MSR MBR
CREATE INDEX IX_MSR_DateTime ON ManageStockRecords(MSdatetime)
CREATE INDEX IX_MBR_DateTime ON ManageBackRecords(MBdatetime)
-- BR SR
CREATE INDEX IX_SR_Date ON SalesRecords(SRdate)
CREATE INDEX IX_BR_Date ON BackRecords(BRdate)
--触发器
CREATE TRIGGER TG_SR_ADD
ON SalesRecords
AFTER INSERT
AS
UPDATE Book SET Bnum = Bnum - inserted.SRnum
FROM Book, inserted
WHERE Book.Bno = inserted.Bno
CREATE TRIGGER TG_BR_DEC
ON BackRecords
AFTER INSERT
AS
UPDATE Book SET Bnum=Bnum + inserted.BRnum
FROM Book,inserted
WHERE Book.Bno = inserted.Bno
CREATE TRIGGER TG_MSR_ADD
ON ManageStockRecords
AFTER INSERT
AS
UPDATE Book SET Bnum=Bnum + inserted.MSnum
FROM Book,inserted
WHERE Book.Bno = inserted.Bno
CREATE TRIGGER TG_MBR_DEC
ON ManageBackRecords
AFTER INSERT
AS
UPDATE Book SET Bnum=Bnum - inserted.MBnum
FROM Book,inserted
WHERE Book.Bno = inserted.Bno
CREATE TRIGGER TG_MemI_ADD
ON SalesRecords
AFTER INSERT
AS
UPDATE Member SET Mintegration=Mintegration + inserted.SRnum * inserted.SRprice
FROM Member,inserted
WHERE Member.Mno = inserted.Mno
CREATE TRIGGER TG_MemI_DEC
ON BackRecords
AFTER INSERT
AS
UPDATE Member SET Mintegration=Mintegration - inserted.BRnum * inserted.BRprice
FROM Member,inserted
WHERE Member.Mno = inserted.Mno
7.2 数据库迁移和导入方案
7.2.1 数据库迁移
通过 msSQL 中相应的数据库进行分离,得到数据文件.方便迁移
7.2.2 数据库导入
把相应文件附加到数据库
八、系统界面设计和后台代码
8.1 系统界面设计
本系统的界面主要用 QT + PyQt5 等技术,力求界面美观大方、友好易用.详细如下:
8.1.1 登录模块界面
该界面为系统的登陆窗口,要求输入账号、密码、或直接以游客方式进入.。如图 7-1:
图 7-1 登陆界面
8.1.2 管理员界面
该界面为管理员界面,是管理员登录后进入的界面,其中有六个小界面,每个界面能够完成相应的功能。如图 7-2 ~7-6:
图 7-2 管理员界面
8.1.3 售货员界面
为售货员使用的界面,点击对应键即可进入实现对应功能的界面,如图 7-7
8.1.4 图书查找界面
该界面为图书查找界面,也是游客能够直接进入的界面。通过该界面能够通过不同的方式快速搜索图书,并显示在表格中,最多 50 条,(如图 7-8),若多于 50 条,则可通过点击显示所有查看数据(图 7-9)
图 7-7 图快搜索界面
图 7-9 显示所有数据界面
8.1.5 图书管理模块界面
图书管理模块包括(图 7-10):图书的增加(7-12),删除(7-13),修改(图 7-11)功能,能与图书搜索界面共存(图 7-11),快速定位图书。通过控制按键的隐藏、显示方便实现对应的功能
图 7-10 全图功能
图 7-11 修改功能及查询并列
图 7-12 添加
图 7-13 删除
8.1.6 销售人员管理模块
销售人员管理模块包括(图 7-14):销售人员的增加,删除,修改功能,能与销售人员显示界面共存。通过控制按键的隐藏、显示方便实现对应的功能,具体布局与图书管理模块类似
图 7-14 添加
8.1.7 信息查看模块
该模块为管理员查看对应信息的模块,点击对应按钮即可在表中显视对应的信(图 7-6)。
8.1.8 购买模块
该模块为购买模块,也是系统的一个核心模块(图 7-15),在该模块实现购买图书功能,点击对应书号即可显示对应的书籍信息,输入书号也会根据是否会员及会员信息生成一个黑夜的单价,生成默认的数量 1。输入完成后会进入数据的合理性检查,若数据输入错误,则清空当前输入的数据。若输入的书号已存在,则在原书号的数量上加 1。数据无法隔行输入。自却生成单号、时间,存入数据库
图 7-14 添加
8.1.9 退货模块
顾客退货,输入基本退货信息,录入退货信息(7-15)。
8.2 主要模块代码
8.2.1 数据处理
参数处理,把对应的参数处理成 SQL 语句
@staticmethod
def insert_parameter_deal(where, *args):
"""
:param self:
:param where: str 插入的表名
:param args: 插入参数列表
:return: str 嵌入语句,可直接使用
"""
# print("参数处理", where, args)
exc = "INSERT INTO " + where + " VALUES " + str(args)
print("参数处理", exc)
return str(exc)
@staticmethod
def select_parmeter_deal(table_name, ** kwargs):
"""
查询参数处理
:param table_name:表名
:param kwargs: a = b and a1 = b1 and a2 = b2
:return:
"""
a = 'SELECT * FROM ' + table_name + " WHERE "
b = ' 1 = 1 '
for i in kwargs:
b = b + ' AND ' + str(i) + ' = ' + str(kwargs[i])
return a + b
@staticmethod
def updata_parmeter_deal(table_name='', set={}, where={}):
update = "UPDATE " + table_name + ' SET '
a = ''
for i, j in set.items():
a = a + ', ' + (str(i)) + ' = ' + DbDesignBase.str_add_quotation(str(j))
a = a + ' WHERE '
b = ''
for i, j in where.items():
b = b + ', ' + (str(i)) + ' = ' + DbDesignBase.str_add_quotation(str(j))
a = re.sub(r"^, ", ' ', a)
b = re.sub(r"^, ", ' ', b)
return update + a + b
@staticmethod
def delete_parmeter_deal(table_name, ** kwargs):
a = 'DELETE FROM ' + table_name + " WHERE "
b = ' 1 = 1'
print(kwargs)
for i in kwargs:
b = b + ' AND ' + str(i) + ' = ' + str(kwargs[i])
return a + b
数据有效性判断,判断输入数据是否正确
@staticmethod
def is_money(string):
if re.match(r'^[1-9][0-9]*$|^[1-9][0-9]*\.[0-9]+$|^0\.[0-9]+$', str(string)):
return True
else:
return False
@staticmethod
def is_no(string):
if re.match(r'^\d{4,11}$', str(string)):
return True
else:
return False
@staticmethod
def is_sale_num(string):
if re.match(r'^[1-9]\d{0,2}$', str(string)):
return True
else:
return False
@staticmethod
def is_tel(string):
if re.match(r'^1\d{10}$|^\d{7,8}$', str(string)):
return True
else:
return False
@staticmethod
def is_name(string):
if re.match(r'^[\u4e00-\u9fa5]{2,4}$', str(string)):
return True
else:
return False
@staticmethod
def is_num(string):
if re.match((r'^[1-9]\d*$'), str(string)):
return True
else:
return False
@staticmethod
def insert_data_check_book(Bno, Bname, Bauthor, Bprice, Btype, Bpublish, Bnum):
flag = 0
if re.match(r'^\d{4,11}$',Bno):
flag |= 1 << 0
# print('Bno')
if re.match(r'\S', Bname):
flag |= 1 << 1
# print('Bname')
if re.match(r'\S', Bauthor):
flag |= 1 << 2
# print('Bauthor')
if re.match(r'^[1-9][0-9]*$|^[1-9][0-9]*\.[0-9]+$|^0\.[0-9]+$',Bprice):
flag |= 1 << 3
# print('Bprice')
type = r'^经典名著$|^专业图书类$|^古典文学$|^外国文学$|^现当代文学$|^历史地理类$|^哲学类$|^社会科学类$|^玄幻文学$|^儿童文学$'
if re.match(type, Btype):
flag |= 1 << 4
# print('Btype')
if re.match(r'\S+出版社$', Bpublish):
flag |= 1 << 5
# print('Bpublish')
if re.match(r'0$|[1-9]\d*$', Bnum):
flag |= 1 << 6
# print('Bnum')
if flag == 0x7F :
flag = 0xff
print(flag)
return flag
8.2.2 登录模块
确认登录系统的身份
def login(self):
print("login")
type = 0
if self.time == 10:
print("root")
type = self.WIN_EXTERN_ROOT
elif self.radioButton_Admini.isChecked():
print("Admini")
type = self.WIN_EXTERN_ADMINI
elif self.radioButton_cust.isChecked():
print("Salesman")
type = self.WIN_EXTERN_SALEMAN
username = self.username.text()
password = self.password.text()
if username == '' and password == '':
self.time += 1
self.label_warning.clear()
if self.time == 5:
self.pushButton_hide.setEnabled(True)
elif self.time > 5:
self.pushButton_hide.setEnabled(False)
self.time = 0
return 0
# 连按处理
import time
counter = time.perf_counter()
space_time = counter - self.perf_counter
print(space_time)
if space_time < 1.5:
return 0
self.perf_counter = counter
import DbSelect
Db = DbSelect.DbSelect()
if type == self.WIN_EXTERN_ADMINI:
# 管理员
Db.select_administrator()
elif type == self.WIN_EXTERN_SALEMAN:
# 销售员
Db.select_salesman()
elif type == self.WIN_EXTERN_ROOT:
# sa 帐户
if username == 'sa' and password == '123':
return type
table_date = Db.cursor_data_to_list()
for i in table_date:
if i[0].strip() == username and i[3].strip() == password:
self.label_warning.setText("登录成功")
return type
self.label_warning.setText("用户名或密码错误,请重新输入")
self.time = 0
return 0
8.2.3 图书管理模块
实现图书的增删改
def on_pushButton_del_released(self):
print('on_pushButton_del_released')
bno = self.lineEdit_bno_3.text()
if bno == '':
return
self.pushButton_del.setEnabled(False)
flag = self.dialog_yes_no("是否删除?", "确认")
if flag is True:
if self.dbcur.delete_book(bno):
self.dialog_text("删除成功","提示窗")
self.data_clear_widget_3()
self.pushButton_del.setEnabled(False)
else:
self.dialog_text("删除失败 可能存在外键限制","提示窗")
def on_pushButton_add_released(self):
print("on_pushButton_add_released")
self.pushButton_add.setEnabled(False)
flag = self.dialog_yes_no("是否添加","提示")
if flag is True:
flag = self.dbcur.book_insert(
self.lineEdit_bno.text().strip(),
self.lineEdit_bname.text().strip(),
self.lineEdit_bauthor.text().strip(),
self.lineEdit_bprice.text().strip(),
self.comboBox_btype.currentText().strip(),
self.lineEdit_bpublish.text().strip(),
self.lineEdit_bnum.text().strip(),
)
if flag is True:
self.dialog_text("添加成功", "提示")
self.widget_3.setEnabled(True)
else:
self.dialog_text("添回失败 可能主键冲突", "提示")
else:
self.pushButton_add.setEnabled(True)
def on_pushButton_change_released(self):
print('on_puchButton_change_released')
self.pushButton_change.setEnabled(False)
set = self.get_set_parmeter()
print(set)
if len(set) == 0:
self.dialog_text("内容未做变更", '提示')
else:
if self.dialog_yes_no("确认修改", "确认") is True:
updata = self.dbcur.updata_parmeter_deal('Book', set, {'Bno':self.lineEdit_bno.text().strip()})
# print(updata)
if self.dbcur.update_run_exec(updata):
self.dialog_text("修改成功", '提示')
else:
self.dialog_text("修改失败", '提示')
else:
self.widget.setEnabled(True)
self.pushButton_pre_view.show()
self.pushButton_pre_view_cancel.hide()
8.2.4 图书购买模块
def buy_deal(self):
# 购买操作处理
self.dbcur.select_run_exec("SELECT TOP 1 * FROM SalesRecords ORDER BY SRdate DESC")
table = self.dbcur.cursor_data_to_list()
crrurent_date = str(QDateTime.toPyDateTime(self.dateTimeEdit_buy.dateTime()).date())
crrurent_time = str(QDateTime.toPyDateTime(self.dateTimeEdit_buy.dateTime()).time())
last_data = table[0][0]
if crrurent_date == last_data:
# 当天存在记录
srno = int(table[0][1])
print("srno", srno)
srno = srno + 1
srno = '000000' + str(srno)
srno = srno[len(srno) - 6:]
mno = ''
if self.checkBox_buy_is_member.isChecked():
mno = self.mno
else:
x = crrurent_date.split('-')
mno = 'C' + x[0] + x[1] + x[2] + srno
print("mno", mno, srno)
exec = "INSERT INTO Member VALUES ( '" + mno + "', NULL, NULL, NULL, NULL, NULL)"
self.dbcur.insert("Member", exec)
else:
# 当前不存在
srno = '000001'
if self.checkBox_buy_is_member.isChecked():
mno = self.mno
else:
x = crrurent_date.split('-')
mno = 'C' + x[0] + x[1] + x[2] + srno
exec = "INSERT INTO Member VALUES ( '" + mno + "', NULL, NULL, NULL, NULL, NULL)"
self.dbcur.insert("Member", exec)
for i in self.buy_book:
if i[0]:
self.dbcur.sales_records_insert(srno, i[0], mno, self.sMno, i[1], i[2], crrurent_time, crrurent_date,)
def on_tableWidget_buy_info_currentCellChanged(self,i, j, m, n):
# 表格信息处理
print('on_tableWidget_buy_info_currentCellChanged', i, j, m, n)
self.label_buy_input_hint.setText("")
if m == -1:
return
if m != 0 :
# 本行上一行数据为空 无法输入数据
item = self.tableWidget_buy_info.item(m - 1, 0)
if item is None or str(item.text()) == '':
if self.tableWidget_buy_info.item(m, n) is not None:
self.tableWidget_buy_info.item(m, n).setText('')
return
elif item.text()=="":
return
# 本行第一列内容为空 无法输入数据
item = self.tableWidget_buy_info.item(m, 0)
if item is None or item.text().strip == '':
if self.tableWidget_buy_info.item(m ,n) is not None:
self.tableWidget_buy_info.item(m, n).setText('')
return
item = self.tableWidget_buy_info.item(m, n)
if item is None or item.text() == '':
# self.dialog_text("未输入数据")
self.label_buy_input_hint.setText("未输入数据")
return
if n == 0:
# 书号
if j == 0 or m != i:
pass
else:
# 输入书号后输入
bno = item.text()
bno = self.dbcur.str_add_quotation(bno)
print(bno)
exec = self.dbcur.select_parmeter_deal('Book', Bno = bno)
self.dbcur.run_exec(exec)
table = self.dbcur.select_cursor_data_to_list()
if len(table):
# 书号存在
# print(table)
for i in range(50):
item = self.tableWidget_buy_info.item(i, 0)
if item == None or item.text() == '' or i == m:
# 书籍未输入过
self.buy_book[m][0] = item.text()
bprice = float(table[0][3])
bprice = bprice * self.discount / 10
item = QtWidgets.QTableWidgetItem(str(bprice)) # 单价
self.tableWidget_buy_info.setItem(m, 1, item)
self.buy_book[m][1] = item.text()
item = QtWidgets.QTableWidgetItem('1') # 数量
self.tableWidget_buy_info.setItem(m, 2, item)
self.buy_book[m][2] = item.text()
self.buy_book[m][3] = table[0][3]
break
elif str(item.text()).strip() == str(table[0][0]).strip():
print(item.text(), table[0][0])
# 本书已经输入过
bnum = int(self.tableWidget_buy_info.item(i, 2).text())
bnum = bnum + 1
self.tableWidget_buy_info.item(i, 2).setText(str(bnum))
self.tableWidget_buy_info.item(m, 0).setText('')
self.buy_book[i][2] = bnum
break
else:
self.label_buy_input_hint.setText("该书不存在")
self.tableWidget_buy_info.item(m,n).setText('')
elif n == 1:
# 金额
bprice = item.text()
if self.dbcur.is_money(bprice):
self.buy_book[m][n] = bprice
else:
self.label_buy_input_hint.setText("金额输入格式错误")
item.setText('')
elif n == 2:
# 数量
bnum = item.text()
if self.dbcur.is_sale_num(bnum):
self.buy_book[m][n] = bnum
else:
self.label_buy_input_hint.setText("数量格式错误或数量过大")
item.setText('')
# print(self.buy_book)
money = self.cal_all_price()
self.label_buy_allprice.setText(str("%.2f"%money))
8.2.5 密码修改模块
def on_pushButton_ensure_released(self):
print('on_pushButton_ensure_released')
if self.lineEdit_new1.text()!=self.lineEdit_new2.text():
self.dialog_text('再次输入密码不一样')
return
elif self.lineEdit_old.text()!=self.tabel[0][3]:
self.dialog_text('旧密码错误')
return
else:
if self.dialog_yes_no("确认修改?"):
exec = self.dbcur.updata_parmeter_deal('SalesMan',
{'SMpassword':self.lineEdit_new1.text()},
{'SMno':self.tabel[0][0]})
if self.dbcur.update_run_exec(exec):
self.dialog_text("修改成功")
self.init()
else:
self.dialog_text('修改失败')
else:
pass
九、安装使用和说明
安装说明
安装 python
要求使用 python3,python 可能存在部分问题
安装插件
pip install PyQt5, 用于生成 UI
pip install pymssql 用于连接数据库
附加数据库
运行文件内的 SQL 文件。
运行
运行文件内的 main.py 文件
结论与展望
本系统完成了任务书中要求的全部内容。参考任务书。
系统还存在着一些缺陷,功能并不是十分完善. 如果还有更多时间可以维护和修改的话,我希望能实现后端通信,因为本项目各个角色的交互方式主要是依赖监听数据库变化进行的,这在用户多的时候,并发性会降低。
在今后的研究学习中,将会对以上问题进行改进,并且对整个框架精益求精,进一步满足用户需求,使开发更具有意义。
参考文献
- 钱雪忠,李京. 数据库系统原理及应用[M]. 北京:北京邮电大学出版社,2010.
- 钱雪忠,陈国俊. 数据库系统原理及应用实验指导[M]. 北京:北京邮电大学出版社,2010
- Eric Matthes. Python 编程从入门到实践[M]. 北京:北京邮电出版社