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

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.73/5 (7投票s)

2010 年 12 月 21 日

CPOL

14分钟阅读

viewsIcon

58499

downloadIcon

2006

这是一个展示如何将 Navision 与任何第三方应用程序集成,并在 Navision 与该应用程序之间进行数据交互的出色示例。

引言

本文演示了如何在 Navision ERP 外部运行的业务流程可以轻松地与 Navision 中的任何业务流程集成。为了更好地理解这一点,我使用了真实的场景。

考虑一个用 C# 开发的系统,它具有授权销售订单数量的功能。一旦在 Navision 中创建了销售订单,那么从 C# 中,您可以根据本文执行各种操作。

  1. 从 C# 查看销售订单
  2. 从 C# 授权销售订单数量。这不仅可以从 C# 授权销售行数量,还可以在授权销售订单时运行 Navision 中存在的业务逻辑。
  3. 授权后,您可以从 C# 过账销售订单以进行销售发货。
  4. 销售发货后,您还可以将销售订单过账为销售发票。
  5. 您还可以同时将销售订单过账为销售发货和销售发票。
  6. 本文不仅允许授权销售订单,还更新了授权的数量。这意味着用户不能进行超过授权数量的发货和发票。
  7. 在 C# 授权之前,用户无法过账销售订单。
  8. 在过账已授权的 Navision SO 行项后,您可以在此“Navision 文档授权”附加组件中查看已过账的发货和发票。

现在,聪明的人们一定会问,为什么我们要从 C# 进行销售授权,而不是仅仅在 Navision 中进行自定义?

为了理解这一点,请考虑一个场景,即:

客户或 ISV 拥有一个授权应用程序,该应用程序具有所有业务逻辑来授权销售订单数量,现在客户或 ISV 要求将此功能与 Navision 集成,以便我们可以利用授权应用程序的功能与 Navision 相互作用。

通过使用这种集成,我们将获得以下好处:

  1. 如果该功能已存在于某个附加组件中,则无需在 Navision 中从头开始开发,只需在 8 小时内将其与 Navision 集成。
  2. 由于附加组件功能可以在 .NET 平台中开发并轻松集成到 Navision 2009 Sp1 中,因此可以节省 ISV 将附加组件产品推向 Navision 市场的大量时间。
  3. ISV 可以将时间投入到开发附加组件中已有的功能上,而不是花费时间重复开发,而是可以利用这些时间为他们的附加组件添加更多功能,这将为他们的附加组件带来更多附加价值,并使其在竞争中更具优势。

假设客户给了我们一个 API,该 API 返回销售订单号、行号、授权信息和授权数量。现在,通过使用这 5 个字段,我开发了一个连接器或适配器,通过 C# 更新 Navision 销售订单,并执行了从步骤 a 到 h 定义的所有操作。

本文旨在帮助 ISV、客户和开发人员将他们的旧应用程序与 Microsoft Dynamics Navision 集成。

观众心中可能会出现一些问题,即通过本文定义的框架可以集成什么类型的应用程序,所以请在此处找到答案,即:

  1. 任何用 VB、C# 开发的零售应用程序都可以轻松地与 Navision 业务流程集成。因此,如果已经有第三方应用程序,则无需在 Navision 中开发零售系统。只需使用本文中的框架将其与 Navision 应用程序集成。
  2. 任何文档标记应用程序和授权应用程序都可以轻松地与 Navision 中的 SOP 流程、POP 流程、制造流程和所有其他流程集成。
  3. 用 C#、WPF 开发的导出和导入功能可以轻松地与 Navision 集成。
  4. 用 C#、WPF 开发的质量模块可以轻松地与 Navision 流程集成。
  5. 用 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。TablesFormsPagesCodeunitsDataportsMenusuites 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 表,即:

p1.JPG

在上图中,为 ID 50000 和 50001 添加了两个字段“Authorize”(授权)和“Authorize Qty”(授权数量)。

开发 2:在 Navision 的“SalesLine”表上添加两个字段的验证

p2.JPG

在上图中,对 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 销售订单。

p3.JPG

上面的代码稍后将在本文中作为 Web 服务公开,以启用 C# 进行过账。

开发 4:在 Navision 中公开 Page 和 Codeunit 作为服务

我们已在 Navision 中为授权附加组件开发了基本业务逻辑。现在我们将从这一点开始 C# 编码。首先,将修改后的 Page Codeunit 公开为 Web 服务,如下所示。

p4.JPG

在上图中,“Web Services”(Web 服务)窗体包含 Page 和 Codeunit 的记录。这意味着 Page ID 132、130、48、46、42、46 和 Codeunit 50001 已公开为 Web 服务。

开发 5:创建文档授权的 C# 应用程序

在 C# 中创建“NavisionDocumentAuthorization”项目,并为 Navision 的公开对象添加引用,如下所示。

p5.JPG

在上图中,Web 服务的地址如下,它们是在修改 4 中公开的。

开发 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”窗体

p6.JPG

开发 8:在 C# 中创建“PostedShipments”窗体

p7.JPG

开发 9:在 C# 中创建“PostedInvoices”窗体

p8.JPG

开发 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# 应用程序

p9.JPG

上面的窗体包含 Navision 销售订单列表。目前,用户在销售订单号 1001 上,它只有一个关联的销售行。

