I am trying to populate a custom object(Account_Report__c) by a batch Apex that will fetch related records from two other objects (Account and Product_Metrics_vod__c).
Account and Product Metrics object are having master-detail relation. Product Metrics have Product Id + Account Id - which I am using in my code as unique key.
For each of Product + Account combination in Product Metrics, we should have one record in the resultant Account_report__c object. So, if this combination key is present in Target (Account_report__c )object we should update the record in target or else we need to insert the record.
But I am getting same recird multiple times in the arInslst List. and the code fails with the error - System.ListException: Before Insert or Upsert list must not have two identically equal elements Please assist.
Thanks, Below is my code
global class batchAccountProductMetricReporting implements
Database.Batchable<sObject> {
global Database.QueryLocator start(Database.BatchableContext BC) {
String query = 'SELECT Id,Name , Products_vod__c, Account_vod__c,Segment_Loyalty_LBK_FI__c,Segment_Potential_LBK_FI__c
FROM Product_Metrics_vod__c WHERE Segment_Loyalty_LBK_FI__c != null';
// where Segment_Potential_LBK_FI__c ! = null or Segment_Loyalty_LBK_FI__c ! = null';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Product_Metrics_vod__c> scope) {
Map<id,Product_Metrics_vod__c> pmMap1 = new Map<id,Product_Metrics_vod__c>();
Map<id,id> pmMap2 = new Map<id,id>();
Map<string,id> pmMap3 = new Map<string,id>();
List<Account> acclist;
List<Account_Report__c> acReplst;
List<Account_Report__c> arInslst = new List<Account_Report__c>();
List<Account_Report__c> arUpdlst = new List<Account_Report__c>();
Set<Id> pmId = new Set<Id>();
String pmKey='';
String pmKey2='';
for(Product_Metrics_vod__c pm: scope)
{
system.debug ('1-------------------Scope '+ pm.Id);
pmId.add(pm.Account_vod__c);
pmKey= pm.Account_vod__c+'_'+pm.Products_vod__c;
pmMap1.put(pm.Id,pm);
pmMap3.put(pmKey,pm.Id);
}
Account_Report__c accMet= new Account_Report__c();
List<Id> acMetNamelst= new List<Id>();
acReplst = new List <Account_Report__c> ([SELECT Id,Name FROM Account_Report__c where Name IN: pmMap3.keySet()]);
Map<id,Account_Report__c> arMap = new Map<id,Account_Report__c>();
Map<id,string> arMap2 = new Map<id,string>();
for (Account_Report__c ar : acReplst)
{
arMap.put(ar.Id,ar);
arMap2.put(ar.Id,ar.Name);
acMetNamelst.add(ar.Id);
}
acclist= new List <Account> ([SELECT Id,Name FROM Account where id IN: pmId]);
for(Product_Metrics_vod__c pm: scope)
{
pmKey2= pm.Account_vod__c+'_'+pm.Products_vod__c;
system.debug ('4-------------------PmId inside for 1 ------------>'+ pm);
for (Account acc : acclist)
{
if (acc.Id==pmMap1.get(pm.Id).Account_vod__c)
{
if (arMap2.get(acc.Id)== null){
if (!pmKey2.Equals(arMap2.get(acc.Id)))
{
accMet.Account_Name__c=pm.Account_vod__c;
accMet.Product_Name__c=pm.Products_vod__c;
accMet.Loyalty__c=Integer.ValueOf(pm.Segment_Loyalty_LBK_FI__c) ;
accMet.Name=pm.Account_vod__c+'_'+pm.Products_vod__c;
accMet.Potential__c=pm.Segment_Potential_LBK_FI__c ;
system.debug('20---------------------hi apurba 2----->'+accMet);
arInslst.add(accMet);
}
system.debug('21---------------------hi apurba 3 list ----->'+arInslst);
}
//update
else
{
system.debug('10---------------------hi apurba 2----->');
accMet.Loyalty__c=Integer.ValueOf(pm.Segment_Loyalty_LBK_FI__c) ;
accMet.Potential__c=pm.Segment_Potential_LBK_FI__c ;
arUpdlst.add(accMet);
}
}
//}//3rd for close
}
}
insert arInslst;
update arUpdlst;
}
global void finish(Database.BatchableContext BC) {
//nothing to write here.
} }
@dphil : no, My problem is with arInsList....the problm lies with list population only..as same Record from Product Metrics is getting added again and again...I understand that currently I am taking the records from one object only...but going fwd I also would need the 2nd object as well so I would need the nested for loop.
@Keith C - thanks for your suggestions. I am sure It would work.However, oing fwd I also would need the 2nd object as well so I would need the nested for loop. Basically I will be doing a join type of stuff b/w the two input objects and will store the result in the Target object based on some criteria.