资源描述
服务项目管理系统
48
2020年5月29日
文档仅供参考
服务项目管理系统
设计说明书
1 软件背景 1
1.1 可行性分析 2
1.1.1 功能可行性 2
1.1.2 经济可行性 2
1.1.3 管理可行性 2
2 软件概述及设计方案 3
软件构架图 7
功能结构分析 7
3 针对软件的各功能模块做具体的设计描述及附注相关设计结果 8
3.1 服务产品管理 8
3.1.1 功能简介 8
3.1.2 功能说明 9
3.1.3 数据表设计 9
3.2 服务方案管理 9
3.2.1 功能简介 9
3.2.2 功能说明 10
3.2.3 数据表设计 10
3.3 培训管理 11
3.3.1 功能简介 11
3.3.2 功能说明 11
3.3.3 数据表设计 11
1 软件背景
系统的背景是:近年来,随着it服务行业的发展,对服务项目管理方面产生了很大需求,针对此需求提出开发服务项目管理系统的必要,能够实现出更多的用途或满足更多需要。与原有技术相比所体现出方便快捷优势。服务项目管理系统是服务项目管理软件的通俗化名称,服务项目管理系统是服务产品管理、服务方案管理,培训管理统计销售业绩的先进工具,适合企业管理部门办公使用,协助方案经理和方案人员快速管理客户、服务和业务的重要数据。服务项目管理系统是典型的信息管理系统(MIS),其开发主要包括后台数据库的建立和维护以及前端应用程序的开发两个方面。对于前者要求建立起数据一致性和完整性强、数据安全性好的库。而对于后者则要求应用程序功能完备,易使用等特点。
1.1 可行性分析
1.1.1 功能可行性
1) 系统完整性:整个服务项目管理系统具备系统设计的科学合理性,方案管理信息录入,修改,删除及学生成绩的查询等功能符合学校对学生的管理要求,满足了相关人员对信息管理的要求,适用于复杂的学生管理,因而达到了设计任务的要求.
2) 系统的可靠性:该系统可靠性高,能无故障正常的工作,当出现异常情况是还采取了一些防止系统破坏的方法和措施,如密码保存,数据备份等.
3) 系统的效率:与旧系统相比,减轻了许多重复的繁琐的劳动和手工计算量,抄写量,在对学生成绩进行评价和统计方面效率提高了不少.
4) 系统的工作质量:学生管理系统所提供数据的精确度,输出结果的易读性都能达到用户要求,使用方便,使学生管理工作变得轻松,有序而有效.
5) 系统的灵活性:系统的环境是不断变化的,因而该学生管理系统具有一定的扩充性,修改信息方便简易,能够、适应环境的变化.
1.1.2 经济可行性
6) 减少资金占用.由于实施了服务项目管理系统,资源得到了充分利用,减少和避免了资金的使用不当.
7) 缩短查询时间.由于采用新技术,大大缩短了查询时间,推进了管理水平.
8) 减少人员.由于实施该系统,在总体工作质量上升的情况下,可减少一半管理人员,减少工资奖金等支出.
1.1.3 管理可行性
各个方案的管理人员能够对管理方案进行编辑,添加,删除
各培训管理人员可对培训方案进行编辑,添加删除,实现了管理上的角色分配,普通用户只能对方案和培训课程进行查看
2 软件概述及设计方案
服务项目管理系统系统应用于it服务项目管理方面,采用了Hessian 、 HttpInvoker 、 XFire 、 Axis 等多种形式的远程调用技术,实现了服务端生成骨架,对外暴露服务;客户端生成服务代理,访问调用服务等技术特点及各功能模块。
在现代 J2EE 企业应用系统中,存在着 Hessian 、 HttpInvoker 、 XFire 、 Axis 等多种形式的远程调用技术。尽管有 Spring 等框架对这些技术进行了封装,降低了使用的复杂度,但对普通程序员而言仍是复杂的—至少需要要掌握这些技术的基础知识。
无论使用那种技术,其基本原理都是一样的:服务端生成骨架,对外暴露服务;客户端生成服务代理,访问调用服务。一般情况下,生成服务代理的代价比较高昂,这也是我们第一次访问远程服务速度比较慢的原因,为每个请求生成新的服务代理恐怕不是我们所期望的。更何况,如果采用这种方式,就要在代码里针对各种不同的技术(如 XFire 、 HttpInvoker )编写不同的服务生成和调用的处理代码。不但麻烦,而且容易出错。我想,没有人愿意去直接操作各种框架技术的底层代码,这并不是一个好注意!
作为一种替代方案,我们设计了一个”服务池”的功能,或者说”服务工厂”更贴切一点。
针对 HttpInvoker 、 XFire 、 Hessian 等各种远程调用技术,抽象出一个”远程服务池”(服务工厂)既 RemoteServicePool 接口。该接口提供了获取服务及一些其它的辅助功能,并针对 HttpInvoker 、 XFire 、 Hessian 等不同技术提供了相应的具体实现。采用这种方式,开发人员只需在代码中”注入” RemoteServicePool ,并以统一的方式(如 getService() )获取实际的服务,只是针对不同技术在配置上有些须差异而已。该技术的原理非常简单,在应用启动之前把所有存在的服务提供者提供的服务都配置好,并为它们分配一个唯一的 ID 。应用启动之后,框架会自动生成和这些地址相对应的服务代理( ServiceProxy ),这些代理已经是可用的服务,服务获取的细节被完全屏蔽掉,开发者只要知道如何从 RemoteServicePool 中获取服务就能够了。
该方案还为”双向关联”的系统服务提供了一个很好解决办法。看下面一张图:
如图,系统 B 和系统 C 都调用系统 A 进行付款操作;同时系统 A 要用远程服务向系统 B 或系统 C 进行认证操作,认证操作的接口(契约)都是一样的,业务逻辑可能有所差异。在这种情况下,配置在系统 A 中的认证服务就比较麻烦,因为要根据不同的系统调用认证服务,既从 B 过来的请求要访问 B 的认证服务,从 C 过来的请求要访问 C 的认证服务。用服务池能够很好的解决这个问题,把两个系统( B 、 C )提供的认证服务地址都配置在同一个服务池中,根据不同的 ID (如 B 、 C )来决定使用那个系统的服务。
尽管服务池解决了一些问题,在某种程度上降低了复杂度,但仍存在如下一些问题:
服务的运行期动态注册
服务的自动注入( IoC )
透明化服务 ID 的传递
在服务池( ServicePool )概念的基础上进行扩展,我们得出了如下的系统模型:
在核心位置上是一个服务中心资源库( ServiceRepository ),存储了系统中用到的所有的远程服务。服务采取动态注册的机制,由对外提供的服务注册器( ServiceRegister )提供服务注册功能。外部系统能够实现该接口向资源中心注册服务。提供了一个启动时运行的注册器,能够把静态配置在系统中的服务都注册进来。
服务的生成、管理等均由服务中心自己维护,委托服务代理生成器( ServiceProxyGenerator )完成服务的创立。能够针对现有的远程调用方式,如 XFire,HttpInvoker,Hessian 等创立服务代理,也能够针对自己定义的远程调用方式创立服务代理,由 CustomServiceProxyGenerator 完成该功能。
一个服务模型包括 5 个因素:
服务接口 serviceClass
服务 ID serviceId
服务类型 serviceType
服务地址 serviceUrl
附加属性 props
查找一个服务需要两个因素,一个是服务接口,另一个是服务 ID 。这两个因素共同决定了一个服务,既服务中心内部的”服务 ID ”。经过这种方式,能够允许存在多个 ID 相同但接口不同的服务,也能够存在多个接口相同但 ID 不同的服务。
服务 ID 的获取是系统中一个关键的功能,这部分对程序员来说应该是透明的,由系统自己维护。相应的提供了一个服务 ID 提供者 (ServiceIdProvider) 接口,由实现该接口的子类完成服务 ID 获取功能(这是比较关键的地方,需要特殊考虑)。
设计方案
服务产品管理是能够在此模块中维护公司所能提供的服务产品。方案人员能够浏览服务产品列表,而且在查询区域输入适当的查询条件进行查询。服务产品除了一些基本信息外,还包括服务产品文档,负责人能够随意为服务产品添加产品文档。
服务方案管理是商机在立项以后都会给客户提供方案,此模块就是用以维护服务方案数据的。服务方案除了基本信息以外还包括方案正文,方案PPT和方案预算表。方案人员除了方案预算表外,其它的数据都能够维护和查看。商务人员对所有服务方案可见,而且能够查看和更新每个方案的方案预算表。公司领导能够查看所有服务方案。
培训管理是培训负责人维护各自负责的培训课程(Course)。培训课程数据的查询功能向全体员工开放,每个员工都能够查看公司所提供的培训课程,下载课程培训文档。员工还能够登录系统查看近期安排的培训日程,而且报名培训。当培训结束后,培训负责人能够给每个学员维护她们的完成状态(参加,或缺席)。
软件构架图
功能结构分析
服务项目管理系统
服务产品管理
服务方案管理
培训管理
服务产品详情
服务产品的修改
培训课程显示
培训课程的修改
角色分配
培训课程查看
培训课程的修改
3 针对软件的各功能模块做具体的设计描述及附注相关设计结果
3.1 服务产品管理
3.1.1 功能简介
每个方案人员能够在此模块中维护公司所能提供的服务产品。方案人员能够浏览服务产品列表,而且在查询区域输入适当的查询条件进行查询。针对查询结果,还能够对服务产品数据进行添加,删除,修改等操作,每个服务产品都会有一个负责人,每个服务产品只能由负责人进行删除或修改,其它人员只能进行查看。服务产品除了一些基本信息外,还包括服务产品文档,负责人能够随意为服务产品添加产品文档。服务产品应该同时向所有公司员工开放,全员能够查看并学习。
3.1.2 功能说明
Ø 服务产品详情
Ø 服务产品的管理,添加,删除,修改
3.1.3 数据表设计
表名:s_service_product服务产品
显示名称
字段名称
字段类型
NULL
PK/FK
备注
产品编号
service_product_id
VARCHAR(10)
NOT NULL
PK
应用程序赋值(4产品类别字母+3位流水号)
产品名称
service_solution_name
VARCHAR(50)
NOT NULL
产品类别
service_product_type
VARCHAR(20)
NOT NULL
产品负责人
service_product_owner
VARCHAR(5)
NOT NULL
FK( s_employee: emp_no )
产品审核人
service_product_approver
VARCHAR(5)
NULL
FK( s_employee: emp_no )
创立日期
create_date
date
NOT NULL
备注
notation
VARCHAR(100)
NULL
3.2 服务方案管理
3.2.1 功能简介
每个商机在立项以后都会给客户提供方案,此模块就是用以维护服务方案数据的。方案人员能够添加,删除,修改服务方案,而且能够浏览和查询已有的服务方案。服务方案除了基本信息以外还包括方案正文,方案PPT和方案预算表。方案人员除了方案预算表外,其它的数据都能够维护和查看。方案总监同样能够对服务方案数据进行增加,删除,修改和查询,而且对每个服务方案的所有属性可见,包括方案预算表。商务人员对所有服务方案可见,而且能够查看和更新每个方案的方案预算表。公司领导能够查看所有服务方案。
3.2.2 功能说明
Ø 客户方案的提供
Ø 管理员对客户方案的修改
Ø 不同人对方案的查看
3.2.3 数据表设计
表名:s_service_solution服务方案
显示名称
字段名称
字段类型
NULL
PK/FK
备注
方案编号
service_solution_id
VARCHAR(10)
NOT NULL
PK
与商机编号一致
方案名称
service_solution_name
VARCHAR(50)
NOT NULL
方案日期
service_solution_date
date
NOT NULL
方案负责人
service_solution_owner
VARCHAR(5)
NOT NULL
FK( s_employee: emp_no )
方案审核人
service_solution_approver
VARCHAR(5)
NULL
FK( s_employee: emp_no )
方案满意度
content_degree_sale
int
NULL
上级满意度
content_degree_leader
int
NULL
方案正文
service_solution_file
int
NULL
FK( s_common_file: file_id )
方案PPT
service_solution_ppt
int
NULL
FK( s_common_file: file_id )
项目预算表
budget_file
int
NULL
FK( s_common_file: file_id )
项目人员成本预算
budget_amount
int
NOT NULL
默认值:0
3.3 培训管理
3.3.1 功能简介
培训负责人维护各自负责的培训课程(Course)。在培训课程维护界面,培训负责人能够增加,删除,修改,浏览和查询培训课程。培训负责人不能访问其它培训负责人负责的培训课程。除此之外,培训课程数据的查询功能向全体员工开放,每个员工都能够查看公司所提供的培训课程,下载课程培训文档。
培训负责人还能够安排具体的培训日程。每个培训日程包括培训课程,报名截止时间,开课时间,报名人数,培训地点等属性。培训负责人能够创立,删除,修改,浏览和查询培训日程。同时员工还能够登录系统查看近期安排的培训日程,而且报名培训。如果尚未到达报名截止日期,允许员工撤销培训报名。培训负责人还能够管理培训日程的进度:培训负责人能够查看报名学员的列表;到了培训报名截止日期时,培训负责人能够给每个员工”发送培训通知”;当培训结束后,培训负责人能够给每个学员维护她们的完成状态(参加,或缺席)。
3.3.2 功能说明
Ø 培训课程信息的查看
Ø 培训课程信息的修改
Ø 培训负责人的特权
3.3.3 数据表设计
表名:s_course培训课程
显示名称
字段名称
字段类型
NULL
PK/FK
备注
课程编号
course_id
VARCHAR(10)
NOT NULL
PK
应用程序赋值(1位课程类别+3位流水号)
课程类别
course_type
VARCHAR(10)
NOT NULL
课程名称
course_name
VARCHAR(50)
NOT NULL
培训方式
training_mode
VARCHAR(30)
NOT NULL
课程创立日期
course_create_date
date
NOT NULL
人均培训费用
cost_per_trainee
int
NOT NULL
课程讲师
course_trainer
VARCHAR(5)
NULL
FK( s_employee: emp_no )
培训负责人
course_owner
VARCHAR(5)
NOT NULL
FK( s_employee: emp_no )
教材
material_id
int
NULL
FK( s_common_file: file_id )
表名:s_lesson培训日程
显示名称
字段名称
字段类型
NULL
PK/FK
备注
培训日程ID
lesson_id
VARCHAR(20)
NOT NULL
PK
应用程序赋值(4位课程编号+3位流水号 )
课程编号
course_id
VARCHAR(10)
NOT NULL
FK( s_course: course_id )
报名截止时间
sign_up_end_date
date
NOT NULL
报名人数
intended_attendance
int
NOT NULL
默认值:0
已报名人数
real_attendance
int
NOT NULL
默认值:0
开课时间
lesson_begin_date
date
NOT NULL
结束时间
lesson_end_date
date
NOT NULL
授课地点
lesson_place
VARCHAR(50)
NOT NULL
课程讲师
lesson_trainer
VARCHAR(5)
NULL
FK( s_employee: emp_no )
培训负责人
lesson_owner
VARCHAR(5)
NOT NULL
FK( s_employee: emp_no )
备注
notation
VARCHAR(100)
NULL
表名:s_lesson_trainee培训名单
显示名称
字段名称
字段类型
NULL
PK/FK
备注
培训学员ID
lesson_trainee_id
int
NOT NULL
PK
数据库自动增长ID
培训日程ID
lesson_id
VARCHAR(20)
NOT NULL
FK( s_lesson: lesson_id )
培训负责人
trainee_no
int
NOT NULL
FK( s_employee: emp_no )
完成情况
feedback
VARCHAR(100)
NULL
代码:
package com.lenovoai.nicemis.web.action;
import org.springframework.web.struts.ActionSupport;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.context.ApplicationContext;
import com.lenovoai.nicemis.service.*;
import com.lenovoai.nicemis.model.*;
import com.lenovoai.nicemis.model.security.*;
import com.lenovoai.nicemis.util.*;
import java.util.*;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) </p>
* <p>Company: </p>
* @author not attributable
* @version 1.0
*/
public class FindServiceProductsForAllAction
extends ActionSupport {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
//collect parameters for business logic
HttpSession httpSession = request.getSession(true);
SecurityDetails sd = (SecurityDetails) httpSession.getAttribute(
SecurityDetails.SECURITY_DETAILS_KEY);
String serviceProductId = (String) request.getParameter("serviceProductId");
String serviceProductName = (String) request.getParameter("serviceProductName");
String serviceProductType = (String) request.getParameter("serviceProductType");
String serviceProductOwnerName = (String) request.getParameter("serviceProductOwnerName");
String year = (String) request.getParameter("year");
int iPageSize = getPageSize(request);
int iPageNo = getPageNo(request);
ServiceProductQueryObj queryObj = new ServiceProductQueryObj();
queryObj.setCurrentUserEmpNo( sd.getUserInfo().getEmpNo() );
queryObj.setServiceProductId(serviceProductId);
queryObj.setServiceProductName(serviceProductName);
queryObj.setServiceProductType(serviceProductType);
queryObj.setServiceProductOwnerName(serviceProductOwnerName);
queryObj.setYear( year );
ApplicationContext context = getWebApplicationContext();
IServiceProductService serviceProductService = (IServiceProductService) context.getBean(
"serviceProductService");
PageInfo pageInfo = new PageInfo();
try {
pageInfo = serviceProductService.findServiceProductsForAll(iPageSize, iPageNo, queryObj);
}
catch (Exception ex) {
request.setAttribute("feedback", ex.getMessage());
}
request.setAttribute("pageInfo", pageInfo);
return mapping.findForward("success");
}
int getPageSize(HttpServletRequest request) {
int iPageSize = 0;
String strPageSize = null;
strPageSize = (String) request.getParameter("pageSize");
if (strPageSize == null || strPageSize.equals("")) {
iPageSize = Constant.getConPagesize(); ////////////////////////////////////
}
else {
try {
iPageSize = Integer.parseInt(strPageSize);
}
catch (Exception ex) {
iPageSize = Constant.getConPagesize(); ////////////////////////////////////
System.out.println(
"Developer Debug Log: [ pageSize parameter is incorrect! ]");
}
}
return iPageSize;
}
int getPageNo(HttpServletRequest request) {
int iPageNo = 0;
String strPageNo = null;
strPageNo = (String) request.getParameter("pageNo");
if (strPageNo == null || strPageNo.equals("")) {
iPageNo = 1; ////////////////////////////////////
}
else {
try {
iPageNo = Integer.parseInt(strPageNo);
}
catch (Exception ex) {
iPageNo = 1; ////////////////////////////////////
System.out.println(
"Developer Debug Log: [ pageNo parameter is incorrect! ]");
}
}
return iPageNo;
}
}
维护服务方案(方案人员)
package com.lenovoai.nicemis.web.action;
import org.springframework.web.struts.ActionSupport;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.context.ApplicationContext;
import com.lenovoai.nicemis.service.*;
import com.lenovoai.nicemis.model.*;
import com.lenovoai.nicemis.model.security.*;
import com.lenovoai.nicemis.util.*;
import java.util.*;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) </p>
* <p>Company: </p>
* @author not attributable
* @version 1.0
*/
public class FindServiceSolutionsForSolutionerAction
extends ActionSupport {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
//collect parameters for business logic
HttpSession httpSession = request.getSession(true);
SecurityDetails sd = (SecurityDetails) httpSession.getAttribute(
SecurityDetails.SECURITY_DETAILS_KEY);
String bizoppId = (String) request.getParameter("bizoppId");
String serviceSolutionName = (String) request.getParameter("serviceSolutionName");
String contentDegreeLeader = (String) request.getParameter("contentDegreeLeader");
String contentDegreeSale = (String) request.getParameter("contentDegreeSale");
String serviceSolutionOwnerName = (String) request.getParameter("serviceSolutionOwnerName");
String year = (String) request.getParameter("year");
int iPageSize = getPageSize(request);
int iPageNo = getPageNo(request);
ServiceSolutionQueryObj queryObj = new ServiceSolutionQueryObj();
queryObj.setCurrentUserEmpNo( sd.getUserInfo().getEmpNo() );
queryObj.setBizoppId(bizoppId);
queryObj.setServiceSolutionName(serviceSolutionName);
queryObj.setServiceSolutionOwnerName(serviceSolutionOwnerName);
queryObj.setYear( year );
queryObj.setContentDegreeLeader(contentDegreeLeader);
queryObj.setContentDegreeSale(contentDegreeSale);
ApplicationContext context = getWebApplicationContext();
IServiceSolutionService serviceSolutionService = (IServiceSolutionService) context.getBean(
"serviceSolutionService");
PageInfo pageInfo = new PageInfo(
展开阅读全文