background

Add External FedEx tracking numbers from an Order

Published on 11 April 2017 in apex fedex 

Today's blog post we will show you how to add an externally created FedEx tracking numbers to an object. Updating tracking is the most common use case, that you are then able to query using the standard Salesforce reporting. We’ll be using the Order object in our demo here.

The code is made up of 3 parts.

  • Trigger on the Order Object:

Line 3: For when a brand new order is added with a tracking number

Line 7: For when the tracking number field is updated

trigger Add_Shipment_Manually on Order (after update, after insert) {
if (AddShipmentManuallyHandler.enablesTrigger) {
if (Trigger.isAfter && Trigger.isInsert) {
AddShipmentManuallyHandler.createOrderShipments(Trigger.new, null);
}
if (Trigger.isAfter && Trigger.isUpdate) {
AddShipmentManuallyHandler.createOrderShipments(Trigger.new, Trigger.old);
}
}
}

1. The trigger Handler class:

This is where the work gets done.

Line 4: Here you will need to contact us to get the ModKey value that allows the creation of a Shipment Object (without actually going through our package for the shipment creation process).

Line 8: You need to create a custom setting to store the ID of the preference, so that when you move this code from your sandbox org to your production org, its easy to update the custom setting to your saved UPS preference.

Line 19-30: For any new Orders, add the new record to the createFedExShipment method.

Line 30-47: If you are just updating the tracking number field (FB_Tracking_Numbers__c) on your Order, these lines take care of the shipment creation.

Line 67-75: For each shipment we create we also need to create a shipment package (zkfedex__ShipmentPackage__c) associated with it.

public class AddShipmentManuallyHandler {
public static Boolean enablesTrigger = true;
private static final String FEDEX_ZKMODKEY = 'CONTACT US AT SUPPORT@ZENKRAFT.COM';
private static final String KEY_FEDEX = 'FedEx';
private static zkfedex__ShipmatePreference__c fedexShipmatePreference;
public static void createOrderShipments(List<Order> newRecords, List<Order> oldRecords) {
initPreferences();
if (!canCreateShipment(KEY_FEDEX)) {
return;
}
List<zkfedex__Shipment__c> fedexShipmentsForInsert = new List<zkfedex__Shipment__c>();
// collect ids
if (oldRecords == null) { // insert, undelete
for (Order newRecord: newRecords) {
// logic for insert and undelete
if (String.isNotBlank(newRecord.FB_Tracking_Numbers__c)) {
if(isOrderForFedEx(newRecord)
&& canCreateShipment(KEY_FEDEX)
&& newRecord.EffectiveDate != null) {
fedexShipmentsForInsert.add(createFedExShipment(newRecord));
}
}
}
} else {
if (newRecords != null) { // update
for (Integer i = 0; i < newRecords.size(); i++) {
Order oldRecord = oldRecords.get(i);
Order newRecord = newRecords.get(i);
// logic for update
if (String.isNotBlank(newRecord.FB_Tracking_Numbers__c)
&& newRecord.FB_Tracking_Numbers__c != oldRecord.FB_Tracking_Numbers__c) {
if(isOrderForFedEx(newRecord)
&& canCreateShipment(KEY_FEDEX)
&& newRecord.EffectiveDate != null) {
fedexShipmentsForInsert.add(createFedExShipment(newRecord));
}
}
}
} else { // delete
// for (Order detail: oldRecords) {
// logic for delete
// }
}
}
if (fedexShipmentsForInsert != null && !fedexShipmentsForInsert.isEmpty()) {
insert fedexShipmentsForInsert;
Map<Id, zkfedex__Package__c> shipmentIdPackageMap = new Map<Id, zkfedex__Package__c>();
for (zkfedex__Shipment__c fedexShipment : fedexShipmentsForInsert) {
shipmentIdPackageMap.put(fedexShipment.Id, new zkfedex__Package__c());
}
insert shipmentIdPackageMap.values();
List<zkfedex__ShipmentPackage__c> shipPackages = new List<zkfedex__ShipmentPackage__c>();
zkfedex__ShipmentPackage__c shipPackage;
for (zkfedex__Shipment__c fedexShipment : fedexShipmentsForInsert) {
shipPackage = new zkfedex__ShipmentPackage__c();
shipPackage.zkfedex__Shipment__c = fedexShipment.Id;
shipPackage.zkfedex__TrackingId__c = fedexShipment.zkfedex__MasterTrackingId__c;
// shipPackage.zkfedex__TrackingIdType__c
shipPackage.zkfedex__Package__c = shipmentIdPackageMap.get(fedexShipment.Id).Id;
shipPackages.add(shipPackage);
}
insert shipPackages;
}
}
private static zkfedex__Shipment__c createFedExShipment(Order order) {
zkfedex__Shipment__c shipment = new zkfedex__Shipment__c();
shipment.zkfedex__MasterTrackingId__c = order.FB_Tracking_Numbers__c;
shipment.zkfedex__ShipDate__c = order.EffectiveDate;
shipment.zkfedex__ShipmatePreference__c = fedexShipmatePreference.Id;
// shipment.zkfedex__RecipientCountry__c = 'US';
shipment.zkfedex__ModKey__c = FEDEX_ZKMODKEY;
shipment.Order__c = order.Id;
return shipment;
}
private static Boolean isOrderForFedEx(Order order) {
return order.FB_Carrier__c == 'FedEx';
}
private static Boolean canCreateShipment(String carrier) {
if (carrier == KEY_FEDEX) {
return (fedexShipmatePreference != null);
}
return false;
}
private static void initPreferences() {
ShipmentSettings__c shipmentFedExSettings = ShipmentSettings__c.getInstance(KEY_FEDEX);
if (shipmentFedExSettings != null
&& String.isNotBlank(shipmentFedExSettings.Shipment_Preference_Id__c)) {
List<zkfedex__ShipmatePreference__c> fedexPreferences = [
SELECT Id, Name
FROM zkfedex__ShipmatePreference__c
WHERE Id =: shipmentFedExSettings.Shipment_Preference_Id__c
LIMIT 1];
if (fedexPreferences != null
&& !fedexPreferences.isEmpty()) {
AddShipmentManuallyHandler.fedexShipmatePreference = fedexPreferences[0];
}
}
}
}

