移动发票审核

商业用户可通过移动功能设计移动体验。 对于高级方案,开发人员还可通过此平台根据需要扩展功能。 若要了解有关移动的一些新概念,最有效的方法是设计一些新方案。 本文旨在通过以供应商发票的移动审核为使用案例,提供移动方案的设计方法实践。 本文应该可以帮助您设计这些方案的变型,还可以适用于与供应商发票无关的其他方案。

必备项

先决条件 Description
移动手册预习 移动平台
Dynamics 365 Finance 已安装了版本 1611 和平台更新 3(2016 年 11 月)的环境
安装修补程序 KB 3204341。 任务录制器可能错误地为平台更新 3(2016 年 11 月更新)中的下拉对话框录制两个关闭命令。
安装修补程序 KB 3207800。 此修补程序允许在平台更新 3(2016 年 11 月更新)中的移动客户端上查看附件。
安装修补程序 KB 3208224。 版本 7.0.1(2016 年 5 月)中的移动供应商发票审核应用程序的应用程序代码。
安装了此移动应用的 Android、iOS 或 Windows 设备。 在相应的应用程序商城中搜索该应用程序。

简介

供应商发票的移动审核需要“必备条件”部分中提到的三个修补程序。 这些修补程序不为发票审核提供工作区。 若要了解移动上下文中的工作区是什么,请阅读“必备条件”部分中提到的移动手册。 必须设计发票审核工作区。

每个组织都以不同方式为供应商发票编排和定义自己的业务流程。 为供应商发票审核设计移动体验时,应考虑以下业务流程因素。 观点是尽量使用这些数据点优化设备上的用户体验。

  • 用户希望在移动体验中看到发票抬头中的哪些字段?其顺序如何?

  • 用户希望在移动体验中看到发票行中的哪些字段?其顺序如何?

  • 一个发票中有多少个发票行? 在此处应用 80-20 规则,并针对 80% 进行优化。

  • 用户是否希望检查期间在移动设备上显示会计分配(发票编码)? 如果此问题的答案为是,请注意以下问题:

    • 一个发票行有多少个会计分配(延伸价格、销售税、费用、拆分等)? 再次应用 80-20 规则。
    • 发票的发票抬头中是否也有会计分配? 如果有,这些会计分配在设备上是否可用?

    注释

    本文不介绍如何编辑会计分配,因为此功能现在不支持移动方案。

  • 用户是否要在设备上查看发票的附件?

发票审核的移动体验设计将有所不同,具体取决于这些问题的答案。 目标是优化组织中移动业务流程的用户体验。 本文的其他部分中,我们将查看两个方案变型,这两个变型基于前面问题的不同答案。

在使用移动设计器时,通常需要确保“发布”更改,以防丢失更新。

为 Contoso 设计简单发票审核方案

方案属性 答卷
用户希望在移动体验中看到发票抬头中的哪些字段?其顺序如何?
  1. 供应商名称
  2. 发票合计
  3. 发票帐户
  4. 发票编号
  5. 发票日期
  6. 发票描述
  7. 到期日期
  8. 发票币种
用户希望在移动体验中看到发票行中的哪些字段?其顺序如何?
  1. 采购类别
  2. 数量
  3. 单价
  4. 行净额
  5. 1099 金额
一个发票中有多少个发票行? 在此处应用 80-20 规则,并针对 80% 进行优化。 1
用户是否希望检查期间在移动设备上显示会计分配(发票编码)?
一个发票行有多少个会计分配(延伸价格、销售税、费用等)? 再次应用 80-20 规则。 延伸价格:2,销售税:0,费用:0
发票的发票抬头中是否也有会计分配? 如果有,这些会计分配在设备上是否可用? 未使用
用户是否要在设备上查看发票的附件?

