Reputation: 559
I have to show the price in a mask based on the alphabets setup in the configuration screen.
I am trying to write a custom attribute for the DAC field so that I can use the same in reports.
I have given the existing piece of code below. The function calls are working fine and i am using it for getting value, but I am not able to use it as DAC Attribute
#region PXPriceMaskAttribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Class)]
public class PXPriceMaskAttribute : PXStringAttribute
{
#region Ctor
public PXPriceMaskAttribute()
: base()
{
}
#endregion
#region Implementation
/// <exclude/>
///
public static string GetPriceMask(PXGraph grp , decimal? val)
{
string _maskedstring = string.Empty;
decimal value = val ?? 0m;
int ivalue = Convert.ToInt32(Math.Floor(value));
if (ivalue > 0)
{
MemoSetUp setUp = PXSelect<MemoSetUp>.Select(grp);
char[] arr = ivalue.ToString().ToCharArray();
char prevvalue = ' ';
foreach (char cval in arr)
{
if (prevvalue != cval)
{
prevvalue = cval;
switch (cval)
{
case '1': _maskedstring += setUp.N1; break;
case '2': _maskedstring += setUp.N2; break;
case '3': _maskedstring += setUp.N3; break;
case '4': _maskedstring += setUp.N4; break;
case '5': _maskedstring += setUp.N5; break;
case '6': _maskedstring += setUp.N6; break;
case '7': _maskedstring += setUp.N7; break;
case '8': _maskedstring += setUp.N8; break;
case '9': _maskedstring += setUp.N9; break;
case '0': _maskedstring += setUp.N0; break;
default: break;
}
}
else
{
_maskedstring += setUp.Repeate;
}
}
}
return _maskedstring;
}
public static string GetPriceMask(MemoSetUp setUp, decimal? val)
{
string _maskedstring = string.Empty;
decimal value = val ?? 0m;
int ivalue = Convert.ToInt32(Math.Floor(value));
if (ivalue > 0)
{
char[] arr = ivalue.ToString().ToCharArray();
char prevvalue = ' ';
foreach (char cval in arr)
{
if (prevvalue != cval)
{
prevvalue = cval;
switch (cval)
{
case '1': _maskedstring += setUp.N1; break;
case '2': _maskedstring += setUp.N2; break;
case '3': _maskedstring += setUp.N3; break;
case '4': _maskedstring += setUp.N4; break;
case '5': _maskedstring += setUp.N5; break;
case '6': _maskedstring += setUp.N6; break;
case '7': _maskedstring += setUp.N7; break;
case '8': _maskedstring += setUp.N8; break;
case '9': _maskedstring += setUp.N9; break;
case '0': _maskedstring += setUp.N0; break;
default: break;
}
}
else
{
_maskedstring += setUp.Repeate;
}
}
}
return _maskedstring;
}
public override void FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
if (e.NewValue != null && !e.Cancel)
{
decimal? value = Convert.ToDecimal(e.NewValue);
e.NewValue = GetPriceMask(sender.Graph, value);
}
}
/// <exclude/>
public override void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
if (_AttributeLevel == PXAttributeLevel.Item || e.IsAltered)
{
e.ReturnState = PXStringState.CreateInstance(e.ReturnState, _Length, _IsUnicode, _FieldName, _IsKey, null, _InputMask, null, null, null, null);
}
}
/// <exclude/>
#endregion
}
#endregion
The above piece of code is not working. What is the best way to fix the issue.
Update
I have created a BQL Evaluator and attached to DAC and it always returns zero.
public class PriceRounding<PriceField> : BqlFormulaEvaluator<PriceField>, IBqlOperand
where PriceField : IBqlField
{
public override object Evaluate(PXCache cache, object item,
Dictionary<Type, object> pars)
{
PXFieldState fState = cache.GetStateExt<PriceField>(item) as PXFieldState;
return GetSortOrderValueExt(Convert.ToDecimal(fState.Value));
}
public decimal GetSortOrderValueExt(decimal dVal)
{
dVal = Math.Round(dVal, 0);
decimal divider = (dVal <= 5000) ? 25m : (dVal <= 10000) ? 50m : (dVal <= 100000) ? 100m : 500m;
decimal reminder = dVal % divider;
if (reminder > 0)
{
decimal diff = divider - reminder;
dVal = dVal + diff;
}
return dVal;
}
}
The DAC field
#region RetailPrice
public abstract class retailPrice : PX.Data.IBqlField
{
}
protected decimal? _RetailPrice;
[PXDBDecimal(2)]
[PXUIField(DisplayName = "Retail Price")]
[PXFormula(typeof(PriceRounding<InfoInventoryItemAttributeExtNV.retailPrice>))]
public virtual decimal? RetailPrice
{
get
{
return this._RetailPrice;
}
set
{
this._RetailPrice = value;
}
}
#endregion
Upvotes: 0
Views: 708
Reputation: 559
The following code works fine for me for custom rounding off than using BQL Formula Evaluator
#region PXDBPriceRoundingAttribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Class)]
public class PXDBPriceRoundingAttribute : PXDBDecimalAttribute
{
#region Implementation
public static decimal Round(decimal value)
{
value = Math.Round(value, 0);
decimal divider = (value <= 5000) ? 25m : (value <= 10000) ? 50m : (value <= 100000) ? 100m : 500m;
decimal reminder = value % divider;
if (reminder > 0)
{
decimal diff = divider - reminder;
value = value + diff;
}
return value;
}
public override void RowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
base.RowSelecting(sender, e);
string name = _FieldName;
if (sender.GetValue(e.Row, _FieldOrdinal) == null)
{
sender.SetValue(e.Row, _FieldOrdinal, 0m);
}
else
{
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value ?? 0m);
if ((value ?? 0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
}
public override void FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
base.FieldUpdating(sender, e);
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value??0m);
if((value??0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
public void FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value ?? 0m);
if ((value ?? 0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
base.RowPersisting(sender, e);
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value ?? 0m);
if ((value ?? 0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
#endregion
#region Initialization
public override void CacheAttached(PXCache sender)
{
base.CacheAttached(sender);
_Precision = CommonSetupDecPl.PrcCst;
}
#endregion
}
#endregion
Using In DAC
#region WholeSalesPrice
public abstract class wholeSalesPrice : PX.Data.IBqlField
{
}
protected decimal? _WholeSalesPrice;
[PXDBPriceRoundingAttribute()]
[PXUIField(DisplayName = "Wholesale Price")]
public virtual decimal? WholeSalesPrice
{
get
{
return this._WholeSalesPrice;
}
set
{
this._WholeSalesPrice = value;
}
}
#endregion
Upvotes: 0
Reputation: 2340
Consider using custom BQL Function (derived from BqlFormulaEvaluator
) – You can refer out-of-box custom BQL functions available in formula sub-folder of PX.Objects
source code. Or you can refer KB article where such custom BQL function HierarchySorting
is used.
Upvotes: 1