I need to add a new segment type to Lot/Serial classes but running into an issue because of a static method.
In class INLotSerClassMaint, the persist method is overridden to do validation on the segments.
Here is the method from standard Acumatica.
public override void Persist()
{
foreach (INLotSerClass lsclass in lotserclass.Cache.Inserted)
{
lsclass.LotSerFormatStr = INLotSerialNbrAttribute.MakeFormatStr(lotserclass.Cache, lsclass);
if (lsclass.LotSerTrack != INLotSerTrack.NotNumbered && lsclass.AutoNextNbr == true)
{
int NumbericCount = 0;
foreach (INLotSerSegment lssegment in lotsersegments.View.SelectMultiBound(new object[] { lsclass }))
{
if (lssegment.SegmentType == INLotSerSegmentType.NumericVal)
{
NumbericCount++;
}
}
if (NumbericCount == 0)
{
throw new PXException(Messages.NumericLotSerSegmentNotExists, Messages.NumericVal);
}
else if (NumbericCount > 1)
{
throw new PXException(Messages.NumericLotSerSegmentMultiple, Messages.NumericVal);
}
}
}
foreach (INLotSerClass lsclass in lotserclass.Cache.Updated)
{
lsclass.LotSerFormatStr = INLotSerialNbrAttribute.MakeFormatStr(lotserclass.Cache, lsclass);
if (lsclass.LotSerTrack != INLotSerTrack.NotNumbered && lsclass.AutoNextNbr == true)
{
int NumbericCount = 0;
foreach (INLotSerSegment lssegment in lotsersegments.View.SelectMultiBound(new object[] { lsclass }))
{
if (lssegment.SegmentType == INLotSerSegmentType.NumericVal)
{
NumbericCount++;
}
}
if (NumbericCount == 0)
{
throw new PXException(Messages.NumericLotSerSegmentNotExists, Messages.NumericVal);
}
else if (NumbericCount > 1)
{
throw new PXException(Messages.NumericLotSerSegmentMultiple, Messages.NumericVal);
}
}
}
base.Persist();
}As you can see, its calling INLotSerialNbrAttribute.MakeFormatStr which is a static method.
This static method is checking each segment type and if the segment type is not found, its throwing an exception.
Here is the method:
public static string MakeFormatStr(PXCache sender, INLotSerClass lsclass)
{
StringBuilder format = new StringBuilder();
if (lsclass != null)
{
foreach (INLotSerSegment seg in PXSelect<INLotSerSegment,
Where<INLotSerSegment.lotSerClassID, Equal<Required<INLotSerSegment.lotSerClassID>>>,
OrderBy<Asc<INLotSerSegment.lotSerClassID, Asc<INLotSerSegment.segmentID>>>>.Select(sender.Graph, lsclass.LotSerClassID))
{
switch (seg.SegmentType)
{
case INLotSerSegmentType.FixedConst:
format.Append(seg.SegmentValue);
break;
case INLotSerSegmentType.NumericVal:
format.Append("{1}");
break;
case INLotSerSegmentType.DateConst:
format.Append("{0");
if (!string.IsNullOrEmpty(seg.SegmentValue))
format.Append(":").Append(seg.SegmentValue);
format.Append("}");
break;
case INLotSerSegmentType.DayConst:
format.Append("{0:dd}");
break;
case INLotSerSegmentType.MonthConst:
format.Append("{0:MM}");
break;
case INLotSerSegmentType.MonthLongConst:
format.Append("{0:MMM}");
break;
case INLotSerSegmentType.YearConst:
format.Append("{0:yy}");
break;
case INLotSerSegmentType.YearLongConst:
format.Append("{0:yyyy}");
break;
default:
throw new PXException();
}
}
}
return format.ToString();
}
Now for my code:
Here is what I have done to add a new segment type:
public class CUSTOMINLotSerSegmentType
{
public class ListAttribute : PXStringListAttribute
{
public ListAttribute() : base(
new[]
{
Pair(NumericVal, Messages.NumericVal),
Pair(FixedConst, Messages.FixedConst),
Pair(DayConst, Messages.DayConst),
Pair(MonthConst, Messages.MonthConst),
Pair(MonthLongConst, Messages.MonthLongConst),
Pair(YearConst, Messages.YearConst),
Pair(YearLongConst, Messages.YearLongConst),
Pair(DateConst, Messages.DateConst),
Pair(CustomSegment , "Custom"), // my custom segment type
}) {}
}
public const string NumericVal = "N";
public const string FixedConst = "C";
public const string DateConst = "D";
public const string DayConst = "U";
public const string MonthConst = "M";
public const string MonthLongConst = "A";
public const string YearConst = "Y";
public const string YearLongConst = "L";
public const string CustomSegment = "Z"; // my custom segment type
}
[PXNonInstantiatedExtension]
public class CustomINLotSerSegment : PXCacheExtension<PX.Objects.IN.INLotSerSegment>
{
#region SegmentType
[PXDBString(1, IsFixed = true)]
[PXDefault(INLotSerSegmentType.FixedConst)]
[CUSTOMINLotSerSegmentType.List()]
[PXUIField(DisplayName="Type")]
public string SegmentType { get; set; }
#endregion
}This works ok and I can see my custom segment type.

