2

The below is what I am trying to do -

  1. Get a list of purchase orders with its line items.
  2. Update the status of the purchase Orders to Rejected.
  3. Clone the purchase orders with its line items.
  4. Set the status of the cloned purchase orders to Resubmit Invoice.
  5. Insert the cloned purchase orders.
  6. Relinkthe line items to the clone purchase orders.
  7. Insert the cloned line items.

What does not work in the below code is the relinking and the insertion of the cloned line items. Could someone point what I am doing wrong in the below code?

List<Purchase_Order__c> purchaseOrders = [
    SELECT Id, 
    Name, 
    PO_Number__c, 
    (SELECT Id, 
        Purchase_Order__c, 
        Name, 
        FROM Purchase_Order_Line_Items__r)
        FROM Purchase_Order__c WHERE Id IN :rejectedInvoicePurchaseOrders];

for (Purchase_Order__c purchaseOrder : purchaseOrders) {
    // Update the status
    purchaseOrder.Status__c = 'Rejected';

    // Clone the purchase order along with its line items
    Purchase_Order__c clonedPurchaseOrder = purchaseOrder.clone(false, true, false, true);
    clonedPurchaseOrders.add(clonedPurchaseOrder);

    // Add the clonedPurchaseOrderLineItem to the clonedPurchaseOrderLineItems list
    for (Purchase_Order_Line_Item__c purchaseOrderlineItem : clonedPurchaseOrder.Purchase_Order_Line_Items__r) {
        clonedPurchaseOrderLineItems.add(purchaseOrderlineItem);
    }
}
// Update the original purchase orders in the database
update purchaseOrders;

// Insert the cloned purchase orders into the database
for (Purchase_Order__c clonedPurchaseOrder : clonedPurchaseOrders) {
    clonedPurchaseOrder.Invoice__c = invoiceRecordIdForToday;
    clonedPurchaseOrder.Status__c = 'Resubmit Invoice';
}
//insert clonedPurchaseOrders;
Database.SaveResult[] clonedPurchaseOrderSaveResults = Database.insert(clonedPurchaseOrders, false);

// Create a map to hold the successful cloned purchase orders
Map<Id, Purchase_Order__c> successfulClonedPurchaseOrders = new Map<Id, Purchase_Order__c>();

// Loop through each save result
for (Database.SaveResult saveResult : clonedPurchaseOrderSaveResults) {
    // If the save was successful, add the cloned purchase order to the map
    if (saveResult.isSuccess()) {
        successfulClonedPurchaseOrders.put(saveResult.getId(), clonedPurchaseOrders[clonedPurchaseOrderSaveResults.indexOf(saveResult)]);
    }   
}
// Update the Purchase_Order__c lookup field on the cloned line items
for (Purchase_Order_Line_Item__c clonedPurchaseOrderlineItem : clonedPurchaseOrderLineItems) {
    // If the original purchase order was cloned successfully, link the line item to the cloned purchase order
    if (successfulClonedPurchaseOrders.containsKey(clonedPurchaseOrderlineItem.Purchase_Order__c)) {
        clonedPurchaseOrderlineItem.Purchase_Order__c = successfulClonedPurchaseOrders.get(clonedPurchaseOrderlineItem.Purchase_Order__c).Id;
    }
}
// Insert the cloned line items into the database
Database.SaveResult[] clonedLineItemSaveResults = Database.insert(clonedPurchaseOrderLineItems, false);

1 Answer 1

3

The cloned purchase order line items still point to the original purchase order id until you update that in memory (and then persist using DML).

So you need to be using the original purchase orders' Ids for the key of successfulClonedPurchaseOrders, not the Id of the newly inserted clone.
In other words, you need a map from the original id to the new id (or to the new record).

Also, using .clone(false, ...) on the parent record does not clear out the Ids on the child records. You should be using .clone(false, ...) on each individual purchase order line item too. Otherwise your line items will still have an Id and Salesforce will complain when you try to insert them.

2
  • Something else to be aware of: Doing a clone on a parent (irrespective of what you use for the isDeepClone argument) with children does not get you an independent copy of the child records. They're still referencing the same child record instances, so any change you make to a child record will be reflected on the child records for the original instance of the parent record (that is, unless you use .clone() on each of the child records, or .deepClone() on the embedded list of child sobjects if you know you won't go over 200 children per parent and thus run into the "querymore" issue).
    – Derek F
    Commented Jun 20 at 14:58
  • Thanks Derek for the detailed explanation.
    – Sumesh
    Commented Jun 20 at 17:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .