Skip to main content
Solved

User Field Value not displaying


Hello,

I am trying to add a user field (decimal) called UsrSalesCommPct 

  public class AMEstimateItemExt : PXCacheExtension<PX.Objects.AM.AMEstimateItem>
  {
        public static bool IsActive() => true;

        #region UsrSalesCommPct 
        [PXDBDecimal]
        [PXUIField(DisplayName = "Sales Commission (%)", Required = true)]
        public virtual decimal? UsrSalesCommPct { get; set; }
        public abstract class usrSalesCommPct : PX.Data.BQL.BqlDecimal.Field<usrSalesCommPct> { }
        #endregion

        #region UsrContingencyPct
        [PXDBDecimal]
        [PXUIField(DisplayName = "Contingency (%)", Required = true)]
        public virtual decimal? UsrContingencyPct { get; set; }
        public abstract class usrContingencyPct : PX.Data.BQL.BqlDecimal.Field<usrContingencyPct> { }
        #endregion

        #region UsrMargin
        [PXDBDecimal]
        [PXUIField(DisplayName = "Margin")]
        public virtual decimal? UsrMargin { get; set; }
        public abstract class usrMargin : PX.Data.BQL.BqlDecimal.Field<usrMargin> { }
        #endregion

        #region UsrMarginPct
        [PXDBDecimal]
        [PXUIField(DisplayName = "Margin (%)")]
        public virtual decimal? UsrMarginPct { get; set; }
        public abstract class usrMarginPct : PX.Data.BQL.BqlDecimal.Field<usrMarginPct> { }
        #endregion

        #region UsrTotalCost
        [PXDecimal]
        [PXUIField(DisplayName = "Total Cost")]
        public virtual decimal? UsrTotalCost { get; set; }
        public abstract class usrTotalCost : PX.Data.BQL.BqlDecimal.Field<usrTotalCost> { }
        #endregion
    }
}