1. The @Test class, is needed for the code coverage to be able to deploy into production.

@isTest
private class AddShipmentManuallyHandlerTest {
static testMethod void test_createFedExShipments() {
zkfedex__ShipmatePreference__c preference = new zkfedex__ShipmatePreference__c();
insert preference;
ShipmentSettings__c shipmentSettings = new ShipmentSettings__c();
shipmentSettings.Name = 'FedEx';
shipmentSettings.Shipment_Preference_Id__c = preference.Id;
insert shipmentSettings;
String trackNumber = 'trackNumber';
Account acc = new Account();
acc.Name = 'Account';
insert acc;
Order ord = new Order();
ord.FB_Tracking_Numbers__c = trackNumber;
ord.AccountId = acc.Id;
ord.Status = 'Draft';
ord.EffectiveDate = Date.today();
ord.FB_Carrier__c = 'FedEx';
Test.startTest();
insert ord;
checkFedExShipmentExists(trackNumber, ord.EffectiveDate);
ord.FB_Tracking_Numbers__c = trackNumber + '1';
update ord;
checkFedExShipmentExists(trackNumber + '1', ord.EffectiveDate);
Test.stopTest();
}
private static void checkFedExShipmentExists(String trackNumber, Date shipDate){
List<zkfedex__Shipment__c> shipments = [
SELECT Id, zkfedex__MasterTrackingId__c, zkfedex__ShipDate__c
FROM zkfedex__Shipment__c
WHERE zkfedex__MasterTrackingId__c = :trackNumber
AND zkfedex__ShipDate__c =: shipDate
LIMIT 1
];
System.assertEquals(1, shipments.size());
}
}

Any questions, please do not hesitate to contact us!