Skip to main content
Question

How would I override this static method on INLotSerialNbrAttribute class ?

  • January 14, 2025
  • 2 replies
  • 85 views

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();
}
}

 

2 replies

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

I’ve puzzled over this for a while and I’m afraid you’re right on all counts.


Chris Hackett
Community Manager
Forum|alt.badge.img
  • Acumatica Community Manager
  • April 24, 2025

Hi ​@mauritzv were you able to find a solution? Thank you!