The field is properly saved in the database but as soon as I save the field value disappears, this is the code I have in the Graph 

    public class EstimateMaint_Extension : PXGraphExtension<PX.Objects.AM.EstimateMaint>
    {

        public PXSelect<AMEstimateItem,
          Where<AMEstimateItem.estimateID, Equal<Required<AMEstimateItem.estimateID>>>> EstimateItemsByEstimateID;

        private const string VALIDATION_UsrSalesCommPct = "The Sales Commission Percentage is required.";
        private const string VALIDATION_UsrContingencyPct = "The Contingency Percentage is required.";

        public static bool IsActive() => true;

        #region Event Handlers

        /*
        protected void AMEstimateItem_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
        {

            var row = (AMEstimateItem)e.Row;
            if (row == null) return;

            AMEstimateItemExt rowExt = PXCache<AMEstimateItem>.GetExtension<AMEstimateItemExt>(row);
            if (rowExt == null) return;

            if (rowExt.UsrSalesCommPct == 0) cache.RaiseExceptionHandling<AMEstimateItemExt.usrSalesCommPct>(row, null, new PXSetPropertyException(VALIDATION_UsrSalesCommPct));
            if (rowExt.UsrContingencyPct == 0) cache.RaiseExceptionHandling<AMEstimateItemExt.usrContingencyPct>(row, null, new PXSetPropertyException(VALIDATION_UsrContingencyPct));
            //SetTotal(row);
        }
        */

        protected void AMEstimateItem_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {

            var row = (AMEstimateItem)e.Row;
            if (row == null) return;

            AMEstimateItemExt rowExt = PXCache<AMEstimateItem>.GetExtension<AMEstimateItemExt>(row);
            if (rowExt == null) return;

            rowExt.UsrMargin = row.CuryExtPrice - row.CuryExtCost;
            rowExt.UsrMarginPct = (row.CuryExtPrice == 0) ? 0 : ((row.CuryExtPrice - row.CuryExtCost) / row.CuryExtPrice) * 100;

            var result = EstimateItemsByEstimateID.Select(row.EstimateID);

            if (result != null)
            {
                var item = result.FirstOrDefault()?.GetItem<AMEstimateItem>();
                if (item != null)
                {
                    rowExt.UsrSalesCommPct = item.GetExtension<AMEstimateItemExt>()?.UsrSalesCommPct;
                    rowExt.UsrContingencyPct = item.GetExtension<AMEstimateItemExt>()?.UsrContingencyPct;
                }
            }

            SetTotal(row );
        }

        protected void AMEstimateItem_UsrSalesCommPct_FieldVerifying(PXCache cache, PXFieldVerifyingEventArgs e)
        {
            if (e.Row == null) return;
            var row = (AMEstimateItem)e.Row;

            decimal? newValue = (decimal?)e.NewValue;
            if (newValue == 0) throw new PXSetPropertyException(VALIDATION_UsrSalesCommPct);
        }

        protected void AMEstimateItem_UsrContingencyPct_FieldVerifying(PXCache cache, PXFieldVerifyingEventArgs e)
        {
            if (e.Row == null) return;
            var row = (AMEstimateItem)e.Row;

            decimal? newValue = (decimal?)e.NewValue;
            if (newValue == 0) throw new PXSetPropertyException(VALIDATION_UsrContingencyPct);
        }

        protected void AMEstimateItem_UsrContingencyPct_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);
        protected void AMEstimateItem_UsrSalesCommPct_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);
        protected void AMEstimateItem_FixedLaborCost_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);
        protected void AMEstimateItem_VariableLaborCost_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);
        protected void AMEstimateItem_MachineCost_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);
        protected void AMEstimateItem_MaterialCost_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);
        protected void AMEstimateItem_ToolCost_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);
        protected void AMEstimateItem_FixedOverheadCost_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);
        protected void AMEstimateItem_VariableOverheadCost_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);
        protected void AMEstimateItem_SubcontractCost_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) => SetTotal((AMEstimateItem)e.Row);

        #endregion

        private void SetTotal(AMEstimateItem row)
        {
            if (row == null) return;
            AMEstimateItemExt rowExt = PXCache<AMEstimateItem>.GetExtension<AMEstimateItemExt>(row);
            if (rowExt == null) return;
            rowExt.UsrTotalCost = CalculateTotalCost(row.FixedLaborCost, row.VariableLaborCost, row.MachineCost, row.MaterialCost, row.ToolCost, row.FixedOverheadCost, row.VariableOverheadCost, row.SubcontractCost, rowExt.UsrSalesCommPct, rowExt.UsrContingencyPct);
        }

        private decimal CalculateTotalCost(decimal? laborCostFixed, decimal? laborCostVar, decimal? machineCost, decimal? materialCost, decimal? toolCost, decimal? overheadCostFixed, decimal? overheadCostVar, decimal? subcontractCost, decimal? salesCommPct, decimal? contingencyPct)
        {
            var totalCost = (laborCostFixed ?? 0m) + (laborCostVar ?? 0m) + (machineCost ?? 0m) + (materialCost ?? 0m) + (toolCost ?? 0m) + (overheadCostFixed ?? 0m) + (overheadCostVar ?? 0m) + (subcontractCost ?? 0m);

            var salesCommission = ((salesCommPct ?? 0m) * (materialCost ?? 0m)) / 100;
            totalCost += salesCommission;

            var contingency = (totalCost * (contingencyPct ?? 0m)) / 100;
            totalCost += contingency;

            return totalCost;
        }

    }

I tried to disable everything under the RowSelected but I still do not see the value after the record is saved.

 

Thank you in Advanced

 

 

Best answer by darylbowman

AMEstimateItem is a projection:

