Search code examples
javascriptgoogle-apps-scriptgoogle-people-api

Add a userDefined field to a Person from a Google Apps Script


UPDATE After help from Tanaike and much playing around, I wrote the following functions to assist with writing a userDefined field specified by key. Maybe they'll be useful to someone. Feel free to tell me how they could be improved.

Next I'm going to try to modify this to work with the Person.externalID fields instead.

/**
 * Writes a userDefined field to a Person based on the key:
 *  If the Person has no userDefined fields, add a field.
 *  If they have some, search for the key and overwrite the value.
 *  If they have some and the key doesn't exist, add a field.
 *  If multiple fields with the key exist, display a warning dialog and exit.
 * @param {People.Person} person
 * @param {userDefined} People.person.userDefined
 */
function writeUserDefined(person, newUserDefinedValue){
  let resource;
  if (!person.userDefined)
  {
    Logger.log("   no keys exists");
    Logger.log("   adding new userDefined resource");  
    resource = {
      userDefined: [newUserDefinedValue],
      etag: person.etag
    };
  }
  else if(person.userDefined)
  {
    //if key exists
    index = getIndexUserDefined(person, newUserDefinedValue.key);
    if(index >= 0){
      Logger.log("   key exists");
      Logger.log("   modifying existing field at " + index);
      person.userDefined[index] = newUserDefinedValue;
      resource = person;
    }

    //if key doesn't exist
    else if (index === -1) {
      Logger.log("   key doesn't exist");
      Logger.log("   adding key to end" + index);
      resource = {
        userDefined: [...person.userDefined, newUserDefinedValue],
        etag: person.etag
      };
    }

    //multiple matching keys exist
    else if (index === -2) {
      Logger.log("   multiple keys exist");
      Logger.log("   displaying warning dialog" + index);
      resource = person;
      showMultipleCustomerIDsAlert(person.names[0].displayName);

    }
  }
  else { Logger.log("nothingburger"); return; }
  People.People.updateContact(resource, person.resourceName, 
                            { updatePersonFields: "userDefined" });
}

/**
 * Finds the index in person.userDefined[] of a field containing a specified key
 *  If no userDefined field with the key exists, returns -1
 *  If multiple fields with the key exists, returns -2
 *  Otherwise returns the index of the field with the key.
 * @param {People.person} person
 * @param {String} key
 * @return {Number} getIndexUserDefined
 */
function getIndexUserDefined(person,key){
  let index = -1;
  for(i=0; i < person.userDefined.length; i++){
    if( person.userDefined[i].key === key && index > -1 ){ 
      return -2; 
    }
    else if( person.userDefined[i].key === key && index == -1 ){
      index = i;
    }
  }
  return index;
}

ORIGINAL POST

I'm trying to use People.userDefined to store an ID number for contacts. However, unless a custom field has already been added from the Contacts app, I'm unable to add one in a script.

This works fine for a contact that already has a custom field created in the app:

let query = "Joe Smith"; 
var found = People.People.searchContacts(
  { 
    "query": query,   
    "readMask": "names,userDefined"
  }); 
thisResult = found.results[0];     
thisResult.person.userDefined[1].key = "HandymanCustID"; 
thisResult.person.userDefined[1].value = "0066"; 
People.People.updateContact(thisResult.person, thisResult.person.resourceName, 
                            {updatePersonFields: "userDefined"});

But if the contact hasn't yet had a custom field created, it fails. I tried this:

var uDef = new People.newUserDefined();
thisResult.person.userDefined.push(uDef);
thisResult.person.clientData[0].key ="HandymanCustID";
thisResult.person.clientData[0].value = "0066";

The push operation fails. Is this possible to do? I really just want to be able to assign my own ID# to each client.


Solution

  • Modification points:

    • I thought that about But if the contact hasn't yet had a custom field created, it fails. I tried this:, in this case, the property of userDefined does not exist. I thought that this might be the reason for your current issue.

    In this case, how about modifying it as follows?

    Modified script:

    let query = "Joe Smith"; 
    var found = People.People.searchContacts(
      { 
        "query": query,   
        "readMask": "names,userDefined"
      }); 
    thisResult = found.results[0];
    
    // I modified the below script.
    var newUserDefinedValue = { key: "HandymanCustID", value: "0066" }; // This is from your script.
    var resource = {
      userDefined: [...(thisResult.person.userDefined || []), newUserDefinedValue],
      etag: thisResult.person.etag
    };
    People.People.updateContact(resource, thisResult.person.resourceName, { updatePersonFields: "userDefined" });
    
    • In this modification, when userDefined is existing, the new value of newUserDefinedValue is added to userDefined. On the other hand, when userDefined does not exist, the new value of newUserDefinedValue is created to userDefined.

    Reference: