65.9K
CodeProject 正在变化。 阅读更多。
Home

细微的调整,巨大的收益:如何定制您的项目管理信息系统(PMIS)以实现更大的业务价值

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2014 年 9 月 4 日

CPOL

9分钟阅读

viewsIcon

8625

如何定制您的 PMIS 以获得更大的业务价值

引言

项目管理信息系统(PMIS)是许多事物的集合——强大、高效、可适应且用途广泛的软件产品。

但它们并非完美(至少开箱即用时并非如此)。

每家公司都有其内部的项目管理职能标准,而开箱即用的PMIS中提供的基础平台功能永远无法自动匹配这些偏好。

但通过一点点的定制,您可以将PMIS的体验调整为符合您组织的独特需求——解锁隐藏的业务价值,并调动一批强大但未被充分利用的平台功能。

默认设置的问题

在本论文中,我们将探讨Microsoft Project Server的定制。

尤其当与Microsoft SharePoint结合使用时,Project Server是企业PMIS最有效且应用最广泛的选择之一。但与任何PMIS一样,它开箱即用时远非完美。

总的来说,PMIS如Project Server肩负着诸多职责,包括

  • 项目启动(包括项目验证以及范围、容量、资源和预算需求的分析)
  • 网络进度计划
  • 项目资源管理
  • 维护运营信息和监控项目状态
  • 项目文档流程和文档归档;
  • 项目风险、问题和变更请求的管理
  • 运营和统计报告

在处理某些任务时——例如网络进度计划和项目资源管理——MS Project Server“开箱即用”时的表现相当不错。但项目工作流功能则完全是另一回事。

为了说明工作流问题,让我们看一个真实的案例。

在此项目的启动和规划阶段,我们将要求MS Project Server协助完成两项主要任务

  1. 创建符合我们所有内部标准的项目——例如,确保项目代码符合内部预算和组合分类。
  2. 创建一个协作工作空间,其中包含我们所有的项目数据,包括
    • 分类(目标、解决方案、结果、收益、可行性分析)
    • 组织结构(管理和运营指导、工作组、技能集)
    • 范围(功能、组织和技术要素,范围变更的程序)
    • 实施方法(部署策略、假设和限制、影响分析)
    • 预算(预算阶段、预算阶段内的工程量和成本项目、总体项目预算)
    • 文档(所有项目报告的结构化存储)
    • 项目章程(最终项目文档的自动生成)

此外,我们还需要这个协作工作空间拥有直观的用户界面。(这在项目的早期阶段尤其重要,因为您的许多团队成员可能仍然在熟悉MS Project Server。)

首先,让我们看看当我们在“开箱即用”的情况下尝试这些任务时会发生什么。

任务一——创建项目——完成得相当好。我们可以通过自定义字段机制选择我们的扩展项目属性,这意味着它们将自动包含在我们的报告数据库中,并且我们可以在此基础上构建分析。

“开箱即用”时遇到的唯一显著限制是,我们无法根据项目类型和其他分类属性自动生成项目代码。

任务二——创建工作空间——问题就大多了,因为我们只能创建一个包含文档、风险和问题的标准项目工作空间。

图 1:标准项目工作空间

因此,我们初步的结论是,“开箱即用”的设置虽然与涉及网络进度计划、资源管理和风险的项目管理职能高度契合,但它们非常不适合自动生成项目章程、项目财务规划、合同工作以及一般的项目文档流程。

考虑到这些限制,让我们探讨一下如何通过对系统默认设置进行一些修改来改进功能。

定制实践

回到我们的项目示例,您会记得在任务一中,我们缺乏根据项目特征自动生成项目代码的功能。

在创建项目时,需要按照以下格式生成代码:PRJ [项目规格类型] [活动] [选定类型和方向内的编号]。

MS Project Server的事件处理程序机制非常适合这项任务。因此,我们需要实现一个处理程序,它将生成并保存我们所需项目代码。

为了直接处理字段,Project Server Web API(称为PSI)需要一个代理程序集,名为*ProjectServerServices.dll*。(请注意,使用PSI非常特殊,因为所有操作都是通过专门的DataSet对象进行的,而这个对象缺乏连贯的文档)。

首先,您需要获取所需的字段ID,具体说明在此。

下一篇

//read project information
var projectDS = ProjectSvc.ReadProject(ProjectUID, SvcProject.DataStoreEnum.WorkingStore);

foreach (ProjectDataSet.ProjectCustomFieldsRow cfRow in projectDS.ProjectCustomFields)
            {
                //if field exists, just update it
                if (cfRow.MD_PROP_UID.ToString() == id.ToString())
                {
                    //update the value
                    cfRow.TEXT_VALUE = code;
                    customFieldFound = true;
                }
            }