You will need to create a cache extension on PX.Objects.AM.Standalone.AMEstimateItem as well. Then change your current field definition to [PXDBDecimal(BqlField = typeof(PX.Objects.AM.Standalone.AMEstimateItemExt.usrSalesCommPct)] (with respect to whatever that cache extension / field name is).

View original
Did this topic help you find an answer to your question?

3 replies

darylbowman
Captain II
Forum|alt.badge.img+13
  • 1690 replies
  • Answer
  • March 17, 2025

AMEstimateItem is a projection:

You will need to create a cache extension on PX.Objects.AM.Standalone.AMEstimateItem as well. Then change your current field definition to [PXDBDecimal(BqlField = typeof(PX.Objects.AM.Standalone.AMEstimateItemExt.usrSalesCommPct)] (with respect to whatever that cache extension / field name is).


  • Author
  • Freshman I
  • 1 reply
  • March 17, 2025

Thank you, that worked, I will add the new code below in case someone else will get stuck on the same issue as me. I am not sure what a projection is, do you have a link I can do some study in regards? 

namespace PX.Objects.AM.Standalone
{
  public class StandaloneAMEstimateItemExt : PXCacheExtension<PX.Objects.AM.Standalone.AMEstimateItem>
  {
        public static bool IsActive() => true;

        #region UsrSalesCommPct 
        [PXDBDecimal]
        [PXUIField(DisplayName = "Sales Commission (%)", Required = true)]
        public virtual decimal? UsrSalesCommPct { get; set; }
        public abstract class usrSalesCommPct : PX.Data.BQL.BqlDecimal.Field<usrSalesCommPct> { }
        #endregion

        #region UsrContingencyPct
        [PXDBDecimal]
        [PXUIField(DisplayName = "Contingency (%)", Required = true)]
        public virtual decimal? UsrContingencyPct { get; set; }
        public abstract class usrContingencyPct : PX.Data.BQL.BqlDecimal.Field<usrContingencyPct> { }
        #endregion

        #region UsrMargin
        [PXDBDecimal]
        [PXUIField(DisplayName = "Margin")]
        public virtual decimal? UsrMargin { get; set; }
        public abstract class usrMargin : PX.Data.BQL.BqlDecimal.Field<usrMargin> { }
        #endregion

        #region UsrMarginPct
        [PXDBDecimal]
        [PXUIField(DisplayName = "Margin (%)")]
        public virtual decimal? UsrMarginPct { get; set; }
        public abstract class usrMarginPct : PX.Data.BQL.BqlDecimal.Field<usrMarginPct> { }
        #endregion

    }
}

namespace PX.Objects.AM
{
    public class AMEstimateItemExt : PXCacheExtension<PX.Objects.AM.AMEstimateItem>
    {
        public static bool IsActive() => true;

        #region UsrSalesCommPct 
        [PXDBDecimal(BqlField = typeof(PX.Objects.AM.Standalone.StandaloneAMEstimateItemExt.usrSalesCommPct))]
        [PXUIField(DisplayName = "Sales Commission (%)", Required = true)]
        public virtual decimal? UsrSalesCommPct { get; set; }
        public abstract class usrSalesCommPct : PX.Data.BQL.BqlDecimal.Field<usrSalesCommPct> { }
        #endregion

        #region UsrContingencyPct
        [PXDBDecimal(BqlField = typeof(PX.Objects.AM.Standalone.StandaloneAMEstimateItemExt.usrContingencyPct))]
        [PXUIField(DisplayName = "Contingency (%)", Required = true)]
        public virtual decimal? UsrContingencyPct { get; set; }
        public abstract class usrContingencyPct : PX.Data.BQL.BqlDecimal.Field<usrContingencyPct> { }
        #endregion

        #region UsrMargin
        [PXDBDecimal(BqlField = typeof(PX.Objects.AM.Standalone.StandaloneAMEstimateItemExt.usrMargin))]
        [PXUIField(DisplayName = "Margin")]
        public virtual decimal? UsrMargin { get; set; }
        public abstract class usrMargin : PX.Data.BQL.BqlDecimal.Field<usrMargin> { }
        #endregion

        #region UsrMarginPct
        [PXDBDecimal(BqlField = typeof(PX.Objects.AM.Standalone.StandaloneAMEstimateItemExt.usrMarginPct))]
        [PXUIField(DisplayName = "Margin (%)")]
        public virtual decimal? UsrMarginPct { get; set; }
        public abstract class usrMarginPct : PX.Data.BQL.BqlDecimal.Field<usrMarginPct> { }
        #endregion

        #region UsrTotalCost
        [PXDecimal]
        [PXUIField(DisplayName = "Total Cost")]
        public virtual decimal? UsrTotalCost { get; set; }
        public abstract class usrTotalCost : PX.Data.BQL.BqlDecimal.Field<usrTotalCost> { }
        #endregion
    }
}

 


darylbowman
Captain II
Forum|alt.badge.img+13

Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings