U bent hier:
Best practices voor Apex prijshaken
Volg deze best practices bij het implementeren van Apex hooks in uw prijsstellingsprocedureplannen om prestaties te optimaliseren en onverwachte resultaten te voorkomen.
Apex Governor-limieten
Apex hooks in procedureplannen worden uitgevoerd binnen dezelfde Apex transactie, waardoor de timer van de centrale verwerkingseenheid cumulatief is voor alle bewerkingen. Houd rekening met beheerlimieten bij het schrijven van hooklogica, vooral voor transacties met veel regelitems.
Zie Uitvoeringsbeheer en limieten in de Apex Developer Guide voor huidige limietwaarden.
Query uitvoeren op alleen de tags die u nodig hebt
Vermijd het uitvoeren van query's op brede tags op entiteitsniveau, zoals SalesTransactionItem, die elk kenmerk voor elk item retourneren. Vraag in plaats daarvan alleen de specifieke tags aan die uw hooklogica vereist.
Niet aanbevolen: Query uitvoeren op brede tags
// BAD: Returns ALL attributes for every SalesTransactionItem
Map<String, Object> input = new Map<String, Object>{
'contextId' => contextId,
'tags' => new List<String>{ 'SalesTransactionItem' }
};
Map<String, Object> output = industriesContext.queryTags(input);
Aanbevolen: Alleen specifieke tags opvragen
// GOOD: Query only the specific tags (attributes) you need
Map<String, Object> input = new Map<String, Object>{
'contextId' => contextId,
'tags' => new List<String>{ 'LineItem', 'LineItemQuantity', 'ItemProductCode' }
};
Map<String, Object> output = industriesContext.queryTags(input);
Aanbevolen: Specifieke tags combineren met leanerQueryTags
// BETTER: Combine specific tags with leanerQueryTags for maximum efficiency
Map<String, Object> input = new Map<String, Object>{
'contextId' => contextId,
'tags' => new List<String>{ 'LineItem', 'LineItem$DmlStatus',
'LineItemQuantity', 'ItemProductCode' }
};
Map<String, Object> output = industriesContext.leanerQueryTags(input);
leanerQueryTags gebruiken in plaats van queryTags
De klasse Context.IndustriesContext biedt twee methoden voor het uitvoeren van query's op contextgegevens. Gebruik leanerQueryTags waar mogelijk voor betere prestaties.
queryTags (heavy): retourneert volledige contextknooppunten met geneste tag-waardekaarten en dataPath. Elk kenmerk is verpakt in een toewijzing met 6 velden (tagValue, dmlStatus, isDirty, isNodeLevelTag, tagPath, contextDataPathBuilder) per kenmerk per item. Alle kenmerken voor de tag worden geretourneerd, ongeacht wat u nodig hebt.
leanerQueryTags (lichtgewicht): retourneert een compacte structuur met platte tagwaarden en op index gebaseerde record-ID-verwijzingen. Tagwaarden hebben slechts 3 velden (tagValue, recordIdIndexesForPath, isNodeLevelTag). Record-ID's worden gededupliceerd in een gedeelde recordsInfo; knooppunten verwijzen ernaar per index.
Het volgende voorbeeld toont hoe u leanerQueryTags aanroept en de uitvoer ervan verwerkt.
String contextId = request.ctxInstanceId;
Context.IndustriesContext industriesContext = new Context.IndustriesContext();
Map<String, Object> input = new Map<String, Object>{
'contextId' => contextId,
'tags' => new List<String>{ 'LineItem', 'ItemProductCode', 'LineItemQuantity' }
};
Map<String, Object> output = industriesContext.leanerQueryTags(input);
// Access the leaner result structure
Map<String, Object> queryResult = (Map<String, Object>)
output.get('leanerQueryTagResult');
List<Object> recordsInfo = (List<Object>) output.get('recordsInfo');
List<Object> lineItems = (List<Object>) queryResult.get('LineItem');
// Iterate over tag values — each tag is flat
List<Object> productCodes = (List<Object>) queryResult.get('ItemProductCode');
for (Object obj : productCodes) {
Map<String, Object> tagNode = (Map<String, Object>) obj;
String productCode = (String) tagNode.get('tagValue');
List<Integer> indexes = (List<Integer>) tagNode.get('recordIdIndexesForPath');
// recordsInfo entries are maps with 'recordId' and 'dmlStatusOrdinal'
String itemId = (String) ((Map<String, Object>)
recordsInfo.get(indexes[1])).get('recordId');
}
De structuur van de leanerQueryTags ziet er als volgt uit:
{
"isSuccess": true,
"contextId": "...",
"leanerQueryTagResult": {
"LineItem": [
{ "recordIdIndexesForPath": [0, 1], "tagValue": "0QLVW000001LxvN4AS", "isNodeLevelTag": false },
{ "recordIdIndexesForPath": [0, 2], "tagValue": "0QLVW000001Lxus4AC", "isNodeLevelTag": false }
],
"ItemProductCode": [
{ "recordIdIndexesForPath": [0, 1], "tagValue": "PROD-001", "isNodeLevelTag": false },
{ "recordIdIndexesForPath": [0, 2], "tagValue": "PROD-002", "isNodeLevelTag": false }
]
},
"recordsInfo": [
{ "recordId": "0Q0VW0000011qC50AI", "dmlStatusOrdinal": null },
{ "recordId": "0QLVW000001LxvN4AS", "dmlStatusOrdinal": null },
{ "recordId": "0QLVW000001Lxus4AC", "dmlStatusOrdinal": null }
]
}
Migreren van queryTags naar leanerQueryTags
Pas bij het migreren van bestaande hooks van queryTags naar leanerQueryTags deze sleuteltransformaties toe.
Invoer: Afzonderlijke tags gebruiken in plaats van brede tags
// Before (queryTags — broad tag):
Map<String, Object> input = new Map<String, Object>{
'contextId' => contextId,
'tags' => new List<String>{ 'SalesTransactionItem' }
};
Map<String, Object> output = industriesContext.queryTags(input);
// After (leanerQueryTags — specific tags):
Map<String, Object> input = new Map<String, Object>{
'contextId' => contextId,
'tags' => new List<String>{ 'LineItem', 'LineItem$DmlStatus',
'ItemProductCode', 'LineItemQuantity' }
};
Map<String, Object> output = industriesContext.leanerQueryTags(input);
Uitvoer: Verschillende sleutel op het hoogste niveau
// Before:
Map<String, Object> queryResult = (Map<String, Object>) output.get('queryResult');
List<Object> items = (List<Object>) queryResult.get('SalesTransactionItem');
// After:
Map<String, Object> queryResult = (Map<String, Object>)
output.get('leanerQueryTagResult');
List<Object> recordsInfo = (List<Object>) output.get('recordsInfo');
List<Object> lineItems = (List<Object>) queryResult.get('LineItem');
Knooppunttoegang: Platte waarden in plaats van geneste kaarten
// Before (queryTags — nested map extraction):
for (Object itemObj : items) {
Map<String, Object> itemNode = (Map<String, Object>) itemObj;
Map<String, Object> tagValueMap = (Map<String, Object>) itemNode.get('tagValue');
String productCode = (String) ((Map<String, Object>)
tagValueMap.get('ItemProductCode')).get('tagValue');
Decimal quantity = (Decimal) ((Map<String, Object>)
tagValueMap.get('LineItemQuantity')).get('tagValue');
}
// After (leanerQueryTags — flat value, iterated per tag):
List<Object> productCodes = (List<Object>) queryResult.get('ItemProductCode');
List<Object> recordsInfo = (List<Object>) output.get('recordsInfo');
for (Object obj : productCodes) {
Map<String, Object> tagNode = (Map<String, Object>) obj;
String productCode = (String) tagNode.get('tagValue');
List<Integer> indexes = (List<Integer>) tagNode.get('recordIdIndexesForPath');
String itemId = (String) ((Map<String, Object>)
recordsInfo.get(indexes[1])).get('recordId');
}
Record-ID's: Indexverwijzingen in plaats van dataPath
// Before (queryTags):
List<Object> dataPath = (List<Object>) itemNode.get('dataPath');
// dataPath = ['contextId', 'txnId', 'itemId'] — 3 elements, first is contextId
dataPath.remove(0);
String transactionId = (String) dataPath.get(0);
// After (leanerQueryTags):
List<Object> recordsInfo = (List<Object>) output.get('recordsInfo');
List<Integer> indexes = (List<Integer>) tagNode.get('recordIdIndexesForPath');
String transactionId = (String) ((Map<String, Object>)
recordsInfo.get(indexes[0])).get('recordId');
String itemId = (String) ((Map<String, Object>)
recordsInfo.get(indexes[1])).get('recordId');
Het tagIdIndexMap-patroon gebruiken
Wanneer u meerdere tags in één lus verwerkt, gebruikt u een tagIdIndexMap om elke tagnaam toe te wijzen aan de positie ervan in de recordIdIndexesForPath. Hierdoor kunt u ID's op elk hiërarchieniveau correct extraheren:
Map<String, Integer> tagIdIndexMap = new Map<String, Integer>{
'LineItem' => 1, // item-level tag, ID at index 1
'LineItem$DmlStatus' => 1, // item-level tag, ID at index 1
'LineItemQuantity' => 1, // item-level tag, ID at index 1
'BusinessUnit__c' => 0, // transaction-level tag, ID at index 0
'Contract' => 0 // transaction-level tag, ID at index 0
};
- Index 0 = transactieniveau (het pad heeft één element: [
txnId]) - Index 1 = itemniveau (het pad heeft twee elementen: [
txnId,itemId]) - Index 2 = detailniveau (het pad heeft drie elementen: [
txnId,itemId,detailId])
Verwijderde items filteren
Sla verwijderde items over aan het begin van uw herhalingslus om onnodige verwerking te voorkomen. Verzoek om LineItem$DmlStatus als een afzonderlijke tag in uw query:
private static final String DML_DELETED = 'DELETED';
for (Map<String, Object> item : salesTransactionInstance.salesTransactionItems) {
String dmlStatus = (String) item.get('LineItem$DmlStatus');
if (dmlStatus == DML_DELETED) {
continue; // Skip deleted items
}
// Process active items...
}
$DmlStatus lezen als een afzonderlijke tag
Bij het uitvoeren van een query op specifieke tags (de aanbevolen benadering) wordt de DML-status niet ingebed in de metagegevens van de tag. U moet LineItem$DmlStatus aanvragen als een afzonderlijke tag. Dit geldt voor zowel queryTags als leanerQueryTags.
// Add LineItem$DmlStatus to your tags list
'tags' => new List<String>{ 'LineItem', 'LineItem$DmlStatus', 'ItemProductCode' }
// Access it like any other tag in the result
Map<String, Object> dmlNode = (Map<String, Object>) dmlStatusValues.get(i);
String dmlStatus = String.valueOf(dmlNode.get('tagValue'));
