Calculating Total Order Quantity - EpiViewNotification Event Type

Hi,

I have added a UD Field to OrderHed which should display the Total Quantity on an Order. This will sum the SellingQuantity per line and display as one total value.

I am using an EpiViewNotification Event Type on the OrderDtl view. I have included my code below. The field correctly updates the value on the first line but it wont recalculate subsequent lines until after I add a line. Would anyone be able to offer some assistance on how to correct this?

Thanks in advance.

Custom Code:

private void edvOrderDtl_EpiViewNotification(EpiDataView view, EpiNotifyArgs args)
	{
				// ** Argument Properties and Uses **
				// view.dataView[args.Row]["FieldName"]
				// args.Row, args.Column, args.Sender, args.NotifyType
				// NotifyType.Initialize, NotifyType.AddRow, NotifyType.DeleteRow, NotifyType.InitLastView, NotifyType.InitAndResetTreeNodes
				if ((args.NotifyType == EpiTransaction.NotifyType.AddRow))
		{
					if ((args.Row > -1))
			{
				EpiDataView edvOrderHed = ((EpiDataView)(this.oTrans.EpiDataViews["OrderHed"]));
				if (edvOrderHed.Row>-1)
				{
					DataRow rowOrderHed=edvOrderHed.dataView.Table.Rows[edvOrderHed.Row];							
					decimal dTotalTradeQuantity=view.dataView.Table.Rows.Count>0 
						? view.dataView.Table.AsEnumerable().Sum(x=> 
							x.Field<decimal>("SellingQuantity")) 
						: 0;
					if (Math.Round((decimal)(rowOrderHed.Field<decimal?>("UD_TotalTradeQty_c") ?? 0),2)!=Math.Round(dTotalTradeQuantity,2))	
					{
						rowOrderHed.BeginEdit();
						rowOrderHed["UD_TotalTradeQty_c"]=Math.Round(dTotalTradeQuantity,2);
						rowOrderHed.EndEdit();
					}
				}
				
			}
		}

	}

Hi @josecgomez ,

Would you have any thoughts on this? Thanks in advance

I won’t update any lines, or it just won’t update the last line? If you have 5 lines in there, does it only update the first row?

Hi Brandon,

It will update with the value from the first line. It wont add in the value from any values there after.

Example:

Line 1= 25,000kgs
Line 2 = 25,000kgs

UD field should display 50,000kgs.

Based on my code the UD field only displays 25,000kgs

Hi Brandon, @Banderson

It will update with the value from the first line. It wont add in the value from any values there after.

Example:

Line 1= 25,000kgs
Line 2 = 25,000kgs

UD field should display 50,000kgs.

Based on my code the UD field only displays 25,000kgs

So you’re notification is on add row. I would assume that it would to all but the last one, because it will do the calculation when a row is added, not when a row is done being edited.

Can you humor me and try with 3+ lines once?

Correct. It is an add row notification.

When i add a 3rd line, it sums up the values from the first two lines. It wont take the 3rd line until i attempt to add a 4th line

So that means that the calculation isn’t being done until you add a line. (which makes sense). You probably would be better off with a field change event, because if someone changes a quantity on a line, you are going to want that to be recalculated. So instead of doing it on an EpiViewNotification, I would try to use an AfterFieldChange event.

Thanks Brandon! That makes more sense. I shall give that a go and see how it works out. Watch this space :grinning:

Thanks for the advice. Very much appreciated.

Hi Brandon @Banderson

I have been working on this again today and have been trying the AfterFieldChange event.

What happens now is;

  1. When i add a line, the Selling Quantity doubles itself in my UD Field. This is an issue with my code as I am using the + operator as opposed to a sum function. I cannot seem to get the sum function to work. I have tried Sum() and Enumerable.Sum().

  2. Secondly, when i add a second line, the UD field reverts to 0. When i add in a quantity on that second line, it does the same as the above again except on the second line only.

Would you have any further thoughts? I would really appreciate it.

private void OrderDtl_AfterFieldChange(object sender, DataColumnChangeEventArgs args)
{
	// ** Argument Properties and Uses **
	// args.Row["FieldName"]
	// args.Column, args.ProposedValue, args.Row
	// Add Event Handler Code
	switch (args.Column.ColumnName)
	{
		case "SellingQuantity":

		EpiDataView edvOrderDtl = ((EpiDataView)(this.oTrans.EpiDataViews["OrderDtl"]));
		edvOrderDtl.dataView[edvOrderDtl.Row] ["UD_TotalTradeQty_c"] = Convert.ToDecimal(args.ProposedValue) + (decimal)edvOrderDtl.dataView[edvOrderDtl.Row] ["SellingQuantity"];

			break;
	}
}

