"use strict"; (function () { 'use strict'; angular.module('myitsmApp') .service('objectValueMapperService', ['$q', 'metadataModel', 'configurationModel', '$log', '$timeout', '$rootScope', 'events', 'fieldValidationModel', function ($q, metadataModel, configurationModel, $log, $timeout, $rootScope, events, fieldValidationModel) { var ticketType = '', ticketMetadata, ootbMapping, fieldList = {}, parentFieldList = {}, widgetMemberFieldList = {}, expressionMapper = { __constantExpressions: [] }, providerActionExpressionMapper = { __constantExpressions: [] }, widgetMemberMap = {}, widgetFieldMap = {}, ootbFieldValueMap = {}, ticket, providerActionsList = [], fieldActionMapping = {}, providerActionTriggerField = {}, isCopyChangeScreen = false, isProviderActionCallExpressionEventRegistered, isParentShelved = false, parentMapping = {}; this.clearMap = function (type) { fieldList = {}; expressionMapper = { __constantExpressions: [] }; providerActionExpressionMapper = { __constantExpressions: [] }; ticketType = type; isCopyChangeScreen = false; }; this.shelveAsParent = function (type) { parentFieldList = fieldList; parentMapping = { expressionMapper: expressionMapper, providerActionExpressionMapper: providerActionExpressionMapper, isCopyChangeScreen: isCopyChangeScreen }; isParentShelved = true; this.clearMap(type); }; this.unshelveParent = function (type) { this.clearMap(type); fieldList = parentFieldList; expressionMapper = parentMapping.expressionMapper; providerActionExpressionMapper = parentMapping.providerActionExpressionMapper; isCopyChangeScreen = parentMapping.isCopyChangeScreen; isParentShelved = false; }; this.isShelvedParentEmpty = function () { return !isParentShelved; }; this.setCopyChangeTicket = function () { isCopyChangeScreen = true; }; this.isCopyChange = function () { return isCopyChangeScreen; }; this.changeMode = function (mode, firstLoad, ticketObj) { if (firstLoad) { ootbFieldValueMap = configurationModel.get('ootbFieldValueMap.' + (ticketType || ticketObj.type)); widgetFieldMap = configurationModel.get('widgetFieldMap'); ticket = ticketObj; metadataModel.getMetadataByType(ticketType || ticketObj.type).then(function (metadata) { ootbMapping = metadata.ootbMapping; ticketMetadata = metadata; }); } }; this.getTicketType = function () { return ticketType; }; this.getFieldList = function () { return fieldList; }; this.addFields = function (fields) { _.each(fields, function (field) { if (!field.isWidgetMember() && field.dataType !== 'group') { console.log(field.name + ' ' + field.dataType); if (widgetFieldMap[ticketType] && widgetFieldMap[ticketType][field.name]) { _.each(widgetFieldMap[ticketType][field.name], function (member) { widgetMemberMap[member] = field.name; }); } else if (field.members.length) { _.each(field.members, function (member) { widgetMemberMap[member.name] = field.name; }); } fieldList[field.name] = field; _handleFieldExpression(field); } else if (field.dataType === 'group') { _.each(field.members, function (member) { fieldList[member.name] = member; _handleFieldExpression(member); }); } else { widgetMemberFieldList[field.name] = field; } }); }; this.getFieldsByType = function (fieldType) { var fieldArray = []; _.forEach(fieldList, function (field) { if (field.type === fieldType) { fieldArray.push(field); } }); return fieldArray; }; this.getValueByFieldName = function (fieldName) { return fieldList[fieldName] ? fieldList[fieldName].value : ''; }; this.getExactValueByFieldName = function (fieldName) { var value, ootbFieldValMap = ootbFieldValueMap[fieldName], valObj, dataType, tempObj; //Fix for SW00542661 - WO and Task uses assigneeName while the assignee widget is built as assignee, //so it fails to find it in the fieldList and looks up in the ticketObject which has the old value so the evaluation fails if (fieldName === 'assigneeName') { fieldName = 'assignee'; } if (fieldList[fieldName] && fieldList[fieldName].dataType === "menu" && fieldList[fieldName].value !== null && fieldList[fieldName].value !== undefined) { //i.e. Custom field having dynamic dropdown and has value value = fieldList[fieldName].value; // The values in path given in ootbFieldValueMap not updated so we are taking value from here } else if (ootbFieldValMap && fieldList[ootbFieldValMap.fieldName]) { value = _.get(fieldList[ootbFieldValMap.fieldName].value, ootbFieldValMap.path, ''); //SW00542730 - fix //Todo: Need to think of better approach if (typeof value === 'object' && value !== null && value.name) { value = value.name; } } else if (widgetMemberMap[fieldName] && fieldList[widgetMemberMap[fieldName]] && fieldList[widgetMemberMap[fieldName]].type === 'category') { valObj = _.find(fieldList[widgetMemberMap[fieldName]].value.listOfTiers, { name: fieldName }); value = valObj.selectedValue || ''; } //It could be custom field so lookup directly in fieldList if (!value) { value = fieldList[fieldName] ? fieldList[fieldName].value : undefined; } //Just fallback to ticketObject which was loaded if still null if (value === undefined && ootbMapping && ootbMapping[fieldName]) { value = _.get(ticket, ootbMapping[fieldName][0], ''); if (!value && ootbMapping[fieldName][1]) { value = _.get(ticket, ootbMapping[fieldName][1], ''); } } if (value && value.name) { value = value.name; } else if (value && value.toString() === '[object Object]') { value = ''; } if (widgetMemberMap[fieldName] && fieldList[widgetMemberMap[fieldName]]) { tempObj = _.find(fieldList[widgetMemberMap[fieldName]].members, { name: fieldName }); dataType = tempObj ? tempObj.type : ''; } if (!dataType) { dataType = fieldList[fieldName] ? fieldList[fieldName].type : ''; } if (value && _.includes(['dateField', 'dateTimeField'], dataType)) { //convert to epoch value = new Date(value).getTime(); } if (value || value === 0 || value === false) { return value; } else { return ''; } }; this.setValueByFieldName = function (fieldName, value) { var field = fieldList[fieldName]; if (field) { field.setValue(value); } }; this.getFieldByName = function (fieldName) { if (fieldList[fieldName]) { return fieldList[fieldName]; } }; this.getFieldPropertyValue = function (fieldName, propertyName) { var field, widgetName, widget, statusFieldVal, matchedStatus; field = this.getFieldByName(fieldName); if (!field) { widgetName = widgetMemberMap[fieldName]; widget = this.getFieldByName(widgetName); field = _.find(widget.members, { name: fieldName }); } if (fieldName === 'statusReason' || fieldName === 'taskStatusReason') { if (propertyName === 'isReadOnly') { return field && field[propertyName]; } statusFieldVal = fieldName === 'taskStatusReason' ? this.getValueByFieldName('taskStatus') : this.getValueByFieldName('status'); matchedStatus = _.find(ticketMetadata.statuses, { name: statusFieldVal }); if (propertyName === 'isRequired') { var statusReasonFieldName = 'statusReason', changeTiming = //fieldValidationModel uses statusReason even for task void 0; //fieldValidationModel uses statusReason even for task if (this.getTicketType() === EntityVO.TYPE_CHANGE) { var changeClass = this.getValueByFieldName('changeClass'); changeTiming = changeClass.timing; } return matchedStatus.statusReasons ? fieldValidationModel.isFieldRequired(ticketType, statusFieldVal, changeTiming, statusReasonFieldName) : false; } if (propertyName === 'isHidden') { return !matchedStatus.statusReasons ? true : false; } } else { if (widget && widget.type === 'category' && fieldName.indexOf('Tier1') === -1 && propertyName === 'isRequired') { return field && field[propertyName]; } return (field && field[propertyName]) || (widget && widget[propertyName]); } }; /** * Get field metadata using field name and itsm field id (optional) * * @param {String} fieldName - field name to search * @param {String} id - itsm field id to narrow search result * @returns {FieldVO} field - matching field definition */ this.getFieldDefinitionByName = function (fieldName, id) { var field = this.getFieldByName(fieldName), ootbFieldValMap = ootbFieldValueMap[fieldName] || {}, parentWidgetName = widgetMemberMap[fieldName]; if (!field || (id && id !== field.itsmFieldId)) { var parentField = this.getFieldByName(ootbFieldValMap.fieldName || parentWidgetName); if (parentField) { var searchParam = { name: fieldName }; if (id) { searchParam.itsmFieldId = id; } field = _.find(parentField.members, searchParam); } } return field; }; this.setByProperty = function (fieldName, property, value, isWidget, source) { $log.debug('Set ' + fieldName + ' property ' + property + ' to ' + value); var shouldBroadcast = true; //ignore if typeof value is function if (typeof value !== 'function') { switch (property) { case 'required': shouldBroadcast = !(fieldList[fieldName].isRequired === value); fieldList[fieldName].isRequired = value; break; case 'hide': shouldBroadcast = !(fieldList[fieldName].isHidden === value); fieldList[fieldName].isHidden = value; break; case 'readOnly': shouldBroadcast = !(fieldList[fieldName].isReadOnly === value); fieldList[fieldName].isReadOnly = value; break; case 'value': if (isWidget) { _setWidgetValue(fieldName, value, source); } else { _setFieldValue(fieldName, value, source); } break; } if (value && shouldBroadcast && (property === 'required' || property === 'hide' || property === 'readOnly')) { if (isWidget) { var widgetMembers = this.getWidgetMembers(fieldName); if (widgetMembers) { $rootScope.$broadcast(events.WIDGET_VALUE_CHANGE, { fieldName: fieldName, memberName: widgetMembers, isCalledFromSetProp: true, source: source }); } } else { $rootScope.$broadcast(events.FIELD_VALUE_CHANGE, { name: fieldName, isCalledFromSetProp: true, source: source }); } } } }; this.setFieldFromProvider = function (dataMap, mappings) { var deferred = $q.defer(), self = this, objWidgetMap = { impactedService: 'ASSET', causalCI: 'ASSET', assignee: 'PERSON', assigneeSupportGroups: 'GROUP', customer: 'PERSON', site: 'SITE', changeLocation: 'SITE', locationCompany: 'LOCATION', contact: 'PERSON', requestedFor: 'PERSON', changeManager: 'PERSON', changeCoordinator: 'PERSON', changeCoordinatorSupportGroups: 'GROUP', changeManagerSupportGroups: 'GROUP', product: 'CATEGORY', resolutionOperational: 'CATEGORY', resolutionProduct: 'CATEGORY', operational: 'CATEGORY', targetDate: 'DATE', scheduledDates: 'DATE', actualDates: 'DATE' }, dummy = { ASSET: { ci: { instanceId: '', name: '', classId: '' } }, GROUP: { supportGroups: '', name: '', id: '', organization: '', company: { name: '' } }, SITE: { site: { name: '' }, region: { name: '' }, siteGroup: { name: '' }, attributeMap: { siteAddress: { street: '', city: '', state: '', country: '', zip: '' } } }, LOCATION: { locationCompany: '' }, PERSON: { firstName: '', lastName: '', fullName: '', organization: '', loginId: '', personId: '', id: '', isVIP: '', site: { name: '', siteGroup: '', region: '', address: { street: '', city: '', state: '', country: '', zip: '' } }, company: { name: '' } }, CATEGORY: { name: '', tiers: {} }, DATE: { "scheduledStartDate": '', "scheduledEndDate": '', "actualStartDate": '', "actualEndDate": '', "targetDate": '' } }, widgetSetFields = {}, customSetFields = {}, customSetWidgets = {}; _.each(mappings, function (map) { var fieldName = map.mappedFieldValue; if (map.type === 'output') { var mappedField = self.getFieldDefinitionByName(fieldName, map.mappedFieldId), mappedValue = dataMap[map.mappedFieldId]; if (mappedField && mappedField.isDropdownField()) { var mappedValueOption = _.find(mappedField.options, { name: mappedValue }); if (mappedValueOption) { mappedValue = mappedValueOption.name; } } //check if this is custom or widget if (fieldList[fieldName] && !fieldList[fieldName].isWidget()) { customSetFields[fieldName] = mappedValue; } else if (fieldList[fieldName] && _.includes(['priority', 'status', 'taskStatus', 'desc', 'phoneNumber', 'internetEmail', 'changeClass', 'organization'], fieldName)) { customSetWidgets[fieldName] = mappedValue; } else if (widgetMemberMap[fieldName] && fieldList[widgetMemberMap[fieldName]] && fieldList[widgetMemberMap[fieldName]].type === 'category') { if (!widgetSetFields[widgetMemberMap[fieldName]]) { widgetSetFields[widgetMemberMap[fieldName]] = _.cloneDeep(dummy[objWidgetMap[widgetMemberMap[fieldName]]]); widgetSetFields[widgetMemberMap[fieldName]].name = widgetMemberMap[fieldName]; //fieldList[widgetMemberMap[fieldName]].fieldName; } widgetSetFields[widgetMemberMap[fieldName]].tiers[fieldName] = mappedValue; if (mappedValue) { if (!(widgetSetFields[widgetMemberMap[fieldName]].changedTiers)) { widgetSetFields[widgetMemberMap[fieldName]].changedTiers = []; } widgetSetFields[widgetMemberMap[fieldName]].changedTiers.push(fieldName); } } else { if (ootbFieldValueMap[fieldName] && ootbFieldValueMap[fieldName].fieldName) { //var dataValue = (ootbFieldValueMap[fieldName].path.indexOf('.') !== -1) ? buildObject(ootbFieldValueMap[fieldName].path.split('.'), 0, mappedValue) : { ootbFieldValueMap.fieldName.path : mappedValue}; if (!widgetSetFields[ootbFieldValueMap[fieldName].fieldName]) { var widgetValueMock = dummy[objWidgetMap[ootbFieldValueMap[fieldName].fieldName]]; if (widgetValueMock) { widgetSetFields[ootbFieldValueMap[fieldName].fieldName] = _.cloneDeep(dummy[objWidgetMap[ootbFieldValueMap[fieldName].fieldName]]); } else { widgetSetFields[ootbFieldValueMap[fieldName].fieldName] = {}; } } _.set(widgetSetFields[ootbFieldValueMap[fieldName].fieldName], ootbFieldValueMap[fieldName].path, mappedValue); } } } }); console.log('customSetFields-', customSetFields); Object.keys(customSetFields).forEach(function (key) { _setFieldValue(key, customSetFields[key]); }); console.log('customSetWidgets-', customSetWidgets); Object.keys(customSetWidgets).forEach(function (key) { _setWidgetValue(key, customSetWidgets[key]); }); console.log('widgetSetFields-', widgetSetFields); Object.keys(widgetSetFields).forEach(function (key) { fieldList[key].setValueFlag = widgetSetFields[key]; }); deferred.resolve(); return deferred.promise; }; this.setProviderActionToExecute = function (action) { if (!_.find(providerActionsList, { actionId: action.actionId })) { providerActionsList.push(action); $rootScope.$broadcast(events.PROVIDER_ACTION, providerActionsList); } }; this.getProviderActionsList = function () { return providerActionsList; }; this.clearProviderActionFromList = function (action) { if (providerActionsList.length) { _.remove(providerActionsList, { actionId: action.id }); } }; function _setFieldValue(fieldName, value, source) { console.log('Set field value: ' + fieldName + '=' + value); /* Todo * 1. Get Field type * 2. convert the value to field type * * like casting for date type and * * for menu driven fields * * if it is static menu and if mapping is available in metadata get object value else get data from dynamics election query menu call */ var field = fieldList[fieldName]; if (field) { field.setValueFlag = value; field.isFromTicketLoad = (source === 'fromTicketLoad') ? true : false; if (field.isTextField() || field.isTextareaField() || field.isNumberField()) { value = ((field.isTextField() || field.isTextareaField()) && value !== null) ? value + '' : value; if (value !== '' && value !== null) { field.setValue(value); } else { field.clearValue(); } } else if (field.hasDateDataType() || field.hasDateTimeDataType() || field.hasTimeDataType()) { _setDateField(field, value); } else if (field.isMenuField() || field.isDropdownField() || field.isRadioField()) { field.setValue(value); } } } function _setDateField(field, value) { if (value && moment(value).isValid()) { if (field.hasDateDataType) { //as we are offsetting the GMT in setValue thinking that it is coming from server field.value = new Date(value).getTime(); field.hasValue = true; } else { field.setValue(new Date(value).getTime()); } } else { field.clearValue(); } } function _setWidgetValue(fieldName, value, source) { console.log('Set widget value: ' + fieldName + '=' + value); var field = fieldList[fieldName]; if (field) { field.setValueFlag = value; field.isFromTicketLoad = (source === 'fromTicketLoad') ? true : false; } } this.getExpreesionMapByFieldName = function (fieldName) { return expressionMapper[fieldName]; }; this.getAllExpressionFields = function () { return Object.keys(expressionMapper); }; this.getWidgetMembers = function (name) { var members = []; if (widgetFieldMap[ticketType] && widgetFieldMap[ticketType][name]) { return widgetFieldMap[ticketType][name]; } else if (fieldList[name] && fieldList[name].members && fieldList[name].members.length) { _.each(fieldList[name].members, function (m) { members.push(m.name); }); return members; } else { return [name]; } }; this.setProviderActionFieldName = function (fieldName, actionId) { if (!providerActionTriggerField[fieldName]) { providerActionTriggerField[fieldName] = []; } if (actionId) { if (getActionIndex(fieldName, actionId) === -1) { providerActionTriggerField[fieldName].push(actionId); } } }; this.clearProviderActionFieldName = function (fieldName, actionId) { if (actionId && providerActionTriggerField[fieldName] && providerActionTriggerField[fieldName].length > 0) { var currIndex = getActionIndex(fieldName, actionId); if (currIndex !== -1) { providerActionTriggerField[fieldName].splice(currIndex, 1); } } }; function getActionIndex(fieldName, actionId) { return providerActionTriggerField[fieldName] && providerActionTriggerField[fieldName].indexOf(actionId); } this.getProviderActionFieldName = function (fieldName) { return providerActionTriggerField[fieldName] && providerActionTriggerField[fieldName].length > 0 ? fieldName : false; }; this.getProviderActionExpressionMapByFieldName = function (fieldName) { return providerActionExpressionMapper[fieldName]; }; this.getAllProviderActionExpressionFields = function () { return Object.keys(providerActionExpressionMapper); }; this.addToProviderActionExpressionMapper = function (expression, action) { var variables = _extractFieldVariables(expression); if (!variables.length) { providerActionExpressionMapper.__constantExpressions.push({ expression: expression, action: action, actionId: action.id }); } _.each(variables, function (fieldVariable) { if (!providerActionExpressionMapper[fieldVariable]) { providerActionExpressionMapper[fieldVariable] = []; } if (!_.find(providerActionExpressionMapper[fieldVariable], { actionId: action.id })) { providerActionExpressionMapper[fieldVariable].push({ expression: expression, action: action, actionId: action.id }); } }); }; /** * Set fields that have action(s) mapped to it from launchController * * @param {Object} fieldActionMap - map of fields with action(s) */ this.setFieldActionMapping = function (fieldAction, ticketType) { if (ticketType && !fieldActionMapping[ticketType]) { fieldActionMapping[ticketType] = fieldAction; } }; /** * Get fields that have action(s) mapped to it * * @returns {Object} map of fields with actions */ this.getFieldActionMapping = function (ticketType) { return fieldActionMapping[ticketType]; }; this.registerProviderActionCallExpressionEvent = function (event) { isProviderActionCallExpressionEventRegistered = event; }; this.isProviderActionEventRegistered = function () { return isProviderActionCallExpressionEventRegistered; }; function _handleFieldExpression(field) { var isWidget = field.isWidget(); if (field.requiredCondition) { _addToExpressionMapper(field.requiredCondition, field.name, 'required', isWidget); } if (field.hideCondition) { _addToExpressionMapper(field.hideCondition, field.name, 'hide', isWidget); } if (field.setValueCondition) { _addToExpressionMapper(field.setValueCondition, field.name, 'value', isWidget); } if (field.readOnlyCondition) { _addToExpressionMapper(field.readOnlyCondition, field.name, 'readOnly', isWidget); } } function _addToExpressionMapper(expression, fieldName, property, isWidget) { var variables = _extractFieldVariables(expression); if (!variables.length) { expressionMapper.__constantExpressions.push({ expression: expression, field: fieldName, property: property, isWidget: isWidget }); } _.each(variables, function (fieldVariable) { if (!expressionMapper[fieldVariable]) { expressionMapper[fieldVariable] = []; } if (!_.find(expressionMapper[fieldVariable], { field: fieldName, property: property })) { expressionMapper[fieldVariable].push({ expression: expression, field: fieldName, property: property, isWidget: isWidget }); } }); } function _extractFieldVariables(expression) { //any string of the form '$variable' or $variable extract them var regex1 = /(?:^|\W)\$(\w+)(?!\w)/g, regex2 = /['"]\$(.*?)['"]/g, match, matches = []; while ((match = regex1.exec(expression)) !== null) { matches.push(match[1]); } while ((match = regex2.exec(expression)) !== null) { matches.push(match[1].replace(/['$]/g, '')); } return matches; } }]); })();