之后,项目需要被返回

            //create a new job id
            jobId = Guid.NewGuid();

            //checkin the updated project
            bool force = false;
            string sessionDescription = "updated custom fields";
            ProjectSvc.QueueCheckInProject(jobId, ProjectUID,
                force, sessionId, sessionDescription);

并发布

                //create a new job id
            jobId = Guid.NewGuid();

            bool fullPublish = false;
            ProjectSvc.QueuePublish(jobId, ProjectUID,
                fullPublish, EndpointAddressProjectSvc.Uri.ToString())

一旦项目创建完成(任务一),我们就需要创建一个工作空间(任务二),该工作空间能够提供编译项目数据的功能——例如,我们的项目章程。

但正如您所记得的,一个标准的MS SharePoint工作空间只是一个包含文档库以及问题和风险列表的简单Web模板。

我们需要一个功能更丰富的Web模板。

总的来说,有两种方法可以创建可用作MS SharePoint工作空间模板的站点定义——创建基于标准PWS工作空间的沙盒解决方案(Sandboxed Solution),或创建场解决方案(Farm Solution)站点定义。

沙盒解决方案站点定义是对现有工作空间的调整。其优点是,我们创建的工作空间会立即出现在管理界面中。然而,沙盒解决方案有严格的限制。例如,不能访问数据库,而这正是我们为了显示各种MS Project和工作空间数据集所缺少的功能。

场解决方案有一个明显的优势——我们可以完全访问SharePoint对象模型,并可以从各种来源检索数据。但是,使用场解决方案,我们如何使我们的站点定义能够用作Project上的模板工作空间?当时Google帮不了我们——所以我们带着IL-Spy或Reflector踏上了征程。

最好从“企业项目类型详细信息”页面(\PWA\ADMIN\EnterpriseProjectTypeDetails.aspx)开始。

从那里,经过一系列调用,我们将进入*Microsoft.Office.Project.Server.dll*以及*Microsoft.Office.Project.Server.BusinessLayer.Admin*类中的ReadWssInstalledLanguagesAndWebTempalates(…)方法。

这是我们将看到的内容

foreach (SPWebTemplate sPWebTemplate in sPWebTemplateCollection)
    {
        if (sPWebTemplate.ID >= 6000 && sPWebTemplate.ID <= 6220)
        {
            dataRow = webTemplatesTable.NewRow();
            dataRow["LanguageId"] = sPLanguage.LCID;
            dataRow["TemplateName"] = sPWebTemplate.Name;
            dataRow["TemplateTitle"] = sPWebTemplate.Title;
            dataRow["TemplateId"] = sPWebTemplate.ID;
            webTemplatesTable.Rows.Add(dataRow);
        }
    }

此ID与*webtemp_***.xml*中定义的ID相同(它必须在6000到6220之间)。然而,如果我们创建一个具有正确ID的SiteDefinition,它肯定会出现在“企业项目类型详细信息”页面上——但站点的创建将失败。

失败原因可以在*Microsoft.Office.Project.Server.BusinessLayer.Project*类中的AddOrChangeProjectWorkspaceAddress(…)方法中找到。

如果您仔细查看代码,您会发现它依赖于PWSIssuesPWSRiskPWSDocLibs列表。我们可以将相关功能添加到我们的SiteDefinition中,或者我们可以简单地将PWS功能添加到*onet.xml*中,这将添加所有必需的内容。

        <!--Activate PWS Feature -->
        <Feature ID="90014905-433F-4a06-8A61-FD153A27A2B5">
          <Properties xmlns="http://schemas.microsoft.com/sharepoint/">
            <Property Key="InheritGlobalNavigation" Value="false"/>
            <Property Key="OnQuickLaunch" Value="false"/>
            <Property Key="InheritCurrentNavigation" Value="false"/>
            <Property Key="IncludeSubSites" Value="false"/>
            <Property Key="IncludePages" Value="False"/>
          </Properties>
        </Feature>

这并不令人惊讶,因为标准的PWS站点定义只是一个启用了此功能的站点。(请注意,我们的工作空间的创建正在“Microsoft Project Server Queue Service 2010”中进行。因此,在对SiteDefinition进行更改后,我们需要重新启动它。)

采用这种方法,我们的工作空间将成为一组具有特定数据的列表,以及一组反映不同列表切片——以及ProjectServer_Reporting数据库的页面。但仍有两个问题

  1. 如何以最少的代码实现数据连接?
  2. 如何选择数据(特别是与当前项目相关而非其他项目相关的任务)?

关于第一个问题,DataFormWebPart及其AggregateDataSource非常适合连接。关键在于,我们将从所有源中选择数据,然后在*.xsl*级别实现连接。例如