创建工作区

  1. 在浏览器中,登录应用程序。
  2. 登录之后,按照以下示例所示将 &mode=mobile 追加到 URL,然后刷新页面:https://<yoururl>/?cmp=usmf&mi=DefaultDashboard**&mode=mobile**
  3. 单击页面右上角的设置(齿轮)按钮,然后单击移动应用程序。 任务录制器显示时,移动应用程序设计器也必须显示。
  4. 单击添加以创建新工作区。 对于此示例,请将该工作区命名为我的审核
  5. 输入描述。
  6. 选择工作区颜色。 此工作区颜色将用于此工作区的移动体验的整体样式。
  7. 为该工作区选择图标。
  8. 单击完成
  9. 单击发布工作区以保存更改。

分配给我的供应商发票

应设计的第一个移动页面是为用户分配以待检查的发票列表。 若要设计此移动页面,请使用 VendMobileInvoiceAssignedToMeListPage 页面。 完成此过程,请确保为您分配至少一个供应商发票进行检查,并且发票行有两个分配。 此设置满足该方案的要求。

  1. 在该 URL 中,将菜单项的名称替换为 VendMobileInvoiceAssignedToMeListPage,以便在应付帐款模块中打开分配给我的待定供应商发票列表页面的移动版本。 此页面根据系统中为您分配的发票数量显示这些发票。 若要查找特定发票,必须使用左侧的筛选器。 但是,此示例不需要特定发票。 只需要为您分配某张发票,这将允许您设计移动页面。 已专门为供应商发票的移动方案设计可用新页面。 因此,您必须使用这些页面。 此 URL 应类似以下 URL,并且输入该 URL 之后,必须显示下图中显示的页面:https://<yourURL>/?cmp=usmf&mi=VendMobileInvoiceAssignedToMeListPage&mode=mobile

    分配给我的待定供应商发票页面。

  2. 单击页面右上角的设置(齿轮)按钮,然后单击移动应用程序

  3. 选择您的工作区,然后单击编辑

  4. 单击添加页面创建第一个移动页面。

  5. 输入名称(如我的供应商发票)和描述(如分配给我检查的供应商发票)。

  6. 单击完成

  7. 在移动设计器中的字段选项卡上,单击选择字段。 列表页面上的列必须类似下图。

    “分配给我的待定供应商发票”页面上的列。

  8. 从列表页面添加必须在移动页面中向用户显示的所需列。 添加顺序为字段向最终用户显示的顺序。 只能通过重新选择所有字段才能更改字段的顺序。 根据此方案的要求,需要下面的八个字段: 但是,某些用户可能会认为八个字段在移动设备上提供的信息太多。 因此,我们将在移动列表视图中仅显示最重要的字段。 其余字段将在我们以后将设计的详细信息视图中显示。 现在我们将仅添加以下字段。 单击这些列中的加号 (+) 添加到移动页面。

    • 供应商名称
    • 发票合计
    • 发票帐户
    • 发票编号
    • 发票日期

    添加字段之后,移动页面必须类似下图。

    添加字段后的页面。

  9. 还必须立即添加以下列,以便在以后启用工作流操作。

    • 显示已完成任务
    • 显示委托任务
    • 显示撤消任务
    • 显示拒绝任务
    • 显示请求完成任务
    • 显示重新提交任务
  10. 单击完成退出编辑模式。

  11. 单击后退,然后单击完成退出工作区

  12. 单击发布工作区以保存工作。

  13. 在“应付帐款参数”窗体中的发票下,启用在待定供应商发票列表中显示发票总计。 请注意,只有通过启用此参数,才能计算发票总计并在待定供应商发票列表页面中显示。 这是必备修补程序 3208224 中的一项新功能。

供应商发票明细

若要为移动设计发票明细页面,请使用 VendMobileInvoiceHeaderDetails 页面。 请注意,此页面根据您在系统中的发票数量,显示时间最久的发票(即最先创建的发票)。 若要查找特定发票,必须使用左侧的筛选器。 但是,此示例不需要特定发票。 我们仅需要一些发票数据,以便设计移动页面。