当用户进入 SalesOrder 屏幕的记录“101009”时,UI 将如下所示。

p10.JPG

上面的窗体包含销售订单“101009”的两个销售行项目。

b) 现在,我们将授权订单号“101015”的销售订单行。

在授权之前,如果用户尝试过账销售订单或对销售“Qty to Invoice”(待开票数量)或销售“Qty to Ship”(待发货数量)字段进行修改,则会引发一个异常,即“Sales Line is not authorized”(销售行未授权)。

p11.JPG

当用户尝试从 C# 应用程序过账时,也会出现上述错误,即:

p12.JPG

c) 现在,我们将从 C# 应用程序授权订单号“101015”的 Item No. “1896-S”。这是 Navision 文档授权的集成点,这样 Navision SO 行项就从 C# 应用程序中按特定数量授权,并且可以从 Navision 或 Navision 文档授权应用程序过账。

p14.JPG

当我们更改记录时,SO“101015”的销售行项目 1896-S 已被授权,即:

p15.JPG

在上图中,可以看出,对于订单号 101015 的第二个网格的行号 6 已被授权。此附加组件具有为特定数量授权销售行的功能。这意味着当销售行被授权为特定数量时,用户不能从 Navision 或“Authorize Navision Sales Order”(授权 Navision 销售订单)附加组件进行超过授权数量的发货。

d) 现在,直接从“Authorize Navision Sales Order”(授权 Navision 销售订单)附加组件授权订单号“101015”的销售行数量为 10。

p16.JPG

如果打开 Navision 中的销售订单,您会发现销售数量为 15,但授权数量为 10。这意味着不能为第 6 行过账超过 10 的销售数量,即:

p17.JPG

在上图中,您可以看到授权数量为 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 中授权数量更多的数量。

p18.JPG

在上图中,您可以看到它弹出错误:“Qty. to ship 11 cannot be greater than Authorized Qty 10.”(待发货数量 11 不能大于授权数量 10。)因此,我们走在正确的道路上,因为此行的附加组件上的授权数量为 10,并且此信息在 Navision 屏幕上也可用。所以,现在尝试过账 8 个数量。

p19.JPG

在上图中,我将 SO 101015 的最后一行的数量更改为 8,并且没有弹出错误。

现在,我们将尝试从 NDA 附加组件过账订单。

p20.JPG

p21.JPG

p22.JPG

因此,我们的销售订单 101015 已发货并为授权数量 10 开具了发票。

f)

现在,可以直接从 NDA 附加组件查看已过账的发货和已过账的发票,而无需进入 Navision。只需点击 NDA 附加组件上的“Posted Shipments”(已过账发货)按钮。

p23.JPG

所以,您在上图中可以看到,对于 SO 号 101015 有 5 个发货,而我们刚才过账的发货号是 102045,数量为 8。

g)

现在,可以直接从 NDA 附加组件查看已过账的发票,而无需进入 Navision。只需点击 NDA 附加组件上的“Posted Invoices”(已过账发票)按钮。

p24.JPG

所以,您在上图中可以看到,对于 SO 号 101015 有 3 个发货,而我们刚才过账的发票号是 103023,数量为 8。

从此附加组件获得的收获

  1. ISV、客户和开发人员可以轻松地将其附加组件与 Navision 集成,以将现有功能引入 Navision。
  2. ISV、客户和开发人员可以轻松理解将 Navision 与任何附加组件集成的最简单方法,即使用 Windows Communication Framework 架构。
  3. ISV、客户和开发人员可以根据本文定义的最新架构,将其附加组件的旧架构(Navision 自动化)更改为新架构,并附带源代码。
  4. 重要提示 - 现在,**无需在 Navision CSIDE 代码中开发任何功能。** 只需确定可以在哪个点将为其他平台开发的功能与 Navision 集成,并提供一个通用适配器,以便我们的附加组件可以与 Navision 以及 Axapta、SAP、Peoplesoft 等其他 ERP 集成。请注意,此附加组件的开发方式使其可以通过更改少量代码连接到 Axapta 和其他 ERP。
  5. 正如开头所述,现在我们可以使用 WPF、WCF、C#、Silverlight、Azax 和 XML 开发任何业务功能,并通过使用 NDA 附加组件中定义的这种方法轻松地将其与 Navision 2009 SP1 集成。最近,Microsoft 发布了 Navision 2009 R2 版本,该版本将 Navision ERP 部署到 Web(互联网)上,因此在我的下一个 NDA R2 版本中,我将把本文的整个架构迁移到 Navision 2009 R2,从而演示如何轻松地将附加组件部署到网上,并进入全新的云计算世界。
  6. 现在,为客户添加新功能的任何 Navision 定制都可以轻松地在 .NET 中开发,如本文所述,这将为实施合作伙伴节省昂贵的 Navision 对象成本。

即将推出

最近,Microsoft 发布了 Navision 2009 R2 版本,该版本将 Navision ERP 部署到 Web(互联网)上,因此在我的下一个 NDA R2 版本中,我将把本文的整个架构迁移到 Navision 2009 R2,从而演示如何轻松地将附加组件部署到网上,并进入全新的云计算世界。

请等待下一个 NDA R2(Release-2)版本,即将推出…

© . All rights reserved.