-
- 系统具体需求
1)采购计划管理:由物料部门接受物料清单,结合库存和提前期的MRP计算,形成物料需求计划,然后对采购计划进行调整,审核后下发
- 采购管理:采购管理是采购任务分配,询价审价,采购合同签订和接受采购发票等采购活动的全过程
- 入库管理:由采购员填写入库申请,保管员对物资名称,规格,数量,质量等验收之后办理实收入库手续
- 出库管理:保管员根据各个部门提出的领料申请单,完成物资的实发工作
1.3 系统数据流图
1.3.1 顶层数据流图
1.3.2 零层数据流图
…
采购计划管理0层
库存管理0层图
2 数据库设计
2.1 概念结构设计ER图
在上述图中,部分对应关系解释如下:
- 员工与部门是一对多的关系,一个员工只能来自一个部门,但是一个部门可以拥有多名员工
- 合同与员工,任务单物资和供应商,合同被员工编写,由部门领导审核,合同涉及供应商编号,物资编号
- 入库,出库中,是由员工或者领料部门发起,和仓库之间对应
2.3 逻辑结构设计
2.3.1 表清单
实体名称 | 中文注释 |
Employee | 员工信息表 |
Department(实体领料部门用的也是这个表) | 部门信息表 |
Material | 物资信息表 |
仓库信息表 | |
Supply | 供应商信息表 |
contract | 合同信息表 |
Task | 任务单 |
Enquiry | 询价单 |
rk | 入库单 |
ck | 出库单 |
2.3.2 表设计
(1)Employee表
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
eID | int | 10 | no | yes | 员工号 |
eName | varchar | 50 | no | no | 员工姓名 |
dNo | varchar | 30 | no | no | 部门编号 |
(2)Department表
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
dNo | int | 10 | no | yes | 部门编号 |
dName | varchar | 50 | no | no | 部门名称 |
(3)Material表
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
mID | int | 10 | no | yes | 物资编号 |
mName | varchar | 50 | no | no | 物资名称 |
mGg | varchar | 30 | no | no | 物资规格 |
mXh | varchar | 50 | no | no | 物资型号 |
jldw | varchar | 50 | no | no | 计量单位 |
- Warehouse表
- Supply表
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
wID | int | 10 | no | yes | 仓库编号 |
wName | varchar | 50 | no | no | 仓库名称 |
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
sID | int | 10 | no | yes | 供应商编号 |
sName | varchar | 50 | no | no | 供应商名称 |
(6)Task表
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
Tasknumber | int | 10 | no | yes | 任务单号 |
mID | int | 10 | no | no | 物资编号 |
Requiredquantity | Int | 10 | no | no | 需求数量 |
Requiredtime | date | 20 | no | no | 需求时间 |
Procurementtime | date | 20 | no | no | 采购时间 |
Quantitypurchased | Int | 10 | no | no | 采购数量 |
eID | int | 10 | no | no | 采购员编号 |
(7)enquiry表
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
enquirynumber | int | 10 | no | yes | 询价单号 |
mID | int | 10 | no | no | 物资编号 |
sID | int | 10 | no | no | 供应商编号 |
Equantity | Int | 10 | no | no | 购买数量 |
[unit price] | decimal(4, 1) | 20 | no | no | 商品单价 |
Eexpense | decimal(5, 1) | 10 | no | no | 总计花费 |
(8)store表
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
sID | int | 10 | no | yes | 库存单号 |
mID | int | 10 | no | no | 物资编号 |
mName | Varchar(20) | 20 | no | no | 物资名称 |
mDate | Date | 10 | no | no | 库存所属月份 |
mQuantity | Int | 20 | no | no | 库存数量 |
wID | int | 10 | no | no | 仓库编号 |
(9)rk表
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
rID | int | 10 | no | yes | 入库单号 |
mID | int | 10 | no | no | 物资编号 |
rApplyQuantity | Int | 20 | no | no | 申请入库数量 |
rDate | Date | 10 | no | no | 入库时间 |
rQuantity | Int | 20 | no | no | 实际入库数量 |
sID | int | 10 | no | no | 供应商编号 |
eIDBg | Int | 10 | No | No | 保管员编号 |
eIDSq | Int | 10 | No | No | 申请员编号 |
contractnumber | Int | 10 | No | No | 合同单号 |
wID | int | 10 | no | no | 仓库编号 |
(9)ck表
字段名 | 数据类型 | 长度 | 允许空 | 主键 | 说明 |
cID | int | 10 | no | yes | 出库单号 |
mID | int | 10 | no | no | 物资编号 |
cApplyQuantity | Int | 20 | no | no | 申请领料数量 |
cDate | Date | 10 | no | no | 领料时间 |
cQuantity | Int | 20 | no | no | 实际领料数量 |
Department | int | 10 | no | no | 领料部门编号 |
eIDBg | Int | 10 | No | No | 保管员编号 |
eIDSq | Int | 10 | No | No | 申请员编号 |
contractnumber | Int | 10 | No | No | 合同单号 |
wID | int | 10 | no | no | 仓库编号 |
3 数据库应用系统开发
3.1 表创建(表关系图)
3.2 索引创建(可以截图)
索引名 | 代码 |
未使用索引 |
3.3 视图创建
视图名(作用)MaterialDemandList (创建物料需求清单视图)
CREATE VIEW MaterialDemandList AS
SELECT m.mID, m.mName, m.mGg, m.mXh, m.jldw,t.Requiredquantity, t.Requiredtime
FROM Meterial m
JOIN Task t ON m.mID = t.mID;
3.4 触发器创建
触发器名(作用)
tri__update3
(入库单表中更新实收数量,对应更新库存表中该物资的库存
数量
)
create trigger tri__update3
on rk
after update
as
begin
if (update(rQuantity))
begin
update store
set mQuantity=(select sum(rQuantity) from rk r
WHERE r.mID = store.mID and
(substring(convert(varchar,rDate,112),1,6)=substring(convert(varchar,mDate,112),1,6)))
WHERE store.mID IN (SELECT DISTINCT mID FROM inserted);
end
end
tri__updateck(出库单中更新实发数量,更新对应物资的库存)
create trigger tri__updateck
on ck
after update
as
begin
if (update(cQuantity))
begin
update store
SET mQuantity = mQuantity - (SELECT cQuantity FROM inserted) from
ck c
WHERE c.mID = store.mID and
substring(convert(varchar,cDate,112),1,6)=substring(convert(varchar,mDate,112),1,6)
and store.mID IN (SELECT DISTINCT mID FROM inserted)
end
end
4 功能模块设计与实现
功能名称 | 模块名称 | 说明 |
采购计划管理 | 物料需求清单接收 | 通过调用存储过程,实现查询具体的物料需求 |
MRP量计算 | 通过调用存储过程,输入需求时间,从而得出具体的采购时间 | |
MRP期计算 | 通过调用存储过程,输入需求数量,从而得出具体的采购数量 | |
采购任务分配 | 采购任务下达 | 通过调用存储过程,实现将任务分配给员工 |
采购任务撤销 | 通过调用存储过程,实现将已经分配任务取消 | |
采购询价 | 采购订单询价 | 对多家供应商的的商品在质量无差异的前提下,选择价格最低的一家 |
采购合同 | 采购合同编制 | 通过调用存储过程,将输入的合同内容录入合同中 |
入库申请 | 合同入库申请单编制 | 合同入库申请,物资信息储存在合同中,无需填写物资编号 |
零星入库申请单编制 | 零星入库申请,物资信息储存在物资单中,无需填写合同编号 | |
库存汇总查询 | 仓库汇总查询 | 按照仓库,查询某一时间段内某物资的储存量 |
领料申请 | 限额领料申请单编制 | 限额领料申请,生产部门通过之前提交的物料需求单进行限额领料,采购部门将其所需要的物资按合同购置,物资的具体信息储存在合同单里 |
零星领料单申请单编制 | 零星领料申请,物资信息储存在物资单中,无需填写合同单号 | |
库存预警 | 库存预警查询 | 通过存储过程,查询仓库中的物资数量是否在安全库存内,如果低于安全库存,则发出提醒 |
Python调用 | Python调用存储过程 | 通过调用python实现功能的具体使用 |
4.1.1 物料需求接受
语句 | CREATE PROCEDURE GetAllMaterialDemandList AS BEGIN SELECT * FROM MaterialDemandList; END; EXEC GetAllMaterialDemandList |
执行结果 | ![]() |
4.1.2MRP计算
语句 | alter procedure MRP_caculating @MID int, @Requiredquantity int, --需求数量 @Requiredtime date --需求时间 as declare @Safetystock int;--安全库存 declare @currentstock int;--目前可用库存 declare @purchaseday int;--采购提前期 declare @Quantitypurchased int ;--采购数量 declare @Procurementtime date;--采购时间 select @Safetystock=Safetystock ,@currentstock=mQuantity ,@purchaseday=purchaseday from Meterial m ,store s where m.mID=s.mID and m.mID=@MID --set @Quantitypurchased=@Requiredquantity-@currentstock+@Safetystock --采购数量MRP计算公式 --set @Procurementtime=@Requiredtime-@purchaseday--采购时间MRP计算公式 if (@Quantitypurchased<=0)--表示当前库存可用数量大于需求数量,无需采购, set @Quantitypurchased=0 else set @Quantitypurchased=@Requiredquantity-@currentstock+@Safetystock set @Procurementtime=dateadd(day,-@purchaseday,@Requiredtime) select @Requiredquantity as 需求数量 ,@Safetystock as 安全库存, @currentstock as 目前可用库存,@Quantitypurchased as 采购数量,@Procurementtime as 采购日期 insert into Task (mID,Requiredquantity,Requiredtime,Procurementtime,Quantitypurchased ) values(@MID,@Requiredquantity,@Requiredtime,@Procurementtime,@Quantitypurchased) |
执行结 | ![]() |
4.2 采购任务分配
4.2.1 下达任务
语句 | CREATE PROCEDURE up_PushTask @streID int, @strTaskID int AS UPDATE TASK SET eID=@streID WHERE Tasknumber=@strTaskID --exec up_PushTask 826530,100003 |
执行结果 | ![]() |
4.2.2 撤销任务
语句 | alter PROCEDURE up_UndoTask @streID int, @strTaskID int AS -- 判断任务是否已分配给员工 IF EXISTS (SELECT 1 FROM TASK WHERE Tasknumber = @strTaskID AND eID = @streID) -- 撤销任务: 将eID设置为NULL,表示任务未分配 UPDATE Task SET eID = NULL WHERE Tasknumber = @strTaskID exec up_UndoTask 826530 ,100003 |
执行结果 | ![]() |
4.3 采购询价
4.3.1
语句 | alter procedure up_enquiry as select top 1 enquirynumber,mID,e.sID,sName,min(Eexpense)from enquiry e,Suppy s where e.sID=s.sID group by enquirynumber,mID,e.sID,sName order by min(Eexpense) asc exec up_enquiry |
执行结果 | ![]() |
4.4采购合同
4.4.1 采购合同编制
语句 | alter procedure up_contract @Cnumber int, @Cdate date, @eid int, @sid int , @Tasknumber int as update contract set signingdate=@Cdate,eID=@eid,sID=@sid,Tasknumber=@Tasknumber where contractnumber=@Cnumber select contractnumber 合同单号,signingdate 签订日期,eID 采购员编号,sID 供应商编号,Tasknumber 任务单号 from contract exec up_contract 300001,'2023-11-16',816530,22224180,100002 |
执行结果 | ![]() |
4.5入库申请
4.5.1 入库申请单编制
语句 | alter PROCEDURE up_rkapply @type VARCHAR(10), @rid int, @mid INT = NULL, @rdate DATE, @eidsq INT, @eidbg INT, @wid INT, @Cnumber INT = NULL AS IF @type = '合同入库' --通过条件判断是合同入库还是零星入库 UPDATE rk SET rDate = @rdate, eIDSq = @eidsq, eIDBg = @eidbg, wID = @wid, contractnumber = @Cnumber where rID=@rid --合同入库则更新合同单号而不更新物资编号 ELSE UPDATE rk SET rDate = @rdate, mID = @mid, eIDSq = @eidsq, eIDBg = @eidbg, wID = @wid where rID=@rid --零星入库则更新物资编号而不更新合同单号 SELECT @mid 物资编号, @rdate 入库日期, @eidsq 申请员编号, @eidbg 保管员编号, @wid 仓库编号, @Cnumber 合同单号 exec up_rkapply @type=合同入库,@rid=202319 ,@rdate='2023-01-11', @eidsq =826530,@eidbg=826531, @wid =4,@Cnumber=300001 |
执行结果 | ![]() |
4.6库存汇总查询
4.6.1仓库汇总查询
语句 | alter PROCEDURE GetWarehouseStorageSummary @WarehouseID INT, -- 仓库ID @StartDate DATE, -- 开始日期 @EndDate DATE -- 结束日期 AS BEGIN SELECT w.wID, s.mID , SUM(mQuantity) --(SELECT SUM(mQuantity) FROM store WHERE mDate BETWEEN @StartDate AND @EndDate) AS MaterialCount FROM Warehouse w JOIN store s ON w.wID = s.wID WHERE w.wID = @WarehouseID AND s.mDate BETWEEN @StartDate AND @EndDate GROUP BY w.wID, s.wID,s.mID END; exec GetWarehouseStorageSummary 4,'2023-01-01','2023-02-01' |
执行结果 | ![]() |
4.7领料申请
4.7.1限额领料单和零星领料单的编制
语句 | create PROCEDURE up_ckapply @type VARCHAR(10), @cid int, @mid INT = NULL, @cdate DATE, @eidsq INT, @eidbg INT, @wid INT, @department varchar(10), @Cnumber INT = NULL AS IF @type = '限额领料' --通过条件判断是生产领料还是零星领料 UPDATE ck --生产领料也等于限额领料,生产部门通过之前提交的物料需求单进行限额领料 SET cDate = @cdate, eIDSq = @eidsq, eIDBg = @eidbg, wID = @wid, department =@department,contractnumber = @Cnumber where cID=@cid --生产领料则更新合同单号而不更新物资编号 ELSE UPDATE ck SET cDate = @cdate, mID = @mid, eIDSq = @eidsq, eIDBg = @eidbg, wID = @wid ,department =@department where cID=@cid --零星领料则更新物资编号而不更新合同单号 SELECT @mid 物资编号, @cdate 出库日期, @eidsq 申请员编号, @eidbg 保管员编号, @wid 仓库编号,@department 部门编号, @Cnumber 合同单号 exec up_ckapply @type=限额领料,@cid=20230013 ,@cdate='2023-01-11', @eidsq =826530,@eidbg=826531, @wid =4,@department=3, @Cnumber=300001 |
执行结果 | ![]() |
4.8库存预警
4.8.1库存预警查询
语句 | alter procedure warehouse_warning7 @ProductName VARCHAR(50) @Warehousename varchar(50) @Warningnumber int = 50 as declare @StockQuantity int; SELECT top 1 w.wName=@Warehousename, m.mName=@ProductName, @StockQuantity=s.mQuantity FROM Warehouse w join (select r.mID ,r.wID from rk r) R on R.wID=w.wID join store s on s.mid= R.mID join Meterial m on m.mID=s.mID --group by w.wID, w.wName, m.mName order by s.mQuantity --select @Warehousename, @ProductName,@StockQuantity IF @StockQuantity < @Warningnumber BEGIN PRINT '该仓库:'+@Warehousename+ '安全库存不足,物资:' + @ProductName + ',库存数量:' + CONVERT(VARCHAR(50), @StockQuantity ) + ',请尽快补货。'; END exec warehouse_warning7 50 |
执行结果 | ![]() |
4.9python调用
语句 | import pyodbc # 连接数据库 count_employy = pyodbc.connect('Driver={SQL Server};Server=杨树杰;Database=wzxt;UID=sa;PWD=123123') if count_employy: print("连接成功") while True: x = input("请选择要进行的操作:") cursor = count_employy.cursor() # 创建游标 if x == '采购计划管理': print("先进行物料需求接收后进行MRP计算") strsql = 'GetAllMaterialDemandList' # 物料需求接受对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() strsql = 'MRP_caculating' # MRP计算对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() elif x == '采购任务下达': strsql = 'up_PushTask' # 采购任务下达对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() elif x == '采购任务撤销': strsql = 'up_UndoTask' # 采购任务撤销对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() elif x == '采购询价': strsql = 'up_enquiry' # 采购询价对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() elif x == '采购合同编制': strsql = 'up_contract' # 采购合同编制对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() elif x == '入库申请': strsql = 'up_rkapply' # 入库申请对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() elif x == '库存汇总查询': strsql = 'GetWarehouseStorageSummary' # 库存汇总查询对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() elif x == '领料申请': strsql = 'up_ckapply' # 领料申请对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() elif x == '库存预警': strsql = 'warehouse_warning7' # 库存预警对应的存储名称 cursor.execute(strsql) row = cursor.fetchone() # 返回结果 while row: print(row) row = cursor.fetchone() else: print("不存在对应操作请重新输入") break cursor.close() # 关闭游标 |
执行结果 | ![]() |
- 结论与体会
在做课设的过程中我们的主要亮点是添加了MRP计算和库存预警,MRP计算可以通过输入需求数量和需求时间结合安全库存和采购提前期计算出实际的采购数量与采购时间,然后添加到任务单里进行分配,另外一个功能库存预警,编写了两个触发器,在出库表和入库表里更新实发数量和实收数量时更新库存表,如果库存表中的数量小于安全库存,则发出警告,具体的体会如下:这次设计让我深刻理解了数据库的实质和重要性。在日常生活和工作中,数据无处不在,而数据库则是对这些数据进行有效管理和利用的重要工具。通过这次设计,我学会了如何从零开始构建一个完整的数据库系统,包括表结构定义、数据插入、查询、更新以及删除等操作。我明白了每一项操作背后的逻辑和原理,也感受到了数据规范化和优化的重要性。在实践过程中,我遇到了很多挑战。例如,在设计复杂的查询语句时,我曾一度感到困惑。但通过反复思考和实践,我逐渐掌握了如何运用SQL语言来高效地检索数据。此外,在处理大量数据时,我意识到了性能优化和安全性的重要性。这让我对数据库的性能调优和安全防护有了更深入的了解。与此同时,我也体会到了团队协作的力量。在课程设计中,我和我的团队成员共同探讨、解决问题,互相学习、共同进步。我们分享彼此的经验和想法,相互支持和鼓励。这种团队氛围让我倍感温暖,也让我明白了沟通与合作在项目中的关键作用。回顾整个过程,我深知自己在数据库领域还有很多需要学习和提高的地方。但这次课程设计为我提供了一个宝贵的实践机会,让我对数据库有了更深入的认识和理解。我相信,这次经历将对我未来的学习和职业生涯产生积极的影响。