import { DataTable } from "./DataTable" ; import { Guid } from "./Guid" ; import { Fetch } from "./Fetch" ; import { AssignRequest , WhoAmIRequest , WhoAmIResponse , RetrieveEntityRequest , RetrieveEntityResponse } from "./Messages" ; import { Entity , EntityReference , OptionSetValue , AttributeTypeCode , EntityFilters , EntityMetadata , AttributeMetadata , BooleanOptionsetMetadata , OptionsetMetadata , Money , Decimal } from "./CRMDataTypes" ; import { ImportExportUtil } from "./ImportExportUtil" ; import { StateUtil } from "./StateUtil" ; import { MetadataUtil } from "./MetadataUtil" ; import path = require ( "path" ) ; import edge = require ( "edge" ) ; var debug = require ( "debug" ) ( "dynamicsnode" ) ; var debugQueries = require ( "debug" ) ( "dynamicsnode:queries" ) ; export class CRMClient { private _crmBridge : any ; classdesc class param { string } connectionString see https for further information
     *
     *  example example example example example constructor ( public connectionString = "default" , fakeBridge = false ) { var config = this . tryGetModule ( path . join ( process . cwd ( ) , "config.json" ) ) ; if ( config && config . connectionStrings && config . connectionStrings [ connectionString ] ) { this . connectionString = config . connectionStrings [ connectionString ] ; } this . _crmBridge = this . getBridge ( fakeBridge ) ; this . testConnection ( ) ; } private method param fakeBridge { boolean } returns private getBridge ( fakeBridge ) { var assemblyFile = path . join ( __dirname , "bin/DynamicsNode.dll" ) ; var createBridge = edge . func ( { assemblyFile : assemblyFile } ) ; var bridge = createBridge ( { connectionString : this . connectionString , useFake : fakeBridge } , true ) ; return bridge ; } private tryGetModule ( moduleId ) { var result = null ; try { result = require ( moduleId ) ; } catch ( e ) { } return result ; } private convert ( propertiesArray ) { var converted = null ; if ( propertiesArray ) { converted = { } ; for ( var i = 0 ; i < propertiesArray . length ; i ++ ) { var propValue = propertiesArray [ i ] ; if ( propValue [ 1 ] instanceof Array ) { var convertedValues = [ ] ; for ( var j = 0 ; i < propValue [ 1 ] . length ; i ++ ) { var arrayItem = propValue [ 1 ] [ j ] ; convertedValues . push ( this . convert ( arrayItem ) ) ; } converted [ propValue [ 0 ] ] = convertedValues ; } else { converted [ propValue [ 0 ] ] = propValue [ 1 ] ; } } } return converted ; } returns a  WhoAmIResponse object with the information about the authenticated user in CRM.
    *  method example whoAmI ( ) { var request = new WhoAmIRequest ( ) ; var response = this . Execute ( request ) ; return response ; } /**
     * Tests the active connection. Throws an exception if there's any error.
     * The method performs a  WhoAmIRequest .
     *  method see CRMClient testConnection ( ) { try { this . whoAmI ( ) ; } catch ( e ) { var error = new Error ( ) ; throw new Error ( "Error trying to connect to server\n" + JSON . stringify ( e ) ) ; } } method param entityName { string } param idOrConditions { string | Guid | object } Either a string with the GUID if the record to be retrieved, a  Guid object with the same value, or a conditions object that returns only one record.
     * Learn how to write condition objects:  Fetch param attributes { string | string [ ] | boolean } returns example example example example example example example example retrieve ( entityName , idOrConditions , pColumns ? ) { var idValue ; var result ; var columns ; if ( ! entityName ) throw new Error ( "Entity name not specified" ) ; if ( ! idOrConditions ) throw new Error ( "Id or Conditions not specified" ) ; entityName = entityName . toLocaleLowerCase ( ) ; if ( pColumns === undefined ) { columns = true ; } else { columns = pColumns ; if ( typeof pColumns == "string" ) { columns = [ pColumns ] ; } if ( Array . isArray ( columns ) ) { for ( var i = 0 ; i < columns . length ; i ++ ) { columns [ i ] = columns [ i ] . toLocaleLowerCase ( ) ; } } } if ( idOrConditions instanceof Guid ) { idValue = idOrConditions . getValue ( ) ; } else if ( typeof idOrConditions === "string" || idOrConditions instanceof String ) { idValue = < string > idOrConditions ; if ( ! Guid . isGuid ( idValue ) ) throw new Error ( "Invalid GUID value" ) ; } else if ( typeof idOrConditions === "object" ) { var idField = this . getIdField ( entityName ) ; var foundRecords = this . retrieveMultiple ( entityName , idOrConditions , idField ) ; if ( foundRecords . rows !== null ) { if ( foundRecords . rows . length > 1 ) throw new Error ( "Too many records found matching the specified criteria" ) ; if ( foundRecords . rows . length > 0 ) { idValue = foundRecords . rows [ 0 ] [ idField ] ; } } } else { throw new Error ( "invalid idOrConditions type value" ) ; } if ( idValue ) { var params = { entityName : entityName , id : idValue , columns : columns } ; var retrieveResult ; try { retrieveResult = this . _crmBridge . Retrieve ( params , true ) ; } catch ( ex ) { var rethrow = false ; if ( ex . Detail && ex . Detail . InnerFault && ex . Detail . InnerFault . Message ) { var msg = `${ entityName } With Id = ${ idValue . toLowerCase ( ) . replace ( "{" , "" ) . replace ( "}" , "" ) } Does Not Exist` ; if ( ex . Detail . InnerFault . Message != msg ) rethrow = true ; } if ( rethrow ) throw ex ; } if ( retrieveResult != null ) { result = this . convert ( retrieveResult ) ; } } return result ; } retrieveMultiple ( fetchXml ) ; retrieveMultiple ( entityName , conditions ? , attributes ? ) ; method param entityNameOrFetchXml { string } Name of the entity or Fetch Xml query to specify the records to be retrieved. More info:  https param conditions { object } Optional. In case you don't want to write a FetchXml to specify the records to retrieve, you can use a conditions object to specify the criteria to retrieve records. If you omit this parameter, all the existing records of the specified entity will be retrieved; omitting this parameter is equivalent to write a FetchXml without any filter conditions.
     * Learn how to write condition objects:  Fetch param attributes { string | string [ ] | boolean } returns { DataTable } DataTable object with the records found.
     *
     *  see Build queries with FetchXML:  https example example example example example retrieveMultiple ( entityNameOrFetchXml , conditions ? , attributes ? ) { var result = new Array < any > ( ) ; var fetchXml ; if ( ! ( conditions || attributes ) ) { fetchXml = entityNameOrFetchXml ; } else { var fetch = new Fetch ( entityNameOrFetchXml ) ; if ( conditions ) { fetch . setFilter ( conditions ) ; } if ( attributes ) { fetch . setAttributes ( attributes ) ; } fetchXml = fetch . toString ( ) ; debugQueries ( fetchXml ) ; } var retrieveResult = this . _crmBridge . RetrieveMultiple ( fetchXml , true ) ; for ( let i = 0 ; i < retrieveResult . length ; i ++ ) { var record = retrieveResult [ i ] ; var convertedRecod = this . convert ( record ) ; result . push ( convertedRecod ) ; } var dt = new DataTable ( entityNameOrFetchXml , result ) ; return dt ; } /** It is a simpified way of retrieving all the existing records of an entity. Is equivalent to call the  CRMClient method not specifying the conditions or attributes method
     *  method param entityName { string } returns { DataTable } DataTable object with the records found.
     *  example retrieveAll ( entityName ) { var fetch = new Fetch ( entityName , "*" ) ; var fetchXml = fetch . toString ( ) ; var result = this . retrieveMultiple ( fetchXml ) ; return result ; } method param entityName { string } param attributes { object } returns { string } create ( entity , attributes ) ; method param entityName { string } param attributes { object } returns { string } create ( data ) ; method param entityName { string } param attributes { object } returns { string } example example method param data { DataTable } example create ( entityNameOrTable , attributes ? ) { var retVal = null ; if ( entityNameOrTable instanceof DataTable ) { if ( entityNameOrTable . name == null ) throw new Error ( "Table name not specified" ) ; debug ( `Preparing to create ${ entityNameOrTable . rows . length } records from a DataTable. Entity ${ entityNameOrTable . name }...` ) ; var primaryAttribute = this . getIdField ( entityNameOrTable . name ) ; debug ( `Primary Attribute:${ primaryAttribute }` ) ; for ( var i = 0 ; i < entityNameOrTable . rows . length ; i ++ ) { debug ( `${ i } of ${ entityNameOrTable . rows . length }...` ) ; var row = entityNameOrTable . rows [ i ] ; var recordId = this . createInternal ( entityNameOrTable . name , row ) ; row [ primaryAttribute ] = recordId ; } } else { if ( attributes === undefined ) throw new Error ( "The attributes parameter is required" ) ; debug ( `Preparing to create a ${ entityNameOrTable } record...` ) ; retVal = this . createInternal ( entityNameOrTable , attributes ) ; } return retVal ; } private createInternal ( entityName , attributes ) { var entity = this . ConvertToEntity ( entityName , attributes ) ; var createdGuid = this . _crmBridge . Create ( entity , true ) ; return createdGuid ; } private ConvertToEntity ( entityName , attributes ) { if ( ! entityName ) throw new Error ( "Entity name not specified" ) ; if ( ! attributes ) throw new Error ( "Attributes not specified" ) ; entityName = entityName . toLocaleLowerCase ( ) ; var entityMetadata = this . getEntityMetadata ( entityName ) ; debug ( "Converting attributes to CRM Entity type..." ) ; var entity = new Entity ( ) ; entity . LogicalName = entityName ; entity . Attributes = { } ; for ( var prop in attributes ) { var attributeValue = null ; var attributeMetadata = MetadataUtil . getAttributeMetadata ( this , entityName , prop . toLocaleLowerCase ( ) ) ; if ( attributeMetadata ) { if ( attributes [ prop ] !== null ) { if ( attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . String ] || attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . Memo ] ) { attributeValue = this . ConvertToString ( prop , attributes [ prop ] ) ; } else if ( attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . DateTime ] ) { attributeValue = this . ConvertToDate ( attributes [ prop ] , attributeMetadata ) ; } else if ( attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . Lookup ] || attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . Customer ] || attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . Owner ] ) { attributeValue = this . ConvertToEntityReference ( attributes [ prop ] , attributeMetadata ) ; } else if ( attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . Picklist ] ) { attributeValue = this . ConvertToOptionset ( attributes [ prop ] , attributeMetadata ) ; } else if ( attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . Boolean ] ) { attributeValue = this . ConvertToBoolean ( attributes [ prop ] , attributeMetadata ) ; } else if ( attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . PartyList ] ) { attributeValue = this . ConvertToPartyList ( attributes [ prop ] , attributeMetadata ) ; } else if ( attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . Money ] ) { attributeValue = this . ConvertToMoney ( prop , attributes [ prop ] ) ; } else if ( attributeMetadata . AttributeType == AttributeTypeCode [ AttributeTypeCode . Decimal ] ) { attributeValue = this . ConvertToDecimal ( prop , attributes [ prop ] ) ; } else { debug ( `Attribute '${ prop }' type '${ attributeMetadata . AttributeType }' not converted. Using the raw value` ) ; attributeValue = attributes [ prop ] ; } } entity . Attributes [ attributeMetadata . LogicalName ] = attributeValue ; } else { console . log ( `*** Attribute '${ prop }' not found in metadata. Skipping...` ) ; } } debug ( `Converted value:` ) ; debug ( entity ) ; return entity ; } private ConvertToDecimal ( attributeName , attributeValue ) { var decimalValue = null ; if ( attributeValue !== null && attributeValue !== undefined ) { if ( typeof attributeValue === "number" ) { decimalValue = new Decimal ( attributeValue ) ; } else { throw new Error ( `Cannot convert attribute '${ attributeName }' value '${ attributeValue }' from '${ typeof attributeValue }' to 'Decimal'` ) ; } } return decimalValue ; } private ConvertToMoney ( attributeName , attributeValue ) { var moneyValue = null ; if ( attributeValue !== null && attributeValue !== undefined ) { if ( typeof attributeValue === "number" ) { moneyValue = new Money ( new Decimal ( attributeValue ) ) ; } else { throw new Error ( `Cannot convert attribute '${ attributeName }' value '${ attributeValue }' from '${ typeof attributeValue }' to 'Money'` ) ; } } return moneyValue ; } private ConvertToString ( attributeName , attributeValue ) { var strValue = null ; if ( attributeValue !== null && attributeValue !== undefined ) { if ( typeof attributeValue === "string" ) { strValue = attributeValue ; } else if ( attributeValue . toString !== undefined && typeof attributeValue . toString === "function" ) { strValue = attributeValue . toString ( ) ; } else { throw new Error ( `Cannot convert attribute '${ attributeName }' value '${ attributeValue }' from '${ typeof attributeValue }' to 'String'` ) ; } } return strValue ; } private ConvertToPartyList ( attributeValue , attributeMetadata ) { var partyList = [ ] ; if ( attributeValue instanceof Array ) { for ( var i = 0 ; i < attributeValue . length ; i ++ ) { var partyItem = attributeValue [ i ] ; var partyItemRecord = { partyid : partyItem } ; var convertedPartyItem = this . ConvertToEntity ( "activityparty" , partyItemRecord ) ; partyList . push ( convertedPartyItem ) ; } } else { throw new Error ( `Cannot convert attribute '${ attributeMetadata . LogicalName }' value '${ attributeValue }' from '${ typeof attributeValue }' to 'ActivityParty'` ) ; } return partyList ; } private ConvertToDate ( attributeValue , attributeMetadata ) { var date = null ; if ( attributeValue instanceof Date ) { date = attributeValue ; } else if ( typeof attributeValue == "string" ) { date = new Date ( attributeValue ) ; } if ( date === null ) throw new Error ( `Cannot convert attribute '${ attributeMetadata . LogicalName }' value '${ attributeValue }' from '${ typeof attributeValue }' to 'Date'` ) ; return date ; } private ConvertToBoolean ( attributeValue , attributeMetadata ) { var boolVal = null ; if ( typeof attributeValue == "boolean" ) { boolVal = attributeValue ; } else if ( typeof attributeValue == "number" ) { if ( attributeValue == 0 ) { boolVal = false ; } else { boolVal = true ; } } else if ( typeof attributeValue == "string" ) { var optionSet = < BooleanOptionsetMetadata > attributeMetadata . OptionSet ; if ( optionSet . TrueOption . Label . UserLocalizedLabel . Label . toLowerCase ( ) == attributeValue . toLowerCase ( ) || attributeValue . toLowerCase ( ) == "yes" ) { boolVal = true ; } else if ( optionSet . FalseOption . Label . UserLocalizedLabel . Label . toLowerCase ( ) == attributeValue . toLowerCase ( ) || attributeValue . toLowerCase ( ) == "no" ) { boolVal = false ; } } if ( boolVal == null ) { throw new Error ( `Can't convert attribute '${ attributeMetadata . LogicalName }' value '${ attributeValue }' from '${ typeof attributeValue }' to Boolean` ) ; } return boolVal ; } private ConvertToOptionset ( attributeValue , attributeMetadata ) { var optionSet = null ; if ( typeof attributeValue == "number" ) { optionSet = new OptionSetValue ( attributeValue ) ; } if ( typeof attributeValue == "string" ) { var optionSetMetadata = < OptionsetMetadata > attributeMetadata . OptionSet ; for ( var i = 0 ; i < optionSetMetadata . Options . length ; i ++ ) { var option = optionSetMetadata . Options [ i ] ; if ( option . Label . UserLocalizedLabel . Label . toLowerCase ( ) == attributeValue . toLowerCase ( ) ) { optionSet = new OptionSetValue ( option . Value ) ; break ; } } } if ( optionSet == null ) { throw new Error ( `Can't convert attribute '${ attributeMetadata . LogicalName }' value '${ attributeValue }' from '${ typeof attributeValue }' to OptionsetValue` ) ; } return optionSet ; } private ConvertToEntityReference ( attributeValue , attributeMetadata ) { var er = null ; var target = null , id = null ; if ( typeof attributeValue == "string" ) { if ( attributeMetadata . Targets . length > 1 ) throw new Error ( `Couldn't get a valid target for attribute '${ attributeMetadata . LogicalName }'. Please specify a valid target using {id:string,type:string}` ) ; target = attributeMetadata . Targets [ 0 ] ; id = attributeValue ; } else if ( typeof attributeValue == "object" ) { id = attributeValue . id ; target = attributeValue . type ; } if ( ! ( target && id ) ) throw new Error ( `Couldn't get a valid EntityReference value for attribute '${ attributeMetadata . LogicalName }'. Please specify a valid target using {id:string,type:string}` ) ; er = new EntityReference ( id , target ) ; return er ; } method param entityName { string } param idsOrConditions { string | Guid | string [ ] | object } Can be either a Guid, a string, an array or a conditions object.
     * If it is Guid will delete the record with the specified id.
     * If it is a string, must be a Guid value, and again, will delete the records matching the specified id.
     * If the parameter is an array, each element in it must be either a string or a Guid, and in each case, the records deleted will be the ones specified by these Guids.
     * If it is a condition object, first, all the matching records will be retrieved, and then deleted.
     * Learn how to write condition objects:  Fetch returns { number } example example example example delete ( entityName , idsOrConditions ) { var ids ; var recordsAffected = 0 ; if ( ! entityName ) throw new Error ( "Entity name not specified" ) ; entityName = entityName . toLowerCase ( ) ; if ( idsOrConditions instanceof Guid ) { ids = [ idsOrConditions . getValue ( ) ] ; } else if ( typeof idsOrConditions == "string" ) { if ( ! Guid . isGuid ( idsOrConditions ) ) throw new Error ( "Invalid GUID value" ) ; ids = [ idsOrConditions ] ; } else if ( Array . isArray ( ids ) ) { for ( var i = 0 ; i < ids . length ; i ++ ) { var item = ids [ i ] ; if ( ! ( item instanceof Guid ) || Guid . isGuid ( item ) ) { throw new Error ( "Invalid GUID" ) ; } } ids = idsOrConditions ; } else if ( typeof idsOrConditions == "object" && ! ( idsOrConditions instanceof Date ) ) { var idField = this . getIdField ( entityName ) ; var foundRecords = this . retrieveMultiple ( entityName , idsOrConditions , idField ) ; ids = [ ] ; for ( var i = 0 ; i < foundRecords . rows . length ; i ++ ) { ids . push ( foundRecords . rows [ i ] [ idField ] ) ; } } recordsAffected = this . deleteMultiple ( entityName , ids ) ; return recordsAffected ; } private deleteMultiple ( entityName , ids ) { var recordsAffected = 0 ; for ( var i = 0 ; i < ids . length ; i ++ ) { var params = { entityName : entityName , id : ids [ i ] } ; this . _crmBridge . Delete ( params , true ) ; recordsAffected ++ ; } return recordsAffected ; } method param entityName { string } param attributes { object } param conditions { opbject } Optional. Javascript condition object with the filter values that is going to be used to know which records are going to be updated.
     * If you omit this parameter, then you have to provide the record GUID in the attributes parameter.
     * Learn how to write condition objects:  Fetch returns { number } example example update ( entityName , attributes , conditions ? ) { var updatedRecordsCount = 0 ; if ( ! entityName ) throw new Error ( "Entity name not specified" ) ; entityName = entityName . toLowerCase ( ) ; debug ( "Preparing to update a record..." ) ; if ( conditions != undefined ) { var idField = this . getIdField ( entityName ) ; debug ( "Conditions specified. Trying to find which records that meets conditions to update..." ) ; var foundRecords = this . retrieveMultiple ( entityName , conditions , idField ) ; debug ( `${ foundRecords . rows . length } records found` ) ; for ( var i = 0 ; i < foundRecords . rows . length ; i ++ ) { debug ( `updating ${ i } of ${ foundRecords . rows . length }` ) ; var foundRecordId = foundRecords . rows [ i ] [ idField ] ; attributes [ idField ] = foundRecordId ; var entity = this . ConvertToEntity ( entityName , attributes ) ; this . _crmBridge . Update ( entity , true ) ; } updatedRecordsCount = foundRecords . rows . length ; } else { var entity = this . ConvertToEntity ( entityName , attributes ) ; this . _crmBridge . Update ( entity , true ) ; updatedRecordsCount = 1 ; } return updatedRecordsCount ; } getIdField ( entityName ) { var idAttr = null ; var metadata = this . getEntityMetadata ( entityName ) ; if ( metadata ) { idAttr = metadata . PrimaryIdAttribute ; } if ( idAttr == null ) throw new Error ( `Primary Attribute not found for entity ${ entityName }` ) ; debug ( `idAttr for entity '${ entityName }': '${ idAttr }'` ) ; return idAttr . toLowerCase ( ) ; } method param entityName { string } param attributes { object } param matchFields { string [ ] } List of fields in the attributes parameter you want to use to know if the record exists in CRM.
     * The attributes specified in this parameter will be used to perform a  CRMClient .
     *  example example createOrUpdate ( entityName , attributes , matchFields ) { this . createUpdate ( entityName , attributes , matchFields ) ; } method param data { DataTable } param matchFields { string [ ] } List of fields in the attributes parameter you want to use to know if the record exists in CRM.
     * The attributes specified in this parameter will be used to perform a  CRMClient .
     *  example createIfDoesNotExist ( data , matchFields ) ; method param entityName { string } param attributes { object } param matchFields { string [ ] } List of fields in the attributes parameter you want to use to know if the record exists in CRM.
     * The attributes specified in this parameter will be used to perform a  CRMClient .
     *  example example createIfDoesNotExist ( entityName , attributes , matchFields ) ; method param data { DataTable } param matchFields { string [ ] } List of fields in the attributes parameter you want to use to know if the record exists in CRM.
     * The attributes specified in this parameter will be used to perform a  CRMClient .
     *  example method param entityName { string } param attributes { object } param matchFields { string [ ] } List of fields in the attributes parameter you want to use to know if the record exists in CRM.
     * The attributes specified in this parameter will be used to perform a  CRMClient .
     *  example example createIfDoesNotExist ( entityNameOrDataTable , attributesOrMatchfields , matchFields ? ) { if ( entityNameOrDataTable instanceof DataTable ) { var data = entityNameOrDataTable ; if ( data === undefined || data === null ) throw new Error ( "DataTable not specified" ) ; if ( data . name === undefined || data . name === null ) throw new Error ( "DataTable name not specified" ) ; if ( ! Array . isArray ( attributesOrMatchfields ) ) throw new Error ( "Wrong data type for the matchFields parameter" ) ; var matchFields = attributesOrMatchfields ; debug ( `About to create if does not exits ${ data . rows . length } records from a DataTable...` ) ; for ( var i = 0 ; i < data . rows . length ; i ++ ) { debug ( `${ i } of ${ data . rows . length }...` ) ; this . createUpdate ( data . name , data . rows [ i ] , matchFields , false ) ; } } else { if ( matchFields === undefined || matchFields === null ) throw new Error ( "matchFields not specified" ) ; this . createUpdate ( entityNameOrDataTable , attributesOrMatchfields , matchFields , false ) ; } } private createUpdate ( entityName , attributes , matchFields , update = true ) { var idField = this . getIdField ( entityName ) ; var conditions = { } ; debug ( "About to create or update a record..." ) ; for ( var i = 0 ; i < matchFields . length ; i ++ ) { var matchField = matchFields [ i ] ; debug ( "Preparing query to know if the record exists..." ) ; var attr = MetadataUtil . getAttributeMetadata ( this , entityName , matchField ) ; if ( attr === null ) throw new Error ( `Attribute '${ matchField }' not found in entity ${ entityName }` ) ; if ( attributes [ matchField ] !== undefined && attributes [ matchField ] !== null ) { conditions [ attr . LogicalName ] = attributes [ matchField ] ; } } var foundRecords = this . retrieveMultiple ( entityName , conditions , idField ) ; if ( foundRecords && foundRecords . rows . length > 0 ) { debug ( `${ foundRecords . rows . length } '${ entityName }' records found` ) ; if ( update ) { if ( foundRecords . rows . length > 1 ) throw new Error ( "Too many records found" ) ; var foundRecord = foundRecords . rows [ 0 ] ; attributes [ idField ] = foundRecord [ idField ] ; this . update ( entityName , attributes ) ; } } else { debug ( "The record doesn't exists. Create it" ) ; this . create ( entityName , attributes ) ; } } /** */ associateData ( data ) { for ( var i = 0 ; i < data . rows . length ; i ++ ) { var row = data . rows [ i ] ; this . associate ( row . from . type , row . from . value , data . name , row . to . type , row . to . value ) ; } } associate ( fromEntityName , fromEntityId , relationshipName , toEntityName , toEntityId ) { if ( ! fromEntityName ) throw new Error ( "From entity name not specified" ) ; fromEntityName = fromEntityName . toLowerCase ( ) ; if ( ! toEntityName ) throw new Error ( "To entity name not specified" ) ; toEntityName = toEntityName . toLowerCase ( ) ; if ( ! fromEntityId ) throw new Error ( "fromEntityId not specified" ) ; if ( ! toEntityId ) throw new Error ( "toEntityId not specified" ) ; var fromId , toId ; if ( fromEntityId instanceof Guid ) { fromId = fromEntityId . getValue ( ) ; } else { fromId = < string > fromEntityId ; } if ( toEntityId instanceof Guid ) { toId = toEntityId . getValue ( ) ; } else { toId = < string > toEntityId ; } var params = { entityName : fromEntityName , entityId : fromId , relationship : relationshipName , relatedEntities : [ { entityName : toEntityName , entityId : toId } ] } ; this . _crmBridge . Associate ( params , true ) ; } disassociateData ( data ) { for ( var i = 0 ; i < data . rows . length ; i ++ ) { var row = data . rows [ i ] ; this . disassociate ( row . from . type , row . from . value , data . name , row . to . type , row . to . value ) ; } } disassociate ( fromEntityName , fromEntityId , relationshipName , toEntityName , toEntityId ) { if ( ! fromEntityName ) throw new Error ( "From entity name not specified" ) ; fromEntityName = fromEntityName . toLowerCase ( ) ; if ( ! toEntityName ) throw new Error ( "To entity name not specified" ) ; toEntityName = toEntityName . toLowerCase ( ) ; if ( ! fromEntityId ) throw new Error ( "fromEntityId not specified" ) ; if ( ! toEntityId ) throw new Error ( "toEntityId not specified" ) ; var fromId , toId ; if ( fromEntityId instanceof Guid ) { fromId = fromEntityId . getValue ( ) ; } else { fromId = < string > fromEntityId ; } if ( toEntityId instanceof Guid ) { toId = toEntityId . getValue ( ) ; } else { toId = < string > toEntityId ; } var params = { entityName : fromEntityName , entityId : fromId , relationship : relationshipName , relatedEntities : [ { entityName : toEntityName , entityId : toId } ] } ; this . _crmBridge . Disassociate ( params , true ) ; } method param entityName { string } example getEntityMetadata ( entityName ) { return MetadataUtil . getEntityMetadata ( this , entityName ) ; } public Execute ( request ) { var response = this . _crmBridge . Execute ( request , true ) ; return response ; } public assign ( targetId , targetType , assigneeId , assigneeType ? ) { if ( assigneeType === undefined ) assigneeType = "systemuser" ; var request = new AssignRequest ( ) ; request . Assignee = new EntityReference ( assigneeId . toString ( ) , assigneeType ) ; request . Target = new EntityReference ( targetId . toString ( ) , targetType ) ; var response = this . Execute ( request ) ; } export ( entityName , fileName ) { ImportExportUtil . export ( this , entityName , fileName ) ; } import ( fileName ) { ImportExportUtil . import ( this , fileName ) ; } method param entityName { string } param entityId { Guid | string } param state { number | string } param status { number | string } example example setState ( entityName , entityId , state , status ) { StateUtil . setState ( this , entityName , entityId , state , status ) ; } }