EDIT relating to this comment:
Hello, Nathanael and really thank you for you response. To be honest i iterate through the product configuration list (pconf) and for each of those records i need to create a rate card record and it's lines. So i need to pick for every rate card generated it's extid. I used the [0](first record) as i cannot figure out how to pick it for each rate card record and assign it to extId. Can you propose something for this? Thank you!
Sure thing! :-) So it sounds like at this point you may not yet be in the habit of using map objects; these are probably what are going to help the most here. Maps allow you to associate one value with another, so that you can use it to quickly look up data related to a common identifier (like a salesforce id or external id), and tie it together.
You might start with this:
// Initialize Your Main Collections
Set<Id> pConfIds = new Set<Id>();
Attachment pConfAttachments = null;
Map<String, cspmb__Rate_Card__c> rateCardsByKey = new Map<String, cspmb__Rate_Card__c>();
Map<String, cspmb__Rate_Card_Line__c[]> rateCardLinesByKey = new Map<String, cspmb__Rate_Card_Line__c[]>();
cspmb__Rate_Card_Line__c[] allRateCardLines = new cspmb__Rate_Card_Line__c[]();
// Query Attachments.
// One other issue I didn't notice on my first read-through of the code is that
// you're running multiple attachment queries, one for each pConf. This is a
// bad practice in Salesforce that they punish with SOQL Query 101 errors and
// the like. Best practice is to run 1 query for all pConfs, then filter the
// attachments by pconf. My assumption in this code is that the external id is
// unique across all pConfs (e.g. the same id isn't used in two different pConfs
// for different rate cards). If that's a wrong assumption, then this code will
// need to be refactored / become a little more complex.
for(Integer i = 0; i < pConfList.size(); i++) {
pConfIds.add(pConfList[i].Id);
}
pConfAttachments = [select parentId, body, name from attachment where name like '%Rate Card%' and parentId IN :pConfIds];
// Process Header Attachments
for (attachment att : pConfAttachments) {
if (att.Name.startsWithIgnoreCase('Rate Card Information')) {
processRateCardAttachment(att, rateCardsByKey);
}
}
// Process Line Attachments
for (attachment att : pConfAttachments) {
if (att.Name.startsWithIgnoreCase('Rate Card Line Information')) {
processRateCardLineAttachment(att, rateCardsByKey, rateCardLinesByKey);
}
}
// Create Records
insert rateCardsByKey.values();
for (cspmb__Rate_Card_Line__c[] rateCardLines : rateCardLinesByKey.values()) {
allRateCardLines.add(rateCardLines);
}
insert allRateCardLines;
Then you would need to define the two attachment processing functions. I'll try to give you an outline of each, but unfortunately I'm not familiar with the data structure of what's being stored in JSON, so your mileage may vary.
In particular, I don't know what data is available on the rate card line that would allow you to link it to the header. There would need to be some sort of key field (perhaps the external id of the header); otherwise it is impossible to know which lines belong to which headers.
The sample code below assumes that there is some sort of a key besides the external id of the header, since you didn't use that in your original code. If the external id of the header is also available on the line, then the code can be simplified to just use lists rather than maps, because you already have all the data you need while processing the line; you don't need a reference to the header. Assuming that some other key is used, the code might look like the following:
@testVisible private static void processRateCardAttachment(Attachment att, Map<String, cspmb__Rate_Card__c> rateCardsByKey) {
...
list<cspmb__Rate_Card__c> rateCards = el_CustomerApprovalTriggerHandler.deserializedRateCard(...);
for(cspmb__Rate_Card__c rateCard: rateCards) {
String key = rateCard.el_External_Id__c; // or whatever key exists in the data to link lines to headers
rateCardsByKey.put(key, rateCard);
}
}
@testVisible private static void processRateCardLineAttachment(Attachment att, Map<String, cspmb__Rate_Card__c> rateCardsByKey, Map<String, cspmb__Rate_Card_Line__c[]> rateCardLinesByKey) {
...
list<cspmb__Rate_Card__c> rateCardLines = el_CustomerApprovalTriggerHandler.deserializedRateCardLines(...);
for(cspmb__Rate_Card__c rateCardLine: rateCardLines){
// Get Lines Related To Header
String headerKey = rateCardLine.el_External_Header_Id__c; // or whatever key exists in the data to link a line to its header
cspmb__Rate_Card__c rateCard = rateCardsByKey.get(headerKey)
cspmb__Rate_Card_Line__c[] headerLines = rateCardLinesByKey.get(headerKey);
if (rateCard == null) continue; // or throw an error
if (headerLines == null) rateCardLinesByKey.put(headerKey, headerLines = new cspmb__Rate_Card_Line__c[]());
rateCardLine.cspmb__Rate_Card__r = new cspmb__Rate_Card__c(el_External_Id__c = rateCard.el_External_Id__c);
headerLines.add(rateCardLine);
}
}