物流管理系统
目录
摘要
0 引言
2 总体设计
2.1 项目规划
2.2 系统功能结构
2.3 系统功能概述
3.2 开发及运行环境
3.3 数据库设计
4 主要功能模块设计
4.1 构建应用程序框架
4.2 封装数据库
4.3 主窗口设计
4.4 基础信息基类
4.4 持扫描仪辅助录入功能业务类
4.5 业务类
4.6 业务查询类
4.7 统计汇总类
4.8 审核类
4.9 派车单写IC卡模块
4.10 配送申请模块
附录A 参考文献
附录B 数据表927
摘要
【摘要】
伴信息时代的到来,使社会的各个行业领域都发生了巨大的变化,物流业也在时代大背景的影响之下,整个行业朝着信息化方向发 展。有效整合业内资源,使个体的、单一的企业物流运输,还是集团化的大企业都朝着高效、可持续发展的方向发展。作为物流行业的主体,物流集团性质的企业在 跟随整个行业的对企业发展方向进行整体调整的同时,对企业内部的一系列资源等也进行全面的整合,而企业管理成为在整合、调整过程中主要调整对象。作为物流 企业的管理者,早已充份的认识到管理在企业整个企业运作过程中的重要性,通过计算机管理系统对企业进行管理,解决传统管理方法中运作节奏和企业内部资源不 能及时作出匹配和调整的问题,进而对企业内物流设施、物流资源等进行更有效的管理,统一按排,降低企业资源的闲置与浪费;大大的提高了企业资源的利用率, 减轻管理者的劳动强度,适应现代物流运作的需要,进而提高企业的工作效率和经济效益。从国内外物流节点管理经验看,一个完善的信息管理系统是检验企业物流 管理能否适应现代物流发展的最基本条件。
【关键词】物流管理系统
0 引言
通过计算机对物流企业运作的全过程进行全面、效的管 理,解决了经营过程中,客户需求和企业资源不能有效协调与统一按排的问题,减少了管理者的工作量,大大提高了企业的工作效率和经济效益,满足了信息时代物 流企业管理、发展的需求,成为物流企业适应时代发展中企业管理者必不可少的管理工具。
1 系统需求分析
根据物流企业日常管理的需要,要求系统具有以下功能:
具有商品信息、往来单位信息、员工信息、仓库信息等基础信息的管理和维护功能。q
全面实用的销售信息管理功能。q
全面实用的库存信息管理功能。q
对有配送、运输、报关的全过程进行有效、全面的管理。q
通过管理系统对企业内部的数据进行分析,以帮助企业及时作出正确的决策。q
设置系统日常维护功能q
设置职工培训管理模块。q
2 总体设计
2.1 项目规划
根据需求分析,设计系统框架。物流综合管理系统由基础信息管理、销售管理、仓储管理、配送管理,运输管理,报关管理,决策管理,系统管理、职员培训等9部分组成。设计各部分具体功能如下:
基础信息管理模块q
基础信息管理模块包括商品信息维护、往来单位信息、员工信息维护和仓库信息维护4部分。
销售管理模块q
销售管理模块由销售开票、销售结款、未付款查询、销售查询4部分组成。
仓储管理模块q
仓储管理模块主要由出库管理、入库管理、库内移动、库存盘点、库存查询、商品库存报表6部分组成。
配送管理模块q
配送管理模块包括配送申请、配送审核、配送查询、配送管理、配送反馈信息维护5个部分。
运输管理模块q
运输管理模块由车辆资料维护、驾驶员信息维护、派车单写ID卡、派车回厂4部分构成。
报关管理模块q
报关管理模块由报关单管理、备案清单管理、报关单审核、三检管理、查验管理、通关管理、报关过程监控7部分构成。
决策管理模块q
决策管理模块由商品入库排行分析、商品出库排行分析、运输工作量分析、客户信用度分析4部分构成。
系统管理模块q
系统管理模块由数据管理、系统初始化、公司设置、操作员信息维护、权限设置5个部分组成。
职员培训模块q
职员培训模块包括视频讲座1个部分。
2.2 系统功能结构
物流综合管理系统的功能结构如图1所示。
图1 物流综合管理系统功能结构图
2.3 设计目标
系统运行稳定,安全可靠。q物流综合管理系统主要帮助物流企业完成进、销、存一体化信息管理,并配有完善的配送、运输、报关、决策等功能。通过本系统可以达到以下目标:
界面设计美观,人机交互界面友好。q
信息查询灵活、方便、快捷、准确,数据存储安全可靠。q
满足键盘和鼠标的双重操作,完全支持回车键。q
信息安全保密。q
对用户输入的数据,系统进行严格的数据检验,尽可能排除人为的错误。q
数据保密性强,为每个用户设置相应的权限级别。q
系统开发平台:Visual C++ 6.0q
数据库管理系统软件:SQL Server 2000q
运行平台:Windows xp/Windows 2000q
显示像素:最低800*600,最佳效果1024*768。q
3.2 数据库设计
1.数据库概要说明
针 对物流综合管理系统欲完成的功能,采用SQL Server2000作为后端数据库,数据库命名为“wlzhglxt”,整个系统共使用了38张数据表。包括:销售退货查询、销售退货明细表、销售退货 明细表查询、销售退货信息表、销售查询、销售明细表、销售明细查询、销售排行汇总、销售排行、销售信息表、银行信息表、退货返厂表、退货返厂查询、退货返 厂明细表、退货返厂明细查询、进货查询、进货明细表、进货明细查询、进货信息表、调货明细表、调货信息表、计量单位表、系统设置表、盘点查询、盘点信息 表、操作员信息表、操作员信息查询、往来类型表、往来单位信息表、往来单位信息查询、库存查询、库存信息表、商品信息表、商品信息查询、员工信息表、仓库 信息表、仓库信息查询。
图2所示,即为本系统中数据库中的数据表结构图,该数据表结构图中包含系统所有数据表。
图2 数据库概要说明
2.数据表的结构
数据库中的数据表请参见附录B。
4 主要功能模块设计
4.1 主窗口设计
主程序界面是应用程序提供给用户访问其他功能模块的平台,根据实际需要,物流综合管理系统的主界面采用了传统的“菜单/工具栏/状态栏”风格。物流综合管理系统主程序界面如图3所示。
图3 系统登录模块运行界面
1.菜单设计
(1)单击“ResourceView”选项卡,右键单击“MyProject Resources”选项,选择“Insert”菜单项,打开“Insert Resource”窗口,如图4所示。
图4 “Insert Resource”窗口
(2)选择“Menu”文件夹,单击“New”按钮,在WordGLXT Resources目录下新增一个Menu目录项,菜单ID为IDR_MENU1。双击此菜单,对此菜单项的属性进行设计。
BEGIN
POPUP "基础信息管理(&B)"
BEGIN
MENUITEM "商品信息维护(&H) \tF2", IDM_JCXX_HPXXWH
MENUITEM "往来单位信息维护(&C)", IDM_JCXX_WLDW
MENUITEM "员工信息维护(&P)", IDM_JCXX_YGXX
MENUITEM "仓库信息维护(&S)", IDM_JCXX_CKXX
END
POPUP "销售管理(&S)"
BEGIN
MENUITEM "销售开票(&S) \tF3", IDM_XSGL_XSKP
MENUITEM "销售结款(&C)", IDM_XSGL_XSJK
MENUITEM "未付款结款(&J)", IDM_XSGL_WFKJK
MENUITEM SEPARATOR
POPUP "销售查询(&Q)"
BEGIN
MENUITEM "销售开票查询(&S)", IDM_XSGL_KPCX
MENUITEM "销售结款查询(&C)", IDM_XSGL_JKCX
MENUITEM SEPARATOR
MENUITEM "未付款查询(&N)", IDM_XSGL_WFKCX
END
END
POPUP "仓储管理(&C)"
BEGIN
POPUP "出库管理(&O)"
BEGIN
MENUITEM "出库登记(&S) \tF4", IDM_CCGL_CKDJ
MENUITEM "出库审核(&A)", IDM_CCGL_CKSH
POPUP "出库统计查询(&Q)"
BEGIN
MENUITEM "出库信息查询(&T)", IDM_CCGL_CKHZCX
MENUITEM "出库汇总报表(&W)", IDM_CCGL_CKZBB
END
END
POPUP "入库管理(&I)"
BEGIN
MENUITEM "入库登记(&I) \tF5", IDM_CCGL_RKDJ
MENUITEM "入库审核(&A)", IDM_CCGL_RKSH
POPUP "入库统计查询(&Q)"
BEGIN
MENUITEM "入库信息查询(&T)", IDM_CCGL_RKHZCX
MENUITEM "入库汇总报表(&W)", IDM_CCGL_RKZBB
END
END
MENUITEM "库内移动(&M)", IDM_CCGL_KNYD
MENUITEM "库存盘点(&C)", IDM_CCGL_KCPD
MENUITEM "库存查询(&Q)", IDM_CCGL_KCCX
MENUITEM "商品库存报表(&W) \tF6", IDM_CCGL_CCZBB
END
POPUP "配送管理(&P)"
BEGIN
MENUITEM "配送申请(&P) \tF7", IDM_PSGL_PSSQ
MENUITEM "配送审核(&A)", IDM_PSGL_PSSH
MENUITEM "配送查询(&Q)", IDM_PSGL_PSCX
POPUP "在途管理(&T)"
BEGIN
MENUITEM "在途反馈(&C)", IDM_PSGL_ZTFK
MENUITEM "在途反馈查询(&Q) \tF8", IDM_PSGL_ZTFKCX
END
MENUITEM "配送反馈信息维护(&R)", IDM_PSGL_SHPJ
END
POPUP "运输管理(&T)"
BEGIN
MENUITEM "车辆资料维护(&W)", IDM_YSGL_CLZLWH
MENUITEM "驾驶员信息维护(&J)", IDM_YSGL_JSYGL
MENUITEM "派车单写ID卡(&P)", IDM_YSGL_PCDXICK
MENUITEM "派车回场确认(&H) \tF9", IDM_YSGL_HCQRGL
END
POPUP "报关管理(&A)"
BEGIN
MENUITEM "报关单管理(&A)", IDM_BGGL_BGDGL
MENUITEM "备案清单管理(&B)", IDM_BGGL_BAQD
MENUITEM "报关单审核(&S)", IDM_BGGL_BGDSH
MENUITEM "三检管理(&E)", IDM_BGGL_SJGL
MENUITEM "查验管理(&C)", IDM_BGGL_CYAGL
MENUITEM "通关管理(&T)", IDM_BGGL_TGGL
MENUITEM "报关过程监控(&J)", IDM_BGGL_BGGCJK
END
POPUP "决策管理(&D)"
BEGIN
MENUITEM "商品入库排行分析(&I)", IDM_JCGL_RKPH
MENUITEM "商品出库排行分析(&O)", IDM_JCGL_CKPH
MENUITEM "运输工作量分析(&F)", IDM_JCGL_YSGZLFX
MENUITEM "客户信誉度分析(&X)", IDM_JCGL_KHXYDFX
END
POPUP "系统管理(&S)"
BEGIN
POPUP "数据管理(&D)"
BEGIN
MENUITEM "数据备份(&B) \tF11", IDM_SJGL_SJBF
MENUITEM "数据恢复(&R)", IDM_SJGL_SJHF
END
MENUITEM "系统初始化(&F)", IDM_XTGL_XTCSH
MENUITEM SEPARATOR
MENUITEM "公司设置(&G)", IDM_XTGL_GSSZ
MENUITEM "操作员信息维护(&O)", IDM_XTGL_CZYGL
MENUITEM "权限设置(&S)", IDM_XTGL_QXSZ
END
POPUP "注册(&R)"
BEGIN
MENUITEM "软件注册((&R)", IDM_ZC_RJZC
END
POPUP "职员培训(&X)"
BEGIN
MENUITEM "视频讲座(&J)\tF12", IDM_ZYPX_SPJZ
END
END
2.工具栏设计
创建一个工具栏。效果如图5所示。
图5 工具栏效果图
(1)工具栏创建过程代码如下:
this->SetIcon(m_hIcon,true);
this->ShowWindow(SW_SHOWMAXIMIZED);
this->ShowWindow(SW_HIDE);
if (!m_ToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_ToolBar.LoadToolBar(IDR_MAINTOOLBAR))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);
m_ToolBar.ShowWindow(SW_SHOW);
(2)判断用户级别,根据级别显示工具栏按钮个数,为工具栏添加消息响应,代码如下。
//判断用户
rst.Open("操作员信息表");
if(rst.GetRecordCount()<1)
{
MessageBox("用户您好!欢迎使用物流综合管理系统,请在稍后弹出的〖操作员管理〗模块中添加一位系统管理员,这个管理员拥有最高权限,且不允许修改,请牢记!","系统提示",MB_OK|MB_ICONINFORMATION);
PostMessage(WM_COMMAND,IDM_XTGL_CZYGL);
}
//根据权限分配功能
CString OPID;
OPID=ado.FieldToOtherField("操作员信息表","用户名",OP,"操作员编号",1);
CString sSQL;
sSQL.Format("SELECT * FROM 权限表 WHERE 操作员编号=%s",OPID);
int nJCXX,nCKGL,nYSGL,nXSGL,nPSGL,nBGGL,nXTGL,nJCGL;
rst.Open(sSQL,adCmdText);
if(rst.GetRecordCount()<1)
{
nJCXX=1;
nCKGL=1;
nYSGL=1;
nXSGL=1;
nPSGL=1;
nBGGL=1;
nXTGL=1;
nJCGL=1;
}
else
{
nJCXX=atoi(rst.GetFieldValue("基础信息"));
nCKGL=atoi(rst.GetFieldValue("仓库管理"));
nYSGL=atoi(rst.GetFieldValue("运输管理"));
nXSGL=atoi(rst.GetFieldValue("销售管理"));
nPSGL=atoi(rst.GetFieldValue("配送管理"));
nBGGL=atoi(rst.GetFieldValue("报关管理"));
nXTGL=atoi(rst.GetFieldValue("系统管理"));
nJCGL=atoi(rst.GetFieldValue("决策管理"));
} CString sCondition[8];
if(nJCXX==0)
sCondition[0]="基础信息管理(&B)";
if(nXSGL==0)
sCondition[1]="销售管理(&S)";
if(nCKGL==0)
sCondition[2]="仓储管理(&C)";
if(nPSGL==0)
sCondition[3]="配送管理(&P)";
if(nYSGL==0)
sCondition[4]="运输管理(&T)";
if(nBGGL==0)
sCondition[5]="报关管理(&A)";
if(nJCGL==0)
sCondition[6]="决策管理(&D)";
if(nXTGL==0)
sCondition[7]="系统管理(&S)";
//计算出快捷按钮各数
int nCount=0;
if(nJCXX!=0)
nCount=nCount+1;
if(nXSGL!=0)
nCount=nCount+1;
if(nCKGL!=0)
nCount=nCount+3;
if(nPSGL!=0)
nCount=nCount+2;
if(nYSGL!=0)
nCount=nCount+1;
if(nXTGL!=0)
nCount=nCount+1;
int pIDArray[15];
int nCur=0;
if(nJCXX!=0)
{
pIDArray[nCur]=IDM_JCXX_HPXXWH;
nCur++;
}
if(nXSGL!=0)
{
pIDArray[nCur]=IDM_XSGL_XSKP;
nCur++;
}
if(nCKGL!=0)
{
pIDArray[nCur]=IDM_CCGL_CKDJ;
pIDArray[nCur+1]=IDM_CCGL_RKDJ;
pIDArray[nCur+2]=IDM_CCGL_CCZBB;
nCur=nCur+3;
}
if(nPSGL!=0)
{
pIDArray[nCur]=IDM_PSGL_PSSQ;
pIDArray[nCur+1]=IDM_PSGL_ZTFKCX;
nCur=nCur+2;
}
if(nYSGL!=0)
{
pIDArray[nCur]=IDM_YSGL_HCQRGL;
nCur++;
}
if(nXTGL!=0)
{
pIDArray[nCur]=IDM_SJGL_SJBF;
nCur++;
}
pIDArray[nCur]=IDM_ZYPX_SPJZ;
nCur++;
m_ToolBar.SetButtons((const unsigned int *)&pIDArray,nCur);
int iImage;
UINT nID,nStyle;
for(i=0;i<nCur;i++)
{
m_ToolBar.GetButtonInfo(i,nID,nStyle,iImage);
switch(nID)
{
case IDM_JCXX_HPXXWH:
{
m_ToolBar.SetButtonInfo(i,IDM_JCXX_HPXXWH,TBBS_BUTTON,0);
break;
}
case IDM_XSGL_XSKP:
{
m_ToolBar.SetButtonInfo(i,IDM_XSGL_XSKP,TBBS_BUTTON,1);
break;
}
case IDM_CCGL_CKDJ:
{
m_ToolBar.SetButtonInfo(i,IDM_CCGL_CKDJ,TBBS_BUTTON,2);
break;
}
case IDM_CCGL_RKDJ:
{
m_ToolBar.SetButtonInfo(i,IDM_CCGL_RKDJ,TBBS_BUTTON,3);
break;
}
case IDM_CCGL_CCZBB:
{
m_ToolBar.SetButtonInfo(i,IDM_CCGL_CCZBB,TBBS_BUTTON,4);
break;
}
case IDM_PSGL_PSSQ:
{
m_ToolBar.SetButtonInfo(i,IDM_PSGL_PSSQ,TBBS_BUTTON,5);
break;
}
case IDM_PSGL_ZTFKCX:
{
m_ToolBar.SetButtonInfo(i,IDM_PSGL_ZTFKCX,TBBS_BUTTON,6);
break;
}
case IDM_YSGL_HCQRGL:
{
m_ToolBar.SetButtonInfo(i,IDM_YSGL_HCQRGL,TBBS_BUTTON,7);
break;
}
case IDM_SJGL_SJBF:
{
m_ToolBar.SetButtonInfo(i,IDM_SJGL_SJBF,TBBS_BUTTON,8);
break;
}
case IDM_ZYPX_SPJZ:
{
m_ToolBar.SetButtonInfo(i,IDM_ZYPX_SPJZ,TBBS_BUTTON,9);
break;
3.客户区设计
(1)在主窗口添加虚函数PreTranslateMessage,为工具栏添加快捷键。具体代码如下。
BOOL CDMain::PreTranslateMessage(MSG* pMsg)
{
if( pMsg->message==WM_KEYDOWN)
{
CString OPID;
OPID=ado.FieldToOtherField("操作员信息表","用户名",OP,"操作员编号",1);
CString sSQL;
sSQL.Format("SELECT * FROM 权限表 WHERE 操作员编号=%s",OPID);
int nJCXX,nCKGL,nYSGL,nXSGL,nPSGL,nXTGL;
RxRecordset rst;
rst.Open(sSQL,adCmdText);
if(rst.GetRecordCount()<1)
{
nJCXX=1;
nCKGL=1;
nYSGL=1;
nXSGL=1;
nPSGL=1;
nXTGL=1;
}
else
{
nJCXX=atoi(rst.GetFieldValue("基础信息"));
nCKGL=atoi(rst.GetFieldValue("仓库管理"));
nYSGL=atoi(rst.GetFieldValue("运输管理"));
nXSGL=atoi(rst.GetFieldValue("销售管理"));
nPSGL=atoi(rst.GetFieldValue("配送管理"));
nXTGL=atoi(rst.GetFieldValue("系统管理"));
}
if(pMsg->wParam==VK_F2 && nJCXX!=0)
PostMessage(WM_COMMAND,IDM_JCXX_HPXXWH);
if(pMsg->wParam==VK_F3 && nXSGL!=0)
PostMessage(WM_COMMAND,IDM_XSGL_XSKP);
if(pMsg->wParam==VK_F4 && nCKGL!=0)
PostMessage(WM_COMMAND,IDM_CCGL_CKDJ);
if(pMsg->wParam==VK_F5 && nCKGL!=0)
PostMessage(WM_COMMAND,IDM_CCGL_RKDJ);
if(pMsg->wParam==VK_F6 && nCKGL!=0)
PostMessage(WM_COMMAND,IDM_CCGL_CCZBB);
if(pMsg->wParam==VK_F7 && nPSGL!=0)
PostMessage(WM_COMMAND,IDM_PSGL_PSSQ);
if(pMsg->wParam==VK_F8 && nPSGL!=0)
PostMessage(WM_COMMAND,IDM_PSGL_ZTFK);
if(pMsg->wParam==VK_F9)
PostMessage(WM_COMMAND,IDM_YSGL_HCQRGL);
if(pMsg->wParam==VK_F11 && nXTGL!=0)
PostMessage(WM_COMMAND,IDM_SJGL_SJBF);
if(pMsg->wParam==VK_F12)
PostMessage(WM_COMMAND,IDM_ZYPX_SPJZ);
}
return CDialog::PreTranslateMessage(pMsg);
}
(2)添加状态栏,代码如下。
m_StatusBar.Create(WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),this,ID_STATUSBAR);
int xpos=::GetSystemMetrics(SM_CXSCREEN);
int width[4];
width[1]=xpos*0.2;
width[2]=xpos*0.74;
width[3]=xpos*0.86;
width[4]=xpos;
CString sText;
sText="操作员:【"+OP+"】";
m_StatusBar.SetParts(4,&width[1]);
RxRecordset rst;
4.2 基础信息基类
1.查询模块
实现目标q
查询子模块可以完成的功能如下:
支持按照多字段、多条件查询。l
支持模糊查询。l
当用户双击表格中某记录时,调用编辑模块进行编辑。l
支持打印功能。l
查询子模块的运行界面如图6所示。
图6 查询子模块的运行界面
设计步骤q
向项目中添加一个新Dialog资源,资源ID为IDD_BASEQUERY。从Controls面板上向Dialog资源中添加2个Static、1个Edit、2个ComboBox、1个ListControl控件。
代码分析q
(1) 根据模块所要完成的功能,抽象出CDBaseQuery的原型如下:
class CDBaseQuery : public Cdialog
{
public:
CDBaseQuery(Cstring sCaption, //窗口标题
Cstring sSQL, //SQL语句字符串
Cstring sIdentify, //由程序自动生成的惟一标识字段名
int nNumberStyle, //惟一标识字段的类型
CWnd* pParent = NULL
); // 构造函数
protected:
//{{AFX_MSG(CDBaseQuery)
virtual void Init(); //为子类提供的初始化虚函数
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
int m_NumberStyle; ///惟一标识字段的类型
Cstring m_Identify; //由程序自动生成的惟一标识字段名
RxRecordset rst; //记录集对象
int m_CurrentRow; //当前行
Cstring m_Caption; //对话框标题
Cstring m_DateBaseName; //数据库名称
(2)当用户单击“查询”按钮时,根据用户选择的字段和条件进行查询:
void CDBaseQuery::OnButquery()
{
Cstring sSQL,sField,sEmblem,sCondition;
this->m_ComField.GetWindowText(sField);
this->m_ComEmblem.GetWindowText(sEmblem);
this->m_EdtCondition.GetWindowText(sCondition);
//判断查询字段的类型
if(m_ComField.m_CurrentFieldType==”数值型”)
sSQL.Format(“SELECT * FROM (%s) DERIVEDTBL WHERE %s %s %s”,\n
m_DateBaseName,sField,sEmblem,sCondition);
else{
if(sEmblem!=”LIKE”)
sSQL.Format(“SELECT * FROM (%s) DERIVEDTBL WHERE %s %s ‘%s’”,\n
m_DateBaseName,sField,sEmblem,sCondition);
else
sSQL.Format(“SELECT * FROM (%s) DERIVEDTBL WHERE %s %s ‘%%%s%%’”,\n
m_DateBaseName,sField,sEmblem,sCondition);
}
rst.Open(sSQL,adCmdText);
m_Grid.AddCellValue(rst);
}
(3)当用户单击“打印”按钮时,通过全局变量m_ps设置打印结构:
void CDBaseQuery::OnButprint()
{
Cstring sCount;
m_ps.MainCaptionFontSize=400;
m_ps.DeckCaptionFontSize=180;
Cstring sText;
this->GetWindowText(sText);
sText=sText.Left(sText.GetLength()-4);
sText=sText+”报表”;
m_ps.MainCaption=sText;
sCount.Format(“%d”,rst.GetRecordCount());
m_ps.TotalNumber=1;
m_ps.Totals[0]=”共计 “+sCount+” 条记录”;
m_ps.Totals[1]=””;
m_ps.Grid=&m_Grid;
CmyApp* theApp;
theApp=(CmyApp*)::AfxGetApp();
theApp->Print(); //执行打印
}
(4)当用户双击表格中某条记录时,对选中记录进行编辑:
void CDBaseQuery::OnDblclkGrid(NMHDR* pNMHDR, LRESULT* pResult)
{
if(m_Grid.GetSelectionMark()==-1 && m_Grid.GetRows()>0)
return;
CDBaseDlg dlg(&m_Grid,m_Identify,m_NumberStyle); //声明CDBaseDlg类对象
dlg.DoModal();
this->m_Grid.DeleteAllItems();
RxRecordset rst;
rst.Open(m_DateBaseName,adCmdText);
this->m_Grid.AddCellValue(rst);
*pResult = 0;
}
从上段代码中可以看出,m_Identify和m_NumberStyle这两个成员变量都是为CDBaseDlg类成员准备的。
2.辑子模块
实现目标q
编辑子模块可以完成的功能如下:
根据指定数据表中的内容动态生成界面。l
可以自动生成基础信息的惟一标识。l
完成添加、修改、复制、删除基础信息的功能。l
编辑子模块的运行界面如图7所示。
图7 编辑子模块的运行界面
设计步骤q
向项目中添加一个新Dialog资源,资源ID为IDD_BASE。从Controls面板上向Dialog资源中添加5个Button控件。
代码分析q
(1)此模块的一个难点就是怎样根据指定数据表中字段的不同动态生成界面。在程序中,笔者通过查询子模块中表格的列数来确定对象数组的长度,再通过处理对象数组实现动态地在对话框资源中显示编辑控件的数量。关键代码如下:
BOOL CDBaseDlg::OnInitDialog()
{
Cdialog::OnInitDialog();
//根据表格信息创建窗口
const int nCol=m_pGrid->GetCols();
m_ColCount=nCol;
//取出表头
LVCOLUMN column;
Cstring sColCaption;
column.mask=LVCF_TEXT;
column.pszText=sColCaption.GetBuffer(sColCaption.GetLength());
column.cchTextMax=20;
//根据列数分配在表单上的位置
//取出屏幕分辨率
int xPix=::GetSystemMetrics(SM_CXSCREEN);
int yPix=::GetSystemMetrics(SM_CYSCREEN);
int nWidth,nHeight;
nWidth=xPix/4;
nHeight=(yPix-200)/(12+5);
Crect rcSta,rcEdit;
Cstring ColCaption;
//分配空间
pSta=new Cstatic[nCol];
pEdt=new CbaseEdit[nCol];
rcSta.left=12;
rcSta.top=70+10;
rcSta.right=rcSta.left+(nWidth*2/5);
rcSta.bottom=rcSta.top+nHeight;
rcEdit.left=rcSta.right;
rcEdit.right=rcEdit.left+(nWidth*1/2);
rcEdit.top=rcSta.top;
rcEdit.bottom=rcSta.bottom;
if(nCol<=13)
rcEdit.right=490;
for(int I=0;I<nCol;I++){
//取出表头
m_pGrid->GetColumn(I,&column);
ColCaption.Format(“%s:”,column.pszText);
www.lwfree.cn WS_CHILD,rcSta,this,WM_USER+I);
pSta[I].ShowWindow(SW_SHOW);
//计算下一个标签位置
if((I+1)%13==0){ //每列最多显示13个
rcSta.top=70+10;
rcSta.bottom=rcSta.top+nHeight;
rcSta.left=rcSta.left+nWidth-5;
rcSta.right=rcSta.left+(nWidth*1/2);
}
else{
rcSta.top=rcSta.bottom+5;
rcSta.bottom=rcSta.top+nHeight;
}
pEdt[I].Create(WS_CHILD|WS_BORDER|WS_TABSTOP|ES_AUTOHSCROLL,rcEdit,this,\
WM_USER+100+I);
pEdt[I].ShowWindow(SW_SHOW);
pEdt[I].SetDlgCtrlID(i);
pEdt[I].SetReadOnly(); //计算下一个文本框的位置
if((I+1)%13==0) {
rcEdit.top=70+10;
rcEdit.bottom=rcEdit.top+nHeight;
rcEdit.left=rcEdit.left+nWidth-5;
rcEdit.right=rcEdit.left+(nWidth*1/2);
}
else{
rcEdit.top=rcEdit.bottom+5;
rcEdit.bottom=rcEdit.top+nHeight;
}
}
//重新调整窗口大小
Crect rcWnd,rcNewWindow;
rcWnd.top=0;
rcWnd.left=0;
rcWnd.bottom=rcEdit.bottom+46;
rcWnd.right=516;
//居中显示
rcNewWindow.left=xPix/2-rcWnd.Width()/2;
rcNewWindow.right=rcNewWindow.left+rcWnd.Width();
rcNewWindow.top=xPix/2-rcWnd.Height()/2-70;
rcNewWindow.bottom=rcNewWindow.top+rcWnd.Height();
if(nCol<14) {
this->MoveWindow(rcNewWindow);
MoveButton(13,rcEdit.top);
}
else{
this->ShowWindow(SW_SHOWMAXIMIZED);
MoveButton(xPix-500,yPix-120);
}
//设置窗口标题
Cstring sCaption;
this->GetParent()->GetWindowText(sCaption);
sCaption=sCaption.Left(sCaption.GetLength()-4);
this->SetWindowText(sCaption+”维护”);
m_DataBaseName=sCaption+”表”;
//设置字符某些只允许输入数字
RxRecordset rst;
rst.Open(m_DataBaseName);
for(I=0;I<rst.GetFieldCount();I++){
if(rst.GetFieldType(i)==”数值型”)
pEdt[I].IsMoneyOnly(true);
if(rst.GetFieldType(i)==”逻辑型”)
pEdt[I].IsBoolOnly(true);
}
this->Invalidate();
this->GetClientRect(&rcNewWindow);
//调整标题区域大小
this->m_StaTitle.MoveWindow(16,16,rcNewWindow.right-32,38,true);
this->m_StaTitle.SetWindowText(sCaption+”维护”);
Display();
return TRUE;
}
(2)现在,所有相关数据表中的字段在对话框中都会有一个对应的编辑框,通过Display成员函数将用户选择的记录添加到和编辑框中。
void CDBaseDlg::Display()
{
Cstring sItemValue;
int nSelectMark=m_pGrid->GetSelectionMark();// m_pGrid是指向查询子模块中表格对象的指针
if(nSelectMark==-1){
m_ButCommand[4].EnableWindow(true);
return;
}
for(int I=0;I<m_ColCount;I++){
sItemValue=m_pGrid->GetItemText(nSelectMark,I);
pEdt[I].SetWindowText(sItemValue);//根据用户选择的列,将各字段内容添加到编辑框中
}
}
(3)基础的准备工作制作完成,现在可以为程序增加编辑功能了。
void CDBaseDlg::OnButnew() //新增
{
Clear(); //清空各编辑框的内容
OnButcopy();
}
void CDBaseDlg::Clear() //清空各编辑框内容
{
for(int m=0;m<m_ColCount;m++)
{
pEdt[m].SetWindowText(“”);
}
}
void CDBaseDlg::OnButchange() //修改
{
m_IsAdd=false; //记录用户执行的是添加操作还是修改操作,在保存时使用
Enabled(true);
}
void CDBaseDlg::OnButdele() //删除
{
if(MessageBox(“确定要删除这条记录吗?”,”系统提示”,\
MB_OKCANCEL|MB_ICONQUESTION)!=1)
return;
Cstring sSQL,sID,sValue;
pSta[0].GetWindowText(sID);
sID=sID.Left(sID.GetLength()-1);
pEdt[0].GetWindowText(sValue);
RxRecordset rst;
rst.Open(m_DataBaseName);
Cstring sType=rst.GetFieldType(0);
if(sType=”字符型”)
sSQL.Format(“DELETE FROM %s WHERE %s=’%s’”,m_DataBaseName,sID,sValue);
else
sSQL.Format(“DELETE FROM %s WHERE %s=%s”,m_DataBaseName,sID,sValue);
rst.Open(sSQL,adCmdText);
this->OnCancel();
}
void CDBaseDlg::OnButcopy() //复制
{
Cstring sSmallCaption,sCaption;
m_IsAdd=true;
Enabled(true);
Cstring NewNumber;
RxRecordset rst;
sCaption=rst.GetFieldName(0);
rst.Open(m_DataBaseName);
Cstring sType=rst.GetFieldType(0);
if(sType==”字符型”){
sSmallCaption=CharToLetterCode(m_DataBaseName);
sSmallCaption=sSmallCaption.Left(2);
NewNumber=ado.AutoNumber(m_DataBaseName,m_Identify,sSmallCaption,m_NumberStyle);
}
else
NewNumber=ado.AutoNumber(m_DataBaseName,m_Identify,””,m_NumberStyle);
pEdt[0].SetWindowText(NewNumber);
pEdt[1].SetFocus();
}
void CDBaseDlg::OnButundo() //撤消
{
if(MessageBox(“确定要撤销操作吗?”,”系统提示”,\
MB_OKCANCEL|MB_ICONQUESTION)!=1)
return;
Clear();
Display();
Enabled(false);
}
void CDBaseDlg::OnButsave() //保存
{
if(MessageBox(“确定要保存记录吗?”,”系统提示”,\
MB_OKCANCEL|MB_ICONQUESTION)!=1)
return;
RxRecordset rst;
rst.Open(m_DataBaseName);
//将文本存入数组
Cstring sValue[50],sCaption[50],sType[50];
for(int I=0;I<m_ColCount;I++)
{
sType[I]=rst.GetFieldType(i);
pEdt[I].GetWindowText(sValue[I]);
pSta[I].GetWindowText(sCaption[I]);
sCaption[I]=sCaption[I].Left(sCaption[I].GetLength()-1);
if(sValue[I].IsEmpty()==true && rst.IsNull(i)==true){//判断数据表中字段是否允许为空
MessageBox(“『”+sCaption[I]+”』 字段不允许为空!”,”系统提示”,\
MB_OK|MB_ICONSTOP);
pEdt[I].SetFocus();
return;
}
if(rst.GetFieldType(i)==”日期型”){
if(IsTime(sValue[I])==false) { //判断用户输入的日期格式是否正确
MessageBox(“请输入正确的日期格式,如“1983-06-16”、“83/6/16”等”,\
“系统提示”,MB_OK|MB_ICONSTOP);
pEdt[I].SetFocus();
return;
}
}
}
//组成新字符串
Cstring sValueString,str,sFiledString;
if(m_IsAdd==true) {
sValueString=””;
sFiledString=””;
for(I=0;I<m_ColCount;I++){
str=””;
str=sValueString;
if(sType[I]==”数值型”)
sValueString.Format(“%s,%s”,str,sValue[I]);
else
sValueString.Format(“%s,’%s’”,str,sValue[I]);
str=””;
str=sFiledString;
sFiledString.Format(“%s,%s”,str,sCaption[I]);
}
}
else{
sValueString=””;
for(I=1;I<m_ColCount;I++){
str=””;
str=sValueString;
if(sType[I]==”数值型”)
sValueString.Format(“%s,%s=%s”,str,sCaption[I],sValue[I]);
else
sValueString.Format(“%s,%s=’%s’”,str,sCaption[I],sValue[I]);
}
}
sFiledString=sFiledString.Right(sFiledString.GetLength()-1);
Cstring sSQL;
if(m_IsAdd==true)
sSQL.Format(“INSERT INTO %s (%s) VALUES(%s)”,\
m_DataBaseName,sFiledString,sValueString.Right(sValueString.GetLength()-1));
else{
if(sType[0]==”数值型”)
sSQL.Format(“UPDATE %s SET %s WHERE %s=%s”,m_DataBaseName\
sValueString.Right(sValueString.GetLength()-1),sCaption[0],sValue[0]);
else
sSQL.Format(“UPDATE %s SET %s WHERE %s=’%s’”,m_DataBaseName,\
sValueString.Right(sValueString.GetLength()-1),sCaption[0],sValue[0]);
}
if(rst.Open(sSQL,adCmdText)==false) {
MessageBox(“数据保存失败!”,”系统提示”,MB_OK|MB_ICONSTOP);
pEdt[1].SetFocus();
return;
}
this->Enabled(false);
this->m_ButCommand[1].SetFocus();
}
void CDBaseDlg::OnButexit() //退出
{
this->OnCancel();
}
4.3 业务类
1.销售结款模块
实现目标q
销售结款模块主要完成如下功能:
自动生成结款票号及开票日期。l
可以由销售开票单直接生成销售结款单,简化经手人的作业。l
提供预计偿还欠款日期设置。l
支持数据统计及金额核算功能。l
支持合计金额的大小写的转换功能。l
支持销售结款单据的打印。l
销售结款及打印模块运行界面如图8所示。
图8 销售结款模块运行界面
设计步骤q
(1) 向项目中添加一个新Dialog资源,资源ID为IDD_OPERATION。从Controls面板上向Dialog资源中添加18个Static、4 个Edit、1个ListControl、3个Button控件。IDD_OPERATION对应的类为CDOperation。
(2)与销售结款模块对应的类为CDCheck,它是从业务基类CDOperation直接派生而来。
代码分析q
重载父类纯虚函数,进行初始化设置。
void CDCheck::Init()
{
this->DrawCheck();
this->SetCaption("销售结款");
this->SetManTitle("经 手 人:");
this->SetNoteIDTitle("结款票号:");
this->SetStoreTitle("销售票号:");
this->SetOperationTitle("客 户:");
this->SetGridHeader("扫描码 , 商品名称 , 规格 , 产地 , 计量单位 , 销售数量 , \
销售单价 , 合计金额");
this->SetHeadersWidth("70 , 100 , 60 , 100 , 74 , 74 , 74 , 76");
RxRecordset rst;
CString sSQL;
sSQL.Format("SELECT * FROM 往来单位信息表 WHERE 类型='客户'");
rst.Open(sSQL,adCmdText);
m_EdtOperation.Initialize(this->GetParent());
m_EdtOperation.StartUpAssciation=true;//启动联想输入
m_EdtOperation.SetRecordset(rst);//设置数据源
m_EdtOperation.SetSelectField("全称");
rst.Open("员工信息表");
m_EdtMan.Initialize(this->GetParent());
m_EdtMan.SetRecordset(rst);//设置数据源
m_EdtMan.SetSelectField("姓名");
sSQL.Format("SELECT a.销售票号,b.全称,a.开票日期 FROM 销售记录表 a INNER EILJOIN 往来单位信息表 b ON a.客户编号=b.编号 AND 结款否=0");
rst.Open(sSQL,adCmdText);
m_EdtStore.StartUpAssciation=true;
m_EdtStore.Initialize(this->GetParent());
m_EdtStore.SetRecordset(rst);//设置数据源
m_EdtStore.SetSelectField("销售票号");
m_Grid.m_Edit.PopHide=true;
m_Grid.m_Edit.Initialize(this->GetParent());
m_Grid.m_Edit.SetRecordset(rst);//设置数据源
m_Grid.m_Edit.SetSelectField("仓库名称");
m_Grid.m_bReadOnly=true;
}
重载父类中“登记”按钮的消息响应函数:
void CDCheck::OnButEnrol()
{
this->m_EdtMan.IsShowing=true;
this->m_EdtMan.SetWindowText("");
this->m_EdtMan.IsShowing=false;
this->m_EdtOperation.IsShowing=true;
this->m_EdtOperation.SetWindowText("");
this->m_EdtOperation.IsShowing=false;
this->m_EdtStore.IsShowing=true;
this->m_EdtStore.SetWindowText("");
this->m_EdtStore.IsShowing=false;
this->m_StaBigTotal.SetWindowText("零元");
this->m_StaTotal.SetWindowText("0");
this->m_StaSumNumber.SetWindowText("0");
Clear();
CString sNewID;
sNewID=ado.AutoNumber("销售结款表","结款票号","JK",3);
this->m_StaIDValue.SetWindowText(sNewID);
this->m_StaIDValue.Invalidate();
this->Enabled(true);
this->m_EdtOperation.SetFocus();
}
重载父类中“保存”按钮的消息响应函数:
void CDCheck::OnButSave()
{
if(MessageBox("确定要保存吗?","系统提示",MB_OKCANCEL|MB_ICONQUESTION)!=1)
return;
CString sNoPay,CheckTime;
this->m_StaNoPayValue.GetWindowText(sNoPay);
if(atoi(sNoPay)>0)
{
CDDlg dlg;
dlg.DoModal();
CheckTime=dlg.m_Time;
if(CheckTime.IsEmpty())
return;
}
CString sID,sSQL,sCode,sOperation,sDate,sMan,sOPID,sMoney,sPay;
this->m_StaIDValue.GetWindowText(sID);
this->m_EdtOperation.GetWindowText(sOperation);
this->m_EdtStore.GetWindowText(sCode);
this->m_StaDateValue.GetWindowText(sDate);
this->m_EdtMan.GetWindowText(sMan);
sMan=ado.FieldToOtherField("员工信息表","姓名",sMan,"编号",1);
sOPID=ado.FieldToOtherField("操作员信息表","用户名",OP,"操作员编号",1);
this->m_StaTotal.GetWindowText(sMoney);
this->m_EdtPay.GetWindowText(sPay);
if(sOperation.IsEmpty()==true){
MessageBox("请输入客户名称!","系统提示",MB_OK|MB_ICONSTOP);
m_EdtOperation.SetFocus();
return;
}
if(sCode.IsEmpty()==true){
MessageBox("请输入销售票号!","系统提示",MB_OK|MB_ICONSTOP);
m_EdtStore.SetFocus();
return;
}
if(sMan.IsEmpty()==true){
MessageBox("请输入经手人!","系统提示",MB_OK|MB_ICONSTOP);
m_EdtMan.SetFocus();
return;
}
//存入销售结款表
sSQL.Format("INSERT INTO 销售结款表 VALUES('%s','%s','%s',%s,%s,%s,%s)",\
sID,sCode,sDate,sMoney,sPay,sMan,sOPID);
RxRecordset rst;
rst.Open(sSQL,adCmdText);
//存入销售挂帐表
if(atoi(sNoPay)>0){
sSQL.Format("INSERT INTO 销售挂帐表 VALUES('%s','%s','%s',%s,0)",\
sCode,sDate,CheckTime,sNoPay);
rst.Open(sSQL,adCmdText);
}
//更新销售记录表
sSQL.Format("UPDATE 销售记录表 SET 结款否 =1 WHERE 销售票号='%s'",sCode);
rst.Open(sSQL,adCmdText);
this->Enabled(false);
}
重载父类中右单击表格的消息响应函数,去掉弹出的快捷菜单:
void CDCheck::OnRclickGrid(NMHDR *pNMHDR, LRESULT *pResult)
{
}
2.库存盘点模块
实现目标q
库存盘点模块主要完成如下功能:
自动生成盘点票号及开票日期。l
通过条形码扫描仪自动生成库存数据,用户只输入实际的盘点数据,简化了用户工作量。l
支持库存盘点单据的打印。l
库存盘点模块运行界面如图9所示。
图9 库存盘点模块运行界面
设计步骤q
(1)与库存盘点模块对应的类为CDInventory,它是从业务基类CDOperation直接派生而来。
代码分析q
(1)当用户向表格内录入条型码,系统自动根据条型码查询出指定商品信息,并显示出来。
void CDInventory::OnCellKillFocus()
{
CString sCode,sSQL;
RxRecordset rst;
if(this->m_Grid.GetCol()==0)
{
sCode=m_Grid.GetItemText(m_Grid.GetRow(),0);
sSQL.Format("SELECT * FROM 商品信息表 WHERE 条形码='%s'",sCode);
rst.Open(sSQL,adCmdText);
if(rst.GetRecordCount()<1)
return;
m_Grid.SetItemText(m_Grid.GetRow(),1,rst.GetFieldValue("名称"));
m_Grid.SetItemText(m_Grid.GetRow(),2,rst.GetFieldValue("规格"));
m_Grid.SetItemText(m_Grid.GetRow(),3,rst.GetFieldValue("产地"));
m_Grid.SetItemText(m_Grid.GetRow(),4,rst.GetFieldValue("计量单位"));
}
}
(2)当用户更改某单元格的值时,系统自动通过提示窗口显示出适当的提示内容。这段代码可算是此类中最有特色的部分。
void CDInventory::OnCellSetFocus()
{
RxRecordset rst;
CString sSQL,sName,sSpec,sAddr,sCode,sStore;
this->m_EdtStore.GetWindowText(sStore);
sStore=ado.FieldToOtherField("仓库信息表","仓库名称",sStore,"编号",1);
switch(this->m_Grid.GetCol()){
case 1:
{
rst.Open("SELECT DISTINCT 名称,简称 from 商品信息表",adCmdText);
m_Grid.m_Edit.NumberOnly(false);
m_Grid.m_Edit.PopHide=false;
m_Grid.m_Edit.EnterNumber=0;
m_Grid.m_Edit.ClearAll();
m_Grid.m_Edit.StartUpAssciation=true;
m_Grid.m_Edit.SetRecordset(rst);
m_Grid.m_Edit.SetSelectField("名称");
m_Grid.m_Edit.AutoPosition();
break;
}
case 2: {
m_Grid.m_Edit.NumberOnly(false);
m_Grid.m_Edit.PopHide=false;
m_Grid.m_Edit.EnterNumber=0;
m_Grid.m_Edit.ClearAll();
sName=m_Grid.GetItemText(m_Grid.GetRow(),1);
sSQL.Format("SELECT DISTINCT 名称,规格 FROM 商品信息表 \
WHERE 名称='%s'",sName);
rst.Open(sSQL,adCmdText);
m_Grid.m_Edit.StartUpAssciation=false;
m_Grid.m_Edit.SetRecordset(rst);
m_Grid.m_Edit.SetSelectField("规格");
m_Grid.m_Edit.AutoPosition();
break;
}
case 3: {
m_Grid.m_Edit.NumberOnly(false);
m_Grid.m_Edit.PopHide=false;
m_Grid.m_Edit.EnterNumber=0;
m_Grid.m_Edit.ClearAll();
sName=m_Grid.GetItemText(m_Grid.GetRow(),1);
sSpec=m_Grid.GetItemText(m_Grid.GetRow(),2);
sSQL.Format("SELECT DISTINCT 名称,产地 from 商品信息表 \
WHERE 名称='%s' AND 规格='%s'",sName,sSpec);
rst.Open(sSQL,adCmdText);
m_Grid.m_Edit.StartUpAssciation=false;
m_Grid.m_Edit.SetRecordset(rst);
m_Grid.m_Edit.SetSelectField("产地");
m_Grid.m_Edit.AutoPosition();
break;
}
case 4: {
m_Grid.m_Edit.NumberOnly(false);
m_Grid.m_Edit.PopHide=false;
m_Grid.m_Edit.EnterNumber=0;
m_Grid.m_Edit.ClearAll();
sName=m_Grid.GetItemText(m_Grid.GetRow(),1);
sSpec=m_Grid.GetItemText(m_Grid.GetRow(),2);
sAddr=m_Grid.GetItemText(m_Grid.GetRow(),3);
sSQL.Format("SELECT * from 商品信息表 WHERE 名称='%s' AND \
规格='%s' AND 产地='%s'",sName,sSpec,sAddr);
rst.Open(sSQL,adCmdText);
this->m_Grid.SetItemText(m_Grid.GetRow(),0,rst.GetFieldValue("条形码"));
sSQL.Format("SELECT DISTINCT 名称,计量单位 from 商品信息表 \
WHERE 名称='%s' AND 规格='%s' AND 产地='%s'",sName,sSpec,sAddr);
rst.Open(sSQL,adCmdText);
m_Grid.m_Edit.StartUpAssciation=false;
m_Grid.m_Edit.SetRecordset(rst);
m_Grid.m_Edit.SetSelectField("计量单位");
m_Grid.m_Edit.AutoPosition();
break;
}
case 5: {
sCode=m_Grid.GetItemText(m_Grid.GetRow(),0);
sSQL.Format("SELECT a.名称,b.库存数量 from 商品信息表 a inner join \
库存信息表 b on a.条形码=b.商品条形码 WHERE a.条形码='%s' \
AND b.仓库编号=%s",sCode,sStore);
rst.Open(sSQL,adCmdText);
if(rst.GetRecordCount()<1)
m_Grid.m_Edit.SetWindowText("0");
else
m_Grid.m_Edit.SetWindowText(rst.GetFieldValue("库存数量"));
m_Grid.m_Edit.PopHide=true;
m_Grid.m_Edit.SetReadOnly(true);
m_Grid.m_Edit.NumberOnly(true);
m_Grid.m_Edit.HideGrid();
break;
}
case 6: {
m_Grid.m_Edit.SetReadOnly(false);
m_Grid.m_Edit.PopHide=true;
m_Grid.m_Edit.NumberOnly(true);
m_Grid.m_Edit.HideGrid();
break;
}
}
}
4.4 业务查询类
1.销售开票查询模块
实现目标l
销售开票查询模块主要完成如下功能:
支持多字段查询及模糊查询。l
支持销售开票主、明细表的调用。l
支持销售开票单据的打印。l
销售开票查询及打印模块运行界面如图10所示。
图10 销售开票查询模块运行界面
设计步骤q
(1) 向项目中添加一个新Dialog资源,资源ID为IDD_OPERATIONQUERY。从Controls面板上向Dialog资源中添加6个 Static、1个Edit、2个ListControl、4个ComboBox控件。IDD_OPERATIONQUERY对应的类为 DOperationQuery。
(2)与销售开票查询模块对应的类为SellQuery,它从业务基类CDOperation直接派生而来。
代码分析q
关键代码如下:
void SellQuery::Init()
{
this->m_StaTitle.SetWindowText("开票日期");
this->SetWindowText("销售开票查询");
this->m_DataBaseName="SELECT a.销售票号, b.全称 AS 客户名称, a.开票日期, a.合计数量,\
a.合计金额, d.姓名 AS 经手人,c.用户名 AS 操作员 \
FROM 销售记录表 a INNER JOIN 往来单位信息表 b ON a.客户编号 = b.编号 \
INNER JOIN 操作员信息表 c ON a.操作员 = c.操作员编号 \
INNER JOIN 员工信息表 d ON a.经手人 = d.编号";
this->m_ListDataBaseName="SELECT a.商品条形码 AS 条形码, b.名称 AS 商品名称,\
b.规格, b.产地, b.计量单位, a.销售数量,b.销售价格 AS 销售单价,a.合计金额 ,a.销售票号\
FROM 销售明细表 a INNER JOIN 商品信息表 b ON a.商品条形码 = b.条形码";
}
2.未付款查询模块
实现目标q
未付款查询模块主要完成如下功能:
支持多字段查询及模糊查询。l
支持未付款结款主、明细表的调用。l
支持销售欠款单的打印。l
未付款查询及打印模块运行界面如图11所示。
图11 未付款查询模块运行界面
设计步骤q
程序中,与未付款查询模块对应的类为NoPayQuery,它是从业务基类CDOperation直接派生而来。
代码分析q
(1)关键代码如下:
void NoPayQuery::Init()
{
this->m_StaTitle.SetWindowText("欠款日期");
this->SetWindowText("未付款查询");
this->m_DataBaseName="SELECT a.销售票号,c.全称 AS 客户全称\
,b.挂帐日期 AS 欠款日期,a.合计金额, b.未付金额,d.姓名 AS 经手人, e.用户名 AS 操作员\
FROM 销售记录表 a INNER JOIN 销售挂帐表 b ON a.销售票号 =b.销售票号 \
INNER JOIN 往来单位信息表 c ON a.客户编号 = c.编号 \
INNER JOIN 员工信息表 d ON a.经手人 = d.编号 \
INNER JOIN 操作员信息表 e ON a.操作员 = e.操作员编号 WHERE b.偿还否=0";
this->m_ListDataBaseName="SELECT a.商品条形码 AS 条形码, b.名称 AS 商品名称,b.规格,\
b.产地, b.计量单位, a.销售数量,b.销售价格 AS 销售单价,a.合计金额 ,a.销售票号 \
FROM 销售明细表 a INNER JOIN 商品信息表 b ON a.商品条形码 = b.条形码";
}
(2)重载入“打印”按钮的消息响应函数:
void NoPayQuery::OnButprint()
{
if(m_HotItem<0) {
MessageBox("请在显示主要信息的表格中双击一条记录!",\
"系统提示",MB_OK|MB_ICONSTOP);
return;
}
RxRecordset rst;
CString sID,sClient,sDate,sMan,sMoney,sNoPay;
……
m_ps.MainCaptionFontSize=400;
m_ps.DeckCaptionFontSize=180;
m_ps.MainCaption="销售欠款单";
m_ps.DeckCaptionNumber=4;
m_ps.DeckCaptions[0]="销售票号:"+sID;
m_ps.DeckCaptions[1]="客户全称:"+sClient;
m_ps.DeckCaptions[2]="欠款日期:"+sDate;
m_ps.DeckCaptions[3]="经 手 人:"+sMan;
m_ps.Grid=&m_ListGrid;
m_ps.TotalNumber=4;
CString sPay;
sPay.Format("%f",atof(sMoney)-atof(sNoPay));
m_ps.Totals[0]="应付金额:"+sMoney;
m_ps.Totals[1]="实付金额:"+sPay;
m_ps.Totals[2]="未付金额:"+sNoPay;
m_ps.Totals[3]="操 作 员:"+OP;
CMyApp* theApp;
theApp=(CMyApp*)::AfxGetApp();
theApp->Print();
由于篇幅有限,只给出部分数据表。
表1 商品信息表
字段名称 字段类型 长度 主键否 允许为空
编号 int 4 T
条形码 VarChar 13
名称 VarChar 40
简称 VarChar 20 T
规格 VarChar 20
产地 VarChar 100
计量单位 VarChar 10 T
进货价格 Money 8 T
销售价格 Money 8 T
表2 销售信息表
字段名称 字段类型 长度 主键否 允许为空
销售票号 VarChar 15 T
内部编号 VarChar 16 T
客户编号 VarChar 10
开票日期 SmallDateTime 8
合计数量 Integer 4
合计金额 Money 8
操作员 Integer 4
经手人 Integer 4
结款否 Bit 1 T
提货否 Bit 1 T
表3 库存信息表
字段名称 字段类型 长度 主键否 允许为空
商品条形码 VarChar 13 T
仓库编号 Integer 4
库存数量 Integer 4
货位_排 Integer 4 T
货位_号 Integer 4 T
库存上限 Integer 4 T
库存下限 Integer 4 T
表4 往来单位信息表
字段名称 字段类型 长度 主键否 允许为空
编号 VarChar 10 T
全称 VarChar 60
简称 VarChar 10 T
类型 VarChar 10 T
地址 VarChar 100 T
电话 VarChar 15 T
联系人 VarChar 16 T
联系人电话 VarChar 15 T
邮箱网址 VarChar 40 T
第1章 系统登录
双击可执行文件后,弹出系统注册的对话框,单击“试用”按钮后弹出如图1.1所示的对话框,在对话框中输入操作员“mr”和密码“mingrisoft”后,单击“登录”按钮即可进入到如图1.2所示的主界面。
图1.1 系统登录
图1.2 物流管理系统主界面
第2章 基本信息管理
基本信息管理主要包括:商品信息维护、往来单位信息维护、员工信息维护和仓库信息维护。
2.1 商品信息维护
1.在商品信息维护中,可对数据进行查询和打印。
注意:双击列表中的商品信息可弹出如图1.4所示的模块,在此模块中可对数据进行新增、修改、复制、删除等操作。
查询:设置完查询条件后,单击“查询”按钮,窗体下方的列表中即可显示查询结果。
打印:单击“打印”按钮即可进行打印。
新增:单击“新增”按钮,可对数据进行添加,添加后单击“保存”按钮即可添加成功。其运行结果如图1.4所示。
修改:选择要修改的数据,单击“修改”按钮即可对数据进行修改,单击“保存”按钮即可修改成功。
复制:选择和想要添加的信息比较相似的数据,单击“复制”按钮,对原数据加以改动后,单击“保存”按钮即可。
删除:选择要删除的数据,单击“删除”按钮即可将数据删除。
图1.3 商品信息查询
图1.4 商品信息维护
2.2 往来单位信息查询
其详细的操作步骤请参考2.1“商品信息维护”的操作步骤即可。
2.3 员工信息维护
其详细的操作步骤请参考2.1“商品信息维护”的操作步骤即可。
2.4 仓库信息维护
其详细的操作步骤请参考2.1 商品信息维护的操作步骤即可。
第3章 仓库管理
仓库管理菜单主要包括:入库管理、出库管理、库存移动、库存盘点、库存查询和商品库存报表。
3.1 入库管理
入库管理包括:入库登记、入库审核和入库查询。
3.1.1 入库登记
单击“登记”按钮,在进货仓库、客户、经手人文本框中可按上下键对数据进行选择,输入条形码后,系统自动显示相应的数据。最后单击“保存”按钮即可登记成功。其运行结果如图1.5所示。
打印:单击“打印”按钮即可对数据进行打印。
3.1.2 入库审核
在票号文本框中输入票号。单击“查询”按钮即可查询到为相关数据。在“审核人” 文本框中输入审核人,单击“通过审核”或“审核作废”按钮即可完成入库审核。其运行结果如图1.6所示。
图1.6 入库审核
3.1.3 入库统计查询
入库统计查询主要还包括两个子模块:分别是入库信息查询和入库汇总报表。
1.入库信息查询
先设置一个日期,在查询条件文本框中输入要查询的条件,输入后单击“查询”按钮即可查询相关数据。其运行结果如图1.7所示。
打印:单击“打印”按钮即可打印数据。
图1.7 入库统计查询
2.入库汇总报表
设置完入库日期后,单击“查询”按钮即可查询在这段时间内的所有数据。其运行结果如图1.8所示。
打印:单击“打印”按钮即可打印所显示的数据。
图1.8 入库汇总报表
注意:入库后即可对数据进行销售管理,销售管理请参见下一章。
3.2 出库管理
出库管理的具体操作步骤请参考3.1节“入库管理”的操作步骤即可。
3.3 库内移动
在显示为黄颜色的数据中,按鼠标左键拖拽可对库内的数据进行移动,如果想知道某货位存放的是哪种物品,把鼠标放在黄颜色的数据上,按下鼠标右键即可显示物品信息。其运行结果如图1.9所示。
图1.9 库内移动
3.4 库存盘点
登记:单击“登记”按钮,在“经手人”和“盘点仓库”文本框中按“↑”、“↓”键可对数据进行选择,在扫描码中输入扫描码后按<Enter>键后可自动弹出相应信息,最后单击“保存”按钮即可。其运行结果如图1.10所示。
打印:单击“打印”按钮即可打印所显示的数据。
图1.10 库存盘点
3.5 库存查询
查询:设置完查询条件后,单击“查询”按钮,窗体下方列表中即可显示查询结果。其运行结果如图1.11所示。
打印:单击“打印”按钮即可打印数据。
图1.11 库存查询
3.6 商品库存报表
打印:单击“打印”按钮即可打印数据。其运行结果如图1.12所示。
图1.12 商品库存报表
第4章 销售管理
销售管理主要包括:销售开票、销售结款、未付款结款和销售查询。
4.1 销售开票
登记:单击“登记”按钮,在“客户”和“经手人”文本框中按“↑”、“↓”可对数据进行选择,输入条形码后按<Enter>按可显示相关数据,单击“保存”按钮即可。其运行结果如图1.13所示。
打印:单击“打印”按钮即可进行打印。
图1.13 销售开票
4.2 销售结款
登记:在:“客户”、“销售票号”和“经手人”这几个文本框中按“↑”、“↓”键可对数据进行选择,输入条形码、商品名称等信息后,单击“保存”按钮即可保存数据。其运行结果如图1.14所示。
打印:单击“打印”按钮即可打印当前所显示的数据。
图1.14 销售结款
4.3 未付款结款
结款:在客户名称文本框中,按“↑”、“↓”键可对客户名称进行选择,然后单击“查询”按钮即可查询数据,在“结款金额” 文本框中输入欠款金额后,单击“结款”按钮即结款成功。其运行结果如图1.15所示。
图1.15 未付款结款
4.4 销售查询
销售查询主要包括:销售开票查询、销售结款查询和未付款查询。
4.4.1 销售开票查询
查询:设置完开票日期与查询条件后单击“查询”按钮即可查询到相关数据。其运行结果如图1.16所示。
打印:单击“打印”按钮即可打印明细表中的数据。其运行结果如图1.17所示。
图1.16 销售开票查询
图1.17 打印
4.4.2 销售结款查询
其详细的操作步骤请参考4.4.1节“销售开票查询”的操作步骤即可。
4.4.3 未付款查询
其详细的操作步骤请参考4.4.1节“销售开票查询”的操作步骤即可。
第5章 配送管理
配送管理主要包括:配送申请、配送审核、配送查询、在途管理和配送反馈信息维护。
5.1 配送申请
新增:单击“新增”按钮,在“出库票号”和“经手人”文本框中可按“↑”、“↓”键对数据进行选择,输入相关信息后,单击“保存”按钮即可申请成功。其运行结果如图1.18所示。
打印:单击“打印”按钮即可打印相关数据。
图1.18 配送申请
5.2 配送审核
在“配送票号”、“审核负责人”、“配送车辆”和“驾驶员”文本框中按“↑”、“↓”键可对数据进行选择,选择后按<Enter>键即可显示数据,单击“通过审核”或“审核作废”即可实现其对应功能。其运行结果如图1.19所示。
其详细的操作步骤请参考4.4.1节“销售开票查询”的操作步骤即可。
5.4 在途管理
在途管理主要包括两个模块:分别是“在途反馈”和“在途反馈查询”。
5.4.1 在途反馈
在司机姓名文本框中按“↑”、“↓”键可自动调出浮动列表,在列表中即可选择司机,在反馈信息文本框中输入所要反馈的信息,单击“确定”按钮即可反馈成功。其运行结果如图1.20所示。
图1.20 在途反馈
5.4.2 在途反馈查询
在查询条件文本框中输入要查询的相关数据,单击“查询”按钮,窗体下方列表中即可显示查询结果。其运行结果如图1.21所示。
打印:单击“打印”按钮即可打印当前所显示的数据。
图1.21 在途反馈查询
5.5 配送反馈信息维护
其详细的操作步骤请参考第2章“商品信息维护”的操作步骤即可。
第6章 运输管理
运输管理主要包括:车辆资料维护、驾驶员信息维护、派车单写ID卡和派车回场确认。
6.1 车辆资料维护
其详细的操作步骤请参考第2章的2.1节 商品信息维护的操作步骤即可。
6.2 驾驶员信息维护
其详细的操作步骤请参考第2章的2.1节 商品信息维护的操作步骤即可。
第7章 报关管理
报关管理主要包括:报关单管理、备案清单管理、报关单审核、三检管理、查验管理、通送管理和报关过程监控。
7.1 报关单管理
新增:单击“新增”按钮,在各文本框中输入数据后,单击“保存”按钮即可添加成功。其运行结果如图1.22所示。
修改:选择要修改的数据,单击“修改”按钮,在原有的数据基础上即可对数据加以修改,修改后单击“保存”按钮即可修改成功。
删除:选择要删除的数据,单击“删除”按钮即可删除数据。
查询:在查询条件文本框中输入要查询的条件,单击“查询”按钮即可查询数据。
图1.22 报关单管理
7.2 备案清单管理
其详细的操作步骤请参考7.1节“报关单管理”的操作步骤即可。
7.3 报关单审核
双击表格可对数据进行审核。其运行结果如图1.23所示。
图1.23 报关单审核
7.4 三检管理
设置一下日期,在“所用”、“待录入”、“己录入”前任意勾选,单击“录入”按钮,勾选三检管理后,单击“保存”按钮即可。其运行结果如图1.24所示。
图1.24 三检管理
7.5 查检管理
其详细的操作步骤请参考7.4节“三检管理”的操作步骤即可。
7.6 通关管理
通关管理的操作步骤几乎和7.4节中的三检管理的操作步骤基本相同,请参考7.4节“三检管理”的操作步骤即可。
7.7 报关过程监控
在窗体左侧的列表中选择一个号后,单击“监控”按钮即可对数据进行监控,其运行结果如图1.25所示。
第8章 决策管理
决策管理主要包括:商品入库排行分析、商品出库排行分析、运输工作量分析和客户信誉度分析。
8.1 商品入库排行分析
设置一下入库日期,单击“查询”按钮即可查询到相关数据。
其查询结果有两种显示方式:一种是表格显示;另一种是图形显示。其运行结果如图1.26所示。
打印:单击“打印”按钮即可打印数据。
图1.26 商品入库排行分析
8.2 商品出库排行分析
其详细的操作步骤请参考8.1节“商品入库排行分析”的操作步骤即可。
8.3 运输工作量分析
其详细的操作步骤请参考8.1节“ 商品入库排行分析”的操作步骤即可。
8.4 客户信誉度分析
其详细的操作步骤请参考8.1节“商品入库排行分析”的操作步骤即可。
第9章 系统管理
系统管理主要包括:数据管理、系统初始化、公司设置、操作员信息维护和权限设置。
9.1 数据管理
数据管理还包括两个子模块:一个是数据备份;另一个是数据恢复。
9.1.1 数据备份
单击“…”按钮选择数据备份的路径,然后单击“备份”按钮即可对数据进行备份,其运行结果如图1.27所示。
图1.27 数据备份
9.1.2 数据恢复
单击“恢复文件路径”后的“…”按钮选择之前数据备份的路径,单击“恢复”按钮即可恢复成功,其运行结果如图1.28所示。
图1.28 数据恢复
9.2 系统初始化
单击“初始化”按钮即可清空数据。其运行结果如图1.29所示。
图1.29 系统初始化
9.3 公司设置
单击“修改”按钮即可修改数据,修改后单击“保存”按钮即修改成功。其运行结果如图1.30所示。
图1.30 公司设置
9.4 操作员信息查询
在操作员信息查询界面可对数据进行查询和打印。
设置完查询条件后,单击“查询”按钮,窗体下方的列表中即可显示查询结果。
双击窗体下方列表中的记录可以对数据进行“新增”、“修改”、“复制”、“删除”等操作,其具体的操作步骤请参考第2章2.1节“商品信息维护”的操作步骤即可。其运行结果如图1.31所示。
图1.31 操作员信息查询
9.5 权限设置
在窗体上方的用户列表中选择需要设置的“用户”,单击“修改”按钮后即可进行权限设置,最后单击“保存”按钮。其运行结果如图1.32所示。
图1.32 权限设置
第10章 注册
10.1 软件注册