The problem I am running into is I cannot save the record because INLotSerClassMaint has Persist overridden and is calling this static method which doesn’t handle my custom segment type.
I can override the persist method in a graph extension and just not call the base method, however, the Persist method in INLotSerClassMaint also calls base.Persist so if I override Persist in my graph extension, base.Persist won’t be called, thus not persisting anything.
What is the best approach to solve this? I am thinking that I will have to create a new custom graph to create Lot/Serial classes because of the static method that I cannot override.
I have tried inheriting from INLotSerialNbrAttribute and then using public static new string MakeFormatStr but to use this I will need to change the Persist to use my class instead of INLotSerialNbrAttribute, which I can’t seem to do.
public class CUSTOMLotSerialNbrAttribute : INLotSerialNbrAttribute
{
public CUSTOMLotSerialNbrAttribute(Type InventoryType, Type SubItemType, Type LocationType, Type ParentLotSerialNbrType, Type CostCenterType)
: base(InventoryType, SubItemType, LocationType, ParentLotSerialNbrType, CostCenterType)
{
}
public CUSTOMLotSerialNbrAttribute(Type InventoryType, Type SubItemType, Type LocationType, Type CostCenterType)
: base(InventoryType, SubItemType, LocationType, CostCenterType)
{
}
protected CUSTOMLotSerialNbrAttribute()
{
}
public static new string MakeFormatStr(PXCache sender, INLotSerClass lsclass)
{
StringBuilder format = new StringBuilder();
if (lsclass != null)
{
foreach (INLotSerSegment seg in PXSelect<INLotSerSegment,
Where<INLotSerSegment.lotSerClassID, Equal<Required<INLotSerSegment.lotSerClassID>>>,
OrderBy<Asc<INLotSerSegment.lotSerClassID, Asc<INLotSerSegment.segmentID>>>>.Select(sender.Graph, lsclass.LotSerClassID))
{
switch (seg.SegmentType)
{
case CUSTOMINLotSerSegmentType.FixedConst:
format.Append(seg.SegmentValue);
break;
case CUSTOMINLotSerSegmentType.NumericVal:
format.Append("{1}");
break;
case CUSTOMINLotSerSegmentType.DateConst:
format.Append("{0");
if (!string.IsNullOrEmpty(seg.SegmentValue))
format.Append(":").Append(seg.SegmentValue);
format.Append("}");
break;
case CUSTOMINLotSerSegmentType.DayConst:
format.Append("{0:dd}");
break;
case CUSTOMINLotSerSegmentType.MonthConst:
format.Append("{0:MM}");
break;
case CUSTOMINLotSerSegmentType.MonthLongConst:
format.Append("{0:MMM}");
break;
case INLotSerSegmentType.YearConst:
format.Append("{0:yy}");
break;
case CUSTOMINLotSerSegmentType.YearLongConst:
format.Append("{0:yyyy}");
break;
case CUSTOMINLotSerSegmentType.CustomSegment:
format.Append("{0:YYdddhh}");
break;
default:
throw new PXException();
}
}
}
return format.ToString();
}
}