<cc1:AggregateDataSource runat="server" 
RowsName="" SeparateRoot="true" RootName="" IsSynchronous="">
      <Sources>
        <cc1:SPSqlDataSource runat="server" AllowIntegratedSecurity="False" ConnectionString="
          <%$ connectionStrings:.._ConnectionString %>" 
          SelectCommand="SELECT TOP 1000 [Results] as WorkResults, 
          [TaskIndex], [TaskOutlineNumber],  [TaskUID],cast(cast(TaskWork as decimal(9,2)) AS FLOAT) 
          as TaskWork,[TaskName] FROM [ProjectServer_Reporting].[dbo].[MSP_EpmTask_UserView] 
          TV INNER JOIN [ProjectServer_Reporting].[dbo].[MSP_EpmProject] PR ON  
          TV.ProjectUID = PR.ProjectUID  WHERE PR.ProjectUID = @ProjUid " ID="SqlDataSource1">
          <SelectParameters>
            <asp:controlparameter name="ProjUid" controlid="PlaceHolderMain$wspp" propertyname="ProjUid"/>
          </SelectParameters>
        </cc1:SPSqlDataSource>
        <cc1:SPDataSource runat="server" DataSourceMode="List" SelectCommand="..."/>
        <cc1:SPDataSource runat="server" DataSourceMode="List" SelectCommand="..."/>
        <cc1:SPDataSource runat="server" DataSourceMode="List" SelectCommand="..."/>
      </Sources>
      <Aggregate>
        <concat name="data source">
          <datasource name="TasksInfo" id="0"  />
          <datasource name="ProjectPhases" id="1" />
          <datasource name="ProjectWorkSteps" id="2" />
          <datasource name="Contracts" id="3"  />
        </concat>
      </Aggregate>
</cc1:AggregateDataSource>

从上面的代码可以看出,有一组用于数据库查询的SPSqlDataSource,以及用于列表查询的SPDataSource。剩下的就是编写一个*.xsl*文件,将其以正确的顺序显示出来。

关于第二个问题——如何选择数据——我们有两种选择。一方面,我们可以关注工作空间的URL,然后使用请求中的MSP_EpmProject表获取已配置的ProjUid。另一方面,MS SharePoint工作空间的ProjUid保存在SPWeb属性的MSPWAPROJUID字段中——所以我们可以编写一个简单的控件来获取它

    public class WSProjectProperties : WebControl
    {
        public String ProjUid
        {
            get
            {
                if (SPContext.Current == null)
                    return null;
                if (SPContext.Current.Web == null)
                    return null;

                return SPContext.Current.Web.AllProperties[“MSPWAPROJUID”] as string;
            }
        }
    }

然后,该值应传递给DataSource,这正是前面示例所涵盖的内容。

定制的成果

通过这些微小的修改,我们赋予了标准工作空间全面的协作功能——符合我们自己内部的要求。

我们来看一下

图 2:基于我们要求的项目分类和自动编码

图 3:用户友好的工作空间,具备所需功能的完整定制

图 4-5:汇编项目主要目标值

图 6-8:项目组织结构,包括多个项目团队的管理

图 9-10:确定项目范围和实施方法

图 11:项目预算规划,包含详细的项目阶段,以及基于Microsoft Project 2010中配置的日历计划进行的合同关系规划

图 12:包含的任务列表基于日历计划生成

图 13:合同关系规划,以及匹配的作业与账户成本和时间框架

图 14:基于计划项目数据(项目章程)自动生成文档硬拷贝

图 15:基于关键参数(项目摘要)的项目运营控制面板

注意:基于Microsoft Project 2010日历计划或财务系统的实际数据自动形成的参数以红色标出。

图 16:基于计划和实际时间框架的项目阶段运营控制,以及包含颜色编码仪表板指示器的项目里程碑达成情况

注意:关于项目阶段、工作范围和截止日期信息是根据Microsoft Project 2010日历计划数据实时收集的;项目里程碑达成信息是从项目库中存储的文档收集的。

简单而强大

在这个项目示例中,我们仅用很低的劳动成本就满足了所有必要的 yb要求。通过定制,我们实现了

  • 全面的项目信息、分类和结构
  • 预算管理,支持多阶段预算场景
  • 风险/范围/变更/质量/时间/成本/采购管理
  • 文档库
  • 支持所有项目阶段
  • 项目状态仪表板、报告和项目指标的自动计算
  • 支持我们内部项目管理方法论中定义的多步骤流程
  • Project Server和SharePoint之间的集成

此外,这个项目示例基于实际的Microsoft Project Server 2010的采用和定制工作——任何行业的任何项目管理团队都可以轻松复制。

事实上,基本的定制不仅能促进项目计划的协作。所有涉及操作数据工作的项目任务都可以通过这种方式进行简化,包括

  • 采购管理
  • 合同工作管理
  • 处理项目问题和风险
  • 处理项目相关文档,包括结构化文档存储和定制工作流

信息很明确:无论公司的内部标准如何,一点点的定制都可以为PMIS功能带来无数新的潜力——为您的企业带来无数新的价值。

© . All rights reserved.