Recommandations de visites en utilisant Apex
Créez une tâche Apex pour répertorier les magasins spécifiques auxquels Einstein doit fournir des recommandations de visite. Vous pouvez créer un flux et ajouter la classe Apex en tant qu'élément Action.
Éditions requises
| Disponible dans Lightning Experience avec les éditions Professional, Unlimited et Enterprise dans lesquelles Consumer Goods Cloud est activé. |
Important Pour utiliser une action Apex dans un flux, demandez à votre développeur d'annoter la méthode appropriée avec @InvocableMethod.
Une classe Apex de filtrage des magasins se présente comme suit :
global class BulkGetVisitRecommendations {
@InvocableMethod(label='Bulk Get Visit Recommendations from Apex')
global static List<Recommendation> getRecommendations(List<List<String>> inputList) {
List<Recommendation> recommendations = new List<Recommendation>();
if(inputList != null && inputList.size() > 0 ){
Recommendation recommendation = new Recommendation();
List<String> recommendedStoreIds = new List<String>();
List<String> reasonForRecommendations = new List<String>();
List<String> input = inputList.get(0);
//Last element in input is DateString
Date visitRecommendationTargetDate = Date.valueof(input.get(input.size()-1));
populateRecommendationsBasedOnCases(input,recommendedStoreIds,reasonForRecommendations);
populateRecommendationsBasedOnPromotions(input,visitRecommendationTargetDate,recommendedStoreIds,reasonForRecommendations);
populateRecommendationsBasedOnOutOfStockKPIs(input,visitRecommendationTargetDate,recommendedStoreIds,reasonForRecommendations);
recommendation.StoreIds = recommendedStoreIds;
recommendation.RecommendationReasons = reasonForRecommendations;
recommendations.add(recommendation);
}
return recommendations;
}
public static void populateRecommendationsBasedOnCases(List<String> storeIds,List<String> recommendedStoreIds,List<String> reasonForRecommendations) {
List<RetailStore> stores = [select Id, PrimaryContactId from RetailStore where Id IN :storeIds AND PrimaryContactId != null];
if(stores!=null){
//Check for open cases agianst primarycontact of store.
//System.debug('stores found ');
Map<String, String> StoreToprimaryContactMap = new Map<String,String>();
if(stores.size() > 0){
for(RetailStore store : stores){
StoreToPrimaryContactMap.put(store.Id,store.PrimaryContactId);
}
List<AggregateResult> casesForPrimaryContactOfStores = [Select contactId, max(createdDate) from Case where isClosed = false AND contactid in :StoreToPrimaryContactMap.values() group by contactId];
Map<String, DateTime> primaryContactToCaseCreationDateTimeMap = new Map<String,DateTime>();
if(casesForPrimaryContactOfStores != null && casesForPrimaryContactOfStores.size() > 0){
for(AggregateResult caseResult : casesForPrimaryContactOfStores){
Date caseDate = Date.valueOf(caseResult.get('expr0'));
DateTime caseDateTime = DateTime.newInstance(caseDate.year(),caseDate.month(),caseDate.day(),0,0,0);
primaryContactToCaseCreationDateTimeMap.put(String.valueof(caseResult.get('ContactId')),caseDateTime);
}
}
//Get latest Visit for PlaceId
List< AggregateResult > latestVisitsForStores = [Select PlaceId, max(PlannedVisitStartTime) FROM Visit where PlaceId in :StoreToPrimaryContactMap.keyset() group by PlaceId];
if(latestVisitsForStores !=null && latestVisitsForStores.size() > 0){
for(AggregateResult visit : latestVisitsForStores){
String storeId = String.valueof(visit.get('PlaceId'));
String primaryContactId = StoreToprimaryContactMap.get(storeId);
//System.debug('primaryContactId found '+primaryContactId+' latest Visit Date for store '+storeId+' is '+visit.get('expr0'));
DateTime caseCreationDateTime = primaryContactToCaseCreationDateTimeMap.get(primaryContactId);
if(DateTime.valueof(visit.get('expr0')) < caseCreationDateTime){
// No visit is created after case is in open state.
reasonForRecommendations.add('No visit created after the latest case logged against primary contact');
recommendedStoreIds.add(storeId);
}
}
}
}
}else{
System.debug('PrimaryContact is empty for all stores');
}
}
public static void populateRecommendationsBasedOnPromotions(List<String> storeIds, Date visitRecommendationTargetDate, List<String> recommendedStoreIds,List<String> reasonForRecommendations) {
Integer noOfDaysToConsiderPromotion = 7;
Date promoStartDate = visitRecommendationTargetDate.addDays(noOfDaysToConsiderPromotion);
Date promoEndDate = visitRecommendationTargetDate.addDays(365);
List<PromotionChannel> promotionchannels = [Select Id, RetailStoreId from PromotionChannel where RetailStoreId IN :storeIds AND startDate > :promoStartDate AND (endDate < :promoEndDate OR endDate = null)];
if(promotionchannels != null){
for(PromotionChannel promotionChannel : promotionchannels){
//upcoming promotion for store
//System.debug('promotionchannels for storeId - ' + promotionChannel.RetailStoreId+' is '+promotionchannel);
reasonForRecommendations.add('Upcoming Promotion for the store scheduled after '+noOfDaysToConsiderPromotion +' days');
recommendedStoreIds.add(promotionChannel.RetailStoreId);
}
}
}
public static void populateRecommendationsBasedOnOutOfStockKPIs(List<String> storeIds,Date visitRecommendationTargetDate,List<String> recommendedStoreIds,List<String> reasonForRecommendations) {
Integer noOfVisitRecordsForStore = 5;
Integer noofDaysStoreNotVisited = 14;
Date actualVisitStartDateForStoreNotVisited = visitRecommendationTargetDate.addDays(-noofDaysStoreNotVisited);
DateTime actualVisitStartDateTimeForStoreNotVisited = DateTime.newInstance(actualVisitStartDateForStoreNotVisited.year(),actualVisitStartDateForStoreNotVisited.month(),actualVisitStartDateForStoreNotVisited.day(),0,0,0);
Integer noOfVisitsToCheckForOOS = 1;
String outOfStock = 'OutOfStock';
List<Visit> visitsExecuted = [SELECT Id,PlaceId FROM Visit WHERE PlaceId IN :storeIds AND ActualVisitStartTime != null AND ActualVisitStartTime > :actualVisitStartDateTimeForStoreNotVisited];
List<String> storeIdsCopy = storeIds;
if(visitsExecuted!= null && visitsExecuted.size() > 0){
// visit is already executed for the stores
for (Visit visit : visitsExecuted) {
Integer index =storeIdsCopy.indexOf(visit.PlaceId);
if(index != -1)
storeIdsCopy.remove(index);
}
}
//System.debug('Visit is not executed for '+storeIdsCopy.size()+' stores');
Map<String,String> visitIdToStoreIdMap = new Map<String,String>();
List<String> filteredVisitIdsToCheckOutOfStockKPIS = new List<String>();
Map<String, List<String>> storeIdToVisits = new Map<String,List<String>>();
List<Visit> visits = [SELECT Id,PlaceId FROM Visit WHERE PlaceId IN :storeIdsCopy AND ActualVisitStartTime != null ORDER BY ActualVisitStartTime];
for (Visit visit : visits) {
String storeId = visit.PlaceId;
visitIdToStoreIdMap.put(visit.Id,storeId);
if (storeIdToVisits.get(storeId) == null){
List<String> newList = new List<String>();
newList.add(visit.Id);
storeIdToVisits.put(storeId, newList);
filteredVisitIdsToCheckOutOfStockKPIS.add(visit.Id);
}else{
// add visit id for store only if no. of visits for each store is less than configured #noOfVisitRecordsForStore
if(storeIdToVisits.get(storeId).size() <= noOfVisitRecordsForStore){
storeIdToVisits.get(storeId).add(visit.Id);
filteredVisitIdsToCheckOutOfStockKPIS.add(visit.Id);
}
}
}
Map<String,Integer> storeIdToOosKPICount = new Map<String,Integer>();
List<RetailVisitKpi> oosRetailVisitkpis= [SELECT Id, Assessmenttask.parentid FROM RetailVisitKpi WHERE Assessmenttask.parentid IN :filteredVisitIdsToCheckOutOfStockKPIS AND Type = :outOfStock AND TargetBooleanValue = 'True'];
for (RetailVisitKpi rvkpi : oosRetailVisitkpis) {
String visitId = rvkpi.Assessmenttask.parentid;
String storeId = visitIdToStoreIdMap.get(visitId);
Integer currentStoreIdOOSKPICount = storeIdToOosKPICount.get(storeId);
if(currentStoreIdOOSKPICount == null){
storeIdToOosKPICount.put(storeId,1);
}else{
Integer newStoreIdOOSKPICount = currentStoreIdOOSKPICount+1;
storeIdToOosKPICount.put(storeId,newStoreIdOOSKPICount);
//System.debug('OOS KPI count for '+storeId+' is '+newStoreIdOOSKPICount);
}
if(storeIdToOosKPICount.get(storeId) == noOfVisitsToCheckForOOS){
reasonForRecommendations.add('Store is not visited in last '+noofDaysStoreNotVisited + ' days and there are atleast '+noOfVisitsToCheckForOOS+ ' Out of stock kpis in previous visits');
recommendedStoreIds.add(storeId);
}
}
}
global class Recommendation {
@InvocableVariable
global List<String> StoreIds;
@InvocableVariable
global List<String> RecommendationReasons;
}
}Cet article a-t-il résolu votre problème ?
Dites-nous ce que nous pouvons améliorer !

