import CrmEnv from './crm-env.mjs'; import RemoteAPI from './remote-api.mjs'; import WsObject from './ws-objects/ws-object.mjs'; import ConsultObject from './remote-objects/consult.mjs'; import EditObject from './remote-objects/edit.mjs'; import EditRelationObject from './remote-objects/edit-relation.mjs'; import SearchObject from './remote-objects/search.mjs'; import {DeleteEntity, CollectionObject} from './remote-objects/api.mjs'; import DataSetObject from './remote-objects/dataset/dataset-object.mjs'; import QueryObject from './remote-objects/dataset/query.mjs'; import QuerySQLObject from './remote-objects/dataset/query-sql.mjs'; import ConsultManyEx from './remote-objects/dataset/consult-many-ex.mjs'; import RecentList from './remote-objects/dataset/recent-list.mjs'; import FavoriteList from './remote-objects/dataset/favorite-list.mjs'; import UserList from './remote-objects/dataset/user-list.mjs'; import ContactsList from './remote-objects/dataset/contacts-list.mjs'; import ListObject from './remote-objects/list/list-object.mjs'; import SystemSettings from './remote-objects/list/system-settings.mjs'; import StringObject from './remote-objects/base-type/string-object.mjs'; import SettingObject from './remote-objects/base-type/setting-object.mjs'; import PropertyObject from './remote-objects/base-type/property-object.mjs'; /** * Class to create Remote Objects * @extends RemoteAPI */ class CrmRpc extends RemoteAPI { /** * Construct a CrmRpc object * @param {CrmEnv} [crmEnv=undefined] - When empty, uses the Efficy context of the browser * @param {function} [logFunction=undefined] - Your (custom) log function to call for requests and responses, e.g. console.log * @param {number} [threadId=undefined] - Unique thread ID for logging purposes * @example * function logger(msg, reqLog) { * console.log(msg); * } * const crm = new CrmRpc(crmEnv, logger); */ constructor(crmEnv, logFunction, threadId) { super(crmEnv, logFunction, threadId); } /** * Execute all assembled and queued RPC operations */ async executeBatch() { return super.executeBatch(); } /** * Logoff the remote session */ logoff() { return super.logoff(); } /** * Retrieves the alias (name) of the currently connected database * @returns {PropertyObject} */ get currentDatabaseAlias() { return new PropertyObject(this, "currentdatabasealias"); } /** * Retrieves the current database timezone * @returns {PropertyObject} */ get currentDatabaseTimezone() { return new PropertyObject(this, "currentdatabasetimezone"); } /** * Retrieves the current license name * @returns {PropertyObject} */ get currentLicenseName() { return new PropertyObject(this, "currentlicensename"); } /** * Retrieves the current user full name * @returns {PropertyObject} */ get currentUserFullName() { return new PropertyObject(this, "currentuserfullname"); } /** * Retrieves the group memberships of the current user as semicolon separated string list, e.g. "1;28;292;936" * @returns {PropertyObject} */ get currentUserGroups() { return new PropertyObject(this, "currentusergroups"); } /** * Retrieves the current user key, e.g. "4" * @returns {PropertyObject} */ get currentUserId() { return new PropertyObject(this, "currentuserid"); } /** * Retrieves the current user code, e.g. "CRM01" * @returns {PropertyObject} */ get currentUserCode() { return new PropertyObject(this, "currentusername"); } /** * Retrieves the current user timezone * @returns {PropertyObject} */ get currentUserTimezone() { return new PropertyObject(this, "currentusertimezone"); } /** * Opens a consult context for the record identified by entity and key. * A context remains memory-resident (on the web server) until it is closed. Always match with a closeContext() call to avoid memory consumption. * @param {string} entity - The entity name, e.g. "Comp" * @param {number} key - The key of the record. Use key = 0 to create a new record. * @returns {ConsultObject} * @example * const comp = crm.openConsultObject("comp", 2); * const dsComp = comp.getMasterDataSet(); * const dsCompAddress = comp.getCategoryDataSet("COMP$ADDRESS"); * const linkedContacts = comp.getDetailDataSet("cont"); * await crm.executeBatch(); * const companyNames = [comp.data.master.NAME, comp.data.category["COMP$ADDRESS"].NAME]; * comp.closeContext(); * await crm.executeBatch(); */ openConsultObject(entity, key) { return new ConsultObject(this, entity, key); } /** * Create and return an ConsultObject based on an existing consultHandle * @param {number} consultHandle * @param {string} entity - Weird, but the RPC interface requires the entity of the consultHandle! */ getConsultObject(consultHandle, entity) { return new ConsultObject(this, entity, 0, consultHandle); } /** * Opens an edit context for the record identified by entity and key. * A context remains memory-resident (on the web server) until it is closed. Always match with a closeContext() call to avoid memory consumption. * @param {string} entity - The entity name, e.g. "Comp" * @param {number} [key=0] - The key of the record. Use key = 0 to create a new record. * @returns {EditObject} * @example * const docu = crm.openEditObject("docu", 0); * docu.updateField("NAME", "Jan"); * docu.insertDetail("Comp", 2); * docu.insertDetail("Cont", 44395, true, true); * docu.commitChanges(); * docu.activateCategory("DOCU$INVOICING"); * docu.updateCategoryFields("DOCU$INVOICING", { * "D_INVOICE":"2021-01-08T00:00:00", * "COMMUNICATION": "Hello World!" * }); * docu.updateCategoryField("DOCU$INVOICING", "PRE_PAID", 123.456) * docu.clearDetail("Comp"); * docu.insertDetail("Comp", 4); * docu.insertDetail("Cont", 50512, false); * docu.insertDetail("Prod", 4); * docu.updateDetail("Prod", 0, { * QUANTITY: 5 * }); * docu.setUsers([169, 170], true); * docu.setUserSecurity(99999002, 271); * docu.setReference(99999001); * docu.commitChanges(); * docu.closeContext(); * await crm.executeBatch(); */ openEditObject(entity, key = 0) { return new EditObject(this, 0, entity, key); } /** * Opens an edit context for a relation. If the relation does not yet exist, it is created. * A context remains memory-resident (on the web server) until it is closed. Always match with a closeContext() call to avoid memory consumption. * @param {string} entity - The entity name, e.g. "Comp" * @param {string} detail - The detail name, e.g. "Cont" * @param {number} key - The key of the entity * @param {number} detailKey - The key of the detail * @param {number} [relationId] - The key of the relation if multi-relation is available * @returns {EditRelationObject} * @example * const contCont = crm.openEditRelationObject("cont", "cont", 5, 6); * contCont.updateField("RELATION", 1); * contCont.updateReciprocityField("RELATION", 2); * contCont.commitChanges(); * const dsContCont = contCont.getMasterDataSet(); * const dsContCont1 = contCont.getMasterDataSet(1); * await crm.executeBatch(); * console.log(dsContCont.item["R_RELATION"]); * console.log(dsContCont1.item["R_RELATION"]); * contCont.closingCommit(); * await crm.executeBatch(); */ openEditRelationObject(entity, detail, key, detailKey, relationId) { return new EditRelationObject(this, 0, entity, detail, key, detailKey, relationId); } /** * Create and return an EditObject based on an existing editHandle * @param {number} editHandle */ getEditObject(editHandle) { return new EditObject(this, editHandle, "", 0); } /** * Create and return an EditObject based on an existing editHandle * @param {number} editHandle */ getEditRelationObject(editHandle) { return new EditRelationObject(this, editHandle, "", "", 0, 0); } /** * Performs a search on the database and returns the data set with search results. * @param {string} entity - The entity name, e.g. "Comp" * @param {string} method - The field to be searched. Special values SEARCHFAST, SEARCHFULL, SEARCHTEXT, SEARCHFILENAME, SEARCHFILE correspond to the search options in the web application user interface * @param {string} value - The value to search * @param {boolean} [own=false] - If true, search own records only. * @param {boolean} [contains=true] - If true, allow matches on part of field * @param {boolean} [opened=true] - If true, search for opened or active records only * @returns {DataSetObject} * @example * const compSearch = crm.search("comp", "SEARCHFAST", "Efficy"); */ search(entity, method, value, own = false, contains = true, opened = true) { return new SearchObject(this, entity, method, value, own, contains, opened); } /** * Returns all the Contacts having one of the e-mail provided in their e-mail fields (or in the Cont_Comp relation). * @param {Array<string>} recipients - The list of email addresses * @returns {DataSetObject} * @example * const contactsByEmail = crm.searchContactsByEmail(["john.doe@efficy.com", "john.doe@outlook.com"]); */ searchContactsByEmail(recipients) { if (!Array.isArray(recipients) || recipients.length < 1) throw TypeError("recipients is not a array with at least one item"); return new ContactsList(this, recipients); } /** * Returns all the first Contacts having a match with the provided (formatted) phone number * @param {string} phoneNumber - The phone number, doesn't have to be stripped from formatting * @returns {DataSetObject} * @example * const contactsByPhone = crm.searchContactsByPhone("+32 474 00 00 00"); */ searchContactsByPhone(phoneNumber) { return new ContactsList(this, undefined, phoneNumber); } /** * Executes a database query stored in QUERIES * @param {number} idQuery * @param {array} [queryParameters] - The query parameters delivered via a JS Array * @param {boolean} [loadBlobs=false] - If true, blob fields (e.g. memo, stream) are returned * @param {number} [recordCount=0] - If 0, return all records * @returns {DataSetObject} * @example * const tags = crm.executeDatabaseQuery(99990034); // Query "Standard: Top company tags" */ executeDatabaseQuery(idQuery, queryParameters, loadBlobs = false, recordCount = 0) { return new QueryObject(this, idQuery, null, null, queryParameters, loadBlobs, recordCount); } /** * Executes a system database query stored in SYS_QUERIES * @param {number} master * @param {number} detail * @param {array} queryParameters - The query parameters delivered via a JS Array * @param {boolean} [loadBlobs=false] - If true, blob fields (e.g. memo, stream) are returned * @param {number} [recordCount=0] - If 0, return all records * @returns {DataSetObject} * @example * const contDupls = crm.executeSystemQuery(4, 1, [11000,2]); // System query "Own Duplicate List" */ executeSystemQuery(master, detail, queryParameters, loadBlobs = false, recordCount = 0) { // @ts-ignore return new QueryObject(this, null, master, detail, queryParameters, loadBlobs, recordCount); } /** * Runs a native (SQL) database query, only if the user has SQL Exec the permissions! * @param {string} sqlQueryText - The SQL query text * @param {array} queryParameters - The query parameters delivered via a JS Array * @param {boolean} [loadBlobs=false] - If true, blob fields (e.g. memo, stream) are returned * @param {number} [recordCount] - Limit the returned records * @returns {DataSetObject} * @example * const appos = crm.executeSqlQuery("Select * from ACTIONS where PLANNED=:p1 and DONE=:p2", ["1", "0"], true, 2); */ executeSqlQuery(sqlQueryText, queryParameters, loadBlobs = false, recordCount = 0) { // @ts-ignore return new QuerySQLObject(this, sqlQueryText, queryParameters, loadBlobs, recordCount); } /** * Selects records that exactly match certain field values * @param {string} entity - The entity name, e.g. "Comp" * @param {array} whereFields - A list of field names to match (used as WHERE criteria), e.g. ["NAME", "OPENED"] * @param {array} whereValues - A list of values to match, e.g. ["Efficy", "1"] * @param {string} orderByExpression - SQL sort expression, e.g. "K_COMPANY desc" * @returns {DataSetObject} * @example * const morningMeetings = crm.consultManyEx("Acti", ["PLANNED", "D_BEGIN"], ["1", "2022-03-14 09:00:00"], "D_BEGIN"); */ consultManyEx(entity, whereFields, whereValues, orderByExpression) { return new ConsultManyEx(this, entity, whereFields, whereValues, orderByExpression); } /** * Consult your recent records, optionally extended by additional fields. * @param {string} entity - The entity name, e.g. "Comp" * @param {array} [extraFields=[]] - A list of extra fields to consult for each recent entity record, e.g. ["POSTCODE", "CITY"] * @returns {DataSetObject} * @example * const compRecents = crm.consultRecent("Comp"); * const compRecentsEx = crm.consultRecent("Comp", ["CITY", "COUNTRY"]); */ consultRecent(entity, extraFields = []) { return new RecentList(this, entity, extraFields); } /** * Consult your favorite records. * @param {string} entity - The entity name, e.g. "Comp" * @returns {DataSetObject} * @example * const compFavorites = crm.consultFavorites("Comp"); */ consultFavorites(entity) { return new FavoriteList(this, entity); } /** * Request the accessible categories - for the current user - of the given entity * @param {string} entity - The entity name, e.g. "Comp" * @returns {DataSetObject} * @example * const compCategories = crm.getCategoryCollection("comp"); */ getCategoryCollection(entity) { const detail = ""; return new CollectionObject(this, entity, detail); } /** * Requests a list of users, groups and resources * @returns {DataSetObject} * @example * const userList = crm.getUserList(); */ getUserList() { return new UserList(this); } /** * Request a list of system settings. Use the Map object to retrieve settings * @returns {ListObject} * @example * const settings = crm.getSystemSettings(); * await crm.executeBatch(); * settings.map.get("ShortDateFormat"); // e.g. "dd/mm/yyyy" * settings.map.forEach(console.log); // prints each setting on console */ getSystemSettings() { return new SystemSettings(this); } /** * Requests the current value of a given Efficy setting. * @param {string} module - The name of the setting. * @param {string} name - The name of the module (JSON object) that owns the setting. * @param {boolean} [asString=true] - If true, the settings of type TDateTime will be returned as a string formatted with the ShortDateTime format. If false, it will be returned as a float value. * @returns {StringObject} * @example * const workingPeriodFrom = crm.getSetting("user", "WorkingPeriodFrom"); * const workingPeriodFromFloat = crm.getSetting("user", "WorkingPeriodFrom", false); * await crm.executeBatch(); * workingPeriodFrom.result; // e.g. "30/12/1899 08:00" * workingPeriodFromFloat.result; // e.g. "0.333333333333333 */ getSetting(module, name, asString = true) { return new SettingObject(this, module, name, asString); } /** * Deletes records * @param {string} entity - The entity name, e.g. "Comp" * @param {number|number[]} keys - List of keys */ deleteEntity(entity, keys) { if (!keys || (Array.isArray(keys) && keys.length === 0)) return; new DeleteEntity(this, entity, keys); } /** * Provides access to the methods of a constructed WsObject * Methods are isolated from RemoteObjects because they contain implicit executeBatch() operations * @type {WsObject} */ get ws() { return new WsObject(this); } /** * Efficy Enterprise constants * @readonly * @enum {object} */ constants = { account_kind: { user: 0, group: 1, resource: 2, team: 3 }, file_type: { embedded: 1, linked: 2, remote: 4, large: 5 }, access_code: { search: 1, read: 2, write: 4, delete: 8, showcontent: 16, addcontent: 32, modifycontent: 64, deletecontent: 128, secure: 256, fullcontrol: 271, securecontent: 512, nocontent: 2048 } } } export default CrmRpc;