进销存管理系统

本项目全部代码已同步上传至Github,仓库链接:Asgard-Tim/Vendition: 重庆大学明月科创实验班软件设计课程作业 (github.com)

一、需求分析


1.1 进销存管理业务概述

随着近年来世界各方面的发展进步和物联网时代的到来及其不断发展,货物销售行业发生了翻天覆地的巨大变革,随着从卖方市场向买方市场的转变,我国的零售行业迅速崛起,并且时时刻刻面临着日益激烈并不断变化的竞争环境。因此,提高进销存管理水平,探索降低成本的方法成为提高企业竞争力的必然选择[1]。

伴随着企业规模的不断扩大和企业效益的进一步发展,原先的管理已经不能跟上企业的发展步伐,更无法满足企业对管理工作快速、准确的要求。在销售业务不断增长的同时,公司日常所需要处理的数据量不断增长,公司内部运转周转的中间传递环节也逐渐增多,进而发展到非常的复杂的经营管理模式,同时,现在复杂多变的市场,人工管理等传统的方法方式在相关方面已无法应对。更为重要的是商品的进销存方面缺乏实时处理的相关分析,管理人员对及时传递资料和命令的需求得无法实现。最后发现如果能够在面对不同种类的货物信息时,能够让管理人员实时掌握销售流程及销售情况,进而支持管理人员对相关商品销售的运营并且可以有效地加速的周转率,从而可以进一步提高行业的服务质量。这时可以组建一个记录、更新、保存数据信息的数据库以建立和支持一个合理高效的软件项目[2]。

具体而言,进销存管理业务的核心是对于商品流动信息的储存与管理,主要涉及到商品品类的新增与删除、进货、商品销售与盘点、平库等相互关联的诸多业务流程。因此,在进销存管理系统中,我们需要让这些业务流程在系统中有所体现,从而达到高效管理的目的。

1.2 功能性需求
1.2.1 商品信息管理

在进销存管理系统中,需要提供渠道给操作管理人员以录入或删除商品信息,同时对于日常的进货与销售过程予以记录,并在需要的时候对库存中已有的商品种类与数量进行盘点,必要时还需要进行平库操作。这些流程会涉及到公司内的诸多部门,诸如采购部、市场部、财务部等,组织架构的复杂性也对软件系统设计的联动能力与处理效率提出了较高的要求。因此,我们不仅需要通过程序设计实现与实际操作对应的相关功能,对于操作人员在系统中输入的文本信息进行读取与必要的处理以模拟上述诸多对于商品实体的实际操作流程,同时还需要建立与实际仓库所对应的商品的数据库,通过对于所有商品的编号、名称、单价、库存数量与计量单位等具体信息进行存储,并在管理人员进行操作的过程中对库中存储的商品信息进行与实际情况同步的改动,实现更加高效的管理。

1.2.2 系统安全

对于公司而言,系统的安全性是软件系统设计过程中一个至关重要的考虑因素,由于系统缺乏维护管理与必要的保护措施所造成的损失与影响将是不可估量且难以弥补的。在进销存管理系统中,系统安全的问题主要可能出现在操作权限与非法输入等方面。基于这样的考虑,软件系统在处理数据时,需要对于非法的输入进行区分并给予用户一定的操作提示;在功能上,需要通过账户密码匹配的机制以对于操作人员的权限进行一定的限制从而保证系统的安全性;在存储数据时,应对于存入的数据在写入文件的同时进行一定的加密操作,防止外部人员盗取或进行修改;同时在用户进行操作时,需要同步保留用户的操作记录,在必要时以供核查。

1.3 非功能性需求
1.3.1 性能需求

1.系统必须具备高可用性,能够保证系统长时间连续运行的需求;

​ 2.系统的响应时间应尽可能的短,系统登陆、信息保存等操作响应时间小于1.5秒,信息查询等复杂操作时间小于2秒;

​ 3.数据库容量要大,能够满足商品采购、销售、库存管理等详细信息长时间保存的需求;

​ 4.可供多个用户分时使用该系统平台。

1.3.2 易用性需求

1.系统的相关提示信息一致,如进货、销售、删除、查询等操作功能,应尽可能使人容易理解;

​ 2.有明确的输入限制提示信息;

​ 3.中英文对应正确。

1.3.3 可扩展性需求

在系统底层设计时,需要强化系统的配置和扩展能力,主要体现在以下方面:

​ 1.系统底层支持的可扩展性;

​ 2.系统数据结构可搭建;

​ 3.系统信息展示的可配置性。


二、系统设计


2.1 系统开发方案

进销存系统需要在简单快速,并且容易维护的、安全性强的开发环境中进行设计[3]。

2.1.1 系统开发技术

事实上,进销存管理的过程,本质上是由操作人员对货物信息进行的一系列操作,而不论是操作人员还是货物,都是系统中的对象,操作人员具有账户和密码等属性,货物则具有编号、名称、数量的属性。基于这样的考量,本进销存管理系统基于命令行界面进行设计,利用面向对象的思想,选用Microsoft Visual Studio Code 作为系统开发工具,后台数据库采用txt格式的文本文件,开发语言选择C++语言。

