zl程序教程

您现在的位置是:首页 >  后端

当前栏目

基于Python+Mysql实现(WinForm)书店销售管理管理子系统【100010028】

PythonmysqlWinform 实现 管理 基于 销售
2023-09-11 14:17:50 时间

书店销售管理管理子系统

一、设 计 总 说 明

现在社会随着计算机技术迅速发展与技术的逐渐成熟,信息技术已经使人们的生活发生深刻的变化。生活中的各种服务系统也使人们在生活中的联系日常销售活动方式发生了很大的变化,让效率较低的手工操作成为过去,而换成信息化自动化的计算机操作。本系统是针对某一小型书店而设计的书店管理信息系统,本 系统的后台数据库选择 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 系统功能划分

在这里插入图片描述

图 5-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)

字段名描述数据类型数据长度NULLPrimarykey
Bno图书编号char10NY
Bname书名varchar20NN
Bauthor作者varchar20NN
Bprice价格moneyNN
Btype种类varchar10YN
Bpublish出版社varchar20YN
Bnum库存量intYN

表 5-2 顾客信息表(Menber)

字段名描述数据类型数据长度NULPrimarykey
Mno会员编号char15NY
Mname姓名varchar20YN
Msex性别char2YN
Mtel电话号码varchar11YN
Mbir出生日期DateYN
Mintegration积分IntYN

表 5-3 销售员表(SalesMan)

字段名描述数据类型数据长度NULLPrimarykey
SMno售货员编号char10NY
SMname姓名varchar20NN
SMsex性别char2YN
SMpassword密码varchar13YN

表 5-4 管理员表(Admonistrator)

字段名描述数据类型数据长度NULLPrimarykey
Ano管理员编号char10NY
Aname姓名varchar20NN
Asex性别char2YN
Apassword密码varchar13YN

表 5-5 销售表(SalesRecords)

字段名描述数据类型数据长度NULLPrimarykey
SRdate日期dateNY
SRno单号char10NY
Bno书号char10NY and F
Mno会员号char15NY and F
SMno售货员号char10NY and F
SRprice价格moneyYN
SRnum数量intYN
SRtime时间timeYN

表 5-6 退货表(cook)

字段名描述数据类型数据长度NULLPrimarykey
BRdate日期dateNY
BRno单号char10NY
Bno书号char10NY and F
Mno会员号char15NY and F
SMno售货员号char10NY and F
BRprice价格moneyYN
BRnum数量intYN
BRtime时间timeYN

表 5-7 图书入库表(ManageStockRecords)

字段名描述数据类型数据长度NULLPrimarykey
MSdatetime时间日期smalldatetimeNY
Ano管理员号char10NY and F
Bno书号date10NY and F
MSnum数量intYN

表 5-8 图书退货表(ManageBackRecords)

字段名描述数据类型数据长度NULLPrimarykey
MBdatetime时间日期smalldatetimeNY
Ano管理员号char10NY and F
Bno书号date10NY and F
MBnum数量intYN

七、数据库实施

7.1 数据库构建

7.1.1 数据说明表

表 6-1 数据说明表

编号数据表名称类型内容
1Book主表图书信息
2Member主表顾客信息
3SalesMan主表销售人员信息
4Administrator主表管理员信息
5SalesRecords主表销售信息
6BackRecords主表退货信息
7ManageStockRecords主表入库信息
8ManageBackRecords主表出库信息

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 管理员界面

图 7-3 图 7-4

图 7-5 图 7-6

图 7-6

图 7-7

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)。

图 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 文件

结论与展望

本系统完成了任务书中要求的全部内容。参考任务书。

系统还存在着一些缺陷,功能并不是十分完善. 如果还有更多时间可以维护和修改的话,我希望能实现后端通信,因为本项目各个角色的交互方式主要是依赖监听数据库变化进行的,这在用户多的时候,并发性会降低。

在今后的研究学习中,将会对以上问题进行改进,并且对整个框架精益求精,进一步满足用户需求,使开发更具有意义。

♻️ 资源

在这里插入图片描述

大小: 1.19MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87248124