private void RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
		{
			var val = (PropertyValue)e.Row;
			var oldValue = (PropertyValue)e.OldRow;
			if (Equals(val.Value, oldValue.Value)) return;

			var itemsCache = View.Cache;
			foreach (PropertyValue item in sender.Cached.
				Cast<PropertyValue>().
				Where(_ => _.Order > val.Order).
				OrderBy(_ => _.Order))
			{
				if (string.IsNullOrWhiteSpace(item.Name)) continue;

				var propertyInfo = itemsCache.GetType().GetProperty(item.Name);
				if (propertyInfo == null) continue;

				var verifier = Attribute.GetCustomAttribute(propertyInfo, PropertyMarkAttribute) as PXMassProcessFieldAttribute;
				if (verifier == null || verifier.SearchCommand == null) continue;

				var searchCommand = (BqlCommand)Activator.CreateInstance(verifier.SearchCommand);
				var verifingParams = new List<object>();
				var itemOrder = item.Order;
				foreach(IBqlParameter param in searchCommand.GetParameters())
				{
					var refType = param.GetReferencedType();
					if (refType == null) continue;

					var propVal = sender.Cached.Cast<PropertyValue>().FirstOrDefault(_ => _.Order < itemOrder && Equals(refType.Name, _.Name));
					verifingParams.Add(propVal.With(_ => _.Value));
				}

				int startRow = 0;
				int totalRows = 0;
				var searchResult = new PXView(Graph, true, searchCommand).
									Select(null, verifingParams.ToArray(),
										new object[] { item.Value },
										new string[] { ((IBqlSearch)searchCommand).GetField().Name },
										new bool[] { false },
										null, ref startRow, 1, ref totalRows);
				if (searchResult == null || searchResult.Count == 0)
				{
					item.Value = null;
				}
			}
		}
		protected virtual void LocationAPPaymentInfo_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
		{
			LocationAPPaymentInfo record = (LocationAPPaymentInfo)e.Row;
            if (!sender.ObjectsEqual<LocationAPPaymentInfo.vCashAccountID, LocationAPPaymentInfo.vPaymentMethodID, LocationAPPaymentInfo.vPaymentLeadTime, LocationAPPaymentInfo.vPaymentByType, LocationAPPaymentInfo.vSeparateCheck, LocationAPPaymentInfo.isRemitAddressSameAsMain, LocationAPPaymentInfo.isRemitContactSameAsMain>(e.Row, e.OldRow))
			{
				Location mainloc = Location.Current;
				mainloc.VCashAccountID = record.VCashAccountID;
				mainloc.VPaymentMethodID = record.VPaymentMethodID;
				mainloc.VPaymentLeadTime = record.VPaymentLeadTime;
				mainloc.VPaymentByType = record.VPaymentByType;
				mainloc.VSeparateCheck = record.VSeparateCheck;
				mainloc.IsRemitAddressSameAsMain = record.IsRemitAddressSameAsMain;
				mainloc.VRemitAddressID = record.VRemitAddressID;
				mainloc.IsRemitContactSameAsMain = record.IsRemitContactSameAsMain;
				mainloc.VRemitContactID = record.VRemitContactID;

				if (Location.Cache.GetStatus(mainloc) == PXEntryStatus.Notchanged)
				{
					Location.Cache.SetStatus(mainloc, PXEntryStatus.Updated);
				}

				sender.Graph.Caches[typeof (Location)].IsDirty = true;
			}
		}        
		protected virtual void LocationAPAccountSub_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
		{
			LocationAPAccountSub record = (LocationAPAccountSub)e.Row;

			if (!sender.ObjectsEqual<LocationAPAccountSub.vAPAccountID, LocationAPAccountSub.vAPSubID>(e.Row, e.OldRow))
			{
				Location mainloc = Location.Current;
				mainloc.VAPAccountID = record.VAPAccountID;
				mainloc.VAPSubID = record.VAPSubID;

				if (Location.Cache.GetStatus(mainloc) == PXEntryStatus.Notchanged)
				{
					Location.Cache.SetStatus(mainloc, PXEntryStatus.Updated);
				}
			}
		}
			public void RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
			{
				CurrencyInfo info = e.Row as CurrencyInfo;
				if (info != null)
				{
					CurrencyInfo old = e.OldRow as CurrencyInfo;
					if (old != null && (String.IsNullOrEmpty(info.CuryID) || String.IsNullOrEmpty(info.BaseCuryID)))
					{
						info.BaseCuryID = old.BaseCuryID;
						info.CuryID = old.CuryID;
					}
					if (currencyInfoDirty == false
						&& info.CuryID == old.CuryID
						&& info.CuryRateTypeID == old.CuryRateTypeID
						&& info.CuryEffDate == old.CuryEffDate
						&& info.CuryMultDiv == old.CuryMultDiv
						&& info.CuryRate == old.CuryRate)
					{
						sender.IsDirty = false;
						currencyInfoDirty = null;
					}
				}
			}
		protected virtual void SOOrder_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
		{
			SOOrder row = e.Row as SOOrder;
			SOOrder oldRow = e.OldRow as SOOrder;
			if (row != null && oldRow != null && row.UnbilledOrderQty != oldRow.UnbilledOrderQty)
			{
				row.IsUnbilledTaxValid = false;
			}
			

			if (e.OldRow != null)
			{
				ARReleaseProcess.UpdateARBalances(this, (SOOrder)e.OldRow, -((SOOrder)e.OldRow).UnbilledOrderTotal, -((SOOrder)e.Row).OpenOrderTotal);
			}
			ARReleaseProcess.UpdateARBalances(this, (SOOrder)e.Row, ((SOOrder)e.Row).UnbilledOrderTotal, ((SOOrder)e.Row).OpenOrderTotal);
		}
		protected override void ARInvoice_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
		{
			ARSetup.Current.RequireControlTotal = (((ARInvoice)e.Row).DocType == ARDocType.CashSale || ((ARInvoice)e.Row).DocType == ARDocType.CashReturn) ? true : ARSetup.Current.RequireControlTotal;

			base.ARInvoice_RowUpdated(sender, e);

			ARInvoice doc = e.Row as ARInvoice;
			if ((doc.DocType == ARDocType.CashSale || doc.DocType == ARDocType.CashReturn) && doc.Released != true)
			{
				if (sender.ObjectsEqual<ARInvoice.curyDocBal, ARInvoice.curyOrigDiscAmt>(e.Row, e.OldRow) == false && doc.CuryDocBal - doc.CuryOrigDiscAmt != doc.CuryOrigDocAmt)
				{
					if (doc.CuryDocBal != null && doc.CuryOrigDiscAmt != null && doc.CuryDocBal != 0)
						sender.SetValueExt<ARInvoice.curyOrigDocAmt>(doc, doc.CuryDocBal - doc.CuryOrigDiscAmt);
					else
						sender.SetValueExt<ARInvoice.curyOrigDocAmt>(doc, 0m);
				}
				else if (sender.ObjectsEqual<ARInvoice.curyOrigDocAmt>(e.Row, e.OldRow) == false)
				{
					if (doc.CuryDocBal != null && doc.CuryOrigDocAmt != null && doc.CuryDocBal != 0)
						sender.SetValueExt<ARInvoice.curyOrigDiscAmt>(doc, doc.CuryDocBal - doc.CuryOrigDocAmt);
					else
						sender.SetValueExt<ARInvoice.curyOrigDiscAmt>(doc, 0m);
				}
			}

			if ((doc.DocType == ARDocType.CashSale || doc.DocType == ARDocType.CashReturn) && doc.Released != true && doc.Hold != true)
			{
				if (doc.CuryDocBal < doc.CuryOrigDocAmt)
				{
					sender.RaiseExceptionHandling<ARInvoice.curyOrigDocAmt>(doc, doc.CuryOrigDocAmt, new PXSetPropertyException(AR.Messages.CashSaleOutOfBalance));
				}
				else
				{
					sender.RaiseExceptionHandling<ARInvoice.curyOrigDocAmt>(doc, doc.CuryOrigDocAmt, null);
				}
			}

			if (!sender.ObjectsEqual<ARInvoice.customerID, ARInvoice.docDate, ARInvoice.finPeriodID, ARInvoice.curyTaxTotal, ARInvoice.curyOrigDocAmt, ARInvoice.docDesc, ARInvoice.curyOrigDiscAmt>(e.Row, e.OldRow))
			{
				SODocument.Current = (SOInvoice)SODocument.Select() ?? (SOInvoice)SODocument.Cache.Insert();
				SODocument.Current.CustomerID = ((ARInvoice)e.Row).CustomerID;

                if ((((ARInvoice)e.Row).DocType == ARDocType.CashSale 
                        || ((ARInvoice)e.Row).DocType == ARDocType.CashReturn 
                        || ((ARInvoice)e.Row).DocType == ARDocType.Invoice) && !sender.ObjectsEqual<ARInvoice.customerID>(e.Row, e.OldRow))
				{
                    SODocument.Cache.SetDefaultExt<SOInvoice.paymentMethodID>(SODocument.Current);
					SODocument.Cache.SetDefaultExt<SOInvoice.pMInstanceID>(SODocument.Current);
				}

				SODocument.Current.AdjDate = ((ARInvoice)e.Row).DocDate;
				SODocument.Current.AdjFinPeriodID = ((ARInvoice)e.Row).FinPeriodID;
				SODocument.Current.AdjTranPeriodID = ((ARInvoice)e.Row).TranPeriodID;
				SODocument.Current.CuryTaxTotal = ((ARInvoice)e.Row).CuryTaxTotal;
				SODocument.Current.TaxTotal = ((ARInvoice)e.Row).TaxTotal;
				SODocument.Current.CuryPaymentAmt = ((ARInvoice)e.Row).CuryOrigDocAmt - ((ARInvoice)e.Row).CuryOrigDiscAmt - SODocument.Current.CuryPaymentTotal;
				SODocument.Current.DocDesc = ((ARInvoice)e.Row).DocDesc;
				SODocument.Current.PaymentProjectID = PM.ProjectDefaultAttribute.NonProject(this);

				if (SODocument.Cache.GetStatus(SODocument.Current) == PXEntryStatus.Notchanged)
				{
					SODocument.Cache.SetStatus(SODocument.Current, PXEntryStatus.Updated);
				}
			}
		}
		protected virtual void SOFreightDetail_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
		{
			SOFreightDetail row = e.Row as SOFreightDetail;
			if (row != null)
			{
				foreach (ARTran tran in PXSelect<ARTran,
				Where<ARTran.lineType, Equal<SOLineType.freight>,
				And<ARTran.tranType, Equal<Current<ARInvoice.docType>>,
				And<ARTran.refNbr, Equal<Current<ARInvoice.refNbr>>,
				And<ARTran.sOShipmentNbr, Equal<Required<ARTran.sOShipmentNbr>>,
				And<ARTran.sOShipmentType, NotEqual<SOShipmentType.dropShip>>>>>>>.Select(this, row.ShipmentNbr))
				{
					Freight.Delete(tran);
				}

				if (row.CuryTotalFreightAmt > 0)
					AddFreightTransaction(row);
			}
		}
 protected virtual void AddDiscountDetails(PXCache sender, PXRowUpdatedEventArgs e)
 {
     foreach (SOInvoiceDiscountDetail dDetail in DiscountDetails.Select())
     {
         ARInvoiceDiscountDetail arDiscountDetail = new ARInvoiceDiscountDetail();
         SOInvoiceDiscountDetail discountCopy = (SOInvoiceDiscountDetail)DiscountDetails.Cache.CreateCopy(dDetail);
         foreach (ARInvoiceDiscountDetail aDetail in ARDiscountDetails.Select())
         {
             if (aDetail.DiscountID == discountCopy.DiscountID && aDetail.DiscountSequenceID == discountCopy.DiscountSequenceID && aDetail.Type == discountCopy.Type)
             {
                 arDiscountDetail = aDetail;
             }
         }
         arDiscountDetail.CuryDiscountableAmt = discountCopy.CuryDiscountableAmt;
         arDiscountDetail.CuryDiscountAmt = discountCopy.CuryDiscountAmt;
         arDiscountDetail.CuryInfoID = discountCopy.CuryInfoID;
         arDiscountDetail.DiscountableAmt = discountCopy.DiscountableAmt;
         arDiscountDetail.DiscountableQty = discountCopy.DiscountableQty;
         arDiscountDetail.DiscountAmt = discountCopy.DiscountAmt;
         arDiscountDetail.DiscountID = discountCopy.DiscountID;
         arDiscountDetail.DiscountPct = discountCopy.DiscountPct;
         arDiscountDetail.DiscountSequenceID = discountCopy.DiscountSequenceID;
         arDiscountDetail.FreeItemID = discountCopy.FreeItemID;
         arDiscountDetail.FreeItemQty = discountCopy.FreeItemQty;
         arDiscountDetail.Type = discountCopy.Type;
         ARDiscountDetails.Update(arDiscountDetail);
     }
 }
		protected virtual void AddDiscount(PXCache sender, PXRowUpdatedEventArgs e)
		{
            AddDiscountDetails(sender, e);
            
            ARTran discount = (ARTran)Discount.Cache.CreateInstance();
			discount.LineType = SOLineType.Discount;
			discount.DrCr = (Document.Current.DrCr == "D") ? "C" : "D";
			discount.FreezeManualDisc = true;
			discount = (ARTran)Discount.Select() ?? (ARTran)Discount.Cache.Insert(discount);

			ARTran old_row = (ARTran)Discount.Cache.CreateCopy(discount);

			discount.CuryTranAmt = (decimal?)sender.GetValue<SOInvoice.curyDiscTot>(e.Row);
			discount.TaxCategoryID = null;
			discount.TranDesc = PXMessages.LocalizeNoPrefix(Messages.DocDiscDescr);
			
			DefaultDiscountAccountAndSubAccount(discount);

            if (discount.TaskID == null && !PM.ProjectDefaultAttribute.IsNonProject(this, discount.ProjectID))
            {
                PM.PMProject project = PXSelect<PM.PMProject, Where<PM.PMProject.contractID, Equal<Required<PM.PMProject.contractID>>>>.Select(this, discount.ProjectID);
                if (project != null && project.BaseType != "C")
                {
                    PM.PMAccountTask task = PXSelect<PM.PMAccountTask, Where<PM.PMAccountTask.accountID, Equal<Required<PM.PMAccountTask.accountID>>>>.Select(this, discount.AccountID);
                    if (task != null)
                    {
                        discount.TaskID = task.TaskID;
                    }
                    else
                    {
                        Account ac = PXSelect<Account, Where<Account.accountID, Equal<Required<Account.accountID>>>>.Select(this, discount.AccountID);
                        throw new PXException(string.Format(Messages.AccountMappingNotConfigured, project.ContractCD, ac.AccountCD));
                    }
                }
            }
			
			if (Discount.Cache.GetStatus(discount) == PXEntryStatus.Notchanged)
			{
				Discount.Cache.SetStatus(discount, PXEntryStatus.Updated);
			}

			discount.ManualDisc = true; //escape SOManualDiscMode.RowUpdated
			Discount.Cache.RaiseRowUpdated(discount, old_row);

			decimal auotDocDisc = GetAutoDocDiscount();
			if (auotDocDisc == discount.CuryTranAmt)
			{
				discount.ManualDisc = false;
			}
			
			if (discount.CuryTranAmt == 0)
			{
				Discount.Delete(discount);
			}
		}
		protected override void ARTran_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
		{
			ARTran row = (ARTran)e.Row;
			ARTran oldRow = (ARTran)e.OldRow;

			if (row != null)
			{
				if (!sender.ObjectsEqual<ARTran.qty,
					ARTran.uOM>(e.OldRow, e.Row))
				{
					SetFlatUnitPrice(sender, row);
				}

                if (!sender.ObjectsEqual<ARTran.branchID>(e.Row, e.OldRow) || !sender.ObjectsEqual<ARTran.inventoryID>(e.Row, e.OldRow) ||
                    !sender.ObjectsEqual<ARTran.qty>(e.Row, e.OldRow) || !sender.ObjectsEqual<ARTran.curyUnitPrice>(e.Row, e.OldRow) ||
                    !sender.ObjectsEqual<ARTran.curyExtPrice>(e.Row, e.OldRow) || !sender.ObjectsEqual<ARTran.curyDiscAmt>(e.Row, e.OldRow) ||
                    !sender.ObjectsEqual<ARTran.discPct>(e.Row, e.OldRow) || !sender.ObjectsEqual<ARTran.manualDisc>(e.Row, e.OldRow) ||
                    !sender.ObjectsEqual<ARTran.discountID>(e.Row, e.OldRow))
                    RecalculateDiscounts(sender, row);

				TaxAttribute.Calculate<ARTran.taxCategoryID>(sender, e);

				//if any of the fields that was saved in avalara has changed mark doc as TaxInvalid.
				if (SODocument.Current != null && IsExternalTax == true &&
					!sender.ObjectsEqual<ARTran.accountID, ARTran.inventoryID, ARTran.tranDesc, ARTran.tranAmt, ARTran.tranDate, ARTran.taxCategoryID>(e.Row, e.OldRow))
				{
					if (SODocument.Current != null && SODocument.Current.IsTaxValid == true)
					{
					    SODocument.Current.IsTaxValid = false;
					    if (SODocument.Cache.GetStatus(SODocument.Current) == PXEntryStatus.Notchanged)
					        SODocument.Cache.SetStatus(SODocument.Current, PXEntryStatus.Updated);
					}

					if (Document.Current != null)
					{
					    Document.Current.IsTaxValid = false;
					    if (Document.Cache.GetStatus(Document.Current) == PXEntryStatus.Notchanged)
					        Document.Cache.SetStatus(Document.Current, PXEntryStatus.Updated);
					}
				}
			}
		}
		protected virtual void SOInvoice_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
		{
			if (!sender.ObjectsEqual<SOInvoice.curyDiscTot>(e.OldRow, e.Row))
			{
                AddDiscount(sender, e);
			}

			if (!sender.ObjectsEqual<SOInvoice.isCCCaptured>(e.Row, e.OldRow) && ((SOInvoice)e.Row).IsCCCaptured == true)
			{
				ARInvoice copy = (ARInvoice)Document.Cache.CreateCopy(Document.Current);

				copy.CreditHold = false;

				Document.Cache.Update(copy);
			}

			if (!sender.ObjectsEqual<SOInvoice.curyPaymentTotal>(e.OldRow, e.Row))
			{
				ARInvoice ardoc = Document.Search<ARInvoice.refNbr>(((SOInvoice)e.Row).RefNbr, ((SOInvoice)e.Row).DocType);
				//is null on delete operation
				if (ardoc != null)
				{
					((SOInvoice)e.Row).CuryPaymentAmt = ardoc.CuryOrigDocAmt - ardoc.CuryOrigDiscAmt - ((SOInvoice)e.Row).CuryPaymentTotal;
				}
			}

			if (!sender.ObjectsEqual<SOInvoice.pMInstanceID, SOInvoice.paymentMethodID, SOInvoice.cashAccountID>(e.Row, e.OldRow))
			{ 
				ARInvoice ardoc = Document.Search<ARInvoice.refNbr>(((SOInvoice)e.Row).RefNbr, ((SOInvoice)e.Row).DocType);
				//is null on delete operation
				if (ardoc != null)
				{
					ardoc.PMInstanceID = ((SOInvoice)e.Row).PMInstanceID;
					ardoc.PaymentMethodID = ((SOInvoice)e.Row).PaymentMethodID;
					ardoc.CashAccountID = ((SOInvoice)e.Row).CashAccountID;
					
					if (Document.Cache.GetStatus(ardoc) == PXEntryStatus.Notchanged)
					{
						Document.Cache.SetStatus(ardoc, PXEntryStatus.Updated);
					}
				}
			}
		}