2.2 技术架构设计

系统技术架构上,从上往下分为表示层、业务逻辑层和数据层。系统对每一层定义功能明确的功能接口,同时在层次内实现组件化的接口实现。层次化、模块组件化的实现,使系统具备了最大程度的灵活度,从而能对业务需求的变化作出快速的反应,使系统具有很好的扩展性。

表现层主要是调用业务逻辑层的功能与用户直接进行交互。

业务逻辑层包含了所有业务逻辑的设计与实现,如用户登录、新增商品种类、删除商品种类、商品进货、商品销售、浏览商品信息、显示操作记录、盘点等。

数据层指具体存储系统各种业务数据的数据库系统,在本进销存管理系统中,选用了txt格式的文本文件作为数据库,以便于数据的快速读写。

本进销存管理系统的总体架构如图2.1所示。

图2.1 系统体系架构图

1

2.3 功能结构与模块设计
2.3.1 系统管理

该系统包括系统界面初始化、用户注册账户、用户登录等相关功能。系统管理模块主要具体实现以下功能:

1.系统界面初始化

用户进入系统,为用户显示操作功能菜单,提示用户进行相应操作;在用户完成一项操作后,刷新界面并重新初始化当前界面。

2.用户注册账户

若用户第一次使用该系统,需要注册自己的账号并设置密码,不符合规定的密码无效,需要重新注册;完成注册操作后,系统会自动将输入的账号与密码配对并存入数据库中,供登录时进行比对。

3.用户登录

若用户已有账号或已完成注册,可输入自己的账号、密码进行登录操作,若与数据库中的已有条目相一致,则说明该用户具有操作权限,可进入进销存系统内部模块进行下一步操作;若输入的账号与密码不匹配或输入有误,会提示用户重新进行输入。

2.3.2 商品采购、销售与库存管理

商品采购、销售与库存管理系统主要包括新增商品种类、删除商品种类、商品进货、商品销售、浏览商品信息、显示操作记录、盘点与平库等相关功能。商品信息管理模块主要具体实现以下功能:

1.新增商品种类

输入需要录入系统的商品的编号、名称、单价、计量单位与库存数量等基本信息,增加商品种类,并同步在数据库中存入该商品的相关信息与操作记录。

2.删除商品种类

输入需要删除的商品种类的编号,即可在系统数据库删除该商品的所有条目信息,并在数据库中留下操作记录;若输入的商品编号无法在数据库中检索到,则该操作无效并给予用户反馈提示。

3.商品进货

对于数据库中已有的商品种类可以进行该操作,否则提示操作失败;输入需要进货的商品种类的编号,界面中会出现数据库中该商品的所有信息,再输入需要进货的数量,若进货的数量有效(为正数),会对应增加该商品的数量并存入数据库中,同时留下操作记录。

4.商品销售

对于数据库中已有的商品种类可以进行该操作,否则提示操作失败;输入需要销售的商品种类的编号,界面中会出现数据库该商品的所有信息,再输入需要销售出去的货物数量,若销售的数量有效(小于等于库存量且为正数),会对应减少该商品的数量并存入数据库中,同时留下操作记录。

5.浏览商品信息

可以将数据库中已有的所有商品的编号、名称、单价、计量单位与库存数量等基本信息以表格的形式展示在界面中以供操作人员进行核对查验。

6.显示操作记录

可以显示改变商品数量的所有操作的操作记录,包括每一次操作的操作类型、操作参数(输入的库存改变量)、操作人员账号和操作时间;其中平库操作进行标红处理。

7.盘点与平库

可以将数据库中已有的所有商品的编号、名称、单价、计量单位与库存数量等基本信息以表格的形式展示在界面中以供操作人员进行核对查验;在盘点完成后,若数据库中的商品数量与实际情况存在出入,在确认原因后可以选择进行平库操作,对于特定商品进行额外的出库或入库操作;平库操作会进行标红处理。

8.数据存储

为了保留已有的操作结果与操作记录,在每一次对于数据库中的商品进行操作时,都会从数据库中重新读取商品信息数据,并在操作完成后将改动之后的商品数据重新存入磁盘的数据库中,并在数据库中保留操作的记录以供日后查验;这也有利于不同操作人员在该系统平台上的协同操作,同时重新启动系统时程序的状态也不会发生改变。

2.4 设计目的与优势
2.4.1 设计目的

在系统界面与整体功能架构的设计上,对于两个模块均采取了先初始化界面显示操作列表、再根据用户的操作指令给予对应的提示、完成相应操作的模式进行设计,并在各个功能的完成过程中贯穿了对于数据库的读写操作以实时修改,以功能实现为导向,希望帮助操作用户更加高效地实现商品信息的读取与写入。

2.4.2 设计优势

1.界面简洁自然,各项功能列表一目了然,方便操作人员迅速完成操作,减少误操作的概率;

2.对于所有输入的位点都进行了规范化处理,保证输入的数据格式都是合乎要求的,同时对于非法的输入操作都给予了反馈警告,便于用户快速上手;

3.设计功能齐全,可以满足大多数情况下商品的采购、销售与库存管理操作;