You don’t want to add it to the existing field. You’re going to keep adding every time you change that field, not only when you are adding a new row. Try this approach instead:

  1. instantiate a variable within your case statement, set that to 0.
  2. loop through your data view with a for each, add each row to the variable (use +=).
  3. After you are done looping through and adding up the the values in the dtl lines, set (not add, set) the value to your header

Let me know if that approach makes sense. Try to code this approach yourself first, and if you get stuck, show me what you have I can help you with the actual code.

Thank you Brandon @Banderson .

I think I got it. As you can see from the image 1 below, I have added 2 lines to my order. Each line is for 25,000 kgs each. The UD field correctly displays 50,000 kgs as required.

The only thing this does is, if i click on the first line, the value resets to the quantity on the first line. Even when more than one line has been added (image 2). This does not recalculate even if the user navigates away from OrderDtl.

Would that be because i have placed the event on OrderDtl and in fact should have the event on OrderHed (I have also bound the field to OrderDtl as opposed to OrderHed)?

		private void OrderDtl_AfterFieldChange(object sender, DataColumnChangeEventArgs args)
	{
			// ** Argument Properties and Uses **
			// args.Row["FieldName"]
			// args.Column, args.ProposedValue, args.Row
			// Add Event Handler Code
			switch (args.Column.ColumnName)
			{
			
					case "SellingQuantity":
					decimal TotalTradeQuantity = 0;

					EpiDataView edvOrderDtl = ((EpiDataView)(this.oTrans.EpiDataViews["OrderDtl"]));
					
						foreach(DataRow dr in edvOrderDtl.dataView.Table.Rows)
							{
								//dr["UD_TotalTradeQty_c"] = 
								TotalTradeQuantity += (Convert.ToDecimal (dr ["SellingQuantity"]));
							
							}

				edvOrderDtl.dataView[edvOrderDtl.Row] ["UD_TotalTradeQty_c"] = TotalTradeQuantity;

					//Convert.ToDecimal(args.ProposedValue);
		
					break;
			}
	}

The event needs to be on orderDtl because that’s actually what’s changing (so that’s ok). But you need to be updating the orderHed dataView, not the order Dtl Data view. In your first example, you are updating the correct field, but then in your later examples you switch to updating the orderDtl view. So you have half of your solution in the first part (updating the header view), and half of your solution in the second part (using the field changed event)

I’m assuming that you bound your field to a header UD field. So when you set your value, set like shown below. You already have a hold of your header data view in your first example, so use that same code to get a hold of it, then use this code to update the field. I should handle the notification so that it changes on your screen.

            edvOrderHed.dataView[edvOrderHed.Row].BeginEdit();
            edvOrderHed.dataView[edvOrderHed.Row]["UD_TotalTradeQty_c"] = TotalTradeQuantity;
            edvOrderHed.dataView[edvOrderHed.Row].EndEdit();

Some other trouble shooting tips to see what’s happening is

  1. If you have visual studio, run in debug mode so you can see the values of the variables
  2. if you don’t then pop in message boxes using MessageBox.Show(yourVariable); to show you what you are getting. That will help you instead of guessing (for example, if your field isn’t updating, is it the actual value of your variable that is wrong, or is it the updating that isn’t working correctly), also it can help you see when your event is actually firing, so you could have figured out the best place to put the method.

That makes logical sense to me. I have updated my code accordingly and it works perfectly now Brandon!! @Banderson

Thank you very much for your help. I definitely have taken a lot on from that so really much appreciated.

		private void OrderDtl_AfterFieldChange(object sender, DataColumnChangeEventArgs args)
	{
			// ** Argument Properties and Uses **
			// args.Row["FieldName"]
			// args.Column, args.ProposedValue, args.Row
			// Add Event Handler Code
			switch (args.Column.ColumnName)
			{
			
					case "SellingQuantity":
					decimal TotalTradeQuantity = 0;

					EpiDataView edvOrderHed = ((EpiDataView)(this.oTrans.EpiDataViews["OrderHed"]));
					
						foreach(DataRow dr in edvOrderDtl.dataView.Table.Rows)

							{ 

								TotalTradeQuantity += (Convert.ToDecimal (dr ["SellingQuantity"]));

							}

				edvOrderHed.dataView[edvOrderHed.Row].BeginEdit();
				edvOrderHed.dataView[edvOrderHed.Row]["UD_TotalTradeQty_c"]=TotalTradeQuantity;
				edvOrderHed.dataView[edvOrderHed.Row].EndEdit();
					
					break;

			}
	}
2 Likes