Skip to main content

Hello

I have this class that is making the request body for an integration with netsuite. 

 

public class netsuite_CustomerMap implements INetsuiteMap{

public map<string, object> getNSMap(SObject sobj) {

Account acc = (Account)sobj;

string objectName = acc.getSObjectType().getDescribe().getName();

netsuite_Service nsService = new netsuite_Service();

map<string,map<string, Netsuite_Mapping__mdt>> ns_Map = nsService.getNSDefaultMap();

map<string, object> objMap = new map<string, object>();

objMap.put('companyname',acc.Name);

objMap.put('externalid', acc.Id);

objMap.put('recordtype', ns_Map.get('recordtype').get(objectName).Netsuite_Value__c);

objMap.put('altPhone',acc.Phone);

objMap.put('currency', ns_Map.get('currency').get(acc.CurrencyIsoCode).Netsuite_Value__c);

objMap.put('customForm', ns_Map.get('customForm').get(objectName).Netsuite_Value__c);

objMap.put('phone', acc.phone);

objMap.put('isPerson', ns_Map.get('isPerson').get(objectName).Netsuite_Value__c);

objMap.put('entityStatus',ns_Map.get('entityStatus').get(objectName).Netsuite_Value__c);*/

return objMap;

}

}

It works nicely but then I started thinking about what would happen if that request body needed to be changed. Perhaps a new field becsomes required by Netsuite, for example. This would require me to make edits to the class and deploying. So, I thought maybe I could put these map definitions into custom metadata, which would allow me to make any required changes by editing custom metdata inside production. I wound up with the following class:

 

public class netsuite_CustomerMap implements INetsuiteMap{

public map<string, object> getNSMap(SObject sobj) {

Account acc = (Account)sobj;

string objectName = acc.getSObjectType().getDescribe().getName();

netsuite_Service nsService = new netsuite_Service();

map<string,map<string, Netsuite_Mapping__mdt>> ns_Map = nsService.getNSDefaultMap();

map<string, object> objMap = new map<string, object>();

for(Netsuite_Master_Map_Definition__mdt mapSource : [select Id,

MasterLabel,

Netsuite_Master_Map__c,

Netsuite_Master_Map__r.MasterLabel,

Netsuite_Field__c,

Salesforce_Value__c

from Netsuite_Master_Map_Definition__mdt

where Netsuite_Master_Map__r.Apex_Class_Name__c = 'netsuite_CustomerMap']) {

objMap.put(mapSource.Netsuite_Field__c, mapSource.Salesforce_Value__c);

}

return objMap;

}

}

And here is an example of what the 2 custom fields in Netsuite_Master_Map_Definition__mdt called Netsuite_Field__c and Salesforce_Value__c are storing:

Netsuite_Field__c = 'companyname'

Salesforce_Value__c = acc.Name

As an admin, what I didn't think through is that this would not work because these are text fields and therefore simply populates the objMap with literal text values like so "'companyname'" => "acc.Name".

So, at this point I'm not sure what to do and will probably just reconcile myself to the reality of updating the class anytime a change to request body is needed.....Unless someone out there has any good ideas.

Thanks!

2 answers
  1. Apr 9, 2019, 10:54 AM

    Hi Andy,

    You can fetch the fields from the Sobject dynamically. I would suggest adding some sort of check, a boolean or a picklist field to determine if the value is string literal or a reference.

    For e.g. Let's add Salesforce_Value_type__c on Netsuite_Master_Map_Definition__mdt which can have two typesof values - 'Literal' or 'Dynamic'. Now in your code, you can check if the Salesforce_Value_type__c is 'Literal', add the value directly. If not, fetch it from the sObj/acc.

    The code sample looks like:

     

    public class netsuite_CustomerMap implements INetsuiteMap{

    public map<string, object> getNSMap(SObject sobj) {

    Account acc = (Account)sobj;

    string objectName = acc.getSObjectType().getDescribe().getName();

    netsuite_Service nsService = new netsuite_Service();

    map<string,map<string, Netsuite_Mapping__mdt>> ns_Map = nsService.getNSDefaultMap();

    map<string, object> objMap = new map<string, object>();

    for(Netsuite_Master_Map_Definition__mdt mapSource : [select Id,

    MasterLabel,

    Netsuite_Master_Map__c,

    Netsuite_Master_Map__r.MasterLabel,

    Netsuite_Field__c,

    Salesforce_Value__c ,

    Salesforce_Value_type__c

    from Netsuite_Master_Map_Definition__mdt

    where Netsuite_Master_Map__r.Apex_Class_Name__c = 'netsuite_CustomerMap']) {

    if('Literal' == mapSource.Salesforce_Value_type__c)

    objMap.put(mapSource.Netsuite_Field__c, mapSource.Salesforce_Value__c);

    else

    objMap.put(mapSource.Netsuite_Field__c, sobj.get(mapSource.Salesforce_Value__c));

    }

    return objMap;

    }

    }

    Please note that you should keep only the fieldName in the Salesforce_Value__c. For instance, the Salesforce_Value__c should be 'Name' and not 'acc.Name' for the above code to work.

    Thanks,

    Princy
0/9000