4.运用数据库实时储存用户信息、商品信息与操作记录,方便必要时进行查询,同时也有利于保存数据,支持多用户对于系统进行操作;

5.用户登录机制与操作记录保存机制为系统的安全性提供了一定的保障。


三、系统实现


本系统的具体框架如下图3.1所示。当成功登录窗口后,用户即进入到主界面中,此时用户可以通过模块选择在自己操作权限范围内的操作,并可在各个功能模块之间进行切换。

图3.1 系统功能流程图

2

3.1 命令行界面的初始化实现

在设计时,我们根据需求,希望系统的界面能够在完成一项指令操作后刷新并重新加载操作功能菜单以使用其他功能。因此,在登录窗口与系统内部商品处理两个模块的界面加载中,采用了相同的实现逻辑以达到这一效果。具体实现逻辑如下图3.2所示。最终实现效果符合预期。

图3.2 命令行界面初始化流程图

3

3.2 登录界面——用户权限管理实现

在登录界面,系统为用户提供了三个选项卡:用户登录、用户注册与退出系统,并分别有与之对应的操作代码。具体实现时,采用了选择分支结构,对于用户输入的功能编号进行检测,并对非法的输入给予反馈,提示需要重新输入正确的功能编号(本系统中所有需要输入操作代码的地方均采用了该流程,后面不再赘述)。

对于文件的读写,在程序中创建了相应的文件操作对象以进行相应的读写操作,并在每一次操作完成后关闭文件并重新打开以重置读写指针,防止影响到后续的操作。(进销存模块的文件读写操作与这里方式相同,后面不再赘述)。

对于用户的个人信息,设计了类user,具有用户名和密码两个私有属性,并设计了一系列公有函数对其进行读写,随后在用户注册与登录环节对该类进行实例化,并对实例化后的对象进行一系列的读写操作以实现功能。(在进销存模块中,对于商品类goods与操作记录类operations也采取了相同的方式进行处理,后面不再赘述)。

若选择“退出系统”选项卡,会提示用户是否确认退出:若确认推出,则立刻自动关闭窗口,反之则重新加载界面。效果图如图3.3。

若选择“用户注册”选项卡,会提示用户输入自己想要设置的用户名与密码(会提示用户用户名和密码只能包含字母和数字;用户名若与库中已有的用户名重复,会提示注册失败;密码还限制了位数不得少于六位,若不足六位也会提示注册失败,需要重新注册);注册成功后,用户的信息会自动存入用户数据库文件“userinformation.txt”,同时重新加载界面。效果图如图3.4。

若选择“用户登录”选项卡,会提示用户输入用户名和密码,输入完成后与数据库中的对应文件进行匹配,若匹配成功则进入进销存系统模块(在程序编写过程中具体体现为进入函数login),反之则提示输入有误,请重新输入,并重新加载界面。效果图如图3.5。

该模块的详细实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
class user
{
private:
string username;
string password;
public:
void putusername(){cin>>username;}
void putpassword(){cin>>password;}
string getusername(){return username;}
string getpassword(){return password;}
};
void initialize()
{
cout<<"********************************************"<<endl;
cout<<"* 欢迎您使用进销存系统 *"<<endl;
cout<<"* *"<<endl;
cout<<"* 1.用户登录 *"<<endl;
cout<<"* 2.用户注册 *"<<endl;
cout<<"* 0.退出系统 *"<<endl;
cout<<"* *"<<endl;
cout<<"********************************************"<<endl;
cout<<"请输入您需要执行的功能编号:";
}
int main()
{
while(true)
{
fstream userinformation;
userinformation.open("userinformation.txt",ios::in|ios::app);
initialize();//初始化界面
//账号注册与登录模块
string op1;
cin>>op1;
if(op1=="1")
{
//用户登录,先让用户输入账号和密码
user user1;
int flagin=0;
cout<<"请输入您的用户名:";
user1.putusername();
cout<<"请输入您的用户密码:";
user1.putpassword();
//将用户录入的与文件中保存的账号密码进行比对
string use=user1.getusername()+" "+user1.getpassword();
while(true)
{
string inform;
getline(userinformation,inform);
if(inform=="")
break;
if(use==inform)
{
cout<<"亲爱的用户"<<user1.getusername()<<",欢迎您登录本系统"<<endl;
Sleep(1000);
system("cls");
login(user1.getusername());//进入进销存系统
flagin=1;
break;
}
}
if(flagin==0)
{
cout<<"您输入的账号或密码错误,请检查后重新输入";
Sleep(1000);
}
}
else if(op1=="2")
{
//用户注册,输入用户名与密码
user user1;
cout<<"请输入您的用户名(仅可使用数字与字母):";
user1.putusername();
//判断用户名是否已经存在
int flag=0;
while(true)
{
string name;
userinformation>>name;
string empty;
getline(userinformation,empty);
if(name=="")
break;
if(user1.getusername()==name)
{
cout<<"您输入的用户名已经存在,注册失败,请重新输入"<<endl;
Sleep(1000);
flag=1;
break;
}
}
userinformation.close();
userinformation.open("userinformation.txt",ios::in|ios::app);
if(flag==0)
{
cout<<"请输入您的用户密码(仅可使用数字或字母,不小于6位):";
user1.putpassword();
//判断用户输入的密码是否符合要求,若符合要求则录入文件
string pass=user1.getpassword();
if(pass.length()<6)
{
cout<<"您输入的密码小于6位,请重新输入"<<endl;
Sleep(1000);
}
else
{
cout<<"您已成功注册,请进行登录"<<endl;
userinformation<<user1.getusername()<<" "<<user1.getpassword()<<endl;
Sleep(1000);
}
}
}
else if(op1=="0")
{
int fl=0;
while(fl==0)
{
cout<<"您确认要退出该系统吗?(是请按1,否请按0)";
int opp;
cin>>opp;
if(opp==1)
exit(0);
else if(opp==0)
fl=1;
else
cout<<"您输入有误,请重新输入"<<endl;
}
}
else
{
cout<<"您输入了无效的操作代码,请重新输入";
Sleep(1000);
}
userinformation.close();
system("cls");
}
return 0;
}

