原文:http://blog.chinaunix.net/uid-13874038-id-191915.html
三 概要设计
3.1 E—R图和相关说明
类别(类别编号,类别名称,上级类别)
仓库(仓库编号,隶属单位,备注)
用户(用户名,密码,权限类型);
客户(客户编号,联系人,单位,联系电话,传真,通信地址,邮政编码)
产品(编号,名称,规格,计算单位,参考价格,数量下限,数量下限,有效期,警告
出库(出库类型,产品类型,单价,数量,总价格,客户单位,出库仓库,经办用户,出库日期)
入库(入库类型,产品名称,生产日期,单价,数量,总价格,客户单位,入库仓库,经办用户,入库日期)
库存(产品入库单价,库存数量,生产日期)
四 逻辑设计
(一)、表的定义如下 :
Client表(客户信息表) Product(产品信息表)
ProinStore(库存信息表) Takeout(出库表)
StoreIn(入库表) Users(用户表)
ProType(产品类型表) Storehouse(仓库信息表)
(二)、视图定义如下:
一、report2(报表视图)
CREATE VIEW Report2
AS
SELECT SiType, Pid, Pprice, Pnum, (Pprice * Pnum) As Amount,
Cid, Sid, EmpName, OptDate FROM StoreIn
UNION
SELECT Ttype, Pid, Pprice, Pnum, (Pprice * Pnum) As Amount, Cid, Sid, EmpName, OptDate FROM TakeOut
二、 库存统计视图
CREATE VIEW Total_Num
AS
SELECT dbo.ProInStore.Pid, SUM(dbo.ProInStore.Pnum) AS Total
FROM dbo.ProInStore INNER JOIN
dbo.Product ON dbo.ProInStore.Pid = dbo.Product.Pid
GROUP BY dbo.ProInStore.Pid
三、库存视图
CREATE VIEW dbo.v_ProInStore
AS
SELECT p.Pid, SUM(s.Pnum) AS SumNum
FROM dbo.Product p INNER JOIN
dbo.ProInStore s ON p.Pid = s.Pid
GROUP BY p.Pid
四、入库视图
CREATE VIEW dbo.v_storein
AS
SELECT p.Pid, SUM(i.Pnum) AS SumNum, SUM(i.Pnum * i.Pprice)
AS SumPrice
FROM dbo.Product p INNER JOIN
dbo.StoreIn i ON p.Pid = i.Pid
GROUP BY p.Pid
五、出库视图
CREATE VIEW dbo.v_takeout
AS
SELECT p.Pid, SUM(t.Pnum) AS SumNum, SUM(t.Pnum * t.Pprice)
AS SumPrice
FROM dbo.Product p INNER JOIN
dbo.TakeOut t ON p.Pid = t.Pid
GROUP BY p.Pid
六、失效期统计视图
CREATE VIEW dbo.Valid
AS
SELECT dbo.ProInStore.SpId AS 库存记录编号, dbo.Product.Pname AS 产品名称,
dbo.ProInStore.Pprice AS 产品价格, dbo.ProInStore.Pnum AS 产品数量,
dbo.ProInStore.MakeDate AS 生产日期, dbo.Storehouse.Sname AS 仓库名称,
ROUND(DATEDIFF(day, DATEADD(day, dbo.Product.Valid, dbo.ProInStore.MakeDate),
GETDATE()), 0) AS 距离失效期的天数
FROM dbo.ProInStore INNER JOIN
dbo.Product ON dbo.ProInStore.Pid = dbo.Product.Pid AND DATEDIFF(day,
GETDATE(), dbo.ProInStore.MakeDate)
>= dbo.Product.Valid - dbo.Product.AlarmDays INNER JOIN
dbo.Storehouse ON dbo.ProInStore.Sid = dbo.Storehouse.Sid
五 详细设计
总体模块设计如下:
模块一(基本信息管理)(由本人完成)
准备工作:
一完成对数据库连接和操作的类
#import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF") rename("BOF","adoBOF")
class ADOConn
{// 定义变量
public:
_ConnectionPtr m_pConnection; //添加一个指向Connection对象的指针:
_RecordsetPtr m_pRecordset; //添加一个指向Recordset对象的指针:
public: // 定义方法
ADOConn();
virtual ~ADOConn(); // 初始化—连接数据库
void OnInitADOConn();
_RecordsetPtr& GetRecordSet(_bstr_t bstrSQL); // 执行查询
BOOL ExecuteSQL(_bstr_t bstrSQL); // 执行SQL语句,Insert Update _variant_t
void ExitConnect();
void Backup(); //备份数据库
void Restore();//恢复数据库};
一、用户登陆:
实现代码如下:
class CLoginDlg : public CDialog
{
// Construction
public:
CLoginDlg(CWnd* pParent = NULL); // standard constructor
~CLoginDlg();
// Dialog Data
//{{AFX_DATA(CLoginDlg)
enum { IDD = IDD_LOGIN_DIALOG };
CEdit m_control_username;
CEdit m_control_password;
int count;
int seconds;
CSMButton m_ok;
CSMButton m_cancel;
CString m_Pwd;
CString m_UserName;
COLORREF m_clrText;
COLORREF m_clrBkgnd;
CBrush m_brBkgnd;
CBrush m_brControlBkgnd1;
CBrush m_brControlBkgnd2;
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual void OnOK();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
afx_msg void OnTimer(UINT nIDEvent);
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
void CLoginDlg::OnOK()
{UpdateData(TRUE);
if (m_UserName == ""){
MessageBox("请输入用户名");
return;}
if (m_Pwd == ""){
MessageBox("请输入密码");
return;}
//定义CUsers对象,用于从表Users中读取数据
CUsers user;
user.GetData(m_UserName);
//如果读取的数据与用户输入数据不同,则返回
if (user.GetPwd() != m_Pwd)
{ if (count<3)
{MessageBox("用户信息不正确,无法登录!");
count++;
m_Pwd.Empty();
m_control_password.SetFocus();
UpdateData(FALSE);}
else
{
MessageBox("你可能是非法用户!","警告",MB_OK|MB_ICONHAND);
exit(0); }}else{KillTimer(0);CDialog::OnOK();}}
二、客户的实现代码
void CClientManDlg::Refresh_Data()
{
UpdateData(TRUE); //将控件的值读取到成员变量中
CString cSource;
CString cCtype; //读取客户类型值
cCtype.Format("%d", m_Ctype.GetCurSel() + 1);
//设置SELECT语句,按客户单位排序
cSource = "SELECT Cid, Cname AS 客户单位, Contact AS 联系人, Address AS 通信地址,";
cSource += " Postcode AS 邮政编码, Phone AS 联系电话, Fax AS 传真电话, Memo AS 备注";
cSource += " FROM Client WHERE Ctype=" + cCtype + " ORDER BY Cname";
m_adodc.SetRecordSource(cSource);
m_adodc.Refresh();
//设置表格列宽度
_variant_t vIndex;
vIndex = long(0);
m_datagrid.GetColumns().GetItem(vIndex).SetWidth(0);
}
BOOL CClientManDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
m_Ctype.SetCurSel(0); //设置客户类型
Refresh_Data(); //刷新表格中的记录集
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CClientManDlg::OnAddButton()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
//打开编辑对话框
CClientEditDlg dlg;
dlg.cCid = "";
dlg.iCtype = m_Ctype.GetCurSel() + 1;
if (dlg.DoModal() == IDOK)
Refresh_Data();
}
void CClientManDlg::OnSelchangeCtypeCombo()
{
// TODO: Add your control notification handler code here
Refresh_Data();
}
void CClientManDlg::OnModiButton()
{
// TODO: Add your control notification handler code here
if (m_adodc.GetRecordset().GetEof())
{
MessageBox("请选择要修改的记录");
return;
}
UpdateData(TRUE);
CClientEditDlg dlg;
dlg.cCid = m_datagrid.GetItem(0); //记录编号
dlg.iCtype = m_Ctype.GetCurSel() + 1; //客户类型
dlg.m_Cname = m_datagrid.GetItem(1); //单位名称
dlg.cCname = m_datagrid.GetItem(1);
dlg.m_Contact = m_datagrid.GetItem(2); //联系人
dlg.m_Address = m_datagrid.GetItem(3); //通信地址
dlg.m_Postcode = m_datagrid.GetItem(4); //邮政编码
dlg.m_Phone = m_datagrid.GetItem(5); //联系电话
dlg.m_Fax = m_datagrid.GetItem(6); //传真
dlg.m_Memo = m_datagrid.GetItem(7); //备注信息
if (dlg.DoModal() == IDOK)
Refresh_Data();
}
void CClientManDlg::OnDelButton()
{
// TODO: Add your control notification handler code here
if (m_adodc.GetRecordset().GetEof())
{
MessageBox("请选择要删除的记录");
return;
}
CString Cid;
Cid = m_datagrid.GetItem(0);
CStoreIn obj;
if (obj.HaveClient(Cid) == 1)
{
MessageBox("客户出现在入库单中,不能删除");
return;
}
CTakeOut obj1;
if (obj1.HaveClient(Cid) == 1)
{
MessageBox("客户出现在出库单中,不能删除");
return;
}
if (MessageBox("是否删除当前记录","请确定", MB_YESNO) == IDYES)
{
CClient clt;
clt.sql_delete(m_datagrid.GetItem(0));
Refresh_Data();
}
}
三、仓库信息管理
void CStoreHouseManDlg::Refresh_Data()
{
UpdateData(TRUE);
CString cSource;
cSource = "SELECT Sid, Sname AS 仓库单位, Memo AS 备注";
cSource += " FROM Storehouse ORDER BY Sname";
m_adodc.SetRecordSource(cSource);
m_adodc.Refresh();
//设置表格列宽度
_variant_t vIndex;
vIndex = long(0);
m_datagrid.GetColumns().GetItem(vIndex).SetWidth(0);
vIndex = long(1);
m_datagrid.GetColumns().GetItem(vIndex).SetWidth(100);
vIndex = long(2);
m_datagrid.GetColumns().GetItem(vIndex).SetWidth(420);
}
void CStoreHouseManDlg::OnAddButton()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
//打开编辑对话框
CStoreHouseEditDlg dlg;
dlg.cSid = "";
if (dlg.DoModal() == IDOK)
Refresh_Data();
}
void CStoreHouseManDlg::OnModiButton()
{
// TODO: Add your control notification handler code here
if (m_adodc.GetRecordset().GetEof())
{
MessageBox("请选择要修改的记录");
return;
}
UpdateData(TRUE);
CStoreHouseEditDlg dlg;
dlg.cSid = m_datagrid.GetItem(0); //记录编号
dlg.m_Sname = m_datagrid.GetItem(1); //仓库名称
dlg.m_Memo = m_datagrid.GetItem(2); //备注信息
if (dlg.DoModal() == IDOK)
Refresh_Data();
}
void CStoreHouseManDlg::OnDelButton()
{
// TODO: Add your control notification handler code here
if (m_adodc.GetRecordset().GetEof())
{
MessageBox("请选择要删除的记录");
return;
}
CString Sid;
Sid = m_datagrid.GetItem(0);
CStoreIn obj;
if (obj.HaveStore(Sid) == 1)
{
MessageBox("此仓库信息出现在入库单中,不能删除");
return;
}
CTakeOut obj1;
if (obj1.HaveStore(Sid) == 1)
{
MessageBox("此仓库信息出现在出库单中,不能删除");
return;
}
CProInStore obj2;
if (obj2.HaveStore(Sid) == 1)
{
MessageBox("此仓库信息出现在库存产品信息中,不能删除");
return;
}
if (MessageBox("是否删除当前记录","请确定", MB_YESNO) == IDYES)
{
CStorehouse sh;
sh.sql_delete(Sid);
Refresh_Data();
}
}
BOOL CStoreHouseManDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
Refresh_Data();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
四、用户信息管理
void CUserManDlg::OnAddButton()
{
CUserEditDlg dlg;
dlg.iUserType = 2;
if (dlg.DoModal() == IDOK)
m_adodc.Refresh(); }
void CUserManDlg::OnModiButton()
{ if (m_datalist.GetText() == "")
{
MessageBox("请选择用户");
return;
}
if (curUser.GetUserName() != "Admin" && curUser.GetUserName() != m_datalist.GetText()
&& m_datalist.GetBoundText() == "1")
{ //除Admin外,其他管理员只能修改普通用户信息
MessageBox("只能对普通用户进行密码复位");
return;
}
if (MessageBox("是否对当前用户进行密码复位","请确认", MB_YESNO) == IDYES){ CUsers usr;
usr.SetPwd("888888"); //设置默认密码
usr.sql_updatePwd(m_datalist.GetText());
MessageBox("密码已经复位");}}
void CUserManDlg::OnDelButton()
{ if (m_datalist.GetText() == ""){
MessageBox("请选择用户");
return;}
if (curUser.GetUserName() != "Admin" && m_datalist.GetBoundText() == "1"){ //除Admin外,其他管理员只能删除普通用户
MessageBox("只能删除普通用户");
return;}if (m_datalist.GetText() == "Admin"){
MessageBox("不能删除Admin用户");
return;}
if (MessageBox("是否删除当前用户","请确认", MB_YESNO) == IDYES)
{ CUsers usr;
usr.sql_delete(m_datalist.GetText());
m_adodc.Refresh();} }
五、用户密码修改
void CChangePwdDlg::OnOK()
{//将对话框中编辑框的数据读取到成员变量中
UpdateData(TRUE);
//检查数据有效性
if (m_OldPwd == "")
{
MessageBox("请输入旧密码");
return;
}
if (m_NewPwd1 == "")
{
MessageBox("请输入新密码");
return;
}
if (m_NewPwd1 != m_NewPwd2)
{
MessageBox("两次输入的新密码不同");
return;
}
//定义CUsers对象,用于从表Users中读取数据
CUsers user;
user.GetData(m_UserName);
//如果读取的数据与用户输入数据不同,则返回
if (user.GetPwd() != m_OldPwd)
{
MessageBox("用户密码不正确!");
return;
}
user.SetPwd(m_NewPwd1);
user.sql_updatePwd(m_UserName);
MessageBox("密码修改成功,下次登录请使用新密码");
CDialog::OnOK();
}
七 测试结果
一、进入系统
输入密码正确进入主界面
二、进入主界面
三、进入客户信息管理
点击添加按钮
选中要修改的表项
如下:
点击修改:
同样选中要删除的表项 点击删除得到如下
点击确定即可删除,不想删除点击“否”。
四、进入仓库管理
操作步骤相同不在赘述了。
五、进入用户管理 六、进入用户密码修改
八 小结
在这次课程设计中,让我学到了很多在课堂和书本上学不到的知识,我在这次课程设计中最大的收获有以下几个方面:
一、领略到了数据库设计在计算机领域的重要性。数据库作为一个永久存储形式在应用中发挥着重要的作用。在数据库设计中,我明白了数据库设计中不是范式越高越好的。我们要根据我们的应用来决定,一切应该以需求为首要选择。
二、对变成环境、一些控件的使用和界面的美化方面更加熟悉。因为《仓库管理系统》中涉及到很多控件的使用,只有很好的使用这些控件才可以给出一个很好的界面呈现在用户的面前。这样更有利于数据库和用户之间的交流。这里就要涉及一些平时不太常见的控件的使用问题。为了更好的在系统中利用这些控件,我上网查询了一些关于控件使用的资料,最主要的是MSDN上面、还有借了一些这方面的书籍。在界面的美化方面,我了解了一些WINDOWS自定义界面的知识,现在的软件其实好多面向用户的时候用户首先看的就是一个软件的界面是否有好,是否漂亮。其实,界面美化是很重要的。因为美,是人一直追求的。主要知识有:自定义窗口形状,按钮的3D效果,控件的自定义等等。这些都是通过面向对象编程的一些特性实现的,又得是通过多态,又得是通过类的继承。
三、利用软件工程学开发系统。虽然这个《仓库管理系统》是一个小的系统,但只有从这些小的项目中就利用软件工程学的知识,这样可以开发在系统设计和实现中我们可以总结很多经验和教训。我们一般按照瀑布开发模型、增量模型、 螺旋模型来做我们的项目。
参考文献
[1]SQL Server 2000数据库及应用 徐人凤 曾建华 高等教育出版社 2004年1月
[2]软件编程规范 徐人凤 孙宏伟 王梅 2005年7月高等教育出版社
[3]《SQL Server数据库开发经典案例解析 》,清华大学出版社,2006年
[4]《SQL SERVER 2000开发与应用》,机械工业出版社,2003年7月
[5]《数据库系统概论(第三版) 萨师煊 王珊