The following functions were added to PartProxy
in v16.5.
These functions were added in support of the new pricing model which is documented in the compile-time section for cm.core.part.Part
.
New: extend public double basePrice(Part part, bool includeChildren=false, Space space=null, bool translatePrice=true) {} New: extend public double optionPriceSum(Part part, bool includeChildren=false, Space space=null, bool translatePrice=true, bool invalidate=false) {}
In v16.5, a new constructor has been introduced for Part to support the new pricing model.
Previously, Part accepted a cached list price (listPrice
) directly as a parameter. This behavior is now being phased out.
constructor(Snapper snapper, str articleCode, str description, double listPrice, ...)
listPrice
.data._useNewPricing = false
to use old pricing behavior.constructor(Snapper snapper, str articleCode, str description, double basePrice, Double optionPriceSum, ...)
basePrice
and optionPriceSum
separately.data._useNewPricing = true
to activate new pricing behavior.Double optionPriceSum
Parameter
generateOptionPriceSum()
documentationinvalidateOptionPriceSum
basePrice
and optionPriceSum
.Old: new Part(snapper, "PART NUM", "PART DESC", listPrice=199.99); New: new Part(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=49.99); New: new Part(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=null);
The following functions are now part of the old pricing system. The new pricing API is introduced in v16.5 and documented in the next section. The old API will remain for backwards compatibility but is expected to be removed in a future version of CET.
extend public double customListPrice() extend public Double upcharge()
Old:
PartProxy
list price valuePartData
cached list price valueNew:
customListPrice()
listPrice()
and calculatedListPrice(..)
documentation for more migration informationOld:
upcharge()
returns null.New:
optionPriceSum()
.useNewPricing()
== false.upcharge()
optionPriceSum(..)
and calculatedListPrice(..)
documentation for more migration informationThe following functions were introduced as part of the new pricing system. They replace Old pricing methods that relied on a cached list price.
Added: final public bool useNewPricing() {} Added: extend public double basePrice(bool includeChildren=false, Space space=null, bool translatePrice=true) {} Added: extend public double optionPriceSum(bool includeChildren=false, Space space=null, bool translatePrice=true, bool invalidate=false) {} Added: final public double calculatedListPrice(bool includeChildren=false, Space space=null) {} Added: extend public Double generateOptionPriceSum() {} Added: extend public void invalidateOptionPriceSum() {}
Indicates whether the new part pricing system should be used on the Part instance. An opt-in feature flag to the new pricing system.
PartData
listPrice
, upcharge
, basePrice
, optionPriceSum
, etc.bool includeChildren
(optional)
Space space
(optional)
translatePrice
bool translatePrice
(optional)
space
Old:
basePrice()
is implemented in cm.abstract.part.AbsPart
DsPart
to return catalog base priceNew:
basePrice()
is implemented in cm.core.part.Part
PartSpecial
is foundPartProxy
base price valuePartData
cached base pricebasePrice
for the PartlistPrice
with basePrice
where you need only the product’s inherent costbool includeChildren
(optional)
Space space
(optional)
translatePrice
bool translatePrice
(optional)
space
bool invalidate
(optional)
Old:
upcharge()
is implemented in cm.abstract.part.AbsPart
PartProxy
New:
optionPriceSum()
is implemented in cm.core.part.Part
useNewPricing
is false, returns upcharge()
PartProxy
option price sum valuePartData
cached option price sum
invalidate=true
), value is regenerated automatically with generateOptionPriceSum()
upcharge()
with optionPriceSum()
invalidateOptionPriceSum()
before recalculation.bool includeChildren
(optional)
Space space
(optional)
translatePrice
bool translatePrice
(optional)
space
bool invalidateOptionPriceSum
(optional)
Old:
customListPrice(..)
is primary source of list price value
PartProxy
list price valuePartData
cached list price valuelistPrice()
when useNewPricing == false
New:
calculatedListPrice(..)
is primary source of list price in new pricing model
basePrice(..) + optionPriceSum(..)
)listPrice()
when useNewPricing == true
customListPrice(..)
to customize list price, migrate this logic into:
basePrice(..)
(for foundational Part price)optionPriceSum(..)
/generateOptionPriceSum()
(for option pricing logic).listPrice()
will automatically call calculatedListPrice(..)
if useNewPricing
is enabled.Old:
New:
ProdPart
and DsPart
generateOptionPriceSum()
in your extended Part class.invalidateOptionPriceSum()
) when option state changes to trigger regeneration.Old:
New:
optionPriceSum
value to trigger regenerationinvalidateOptionPriceSum()
whenever Part configuration changes (options, children, etc.)invalidateOptionPriceSum()
after any Part modifications that may affect option pricing.The following functions were added or changed in Part
in v16.5. The new pricing model API is documented above and not included in this section.
translatePrice
functions were modified to remove unused includeChildren
parameter.
Added: extend public double totalBasePrice(bool includeChildren=false, Space space=null) {} Added: extend public double totalOptionPriceSum(bool includeChildren=false, Space space=null) {} Old: final public double translatePrice(double price, bool includeChildren=false, Space space=null) { New: final public double translatePrice(double price, Space space=null) { Old: final public double translatePrice(double price, currencyId currency, bool includeChildren=false, Space space=null) { New: final public double translatePrice(double price, currencyId currency, Space space=null) {
As of 16.5, a new interface for lead time has been added to core Part
. It's value is displayed in the new LeadTimeColumn
implemented in cm/core/init/leadTimeColumn.cm
.
In cm/core/part/part.cm /** * Get lead time string. * Ex. 20 days, 3 weeks, etc. */ extend public str leadTime() { return ""; }
In v16.5, a new constructor has been introduced for WorldPart to support the new pricing model.
Previously, WorldPart accepted a cached list price (listPrice
) directly as a parameter. This behavior is now being phased out.
constructor(World world, str articleCode, str description, double listPrice, ...)
listPrice
value to cache.cm.core.part.Part
for more infoconstructor(World world, str articleCode, str description, double basePrice, Double optionPriceSum, ...)
basePrice
and optionPriceSum
separately for caching.cm.core.part.Part
for more infobasePrice
and optionPriceSum
.Old: new WorldPart(snapper, "PART NUM", "PART DESC", listPrice=199.99); New: new WorldPart(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=49.99); New: new WorldPart(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=null);
put
remove
removeAll
See cm.core.part.attributes
section in 16.5 New Features migration guide for new PartAnnotationHolder
class documentation.
The following functions were added to PartData
in v16.5.
These functions were added in support of the new pricing model which is documented in the compile-time section for cm.core.part.Part
.
// FUNCTIONS New: extend public bool useNewPricing() {} New: extend public double basePrice() : abstract {} New: extend public void setBasePrice(double v) : abstract {} New: extend public Double optionPriceSum() : abstract {} New: extend public void setOptionPriceSum(Double v) : abstract {}
See cm.core.part.attributes
section in 16.5 New Features migration guide for new PartAnnotation
class documentation.
In v16.5, a new constructor has been introduced for BasicPartData to support the new pricing model.
Previously, BasicPartData accepted a cached list price (listPrice
) directly as a parameter. This behavior is now being phased out.
constructor(Snapper snapper, str articleCode, str description, double inPrice=0, double outPrice=0, ...)
outPrice
(list price) value to cache._useNewPricing
as false to use old pricing behavior.constructor(Snapper snapper, str articleCode, str description, double basePrice=0, Double optionPriceSum=null, ...)
basePrice
and optionPriceSum
separately for caching._useNewPricing
as true to activate new pricing behavior._outPrice
field to (basePrice
+ optionPriceSum
)
Double optionPriceSum
Parameter
cm.core.part.Part
for documentationbasePrice
and optionPriceSum
.Old: new BasicPartData(snapper, "PART NUM", "PART DESC", outPrice=199.99); New: new BasicPartData(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=49.99); New: new BasicPartData(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=null);
The following functions and fields were added to BasicPartData
in v16.5.
These functions were added in support of the new pricing model which is documented in the compile-time section for cm.core.part.Part
.
// FIELDS New: package bool _useNewPricing; New: public double _basePrice; New: public Double _optionPriceSum; // OVERRIDDEN FUNCTIONS (from PartData) New: public bool useNewPricing() {} New: public double basePrice() {} New: public void setBasePrice(double v) {} New: public Double optionPriceSum() {} New: public void setOptionPriceSum(Double v) {}
The following functions were added or modified in cm/core/part/parts.cm
in v16.5.
These functions were modified in support of the new pricing model which is documented in the compile-time section for cm.core.part.Part
.
Changed: private void propagatePrice(Part p) {} Added: private void propagatePriceNew(Part parent) {}
With the introduction of the new pricing system, the behavior of propagatePrice
in cm/core/part/parts.cm
has undergone changes.
Old:
listPrice
only.invisiblePricing() == true
:
totalListPrice()
was divided by the parent’s quantity and added to the parent’s list price.listPrice
was set to 0.NEW:
propagatePrice
now branches on the parent’s pricing model:
propagatePriceNew(..)
is calledIf the parent Part has useNewPricing()
set to true, the new propagation system is utilized on the parent and child Parts.
With the new pricing model, invisible pricing propagation is split into two: base price and option price sum.
Old:
propagatePrice(..)
and utilizes cached listPrice
only.NEW:
propagatePrice
now branches on the parent’s pricing model:
totalBasePrice
)totalOptionPriceSum
)translatePrice
flag which is set to false during aggregationPartSpecial
instance to anotherthis
to values from passed in special
str partNum
str descr
bool priceReplace
double amount
Old:
Old: public constructor(PartGridBuilderEnv env=null) { this.env = env; }
New:
New: public constructor(PartGridBuilderEnv env=null) { this.env = env ?? PartGridBuilderEnv(buildTotalsRow:true); }
GridWindow
with arbitrary data.populateColumns(grid, env)
populateRows(data, grid, env)
GridWindow
from different types of input collections.populateRow(obj, grid, env)
for each.env.buildTotalsRow == true
, appends a totals row after populating all others.The following functions were modified with the introduction of the new pricing system (documented in cm.core.part.Part
compile-time section).
Changed: final public double listPrice(bool includeChildren=false, Space space=null) {}
Old:
customListPrice(..)
New:
useNewPricing()
to determine pricing behavior
calculatedListPrice(..)
when useNewPricing
is truecustomListPrice(..)
when useNewPricing
is falsecm.core.part.Part
compile-time section for migration tipsRetrieval and modification of PartSpecial
s on Part
has been updated to account for flattened parts and to allow optional invalidation of world price.
Old:
PartSpecial
using the implicit specialsKey()
.New:
Old:
New:
containsSpecial
now considers both self and inherited/related owners instead of just one.Old: extend public void putSpecial(PartSpecial special, PropObj s=null) {} New: extend public void putSpecial(PartSpecial special, PropObj s=null, bool invalidateWorldPrice=true) {} New: extend public void putSpecial(str id, PartSpecial special, PropObj s=null, bool invalidateWorldPrice=true) {}
Old:
PartSpecial
in the current owner’s PartSpecialHolder
keyed by specialsKey()
New:
bool invalidateWorldPrice = true
PropObj s=null
parameter is not null → s.putSpecial(...)Old: extend public void removeSpecial(PropObj s=null) {} New: extend public void removeSpecial( PropObj s=null, bool invalidateWorldPrice=true) {} New: extend public void removeSpecial(str id, PropObj s=null, bool invalidateWorldPrice=true) {
Old:
specialsKey()
New:
specialsKey()
With the addition of the new part attribute description/notes system, Part
s now
need to be differentiable/split by their attribute values.
The following helper function to generate the flattenable key for attributes has been made. It is appended to the flattenable key in flattenableKey()
:
/** * Flattened annotation note/descs key. * @return str of flattenable key of PartAnnotation(s) */ extend public str annotationFlattenableKey() { StrBuf buf(); bool first = true; for (annotation in getAnnotations()) { if (first) first = false; else buf << ','; buf << annotation.key(); } return buf.retireToS(); }
With the addition of the new part attribute description/notes system, Part
s now
need to be differentiable/split by their attribute values.
The following change has been made in flattenableKey
to account for this:
/** * Flattenable key. */ extend public str flattenableKey() { StrBuf key; ... New: key << annotationFlattenableKey(); return key.any() ? key.retireToS() : articleCode(); }
With the addition of the new part attribute description and note columns in Calculations, the valueOf(..)
function
has been updated in Part
to provide values for these columns.
This is mainly useful for the Excel order export and exporting a single, comma-delimited, str
value for PartAttributeColumn
s.
/** * Normally returned from value method in 'column', this is a change to override it from part. */ extend public Object valueOf(PartColumn column) { if (column as PartAttributeColumn) { ?str[] colVals = column.value(this, null); if (!colVals) return null; StrBuf valuesBuf(); bool first = true; for (val in colVals) { if (first) first = false; else valuesBuf << ", "; valuesBuf << val; } return valuesBuf.retireToS(); } return null; }
With the addition of the new str articleCodeText
field on ItemTagInfo
, Part
now sets this
value during updateItemTags()
if it is not already set. This ensures that the field has a value and that the new Control Panel
setting for toggling article codes for Ind Tags is functional in most cases.
/** * Update the Item tags. */ extend public void updateItemTags() { ... if (owner and acceptItemTags()) { if (ItemTags tags = owner.itemTags()) { if (ItemTag tag = tags.get(itemTagKey())) { ... New: if (tag.info and !tag.info.articleCodeText) { New: tag.info.articleCodeText = articleCode(); New: invalidate = true; } ... return; } } ... } }
A new interface, partToOwnerKeys
, has been added to FlattenedPartData
.
These keys are str
values that are unique for each Part
within a single owner. Their purpose is to distinguish between multiple Part
s on the same Snapper
owner
that may share the same flattenableKey
but originate from different creators.
Consider a table Snapper
with four legs:
Part
for the tabletop and four Part
s for the legs.Part
.FlattenedPartData
contains an owners sequence pointing only to the table Snapper.In this scenario, the flattened part had no way to reference the four individual leg parts that were merged together—it only knew about the shared owner.
The partToOwnerKeys
interface resolves this gap by assigning unique keys for each contributing Part
.
This allows the flattened part to retain identifiers for the individual parts that generated it, ensuring traceability even after merging.
To accomplish this, FlattenedPartData
has a new field where the keys are stored (private str{} _partToOwnerKeys
), a new accessor function (final public str{} partToOwnerKeys()
), and a change in appendSimilar
to build the keys.
The appendSimilar
function's purpose is to append a new Part
to the flattened part info. It increases quantity, appends owners, and changes the level of the flattened part.
It now also appends the passed in Part part
s partToOwnerKey
into the _partToOwnerKeys
sequence.
In cm/core/part/flattenedPartData.cm New: private str{} _partToOwnerKeys; New: final public str{} partToOwnerKeys() {} Changed: /** * Append a similar part. */ final public void appendSimilar(Part part, double multiplier) { appendOwnersFrom(part.data); New: if (!_partToOwnerKeys) init _partToOwnerKeys(); New: _partToOwnerKeys << part.partToOwnerKey(); _quantity += part.quantity()*multiplier; level = min(level, part.level()); #if (!builtInReleaseMode) assert(_allowOtherParent == part.data.allowOtherParent); }
See cm.core.part.attributes
section in 16.5 New Features migration guide for new PartAnnotationHolder
class documentation.
Object data
: Data for row to get cell brush forint columnIdx
: Column index to get cell brush forwhiteBrush
by defaultObject data
: Data for row to get default cell for (can be null)int columnIdx
: Column index to get default cell for ColorNameGridCell("", bgColor=getCellBrush(..).color)
by defaultPart part
: Part for row to get cell for (can be null)int columnIdx
: Column index to get cell for Part
is null or column index is out of bounds, returns getDefaultCell(..)
getCellBrush(..)
Old:
GridCell
s New:
getPartRowCell
for each column and appending it to the returned GridCell
sequenceSee cm.core.part.attributes
section in 16.5 New Features migration guide for new PartAnnotation
class documentation.
bool invalidateWorldPrice=true
has been added to special functions
Old: public void removeSpecialHolder(PropObj s) {} New: public void removeSpecialHolder(PropObj s, bool invalidateWorldPrice=true) {} Old: public void putSpecial(PropObj s, str key, PartSpecial special) {} New: public void putSpecial(PropObj s, str key, PartSpecial special, bool invalidateWorldPrice=true) {} Old: public void removeSpecial(PropObj s, str key) {} New: public void removeSpecial(PropObj s, str key, bool invalidateWorldPrice=true) {} Old: public void removeAllSpecials(PropObj s) {} New: public void removeAllSpecials(PropObj s, bool invalidateWorldPrice=true) {}