关键词 银行帐户系统;VC;ODBC; SQL Server 2000
随着银行行业的发展,银行的业务发展也逐渐地走向了多样化,业务类型逐渐增多,使银行的服务范围逐渐地变广,随着经济全球化的发展很多银行已走向了国际化,不仅为国内的众多客户提供了更优质服务,还使外国公民从中获得更多益处。
本系统主要实现了开户、销户、用户信息修改、存款、取款、办卡、挂失卡、数据查询(用户信息查询,及交易记录查询)。根据这些功能及系统设计方面的考虑,系统采用模块化设计,各模块分别实现为:
“管理用户模块”包括:
开户:由客户提供姓名、身份证号、联系地址、联系电话、存入金额、初始密码等。开户时间有系统自动生成。
销户:提供帐号用于销户,系统显示客户姓名及余额以便确认。
数据查询:查询客户存取款记录。
用户信息查询及修改:通过帐号、卡号、证件号进行查询。系统显示客户信息并可修改。
“管理员模块”包括:
业务设置:利率等相关业务设置。
管理员密码修改:修改登录的管理员密码。
“卡管理模块” 包括:
办卡:输入帐号信息,生成卡号,并由客户提供密码。
换卡:输入帐号信息,生成新卡号,并由客户提供密码。
挂失卡:由客户提供卡号及身份证号(此为真实用户挂失依据)。
“存取操作模块” 包括:
存款:提供帐号或卡号以及存款金额,操作完成后显示余额。
取款:提供帐号或卡号以及取款金额,操作完成后显示余额。
同时,系统还实现了客户信息及客户交易记录的打印功能。
根据本系统实现的功能,我们需要建立5个表,分别是用户数据表user_data,用户密码表user_password,交易记录表user_exchange,用户余额表user_balance,管理员密码表admin_password。user_data表用于开户时,前台应用将用户开户时所需要的客户信息写入此表。
其中包括的数据有用户名、证件号、联系地址、联系电话、业务类型、存入金额、开户时间、帐号、卡号,共9个数据。为了便于简化前台应用与数据库的存取,其数据类型都设为字符型(char),但不影响正常的程序功能与精度。如user_data建立如表1所示。
表1 user_data表
列名 | 数据类型 | 长度 | 允许空 |
用户名 | char | 15 | |
证件号 | char | 20 | |
联系地址 | char | 80 | |
联系电话 | char | 15 | |
业务类型 | char | 15 | |
存入金额 | char | 15 | |
开户时间 | char | 20 | |
帐号 | char | 15 | |
卡号 | char | 15 | 允许 |
创建user_data表的SQL语句为:
USE BankManager
CREATE TABLE user_data
(
用户名 char(15) NOT NULL,
证件号 char(20) NOT NULL,
联系地址 char(80) NOT NULL,
联系电话 char(15) NOT NULL,
业务类型 char(15) NOT NULL,
存入金额 char(15) NOT NULL,
开户时间 char(20) NOT NULL,
帐号 char(15) NOT NULL,
卡号 char(15) NULL
)
GO
因为各模块的代码实现基本上都是在用CRecordset类,所以在这里只给出具有代表性的代码实现的分析,其它模块的代码不再讲述。
先来分析登录代码:
登录代码的第一个语句为:
UpdateData(true);
这条语句是将登录对话框中的数据传递给Login类中对应绑定的String变量。这样可以对用户输入的用户名、密码、数据源等信息进行分析处理。
然后我们需要判断用户是否输入了用户名、密码和数据源,如果没有输入提示用户输入。代码如下:
if(m_UserName==_T(""))
{
MessageBox("请输入用户名!");
return ;
}
if(m_Password==_T(""))
{
MessageBox("请输入密码!");
return ;
}
DataSource="ODBC;DSN=";
DataSource+=m_DataSource;
if(m_Database.Open(NULL,false,false,DataSource)==false)
{
MessageBox("请正确输入数据源!");
return ;
}
如果用户输入了用户名、密码、数据源信息,我们还需要根据管理员静态变量Admin,判断用户是作为管理员登录还是用户登录。
如果是管理员登录,就查找admin_password表,要访问Admin_password表,我们需要先建立个CRecordset类:
CRecordset m_PasswordSet(&m_Database);
用前面打开的数据库连接构造CRecordset类。
然后必须打开此记录集,打开时,第一个参数指定记录集以向前只读方式打开,第二项用SQL语句指定返回给记录集的列,代码如下:
CString strSQL;
strSQL.Format("select * from admin_password where [管理员]='%s'",m_UserName);
m_PasswordSet.Open(CRecordset::forwardOnly,strSQL);
在此,我们忽略了对Admin变量的判断。
下一步判断是否存在此管理员,通过记录集类的IsEOF()可以知道返回的记录集是否有记录,没有说明不存在此管理员,那就return。
if(m_PasswordSet.IsEOF())
{
MessageBox("没有此管理员!");
m_PasswordSet.Close();
m_Database.Close();
return ;
}如果有记录我们需要判断管理员密码是否正确,首先要先把密码取出,然后跟用户的输入进行比较。
CString tempPWD;
m_PasswordSet.GetFieldValue("密码",tempPWD);
if(tempPWD.Compare(m_Password))
{
MessageBox("密码错误,请正确输入管理员名和密码!");
m_PasswordSet.Close();
m_Database.Close();
return ;
}
如果是作为用户登录,就查询user_password表中的卡号和卡密码,这是先建立记录集类,这次我们建立的是我们自己定义的派生自CRecordset类的CuserPasswordSet类,此类中的数据与user_data表中的数据对应,已经绑定好。打开方式我们选CRecordset::snapshot,即快照方式,因为我们在后面要对数据库中绑定的数据进行查询(使用Requery()函数),其实我们也是可以用前面查询admin_password表的方法的。
strSQL.Format("select * from user_password where [卡号]='%s'",m_UserName);
CUserPasswordSet m_PasswordSet(&m_Database);
m_PasswordSet.Open(CRecordset::snapshot,strSQL);
然后我们看看是否存在此卡号,与前面的方法相同。
下一步我们查询user_data表中的挂失状态,看看是否此卡已经挂失,若挂失就return。
m_PasswordSet.Requery();
if(m_PasswordSet.status==TRUE)
{
MessageBox("此卡已经挂失,暂不能用!");
m_PasswordSet.Close();
m_Database.Close();
return ;
}
然后就是确认密码是否正确了,与前面不同的是用m_PasswordSet.m_CardPassword!=m_Password 进行判断,m_CardPassword与数据库中的卡密码对应。
如果用户输入的各项数据都正确,就销毁登录框,进入主界面。
CDialog::OnOK();
如果用户按了“取消”,退出整个程序,实现是在BankManager.cpp中的InitInstance()中完成的。如下:
Login* m_pLogin=new Login();
if(IDCANCEL==m_pLogin->DoModal())
{
return false;
}
接下来我们分析开户模块:
开户时我们需要在user_data表中添加数据,所以要用记录集类中的AddNew()和Update()函数。一些代码实现与登录框的很相近,我们就主要说差别的地方。
首先我们检测用户是否输入了所有数据,并且检测存入金额是否合法:
if(m_CunRuJinE<COleCurrency(0, 0))
{
MessageBox("输入的“存入金额”小于零!");
return ;
}
然后查看“证件号”是否使用过,若使用过就提示并返回,方法和查看前面的卡号是否挂失等同。
下一步取得用户的帐号密码给全局变量transfer:
CPassword m_Password;
if(IDOK!=m_Password.DoModal())
return ;
然后整理要存入数据库的各变量值,大部分是由用户输入的,而卡号和开户时间是由系统生成的。
根据用户的输入,将业务类型记录到m_Item变量中。
开户时间的生成比较简单,建立了ColeDateTime后,获得当前时间并格式化成字符串后即可:
COleDateTime now;
now=COleDateTime::GetCurrentTime();
m_KaiHuShiJian=now.Format();
帐号利用时间生成(后来的卡号也是),前面加个A,是Accounts的第一个字母,共15位。
最后我们要把数据写入各个表先打开对应的记录集,然后AddNew(),添加新值,下一步Update(),最后对所有表进行更新。
比如说向user_data表写数据:
m_DataSet.Open(); //CRecordset::snapshot,strSQL1
if(!m_DataSet.IsEOF())
m_DataSet.MoveLast();
m_DataSet.AddNew();
m_DataSet.m_UserName=m_XingMing;
m_DataSet.m_Type=m_Item;
m_DataSet.m_Certificate =m_ZhengJianHao;
m_DataSet.m_Accounts =m_ZhangHao;
m_DataSet.m_Address = m_LianXiDiZhi;
m_DataSet.m_Telephone = m_LianXiDianHua;
m_DataSet.m_Time =m_KaiHuShiJian;
m_DataSet.m_Currency = m_CunRuJinE.Format();
密码表需要写入帐号、密码和挂失状态,余额表写入帐号和余额,写入方法同写入user_data一样。更新如下:
if(m_BalanceSet.Update()&&m_DataSet.Update()&&m_UserPassword.Update())
MessageBox("开户成功!");
else
MessageBox("开户失败!");
在我们的应用程序中,一用到密码,基本上都要调用密码框,相应的类是CPassword,它的作用是将用户输入的密码传递给全局变量transfer。代码如下:
UpdateData(true);
if(m_Password1.GetLength()!=6||m_Password2.GetLength()!=6)
MessageBox("你确认输入6位密码!");
else if(m_Password1!=m_Password2)
MessageBox("请确认两次输入的密码一致!");
else
{
transfer=m_Password1;
CDialog::OnOK();
}
文中设计的银行帐户系统主要用VC和SQL Server 2000,对于VC我们要掌握MFC的编程框架,以及一些类的使用,这些类主要是CDatabase类、CRecordset类、COleDateTime类、COleCurrency类、CString类、CcomboBox类,而这里主要应用的就是CRecordset类。因为这个系统可以说就是一个数据库应用程序,而文中使用的是ODBC编程,所以程序的编写也就应用MFC提供的ODBC类。在整个的设计过程中应用的类成员函数有:CRecordset类中Open(),AddNew(),Edit(),Delete(),Update(),Close()Requery(),GetFieldValue(),IsEOF();Cdatabase类中的Open(),Close();ColeDateTime类中 GetCurrentTime(),Format(),GetYear(),GetMonth(),GetDay(),GetHour(),GetMinute(),GetSecond();COleCurrency类中的Format();CString类中的Format();CcomboBox类中的GetCurSel();这些函数有的需要带一些复杂的参数,而且还是多态的,设计过程中要多加留意。
[1] 刘胜华.个性化银行帐户的设想.《金融电子
化》2004年12月7日.第12期,总第111期
[2] 陈爱云.银行帐户管理有待电子化.《金融电子化》2004年11月7日.第11期,总第110期
[3] 黄明,梁旭,周绍斌.Visual C++信息系统设计与开发实例. 北京:机械工业出版社,2005