图3.3 “退出系统”功能效果图

4

图3.4 “用户注册”功能效果图

5

6

7

图3.5 “用户登录”功能效果图

8

9

3.3 商品进销存功能实现

进入进销存模块界面,系统为用户提供了八个选项卡:新增商品种类、删除商品种类、商品进货、商品销售、浏览商品信息、显示操作记录、盘点、退出登录,并分别有与之对应的操作代码。

若选择“退出登录”选项卡,会直接退出登录,停顿一秒后回到登录主界面。效果图如图3.6。

若选择“新增商品种类”选项卡,会提示用户输入需要新增种类的商品编号(不得与数据库中已有的商品编号相同,否则会提示重新输入),并依次提示输入商品的名称、单位、价格与库存数量;提示添加成功后,该商品的信息会自动存入商品数据库文件“goodsinformation.txt”,而相应的操作记录(包括操作编号、操作的商品编号、操作的种类、操作的商品数量、操作人的用户名与操作时间等详细信息)会被录入操作数据库文件“operationinformation.txt”(“删除商品种类”、“商品进货”、“商品销售”、“盘点”等操作也会在操作完成后录入该数据库,后面不再赘述),同时重新加载界面。效果图如图3.7。

若选择“删除商品种类”选项卡,会提示用户输入需要删除的商品编号(必须是库中已有的商品种类,否则会提示重新输入);提示删除成功后,数据库中该商品的条目信息也会一并删除,同时留下操作记录,并重新加载界面。效果图如图3.8。

若选择“商品进货”选项卡,会提示用户输入需要进货的商品编号(必须是库中已有的商品种类,否则会提示重新输入),并相应显示该商品的详细信息;用户还需要输入进货量(不可以为负数,否则提示重新输入)。提示进货成功后,数据库中该商品的库存量也会相应增加,同时留下操作记录,并重新加载界面。效果图如图3.9。

若选择“商品销售”选项卡,会提示用户输入需要销售的商品编号(必须是库中已有的商品种类,否则会提示重新输入),并相应显示该商品的详细信息;用户还需要输入销售量(不可以为负数或小于库存量,否则提示重新输入)。提示销售成功后,数据库中该商品的库存量也会相应减少,同时留下操作记录,并重新加载界面。效果图如图3.10。

若选择“浏览商品信息”选项卡,将会把数据库中所有货物的详细信息列举出来以供查看。效果图如图3.11。

若选择“显示操作记录”选项卡,将会把数据库中所有操作记录的具体信息列举出来以供查看。其中,平库过程中的出库与入库操作均会被标红。效果图如图3.12。

若选择“盘点”选项卡,将会把数据库中所有货物的详细信息列举出来以供查看,并在下方提示是否需要平库。若选择不需要平库,则会直接重新加载界面;若选择需要平库,则需选择需要出库或者入库(此行会被标红以示警告),出库操作与商品销售类似,而入库操作则与商品进货类似,在此不再重复。效果图如图3.13。

