Something went wrong on our end
-
Benjamin Ulrich authored
[Projekt: xRM-Sales][TicketNr.: 1082421][Klassifizierung: Problem wenn classificationGroup dazukommt]
Benjamin Ulrich authored[Projekt: xRM-Sales][TicketNr.: 1082421][Klassifizierung: Problem wenn classificationGroup dazukommt]
process.js 19.32 KiB
import("ClassificationIndicatorFieldRegistry_basic");
import("AttributeFilter_lib");
import("Attribute_lib");
import("Dependency_lib");
import("Sql_lib");
import("system.db");
import("system.neon");
import("system.text");
import("system.translate");
import("system.util");
import("system.vars");
/**
* Methods to manage classifications.<br>
* <b>Do not create an instance of this!</b>
*
* @class
*/
function ClassificationUtils() {}
/**
* Formats the summary title for one specific group <br/>
* e.g: "1. Target Group: 45/120 points = B"
* so: groupName: achievedPoints/possibleMaxPoints points = gradingChar
*
* @param {Number|String} pAchievedScore <p/>Current score that is reached for a group, e.g. 45
* @param {Number|String} pBestPossibleScore <p/>Current score that is reached for a group, e.g. 45
* @param {String} pGroupName <p/>Name of the group that was passed as ID. This is used as display value and will not be translated,
* you have to pass this value already translated to the target locale. <br/>
* The reason for not loading this value based on the groupId is: better performance optimization
* @param {Number|String} pGrading <p/>Current score that is reached for a group, e.g. 45
* @return {String} <p/>formated and translated title, e.g.: "1. Target Group: 45/120 points = B"
*/
ClassificationUtils.formatDisplaySummaryForGroup = function(pAchievedScore, pBestPossibleScore, pGroupName, pGrading)
{
pCurrentScore = text.formatDouble(pAchievedScore, "#");
pBestPossibleScore = text.formatDouble(pBestPossibleScore, "#");
var res = translate.withArguments("%0: %1/%2 points = %3", [pGroupName, pAchievedScore, pBestPossibleScore, pGrading]);
return res;
};
/**
* Get all possible groupnames for a classificationtype.<br>
* Either as [["group", "group"]] (for the possible items process).
* Or as [["group"]].<br>
*
* @param {String} pObjectType <p>
* The object type.<br>
*/
ClassificationUtils.getAllGroups = function(pObjectType)
{
var sql = new SqlBuilder()
.select(["distinct CLASSIFICATIONGROUP.CLASSIFICATIONGROUPID", "CLASSIFICATIONGROUP.TITLE"])
.from("CLASSIFICATIONGROUP")
.join("CLASSIFICATIONTYPE", "CLASSIFICATIONTYPE.CLASSIFICATIONGROUP_ID = CLASSIFICATIONGROUP.CLASSIFICATIONGROUPID")
.where("CLASSIFICATIONTYPE.OBJECT_TYPE", pObjectType)
.orderBy("CLASSIFICATIONGROUP.TITLE");
return sql.table();
}
/**
* Set a value for a classification type
*
* @param {String} pObjectType
* @param {String} pObjectId
* @param {String} pClassificationTypeId
* @param {String} pClassificationScoreId
*/
ClassificationUtils.setClassificationValue = function(pObjectType, pObjectId, pClassificationTypeId, pClassificationScoreId)
{
var newId = util.getNewUUID();
db.insertData("CLASSIFICATION", ["CLASSIFICATIONID", "OBJECT_TYPE", "OBJECT_ROWID", "CLASSIFICATIONTYPE_ID", "VALUE"], null, [
newId,
pObjectType,
pObjectId,
pClassificationTypeId,
pClassificationScoreId,
]);
newWhere("CLASSIFICATIONSTORAGE.OBJECT_ROWID", pObjectId).updateData(true, "CLASSIFICATIONSTORAGE", ["OUTDATED"], null, 1)
}
/**
* Gets the classificationGradingTable for a classificationGroup as Array.<br>
* ordered by the MinPercent descending <br>
*
* @param {String} pClassificationGroupId <p>
* The classificationgroup you want the grading for <br>
*
* @return {Array} <p>
* The resulting gradingTable. <br>
*/
ClassificationUtils.getGradingTableByGroupId = function(pClassificationGroupId)
{
var classificationGroupId = pClassificationGroupId;
var gradingObject = {};
var gradingTable = newSelect("CLASSIFICATIONGRADING.CLASSIFICATIONGRADINGID, CLASSIFICATIONGRADING.MINPERCENT, CLASSIFICATIONGRADING.GRADING")
.from("CLASSIFICATIONGRADING")
.where("CLASSIFICATIONGRADING.CLASSIFICATIONGROUP_ID", classificationGroupId)
.orderBy("CLASSIFICATIONGRADING.MINPERCENT asc")
.table()
for (let i = 0; i < gradingTable.length; i++)
{
if (gradingObject[classificationGroupId] == undefined)
{
gradingObject[classificationGroupId] = [];
}
gradingObject[classificationGroupId].push([gradingTable[i][1], gradingTable[i][2]]);
}
return gradingObject;
}
/**
* Gets the classificationgroupId of a classification type as String.<br>
*
* @param {String} pClassificationType <p>
* The classification-type (usage)<br>
* (e.g. the key id from keyword ClassificationType)
* @return {String} <p>
* The classificationgroupId of the chosen classificationtype<br>
*/
ClassificationUtils.getClassificationGroup = function(pClassificationType)
{
var classificationGroupId = newSelect("CLASSIFICATIONTYPE.CLASSIFICATIONGROUP_ID")
.from("CLASSIFICATIONTYPE")
.where("CLASSIFICATIONTYPE.CLASSIFICATIONTYPEID", pClassificationType)
.groupBy("CLASSIFICATIONGROUP_ID")
.cell();
return classificationGroupId;
}
/**
* Gets the classificationTypeIds of a classification group.<br>
*
* @param {String} pClassificationGroupId <p>
* The classificationGroupId<br>
* @return {Array} <p>
* The classificationTypeIds of the chosen pClassificationGroupId<br>
*/
ClassificationUtils.getClassificationTypesOfGroup = function(pClassificationGroupId)
{
var classificationTypeIds = newSelect("CLASSIFICATIONTYPE.CLASSIFICATIONTYPEID")
.from("CLASSIFICATIONTYPE")
.where("CLASSIFICATIONTYPE.CLASSIFICATIONGROUP_ID", pClassificationGroupId)
.arrayRow();
return classificationTypeIds;
}
/**
* Get all classification type ids for a score using it's unique classification score id.<br>
*
* @param {String} pClassificationScoreId <p>
* The classification score id
* @return {String} <p>
* The resulting classification type.<br>
*/
ClassificationUtils.getClassificationType = function(pClassificationScoreId)
{
var classificationType = newSelect("CLASSIFICATIONSCORE.CLASSIFICATIONTYPE_ID")
.from("CLASSIFICATIONSCORE")
.where("CLASSIFICATIONSCORE.CLASSIFICATIONSCOREID", pClassificationScoreId)
.arrayColumn();
return classificationType;
}
/**
* Gets the Grading of a score for a group using an object that contains all the gradings and the greatest possible score.<br>
*
* @param {String} pGradingObject <p>
* The classification grading object
* @param {String} pGroupId <p>
* The classification group id
* @param {String} pScore <p>
* The achieved score
* @param {String} pMaxPossibleScore <p>
* The greatest possible score
* @return {String} <p>
* The resulting classification grading.<br>
*/
ClassificationUtils.getGradingFromObject = function(pGradingObject, pGroupId, pScore, pMaxPossibleScore)
{
var gradingObject = pGradingObject;
if (gradingObject == null)
{
gradingObject = ClassificationUtils.getGradingTableByGroupId(pGroupId);
}
var groupId = pGroupId;
var scorePercent = pScore/(pMaxPossibleScore/100); //the score in percent in relation to the maxScore
var grading = "-";
for (var index in gradingObject[groupId])
{
if (Number(scorePercent) >= Number(gradingObject[groupId][index][0]) && scorePercent != 0)
{
grading = gradingObject[groupId][index][1];
}
}
return grading;
}
/**
* This function is used in the workflowExtention_serverProcess.
* It checks whether or not the change has any influence on stored classificationStorage datasets
* by checking if the entity itself is classificationRelevant or the entity has an relation with an classificationRelevant entity
* <p/>
* For further context behind why we use this outdated flag see also the documentation properties of "updateClassifications_serverProcess" and the classification_entities
*
*
* @param {Array} pTargetIds <p/> TargetIds
* @param {String} pEntityName <p/> Entity name
* @param {Object} pRowData <p/> row data
* @param {Object} pChangedRows <p/> changed rows
*
* @return {void}
* @static
*/
ClassificationUtils.setClassificationStorageDatasetsOutdated = function (pTargetIds, pEntityName, pRowData, pChangedRows)
{
var relevantForClassification = false;
var classificationStorageIds = [];
var entityName = pEntityName;
if (entityName == "Organisation_entity" || entityName == "Salesproject_entity")
{
relevantForClassification = true;
classificationStorageIds.push(pTargetIds);
}
if (Dependency.getDependency(entityName).includes("Organisation_entity"))
{
relevantForClassification = true;
classificationStorageIds.push(Dependency.mapping()[entityName]["Organisation_entity"].getUIDsfn(pRowData, pChangedRows));
}
if (Dependency.getDependency(entityName).includes("Salesproject_entity"))
{
relevantForClassification = true;
classificationStorageIds.push(Dependency.mapping()[entityName]["Salesproject_entity"].getUIDsfn(pRowData, pChangedRows));
}
//we have to remove empty arrays, since otherwise it would lead to an error when trying to use the condition for updating
//empty arrays occur when e.g. inserting something that doesn't have any classificationStorageIds even though it is classificationrelevant
for (let i = 0; i < classificationStorageIds.length; i++)
{
if (classificationStorageIds[i][0] == undefined)
{
classificationStorageIds.splice(i, 1);
i--;
}
}
//set outdated flag for the classificationStorage datasets
if (relevantForClassification && classificationStorageIds.length > 0) // also check for the classificationStorageIds.length since it could be empty
{
for (let i = 0; i < classificationStorageIds.length; i++)
{
var cond = newWhere("CLASSIFICATIONSTORAGE.OBJECT_ROWID", classificationStorageIds[i], SqlBuilder.IN());
cond.updateData(true, "CLASSIFICATIONSTORAGE", ["OUTDATED"], null, [1]);
}
}
};
/**
* This function is used in the FIELD.dropDownProcess in ClassificationAdmin.
* Concats and reruns the entityfields specified in $ClassificationIndicatorRegistry.getEntityNumberFields(), $ClassificationIndicatorRegistry.getEntityDropDownFields()
* <p/>
* @param {Object} pObjectType <p/> object type we want the fields for
*
* @return {Array} Array with array of [[value], [displayvalue]] (like in a dropdownproess)
*/
ClassificationUtils.getEntityFields = function (pObjectType)
{
var entityNumberFields = $ClassificationIndicatorRegistry.getEntityNumberFields(pObjectType);
var entityDropDownFields = $ClassificationIndicatorRegistry.getEntityDropDownFields(pObjectType);
var res = entityNumberFields.concat(entityDropDownFields);
return res;
};
/**
* Returns the entity dropdown fields of pObjectType
* <p/>
* @param {Array[][]} pFields <p/> two dimensional Array with key and displayvalue
* @param {String} pKey <p/> key we want the displayvalue for
*
* @return {String} displayvalue, empty string if pKey isn't included in pFields
*/
ClassificationUtils.getFieldDisplayValue = function (pFields, pKey)
{
for (let i = 0; i < pFields.length; i++)
{
if (pFields[i][0] == pKey)
{
return pFields[i][1];
}
}
return "";
}
/**
* Returns the attribute dropdown, number and integer fields of pObjectType using AttributeFilterExtensionMaker.makeFilterFields(pObjectType) and checking for their contentType
* <p/>
* @param {Object} pObjectType <p/> object type we want the Attributes for
*
* @return {Array} Array with Objects for each attribute (see also AttributeFilterExtensionMaker.makeFilterFields())
*/
ClassificationUtils.getEntityAttributes = function (pObjectType)
{
let attributeFields = JSON.parse(AttributeFilterExtensionMaker.makeFilterFields(pObjectType));
for (i = 0; i < attributeFields.length; i++)
{
if (!(attributeFields[i]["contentType"] == AttributeTypes.TEXT() && attributeFields[i]["hasDropDownValues"] === true)
&& !(attributeFields[i]["contentType"] == AttributeTypes.BOOLEAN())
&& !(attributeFields[i]["contentType"] == AttributeTypes.COMBO())
&& !(attributeFields[i]["contentType"] == AttributeTypes.KEYWORD())
&& !(attributeFields[i]["contentType"] == AttributeTypes.NUMBER())
&& !(attributeFields[i]["contentType"] == AttributeTypes.INTEGER()))
{
attributeFields.splice(i, 1);
i--;
}
}
return attributeFields;
};
/**
* This function is used in the FIELD.dropDownProcess in ClassificationAdmin.
* Turns the object array that ClassificationUtils.getEntityAttributes() returns into a useable twodimensional Array
* <p/>
* @param {Object} pAttributeFilterFields <p/> object you get from ClassificationUtils.getEntityAttributes()
*
* @return {Array} Array with array of [[value], [displayvalue]] (like in a dropdownproess)
*/
ClassificationUtils.getEntityAttributesArray = function (pAttributeFilterFields)
{
var attributeFields = pAttributeFilterFields;
var resArray = [];
for (i = 0; i < attributeFields.length; i++)
{
resArray.push([attributeFields[i]["name"], attributeFields[i]["title"]]);
}
return resArray;
};
/**
* This function is used in the stateprocess of multiple fields of classificationScore_entity
* We check if the pFieldTypes includes the one we have in pClassificationTypeInfo and set the recordstate according to the current pRecordState
* <p/>
* @param {String} pRecordState <p/> the record state as in the $sys.recordState-variable; e.g. neon.OPERATINGSTATE_NEW
*
* @param {Array} pFieldTypes <p/> the field types
*
* @param {Object} pClassificationTypeInfo <p/> classification type info (object with field, fieldType and IndicatorType) (JSON.parse(vars.getString("$param.ClassificationTypeInfo_param")))
*
* @param {Array} [pIndicatorTypes] <p/> the indicator types (see also $ClassificationIndicatorTypes)
*
* @param {Object} [pFilterValue] <p/> filter value (only needed for displayValueForTitleField)
*
* @return {String} resulting recordState<br/>
*/
ClassificationUtils.getClassificationScoreStateProcess = function (pRecordState, pFieldTypes, pClassificationTypeInfo, pIndicatorTypes, pFilterValue)
{
var state = neon.COMPONENTSTATE_INVISIBLE;
if (!pFieldTypes)//special case for displayValueForTitleField
{
state = neon.COMPONENTSTATE_INVISIBLE;
if (pRecordState == neon.OPERATINGSTATE_VIEW
|| ((pRecordState == neon.OPERATINGSTATE_NEW || pRecordState == neon.OPERATINGSTATE_EDIT)
&& pFilterValue && JSON.parse(filterValue)["filter"]["childs"].length > 0))
{
state = neon.COMPONENTSTATE_READONLY;
}
return state;
}
var fieldType = pClassificationTypeInfo["fieldType"];
var indicatorType = pClassificationTypeInfo["indicatorType"];
if (pRecordState == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
{
if (pFieldTypes.includes(fieldType) && (!pIndicatorTypes || pIndicatorTypes.length == 0 || pIndicatorTypes.includes(indicatorType)))
{
state = neon.COMPONENTSTATE_EDITABLE;
}
}
return state;
};
/*this is right now (2020-08-15) the only way to get something like a constant with
- a prober name
- autocomplete support within the ADITO Designer
- and proper packageing all constants together
This may change in the future, if there is something better feel free to improve this */
function $ClassificationRecordCategories(){}
$ClassificationRecordCategories.CLASSIFICATION_OBJECT_TYPE = function(){return "ClassificationObject_Type"};
$ClassificationRecordCategories.CLASSIFICATION_CLASSIFICATION_GROUP = function(){return "ClassificationGroup"};
$ClassificationRecordCategories.CLASSIFICATION_CLASSIFICATION_TYPE = function(){return "ClassificationType"};
$ClassificationRecordCategories.CLASSIFICATION_GROUP_EXISTS = function(){return "ClassificationGroupExists"};
$ClassificationRecordCategories.CLASSIFICATION_GROUP_DOESNT_EXIST = function(){return "ClassificationGroupDoesntExist"};
function $ClassificationPlaceholder(){}
$ClassificationPlaceholder.TOPSECRETPLACEHOLDER = function(){return "T0PS3CR3TPL4CEH0LD3R"};
function $ClassificationFieldTypes(){}
$ClassificationFieldTypes.NUMBER = function(){return "number"};
$ClassificationFieldTypes.INTEGER = function(){return "integer"};
$ClassificationFieldTypes.DROPDOWN = function(){return "dropDown"};
$ClassificationFieldTypes.DATE = function(){return "date"};
function $ClassificationIndicatorTypes(){}
$ClassificationIndicatorTypes.ENTITYFIELD = function(){return "entityField"};
$ClassificationIndicatorTypes.ATTRIBUTE = function(){return "attribute"};
$ClassificationIndicatorTypes.COMPLEX = function(){return "complex"};