Loading
設定並維護零售執行
目錄
選取篩選

          沒有結果
          沒有結果
          以下是搜尋小祕訣

          檢查關鍵字的拼字。
          使用較常見的搜尋字詞。
          選取較少篩選條件以擴大您的搜尋。

          搜尋所有 Salesforce 說明
          使用 Apex 建議造訪

          使用 Apex 建議造訪

          對 Einstein 必須提供造訪建議的特定商店清單建立 Apex 類別。然後您便可以建立流程,並將 Apex 類別作為「動作」元素新增。

          必要版本

          適用於已啟用 Consumer Goods Cloud 的 Lightning Experience ProfessionalUnlimitedEnterprise Edition。
          重要
          重要 若要在策略中使用 Apex 動作,請您的開發人員以 @InvocableMethod 註解適當的方法。

          用於篩選商店的 Apex 類別如下所示:

          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;
            }
          
          }
           
          正在載入
          Salesforce Help | Article