工作流页面。

  1. 在该 URL 中,将菜单项的名称替换为 VendMobileInvoiceHeaderDetails 以打开窗体

  2. 通过设置(齿轮)按钮打开移动设计器。

  3. 单击编辑按钮在工作区中启动编辑模式。

  4. 选择前面创建的我的供应商发票页面,然后单击编辑

  5. 字段选项卡上,单击窗格列标题。

  6. 单击属性 > 添加页面。 注意: 当您单击 网格 标题并添加页面时,将自动建立与详细信息页面的关系。

  7. 输入页面标题(如发票明细)和描述(如查看发票抬头和行明细)。

  8. 单击选择字段。 请注意,添加顺序为字段向最终用户显示的顺序。 只能通过重新选择所有字段才能更改字段的顺序。

  9. 根据此方案的要求,从抬头添加以下字段:

    • 供应商名称
    • 发票合计
    • 发票帐户
    • 发票编号
    • 发票日期
    • 发票描述
    • 到期日期
    • 发票币种
  10. 从页面中的行窗格添加以下字段:

    • 采购类别
    • 数量
    • 单价
    • 行净额
    • 1099 金额
  11. 添加了前面两步骤中的所有字段之后,单击完成。 此页面必须类似下图。

    显示添加的其他字段的图示。

  12. 单击完成退出编辑模式。

  13. 单击后退,然后单击完成退出工作区

  14. 单击发布工作区以保存工作

工作流操作

若要添加工作流操作,请使用 VendMobileInvoiceHeaderDetails 页面。 若要打开此页面,请替换 URL 中的菜单项名称,如前面执行的操作。 然后通过设置(齿轮)按钮打开移动设计器。 执行以下步骤在明细页面上添加工作流操作。 您必须将状态为可提供您要设计的工作流操作的发票分配给您。

记录工作流操作

  1. 单击编辑按钮在工作区中启动编辑模式。
  2. 选择前面创建的发票明细页面,然后单击编辑
  3. 操作选项卡上,单击添加操作
  4. 输入操作标题(如审核)和描述(如审核发票)。 请注意,此处输入的操作标题将成为移动应用程序中对用户显示的操作名称。
  5. 单击完成
  6. 单击选择字段
  7. 完成 VendMobileInvoiceHeaderDetails 页面中的工作流流程,然后完成要录制的操作。 确保此流程中输入工作流注释,这样移动体验中也会包括注释字段。
  8. 运行工作流操作后,单击完成完成“选择字段”任务。
  9. 单击完成退出编辑模式。
  10. 单击后退,然后单击完成退出工作区
  11. 单击发布工作区以保存工作
  12. 重复前面的步骤,记录需要的所有工作流操作。

创建 .js 文件

  1. 打开“记事本”或 Microsoft Visual Studio,然后粘贴以下代码。 将文件保存为 .js 文件。 此代码执行以下操作:

    • 隐藏我们前面在移动列表页面中添加且与工作流有关的额外列。 我们添加这些列是为了让应用程序在上下文中有这些信息,并且可以执行下一步。
    • 它根据处于活动状态的工作流步骤应用逻辑,以便仅显示这些操作。

    注释

    这些页面和代码中的其他控件的名称必须与工作区中的名称相同。

    function main(metadataService, dataService, cacheService, $q) {
           return {
               appInit: function (appMetadata) {
                   // Hide controls that need to be present, but not visible
                   metadataService.configureControl('My-vendor-invoices', 'ShowAccept', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowApprove', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowReject', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowDelegate', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowRequestChange', { hidden: true });
                 metadataService.configureControl('My-vendor-invoices', 'ShowRecall', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowComplete', { hidden: true });
               metadataService.configureControl('My-vendor-invoices', 'ShowResubmit', { hidden: true });
               },
               pageInit: function (pageMetadata, params) {
        if (pageMetadata.Name == 'Invoice-details') {
                       // Show/hide workflow actions based on workflow step
                       metadataService.configureAction('Accept', { visible: true });
                       metadataService.configureAction('Approve', { visible: true });
                       metadataService.configureAction('Reject', { visible: true });
                       metadataService.configureAction('Delegate', { visible: true });
                       metadataService.configureAction('Request-change', { visible: true });
                       metadataService.configureAction('Recall', { visible: true });
                       metadataService.configureAction('Complete', { visible: true });
                       metadataService.configureAction('Resubmit', { visible: true });
    
                       var entityContextParts = params.pageContext.split(':');
                       var data = dataService.getEntityData(entityContextParts[0], entityContextParts[1]);
    
                       var acceptControl = data.getPropertyValue('VendInvoiceInfoTable/showAccept');
                       var approveControl = data.getPropertyValue('VendInvoiceInfoTable/showApprove');
                       var rejectControl = data.getPropertyValue('VendInvoiceInfoTable/showReject');
                       var delegateControl = data.getPropertyValue('VendInvoiceInfoTable/showDelegate');
                       var requestChangeControl = data.getPropertyValue('VendInvoiceInfoTable/showRequestChange');
                       var recallControl = data.getPropertyValue('VendInvoiceInfoTable/showRecall');
                       var completeControl = data.getPropertyValue('VendInvoiceInfoTable/showComplete');
                       var resubmitControl = data.getPropertyValue('VendInvoiceInfoTable/showResubmit');
    
                       var showAcceptControl = Boolean(acceptControl == 1);
                       var showApproveControl = Boolean(approveControl == 1);
                       var showRejectControl = Boolean(rejectControl == 1);
                      var showDelegateControl = Boolean(delegateControl == 1);
                       var showRequestChangeControl = Boolean(requestChangeControl == 1);
                       var showRecallControl = Boolean(recallControl == 1);
                       var showCompleteControl = Boolean(completeControl == 1);
                       var showResubmitControl = Boolean(resubmitControl == 1);
    
                       metadataService.configureAction('Accept', { visible: showAcceptControl });
                       metadataService.configureAction('Approve', { visible: showApproveControl });
                       metadataService.configureAction('Reject', { visible: showRejectControl });
                       metadataService.configureAction('Delegate', { visible: showDelegateControl });
                       metadataService.configureAction('Request-change', { visible: showRequestChangeControl });
                       metadataService.configureAction('Recall', { visible: showRecallControl });
                       metadataService.configureAction('Complete', { visible: showCompleteControl });
                     metadataService.configureAction('Resubmit', { visible: showResubmitControl });
                   }
                 },
           };
        }
    
  2. 通过选择逻辑选项卡,将该代码文件上传到工作区。

  3. 单击完成退出编辑模式。

  4. 单击后退,然后单击完成退出工作区

  5. 单击发布工作区以保存工作

供应商发票附件

  1. 单击页面右上角的设置(齿轮)按钮,然后单击移动应用程序

  2. 单击编辑按钮在工作区中启动编辑模式。

  3. 选择前面创建的发票明细**页面,然后单击**编辑

  4. 文档管理选项设置为,如下所示。 注意: 如果没有要求在移动设备上显示附件,您可以将此选项设置为 ”,这是默认设置。

    文档管理。

  5. 单击完成退出编辑模式。

  6. 单击后退,然后单击完成退出工作区

  7. 单击发布工作区以保存工作

供应商发票行配送

此方案的要求确认将仅有行级别的分配,并且一张发票始终只有一行。 由于此方案非常简单,所以移动设备上的用户体验还必须足够简单,这样用户才不必向下滚动多次即可查看分配。 供应商发票包含用于显示发票抬头中的所有分配的选项。 此体验正是移动方案需要的。 因此,我们将使用 VendMobileInvoiceAllDistributionTree 页面设计移动方案的此部分。

注释

了解要求可以帮助我们在设计方案时确定要使用哪个特定页面和到底如何为用户优化移动体验。 在第二个方案中,我们将使用其他页面显示分配,因为该方案的要求不同。

  1. 在 URL 中,替换 URL 中的菜单项名称,如前面执行的操作。 显示的页面应类似下图。

    “全部分配”页面。

  2. 通过设置(齿轮)按钮打开移动设计器。

  3. 单击编辑按钮在工作区中启动编辑模式。 注意: 您将看到自动创建了两个新页面。 系统之所以创建这些页面,是因为您在上一部分中开启了文档管理。 您可以忽略这些新页面。

  4. 单击添加页面

  5. 输入页面标题(如查看会计)和描述(如查看发票的会计)。

  6. 单击完成

  7. 字段选项卡上,单击选择字段,从分配页面选择以下字段,然后单击完成

    1. 金额
    2. 币种
    3. 分类帐帐户

    注释

    我们未从分配网格选择描述列,因为此方案的要求确认只有延伸价格才是有分配的金额。 因此,我们不需要再一个字段来确定分配针对的金额类型。 但是在下一个方案中,使用此信息,因为该方案的要求指定,其他金额类型有分配(如销售税)。

  8. 单击完成退出编辑模式。

  9. 单击后退,然后单击完成退出工作区

  10. 单击发布工作区以保存工作

添加“查看会计”页面的导航

查看会计移动页面现在未链接到我们迄今为止设计的任何移动页面。 因为用户应该可以从移动设备上的发票明细页面导航到查看会计页面,所以我们必须提供从发票明细页面到查看会计页面的导航。 我们使用通过 JavaScript 的更多逻辑建立此导航。

  1. 打开您在前面创建的 .js 文件,然后添加以下代码中突出显示的行。 此代码执行两项操作:

    1. 这将帮助确保用户不能直接从工作区导航到查看会计页面。
    2. 它建立从发票明细页面到查看会计页面的导航控件。

    注释

    这些页面和代码中的其他控件的名称必须与工作区中的名称相同。

    function main(metadataService, dataService, cacheService, $q) {
           return {
               appInit: function (appMetadata) {
                   // Hide controls that need to be present, but not visible
                   metadataService.configureControl('My-vendor-invoices', 'ShowAccept', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowApprove', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowReject', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowDelegate', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowRequestChange', { hidden: true });
                 metadataService.configureControl('My-vendor-invoices', 'ShowRecall', { hidden: true });
                   metadataService.configureControl('My-vendor-invoices', 'ShowComplete', { hidden: true });
               metadataService.configureControl('My-vendor-invoices', 'ShowResubmit', { hidden: true });
                   // Hide pages not applicable for root navigation
                   metadataService.hideNavigation('View-accounting');
                   //Link to view accounting
                   metadataService.addLink('Invoice-details', 'View-accounting', 'View-accounting-nav-control', 'View accounting', true);
               },
               pageInit: function (pageMetadata, params) {
        if (pageMetadata.Name == 'Invoice-details') {
                       // Show/hide workflow actions based on workflow step
                       metadataService.configureAction('Accept', { visible: true });
                       metadataService.configureAction('Approve', { visible: true });
                       metadataService.configureAction('Reject', { visible: true });
                       metadataService.configureAction('Delegate', { visible: true });
                       metadataService.configureAction('Request-change', { visible: true });
                       metadataService.configureAction('Recall', { visible: true });
                       metadataService.configureAction('Complete', { visible: true });
                       metadataService.configureAction('Resubmit', { visible: true });
    
                       var entityContextParts = params.pageContext.split(':');
                       var data = dataService.getEntityData(entityContextParts[0], entityContextParts[1]);
    
                       var acceptControl = data.getPropertyValue('VendInvoiceInfoTable/showAccept');
                       var approveControl = data.getPropertyValue('VendInvoiceInfoTable/showApprove');
                       var rejectControl = data.getPropertyValue('VendInvoiceInfoTable/showReject');
                       var delegateControl = data.getPropertyValue('VendInvoiceInfoTable/showDelegate');
                       var requestChangeControl = data.getPropertyValue('VendInvoiceInfoTable/showRequestChange');
                       var recallControl = data.getPropertyValue('VendInvoiceInfoTable/showRecall');
                       var completeControl = data.getPropertyValue('VendInvoiceInfoTable/showComplete');
                       var resubmitControl = data.getPropertyValue('VendInvoiceInfoTable/showResubmit');
    
                       var showAcceptControl = Boolean(acceptControl == 1);
                       var showApproveControl = Boolean(approveControl == 1);
                     var showRejectControl = Boolean(rejectControl == 1);
                       var showDelegateControl = Boolean(delegateControl == 1);
                       var showRequestChangeControl = Boolean(requestChangeControl == 1);
                       var showRecallControl = Boolean(recallControl == 1);
                       var showCompleteControl = Boolean(completeControl == 1);
                       var showResubmitControl = Boolean(resubmitControl == 1);
    
                       metadataService.configureAction('Accept', { visible: showAcceptControl });
                       metadataService.configureAction('Approve', { visible: showApproveControl });
                       metadataService.configureAction('Reject', { visible: showRejectControl });
                       metadataService.configureAction('Delegate', { visible: showDelegateControl });
                       metadataService.configureAction('Request-change', { visible: showRequestChangeControl });
                       metadataService.configureAction('Recall', { visible: showRecallControl });
                       metadataService.configureAction('Complete', { visible: showCompleteControl });
                       metadataService.configureAction('Resubmit', { visible: showResubmitControl });
        }
                 },
           };
        }
    
  2. 通过选择逻辑选项卡,将该代码文件上传到工作区以覆盖以前的代码

  3. 单击完成退出编辑模式。

  4. 单击后退,然后单击完成退出工作区

  5. 单击发布工作区以保存工作

验证

从您的移动设备打开应用程序,然后连接到您的实例。 确保在供应商发票分配给您检查的位置登录公司。 您应该可以执行以下操作:

  • 查看我的审核工作区。
  • 钻取到我的审核工作区中,并查看我的供应商发票页面。
  • 钻取到我的供应商发票页面中,并查看分配给您的发票的列表。
  • 钻取到一张发票中,并查看发票抬头明细和行明细。
  • 在明细页面中,查看附件的链接,并使用该链接导航到附件列表和查看附件。
  • 在明细页面中,查看查看会计页面的链接,并使用该链接导航到分配页面和查看分配。
  • 在明细页面中,单击底部的操作菜单,并执行适用于工作流步骤的工作流操作。

为 Fabrikam 设计复杂发票审核方案

方案属性 答卷
用户希望在移动体验中看到发票抬头中的哪些字段?其顺序如何?
  1. 供应商名称
  2. 发票金额
  3. 发票帐户
  4. 发票编号
  5. 发票日期
  6. 发票描述
  7. 到期日期
  8. 发票币种
用户希望在移动体验中看到发票行中的哪些字段?其顺序如何?
  1. 采购类别
  2. 数量
  3. 单价
  4. 行净额
  5. 1099 金额
一个发票中有多少个发票行? 在此处应用 80-20 规则,并针对 80% 进行优化。 5
用户是否希望检查期间在移动设备上显示会计分配(发票编码)?
一个发票行有多少个会计分配(延伸价格、销售税、费用等)? 再次应用 80-20 规则。 延伸价格:2,销售税:2,费用:2
发票的发票抬头中是否也有会计分配? 如果有,这些会计分配在设备上是否可用? 未使用
用户是否要在设备上查看发票的附件?

后续步骤

可根据方案 2 的要求为方案 1 完成以下变型。 您可以使用此部分提高您的移动应用体验。

  1. 因为方案 2 中应该有更多行,所以对设计的以下更改将帮助优化移动设备上的用户体验:

    1. 用户可以选择查看单独移动页面上的行,而不是查看明细页面上的发票行(如方案 1 中)。
    2. 因为此方案中应该有多张发票,所以如果使用 VendMobileInvoiceAllDistributionTree 页面为移动设计分配页面(如方案 1 中),用户可能很难将行与分配关联。 因此,请使用 VendMobileInvoiceLineDistributionTree 页面设计分配页面。
    3. 理想情况下,应该在此方案中的发票行上下文内显示分配。 因此,请确保用户可以钻取到行中以查看分配页面。 请使用页面链接功能建立钻取,就如在方案 1 中对抬头和明细页面执行的操作。
  2. 因为方案 2 中分配上应该有多个金额类型(销售税、费用等),所以显示金额类型的描述非常有用。 (我们在方案 1 中忽略了此信息。)