该模块的详细实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
#include<iostream>
#include<fstream>
#include<string>
#include<windows.h>
#include<ctime>
#include<iomanip>
using namespace std;
string gettime()
{
time_t t=time(NULL);
tm *now=localtime(&t);
int year=1900+now->tm_year;
int mon=1+now->tm_mon;
int day=now->tm_mday;
int hour=now->tm_hour;
int min=now->tm_min;
int sec=now->tm_sec;
string to_year=to_string( year );
string to_month=to_string( mon );
string to_day=to_string( day );
string to_hour=to_string( hour );
string to_min=to_string( min );
string to_sec=to_string( sec );
return to_year+"-"+to_month+"-"+to_day+" "+to_hour+":"+to_min+":"+to_sec;
}
class goods
{
private:
string no;
string name;
string count;
string price;
int num;
public:
void putno(){cin>>no;}
void putname(){cin>>name;}
void putcount(){cin>>count;}
void putprice(){cin>>price;}
void putnum(){cin>>num;}
void putnum(int input){num=input;}
void putno(string input){no=input;}
void putname(string input){name=input;}
void putcount(string input){count=input;}
void putprice(string input){price=input;}
string getno(){return no;}
string getname(){return name;}
string getcount(){return count;}
string getprice(){return price;}
int getnum(){return num;}
};
class operations
{
private:
string no;
string kinds;
int num;
string acount;
string date;
int flag;
public:
void putno(string input){no=input;}
void putkinds(string input){kinds=input;}
void putnum(int input){num=input;}
void putacount(string input){acount=input;}
void putdate(){date=gettime();}
string getno(){return no;}
string getkinds(){return kinds;}
int getnum(){return num;}
string getacount(){return acount;}
string getdate(){return date;}
int putflag(int input){flag=input;}
int getflag(){return flag;}
};
void systeminitialize(string username)
{
cout<<"******************************************"<<endl;
cout<<"* 功能菜单 *"<<endl;
cout<<"* *"<<endl;
cout<<"* 1.新增商品种类 *"<<endl;
cout<<"* 2.删除商品种类 *"<<endl;
cout<<"* 3.商品进货 *"<<endl;
cout<<"* 4.商品销售 *"<<endl;
cout<<"* 5.浏览商品信息 *"<<endl;
cout<<"* 6.显示操作记录 *"<<endl;
cout<<"* 7.盘点 *"<<endl;
cout<<"* 0.退出登录 *"<<endl;
cout<<"* *"<<endl;
cout<<"******************************************"<<endl;
cout<<"亲爱的用户"<<username<<",欢迎进入进销存管理平台"<<endl;
cout<<"请输入您需要执行的功能编号:";
}
string CharToStr(char * contentChar)
{
string tempStr;
for (int i=0;contentChar[i]!='\0';i++)
{
tempStr+=contentChar[i];
}
return tempStr;
}
void DelLineData(char* fileName, int lineNum)
{
ifstream in;
in.open(fileName);

string strFileData = "";
int line = 0;
char lineData[1024] = {0};
while(in.getline(lineData, sizeof(lineData)))
{
line++;
if (line == lineNum)
continue;
else
{
strFileData += CharToStr(lineData);
strFileData += "\n";
}
}
in.close();

//写入文件
ofstream out;
out.open(fileName);
out.flush();
out<<strFileData;
out.close();
}
void login(string username)
{
while(true)
{
fstream goodsinformation;
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
fstream operationinformation;
operationinformation.open("operationinformation.txt",ios::in|ios::app);
systeminitialize(username);//初始化界面
//进销存系统内部操作
string op2;
cin>>op2;
if(op2=="1")
{
goods good1;
cout<<"请输入商品编号:";
good1.putno();
//检测输入商品的编号,若编号与之前的一致,则需要重新输入
int flag1=0;
while(true)
{
string no;
goodsinformation>>no;
string empty1;
getline(goodsinformation,empty1);
if(goodsinformation.eof())//判断是否读取到文件末尾
break;
if(good1.getno()==no)
{
cout<<"您输入的商品种类已经存在,本次录入操作失败,请重新输入"<<endl;
Sleep(1000);
flag1=1;
break;
}
}
goodsinformation.close();
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
if(flag1==0)
{

cout<<"请输入商品名称:";
good1.putname();
cout<<"请输入商品单位:";
good1.putcount();
cout<<"请输入商品价格:";
good1.putprice();
cout<<"请输入商品库存数量:";
good1.putnum();
cout<<"添加商品种类成功"<<endl;
goodsinformation<<setw(10)<<good1.getno()<<setw(10)<<good1.getname()<<setw(10)<<good1.getcount()<<setw(10)<<good1.getprice()<<setw(10)<<good1.getnum()<<endl;
//保留操作记录
operations operate1;
operate1.putno(good1.getno());
operate1.putkinds("新增商品种类");
operate1.putnum(good1.getnum());
operate1.putacount(username);
operate1.putdate();
operate1.putflag(0);
operationinformation<<operate1.getflag()<<endl;
operationinformation<<setw(15)<<operate1.getno()<<setw(15)<<operate1.getkinds()<<setw(15)<<operate1.getnum()<<setw(15)<<operate1.getacount()<<setw(25)<<operate1.getdate()<<endl;
operationinformation.close();
operationinformation.open("operationinformation.txt",ios::in|ios::app);
system("pause");
}
}
else if(op2=="2")
{
cout<<"请输入您需要删除的商品编号:";
string no1;
cin>>no1;
int flag2=0;
int line=1;
while(true)
{
string no2;
goodsinformation>>no2;
string name2;
goodsinformation>>name2;
string count2;
goodsinformation>>count2;
string price2;
goodsinformation>>price2;
int num2;
goodsinformation>>num2;
if(goodsinformation.eof())//判断是否读取到文件末尾
break;
if(no2==no1)
{
//删除商品信息
DelLineData("goodsinformation.txt", line);
cout<<"删除商品种类成功"<<endl;
flag2=1;
//保留操作记录
operations operate1;
operate1.putno(no2);
operate1.putkinds("删除商品种类");
operate1.putnum(num2);
operate1.putacount(username);
operate1.putdate();
operate1.putflag(0);
operationinformation<<operate1.getflag()<<endl;
operationinformation<<setw(15)<<operate1.getno()<<setw(15)<<operate1.getkinds()<<setw(15)<<operate1.getnum()<<setw(15)<<operate1.getacount()<<setw(25)<<operate1.getdate()<<endl;
operationinformation.close();
operationinformation.open("operationinformation.txt",ios::in|ios::app);
break;
}
line++;
}
goodsinformation.close();
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
if(flag2==0)
cout<<"系统中没有编号为"<<no1<<"的商品信息,删除商品失败,请检查后再试"<<endl;
system("pause");
}
else if(op2=="3")
{
cout<<"请输入需要进货的商品编号:";
goods good2;
string no1;
cin>>no1;
int flag2=0;
int line=0;
while(true)
{
line++;
string no2;
goodsinformation>>no2;
string name2;
goodsinformation>>name2;
string count2;
goodsinformation>>count2;
string price2;
goodsinformation>>price2;
int num2;
goodsinformation>>num2;
if(goodsinformation.eof())//判断是否读取到文件末尾
break;
if(no2==no1)
{
flag2=1;
//显示该商品在系统中的信息
cout<<"编号"<<setw(10)<<"名称"<<setw(10)<<"单位"<<setw(10)<<"价格"<<setw(10)<<"库存量"<<endl;
cout<<no2<<setw(10)<<name2<<setw(10)<<count2<<setw(10)<<price2<<" "<<setw(10)<<num2<<endl;
//进货
cout<<"请输入进货量:";
int num1;
cin>>num1;
//判断非负
if(num1<0)
{
cout<<"进货量不能小于零,输入有误,请重新输入"<<endl;
break;
}
good2.putnum(num1+num2);
good2.putno(no2);
good2.putname(name2);
good2.putcount(count2);
good2.putprice(price2);
DelLineData("goodsinformation.txt", line);
goodsinformation<<setw(10)<<good2.getno()<<setw(10)<<good2.getname()<<setw(10)<<good2.getcount()<<setw(10)<<good2.getprice()<<setw(10)<<good2.getnum()<<endl;
cout<<"进货成功"<<endl;
//保留操作记录
operations operate1;
operate1.putno(no2);
operate1.putkinds("商品进货");
operate1.putnum(num2);
operate1.putacount(username);
operate1.putdate();
operate1.putflag(0);
operationinformation<<operate1.getflag()<<endl;
operationinformation<<setw(15)<<operate1.getno()<<setw(15)<<operate1.getkinds()<<setw(15)<<operate1.getnum()<<setw(15)<<operate1.getacount()<<setw(25)<<operate1.getdate()<<endl;
operationinformation.close();
operationinformation.open("operationinformation.txt",ios::in|ios::app);
break;
}
}
goodsinformation.close();
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
if(flag2==0)
cout<<"系统中没有编号为"<<no1<<"的商品信息,商品进货失败,请检查后再试"<<endl;
system("pause");
}
else if(op2=="4")
{
cout<<"请输入需要售出的商品编号:";
goods good2;
string no1;
cin>>no1;
int flag2=0;
int line=0;
while(true)
{
line++;
string no2;
goodsinformation>>no2;
string name2;
goodsinformation>>name2;
string count2;
goodsinformation>>count2;
string price2;
goodsinformation>>price2;
int num2;
goodsinformation>>num2;
if(goodsinformation.eof())//判断是否读取到文件末尾
break;
if(no2==no1)
{
flag2=1;
//显示该商品在系统中的信息
cout<<"编号"<<setw(10)<<"名称"<<setw(10)<<"单位"<<setw(10)<<"价格"<<setw(10)<<"库存量"<<endl;
cout<<no2<<setw(10)<<name2<<setw(10)<<count2<<setw(10)<<price2<<" "<<setw(10)<<num2<<endl;
//进货
cout<<"请输入销售量:";
int num1;
cin>>num1;
if(num1<0)
{
cout<<"销售量不能小于零,输入有误,请重新输入"<<endl;
break;
}
int out=num2-num1;
if(out<0)
{
cout<<"库存量不足,无法销售,请核对后重新输入"<<endl;
break;
}
good2.putnum(out);
good2.putno(no2);
good2.putname(name2);
good2.putcount(count2);
good2.putprice(price2);
DelLineData("goodsinformation.txt", line);
goodsinformation<<setw(10)<<good2.getno()<<setw(10)<<good2.getname()<<setw(10)<<good2.getcount()<<setw(10)<<good2.getprice()<<setw(10)<<good2.getnum()<<endl;
cout<<"商品销售成功"<<endl;
//保留操作记录
operations operate1;
operate1.putno(no2);
operate1.putkinds("商品销售");
operate1.putnum(num2);
operate1.putacount(username);
operate1.putdate();
operate1.putflag(0);
operationinformation<<operate1.getflag()<<endl;
operationinformation<<setw(15)<<operate1.getno()<<setw(15)<<operate1.getkinds()<<setw(15)<<operate1.getnum()<<setw(15)<<operate1.getacount()<<setw(25)<<operate1.getdate()<<endl;
operationinformation.close();
operationinformation.open("operationinformation.txt",ios::in|ios::app);
break;
}
}
goodsinformation.close();
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
if(flag2==0)
cout<<"系统中没有编号为"<<no1<<"的商品信息,商品销售失败,请检查后再试"<<endl;
system("pause");
}
else if(op2=="5")
{
cout<<setw(10)<<"编号"<<setw(10)<<"名称"<<setw(10)<<"单位"<<setw(10)<<"价格"<<setw(10)<<"库存量"<<endl;
while(!goodsinformation.eof())
{
string informate;
getline(goodsinformation,informate);
if(goodsinformation.fail())
break;
cout<<informate<<endl;
}
goodsinformation.close();
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
system("pause");
}
else if(op2=="6")
{
int optime=1;
cout<<setw(15)<<"编号"<<setw(15)<<"商品编号"<<setw(15)<<"所作操作"<<setw(15)<<"数量"<<setw(15)<<"操作人账户"<<setw(25)<<"操作时间"<<endl;
while(!operationinformation.eof())
{
int flag;
operationinformation>>flag;
string empty;
getline(operationinformation,empty);
if (flag==0)
{
string informate;
getline(operationinformation,informate);
if(operationinformation.fail())
break;
cout<<setw(15)<<optime<<informate<<endl;
optime++;
}
else if (flag==1)
{
string informate;
getline(operationinformation,informate);
if(operationinformation.fail())
break;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
cout<<setw(15)<<optime<<informate<<endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED |FOREGROUND_GREEN | FOREGROUND_BLUE);
optime++;
}
}
operationinformation.close();
operationinformation.open("operationinformation.txt",ios::in|ios::app);
system("pause");
}
else if(op2=="7")
{
cout<<setw(10)<<"编号"<<setw(10)<<"名称"<<setw(10)<<"单位"<<setw(10)<<"价格"<<setw(10)<<"库存量"<<endl;
while(!goodsinformation.eof())
{
string informate;
getline(goodsinformation,informate);
if(goodsinformation.fail())
break;
cout<<informate<<endl;
}
goodsinformation.close();
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
cout<<"---------------------------------------------"<<endl;
int flagx=0;
while(flagx==0)
{
cout<<"是否需要平库?(是请按1,否请按0)";
int op3;
cin>>op3;
if(op3==1)
{
int flagy=0;
while(flagy==0)
{
//设置红色字体
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
cout << "您需要出库还是入库?(出库请按1,入库请按0):" ;
int op4;
cin>>op4;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED |FOREGROUND_GREEN | FOREGROUND_BLUE);//把颜色换回来
if(op4==0)
{
flagy=1;
cout<<"请输入需要入库的商品编号:";
goods good2;
string no1;
cin>>no1;
int flag2=0;
int line=0;
while(true)
{
line++;
string no2;
goodsinformation>>no2;
string name2;
goodsinformation>>name2;
string count2;
goodsinformation>>count2;
string price2;
goodsinformation>>price2;
int num2;
goodsinformation>>num2;
if(goodsinformation.eof())//判断是否读取到文件末尾
break;
if(no2==no1)
{
flag2=1;
//入库
cout<<"请输入入库量:";
int num1;
cin>>num1;
//判断非负
if(num1<0)
{
cout<<"入库量不能小于零,输入有误,请重新输入入库量:";
break;
}
good2.putnum(num1+num2);
good2.putno(no2);
good2.putname(name2);
good2.putcount(count2);
good2.putprice(price2);
DelLineData("goodsinformation.txt", line);
goodsinformation<<setw(10)<<good2.getno()<<setw(10)<<good2.getname()<<setw(10)<<good2.getcount()<<setw(10)<<good2.getprice()<<setw(10)<<good2.getnum()<<endl;
cout<<"商品盘点成功"<<endl;
//保留操作记录
operations operate1;
operate1.putno(no2);
operate1.putkinds("盘点入库");
operate1.putnum(num2);
operate1.putacount(username);
operate1.putdate();
operate1.putflag(1);
operationinformation<<operate1.getflag()<<endl;
operationinformation<<setw(15)<<operate1.getno()<<setw(15)<<operate1.getkinds()<<setw(15)<<operate1.getnum()<<setw(15)<<operate1.getacount()<<setw(25)<<operate1.getdate()<<endl;
operationinformation.close();
operationinformation.open("operationinformation.txt",ios::in|ios::app);
break;
}
}
goodsinformation.close();
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
if(flag2==0)
cout<<"系统中没有编号为"<<no1<<"的商品信息,商品盘点失败,请检查后再试"<<endl;
}
else if(op4==1)
{
flagy=1;
cout<<"请输入需要出库的商品编号:";
goods good2;
string no1;
cin>>no1;
int flag2=0;
int line=0;
while(true)
{
line++;
string no2;
goodsinformation>>no2;
string name2;
goodsinformation>>name2;
string count2;
goodsinformation>>count2;
string price2;
goodsinformation>>price2;
int num2;
goodsinformation>>num2;
if(goodsinformation.eof())//判断是否读取到文件末尾
break;
if(no2==no1)
{
flag2=1;
//出库
cout<<"请输入出库量:";
int num1;
cin>>num1;
if(num1<0)
{
cout<<"出库量不能小于零,输入有误,请重新输入出库量:";
break;
}
int out=num2-num1;
if(out<0)
{
cout<<"库存量不足,无法完成出库操作,请核对后重新输入出库量:";
break;
}
good2.putnum(out);
good2.putno(no2);
good2.putname(name2);
good2.putcount(count2);
good2.putprice(price2);
DelLineData("goodsinformation.txt", line);
goodsinformation<<setw(10)<<good2.getno()<<setw(10)<<good2.getname()<<setw(10)<<good2.getcount()<<setw(10)<<good2.getprice()<<setw(10)<<good2.getnum()<<endl;
cout<<"商品盘点成功"<<endl;
//保留操作记录
operations operate1;
operate1.putno(no2);
operate1.putkinds("盘点出库");
operate1.putnum(num2);
operate1.putacount(username);
operate1.putdate();
operate1.putflag(1);
operationinformation<<operate1.getflag()<<endl;
operationinformation<<setw(15)<<operate1.getno()<<setw(15)<<operate1.getkinds()<<setw(15)<<operate1.getnum()<<setw(15)<<operate1.getacount()<<setw(25)<<operate1.getdate()<<endl;
operationinformation.close();
operationinformation.open("operationinformation.txt",ios::in|ios::app);
break;
}
}
goodsinformation.close();
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
if(flag2==0)
cout<<"系统中没有编号为"<<no1<<"的商品信息,商品进货失败,请检查后再试"<<endl;
}
else
cout<<"输入有误,请重新输入"<<endl;
}
flagx=1;
}
else if(op3==0)
flagx=1;
else
cout<<"输入有误,请重新输入"<<endl;
}
goodsinformation.close();
goodsinformation.open("goodsinformation.txt",ios::in|ios::app);
system("pause");
}
else if(op2=="0")
{
cout<<"正在为您登出中……";
Sleep(1000);
return;
}
else
{
cout<<"您输入了无效的操作代码,请重新输入";
Sleep(1000);
}
goodsinformation.close();
operationinformation.close();
system("cls");
}
}

