使用 Navision 附加组件“NDA”授权 Navision 销售订单行,使用 C# 开发






3.73/5 (7投票s)
这是一个展示如何将 Navision 与任何第三方应用程序集成,并在 Navision 与该应用程序之间进行数据交互的出色示例。
引言
本文演示了如何在 Navision ERP 外部运行的业务流程可以轻松地与 Navision 中的任何业务流程集成。为了更好地理解这一点,我使用了真实的场景。
考虑一个用 C# 开发的系统,它具有授权销售订单数量的功能。一旦在 Navision 中创建了销售订单,那么从 C# 中,您可以根据本文执行各种操作。
- 从 C# 查看销售订单
- 从 C# 授权销售订单数量。这不仅可以从 C# 授权销售行数量,还可以在授权销售订单时运行 Navision 中存在的业务逻辑。
- 授权后,您可以从 C# 过账销售订单以进行销售发货。
- 销售发货后,您还可以将销售订单过账为销售发票。
- 您还可以同时将销售订单过账为销售发货和销售发票。
- 本文不仅允许授权销售订单,还更新了授权的数量。这意味着用户不能进行超过授权数量的发货和发票。
- 在 C# 授权之前,用户无法过账销售订单。
- 在过账已授权的 Navision SO 行项后,您可以在此“Navision 文档授权”附加组件中查看已过账的发货和发票。
现在,聪明的人们一定会问,为什么我们要从 C# 进行销售授权,而不是仅仅在 Navision 中进行自定义?
为了理解这一点,请考虑一个场景,即:
客户或 ISV 拥有一个授权应用程序,该应用程序具有所有业务逻辑来授权销售订单数量,现在客户或 ISV 要求将此功能与 Navision 集成,以便我们可以利用授权应用程序的功能与 Navision 相互作用。
通过使用这种集成,我们将获得以下好处:
- 如果该功能已存在于某个附加组件中,则无需在 Navision 中从头开始开发,只需在 8 小时内将其与 Navision 集成。
- 由于附加组件功能可以在 .NET 平台中开发并轻松集成到 Navision 2009 Sp1 中,因此可以节省 ISV 将附加组件产品推向 Navision 市场的大量时间。
- ISV 可以将时间投入到开发附加组件中已有的功能上,而不是花费时间重复开发,而是可以利用这些时间为他们的附加组件添加更多功能,这将为他们的附加组件带来更多附加价值,并使其在竞争中更具优势。
假设客户给了我们一个 API,该 API 返回销售订单号、行号、授权信息和授权数量。现在,通过使用这 5 个字段,我开发了一个连接器或适配器,通过 C# 更新 Navision 销售订单,并执行了从步骤 a 到 h 定义的所有操作。
本文旨在帮助 ISV、客户和开发人员将他们的旧应用程序与 Microsoft Dynamics Navision 集成。
观众心中可能会出现一些问题,即通过本文定义的框架可以集成什么类型的应用程序,所以请在此处找到答案,即:
- 任何用 VB、C# 开发的零售应用程序都可以轻松地与 Navision 业务流程集成。因此,如果已经有第三方应用程序,则无需在 Navision 中开发零售系统。只需使用本文中的框架将其与 Navision 应用程序集成。
- 任何文档标记应用程序和授权应用程序都可以轻松地与 Navision 中的 SOP 流程、POP 流程、制造流程和所有其他流程集成。
- 用 C#、WPF 开发的导出和导入功能可以轻松地与 Navision 集成。
- 用 C#、WPF 开发的质量模块可以轻松地与 Navision 流程集成。
- 用 C#、WPF...开发的批量制造、敏捷制造、精益制造……可以轻松地与 Navision 流程集成。
上面,我提供了一些用 C# 和 WPF 开发的附加组件示例,它们可以轻松地与 Navision 集成。因此,ISV 可以轻松地将他们的应用程序与 Navision 集成,而无需了解 Navision 的专有语言 CAL。这很有趣。我在 Navision 的各种 ISV 工作过。我们过去会使用 COM 在 CAL 中开发连接器,并将代码放在我们想要集成的许多表单中,但现在使用本文定义的架构,无需在 Navision 表单中放置按钮,只需通过 WCF 在 C# 应用程序中获取 Navision 表的全部数据并进行集成。它不仅允许将数据从 Navision 传递到外部世界,还可以从外部执行 Navision 中的业务逻辑,并将处理过的数据从外部世界传回 Navision。
我们已经详细讨论了以上所有有趣的内容,现在让我们开始精彩激动人心的 C# 编码之旅,将 Navision 与文档授权集成……
背景
由于这是一个附加组件,因此需要在 Navision 端进行一些修改,例如在表、页面和公开页面和代码单元作为 Web 服务中添加一些字段。在将 Navision 对象公开为 Web 服务后,我们就可以开始在 C# 中进行开发了。Navision 的专有语言是 CAL,Navision 的 IDE 是 Object designer。Tables
、Forms
、Pages
、Codeunits
、Dataports
、Menusuites
和 XmlPort
是 Navision 的对象。简而言之,Pages
和 forms
用于向最终用户显示表数据。Codeunit
类似于 SQL 过程。Dataport
和 XMLport
用于将数据导出到 Navision 或从 Navision 导入数据。在 Navision 中,我们可以将 page
和 codeunit
公开为 Web 服务。Codeunits
和 page
将 Navision 的业务逻辑和数据公开给外部世界。本文使用了 Navision 2009 sp1、.NET 3.5、VS 2008 sp1 和 SQL Server 2005。
现在,我们先从 Navision 开始开发。(Navision 的修改会非常少。98% 的开发将在 C# 中完成。)
开发 1:在 Navision 的“SalesLine”表中添加新字段
由于我们要进行销售订单项授权,因此我们需要修改 SalesLine
表,即:
在上图中,为 ID 50000 和 50001 添加了两个字段“Authorize”(授权)和“Authorize Qty”(授权数量)。
开发 2:在 Navision 的“SalesLine”表上添加两个字段的验证
在上图中,对 Navision “SalesLine
”表进行了以下修改:
//(i)"Qty. to Invoice" field- OnValidate trigger -
// Authorization (The Great AP) Start
IF ( Authorize = FALSE) THEN
ERROR(APText002)
ELSE
IF ((("Qty. to Invoice") + ("Quantity Invoiced")) > "Authorize Qty") THEN
ERROR(APText003,"Qty. to Invoice","Authorize Qty");
// Authorization (The Great AP) end
上面的代码规定,“Qty. to Invoice”(待开票数量)字段的值不能大于“Authorize Qty”(授权数量)。这里,“Authorize Qty”字段的值将来自 C# 应用程序。这是任何销售周期文档授权管理系统的集成点。
//(ii) ”Qty. to Ship” field- OnValidate trigger –
//Qty. to Ship - OnValidate()
// Authorization (The Great AP) Start
IF ( Authorize = FALSE) THEN
ERROR(APText002)
ELSE
IF ((("Qty. to Ship") + ("Quantity Shipped")) > "Authorize Qty") THEN
ERROR(APText001,"Qty. to Ship","Authorize Qty");
// Authorization (The Great AP) end
上面的代码规定,“Qty. to Invoice”(待开票数量)字段的值不能大于“Authorize Qty”(授权数量)。这里,“Authorize Qty”字段的值将来自 C# 应用程序。这是任何销售周期文档授权管理系统的集成点。
在上图中,突出显示的红色代码指定,在将销售订单过账到销售发货和销售发票之前,将执行验证检查,即“Qty. to Ship”(待发货数量)和“Qty. to Invoice”(待开票数量)不能大于“Authorize Qty”(授权数量)字段。
开发 3:在 Navision 中创建 Codeunit 50001
创建此代码单元是为了能够从 C# 过账 Navision 销售订单。
上面的代码稍后将在本文中作为 Web 服务公开,以启用 C# 进行过账。
开发 4:在 Navision 中公开 Page 和 Codeunit 作为服务
我们已在 Navision 中为授权附加组件开发了基本业务逻辑。现在我们将从这一点开始 C# 编码。首先,将修改后的 Page
和 Codeunit
公开为 Web 服务,如下所示。
在上图中,“Web Services”(Web 服务)窗体包含 Page 和 Codeunit 的记录。这意味着 Page ID 132、130、48、46、42、46 和 Codeunit 50001 已公开为 Web 服务。
开发 5:创建文档授权的 C# 应用程序
在 C# 中创建“NavisionDocumentAuthorization
”项目,并为 Navision 的公开对象添加引用,如下所示。
在上图中,Web 服务的地址如下,它们是在修改 4 中公开的。
- “
PostedSalesinvoice
” - https://:7047/DynamicsNAV/WS/CRONUS%20India%20Ltd/services - “
PostedSalesShipment
” – https://:7047/DynamicsNAV/WS/CRONUS%20India%20Ltd/Page/PostedSalesShipment - “
SalesHeader
”- https://:7047/DynamicsNAV/WS/CRONUS%20India%20Ltd./services - “
Sll
”- https://:7047/DynamicsNAV/WS/CRONUS%20India%20Ltd/Page/SalesOrderLine - “
SO
”- https://:7047/DynamicsNAV/WS/CRONUS%20India%20Ltd/Page/SalesOrder
开发 6:在 C# 中创建“FetchNavisionSOP”类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NavisionDocumentAuthorization.SalesHeader;
using System.Reflection;
namespace NavisionDocumentAuthorization
{
class FetchNavisionSOP
{
SalesHeader_Binding sh_serv =new SalesHeader_Binding();
SalesHeader.SalesHeader sh =
new NavisionDocumentAuthorization.SalesHeader.SalesHeader();
SalesLine_Binding navSL = new SalesLine_Binding();
SalesLine_Filter salesLineFIlterNo = new SalesLine_Filter();
SalesLine_Filter salesLineFIlterType = new SalesLine_Filter();
Sales_Order_Line sline = new Sales_Order_Line();
SalesHeader.SalesHeader sr =
new NavisionDocumentAuthorization.SalesHeader.SalesHeader();
SalesHeader.SalesHeader[] salesHeader;
SO.SalesOrder_Service soos =
new NavisionDocumentAuthorization.SO.SalesOrder_Service();
SO.SalesOrder so1;
PostedSalesShipment.PostedSalesShipment_Service posSalesShpmnt =
new NavisionDocumentAuthorization.
PostedSalesShipment.PostedSalesShipment_Service();
NavisionDocumentAuthorization.PostedSalesInvoice.
PostedSalesInvoice_Binding posSalesInvoice =
new NavisionDocumentAuthorization.
PostedSalesInvoice.PostedSalesInvoice_Binding();
public SalesHeader.SalesHeader[] NavisionSalesOrder()
{
sh_serv.UseDefaultCredentials = true;
salesHeader = sh_serv.ReadMultiple(null, null, 0);
return salesHeader;
}
public Sales_Order_Line1[] NavisionSalesLine(string slectedSalesHeaderNo)
{
SalesHeader_Binding slvc = new SalesHeader_Binding();
sr = slvc.Read(slectedSalesHeaderNo);
return sr.SalesLines;
}
public void UpdateSalesLine
(bool authorize, decimal authorizeQty, string documentNo, int index)
{
SalesHeader.Sales_Orders sOs =
new NavisionDocumentAuthorization.SalesHeader.Sales_Orders();
NavisionDocumentAuthorization.SalesHeader.Sales_Orders_Binding soB =
new NavisionDocumentAuthorization.SalesHeader.Sales_Orders_Binding();
soB.UseDefaultCredentials = true;
sOs = soB.Read(documentNo);
SO.Sales_Order_Line sool =
new NavisionDocumentAuthorization.SO.Sales_Order_Line();
soos.UseDefaultCredentials = true;
so1 = soos.Read(documentNo);
SO.Sales_Order_Line[] sol1 = so1.SalesLines;
sol1[index].Authorize = authorize;
sol1[index].Authorize_Qty = authorizeQty;
soos.Update(ref so1);
}
public void PostSOShipment(string documentNo)
{
so1 = soos.Read(documentNo);
soos.PostOrder(so1.Key);
}
public void PostSOInvoice(string documentNo)
{
so1 = soos.Read(documentNo);
soos.PostOrderInvoice(so1.Key);
}
public void PostSOShipInvoice(string documentNo)
{
so1 = soos.Read(documentNo);
soos.PostOrderShipInvoice(so1.Key);
}
public NavisionDocumentAuthorization.PostedSalesShipment.
PostedSalesShipment[] GetPostedSalesShipment(
string SONo)
{
posSalesShpmnt.UseDefaultCredentials = true;
PostedSalesShipment.PostedSalesShipment_Filter pSSF =
new NavisionDocumentAuthorization.
PostedSalesShipment.PostedSalesShipment_Filter();
pSSF.Field =
NavisionDocumentAuthorization.PostedSalesShipment.
PostedSalesShipment_Fields.Order_No;
pSSF.Criteria = SONo;
PostedSalesShipment.PostedSalesShipment_Filter[] pssfFilters =
new NavisionDocumentAuthorization.
PostedSalesShipment.PostedSalesShipment_Filter[] {
pSSF };
return posSalesShpmnt.ReadMultiple(pssfFilters, null, 0);
}
public NavisionDocumentAuthorization.PostedSalesShipment.
Posted_Sales_Shpt_Line[] GetPostedSalesShipBody(string shpNo)
{
PostedSalesShipment.PostedSalesShipment_Service posSalesShpbdy =
new NavisionDocumentAuthorization.
PostedSalesShipment.PostedSalesShipment_Service();
PostedSalesShipment.PostedSalesShipment posSH;
posSH = posSalesShpbdy.Read(shpNo);
return posSH.SalesShipmLines;
}
public NavisionDocumentAuthorization.PostedSalesInvoice.
PostedSalesInvoice[] GetPostedSalesInvoice(
string SONo)
{
posSalesInvoice.UseDefaultCredentials = true;
NavisionDocumentAuthorization.PostedSalesInvoice.
PostedSalesInvoice_Filter pSiQry =
new NavisionDocumentAuthorization.PostedSalesInvoice.
PostedSalesInvoice_Filter();
pSiQry.Field = NavisionDocumentAuthorization.
PostedSalesInvoice.PostedSalesInvoice_Fields.Order_No;
pSiQry.Criteria = SONo;
NavisionDocumentAuthorization.PostedSalesInvoice.
PostedSalesInvoice_Filter[] pSiQrys =
new NavisionDocumentAuthorization.PostedSalesInvoice.
PostedSalesInvoice_Filter[] { pSiQry };
return posSalesInvoice.ReadMultiple(pSiQrys, null, 0);
}
public NavisionDocumentAuthorization.PostedSalesInvoice.
Posted_Sales_Invoice_Line[] GetPostedSalesInvBody(string InvNo)
{
PostedSalesInvoice.PostedSalesInvoice_Binding posSalesInvbdy =
new NavisionDocumentAuthorization.
PostedSalesInvoice.PostedSalesInvoice_Binding();
PostedSalesInvoice.PostedSalesInvoice posIn;
posIn = posSalesInvbdy.Read(InvNo);
return posIn.SalesInvLines;
}
}
}
上述类包含获取 Navision 销售订单、销售发货和销售发票的逻辑。它还包含将销售订单过账为销售发货和销售发票的逻辑。
开发 7:在 C# 中创建“ViewSO”窗体
开发 8:在 C# 中创建“PostedShipments”窗体
开发 9:在 C# 中创建“PostedInvoices”窗体
开发 10:在“ViewSO”窗体的按钮触发器上编写代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace NavisionDocumentAuthorization
{
public partial class frmAthSO : Form
{
FetchNavisionSOP fetchnavisionSO = new FetchNavisionSOP();
string selectedSONo = string.Empty;
bool authorize;
SalesHeader.Sales_Order_Line1[] SOL;
DataGridViewRow SalesLineRow = new DataGridViewRow();
public frmAthSO()
{
InitializeComponent();
}
private void frmAthSO_Load(object sender, EventArgs e)
{
datagridviewSalesHeader.DataSource = fetchnavisionSO.NavisionSalesOrder();
datagridviewSalesHeader.EditMode = DataGridViewEditMode.EditProgrammatically;
datagridviewSalesHeader.Columns[0].Visible = false;
}
private void datagridviewSalesHeader_SelectionChanged
(object sender, EventArgs e)
{
selectedSONo = string.Empty;
DataGridViewRow row = new DataGridViewRow();
row = datagridviewSalesHeader.CurrentRow;
selectedSONo = row.Cells[1].Value.ToString();
datagridviewSalesLine.DataSource =
fetchnavisionSO.NavisionSalesLine(selectedSONo);
SOL = fetchnavisionSO.NavisionSalesLine(selectedSONo);
DataGridViewRow rowline = new DataGridViewRow();
rowline = datagridviewSalesLine.CurrentRow;
datagridviewSalesLine.Columns[0].Visible = false;
}
private void datagridviewSalesLine_CellValueChanged(object sender,
DataGridViewCellEventArgs e)
{
try
{
decimal authQty = 0;
SalesLineRow = datagridviewSalesLine.CurrentRow;
string aut =
datagridviewSalesLine.Rows[SalesLineRow.Index].
Cells["Authorize"].Value.ToString();
decimal.TryParse(
datagridviewSalesLine.Rows[SalesLineRow.Index].
Cells["Authorize_Qty"].Value.ToString(),
out authQty);
fetchnavisionSO.UpdateSalesLine(Boolean.Parse(
datagridviewSalesLine.Rows[SalesLineRow.Index].
Cells["Authorize"].Value.ToString()),
authQty, selectedSONo, SalesLineRow.Index);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message,ex.HelpLink);
}
}
private void btnShip_Click(object sender, EventArgs e)
{
try
{
DataGridViewRow row = new DataGridViewRow();
row = datagridviewSalesHeader.CurrentRow;
selectedSONo = row.Cells[1].Value.ToString();
fetchnavisionSO.PostSOShipment(selectedSONo);
datagridviewSalesLine.DataSource =
fetchnavisionSO.NavisionSalesLine(selectedSONo);
MessageBox.Show("Sales order no. " +
selectedSONo + "Shipped", "Sales Shipment");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, ex.HelpLink);
}
}
private void btnInv_Click(object sender, EventArgs e)
{
try
{
DataGridViewRow row = new DataGridViewRow();
row = datagridviewSalesHeader.CurrentRow;
selectedSONo = row.Cells[1].Value.ToString();
fetchnavisionSO.PostSOInvoice(selectedSONo);
datagridviewSalesHeader.DataSource = fetchnavisionSO.NavisionSalesOrder();
datagridviewSalesHeader.EditMode =
DataGridViewEditMode.EditProgrammatically;
datagridviewSalesHeader.Columns[0].Visible = false;
datagridviewSalesLine.DataSource =
fetchnavisionSO.NavisionSalesLine(selectedSONo);
MessageBox.Show("Sales order no. " +
selectedSONo + "Invoiced", "Sales Invoice");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, ex.HelpLink);
}
}
private void btnShipInv_Click(object sender, EventArgs e)
{
try
{
DataGridViewRow row = new DataGridViewRow();
row = datagridviewSalesHeader.CurrentRow;
selectedSONo = row.Cells[1].Value.ToString();
fetchnavisionSO.PostSOShipInvoice(selectedSONo);
datagridviewSalesHeader.DataSource =
fetchnavisionSO.NavisionSalesOrder();
datagridviewSalesHeader.EditMode =
DataGridViewEditMode.EditProgrammatically;
datagridviewSalesHeader.Columns[0].Visible = false;
datagridviewSalesLine.DataSource =
fetchnavisionSO.NavisionSalesLine(selectedSONo);
MessageBox.Show("Sales order no. " +
selectedSONo + "Shipped & Invoice",
"Sales Shipment & Invoice");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, ex.HelpLink);
}
}
private void btnPstdShip_Click(object sender, EventArgs e)
{
try
{
DataGridViewRow row = new DataGridViewRow();
row = datagridviewSalesHeader.CurrentRow;
selectedSONo = row.Cells[1].Value.ToString();
DataGrid dgPstdShp = new DataGrid();
DataGrid dgPstbdy = new DataGrid();
NavisionDocumentAuthorization.PostedSalesShipment.
PostedSalesShipment[] psSalesShp;
dgPstdShp.DataSource = fetchnavisionSO.GetPostedSalesShipment
(selectedSONo);
psSalesShp = fetchnavisionSO.GetPostedSalesShipment(selectedSONo);
if (psSalesShp.Count() > 0)
{
dgPstbdy.DataSource =
fetchnavisionSO.GetPostedSalesShipBody
(psSalesShp[0].No);
PostedShipments postdShipments =
new PostedShipments
(dgPstdShp, dgPstbdy, true);
postdShipments.Show();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, ex.HelpLink);
}
}
private void btnPstInv_Click(object sender, EventArgs e)
{
try
{
DataGridViewRow row = new DataGridViewRow();
row = datagridviewSalesHeader.CurrentRow;
selectedSONo = row.Cells[1].Value.ToString();
DataGrid dgPstdInv = new DataGrid();
DataGrid dgPstdInvBdy = new DataGrid();
NavisionDocumentAuthorization.
PostedSalesInvoice.PostedSalesInvoice[] psSalesInv;
dgPstdInv.DataSource =
fetchnavisionSO.GetPostedSalesInvoice(selectedSONo);
psSalesInv =
fetchnavisionSO.GetPostedSalesInvoice(selectedSONo);
if (psSalesInv.Count() > 0)
{
dgPstdInvBdy.DataSource =
fetchnavisionSO.GetPostedSalesInvBody
(psSalesInv[0].No);
PostedInvoices postdInvoices =
new PostedInvoices(dgPstdInv, dgPstdInvBdy);
postdInvoices.Show();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, ex.HelpLink);
}
}
}
}
上述代码包含调用“FetchNavisionSOP
”类中编写的函数的业务逻辑,以便将 Navision SOP 的所有业务逻辑以及附加组件“DocumentAuthorization
”集成在一起。
开发 11:在“PostedShipments”类上编写代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace NavisionDocumentAuthorization
{
public partial class PostedShipments : Form
{
public PostedShipments()
{
InitializeComponent();
}
public PostedShipments(DataGrid dataGridSalesShp,
DataGrid dataGridSalesShpBody,
bool postedSalesShip )
{
InitializeComponent();
if (postedSalesShip)
{
datagridviewPostedSalesShipments.DataSource =
dataGridSalesShp.DataSource;
datagridviewPostedSalesShipBody.DataSource =
dataGridSalesShpBody.DataSource;
datagridviewPostedSalesShipments.EditMode =
DataGridViewEditMode.EditProgrammatically;
datagridviewPostedSalesShipBody.EditMode =
DataGridViewEditMode.EditProgrammatically;
datagridviewPostedSalesShipments.Columns[0].
Visible = false;
datagridviewPostedSalesShipBody.Columns[0].
Visible = false;
}
else
{
}
}
private void datagridviewPostedSalesShipments_SelectionChanged
(object sender, EventArgs e)
{
string selectedShpNo = string.Empty;
DataGridViewRow row = new DataGridViewRow();
FetchNavisionSOP fetchnavisionSO = new FetchNavisionSOP();
row = datagridviewPostedSalesShipments.CurrentRow;
selectedShpNo = row.Cells["No"].Value.ToString();
datagridviewPostedSalesShipBody.DataSource =
fetchnavisionSO.GetPostedSalesShipBody(selectedShpNo);
}
}
}
上述代码包含实例化窗体 Datasource
的业务逻辑。
开发 12:在“PostedInvoices”类上编写代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace NavisionDocumentAuthorization
{
public partial class PostedInvoices : Form
{
public PostedInvoices()
{
InitializeComponent();
}
public PostedInvoices(DataGrid dataGridSalesInv,
DataGrid dataGridSalesInvBody)
{
InitializeComponent();
dgPostedSalesInv.DataSource = dataGridSalesInv.DataSource;
dgPostedSalesInv.EditMode =
DataGridViewEditMode.EditProgrammatically;
dgPostedSalesInv.Columns[0].Visible = false;
datagridviewPostedSalesInvBody.EditMode =
DataGridViewEditMode.EditProgrammatically;
datagridviewPostedSalesInvBody.DataSource =
dataGridSalesInvBody.DataSource;
datagridviewPostedSalesInvBody.Columns[0].Visible = false;
}
private void dgPostedSalesInv_SelectionChanged
(object sender, EventArgs e)
{
string selectedInvNo = string.Empty;
DataGridViewRow row = new DataGridViewRow();
FetchNavisionSOP fetchnavisionSO = new FetchNavisionSOP();
row = dgPostedSalesInv.CurrentRow;
selectedInvNo = row.Cells["No"].Value.ToString();
datagridviewPostedSalesInvBody.DataSource =
fetchnavisionSO.GetPostedSalesInvBody(
selectedInvNo);
}
}
}
上述代码包含实例化窗体 Datasource
的业务逻辑。
现在,让我们进行演示。
演示
a) 启动 C# 应用程序
上面的窗体包含 Navision 销售订单列表。目前,用户在销售订单号 1001 上,它只有一个关联的销售行。
当用户进入 SalesOrder
屏幕的记录“101009”时,UI 将如下所示。
上面的窗体包含销售订单“101009”的两个销售行项目。
b) 现在,我们将授权订单号“101015”的销售订单行。
在授权之前,如果用户尝试过账销售订单或对销售“Qty to Invoice”(待开票数量)或销售“Qty to Ship”(待发货数量)字段进行修改,则会引发一个异常,即“Sales Line is not authorized”(销售行未授权)。
当用户尝试从 C# 应用程序过账时,也会出现上述错误,即:
c) 现在,我们将从 C# 应用程序授权订单号“101015”的 Item No. “1896-S”。这是 Navision 文档授权的集成点,这样 Navision SO 行项就从 C# 应用程序中按特定数量授权,并且可以从 Navision 或 Navision 文档授权应用程序过账。
当我们更改记录时,SO“101015”的销售行项目 1896-S 已被授权,即:
在上图中,可以看出,对于订单号 101015 的第二个网格的行号 6 已被授权。此附加组件具有为特定数量授权销售行的功能。这意味着当销售行被授权为特定数量时,用户不能从 Navision 或“Authorize Navision Sales Order”(授权 Navision 销售订单)附加组件进行超过授权数量的发货。
d) 现在,直接从“Authorize Navision Sales Order”(授权 Navision 销售订单)附加组件授权订单号“101015”的销售行数量为 10。
如果打开 Navision 中的销售订单,您会发现销售数量为 15,但授权数量为 10。这意味着不能为第 6 行过账超过 10 的销售数量,即:
在上图中,您可以看到授权数量为 10,且不可编辑。此授权只能通过 Navision 文档授权附加组件进行。此功能表明,如果任何 ISV、客户已经拥有附加组件,为什么还要有人从零开始在 Navision 中开发相同的功能。由于 Microsoft 发布了 Navision 2009 SP1,因此这种集成非常容易实现,并且在其中,他们通过 Windows Communication Framework 架构公开了所有 Navision 页面和代码单元。
e) 现在,如果用户尝试过账 SO 号 101015 的销售行号 5,则 SO 将根据用户的选择过账到发货或发票或两者都过账。我为“Navision Document Authorization”(Navision 文档授权)附加组件提供的另一个有趣的集成是,任何用户都可以直接从附加组件过账 SO 到发货和发票。此功能还为任何 ISV、合作伙伴或客户提供了双向集成的功能。从 Navision 到 NDA(Navision 文档授权)附加组件,反之亦然。在本例中,从 Navision 到 NDA(Navision 文档授权)附加组件,反之亦然。
近 7 年来,我一直对只从 Navision 过账 Navision 销售订单感到厌倦,这次我想做些改变,所以我决定从我的 NDA 附加组件过账…
您可以看到,用户可以只过账到发货,然后开票,或者直接到发货和开票。所以我更倾向于直接过账和开票。
首先,让我们尝试过账比 Navision 中授权数量更多的数量。
在上图中,您可以看到它弹出错误:“Qty. to ship 11 cannot be greater than Authorized Qty 10.”(待发货数量 11 不能大于授权数量 10。)因此,我们走在正确的道路上,因为此行的附加组件上的授权数量为 10,并且此信息在 Navision 屏幕上也可用。所以,现在尝试过账 8 个数量。
在上图中,我将 SO 101015 的最后一行的数量更改为 8,并且没有弹出错误。
现在,我们将尝试从 NDA 附加组件过账订单。
因此,我们的销售订单 101015 已发货并为授权数量 10 开具了发票。
f)
现在,可以直接从 NDA 附加组件查看已过账的发货和已过账的发票,而无需进入 Navision。只需点击 NDA 附加组件上的“Posted Shipments”(已过账发货)按钮。
所以,您在上图中可以看到,对于 SO 号 101015 有 5 个发货,而我们刚才过账的发货号是 102045,数量为 8。
g)
现在,可以直接从 NDA 附加组件查看已过账的发票,而无需进入 Navision。只需点击 NDA 附加组件上的“Posted Invoices”(已过账发票)按钮。
所以,您在上图中可以看到,对于 SO 号 101015 有 3 个发货,而我们刚才过账的发票号是 103023,数量为 8。
从此附加组件获得的收获
- ISV、客户和开发人员可以轻松地将其附加组件与 Navision 集成,以将现有功能引入 Navision。
- ISV、客户和开发人员可以轻松理解将 Navision 与任何附加组件集成的最简单方法,即使用 Windows Communication Framework 架构。
- ISV、客户和开发人员可以根据本文定义的最新架构,将其附加组件的旧架构(Navision 自动化)更改为新架构,并附带源代码。
- 重要提示 - 现在,**无需在 Navision CSIDE 代码中开发任何功能。** 只需确定可以在哪个点将为其他平台开发的功能与 Navision 集成,并提供一个通用适配器,以便我们的附加组件可以与 Navision 以及 Axapta、SAP、Peoplesoft 等其他 ERP 集成。请注意,此附加组件的开发方式使其可以通过更改少量代码连接到 Axapta 和其他 ERP。
- 正如开头所述,现在我们可以使用 WPF、WCF、C#、Silverlight、Azax 和 XML 开发任何业务功能,并通过使用 NDA 附加组件中定义的这种方法轻松地将其与 Navision 2009 SP1 集成。最近,Microsoft 发布了 Navision 2009 R2 版本,该版本将 Navision ERP 部署到 Web(互联网)上,因此在我的下一个 NDA R2 版本中,我将把本文的整个架构迁移到 Navision 2009 R2,从而演示如何轻松地将附加组件部署到网上,并进入全新的云计算世界。
- 现在,为客户添加新功能的任何 Navision 定制都可以轻松地在 .NET 中开发,如本文所述,这将为实施合作伙伴节省昂贵的 Navision 对象成本。
即将推出
最近,Microsoft 发布了 Navision 2009 R2 版本,该版本将 Navision ERP 部署到 Web(互联网)上,因此在我的下一个 NDA R2 版本中,我将把本文的整个架构迁移到 Navision 2009 R2,从而演示如何轻松地将附加组件部署到网上,并进入全新的云计算世界。
请等待下一个 NDA R2(Release-2)版本,即将推出…