diff --git a/examples/b2c/checkout/integrations/classes/B2CDeliverySample.cls b/examples/b2c/checkout/integrations/classes/B2CDeliverySample.cls index c76901d..766b871 100644 --- a/examples/b2c/checkout/integrations/classes/B2CDeliverySample.cls +++ b/examples/b2c/checkout/integrations/classes/B2CDeliverySample.cls @@ -31,16 +31,28 @@ global class B2CDeliverySample implements sfdc_checkout.CartShippingCharges { shippingOptionsAndRatesFromExternalService = getShippingOptionsAndRatesFromMockedService(siteLanguage); } - // On re-entry of the checkout flow delete all previous CartDeliveryGroupMehods for the given cartDeliveryGroupId - delete [SELECT Id FROM CartDeliveryGroupMethod WHERE WebCartId = :cartId]; - // Create a CartDeliveryGroupMethod record for every shipping option returned from the external service Integer cdgmToBeCreated = 0; CartDeliveryGroupMethod[] cdgmsToInsert = new CartDeliveryGroupMethod[]{}; - for (ShippingOptionsAndRatesFromExternalService shippingOption: shippingOptionsAndRatesFromExternalService) { - for(CartDeliveryGroup curCartDeliveryGroup : cartDeliveryGroups){ - CartDeliveryGroupMethod cdgm = populateCartDeliveryGroupMethodWithShippingOptions(shippingOption, curCartDeliveryGroup.Id, cartId); - cdgmsToInsert.add(cdgm); + // there can be multiple delivery groups so we will iterate thru DGs + for(CartDeliveryGroup curCartDeliveryGroup : cartDeliveryGroups){ + // get selected Delivery method id for cart delivery groupId + ID previousSelectDeliveryMethodId = [SELECT SelectedDeliveryMethodId FROM CartDeliveryGroup WHERE Id = :curCartDeliveryGroup.Id][0].SelectedDeliveryMethodId; + + if(previousSelectDeliveryMethodId != null) { + // delete all the cart delivery group method id except selected one + delete [SELECT Id FROM CartDeliveryGroupMethod WHERE CartDeliveryGroupId = :curCartDeliveryGroup.Id and Id!= :previousSelectDeliveryMethodId]; + } else { + //Delete all the delivery methods if previousSelectDeliveryMethod is null + delete [SELECT Id FROM CartDeliveryGroupMethod WHERE CartDeliveryGroupId = :curCartDeliveryGroup.Id]; + } + // iterate thru all shipping rates + for (ShippingOptionsAndRatesFromExternalService shippingOption: shippingOptionsAndRatesFromExternalService) { + //if selected CDGM is matching with shipping option then we don't need to create shipping option and existing can be reused + if(!isShippingOptionMatchingWithSelectedDM(shippingOption,previousSelectDeliveryMethodId)){ + CartDeliveryGroupMethod cdgm = populateCartDeliveryGroupMethodWithShippingOptions(shippingOption, curCartDeliveryGroup.Id, cartId); + cdgmsToInsert.add(cdgm); + } cdgmToBeCreated += 1; } } @@ -83,6 +95,44 @@ global class B2CDeliverySample implements sfdc_checkout.CartShippingCharges { return integStatus; } + /** + This method compares previous Selected Delivery method with current shipping options and if both matches returns ture + */ + private boolean isShippingOptionMatchingWithSelectedDM(ShippingOptionsAndRatesFromExternalService shippingOption, String previousSelectDeliveryMethodId) { + if(previousSelectDeliveryMethodId != null && !previousSelectDeliveryMethodId.equals('')) { + // get delivery group method for seletctedDMId + CartDeliveryGroupMethod previousSelectDeliveryMethod = [SELECT Name, ShippingFee, WebCartId, Carrier, ClassOfService, ExternalProvider, ProductId, ReferenceNumber, IsActive, TransitTimeMin, TransitTimeMax, TransitTimeUnit, ProcessTime, ProcessTimeUnit FROM CartDeliveryGroupMethod WHERE Id= :previousSelectDeliveryMethodId]; + + // return if all fields of shipping option matches with selectedDM else return false + return (previousSelectDeliveryMethod.Name.equals(shippingOption.getName()) && // compare name + previousSelectDeliveryMethod.IsActive.equals(shippingOption.isActive()) && // compare isActive flag + + previousSelectDeliveryMethod.ShippingFee.equals(shippingOption.getRate()) && // compare shipping fee + + isNullOrEquals(previousSelectDeliveryMethod.ProcessTime, shippingOption.getProcessTime()) && // compare process time + isNullOrEquals(previousSelectDeliveryMethod.ProcessTimeUnit, shippingOption.getProcessTimeUnit()) && // compare time unit + + // ideally reference number should match but in this sample we are generating random string so won't match + //previousSelectDeliveryMethod.ReferenceNumber.equals(shippingOption.getReferenceNumber()) && + previousSelectDeliveryMethod.Carrier.equals(shippingOption.getCarrier()) && // compare carrier + previousSelectDeliveryMethod.ClassOfService.equals(shippingOption.getClassOfService()) && + previousSelectDeliveryMethod.ExternalProvider.equals(shippingOption.getProvider()) && // compare external provider + + isNullOrEquals(previousSelectDeliveryMethod.TransitTimeMax, shippingOption.getTransitTimeMax()) && // compare transit time + isNullOrEquals(previousSelectDeliveryMethod.TransitTimeMin, shippingOption.getTransitTimeMin()) && + isNullOrEquals(previousSelectDeliveryMethod.TransitTimeUnit, shippingOption.getTransitTimeUnit())); // compare transit time unit + } + // we will return false so DM can be created if no previous selected DM is null + return false; + } + + /** + This method compares two objects, if both are null or equals returns true + */ + private boolean isNullOrEquals(Object o1, Object o2) { + return (o1 == null && o2 == null) || (o1 != null && o1.equals(o2)); + } + /** This method provides a sample of how to call an external service to retrieve Shipping Options. The heroku servie called in this method is just a reference implementation that responds back with diff --git a/examples/b2c/checkout/integrations/classes/B2CDeliverySampleTest.cls b/examples/b2c/checkout/integrations/classes/B2CDeliverySampleTest.cls index 1e55b01..2674aed 100644 --- a/examples/b2c/checkout/integrations/classes/B2CDeliverySampleTest.cls +++ b/examples/b2c/checkout/integrations/classes/B2CDeliverySampleTest.cls @@ -51,4 +51,71 @@ private class B2CDeliverySampleTest { Test.stopTest(); } + + @isTest static void testIntegrationRunsSuccessfully_toRetainPrevSelectedDeliveryMethod() { + Test.startTest(); + init(); + // Test: execute the integration for the test cart ID. + B2CDeliverySample apexSample = new B2CDeliverySample(); + sfdc_checkout.IntegrationInfo integInfo = new sfdc_checkout.IntegrationInfo(); + WebCart webCart = [SELECT Id FROM WebCart WHERE Name='Cart' LIMIT 1]; + integInfo.jobId = null; + sfdc_checkout.IntegrationStatus integrationResult = apexSample.startCartProcessAsync(integInfo, webCart.Id); + // Verify: the integration executed successfully + System.assertEquals(sfdc_checkout.IntegrationStatus.Status.SUCCESS, integrationResult.status); + + List CDGMs = new List([SELECT Id FROM CartDeliveryGroupMethod WHERE WebCartId = :webCart.Id]); + Integer expectedCDGMs = cartDeliveryGroupsNo * expectedCDGMInTheIntegrationMock; + System.assertEquals(expectedCDGMs, CDGMs.size(),'(MultipppleDeliveryGroups/MDG support validation) The expected ' + expectedCDGMs + ' CartDeliveryGroupMethods were not created by the integration'); + + //Till here first run completed and we got some selected delivery method for each Delivery group + //now we will update our selected delivery method and rerun the calculations and check even post completion of intgration our selected DM should remain same + + //fetch all cart delivery groups + List cartDeliveryGroups = new List([SELECT Id FROM CartDeliveryGroup WHERE CartId = :webCart.Id]); + + //fetch selected delivery method id for first cdg + Id previousSelectDeliveryMethodId = [SELECT SelectedDeliveryMethodId FROM CartDeliveryGroup WHERE Id = :cartDeliveryGroups[0].Id][0].SelectedDeliveryMethodId; + + //find delivery method for same delivery group where id does not match with previous selected DM + List cartDeliveryGroupMethods = new List([SELECT Id FROM cartDeliveryGroupMethod WHERE CartDeliveryGroupId = :cartDeliveryGroups[0].Id]); + String nonSelectedId = null; + for( CartDeliveryGroupMethod cdgm : cartDeliveryGroupMethods) { + if(cdgm.Id != previousSelectDeliveryMethodId) { + nonSelectedId = cdgm.Id; + break; + } + } + //update cart delivery group with updated DM + CartDeliveryGroup cdgToUpdate = cartDeliveryGroups[0]; + cdgToUpdate.SelectedDeliveryMethodId = nonSelectedId; + update cdgToUpdate; + + // run integration again + integInfo.jobId = null; + integrationResult = apexSample.startCartProcessAsync(integInfo, webCart.Id); + // Verify: the integration executed successfully + System.assertEquals(sfdc_checkout.IntegrationStatus.Status.SUCCESS, integrationResult.status); + + //fetch all cart delivery groups + cartDeliveryGroups = new List([SELECT Id FROM CartDeliveryGroup WHERE CartId = :webCart.Id]); + //update cart delivery group with updated DM + cdgToUpdate = cartDeliveryGroups[0]; + cdgToUpdate.DeliverToPostalCode = '100001'; + update cdgToUpdate; + + // run integration again + integInfo.jobId = null; + integrationResult = apexSample.startCartProcessAsync(integInfo, webCart.Id); + // Verify: the integration executed successfully + System.assertEquals(sfdc_checkout.IntegrationStatus.Status.SUCCESS, integrationResult.status); + + // verify that newPreviousSelectDeliveryMethodId should match with our selected DM id + Id newPreviousSelectDeliveryMethodId = [SELECT SelectedDeliveryMethodId FROM CartDeliveryGroup WHERE Id = :cartDeliveryGroups[0].Id][0].SelectedDeliveryMethodId; + System.assertEquals(nonSelectedId, newPreviousSelectDeliveryMethodId); + + Test.stopTest(); + } + + }