图3.6 “退出登录”功能效果图

10

图3.7 “新增商品种类”功能效果图

11

12

图3.8 “删除商品种类”功能效果图

13

14

图3.9 “商品进货”功能效果图

15

16

17

图3.10 “商品销售”功能效果图

18

19

20

21

图3.11 “浏览商品信息”功能效果图

22

图3.12 “显示操作记录”功能效果图

23

图3.13 “盘点”功能效果图

24


四、总结


本文首先对进销存管理业务的现状进行归纳,通过分析目前的进销存管理流程,找出存在的问题和原因,对信息化手段给进销存管理带来的好处进行评估,并制订流程以改进管理方案,从系统功能、性能、运行环境等方面提出进销存管理系统的需求,确定开发方案,本着面向对象编程的核心思想,根据数据结构,找到实体间的关系,细化设计思路,并最终依托命令行界面完成了整个进销存管理系统的设计与实现。 根据需要,本进销存管理系统采用三层架构设计,功能模块涵盖了系统管理与商品信息管理两大板块,采用文本文件作为整个系统的数据库,具有实用性、通用性、使用性、扩充性、安全性能高,维护成本低等优点。

在完成了初版的整体设计以及程序实现之后,又对其各项功能进行了多方面的测试,针对其中不足的方面以及小的漏洞进行了进一步的调试、修正、完善与迭代,目前已经能够正常运行。在整个项目的完成过程中,一方面是对于C++编程语言的掌握在实践中进行又一次的巩固加强,另一方面也是对于面向对象这一重要的程序设计思想的深入体会。

