I am creating a cross-objects trigger that whenever a new opportunity is opened, the trigger goes to check whether the company has sold the same product to the customer before; if so, the type of the opportunity will be 'Existing', otherwise it will be 'New'.
trigger InOfficeOp on Opportunity (after insert, after update) {
Set<Id> account_id = new Set<Id>();
List<Id> opp_id = new List<Id>();
for (Opportunity opp: Trigger.new){
if(opp.HasOpportunityLineItem){
account_id.add(opp.AccountId);
opp_id.add(opp.Id);
}
}
Map<Id, List<Asset>> acc_asset_map = new Map<Id, List<Asset>>();
Map<Id, List<OpportunityLineItem>> opp_prod_map = new Map<Id, List<OpportunityLineItem>>();
for(Asset ast: [SELECT Product2Id, AccountId FROM Asset WHERE AccountId IN: account_id]) {
if(acc_asset_map!=null && acc_asset_map.containsKey(ast.Product2Id)) {
List<Asset> asset_List = acc_asset_map.get(ast.Product2Id);
asset_List.add(ast);
acc_asset_map.put(ast.Product2Id,asset_List);
}
else {
acc_asset_map.put(ast.Product2Id, new List<Asset>{ast});
}
}
for (OpportunityLineItem oli: [SELECT Product2Id, OpportunityId FROM OpportunityLineItem WHERE OpportunityId IN: opp_id]){
if(opp_prod_map!=null && opp_prod_map.containsKey(oli.Product2Id)){
List<OpportunityLineItem> oppLineItem_Recd = opp_prod_map.get(oli.Product2Id);
oppLineItem_Recd.add(oli);
opp_prod_map.put(oli.Product2Id, oppLineItem_Recd);
}
else {
opp_prod_map.put(oli.Product2Id, new List<OpportunityLineItem>{oli});
}
}
Id op;
for(Id prodId: acc_asset_map.keyset()){
if(opp_prod_map!= null && opp_prod_map.containsKey(prodId)) {
for(OpportunityLineItem oppLine_Recd:opp_prod_map.get(prodId)) {
op = oppLine_Recd.OpportunityId;
}
}
}
for(Opportunity o:Trigger.new){
if(o.Id == op){
o.Type = 'Existing_Business';
}
else{
o.Type = 'New_Business';
}
}
}
The above is my trigger code.
And here is my test:
@isTest
private class OppTriggerTest{
static void PopulateExtensiontest()
{
Date closeDt = Date.Today();
date myDate = date.today();
Account a2 = new Account(Name='icrm test acc');
insert a2;
Opportunity oppr = new Opportunity(Name='testing DIE 6/4/2017', AccountId =
a2.Id,StageName='Prodpecting',
CloseDate = Date.Today());
insert oppr;
Pricebook2 pb22 = new Pricebook2(Name='testDIE');
insert pb22;
Product2 pro2 = new Product2(Name='BXCD', isActive=true);
insert pro2;
PricebookEntry pbe2 =new
PricebookEntry(unitprice=0.01,Product2Id=pro2.Id, Pricebook2Id=Test.getStandardPricebookId(), isActive=true, UseStandardPrice=false);
insert pbe2;
OpportunityLineItem OPplineitem2 = new OpportunityLineItem (Quantity=2,
OpportunityId=oppr.Id, UnitPrice=0.01, PriceBookEntryId =pbe2.Id);
insert OPplineitem2;
update oppr;
}
}
And I got the error message after I exceture the test:
System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, InOfficeOp: execution of AfterInsert caused by: System.FinalException: Record is read-only
Trigger.InOfficeOp: line 51, column 1: []
I don't quite understand what does the message mean. Could anyone please help me what does the error mean? Is my test wrong?