总而言之,个人对于本次进销存管理系统项目的完成度是比较满意的,但目前的系统程序仍然存在着许多问题有待于进一步深入研究与学习。一方面是模块化的程度并没有达到预期的效果,整个程序结构仍然稍显冗长。事实上在整个程序设计过程中,受限于不断要对文件进行读写,很难将每一个选项卡单独拆分出来作为独立的函数,同时对于面向对象过程中类的使用仅仅停留在对于其内部私有成员的封装与访问,而并没有涉及到更进一步的针对于特定对象的函数编写与使用 ,希望之后可以进行进一步的迭代与改进。另一方面,虽然在界面设计时本着简洁实用的思想,但很多流程上以及设计上的细节仍然可以进一步深挖改进,这也需要基于一定的实际投放测试并收集反馈来进行;同时受限于时间紧迫,对于QT图形界面无法进行详细的学习以应用在本项目中,希望如果之后有机会可以基于QT界面对于本进销存管理系统进行进一步的重塑与迭代。


参考文献


[1] 郭宁 , 郑小玲.管理信息系统[M].北京 : 人民邮电出版社 , 2009.

[2] 刘俊 , 钱瑞明 , 基于 B/S 结构、面向供应链的供销管理系统设计[J] , 微计算机管理 , 2004 ( 1 ) : 42-43

[3] 吴雪海.食品公司进销存系统设计与实现[D].导师:赫枫龄;张雪松.吉林大学,2015.

作者

明诚

发布于

2023-05-02

更新于

2023-08-03

许可协议

评论