///* globals moment, moment-timezone, Lines, Moment, MomentTimezone */ /* globals moment, Lines, md5, toastr */ /* globals currentPage, userObj, apiHost, jwtToken */ /* globals currentMeasurement, openModalMeasureStructure, openModalMeasureStructureForEdit, elementOeCombinations */ /* globals handleFailedApiCall, clickOnNav1Item */ /* globals Datatable */ var fileObj; var fileUploadSuccessCounter=0; // Global constants const measurementsElementContainerId='parentStructureElements'; const measurementsOeContainerId='parentStructureOEs'; const measurementsElementOeListContainerId='elementList'; const measurementsTableHistoricValuesContainer='parentDatatableHistoricMeasurements'; const measurementsPlotHistoricValuesContainer='parentPlotHistoricMeasurements'; const measurementsTableHistoricValues='datatableHistoricMeasurements'; const approvalTableContainer='approvalOpenTableContainer'; const approvalTable='approvalOpenTable'; const consumptionApprovalsTableContainer='consumptionApprovalsOpenTableContainer'; const consumptionApprovalsTable='consumptionApprovalsOpenTable'; const elementOeCombinationsElementContainerId='parentStructureElements'; const elementOeCombinationsOeContainerId='parentStructureOEs'; const elementOeCombinationsTableId='tableElementOeCombinations'; const elementOeCombinationsButtonId='buttonCombinationSave'; const elementOeCombinationsButtonRemarkId='buttonCombinationSaveRemark'; const idModalInput='modalInput'; const idModalInputForm='modalInputForm'; const idModalInputInput='modalInputInput'; const idModalInputButton='modalInputButton'; const lineBreakPattern=''; const csrdValueSeparator='|'; let htmlIdConsumpCategoryButtonsContainer='consumpCategoryButtonsContainer'; let htmlIdConsumpFiltersContainer='consumpFiltersContainer'; let htmlIdConsumptionFiltersOUsExisting='consumptionFiltersOUsExisting'; let htmlIdConsumptionEntitiesTable='consumptionEntitiesTable'; let htmlIdConsumptionEntitiesTableContainer='consumptionEntitiesTableContainer'; let htmlIdConsumptionEntityModal='modalConsumptionEntity'; let htmlIdConsumptionEntityTableValuesTable='modalConsumptionEntityTableValues'; let htmlIdConsumptionEntityTableValuesTableContainer='modalConsumptionEntityTableValuesContainer'; let htmlIdConsumptionCustomEFModal='modalConsumptionCustomEF'; let htmlIdConsumptionCustomEFModalBody='modalConsumptionCustomEFBody'; let htmlIdConsumptionCustomEFTable='modalConsumptionCustomEFBodyTable'; let htmlIdConsumptionTargetMeasurementsModal='modalConsumptionTargetMeasurements'; let htmlIdConsumptionTargetMeasurementsTable='modalConsumptionTargetMeasurementsTable'; let htmlIdConsumptionCO2TargetMeasurementsModal='modalConsumptionCO2TargetMeasurements'; let htmlIdConsumptionCO2TargetMeasurementsTable='modalConsumptionCO2TargetMeasurementsTable'; let htmlIdConsumptionTimerangesModal='modalConsumptionTimeranges'; let htmlIdConsumptionTimerangesTable='modalConsumptionTimerangesTable'; let htmlIdConsumptionTimerangesTableContainer='modalConsumptionTimerangesTableContainer'; let htmlIdConsumptionValuesModal='modalConsumptionValues'; let htmlIdConsumptionValuesTable='modalConsumptionValuesTable'; let htmlIdConsumptionValuesTableContainer='modalConsumptionValuesTableContainer'; let htmlIdConsumptionValuesFilesModal='modalConsumptionValuesFiles'; let htmlIdConsumptionValuesFilesModalBody='modalConsumptionValuesFilesBody'; const elementRelevance={100: {nameLong: 'Core', nameShort: 'Core'}, 200: {nameLong:'Optional 1', nameShort:'Opt1'}, 300: {nameLong:'Optional 2', nameShort:'Opt2'}}; //const elementDflCriteria={'ONE': {nameShort: 'MK1', nameLong: 'Mindeskriterium 1'}, 'TWO': {nameShort: 'MK2', nameLong: 'Mindeskriterium 2'}, 'THREE': {nameShort: 'EK', nameLong: 'Erweitertes Kriterium'}, 'NOTDFL': {nameShort: 'Nicht-DFL', nameLong: 'Kein DFL-Kriterium'}}; const elementDflCriteria={ 'ONE': {nameShort: 'A', nameLong: 'A-Kriterium'} , 'TWO': {nameShort: 'B', nameLong: 'B-Kriterium'} , 'THREE': {nameShort: 'C', nameLong: 'C-Kriterium'} , 'NOTDFL': {nameShort: 'Nicht-DFL', nameLong: 'Kein DFL-Kriterium'} , 'ONE_OLD': {nameShort: 'MK1', nameLong: 'Mindeskriterium 1'} , 'TWO_OLD': {nameShort: 'MK2', nameLong: 'Mindeskriterium 2'} , 'THREE_OLD': {nameShort: 'EK', nameLong: 'Erweitertes Kriterium'} }; const userRole={1: 'User', 2: 'Kunden-Admin', 3: 'Master-Admin'}; const measurementScale={'metric': 'metrisch', 'binary': 'binär', 'categoric': 'kategorisch'}; const measurementScaleCSRD={'informativ': 'informativ', 'quant': 'quantitativ', 'qual': 'qualitativ'}; const measurementTime={'range': 'Zeitraum', 'point': 'Zeitpunkt'}; const measurementType={'absolute': 'Absolutwert', 'delta': 'Veränderung'}; const elementCSRD_OP={shall: {nameLong: 'Shall', nameShort: 'Shall'}, may: {nameLong:'May', nameShort:'May'}}; const elementCSRD_Section={ // Order is not yet used anywhere 100: {nameLong: 'Governance', /*nameShort: 'Governance',*/ id: 'Governance', order: 2} , 200: {nameLong:'Basis for preparation', /*nameShort:'Erstellung',*/ id: 'Grundlagen für die Erstellung', order: 3} , 300: {nameLong:'IRO management', /*nameShort:'Auswirkungen',*/ id: 'Management der Auswirkungen, Risiken und Chancen', order: 4} , 400: {nameLong:'Metrics and targets', /*nameShort:'Parameter',*/ id: 'Parameter und Ziele', order: 5} , 500: {nameLong:'Strategy', /*nameShort:'Strategie',*/ id: 'Strategie', order: 6} , 600: {nameLong:'Objective', /*nameShort:'Ziel',*/ id: 'Ziel', order: 7} , 700: {nameLong:'General', /*nameShort:'Allgemein',*/ id: 'Allgemein', order: 1} }; function getSectionNrByID(id) { for (let key in elementCSRD_Section) { if (elementCSRD_Section[key].id==id) return key; } return null; } const accountTableAcquisitionPeriodsContainer='newAccountAcquisitionPeriodsContainer'; const accountTableAcquisitionPeriods='newAccountAcquisitionPeriodsTable'; const accountTableAcquisitionPeriodsConsumptionsContainer='newAccountConsumptionAcquisitionPeriodsContainer'; const accountTableAcquisitionConsumptionsPeriods='newAccountConsumptionsAcquisitionPeriodsTable'; const accountTableAcquisitionPeriodsCSRDContainer='newAccountCSRDAcquisitionPeriodsContainer'; const accountTableAcquisitionCSRDPeriods='newAccountCSRDAcquisitionPeriodsTable'; // Global variables var externalCallMeasurementId=null; var externalCallCSRDMeasurementId=null; var externalCallElementOUCombiId=null; var externalCallCSRDElementOUCombiId=null; var externalCallMeasureId=null; var externalCallCSRDMeasureId=null; var externalCallConsumptionValueId=null; var structureElements=[]; var structureOEs=[]; var elementOeCombinations=[]; var elementSets=[]; var structureMeasures=[]; var structureDFLCriteriaSet=null; var accountPrivilegesDefault=null; var consumptionCategories=[]; var csrdStructureElements=[]; var csrdStructureOEs=[]; var csrdElementOeCombinations=[]; var csrdElementSets=[]; var csrdStructureMeasures=[]; var emailCronpatterns={ none: { displayTitle: 'Kein Email-Versand', cronpattern: null } , weekly_monday: { displayTitle: 'Wöchentlich (Montags)', cronpattern: '0 0 4 ? * MON *' } , monthly_first: { displayTitle: 'Monatlich (Am 1sten)', cronpattern: '0 0 4 1 * ? *' } }; // Logger /* const loggableUserActions=['login_success', 'login_failure', 'logout', 'click_web', 'click_email', 'email_open', 'click_external_offer_link', 'email_sent_out', 'api_call', 'geo_autocomplete_failure', 'offerors_autocomplete_failure', 'offerors_stats_current_failure', 'offerors_stats_historic_failure', 'settings_update', 'searchprofile_update', 'pwd_reset', 'pwd_change', 'file_upload_success', 'file_upload_failure', 'customer_service_msg_success', 'customer_service_msg_failure', 'check_prerequisites', 'object_modal_show', 'object_details_modal_show', 'object_modal_external_show', 'searchprofile_external_show', 'competitor_external_show', 'social_sharing_opened', 'social_sharing', 'favorite_obj_add', 'favorite_obj_delete', 'objects_filter_remove', 'objects_filter_apply', 'objects_columns_apply', 'objects_searchprofile_change', 'objects_searchprofile_save', 'objects_searchprofile_savenew', 'questionaire_searchprofile_savenew', 'objects_searchprofile_makestandard', 'objects_searchprofile_activate_emailalert', 'objects_searchprofile_deactivate_emailalert', 'objects_searchprofile_delete', 'objects_datatable_open_details', 'objects_datatable_favorite_on', 'objects_datatable_favorite_off', 'objects_datatable_pagelength_change', 'objects_datatable_page', 'objects_datatable_object_collapse', 'markets_filter_remove', 'markets_filter_apply', 'admin_user_created', 'admin_account_created', 'admin_user_deactivated', 'admin_account_deactivated', 'admin_user_created_email', 'admin_elementoucombi_created', 'admin_elementoucombi_deactivated', 'admin_elementoucombi_reactivated', 'admin_measurestructure_created', 'admin_measurestructure_edited', 'admin_measurestructure_deactivated', 'admin_measurestructure_reactivated', 'admin_measure_created', 'admin_measure_edited', 'admin_measure_deactivated', 'admin_measure_reactivated', 'admin_measurement_created', 'admin_measurement_edited', 'admin_measurement_deactivated', 'admin_measurement_deactivation_approval_request', 'admin_measurement_approval_edited', 'admin_measurement_approval_file_deactivated', 'admin_measurement_approval_restart_request', 'dashboard_filter_save_new', 'dashboard_filter_deactivated', 'measurement_external_show', 'global_data_load' ]; const loggableSystemActions=['log_user', 'api_call', 'email_sent_out' , 'customer_service_msg_failure', 'file_upload_failure' , 'unspecifiedValue' , 'data_missing', 'check_prerequisites', 'tour_element_not_available' , 'geo_autocomplete_failure' , 'object_modal_external_show', 'searchprofile_external_show', 'competitor_external_show', 'object_modal_show' , 'measurement_external_show' ]; */ const loggableEvents=['FRONTEND_CLIENT_LOG' , 'FRONTEND_SERVER_LOGIN' // Only used in PHP, not here in JS , 'FRONTEND_SERVER_LOGOUT' // Only used in PHP, not here in JS , 'FRONTEND_CLIENT' , 'FRONTEND_CLIENT_PLATFORM' , 'FRONTEND_CLIENT_CLICK' , 'FRONTEND_CLIENT_LOADCONTENTPAGE' , 'FRONTEND_CLIENT_EXTERNALCALL' , 'FRONTEND_CLIENT_CONSISTENCECHECK' , 'FRONTEND_CLIENT_FORMATMEASUREMENTVALUE' , 'FRONTEND_CLIENT_DASHBOARD' , 'FRONTEND_CLIENT_ACQUSITIONPERIOD_NOT_ACTIVE' , 'FRONTEND_CLIENT_DFLCRITERIA_TYPE_CHECK' , 'FRONTEND_CLIENT_DFLCRITERIA_SATISFIED_CHECK' , 'FRONTEND_CLIENT_PRESELECT' , 'FRONTEND_CLIENT_NOTFOUND' , 'FRONTEND_CLIENT_API_ACCOUNTLOGO' , 'FRONTEND_CLIENT_API_GLOBALDATA' , 'FRONTEND_CLIENT_API_NEW_ACCOUNT' , 'FRONTEND_CLIENT_API_EDIT_ACCOUNT' , 'FRONTEND_CLIENT_API_GET_ALLACCOUNTS' , 'FRONTEND_CLIENT_API_GET_ACCOUNT' , 'FRONTEND_CLIENT_API_GET_ACCOUNT_PRIVILEGES_DEFAULT' , 'FRONTEND_CLIENT_API_NEW_USER' , 'FRONTEND_CLIENT_API_EDIT_USER' , 'FRONTEND_CLIENT_API_GET_ALLUSERS' , 'FRONTEND_CLIENT_API_NEW_DASHBOARDFILTERMEASUREMENTS' , 'FRONTEND_CLIENT_API_EDIT_DASHBOARDFILTERMEASUREMENTS' , 'FRONTEND_CLIENT_API_NEW_DASHBOARDFILTERMEASURES' , 'FRONTEND_CLIENT_API_EDIT_DASHBOARDFILTERMEASURES' , 'FRONTEND_CLIENT_API_NEW_DASHBOARDFILTERCONSUMPTIONS' , 'FRONTEND_CLIENT_API_EDIT_DASHBOARDFILTERCONSUMPTIONS' , 'FRONTEND_CLIENT_API_GET_ALLELEMENTOUCOMBIS' , 'FRONTEND_CLIENT_API_NEW_ELEMENTOUCOMBI' , 'FRONTEND_CLIENT_API_EDIT_ELEMENTOUCOMBI' , 'FRONTEND_CLIENT_API_RELINK_ELEMENTOUCOMBI' , 'FRONTEND_CLIENT_API_GET_ALLELEMENTSETS' , 'FRONTEND_CLIENT_API_GET_ALLELEMENTS' , 'FRONTEND_CLIENT_API_GET_ALLOUS' , 'FRONTEND_CLIENT_API_NEW_MEASUREMENT' , 'FRONTEND_CLIENT_API_EDIT_MEASUREMENT' , 'FRONTEND_CLIENT_API_NEW_MEASUREMENTAPPROVAL' , 'FRONTEND_CLIENT_API_GET_ALLACTIVEOPENMEASUREMENTS' , 'FRONTEND_CLIENT_API_EDIT_MEASUREMENTAPPROVAL' , 'FRONTEND_CLIENT_API_EDIT_FILE' , 'FRONTEND_CLIENT_API_FILE_UPLOAD' , 'FRONTEND_CLIENT_API_FILE_DOWNLOAD' , 'FRONTEND_CLIENT_API_GET_ALLMEASURESTRUCTURES' , 'FRONTEND_CLIENT_API_NEW_MEASURESTRUCTURE' , 'FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE' , 'FRONTEND_CLIENT_API_NEW_MEASURE' , 'FRONTEND_CLIENT_API_EDIT_MEASURE' , 'FRONTEND_CLIENT_API_GET_DFLCRITERIAS' , 'FRONTEND_CLIENT_API_EDIT_DFLCRITERIASELEMENTOUS' , 'FRONTEND_CLIENT_API_NEW_DFLCRITERIASELEMENTOUS' , 'FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYCRITERIAS' , 'FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIES' , 'FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY' , 'FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITY' , 'FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITY' , 'FRONTEND_CLIENT_API_DUPLICATE_CONSUMPTIONENTITY' , 'FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIYTIMERANGES' , 'FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITIYTIMERANGES' , 'FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITIYTIMERANGES' , 'FRONTEND_CLIENT_API_GET_DASHBOARDCONSUMPTIONDATA' , 'FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL' , 'FRONTEND_CLIENT_API_EDIT_CONSUMPTIONVALUEAPPROVAL' , 'FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYAPPROVALS' , 'FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY_BY_CONSUMPTIONVALUE' , 'FRONTEND_CLIENT_API_GET_CONSUMPTIONVALUE' , 'FRONTEND_CLIENT_API_GET_ALLACTIVEOPENCONSUMPTIONVALUES' , 'FRONTEND_CLIENT_API_GET_LOGS_MEASUREMENT' // CSRD , 'FRONTEND_CLIENT_API_GET_CSRD_ALLELEMENTOUCOMBIS' , 'FRONTEND_CLIENT_API_NEW_CSRD_ELEMENTOUCOMBI' , 'FRONTEND_CLIENT_API_EDIT_CSRD_ELEMENTOUCOMBI' , 'FRONTEND_CLIENT_API_RELINK_CSRD_ELEMENTOUCOMBI' , 'FRONTEND_CLIENT_API_GET_CSRD_ALLELEMENTSETS' , 'FRONTEND_CLIENT_API_GET_CSRD_ALLELEMENTS' , 'FRONTEND_CLIENT_API_GET_CSRD_ALLOUS' , 'FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENT' , 'FRONTEND_CLIENT_API_EDIT_CSRD_MEASUREMENT' , 'FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENTAPPROVAL' , 'FRONTEND_CLIENT_API_GET_CSRD_ALLACTIVEOPENMEASUREMENTS' , 'FRONTEND_CLIENT_API_EDIT_CSRD_MEASUREMENTAPPROVAL' , 'FRONTEND_CLIENT_API_EDIT_CSRD_FILE' , 'FRONTEND_CLIENT_API_FILE_CSRD_UPLOAD' , 'FRONTEND_CLIENT_API_FILE_CSRD_DOWNLOAD' , 'FRONTEND_CLIENT_API_GET_CSRD_ALLMEASURESTRUCTURES' , 'FRONTEND_CLIENT_API_NEW_CSRD_MEASURESTRUCTURE' , 'FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE' , 'FRONTEND_CLIENT_API_NEW_CSRD_MEASURE' , 'FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE' , 'FRONTEND_CLIENT_API_GET_CSRD_ELEMENT' , 'FRONTEND_CLIENT_API_NEW_CSRD_DASHBOARDFILTERMEASUREMENTS' , 'FRONTEND_CLIENT_API_EDIT_CSRD_DASHBOARDFILTERMEASUREMENTS' , 'FRONTEND_CLIENT_API_NEW_CSRD_DASHBOARDFILTERMEASURES' , 'FRONTEND_CLIENT_API_EDIT_CSRD_DASHBOARDFILTERMEASURES' ] const loggableEventStatus=['OK' , 'ERROR_USER_UNAUTHENTICATED' , 'ERROR_USER_UNAUTHORIZED' , 'ERROR_USER_RATELIMITQUOTAEXCEEDED' , 'ERROR_SYSTEM' , 'ERROR_USER' , 'ERROR_SYSTEM_DATAACCESS' , 'ERROR_SYSTEM_DATAPERSIST' , 'ERROR_SYSTEM_DUPLICATE' , 'ERROR_USER_DUPLICATE' , 'ERROR_SYSTEM_INACTIVE' , 'ERROR_SYSTEM_TIMEOVERLAP' , 'ERROR_SYSTEM_EMAIL' , 'ERROR_SYSTEM_LOG' , 'ERROR_SYSTEM_DESERIALIZATION' , 'ERROR_SYSTEM_DATALOAD' , 'ERROR_SYSTEM_PARAMETER' , 'ERROR_NOT_FOUND' , 'WARNING_NOT_FOUND' , 'ERROR_SYSTEM_LOGEVENTUNDEFINED' , 'ERROR_SYSTEM_LOGEVENTSTATUSUNDEFINED' , 'ERROR_SYSTEM_LOGEVENTDETAILSNOTOBJECT' , 'ERROR_SYSTEM_APIREQUEST' , 'ERROR_USER_APIREQUEST' , 'ERROR_SYSTEM_DATAUNSPECIFIED' , 'ERROR_SYSTEM_FORMULARINVALID' , 'ERROR_SYSTEM_DATA_INCONSISTENT' ] //const loggableTypes=['info', 'error']; // MarketsFilters const localStorageFiltersPrefix='markets_Filter_'; // For responsive behaviour adjustments/controlling const mediaQueryMatchXS = window.matchMedia('(max-width: 576px)'); const mediaQueryMatchSM = window.matchMedia('(min-width:577px) and (max-width: 768px)'); const mediaQueryMatchMD = window.matchMedia('(min-width:769px) and (max-width: 992px)'); const mediaQueryMatchLG = window.matchMedia('(min-width:993px) and (max-width: 1200px)'); const mediaQueryMatchXL = window.matchMedia('(min-width:1201px) and (max-width: 1440px)'); const mediaQueryMatchXXL = window.matchMedia('(min-width:1441px)'); class Helper { constructor() { // Covers also all dynamically created/appended HTML elements $("#toastr-clear").on("click", function() { toastr.clear(); }); } /* * All timestamps to be provided as moment objects * aTo == bFrom IS considered as overlap */ static isOverlappingIncl(aFrom, aTo, bFrom, bTo) { //console.log(aFrom, aTo, bFrom, bTo); return !aFrom.isAfter(bTo) && !bFrom.isAfter(aTo); } static showFullScreenProcessingBackdrop() { $('body').append(''); } static hideFullScreenProcessingBackdrop() { $('#backdropDataLoad').remove(); } /** * * fileAry structure: * [ * { * , id: 463 * , filename: 'Datei123.pdf' * , sizeInBytes: 123456 * , timestampCreation: 1678890044000 [unix timestamp in millis] * } * ] * * @param {*} htmlIdListContainer * @param {*} fileAry * @param {*} callbackCheckUserPrivilegesDelete * @param {*} callbackCheckAccountPrivilegesDelete * @param {*} callbackDelete * @param {*} callbackCheckUserPrivilegesView * @param {*} callbackView */ static getFileList(htmlIdListContainer, fileAry , callbackCheckUserPrivilegesDelete, callbackCheckAccountPrivilegesDelete, callbackDelete, callbackCheckUserPrivilegesView, callbackView , callbackNewFile=null , documentTypeName='Freigabe-Dokument' ) { // ### Show existing approval files $('#'+htmlIdListContainer).empty(); if (fileAry.length>0) { // If >0 files exist $('#'+htmlIdListContainer).append('Vorhandene Dokumente:'); $('#'+htmlIdListContainer).append(''; // Close list level 2 html+='
  • '+s+'
  • '; } else { // Previous was normal text html+='
      '; // Open list level 1; do no show bullet icons html+='
    • '+s+'
    • '; } bolPrevList1=true; bolPrevList2=false; } else if (rListLevel2.test(s)) { // List level 2 if (bolPrevList1) { html+='
        '; // Open list level 2; do no show bullet icons html+='
      • '+s+'
      • '; } else if (bolPrevList2) { html+='
      • '+s+'
      • '; } else { // Previous was normal text html+='
            '; // Open list level 2; do no show bullet icons html+='
          • '+s+'
          • '; } bolPrevList1=false; bolPrevList2=true; } else { // Normal text if (bolPrevList1) { html+='
          '; // Close list level 1 html+='

          '+s+'

          '; } else if (bolPrevList2) { html+='
      '; // Close list level 2 html+='

      '+s+'

      '; } else { // Previous was normal text html+='

      '+s+'

      '; } bolPrevList1=false; bolPrevList2=false; } } if (bolPrevList1) { html+='
    '; // Close list level 1 } else if (bolPrevList2) { html+=''; // Close list level 2 } else { // Previous was normal text // Do nothing } return html; } else { return null; } } /* */ static transformElementStructure(dataUnstructured) { dataUnstructured.sort(function(a,b) { if (a.pk_csrd_elements < b.pk_csrd_elements) return -1; else if (a.pk_csrd_elements > b.pk_csrd_elements) return 1; else return 0; }); var dataStructured=[]; if (dataUnstructured!==null && Array.isArray(dataUnstructured)) { for (let entryUn of dataUnstructured) { var level1Obj=null; var level2Obj=null; var level3Obj=null; var level4Obj=null; var level5Obj=null; // ### Check if structure path already exists (if not, create it) for (let entry of dataStructured) { if (entry.nodeId==entryUn.id_node_level1) { level1Obj=entry; if ('childs' in entry && Array.isArray(entry.childs)) { for (let entry2 of entry.childs) { if (entry2.nodeId==level1Obj.nodeId+'_'+entryUn.id_node_level2) { level2Obj=entry2; if ('childs' in entry2) { for (let entry3 of entry2.childs) { if (entry3.nodeId==level2Obj.nodeId+'_'+entryUn.id_node_level3) { level3Obj=entry3; if ('childs' in entry3) { for (let entry4 of entry3.childs) { if (entry4.nodeId==level3Obj.nodeId+'_'+entryUn.id_node_level4) { level4Obj=entry4; // ... a 5th level could be added here if required } } } } } } } } } } } // Create new nodes (if necessary) if (level1Obj===null) { level1Obj=new ElemntCSRD({name_short: entryUn.name_node_level1}); level1Obj['nodeId']=entryUn.id_node_level1; dataStructured.push(level1Obj); } if (level2Obj===null && entryUn.id_node_level1!==null) { if (entryUn.id_node_level2!==null) { level2Obj=new ElemntCSRD({name_short: entryUn.name_node_level2}); level2Obj['nodeId']=level1Obj.nodeId+'_'+entryUn.id_node_level2; } else { level2Obj=new ElemntCSRD(entryUn); level2Obj['nodeId']=level1Obj.nodeId+'_'+entryUn.pk_csrd_elements; } if (!('childs' in level1Obj)) level1Obj['childs']=[]; level1Obj['childs'].push(level2Obj); } if (level3Obj===null && entryUn.id_node_level2!==null) { if (entryUn.id_node_level3!==null) { level3Obj=new ElemntCSRD({name_short: entryUn.name_node_level3}); level3Obj['nodeId']=level2Obj.nodeId+'_'+entryUn.id_node_level3; } else { level3Obj=new ElemntCSRD(entryUn); level3Obj['nodeId']=level2Obj.nodeId+'_'+entryUn.pk_csrd_elements; } if (!('childs' in level2Obj)) level2Obj['childs']=[]; level2Obj['childs'].push(level3Obj); } if (level4Obj===null && entryUn.id_node_level3!==null) { if (entryUn.id_node_level4!==null) { level4Obj=new ElemntCSRD({name_short: entryUn.name_node_level4_no}); level4Obj['nodeId']=level3Obj.nodeId+'_'+entryUn.id_node_level4; } else { //console.log(entryUn); level4Obj=new ElemntCSRD(entryUn); level4Obj['nameShort']=entryUn.name_node_level4_no; level4Obj['nodeId']=level3Obj.nodeId+'_'+entryUn.pk_csrd_elements; } if (!('childs' in level3Obj)) level3Obj['childs']=[]; level3Obj['childs'].push(level4Obj); } } } return dataStructured; } static createStructureTable(tableHtmlId, csrdStructureElements, expandChildRows=true, startCollapsed=false) { // ### Get users (to show users with write privileges per row) let structureElementsAsMapByNodeId=ElementOeSelectorCSRD.getStructureAsMapByNodeId(csrdStructureElements); //console.log(csrdStructureElements, structureElementsAsMapByNodeId); User.getAllUsers(function(dataFromApi) { let userObjsForWritePrivileges=[]; if (Array.isArray(dataFromApi) && dataFromApi.length>0) { for (var i=0; i0) { for (var i=0; i')+'n/a: '; Logger.log('FRONTEND_CLIENT', 'ERROR_NOT_FOUND', { errorMsg: 'OE obj not found by ID='+oeId, flag: 'csrd' }); // TODO Tmp marker, can be deleted } else { usersWithWritePrivilegesStr+=(first ? '' : '
    ')+''+oeObj.nameShort+': '; } let firstName=true; for (let userName of oes[oeId]) { usersWithWritePrivilegesStr+=(firstName ? '' : ', ')+userName; firstName=false; } first=false; } } // ### Create details string let $details=$('
    '); // let required to limit variable scope local to the loop and thus allows usage in the click event handler $details.append('
    ID:
    '+structureObj[i].idGlobal+'
    '); $details.append('
    Disclosure Requirement No.:
    '+structureObj[i].nameShort+'
    '); $details.append('
    Einheiten:
    '+(unit!==null ? unit : '')+'
    '); $details.append('
    Messniveau:
    '+scale+'
    '); $details.append('
    Messzeit:
    '+(time!==null ? time : '-')+'
    '); $details.append('
    Gültig­keits­zeit­raum:
    '+ElemntCSRD.getActiveTimeRangeStr(structureObj[i].activeTimeRange)+'
    '); $details.append('
    Deaktiviert:
    '+(!active ? 'Ja'+(activeObj.timestampDeactivated!==null ? ' ('+Helper.timestampFormat(activeObj.timestampDeactivated, false, false)+')' : '') : 'Nein')+'
    '); $details.append('
    Schreib­rechte:
    '+usersWithWritePrivilegesStr+'
    '); // ### Create HTML var $tableRow=$(''); let $tdTitle=$(''); $tdTitle.html(structureObj[i].nameShort); if (structureObj[i].childElementsDe!==null && structureObj[i].childElementsDe!==undefined && structureObj[i].childElementsDe!='') $tdTitle.attr('data-toggle', 'tooltip').attr('title', structureObj[i].childElementsDe.replaceAll(lineBreakPattern,' ')); //$tableRow.append(''+structureObj[i].nameShort+''); $tableRow.append($tdTitle); $tableRow.append(''+structureObj[i].idGlobal+''); $tableRow.append(''+(unit!==null ? unit : '')+''); $tableRow.append(''+scale+''); $tableRow.append(''+(time!==null ? time : '-')+''); $tableRow.append(''+ElemntCSRD.getActiveTimeRangeStr(structureObj[i].activeTimeRange)+''); $tableRow.append(''+(!active ? 'Ja'+(activeObj.timestampDeactivated!==null ? ' ('+Helper.timestampFormat(activeObj.timestampDeactivated, false, false)+')' : '') : 'Nein')+''); $tableRow.append(''+usersWithWritePrivilegesStr+''); $tableRow.append( $('') .append($('') .on('click', function() { Helper.confirmModal($details.prop('outerHTML'), 'Schließen', null, 'Element Details', false); }) ) ); $returnJQueryObj=$returnJQueryObj.add($tableRow); } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort+'' +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort+'' +''); $returnJQueryObj=$returnJQueryObj.add( ElemntCSRD.createStructureTableRow(structureObj[i].childs, (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1)), userObjsForWritePrivileges, eocMap) ); } } } return $returnJQueryObj; } static createStructureTableRowForMultipleSelection(structureObj, levelStr=null, showLeafs=true, showIdGlobal=false, showId=true) { var $returnJQueryObj=$(); // ? var levelAry=[]; if (levelStr!==null) levelAry=levelStr.split('_'); var levelClass=''; if (levelAry.length==0) levelClass='level1'; else if (levelAry.length==1) levelClass='level2'; else if (levelAry.length==2) levelClass='level3'; else if (levelAry.length==3) levelClass='level4'; if (structureObj!==null && Array.isArray(structureObj) && structureObj.length>0) { for (var i=0; i' $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort //+(showId===true && showIdGlobal && 'idGlobal' in structureObj[i] && structureObj[i].idGlobal!==undefined && structureObj[i].idGlobal!==null ? ' (ID: '+structureObj[i].idGlobal+')' : '')+'' +'' +' ' +(showCheckbox ? '' : '') +'' +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort //+(showId===true && showIdGlobal && 'idGlobal' in structureObj[i] && structureObj[i].idGlobal!==undefined && structureObj[i].idGlobal!==null ? ' (ID: '+structureObj[i].idGlobal+')' : '') +'' +' ' +(showCheckbox ? '' : '') +'' +''); } } } else { // Childs exist == Inner node == no Leaf let allChildsAreLeafs=false; if (!showLeafs) { // Are all childs leafes? Do not show chevron for last level shown allChildsAreLeafs=true; for (let child of structureObj[i].childs) { //////console.log(child); if ((!('childs' in child) || (Array.isArray(child.childs) && child.childs.length==0))) { // No childs exist == Leaf // do nothing } else { allChildsAreLeafs=false; break; } } } $returnJQueryObj=$returnJQueryObj.add('' +' '+(allChildsAreLeafs ? ' ' : ' ') +structureObj[i].nameShort //+(showId===true && showIdGlobal && 'idGlobal' in structureObj[i] && structureObj[i].idGlobal!==undefined && structureObj[i].idGlobal!==null ? ' (ID: '+structureObj[i].idGlobal+')' : '') +'' +' ' +(showCheckbox ? '' : '') +'' +''); $returnJQueryObj=$returnJQueryObj.add( ElemntCSRD.createStructureTableRowForMultipleSelection(structureObj[i].childs, (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1)), showLeafs, showIdGlobal, showId) ); } } } return $returnJQueryObj; } static isActive(elementObj, timestampUnix=null) { // returns obj: { active: active, timestampDeactivated: timestampDeactivated, deactivatedStr: deactivatedStr } let tsUnix=moment().tz('Europe/Berlin').unix(); if (timestampUnix!==null) tsUnix=timestampUnix; var active=true; var timestampDeactivated=null; var deactivatedStr=null; if (elementObj.timestamp_deactivated!==undefined && elementObj.timestamp_deactivated!==null) { active=false; timestampDeactivated=elementObj.timestamp_deactivated; deactivatedStr=null; } else if (elementObj.timestampDeactivated!==undefined && elementObj.timestampDeactivated!==null) { active=false; timestampDeactivated=elementObj.timestampDeactivated; deactivatedStr=null; } if (active && elementObj.activeTimeRange!==undefined) { if (elementObj.activeTimeRange===null) active=true; else if (Array.isArray(elementObj.activeTimeRange) && elementObj.activeTimeRange.length>0) { let activeTmp=false; let timestampDeactivatedTmp=null; for (var i=0; i0) { var str=''; for (var i=0; i0) str+=', '; str+=Helper.getHumanReadableTimestampFromUnixInSec(activeTimeRangeObj[i].activeFromTimestampInSec, true)+' - '+Helper.getHumanReadableTimestampFromUnixInSec(activeTimeRangeObj[i].activeToTimestampInSec, true); } return str; } else return '-'; } static createMultiSelectionTreeElements(tableHtmlId, structureElementsAry, showLeafs=true, startCollapsed=false, showId=true) { // Used in dashboard measurement, dashboard measures and settings admin let m1=moment(); $('#'+tableHtmlId+' tbody').empty(); // Creates the actual table $('#'+tableHtmlId+' tbody').append(ElemntCSRD.createStructureTableRowForMultipleSelection(structureElementsAry, null, showLeafs, true, showId)); // Formats the table and makes it collapsable Helper.createCollapsableTable(tableHtmlId , function(tableRow, open=true) { if (open) $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90").addClass("fa-rotate-90"); // Make sure chevron is shown correctly (i.e. is in OPEN state) else $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90"); // closed } , false ); // Event handler to propagate checkbox-changes to parent checkboxes // Fills all checkboxes $("#"+tableHtmlId+" tbody tr input[type=checkbox]").change(function(event) { ElemntCSRD.propagateUpdatesInMultiSelectionTree($(this), tableHtmlId); }); // FE Start collapsed if (startCollapsed) { $('#'+tableHtmlId+' tbody tr').each(function(i) { $(this).find('span.fa-chevron-right').removeClass('fa-rotate-90'); if (!$(this).hasClass('level1')) $(this).addClass('d-none'); }); } } /* OUTDATED - NOT USED ANYMORE */ static updateElementCheckboxesOfHigherLevelsOLD(tableHtmlId, lowestLevelTRClass='level4') { // User only for multi selection trees: For a multi selection tree, this method makes sure all higher hierarchy levels are in a proper state var level3doneAry=[]; var counterTmp=0; var counter2Tmp=0; let momentStart=moment(); let msCum1=0; let msCum2=0; let msCum3=0; $('#'+tableHtmlId+' tbody tr.'+lowestLevelTRClass+' input[type=checkbox]:checked').each(function() { // For each checkbox on lowest level counterTmp++; let momentA=moment(); let $tr=$(this).closest('tr'); let dataLevel=$tr.attr('data-level'); let dataLevelAry=dataLevel.split('_'); let dataLevelStrWithoutLowestLevel=''; for (let dataLevelLevel of dataLevelAry) { if (dataLevelStrWithoutLowestLevel.length>0) dataLevelStrWithoutLowestLevel+='_'; dataLevelStrWithoutLowestLevel+=dataLevelLevel; } msCum1+=moment()-momentA; let momentB=moment(); if (!level3doneAry.includes(dataLevelStrWithoutLowestLevel)) { // Execute only, if second lowest level was not yet executed counter2Tmp++; let momentC=moment(); level3doneAry.push(dataLevelStrWithoutLowestLevel); //Elemnt.propagateUpdatesInMultiSelectionTree($('#dashboardFiltersElementsExisting tr[data-nodeid='+$tr.attr('data-nodeid')+'] input[type=checkbox]'), tableHtmlId); ElemntCSRD.propagateUpdatesInMultiSelectionTree($tr.find('input[type=checkbox]'), tableHtmlId); msCum3+=moment()-momentC; } msCum2+=moment()-momentB; }); console.log('counterTmp = '+counterTmp); console.log('counter2Tmp = '+counter2Tmp); console.log((moment() - momentStart)+' ms', msCum1, msCum2, msCum3); } static updateElementCheckboxesOfHigherLevelsNEW(tableHtmlId, startLevel=3) { // User only for multi selection trees: For a multi selection tree, this method makes sure all higher hierarchy levels are in a proper state var level1='level1'; var level2='level2'; var level3='level3'; //var level4='level4'; var levelParent; //var levelChild; if (startLevel==3) { levelParent=level3; /*levelChild=level4;*/ } else if (startLevel==2) { levelParent=level2; /*levelChild=level3;*/ } else if (startLevel==1) { levelParent=level1; /*levelChild=level2;*/ } $('#'+tableHtmlId+' tbody tr.'+levelParent+' input[type=checkbox]').each(function() { // For each checkbox on second lowest level var $checkboxParent=$(this); let $trParent=$checkboxParent.closest('tr'); var nrChecked=0; var nrUnchecked=0; var nrIndetermined=0; var boolIndetermined=false; $trParent.siblings('tr[data-level^='+$trParent.attr('data-level')+'_]').each(function() { // Iterate over all child rows/checkboxes (1 level lower) let $checkboxChild=$(this).find('input[type=checkbox]'); if ($checkboxChild.is(':checked')) nrChecked++; else if ($checkboxChild.is(':indeterminate')) nrIndetermined++; else nrUnchecked++; if ((nrChecked>0 && nrUnchecked>0) || nrIndetermined>0) { boolIndetermined=true; return; } }); //console.log($trParent, $checkboxParent, $trParent.attr('data-level'), $trParent.siblings('tr[data-level^='+$trParent.attr('data-level')+'_]').length, boolIndetermined, nrChecked, nrUnchecked); if (boolIndetermined) ElemntCSRD.indeterminateCheckboxInMultiSelectionTree($checkboxParent); else if (nrChecked>0) ElemntCSRD.checkCheckboxInMultiSelectionTree($checkboxParent); else ElemntCSRD.uncheckCheckboxInMultiSelectionTree($checkboxParent); }); if (startLevel > 1) ElemntCSRD.updateElementCheckboxesOfHigherLevelsNEW(tableHtmlId, startLevel-1); } static propagateUpdatesInMultiSelectionTree($checkbox, tableHtmlId) { // User only for multi selection trees: For a given checkbox in a multi selection tree, this method updates the checkbox's hierarchy path (i.e. childs and parents on the path) console.log('propagateUpdatesInMultiSelectionTree'); // Get data from frontend var $tr = $checkbox.closest('tr'); var isNowChecked = $checkbox.is(':checked'); var dataLevel=$tr.attr('data-level'); var parentDataLevel=dataLevel.substring(0, dataLevel.lastIndexOf('_')); var write=$checkbox.hasClass('write'); // nor sure if this is still required // Identify direct parent checkbox let $parentCheckbox=null; if (parentDataLevel.length>0) { let $table=$checkbox.closest('table'); if ($table.length) $parentCheckbox=$table.find('tr[data-level='+parentDataLevel+'] input[type=checkbox]'); } // This checkbox is indeterminate (new state) & parent exists & parent is not checked (never happens for the initially clicked checkbox [as this checkbox can ony be checked or notChecked], happens only in up-cascade to parents) if ($checkbox.is(':indeterminate') /*&& ($parentCheckbox!==null && $parentCheckbox.is(':not(:checked)'))*/) { if ($parentCheckbox!==null /*&& $parentCheckbox.is(':not(:checked)')*/) { ElemntCSRD.indeterminateCheckboxInMultiSelectionTree($parentCheckbox); ElemntCSRD.propagateUpdatesInMultiSelectionTree($parentCheckbox, tableHtmlId); // Propagate changes upwards } // This checkboxis checked (new state) } else if (isNowChecked) { // Propagate changes downwards > Check all child checkboxes $("#"+tableHtmlId+" tbody tr[data-level^="+$tr.attr('data-level')+"_] input[type=checkbox]:not(:checked)"+(write ? '.write' : '.read')).each(function(index) { ElemntCSRD.checkCheckboxInMultiSelectionTree($(this)); // Does this trigger event handlers? No. }); // Propagate changes upwards > Check parent checkbox, if all childs are checked if ($parentCheckbox!==null && $parentCheckbox.length) { // If a parent checkbox exists var allChecked=true; $tr.siblings('[data-level^='+parentDataLevel+'_]').each(function(index) { if ($(this).find('input[type=checkbox]:not(:checked)').length>0) { // checkbox of sibling is not checked allChecked=false; return; } }); if (allChecked /*&& $parentCheckbox.is(':not(:checked)')*/) { // n-1 -> n checked // Check parent & trigger change ElemntCSRD.checkCheckboxInMultiSelectionTree($parentCheckbox); ElemntCSRD.propagateUpdatesInMultiSelectionTree($parentCheckbox, tableHtmlId); } else if ($parentCheckbox.is(':not(:indeterminate)')) { // 0 -> 1 checked indeterminate // Indeterminante check parent & trigger change ElemntCSRD.indeterminateCheckboxInMultiSelectionTree($parentCheckbox); ElemntCSRD.propagateUpdatesInMultiSelectionTree($parentCheckbox, tableHtmlId); } } } else { // is now not checked anymore // Propagate downwards > Uncheck all child checkboxes if (!$checkbox.is(':indeterminate')) { $("#"+tableHtmlId+" tbody tr[data-level^="+$tr.attr('data-level')+"_] input[type=checkbox]:checked"+(write ? '.write' : '.read')).each(function(index) { ElemntCSRD.uncheckCheckboxInMultiSelectionTree($(this)); }); } // Propagate upwards > Uncheck all parent checkboxes if ($parentCheckbox!==null && $parentCheckbox.length) { // If a parent checkbox exists // Check status of siblings var atLeastOneCheckedOrIndeterminate=false; $tr.siblings('[data-level^='+parentDataLevel+'_]').each(function(index) { if ($(this).find('input[type=checkbox]:checked').length>0 || $(this).find('input[type=checkbox]:indeterminate').length>0) { // checkbox of sibling is not checked atLeastOneCheckedOrIndeterminate=true; return; } }); // Propagate changes to parents if (!atLeastOneCheckedOrIndeterminate) { // 1 -> 0 still checked ElemntCSRD.uncheckCheckboxInMultiSelectionTree($parentCheckbox); ElemntCSRD.propagateUpdatesInMultiSelectionTree($parentCheckbox, tableHtmlId); } else { // n -> n-1 still checked ElemntCSRD.indeterminateCheckboxInMultiSelectionTree($parentCheckbox); ElemntCSRD.propagateUpdatesInMultiSelectionTree($parentCheckbox, tableHtmlId); } } } } static uncheckCheckboxInMultiSelectionTree($checkbox) { $checkbox.prop('indeterminate', false).prop('checked', false); } static checkCheckboxInMultiSelectionTree($checkbox) { $checkbox.prop('indeterminate', false).prop('checked', true); } static indeterminateCheckboxInMultiSelectionTree($checkbox) { $checkbox.prop('indeterminate', true).prop('checked', false); } static getElementByID(id) { let map=ElementOeSelectorCSRD.getStructureAsMapByNodeId(csrdStructureElements); if (map!==null) { for (let key in map) { let e=map[key]; if (e.id==id) { return e; } } } return null; } isLeaf() { if ('childs' in this && Array.isArray(this.childs)) { if (this.childs.length==0) return true; else return false; } else { return true; } } getDisplayTitle() { let str=""; if (this.name_node_level1!==undefined && this.name_node_level1!==null) str+=this.name_node_level1; if (this.name_node_level2!==undefined && this.name_node_level2!==null) str+=(str=='' ? '' : '/')+this.name_node_level2; if (this.name_node_level3!==undefined && this.name_node_level3!==null) str+=(str=='' ? '' : '/')+this.name_node_level3; if (this.name_node_level4_no!==undefined && this.name_node_level4_no!==null) str+=(str=='' ? '' : '/')+this.name_node_level4_no; //if (this.nameShort!==undefined && this.nameShort!==null) str+=(str=='' ? '' : '/')+this.nameShort+' (ID: '+this.idGlobal+')'; if (this.nameShort!==undefined && this.nameShort!==null) str+=(str=='' ? '' : '/')+this.nameShort; return str; } getNodeId() { let nodeId=""; if (this.id_node_level1!==undefined && this.id_node_level1!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level1; if (this.id_node_level2!==undefined && this.id_node_level2!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level2; if (this.id_node_level3!==undefined && this.id_node_level3!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level3; if (this.id_node_level4!==undefined && this.id_node_level4!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level4; if (this.id!==undefined && this.id!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id; return nodeId; } static getAllNodeIdsWhereCurrentUserHasWritePrivileges() { // FE if (userObj.role==3) return null; let map=ElementOeSelectorCSRD.getStructureAsMapByNodeId(csrdStructureElements); let elementPksActiveAry=null; if ('privilegesObj' in userObj && userObj.privilegesObj!==null) { if ('csrdElementPksWrite' in userObj.privilegesObj) elementPksActiveAry=userObj.privilegesObj.csrdElementPksWrite; } //console.log(elementPksActiveAry); let nodeIdsAry=[]; let nodeIds={}; let nrElementsPerElementStructure={}; for (let nodeId in map) { let eObj=map[nodeId]; if (ElemntCSRD.isActive(eObj).active) { // Is Element active at all? if (eObj.id===undefined || eObj.id===null) { // ElementStructure nodeIds[eObj.nodeId]=true; // By default, User has privileges for all ElementStructures if (!(eObj.nodeId in nrElementsPerElementStructure)) nrElementsPerElementStructure[eObj.nodeId]=0; } else { // Element // Count nr of Elements per each ElementStructure let ary=eObj.nodeId.split("_"); if (ary.length>=2) { if (!(ary[0] in nrElementsPerElementStructure)) nrElementsPerElementStructure[ary[0]]=1; else nrElementsPerElementStructure[ary[0]]++; } if (ary.length>=3) { if (!(ary[0]+'_'+ary[1] in nrElementsPerElementStructure)) nrElementsPerElementStructure[ary[0]+'_'+ary[1]]=1; else nrElementsPerElementStructure[ary[0]+'_'+ary[1]]++; } if (ary.length>=4) { if (!(ary[0]+'_'+ary[1]+'_'+ary[2] in nrElementsPerElementStructure)) nrElementsPerElementStructure[ary[0]+'_'+ary[1]+'_'+ary[2]]=1; else nrElementsPerElementStructure[ary[0]+'_'+ary[1]+'_'+ary[2]]++; } if (elementPksActiveAry.includes(eObj.id)) { // Current user has write privileges for this Element // Do nothing nodeIdsAry.push(eObj.nodeId); } else { // Current user has NO write privileges for this Element // Logic: If user has no write privileges for >0 Elements, all parent ElementStructures are disabled/forbidden // Set privilege for all parent ElementStructures to false let ary=eObj.nodeId.split("_"); if (ary.length>=1 && ary[0] in nodeIds) nodeIds[ary[0]]=false; if (ary.length>=2 && ary[0]+'_'+ary[1] in nodeIds) nodeIds[ary[0]+'_'+ary[1]]=false; if (ary.length>=3 && ary[0]+'_'+ary[1]+'_'+ary[2] in nodeIds) nodeIds[ary[0]+'_'+ary[1]+'_'+ary[2]]=false; if (ary.length>=4 && ary[0]+'_'+ary[1]+'_'+ary[2]+'_'+ary[3] in nodeIds) nodeIds[ary[0]+'_'+ary[1]+'_'+ary[2]+'_'+ary[3]]=false; } } } } //console.log('nrElementsPerElementStructure', nrElementsPerElementStructure); for (let nodeId in nodeIds) { //if (nodeIds[nodeId]) nodeIdsAry.push(nodeId); if (nodeIds[nodeId]) { if (!(nodeId in nrElementsPerElementStructure) || nrElementsPerElementStructure[nodeId]>0) { // Exclude if no child Element exists (e.g. all deactivated) -> i.e. no write privilege nodeIdsAry.push(nodeId); } } } //console.log('nodeIdsAry', nodeIdsAry); return nodeIdsAry; } } class OEMeasurements { constructor(apiOUObj) { this.id=apiOUObj.pk_organizational_units; this.accountsId=apiOUObj.fk_accounts; this.timestamp_deactivated=apiOUObj.timestamp_deactivated; this.activeTimeRange=[]; if (apiOUObj.active_from!==undefined && apiOUObj.active_from!==null && apiOUObj.active_to!==undefined && apiOUObj.active_to!==null) this.activeTimeRange.push({activeFromTimestampInSec: moment(apiOUObj.active_from).tz('Europe/Berlin').unix(), activeToTimestampInSec: moment(apiOUObj.active_to).tz('Europe/Berlin').unix()}); this.id_node_level1=apiOUObj.id_node_level1; this.id_node_level2=apiOUObj.id_node_level2; this.id_node_level3=apiOUObj.id_node_level3; this.id_node_level4=apiOUObj.id_node_level4; this.id_node_level5=apiOUObj.id_node_level5; this.name_node_level1=apiOUObj.name_node_level1; this.name_node_level2=apiOUObj.name_node_level2; this.name_node_level3=apiOUObj.name_node_level3; this.name_node_level4=apiOUObj.name_node_level4; this.name_node_level5=apiOUObj.name_node_level5; this.relatable=null; if ('relatable' in apiOUObj && apiOUObj.relatable!==null) this.relatable=apiOUObj.relatable; // Not provided by api object, but required to be filled additionally this.nameShort=apiOUObj.name_short; this.nameLong=apiOUObj.name_long; this.nodeId=null; } static loadOUStructureFromApi(callbackSuccessAry=null) { if (callbackSuccessAry===undefined || callbackSuccessAry===null) callbackSuccessAry=[]; callbackSuccessAry.push(function(structureOEsOfAccount) { structureOEs=structureOEsOfAccount; }); OEMeasurements.loadOUStructureOfAccountFromApi(userObj.accountObj.id, callbackSuccessAry); } static loadOUStructureOfAccountFromApi(fkAccounts, callbackSuccessAry=null) { ////console.log('LOAD OU STRUCTURE OF ACCOUNT ', fkAccounts, apiHost); if (fkAccounts===undefined || fkAccounts===null) { Helper.showToastr('Fehler', 'Account ID fehlt.', 'error'); return; } const tsStartApi=Date.now(); var apiUrl=apiHost+'/organizational_units_measurements/accountId/'+fkAccounts; ////console.log(apiUrl); //$.getJSON(apiUrl, function (dataFromApi) { $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { Logger.log('FRONTEND_CLIENT_API_GET_ALLOUS', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let structureOEsOfAccount=OEMeasurements.transformOUStructure(dataFromApi); //if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(structureOEsOfAccount); if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(structureOEsOfAccount); } } } }).fail(function(xhr, status, error){ ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Logger.log('FRONTEND_CLIENT_API_GET_ALLOUS', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg }); Helper.showToastr('Fehler', 'Es ist ein Fehler aufgetreten (\'callApi()\').', 'error'); */ handleFailedApiCall('FRONTEND_CLIENT_API_GET_ALLOUS', apiUrl, xhr, status, error); }); } static transformOUStructure(dataUnstructured) { dataUnstructured.sort(function(a,b) { if (a.pk_organizational_units < b.pk_organizational_units) return -1; else if (a.pk_organizational_units > b.pk_organizational_units) return 1; else return 0; }); //////console.log(dataUnstructured); var dataStructured=[]; if (dataUnstructured!==null && Array.isArray(dataUnstructured)) { for (let entryUn of dataUnstructured) { var level1Obj=null; var level2Obj=null; var level3Obj=null; var level4Obj=null; var level5Obj=null; // ### Check if structure path already exists (if not, create it) for (let entry of dataStructured) { if (entry.nodeId==entryUn.id_node_level1) { level1Obj=entry; if ('childs' in entry && Array.isArray(entry.childs)) { for (let entry2 of entry.childs) { if (entry2.nodeId==level1Obj.nodeId+'_'+entryUn.id_node_level2) { level2Obj=entry2; if ('childs' in entry2) { for (let entry3 of entry2.childs) { if (entry3.nodeId==level2Obj.nodeId+'_'+entryUn.id_node_level3) { level3Obj=entry3; if ('childs' in entry3) { for (let entry4 of entry3.childs) { if (entry4.nodeId==level3Obj.nodeId+'_'+entryUn.id_node_level4) { level4Obj=entry4; if ('childs' in entry4) { for (let entry5 of entry4.childs) { if (entry5.nodeId==level4Obj.nodeId+'_'+entryUn.id_node_level5) { level5Obj=entry5; // ... a 6th level could be added here if required } } } } } } } } } } } } } } // Create new nodes (if necessary) if (level1Obj===null && entryUn.id_node_level1!==null) { //level1Obj={nameShort: entryUn.name_node_level1, nameLong: entryUn.name_node_level1, nodeId: entryUn.id_node_level1}; level1Obj=new OEMeasurements(entryUn); level1Obj['nameShort']=entryUn.name_node_level1; level1Obj['nameLong']=entryUn.name_node_level1; level1Obj['nodeId']=entryUn.id_node_level1; dataStructured.push(level1Obj); } if (level2Obj===null && entryUn.id_node_level2!==null) { //level2Obj={nameShort: entryUn.name_node_level2, nameLong: entryUn.name_node_level2, nodeId: level1Obj.nodeId+'_'+entryUn.id_node_level2}; level2Obj=new OEMeasurements(entryUn); level2Obj['nameShort']=entryUn.name_node_level2; level2Obj['nameLong']=entryUn.name_node_level2; level2Obj['nodeId']=level1Obj.nodeId+'_'+entryUn.id_node_level2; if (!('childs' in level1Obj)) level1Obj['childs']=[]; level1Obj['childs'].push(level2Obj); } if (level3Obj===null && entryUn.id_node_level3!==null) { //level3Obj={nameShort: entryUn.name_node_level3, nameLong: entryUn.name_node_level3, nodeId: level2Obj.nodeId+'_'+entryUn.id_node_level3}; level3Obj=new OEMeasurements(entryUn); level3Obj['nameShort']=entryUn.name_node_level3; level3Obj['nameLong']=entryUn.name_node_level3; level3Obj['nodeId']=level2Obj.nodeId+'_'+entryUn.id_node_level3; if (!('childs' in level2Obj)) level2Obj['childs']=[]; level2Obj['childs'].push(level3Obj); } if (level4Obj===null && entryUn.id_node_level4!==null) { //level4Obj={nameShort: entryUn.name_node_level4, nameLong: entryUn.name_node_level4, nodeId: level3Obj.nodeId+'_'+entryUn.id_node_level4}; level4Obj=new OEMeasurements(entryUn); level4Obj['nameShort']=entryUn.name_node_level4; level4Obj['nameLong']=entryUn.name_node_level4; level4Obj['nodeId']=level3Obj.nodeId+'_'+entryUn.id_node_level4; if (!('childs' in level3Obj)) level3Obj['childs']=[]; level3Obj['childs'].push(level4Obj); } if (level5Obj===null && entryUn.id_node_level5!==null) { //level5Obj={nameShort: entryUn.name_node_level5, nameLong: entryUn.name_node_level5, nodeId: level4Obj.nodeId+'_'+entryUn.id_node_level5}; level5Obj=new OEMeasurements(entryUn); level5Obj['nameShort']=entryUn.name_node_level5; level5Obj['nameLong']=entryUn.name_node_level5; level5Obj['nodeId']=level4Obj.nodeId+'_'+entryUn.id_node_level5; if (!('childs' in level4Obj)) level4Obj['childs']=[]; level4Obj['childs'].push(level5Obj); } } } return dataStructured; } static createStructureTable(tableHtmlId, structureOEs) { $('#'+tableHtmlId+' tbody').empty(); $('#'+tableHtmlId+' tbody').append(OEMeasurements.createStructureTableRow(structureOEs)); Helper.createCollapsableTable(tableHtmlId, function(tableRow) { $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90").addClass("fa-rotate-90"); // Make sure chevron is shown correctly (i.e. is in OPEN state) }); } static createStructureTableRow(structureObj, levelStr=null) { var $returnJQueryObj=$(); var levelAry=[]; if (levelStr!==null) levelAry=levelStr.split('_'); var levelClass=''; if (levelAry.length==0) levelClass='level1'; else if (levelAry.length==1) levelClass='level2'; else if (levelAry.length==2) levelClass='level3'; else if (levelAry.length==3) levelClass='level4'; else if (levelAry.length==4) levelClass='level5'; if (structureObj!==null && Array.isArray(structureObj) && structureObj.length>0) { for (var i=0; i' +' '+structureObj[i].nameLong+'' +' '+(structureObj[i].relatable ? 'Ja' : 'Nein')+'' +' '+(!active ? 'Ja'+(activeObj.timestampDeactivated!==null ? ' ('+Helper.timestampFormat(activeObj.timestampDeactivated, false, false)+')' : '') : 'Nein')+'' +' '+Elemnt.getActiveTimeRangeStr(structureObj[i].activeTimeRange)+'' +''); } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameLong+'' +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameLong+'' +' '+(structureObj[i].relatable ? 'Ja' : 'Nein')+'' //+'  ' //+'  ' +' '+(!active ? 'Ja'+(activeObj.timestampDeactivated!==null ? ' ('+Helper.timestampFormat(activeObj.timestampDeactivated, false, false)+')' : '') : 'Nein')+'' +' '+Elemnt.getActiveTimeRangeStr(structureObj[i].activeTimeRange)+'' +''); $returnJQueryObj=$returnJQueryObj.add( OEMeasurements.createStructureTableRow(structureObj[i].childs, (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1))) ); } } } return $returnJQueryObj; } static createStructureTableRowForMultipleSelection(structureObj, levelStr=null, showDfl=false, callbackFilter=null) { var $returnJQueryObj=$(); var levelAry=[]; if (levelStr!==null) levelAry=levelStr.split('_'); var levelClass=''; if (levelAry.length==0) levelClass='level1'; else if (levelAry.length==1) levelClass='level2'; else if (levelAry.length==2) levelClass='level3'; else if (levelAry.length==3) levelClass='level4'; else if (levelAry.length==4) levelClass='level5'; if (structureObj!==null && Array.isArray(structureObj) && structureObj.length>0) { for (var i=0; i' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +(showDfl ? '' : '') +(showDfl2 ? '' : '') +(showDfl ? '' : '') +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +(showDfl ? '' : '') +(showDfl2 ? '' : '') +(showDfl ? '' : '') +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +(showDfl ? '' : '') +(showDfl2 ? '' : '') +(showDfl ? '' : '') +''); $returnJQueryObj=$returnJQueryObj.add( OEMeasurements.createStructureTableRowForMultipleSelection(structureObj[i].childs, (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1)), showDfl, callbackFilter) ); } } } } return $returnJQueryObj; } static createMultiSelectionTreeOEs(tableHtmlId, structureOEsAry, showDfl=false, callbackFilter=null) { $('#'+tableHtmlId+' tbody').empty(); // Creates actual table $('#'+tableHtmlId+' tbody').append(OEMeasurements.createStructureTableRowForMultipleSelection(structureOEsAry, null, showDfl, callbackFilter)); // Formats the table and makes it collapsable Helper.createCollapsableTable(tableHtmlId, function(tableRow) { $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90").addClass("fa-rotate-90"); // Make sure chevron is shown correctly (i.e. is in OPEN state) }); // Create event handler for checkboxes (... doing what?) $("#"+tableHtmlId+" tbody tr input[type=checkbox]:not(.dfl)").change(function(event) { // What are these 3 variables used for? var $parentTr = $(this).closest('tr'); var isNowChecked = $(this).is(":checked"); var write=$(this).hasClass('write'); // New DFL code if (showDfl) { if (isNowChecked) { // If 'Zugeordnete OE' is checked, show and check DFL checkbox $parentTr.find('input[type=checkbox].dfl').closest('label:not(.dontShow)').removeClass('d-none'); $parentTr.find('input[type=checkbox].dfl').prop('checked', true); } else { // If 'Zugeordnete OE' is unchecked, hide and uncheck DFL checkbox $parentTr.find('input[type=checkbox].dfl').closest('label:not(.dontShow)').addClass('d-none'); $parentTr.find('input[type=checkbox].dfl').prop('checked', false); } } }); } static getOEById(id, oeSubAry=structureOEs) { for (let oe of oeSubAry) { if (oe.id==id) return oe; if ('childs' in oe && oe.childs.length>0) { let result=OEMeasurements.getOEById(id, oe.childs); if (result!==null) return result; } } return null; } static getPathAryByID(id) { let oeObj=OEMeasurements.getOEById(id); //console.log(oeObj); return oeObj.path; } getDisplayTitle() { let str=""; if (this.name_node_level1!==undefined && this.name_node_level1!==null) str+=this.name_node_level1; if (this.name_node_level2!==undefined && this.name_node_level2!==null) str+=(str=='' ? '' : '/')+this.name_node_level2; if (this.name_node_level3!==undefined && this.name_node_level3!==null) str+=(str=='' ? '' : '/')+this.name_node_level3; if (this.name_node_level4!==undefined && this.name_node_level4!==null) str+=(str=='' ? '' : '/')+this.name_node_level4; if (this.name_node_level5!==undefined && this.name_node_level5!==null) str+=(str=='' ? '' : '/')+this.name_node_level5; if (this.nameShort!==undefined && this.nameShort!==null) str+=(str=='' ? '' : '/')+this.nameShort; return str; } getDisplayTitle2() { let str=""; if (this.name_node_level1!==undefined && this.name_node_level1!==null) str+=this.name_node_level1; if (this.name_node_level2!==undefined && this.name_node_level2!==null) str+=(str=='' ? '' : '/')+this.name_node_level2; if (this.name_node_level3!==undefined && this.name_node_level3!==null) str+=(str=='' ? '' : '/')+this.name_node_level3; if (this.name_node_level4!==undefined && this.name_node_level4!==null) str+=(str=='' ? '' : '/')+this.name_node_level4; if (this.name_node_level5!==undefined && this.name_node_level5!==null) str+=(str=='' ? '' : '/')+this.name_node_level5; //if (this.nameShort!==undefined && this.nameShort!==null) str+=(str=='' ? '' : '/')+this.nameShort; return str; } getNodeId() { let nodeId=""; if (this.id_node_level1!==undefined && this.id_node_level1!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level1; if (this.id_node_level2!==undefined && this.id_node_level2!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level2; if (this.id_node_level3!==undefined && this.id_node_level3!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level3; if (this.id_node_level4!==undefined && this.id_node_level4!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level4; if (this.id_node_level5!==undefined && this.id_node_level5!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level5; return nodeId; } static getAllIdsWhereCurrentUserHasWritePrivileges() { if (userObj.role==3) return null; let map=ElementOeSelector.getStructureAsMapByNodeId(structureOEs); let ouPksActiveAry=null; if ('privilegesObj' in userObj && userObj.privilegesObj!==null) { if ('ouPksWrite' in userObj.privilegesObj) { //ouPksActiveAry=userObj.privilegesObj.ouPksWrite; return userObj.privilegesObj.ouPksWrite; } } /* let nodeIdsAry=[]; for (let nodeId in map) { let ouObj=map[nodeId]; if (Element.isActive(ouObj).active) { // Is Element active at all? if (ouPksActiveAry.includes(ouObj.id)) { nodeIdsAry.push(nodeId); } } } ////console.log('nodeIdsAry', nodeIdsAry); */ return []; } } class OEMeasurementsCSRD { constructor(apiOUObj) { this.id=apiOUObj.pk_csrd_organizational_units; this.accountsId=apiOUObj.fk_accounts; this.timestamp_deactivated=apiOUObj.timestamp_deactivated; this.activeTimeRange=[]; if (apiOUObj.active_from!==undefined && apiOUObj.active_from!==null && apiOUObj.active_to!==undefined && apiOUObj.active_to!==null) this.activeTimeRange.push({activeFromTimestampInSec: moment(apiOUObj.active_from).tz('Europe/Berlin').unix(), activeToTimestampInSec: moment(apiOUObj.active_to).tz('Europe/Berlin').unix()}); this.id_node_level1=apiOUObj.id_node_level1; this.id_node_level2=apiOUObj.id_node_level2; this.id_node_level3=apiOUObj.id_node_level3; this.id_node_level4=apiOUObj.id_node_level4; this.id_node_level5=apiOUObj.id_node_level5; this.name_node_level1=apiOUObj.name_node_level1; this.name_node_level2=apiOUObj.name_node_level2; this.name_node_level3=apiOUObj.name_node_level3; this.name_node_level4=apiOUObj.name_node_level4; this.name_node_level5=apiOUObj.name_node_level5; this.relatable=null; if ('relatable' in apiOUObj && apiOUObj.relatable!==null) this.relatable=apiOUObj.relatable; // Not provided by api object, but required to be filled additionally this.nameShort=apiOUObj.name_short; this.nameLong=apiOUObj.name_long; this.nodeId=null; } static loadOUStructureFromApi(callbackSuccessAry=null) { if (callbackSuccessAry===undefined || callbackSuccessAry===null) callbackSuccessAry=[]; callbackSuccessAry.push(function(structureOEsOfAccount) { csrdStructureOEs=structureOEsOfAccount; }); OEMeasurementsCSRD.loadOUStructureOfAccountFromApi(userObj.accountObj.id, callbackSuccessAry); } static loadOUStructureOfAccountFromApi(fkAccounts, callbackSuccessAry=null) { if (fkAccounts===undefined || fkAccounts===null) { Helper.showToastr('Fehler', 'Account ID fehlt.', 'error'); return; } const tsStartApi=Date.now(); var apiUrl=apiHost+'/csrd/organizational_units_measurements/accountId/'+fkAccounts; $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { Logger.log('FRONTEND_CLIENT_API_GET_CSRD_ALLOUS', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let structureOEsOfAccount=OEMeasurementsCSRD.transformOUStructure(dataFromApi); if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(structureOEsOfAccount); } } } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_ALLOUS', apiUrl, xhr, status, error); }); } static transformOUStructure(dataUnstructured) { dataUnstructured.sort(function(a,b) { if (a.pk_csrd_organizational_units < b.pk_csrd_organizational_units) return -1; else if (a.pk_csrd_organizational_units > b.pk_csrd_organizational_units) return 1; else return 0; }); var dataStructured=[]; if (dataUnstructured!==null && Array.isArray(dataUnstructured)) { for (let entryUn of dataUnstructured) { var level1Obj=null; var level2Obj=null; var level3Obj=null; var level4Obj=null; var level5Obj=null; // ### Check if structure path already exists (if not, create it) for (let entry of dataStructured) { if (entry.nodeId==entryUn.id_node_level1) { level1Obj=entry; if ('childs' in entry && Array.isArray(entry.childs)) { for (let entry2 of entry.childs) { if (entry2.nodeId==level1Obj.nodeId+'_'+entryUn.id_node_level2) { level2Obj=entry2; if ('childs' in entry2) { for (let entry3 of entry2.childs) { if (entry3.nodeId==level2Obj.nodeId+'_'+entryUn.id_node_level3) { level3Obj=entry3; if ('childs' in entry3) { for (let entry4 of entry3.childs) { if (entry4.nodeId==level3Obj.nodeId+'_'+entryUn.id_node_level4) { level4Obj=entry4; if ('childs' in entry4) { for (let entry5 of entry4.childs) { if (entry5.nodeId==level4Obj.nodeId+'_'+entryUn.id_node_level5) { level5Obj=entry5; // ... a 6th level could be added here if required } } } } } } } } } } } } } } // Create new nodes (if necessary) if (level1Obj===null && entryUn.id_node_level1!==null) { //level1Obj={nameShort: entryUn.name_node_level1, nameLong: entryUn.name_node_level1, nodeId: entryUn.id_node_level1}; level1Obj=new OEMeasurementsCSRD(entryUn); level1Obj['nameShort']=entryUn.name_node_level1; level1Obj['nameLong']=entryUn.name_node_level1; level1Obj['nodeId']=entryUn.id_node_level1; dataStructured.push(level1Obj); } if (level2Obj===null && entryUn.id_node_level2!==null) { //level2Obj={nameShort: entryUn.name_node_level2, nameLong: entryUn.name_node_level2, nodeId: level1Obj.nodeId+'_'+entryUn.id_node_level2}; level2Obj=new OEMeasurementsCSRD(entryUn); level2Obj['nameShort']=entryUn.name_node_level2; level2Obj['nameLong']=entryUn.name_node_level2; level2Obj['nodeId']=level1Obj.nodeId+'_'+entryUn.id_node_level2; if (!('childs' in level1Obj)) level1Obj['childs']=[]; level1Obj['childs'].push(level2Obj); } if (level3Obj===null && entryUn.id_node_level3!==null) { //level3Obj={nameShort: entryUn.name_node_level3, nameLong: entryUn.name_node_level3, nodeId: level2Obj.nodeId+'_'+entryUn.id_node_level3}; level3Obj=new OEMeasurementsCSRD(entryUn); level3Obj['nameShort']=entryUn.name_node_level3; level3Obj['nameLong']=entryUn.name_node_level3; level3Obj['nodeId']=level2Obj.nodeId+'_'+entryUn.id_node_level3; if (!('childs' in level2Obj)) level2Obj['childs']=[]; level2Obj['childs'].push(level3Obj); } if (level4Obj===null && entryUn.id_node_level4!==null) { //level4Obj={nameShort: entryUn.name_node_level4, nameLong: entryUn.name_node_level4, nodeId: level3Obj.nodeId+'_'+entryUn.id_node_level4}; level4Obj=new OEMeasurementsCSRD(entryUn); level4Obj['nameShort']=entryUn.name_node_level4; level4Obj['nameLong']=entryUn.name_node_level4; level4Obj['nodeId']=level3Obj.nodeId+'_'+entryUn.id_node_level4; if (!('childs' in level3Obj)) level3Obj['childs']=[]; level3Obj['childs'].push(level4Obj); } if (level5Obj===null && entryUn.id_node_level5!==null) { //level5Obj={nameShort: entryUn.name_node_level5, nameLong: entryUn.name_node_level5, nodeId: level4Obj.nodeId+'_'+entryUn.id_node_level5}; level5Obj=new OEMeasurementsCSRD(entryUn); level5Obj['nameShort']=entryUn.name_node_level5; level5Obj['nameLong']=entryUn.name_node_level5; level5Obj['nodeId']=level4Obj.nodeId+'_'+entryUn.id_node_level5; if (!('childs' in level4Obj)) level4Obj['childs']=[]; level4Obj['childs'].push(level5Obj); } } } return dataStructured; } static createStructureTable(tableHtmlId, csrdStructureOEs) { $('#'+tableHtmlId+' tbody').empty(); $('#'+tableHtmlId+' tbody').append(OEMeasurementsCSRD.createStructureTableRow(csrdStructureOEs)); Helper.createCollapsableTable(tableHtmlId, function(tableRow) { $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90").addClass("fa-rotate-90"); // Make sure chevron is shown correctly (i.e. is in OPEN state) }); } static createStructureTableRow(structureObj, levelStr=null) { var $returnJQueryObj=$(); var levelAry=[]; if (levelStr!==null) levelAry=levelStr.split('_'); var levelClass=''; if (levelAry.length==0) levelClass='level1'; else if (levelAry.length==1) levelClass='level2'; else if (levelAry.length==2) levelClass='level3'; else if (levelAry.length==3) levelClass='level4'; else if (levelAry.length==4) levelClass='level5'; if (structureObj!==null && Array.isArray(structureObj) && structureObj.length>0) { for (var i=0; i' +' '+structureObj[i].nameLong+'' +' '+(structureObj[i].relatable ? 'Ja' : 'Nein')+'' +' '+(!active ? 'Ja'+(activeObj.timestampDeactivated!==null ? ' ('+Helper.timestampFormat(activeObj.timestampDeactivated, false, false)+')' : '') : 'Nein')+'' +' '+ElemntCSRD.getActiveTimeRangeStr(structureObj[i].activeTimeRange)+'' +''); } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameLong+'' +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameLong+'' +' '+(structureObj[i].relatable ? 'Ja' : 'Nein')+'' //+'  ' //+'  ' +' '+(!active ? 'Ja'+(activeObj.timestampDeactivated!==null ? ' ('+Helper.timestampFormat(activeObj.timestampDeactivated, false, false)+')' : '') : 'Nein')+'' +' '+ElemntCSRD.getActiveTimeRangeStr(structureObj[i].activeTimeRange)+'' +''); $returnJQueryObj=$returnJQueryObj.add( OEMeasurementsCSRD.createStructureTableRow(structureObj[i].childs, (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1))) ); } } } return $returnJQueryObj; } static createStructureTableRowForMultipleSelection(structureObj, levelStr=null, showDfl=false, callbackFilter=null) { var $returnJQueryObj=$(); var levelAry=[]; if (levelStr!==null) levelAry=levelStr.split('_'); var levelClass=''; if (levelAry.length==0) levelClass='level1'; else if (levelAry.length==1) levelClass='level2'; else if (levelAry.length==2) levelClass='level3'; else if (levelAry.length==3) levelClass='level4'; else if (levelAry.length==4) levelClass='level5'; if (structureObj!==null && Array.isArray(structureObj) && structureObj.length>0) { for (var i=0; i' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +(showDfl ? '' : '') +(showDfl2 ? '' : '') +(showDfl ? '' : '') +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +(showDfl ? '' : '') +(showDfl2 ? '' : '') +(showDfl ? '' : '') +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +(showDfl ? '' : '') +(showDfl2 ? '' : '') +(showDfl ? '' : '') +''); $returnJQueryObj=$returnJQueryObj.add( OEMeasurementsCSRD.createStructureTableRowForMultipleSelection(structureObj[i].childs, (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1)), showDfl, callbackFilter) ); } } } } return $returnJQueryObj; } static createMultiSelectionTreeOEs(tableHtmlId, structureOEsAry, showDfl=false, callbackFilter=null) { $('#'+tableHtmlId+' tbody').empty(); // Creates actual table $('#'+tableHtmlId+' tbody').append(OEMeasurementsCSRD.createStructureTableRowForMultipleSelection(structureOEsAry, null, showDfl, callbackFilter)); // Formats the table and makes it collapsable Helper.createCollapsableTable(tableHtmlId, function(tableRow) { $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90").addClass("fa-rotate-90"); // Make sure chevron is shown correctly (i.e. is in OPEN state) }); // Create event handler for checkboxes (... doing what?) $("#"+tableHtmlId+" tbody tr input[type=checkbox]:not(.dfl)").change(function(event) { // What are these 3 variables used for? var $parentTr = $(this).closest('tr'); var isNowChecked = $(this).is(":checked"); var write=$(this).hasClass('write'); // New DFL code if (showDfl) { if (isNowChecked) { // If 'Zugeordnete OE' is checked, show and check DFL checkbox $parentTr.find('input[type=checkbox].dfl').closest('label:not(.dontShow)').removeClass('d-none'); $parentTr.find('input[type=checkbox].dfl').prop('checked', true); } else { // If 'Zugeordnete OE' is unchecked, hide and uncheck DFL checkbox $parentTr.find('input[type=checkbox].dfl').closest('label:not(.dontShow)').addClass('d-none'); $parentTr.find('input[type=checkbox].dfl').prop('checked', false); } } }); } static getOEById(id, oeSubAry=csrdStructureOEs) { for (let oe of oeSubAry) { if (oe.id==id) return oe; if ('childs' in oe && oe.childs.length>0) { let result=OEMeasurementsCSRD.getOEById(id, oe.childs); if (result!==null) return result; } } return null; } static getPathAryByID(id) { let oeObj=OEMeasurementsCSRD.getOEById(id); //console.log(oeObj); return oeObj.path; } getDisplayTitle() { let str=""; if (this.name_node_level1!==undefined && this.name_node_level1!==null) str+=this.name_node_level1; if (this.name_node_level2!==undefined && this.name_node_level2!==null) str+=(str=='' ? '' : '/')+this.name_node_level2; if (this.name_node_level3!==undefined && this.name_node_level3!==null) str+=(str=='' ? '' : '/')+this.name_node_level3; if (this.name_node_level4!==undefined && this.name_node_level4!==null) str+=(str=='' ? '' : '/')+this.name_node_level4; if (this.name_node_level5!==undefined && this.name_node_level5!==null) str+=(str=='' ? '' : '/')+this.name_node_level5; if (this.nameShort!==undefined && this.nameShort!==null) str+=(str=='' ? '' : '/')+this.nameShort; return str; } getDisplayTitle2() { let str=""; if (this.name_node_level1!==undefined && this.name_node_level1!==null) str+=this.name_node_level1; if (this.name_node_level2!==undefined && this.name_node_level2!==null) str+=(str=='' ? '' : '/')+this.name_node_level2; if (this.name_node_level3!==undefined && this.name_node_level3!==null) str+=(str=='' ? '' : '/')+this.name_node_level3; if (this.name_node_level4!==undefined && this.name_node_level4!==null) str+=(str=='' ? '' : '/')+this.name_node_level4; if (this.name_node_level5!==undefined && this.name_node_level5!==null) str+=(str=='' ? '' : '/')+this.name_node_level5; //if (this.nameShort!==undefined && this.nameShort!==null) str+=(str=='' ? '' : '/')+this.nameShort; return str; } getNodeId() { let nodeId=""; if (this.id_node_level1!==undefined && this.id_node_level1!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level1; if (this.id_node_level2!==undefined && this.id_node_level2!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level2; if (this.id_node_level3!==undefined && this.id_node_level3!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level3; if (this.id_node_level4!==undefined && this.id_node_level4!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level4; if (this.id_node_level5!==undefined && this.id_node_level5!==null) nodeId+=(nodeId=='' ? '' : '_')+this.id_node_level5; return nodeId; } static getAllIdsWhereCurrentUserHasWritePrivileges() { if (userObj.role==3) return null; let map=ElementOeSelectorCSRD.getStructureAsMapByNodeId(csrdStructureOEs); let ouPksActiveAry=null; if ('privilegesObj' in userObj && userObj.privilegesObj!==null) { if ('csrdOuPksWrite' in userObj.privilegesObj) { return userObj.privilegesObj.csrdOuPksWrite; } } return []; } } class LogMeasurementESG { constructor(apiLogMeasurementESGObj) { this.timestamp=null; if (apiLogMeasurementESGObj.timestamp!==undefined && apiLogMeasurementESGObj.timestamp!==null) this.timestamp=moment(apiLogMeasurementESGObj.timestamp).tz('Europe/Berlin'); this.user=null; if (apiLogMeasurementESGObj.user!==undefined && apiLogMeasurementESGObj.user!==null) this.user=User.createUserObjByApiData(apiLogMeasurementESGObj.user); this.event=null; if (apiLogMeasurementESGObj.event!==undefined && apiLogMeasurementESGObj.event!==null) this.event=apiLogMeasurementESGObj.event; this.details=null; if (apiLogMeasurementESGObj.details!==undefined && apiLogMeasurementESGObj.details!==null) this.details=apiLogMeasurementESGObj.details; } static loadLogsFromApi(measurementId, callbackSuccess) { const tsStartApi=Date.now(); var apiUrl=apiHost+'/log/measurement_esg/'+measurementId; $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { console.log(dataFromApi); Logger.log('FRONTEND_CLIENT_API_GET_LOGS_MEASUREMENT', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, type: 'esg' }); let logsAry=[]; if (dataFromApi!==null && dataFromApi.length>0) { for (let lm of dataFromApi) { logsAry.push(new LogMeasurementESG(lm)); } } if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(logsAry); } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_LOGS_MEASUREMENT', apiUrl, xhr, status, error); }); } } class LogMeasurementCSRD { constructor(apiLogMeasurementCSRDObj) { this.timestamp=null; if (apiLogMeasurementCSRDObj.timestamp!==undefined && apiLogMeasurementCSRDObj.timestamp!==null) this.timestamp=moment(apiLogMeasurementCSRDObj.timestamp).tz('Europe/Berlin'); this.user=null; if (apiLogMeasurementCSRDObj.user!==undefined && apiLogMeasurementCSRDObj.user!==null) this.user=User.createUserObjByApiData(apiLogMeasurementCSRDObj.user); this.event=null; if (apiLogMeasurementCSRDObj.event!==undefined && apiLogMeasurementCSRDObj.event!==null) this.event=apiLogMeasurementCSRDObj.event; this.details=null; if (apiLogMeasurementCSRDObj.details!==undefined && apiLogMeasurementCSRDObj.details!==null) this.details=apiLogMeasurementCSRDObj.details; } static loadLogsFromApi(measurementId, callbackSuccess) { const tsStartApi=Date.now(); var apiUrl=apiHost+'/log/measurement_csrd/'+measurementId; $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { console.log(dataFromApi); Logger.log('FRONTEND_CLIENT_API_GET_LOGS_MEASUREMENT', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, type: 'csrd' }); let logsAry=[]; if (dataFromApi!==null && dataFromApi.length>0) { for (let lm of dataFromApi) { logsAry.push(new LogMeasurementCSRD(lm)); } } if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(logsAry); } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_LOGS_MEASUREMENT', apiUrl, xhr, status, error); }); } } class Measurement { // Messpunkt constructor(apiMeasurementObj) { //////console.log(apiMeasurementObj); this.id=apiMeasurementObj.pk_measurements; if (apiMeasurementObj.usersCreator!==undefined && apiMeasurementObj.usersCreator!==null) { //id, email, pwdSaltedMd5, role, firstname, lastname, title, department, privilegesObj, accountObj let u=apiMeasurementObj.usersCreator; this.userCreatorObj=new User(u.pk_users, null, null, u.firstname, u.lastname, null, null, null, null, null); } this.valueMet=apiMeasurementObj.value_met; this.valueBin=apiMeasurementObj.value_bin; this.valueCat=apiMeasurementObj.value_cat; this.calculation_input_values=null; if ('calculation_input_values' in apiMeasurementObj && apiMeasurementObj.calculation_input_values!==null) this.calculation_input_values=apiMeasurementObj.calculation_input_values; this.note=apiMeasurementObj.note; this.timestampPointUnixInSec=null; if (apiMeasurementObj.timestamp_point!==undefined && apiMeasurementObj.timestamp_point!==null) this.timestampPointUnixInSec=moment(apiMeasurementObj.timestamp_point).tz('Europe/Berlin').unix(); this.timestampRangeFromUnixInSec=null; if (apiMeasurementObj.timestamp_range_from!==undefined && apiMeasurementObj.timestamp_range_from!==null) this.timestampRangeFromUnixInSec=moment(apiMeasurementObj.timestamp_range_from).tz('Europe/Berlin').unix(); this.timestampRangeToUnixInSec=null; if (apiMeasurementObj.timestamp_range_to!==undefined && apiMeasurementObj.timestamp_range_to!==null) this.timestampRangeToUnixInSec=moment(apiMeasurementObj.timestamp_range_to).tz('Europe/Berlin').unix(); this.automaticFromConsumptionModule=null; if (apiMeasurementObj.automatic_from_consumption_module!==undefined) this.automaticFromConsumptionModule=apiMeasurementObj.automatic_from_consumption_module; this.timestampDeactivated=apiMeasurementObj.timestamp_deactivated; this.approvals=[]; if (apiMeasurementObj.measurementApprovals!==undefined && apiMeasurementObj.measurementApprovals!==null && Array.isArray(apiMeasurementObj.measurementApprovals)) { for (let idx=0; idx approvedObj.timestampUnixInSec)) { if (a.timestampApproved!==null) { //approvedObj={ approved: true, declined: false, timestampUnixInSec: moment(a.timestampApproved).tz('Europe/Berlin').unix(), user: a.userApproverActual, measurementApprovalId: a.id, measurementObj: this, measurementApprovalObj: a, deleteApproval: {} }; approvedObj={ approved: true, declined: false, timestampUnixInSec: moment(a.timestampApproved).tz('Europe/Berlin').unix(), user: a.userApproverActual, measurementApprovalId: a.id, measurementObj: this, measurementApprovalObj: a }; } else if (a.timestampDeclined!==null) { //approvedObj={ approved: false, declined: true, timestampUnixInSec: moment(a.timestampDeclined).tz('Europe/Berlin').unix(), user: a.userApproverActual, measurementApprovalId: a.id, measurementObj: this, measurementApprovalObj: a, deleteApproval: {} }; approvedObj={ approved: false, declined: true, timestampUnixInSec: moment(a.timestampDeclined).tz('Europe/Berlin').unix(), user: a.userApproverActual, measurementApprovalId: a.id, measurementObj: this, measurementApprovalObj: a }; } } } if (approvedObj!==null) { approvedObj['fileExists']=[]; for (let af of approvedObj.measurementApprovalObj.approvalFiles) { if (af.timestampDeactivated===null) { // File is active approvedObj['fileExists'].push(af); } } } if (breakAtEndOfLoop===true) break; } } lastApproveTimestamp=null; lastApproveUser=null; breakAtEndOfLoop=false; for (let a of this.approvals) { if (a.type=='MEASUREMENT_DELETE') { //if (!('deleteApproval' in approvedObj)) approvedObj['deleteApproval']={}; if (a.timestampApproved===null) { // Not yet approved approvedObj['deleteApproval']={ approved: false, user: a.userApprover, measurementApprovalId: a.id }; breakAtEndOfLoop=true; } else { // Is approved if (!('deleteApproval' in approvedObj) || !('approved' in approvedObj['deleteApproval']) || moment(a.timestampApproved).tz('Europe/Berlin').unix() > approvedObj.timestampUnixInSec) { approvedObj['deleteApproval']={ approved: true, timestampUnixInSec: moment(a.timestampApproved).tz('Europe/Berlin').unix(), user: a.userApproverActual, measurementApprovalId: a.id }; } } if (breakAtEndOfLoop===true) break; } } if (approvedObj===null) return { approved: false, declined: false, measurementObj: this }; else return approvedObj; } createPostData(isEdit=false) { // ### Check data consistency & assemble POST data obj var postData={}; if (isEdit) { postData['value_met']=null; postData['value_bin']=null; postData['value_cat']=null; postData['timestamp_point']=null; postData['timestamp_range_from']=null; postData['timestamp_range_to']=null; } // Values let count=0; if (this.valueMet!==undefined && this.valueMet!==null) { count++; try { Helper.formatMeasurementValue(this.valueMet, 'metric'); // just call to utilize type check and (return value is irrelevant here) } catch (e) { Helper.showToastr('Fehler', 'Metrischer Wert liegt nicht in korrektem Format vor.', 'error'); return; } postData['value_met']=this.valueMet; } if (this.valueBin!==undefined && this.valueBin!==null) { count++; try { Helper.formatMeasurementValue(this.valueBin, 'binary'); // just call to utilize type check and (return value is irrelevant here) } catch (e) { Helper.showToastr('Fehler', 'Binärer Wert liegt nicht in korrektem Format vor.', 'error'); return; } postData['value_bin']=this.valueBin; } if (this.valueCat!==undefined && this.valueCat!==null) { count++; try { Helper.formatMeasurementValue(this.valueCat, 'categoric'); // just call to utilize type check and (return value is irrelevant here) } catch (e) { Helper.showToastr('Fehler', 'Kategorischer Wert liegt nicht in korrektem Format vor.', 'error'); return; } postData['value_cat']=this.valueCat; } if (count!=1) { Helper.showToastr('Fehler', 'Es wurden 0 oder >1 Werte übergeben.', 'error'); return; } //if (count>1) { Helper.showToastr('Fehler', 'Es wurden >1 Werte übergeben.', 'error'); return; } // Calculation input fields (if required) if (this.calculation_input_values!==undefined && this.calculation_input_values!==null) { postData['calculation_input_values']=this.calculation_input_values; } // Time count=0; if (this.timestampPointUnixInSec!==undefined && this.timestampPointUnixInSec!==null) { count++; //postData['timestamp_point']=moment.unix(this.timestampPointUnixInSec).local().format('YYYY-MM-DD HH:mm:ssZZ'); postData['timestamp_point']=moment.unix(this.timestampPointUnixInSec).tz('Europe/Berlin').format(); } if (this.timestampRangeFromUnixInSec!==undefined && this.timestampRangeFromUnixInSec!==null && this.timestampRangeToUnixInSec!==undefined && this.timestampRangeToUnixInSec!==null) { count++; if (this.timestampRangeFromUnixInSec > this.timestampRangeToUnixInSec) { Helper.showToastr('Fehler', 'Zeitraum bis liegt vor Zeitraum von.', 'error'); return; } //postData['timestamp_range_from']=moment.unix(this.timestampRangeFromUnixInSec).local().format('YYYY-MM-DD HH:mm:ssZZ'); postData['timestamp_range_from']=moment.unix(this.timestampRangeFromUnixInSec).tz('Europe/Berlin').format(); //postData['timestamp_range_to']=moment.unix(this.timestampRangeToUnixInSec).local().format('YYYY-MM-DD HH:mm:ssZZ'); postData['timestamp_range_to']=moment.unix(this.timestampRangeToUnixInSec).tz('Europe/Berlin').format(); } if (count!=1) { Helper.showToastr('Fehler', 'Zeitpunkt oder Zeitraum wurden nicht korrekt angegeben.', 'error'); return; } // Comment if (this.note!==undefined) { postData['note']=this.note; } if (!isEdit) { // User creator if (this.userCreatorObj!==undefined && this.userCreatorObj!==null && this.userCreatorObj.id!==null) { postData['usersCreator']={ pk_users: this.userCreatorObj.id }; } else { Helper.showToastr('Fehler', 'Der erstellende User wurde nicht übergeben.', 'error'); return; } } return postData; } checkTimeConstraints(postData, elementOeCombiId, currentMeasurementObj=null) { // ### Logic checks which lead to an additional confirmation required from the user let textModal=[]; let apObj=userObj.accountObj.getCurrentAcquisitionPeriodMeasurementsObj(); if (postData['timestamp_point']!==undefined && postData['timestamp_point']!==null) { if (moment(postData['timestamp_point']).tz('Europe/Berlin').isBefore(moment().tz('Europe/Berlin').subtract(3, 'y'))) textModal.push('Der Messpunkt liegt mehr als 3 Jahre in der Vergangenheit.'); if (moment(postData['timestamp_point']).tz('Europe/Berlin').isAfter(moment().tz('Europe/Berlin'))) textModal.push('Der Messpunkt liegt in der Zukunft.'); if (!userObj.accountObj.isTimestampInAcquisitionPeriodMeasurements(postData['timestamp_point'])) textModal.push('Der Messpunkt befindet sich nicht in einem Erfassungszeitraum.'); else { if (apObj!==null && moment(postData['timestamp_point']).tz('Europe/Berlin').isBefore(moment(apObj.timestamp_from_incl))) textModal.push('Der Messpunkt liegt vor dem aktuellen Erfassungszeitraum \''+apObj.name+'\' ('+Helper.timestampFormat(apObj.timestamp_from_incl, false, false)+' bis '+Helper.timestampFormat(apObj.timestamp_to_incl, false, false)+').'); if (apObj!==null && moment(postData['timestamp_point']).tz('Europe/Berlin').isAfter(moment(apObj.timestamp_to_incl))) textModal.push('Der Messpunkt liegt nach dem aktuellen Erfassungszeitraum \''+apObj.name+'\' ('+Helper.timestampFormat(apObj.timestamp_from_incl, false, false)+' bis '+Helper.timestampFormat(apObj.timestamp_to_incl, false, false)+').'); } } if (postData['timestamp_range_to']!==undefined && postData['timestamp_range_to']!==null) { if (moment(postData['timestamp_range_to']).tz('Europe/Berlin').isBefore(moment().tz('Europe/Berlin').subtract(3, 'y'))) textModal.push('Das Zeitraumende liegt mehr als 3 Jahre in der Vergangenheit.'); if (moment(postData['timestamp_range_to']).tz('Europe/Berlin').isAfter(moment().tz('Europe/Berlin'))) textModal.push('Der Messpunkt liegt in der Zukunft.'); if (!userObj.accountObj.isTimestampInAcquisitionPeriodMeasurements(postData['timestamp_range_to'])) textModal.push('Der Messpunkt (Zeitraum bis) befindet sich nicht in einem Erfassungszeitraum.'); else { if (apObj!==null && moment(postData['timestamp_range_to']).tz('Europe/Berlin').isBefore(moment(apObj.timestamp_from_incl))) textModal.push('Der Messpunkt (Zeitraum bis) liegt vor dem aktuellen Erfassungszeitraum \''+apObj.name+'\' ('+Helper.timestampFormat(apObj.timestamp_from_incl, false, false)+' bis '+Helper.timestampFormat(apObj.timestamp_to_incl, false, false)+').'); if (apObj!==null && moment(postData['timestamp_range_to']).tz('Europe/Berlin').isAfter(moment(apObj.timestamp_to_incl))) textModal.push('Der Messpunkt (Zeitraum bis) liegt nach dem aktuellen Erfassungszeitraum \''+apObj.name+'\' ('+Helper.timestampFormat(apObj.timestamp_from_incl, false, false)+' bis '+Helper.timestampFormat(apObj.timestamp_to_incl, false, false)+').'); } } if (postData['timestamp_range_from']!==undefined && postData['timestamp_range_from']!==null && postData['timestamp_range_to']!==undefined && postData['timestamp_range_to']!==null) { if (moment(postData['timestamp_range_from']).tz('Europe/Berlin').add(1, 'y').isBefore(moment(postData['timestamp_range_to']).tz('Europe/Berlin'))) textModal.push('Der Zeitraum beträgt mehr als 1 Jahr.'); // Check if time range is consecutive to existing time ranges & check for overlaps let consecutive=false; let overlap=false; let counter=0; //////console.log(elementOeCombinations, elementOeCombiId); for (let eoc of elementOeCombinations) { if (eoc.id==elementOeCombiId) { // Find correct elementOeCombi //////console.log(eoc.measurementsObjAry); for (let m of eoc.measurementsObjAry) { // For all existing measurements if (m.timestampDeactivated===null) { // If active (approval status is irrelevant here) if (currentMeasurementObj===null || currentMeasurementObj.id!=m.id) { counter++; ////console.log(moment(postData['timestamp_range_from']).startOf('day'), moment(m.timestampRangeToUnixInSec*1000).startOf('day')); // Check consecutive time ranges //if (Math.abs(moment(postData['timestamp_range_from']).unix() - m.timestampRangeToUnixInSec) < 60*60*24) { // max. 1 day difference if (moment(postData['timestamp_range_from']).tz('Europe/Berlin').startOf('day').isSame(moment(m.timestampRangeToUnixInSec*1000).tz('Europe/Berlin').startOf('day').add(1, 'days'))) { consecutive=true; break; } //if (Math.abs(moment(postData['timestamp_range_to']).unix() - m.timestampRangeFromUnixInSec) < 60*60*24) { // max. 1 day difference if (moment(postData['timestamp_range_to']).tz('Europe/Berlin').startOf('day').add(1, 'days').isSame(moment(m.timestampRangeFromUnixInSec*1000).tz('Europe/Berlin').startOf('day'))) { consecutive=true; break; } // Check overlaps //if (excludeMeasurementObjFromOverlapCheck.id!=m.id) { if (moment(postData['timestamp_range_from']).tz('Europe/Berlin').startOf('day').isSameOrBefore(moment(m.timestampRangeToUnixInSec*1000).tz('Europe/Berlin').startOf('day')) && moment(postData['timestamp_range_to']).tz('Europe/Berlin').startOf('day').isSameOrAfter(moment(m.timestampRangeFromUnixInSec*1000).tz('Europe/Berlin').startOf('day'))) { overlap=true; break; } //if (moment(postData['timestamp_range_to']).startOf('day').add(1, 'days').isAfter(moment(m.timestampRangeFromUnixInSec*1000).startOf('day')) // && moment(postData['timestamp_range_from']).startOf('day').isBefore(moment(m.timestampRangeFromUnixInSec*1000).startOf('day'))) { // overlap=true; // break; //} //} } } } break; } } //////console.log('COUNTER', counter); if (counter==0) consecutive=true; // To account for very first measurement to be added (i.e. do not through warning then) if (!consecutive) textModal.push('Der Zeitraum schließt nicht direkt an einen vorhanden Messpunkt-Zeitraum an.'); if (overlap) { //textModal.push('Der Zeitraum überlappt mit einem vorhandenen Messpunkt-Zeitraum.'); Helper.showToastr('Fehler', 'Der Zeitraum überlappt mit einem vorhandenen Messpunkt-Zeitraum.', 'error'); return null; } } // FOLLOWING CODE IS DEAD CODE AS A MISSING APPROVAL DOCUMENT IS ALREADY ACKNOWLEDGED WITH AN ERROR EARLIER IN THE CODE EXECUTION // Check if document upload is required, but missing if (this.isApprovalFileRequiredForNewMeasurement(elementOeCombiId, postData['value_bin'], postData['value_met'])) { if (!this.approvalFileExistsOrIsSelected(currentMeasurementObj)) { textModal.push('Der Messpunkt verlangt ein Freigabe-Dokument, es wurde aber bisher kein Dokument hochgeladen.'); } } return textModal; } saveNew(elementOeCombiId, callbackSuccess) { ////console.log('saveNew', this); /* * { * "value_met": 5.2341 * , "timestamp_range_from": "2020-02-01 09:24:00+01" * , "timestamp_range_to": "2020-02-28 09:25:00+01" * } */ // ### Check data consistency & assemble POST data obj var postData=this.createPostData(); if (postData==null) return; // File required if (this.isApprovalFileRequiredForNewMeasurement(elementOeCombiId, postData['value_bin'], postData['value_met']) && !this.approvalFileExistsOrIsSelected(null)) { Helper.showToastr('Fehler', 'Mindestens ein Freigabe-Dokument ist erforderlich.', 'error'); return; } // ### Logic checks which lead to an additional confirmation required from the user let textModal=this.checkTimeConstraints(postData, elementOeCombiId); if (textModal===null) return; function callApi() { // ### Call API //var apiUrl=apiHost+'/measurement/new/element_oe_combi/'+elementOeCombiId+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measurement/new/element_oe_combi/'+elementOeCombiId; ////console.log(apiUrl); let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_MEASUREMENT', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); //if (data.status=='ok') { if ('pk_measurements' in data && data.pk_measurements!==null && data.pk_measurements!==undefined && data.pk_measurements!='') { //Logger.log('info', 'api_call', {url: apiUrl, durationInMs: (Date.now()-tsStartApi)}); //Logger.log('info', 'admin_measurement_created', {data: data}); Helper.showToastr('Erfolg', 'Neuer Messpunkt wurde gespeichert.', 'success'); let measurementObj=new Measurement(data); ////console.log('measurementObj: ', measurementObj); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(measurementObj); } else { // TODO: THIS PIECE OF CODE SHOULD NOT BE REQUIRED, AS ERRORS ARE RETURNED BY SPECIFIC HTTP STATUS CODES (THIS ALSO TRUE FOR OTHER AJAX CALLS HERE ...) ////console.log(data); Logger.log('FRONTEND_CLIENT_API_NEW_MEASUREMENT', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); Helper.showToastr('Fehler', 'Fehler beim Speichern des Messpunkts: '+data.msg, 'error'); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_NEW_MEASUREMENT', apiUrl, xhr, status, error, null, { json: jsonData }); }); } if (textModal.length>0) { let str=''; for (let t of textModal) { str+=(str=='' ? '' : '
    ')+''+t; } //Helper.confirmModal(textModal.join('
    ')+'
     
    Bitte das Speichern bestätigen.', 'Bestätigen', function() { callApi(); }, 'Speichern bestätigen', true); Helper.confirmModal(str+'
     
    Bitte das Speichern bestätigen.', 'Bestätigen', function() { callApi(); }, 'Speichern bestätigen', true); } else { callApi(); } } save(elementOeCombiId, callbackSuccess) { ////console.log('save', this); /* * { * "value_met": 5.2341 * , "timestamp_range_from": "2020-02-01 09:24:00+01" * , "timestamp_range_to": "2020-02-28 09:25:00+01" * } */ // ### Check data consistency & assemble POST data obj var postData=this.createPostData(true); if (postData===null || postData===undefined) { //console.log('postData null'); return; } let textModal=this.checkTimeConstraints(postData, elementOeCombiId, this); if (textModal===null) { //console.log('textModal null'); return; } function callApi(measurementId) { // ### Call API //var apiUrl=apiHost+'/measurement/edit/'+measurementId+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measurement/edit/'+measurementId; ////console.log(apiUrl, postData); let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASUREMENT', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); //Logger.log('info', 'admin_measurement_edited', {page: 'settings/profile', data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASUREMENT', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Helper.showToastr('Fehler', 'Daten können nicht gespeichert werden ('+errorMsg+').', 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASUREMENT', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg }); */ handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASUREMENT', apiUrl, xhr, status, error, null, { json: jsonData }); }); } let parent=this; if (textModal.length>0) { let str=''; for (let t of textModal) { str+=(str=='' ? '' : '
    ')+''+t; } //Helper.confirmModal(textModal.join('
    ')+'
     
    Bitte das Speichern bestätigen.', 'Bestätigen', function() { callApi(); }, 'Speichern bestätigen', true); Helper.confirmModal(str+'
     
    Bitte das Speichern bestätigen.', 'Bestätigen', function() { callApi(parent.id); }, 'Speichern bestätigen', true); } else { callApi(this.id); } } deactivate(callbackSuccess) { //var apiUrl=apiHost+'/measurement/edit/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measurement/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 //////console.log(postData['timestamp_deactivated']); let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASUREMENT', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Der Messpunkt wurde erfolgreich deaktiviert.', 'success'); //Logger.log('info', 'admin_measurement_deactivated', {data: data}); ////console.log('deactivate succes'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Der Messpunkt wurde nicht deaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASUREMENT', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASUREMENT', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg }); Helper.showToastr('Fehler', 'Daten können momentan nicht gespeichert werden ('+errorMsg+').', 'error'); */ handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASUREMENT', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivateApprovalRequest(callbackSuccess) { // Triggered when an already approved Measurement shall be deleted (a deletion approval request is initiated) //var apiUrl=apiHost+'/measurement_approval/new/measurement/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measurement_approval/new/measurement/'+this.id; // !the keys have to equal the Java class fields! var postData={}; //postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInJavaZonedDateTimeFormat(); // Format to be provided: "2021-01-03 09:23:00+02" postData['type']='MEASUREMENT_DELETE'; //////console.log(postData['timestamp_deactivated']); let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_MEASUREMENTAPPROVAL', 'OK', { apiUrl: apiUrl, type: postData['type'], requestDurationMs: Date.now()-tsStartApi, json: jsonData }); //if (data.status=='ok') { if ('pk_measurement_approvals' in data && data.pk_measurement_approvals!==null && data.pk_measurement_approvals!==undefined && data.pk_measurement_approvals!='') { Helper.showToastr('Erfolg', 'Die Lösch-Freigabe wurde erfolgreich beantragt.', 'success'); //Logger.log('info', 'api_call', {url: apiUrl, durationInMs: (Date.now()-tsStartApi)}); //Logger.log('info', 'admin_measurement_deactivation_approval_request', {data: data}); ////console.log('deactivate succes'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Lösch-Freigabe wurde nicht beantragt, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_MEASUREMENTAPPROVAL', 'ERROR_SYSTEM', { apiUrl: apiUrl, type: postData['type'], data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Logger.log('FRONTEND_CLIENT_API_NEW_MEASUREMENTAPPROVAL', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg, type: postData['type'] }); Helper.showToastr('Fehler', 'Daten können momentan nicht gespeichert werden ('+errorMsg+').', 'error'); */ handleFailedApiCall('FRONTEND_CLIENT_API_NEW_MEASUREMENTAPPROVAL', apiUrl, xhr, status, error, null, { type: postData['type'], json: jsonData }); }); } restartApproval(callbackSuccess) { // Triggered when user asks for new approval after first approval has been declined //var apiUrl=apiHost+'/measurement_approval/new/measurement/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measurement_approval/new/measurement/'+this.id; // !the keys have to equal the Java class fields! var postData={}; //postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInJavaZonedDateTimeFormat(); // Format to be provided: "2021-01-03 09:23:00+02" postData['type']='NEW_MEASUREMENT'; //////console.log(postData['timestamp_deactivated']); // File required if (this.isApprovalFileRequired() && !this.approvalFileExists(this)) { Helper.showToastr('Fehler', 'Mindestens ein Freigabe-Dokument ist erforderlich.', 'error'); return; } let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_MEASUREMENTAPPROVAL', 'OK', { apiUrl: apiUrl, type: postData['type'], requestDurationMs: Date.now()-tsStartApi, json: jsonData }); //if (data.status=='ok') { if ('pk_measurement_approvals' in data && data.pk_measurement_approvals!==null && data.pk_measurement_approvals!==undefined && data.pk_measurement_approvals!='') { Helper.showToastr('Erfolg', 'Die Freigabe wurde erfolgreich beantragt.', 'success'); //Logger.log('info', 'api_call', {url: apiUrl, durationInMs: (Date.now()-tsStartApi)}); //Logger.log('info', 'admin_measurement_approval_restart_request', {data: data}); ////console.log('deactivate succes'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Freigabe wurde nicht beantragt, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_MEASUREMENTAPPROVAL', 'ERROR_SYSTEM', { apiUrl: apiUrl, type: postData['type'], data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Logger.log('FRONTEND_CLIENT_API_NEW_MEASUREMENTAPPROVAL', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg, type: postData['type'] }); Helper.showToastr('Fehler', 'Daten können momentan nicht gespeichert werden ('+errorMsg+').', 'error'); */ handleFailedApiCall('FRONTEND_CLIENT_API_NEW_MEASUREMENTAPPROVAL', apiUrl, xhr, status, error, null, { type: postData['type'], json: jsonData }); }); } getCreatorUserId() { if ('userCreatorObj' in this && this.userCreatorObj!==null) return this.userCreatorObj.id; else return null; } getElementOuCombiObj() { //var elementNode=null; //var oeNode=null; var eocObj=null; for (let eoc of elementOeCombinations) { for (let m2 of eoc.measurementsObjAry) { if (m2.id==this.id) { //elementNode=eoc.elementObj; //oeNode=eoc.oeObj; eocObj=eoc; } if (eocObj!==null) break; } if (eocObj!==null) break; } return eocObj; } static getNrOfSelectedFiles() { let filesCount=0; filesCount+=$('#measurementApprovalFileUpload').fileinput('getFilesCount'); filesCount+=$('#measurementApprovalFileUpload2').fileinput('getFilesCount'); filesCount+=$('#measurementApprovalFileUpload3').fileinput('getFilesCount'); return filesCount; } static loadActiveMeasurementsWithOpenApprovalsFromApi(callbackSuccess) { ////console.log('LOAD OPEN APPROVALS'); const tsStartApi=Date.now(); //var apiUrl=apiHost+'/measurements/all_active_open/accountId/'+userObj.accountObj.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measurements/all_active_open/accountId/'+userObj.accountObj.id; ////console.log(apiUrl); //$.getJSON(apiUrl, function (dataFromApi) { $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { Logger.log('FRONTEND_CLIENT_API_GET_ALLACTIVEOPENMEASUREMENTS', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let measuresAry=[]; if (dataFromApi!==null && dataFromApi.length>0) { for (let m of dataFromApi) { measuresAry.push(new Measurement(m)); } } if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(measuresAry); } }).fail(function(xhr, status, error){ ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Logger.log('FRONTEND_CLIENT_API_GET_ALLACTIVEOPENMEASUREMENTS', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg }); Helper.showToastr('Fehler', 'Es ist ein Fehler aufgetreten (\'callApi()\').', 'error'); */ handleFailedApiCall('FRONTEND_CLIENT_API_GET_ALLACTIVEOPENMEASUREMENTS', apiUrl, xhr, status, error); }); } static showMeasurementFromExternal(measurementId) { externalCallMeasurementId=measurementId; clickOnNav1Item(['measurement','measurement_measurement']); } static showMeasurementElementOUCombiFromExternal(elementOUCombiId) { //externalCallMeasurementId=measurementId; externalCallElementOUCombiId=elementOUCombiId; clickOnNav1Item(['measurement','measurement_measurement']); } isActive() { if (this.timestampDeactivated!==undefined && this.timestampDeactivated!==null) return false; else return true; } approvalFileExistsOrIsSelected(currentMeasurementObj) { if (Measurement.getNrOfSelectedFiles()>0) { // A file is supposed to be uploaded - do nothing return true; } else if (currentMeasurementObj!==null) { return this.approvalFileExists(currentMeasurementObj); } else { // Neither does a file already exist nor is a file supposed to be uploaded return false; } } approvalFileExists(currentMeasurementObj) { let approvalObj=currentMeasurementObj.getApprovalStatus(); if ('fileExists' in approvalObj) { if (approvalObj.fileExists.length>0) { // A file already exists - do nothing return true; } else { return false; } } else { return false; } } isApprovalFileRequired() { // TODO See also duplicate method Element.isApprovalDocumentRequired(currentBinaryValue) let elementObj=this.getElementOuCombiObj().elementObj; if (elementObj.isApprovalDocumentRequired(this.valueBin, this.valueMet)) return true; else return false; } isApprovalFileRequiredForNewMeasurement(elementOeCombiId, currentBinaryValue, currentMetricValue) { let documentRequired=false; for (let eoc of elementOeCombinations) { if (eoc.id==elementOeCombiId) { // Find correct elementOeCombi if (eoc.elementObj.isApprovalDocumentRequired(currentBinaryValue, currentMetricValue)) documentRequired=true; break; } } return documentRequired; } isApprovalFileMissing(currentMeasurement) { // NOT USED ANYMORE //console.log(currentMeasurement); let approvalObj=currentMeasurement.getApprovalStatus(); //console.log(approvalObj); let fileMissing=false; // Check, if a file is actually required let fileRequired=this.isApprovalFileRequired(); //console.log(fileRequired); // Check, if file exists if (fileRequired===true && ( (!('fileExists' in approvalObj)) || (approvalObj.fileExists===null) || (approvalObj.fileExists.length==0) //'fileExists' in approvalObj //&& approvalObj.fileExists!==null //&& approvalObj.fileExists.length==0 ) ) { fileMissing=true; } //console.log(fileMissing); return fileMissing; } isInAcquisitionPeriod(aap) { let tsUnixSec=(this.timestampPointUnixInSec!==null ? this.timestampPointUnixInSec : this.timestampRangeToUnixInSec ); if ( (aap.timestamp_from_incl!==null && aap.timestamp_to_incl!==null && tsUnixSec >= moment(aap.timestamp_from_incl).unix() && tsUnixSec <= moment(aap.timestamp_to_incl).unix()) || (aap.timestamp_from_incl===null && aap.timestamp_to_incl===null) ) { return true; /* nrActiveMeasurements++; if (m.getApprovalStatus().approved!==true && dfObj.approvalStatus=='APPROVED') { // Measurement is not approved atLeastOneNotApproved=true; break; } if (m.getApprovalStatus().approved===false && m.getApprovalStatus().declined===false && dfObj.approvalStatus=='OPEN') { // Measurement is open nrMatches++; break; } */ } return false; } } class MeasurementCSRD { // Messpunkt constructor(apiMeasurementObj) { this.id=apiMeasurementObj.pk_csrd_measurements; if (apiMeasurementObj.usersCreator!==undefined && apiMeasurementObj.usersCreator!==null) { //id, email, pwdSaltedMd5, role, firstname, lastname, title, department, privilegesObj, accountObj let u=apiMeasurementObj.usersCreator; this.userCreatorObj=new User(u.pk_users, null, null, u.firstname, u.lastname, null, null, null, null, null); } //this.valueMet=apiMeasurementObj.value_met; //this.valueBin=apiMeasurementObj.value_bin; //this.valueCat=apiMeasurementObj.value_cat; this.valueMet1=apiMeasurementObj.value_met_1; this.valueMet2=apiMeasurementObj.value_met_2; this.valueMet3=apiMeasurementObj.value_met_3; //this.calculation_input_values=null; if ('calculation_input_values' in apiMeasurementObj && apiMeasurementObj.calculation_input_values!==null) this.calculation_input_values=apiMeasurementObj.calculation_input_values; this.note=apiMeasurementObj.note; this.timestampPointUnixInSec=null; if (apiMeasurementObj.timestamp_point!==undefined && apiMeasurementObj.timestamp_point!==null) this.timestampPointUnixInSec=moment(apiMeasurementObj.timestamp_point).tz('Europe/Berlin').unix(); this.timestampRangeFromUnixInSec=null; if (apiMeasurementObj.timestamp_range_from!==undefined && apiMeasurementObj.timestamp_range_from!==null) this.timestampRangeFromUnixInSec=moment(apiMeasurementObj.timestamp_range_from).tz('Europe/Berlin').unix(); this.timestampRangeToUnixInSec=null; if (apiMeasurementObj.timestamp_range_to!==undefined && apiMeasurementObj.timestamp_range_to!==null) this.timestampRangeToUnixInSec=moment(apiMeasurementObj.timestamp_range_to).tz('Europe/Berlin').unix(); //this.automaticFromConsumptionModule=null; if (apiMeasurementObj.automatic_from_consumption_module!==undefined) this.automaticFromConsumptionModule=apiMeasurementObj.automatic_from_consumption_module; this.timestampDeactivated=apiMeasurementObj.timestamp_deactivated; this.approvals=[]; if (apiMeasurementObj.measurementApprovals!==undefined && apiMeasurementObj.measurementApprovals!==null && Array.isArray(apiMeasurementObj.measurementApprovals)) { for (let idx=0; idx approvedObj.timestampUnixInSec)) { if (a.timestampApproved!==null) { approvedObj={ approved: true, declined: false, timestampUnixInSec: moment(a.timestampApproved).tz('Europe/Berlin').unix(), user: a.userApproverActual, measurementApprovalId: a.id, measurementObj: this, measurementApprovalObj: a }; } else if (a.timestampDeclined!==null) { approvedObj={ approved: false, declined: true, timestampUnixInSec: moment(a.timestampDeclined).tz('Europe/Berlin').unix(), user: a.userApproverActual, measurementApprovalId: a.id, measurementObj: this, measurementApprovalObj: a }; } } } if (approvedObj!==null) { approvedObj['fileExists']=[]; for (let af of approvedObj.measurementApprovalObj.approvalFiles) { if (af.timestampDeactivated===null) { // File is active approvedObj['fileExists'].push(af); } } } if (breakAtEndOfLoop===true) break; } } lastApproveTimestamp=null; lastApproveUser=null; breakAtEndOfLoop=false; for (let a of this.approvals) { if (a.type=='MEASUREMENT_DELETE') { if (a.timestampApproved===null) { // Not yet approved approvedObj['deleteApproval']={ approved: false, user: a.userApprover, measurementApprovalId: a.id }; breakAtEndOfLoop=true; } else { // Is approved if (!('deleteApproval' in approvedObj) || !('approved' in approvedObj['deleteApproval']) || moment(a.timestampApproved).tz('Europe/Berlin').unix() > approvedObj.timestampUnixInSec) { approvedObj['deleteApproval']={ approved: true, timestampUnixInSec: moment(a.timestampApproved).tz('Europe/Berlin').unix(), user: a.userApproverActual, measurementApprovalId: a.id }; } } if (breakAtEndOfLoop===true) break; } } if (approvedObj===null) return { approved: false, declined: false, measurementObj: this }; else return approvedObj; } /** * This is where also the data qulity checks are executed. * * @param {*} isEdit * @returns */ createPostData(isEdit=false, elementOeCombiId) { // ### Check data consistency & assemble POST data obj var postData={}; if (isEdit) { postData['value_met_1']=null; postData['value_met_2']=null; postData['value_met_3']=null; postData['timestamp_point']=null; postData['timestamp_range_from']=null; postData['timestamp_range_to']=null; } // Values let count=0; if (this.valueMet1!==undefined && this.valueMet1!==null) { count++; try { Helper.formatMeasurementValue(this.valueMet1, 'metric'); // just call to utilize type check and (return value is irrelevant here) } catch (e) { Helper.showToastr('Fehler', 'Metrischer Wert 1 liegt nicht in korrektem Format vor.', 'error'); return; } postData['value_met_1']=this.valueMet1; } if (this.valueMet2!==undefined && this.valueMet2!==null) { count++; try { Helper.formatMeasurementValue(this.valueMet2, 'metric'); // just call to utilize type check and (return value is irrelevant here) } catch (e) { Helper.showToastr('Fehler', 'Metrischer Wert 2 liegt nicht in korrektem Format vor.', 'error'); return; } postData['value_met_2']=this.valueMet2; } if (this.valueMet3!==undefined && this.valueMet3!==null) { count++; try { Helper.formatMeasurementValue(this.valueMet3, 'metric'); // just call to utilize type check and (return value is irrelevant here) } catch (e) { Helper.showToastr('Fehler', 'Metrischer Wert 3 liegt nicht in korrektem Format vor.', 'error'); return; } postData['value_met_3']=this.valueMet3; } //if (count!=1) { Helper.showToastr('Fehler', 'Es wurden 0 oder >1 Werte übergeben.', 'error'); return; } // Time count=0; if (this.timestampPointUnixInSec!==undefined && this.timestampPointUnixInSec!==null) { count++; //postData['timestamp_point']=moment.unix(this.timestampPointUnixInSec).local().format('YYYY-MM-DD HH:mm:ssZZ'); postData['timestamp_point']=moment.unix(this.timestampPointUnixInSec).tz('Europe/Berlin').format(); } if (this.timestampRangeFromUnixInSec!==undefined && this.timestampRangeFromUnixInSec!==null && this.timestampRangeToUnixInSec!==undefined && this.timestampRangeToUnixInSec!==null) { count++; if (this.timestampRangeFromUnixInSec > this.timestampRangeToUnixInSec) { Helper.showToastr('Fehler', 'Zeitraum bis liegt vor Zeitraum von.', 'error'); return; } //postData['timestamp_range_from']=moment.unix(this.timestampRangeFromUnixInSec).local().format('YYYY-MM-DD HH:mm:ssZZ'); postData['timestamp_range_from']=moment.unix(this.timestampRangeFromUnixInSec).tz('Europe/Berlin').format(); //postData['timestamp_range_to']=moment.unix(this.timestampRangeToUnixInSec).local().format('YYYY-MM-DD HH:mm:ssZZ'); postData['timestamp_range_to']=moment.unix(this.timestampRangeToUnixInSec).tz('Europe/Berlin').format(); } if (count!=1) { Helper.showToastr('Fehler', 'Zeitpunkt oder Zeitraum wurden nicht korrekt angegeben.', 'error'); return; } // Comment if (this.note!==undefined) { postData['note']=this.note; } let eoc=ElementOuCombiCSRD.getElementOuCombiById(elementOeCombiId); if (eoc!==null) { if (eoc.elementObj.measurementValueType=='qual' && (this.note===undefined || this.note===null || this.note.trim()=='')) { Helper.showToastr('Fehler', 'Bei einem qualitativen Messpunkt darf das Kommentarfeld nicht leer bleiben.', 'error'); return; } } else { Helper.showToastr('Fehler', 'Element-OE-Kombination wurde nicht gefunden.', 'error'); return; } if (!isEdit) { // User creator if (this.userCreatorObj!==undefined && this.userCreatorObj!==null && this.userCreatorObj.id!==null) { postData['usersCreator']={ pk_users: this.userCreatorObj.id }; } else { Helper.showToastr('Fehler', 'Der erstellende User wurde nicht übergeben.', 'error'); return; } } return postData; } checkTimeConstraints(postData, elementOeCombiId, currentMeasurementObj=null) { // ### Logic checks which lead to an additional confirmation required from the user let textModal=[]; let apObj=userObj.accountObj.getCurrentAcquisitionPeriodMeasurementsObj(); if (postData['timestamp_point']!==undefined && postData['timestamp_point']!==null) { if (moment(postData['timestamp_point']).tz('Europe/Berlin').isBefore(moment().tz('Europe/Berlin').subtract(3, 'y'))) textModal.push('Der Messpunkt liegt mehr als 3 Jahre in der Vergangenheit.'); if (moment(postData['timestamp_point']).tz('Europe/Berlin').isAfter(moment().tz('Europe/Berlin'))) textModal.push('Der Messpunkt liegt in der Zukunft.'); if (!userObj.accountObj.isTimestampInAcquisitionPeriodMeasurements(postData['timestamp_point'])) textModal.push('Der Messpunkt befindet sich nicht in einem Erfassungszeitraum.'); else { if (apObj!==null && moment(postData['timestamp_point']).tz('Europe/Berlin').isBefore(moment(apObj.timestamp_from_incl))) textModal.push('Der Messpunkt liegt vor dem aktuellen Erfassungszeitraum \''+apObj.name+'\' ('+Helper.timestampFormat(apObj.timestamp_from_incl, false, false)+' bis '+Helper.timestampFormat(apObj.timestamp_to_incl, false, false)+').'); if (apObj!==null && moment(postData['timestamp_point']).tz('Europe/Berlin').isAfter(moment(apObj.timestamp_to_incl))) textModal.push('Der Messpunkt liegt nach dem aktuellen Erfassungszeitraum \''+apObj.name+'\' ('+Helper.timestampFormat(apObj.timestamp_from_incl, false, false)+' bis '+Helper.timestampFormat(apObj.timestamp_to_incl, false, false)+').'); } } if (postData['timestamp_range_to']!==undefined && postData['timestamp_range_to']!==null) { if (moment(postData['timestamp_range_to']).tz('Europe/Berlin').isBefore(moment().tz('Europe/Berlin').subtract(3, 'y'))) textModal.push('Das Zeitraumende liegt mehr als 3 Jahre in der Vergangenheit.'); if (moment(postData['timestamp_range_to']).tz('Europe/Berlin').isAfter(moment().tz('Europe/Berlin'))) textModal.push('Der Messpunkt liegt in der Zukunft.'); if (!userObj.accountObj.isTimestampInAcquisitionPeriodMeasurements(postData['timestamp_range_to'])) textModal.push('Der Messpunkt (Zeitraum bis) befindet sich nicht in einem Erfassungszeitraum.'); else { if (apObj!==null && moment(postData['timestamp_range_to']).tz('Europe/Berlin').isBefore(moment(apObj.timestamp_from_incl))) textModal.push('Der Messpunkt (Zeitraum bis) liegt vor dem aktuellen Erfassungszeitraum \''+apObj.name+'\' ('+Helper.timestampFormat(apObj.timestamp_from_incl, false, false)+' bis '+Helper.timestampFormat(apObj.timestamp_to_incl, false, false)+').'); if (apObj!==null && moment(postData['timestamp_range_to']).tz('Europe/Berlin').isAfter(moment(apObj.timestamp_to_incl))) textModal.push('Der Messpunkt (Zeitraum bis) liegt nach dem aktuellen Erfassungszeitraum \''+apObj.name+'\' ('+Helper.timestampFormat(apObj.timestamp_from_incl, false, false)+' bis '+Helper.timestampFormat(apObj.timestamp_to_incl, false, false)+').'); } } if (postData['timestamp_range_from']!==undefined && postData['timestamp_range_from']!==null && postData['timestamp_range_to']!==undefined && postData['timestamp_range_to']!==null) { if (moment(postData['timestamp_range_from']).tz('Europe/Berlin').add(1, 'y').isBefore(moment(postData['timestamp_range_to']).tz('Europe/Berlin'))) textModal.push('Der Zeitraum beträgt mehr als 1 Jahr.'); // Check if time range is consecutive to existing time ranges & check for overlaps let consecutive=false; let overlap=false; let counter=0; for (let eoc of csrdElementOeCombinations) { if (eoc.id==elementOeCombiId) { // Find correct elementOeCombi for (let m of eoc.measurementsObjAry) { // For all existing measurements if (m.timestampDeactivated===null) { // If active (approval status is irrelevant here) if (currentMeasurementObj===null || currentMeasurementObj.id!=m.id) { counter++; // Check consecutive time ranges if (moment(postData['timestamp_range_from']).tz('Europe/Berlin').startOf('day').isSame(moment(m.timestampRangeToUnixInSec*1000).tz('Europe/Berlin').startOf('day').add(1, 'days'))) { consecutive=true; break; } if (moment(postData['timestamp_range_to']).tz('Europe/Berlin').startOf('day').add(1, 'days').isSame(moment(m.timestampRangeFromUnixInSec*1000).tz('Europe/Berlin').startOf('day'))) { consecutive=true; break; } // Check overlaps if (moment(postData['timestamp_range_from']).tz('Europe/Berlin').startOf('day').isSameOrBefore(moment(m.timestampRangeToUnixInSec*1000).tz('Europe/Berlin').startOf('day')) && moment(postData['timestamp_range_to']).tz('Europe/Berlin').startOf('day').isSameOrAfter(moment(m.timestampRangeFromUnixInSec*1000).tz('Europe/Berlin').startOf('day'))) { overlap=true; break; } } } } break; } } if (counter==0) consecutive=true; // To account for very first measurement to be added (i.e. do not through warning then) if (!consecutive) textModal.push('Der Zeitraum schließt nicht direkt an einen vorhanden Messpunkt-Zeitraum an.'); if (overlap) { Helper.showToastr('Fehler', 'Der Zeitraum überlappt mit einem vorhandenen Messpunkt-Zeitraum.', 'error'); return null; } } // FOLLOWING CODE IS DEAD CODE AS A MISSING APPROVAL DOCUMENT IS ALREADY ACKNOWLEDGED WITH AN ERROR EARLIER IN THE CODE EXECUTION /* if (this.isApprovalFileRequiredForNewMeasurement(elementOeCombiId, /postData['value_met'])) { if (!this.approvalFileExistsOrIsSelected(currentMeasurementObj)) { textModal.push('Der Messpunkt verlangt ein Freigabe-Dokument, es wurde aber bisher kein Dokument hochgeladen.'); } } */ return textModal; } saveNew(elementOeCombiId, callbackSuccess) { ////console.log('saveNew', this); /* * { * "value_met": 5.2341 * , "timestamp_range_from": "2020-02-01 09:24:00+01" * , "timestamp_range_to": "2020-02-28 09:25:00+01" * } */ // ### Check data consistency & assemble POST data obj var postData=this.createPostData(false, elementOeCombiId); if (postData==null) return; // ### Logic checks which lead to an additional confirmation required from the user let textModal=this.checkTimeConstraints(postData, elementOeCombiId); if (textModal===null) return; function callApi() { // ### Call API var apiUrl=apiHost+'/csrd/measurement/new/element_oe_combi/'+elementOeCombiId; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENT', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); //if (data.status=='ok') { if ('pk_csrd_measurements' in data && data.pk_csrd_measurements!==null && data.pk_csrd_measurements!==undefined && data.pk_csrd_measurements!='') { Helper.showToastr('Erfolg', 'Neuer Messpunkt wurde gespeichert.', 'success'); let measurementObj=new MeasurementCSRD(data); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(measurementObj); } else { // TODO: THIS PIECE OF CODE SHOULD NOT BE REQUIRED, AS ERRORS ARE RETURNED BY SPECIFIC HTTP STATUS CODES (THIS ALSO TRUE FOR OTHER AJAX CALLS HERE ...) Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENT', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); Helper.showToastr('Fehler', 'Fehler beim Speichern des Messpunkts: '+data.msg, 'error'); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_NEW_MEASUREMENT', apiUrl, xhr, status, error, null, { json: jsonData }); }); } if (textModal.length>0) { let str=''; for (let t of textModal) { str+=(str=='' ? '' : '
    ')+''+t; } Helper.confirmModal(str+'
     
    Bitte das Speichern bestätigen.', 'Bestätigen', function() { callApi(); }, 'Speichern bestätigen', true); } else { callApi(); } } save(elementOeCombiId, callbackSuccess) { ////console.log('save', this); /* * { * "value_met": 5.2341 * , "timestamp_range_from": "2020-02-01 09:24:00+01" * , "timestamp_range_to": "2020-02-28 09:25:00+01" * } */ // ### Check data consistency & assemble POST data obj var postData=this.createPostData(true, elementOeCombiId); if (postData===null || postData===undefined) { return; } let textModal=this.checkTimeConstraints(postData, elementOeCombiId, this); if (textModal===null) { return; } function callApi(measurementId) { // ### Call API var apiUrl=apiHost+'/csrd/measurement/edit/'+measurementId; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASUREMENT', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASUREMENT', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASUREMENT', apiUrl, xhr, status, error, null, { json: jsonData }); }); } let parent=this; if (textModal.length>0) { let str=''; for (let t of textModal) { str+=(str=='' ? '' : '
    ')+''+t; } Helper.confirmModal(str+'
     
    Bitte das Speichern bestätigen.', 'Bestätigen', function() { callApi(parent.id); }, 'Speichern bestätigen', true); } else { callApi(this.id); } } deactivate(callbackSuccess) { var apiUrl=apiHost+'/csrd/measurement/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASUREMENT', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Der Messpunkt wurde erfolgreich deaktiviert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Der Messpunkt wurde nicht deaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASUREMENT', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASUREMENT', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivateApprovalRequest(callbackSuccess) { // Triggered when an already approved Measurement shall be deleted (a deletion approval request is initiated) var apiUrl=apiHost+'/csrd/measurement_approval/new/measurement/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['type']='MEASUREMENT_DELETE'; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENTAPPROVAL', 'OK', { apiUrl: apiUrl, type: postData['type'], requestDurationMs: Date.now()-tsStartApi, json: jsonData }); //if (data.status=='ok') { if ('pk_csrd_measurement_approvals' in data && data.pk_csrd_measurement_approvals!==null && data.pk_csrd_measurement_approvals!==undefined && data.pk_csrd_measurement_approvals!='') { Helper.showToastr('Erfolg', 'Die Lösch-Freigabe wurde erfolgreich beantragt.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Lösch-Freigabe wurde nicht beantragt, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENTAPPROVAL', 'ERROR_SYSTEM', { apiUrl: apiUrl, type: postData['type'], data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENTAPPROVAL', apiUrl, xhr, status, error, null, { type: postData['type'], json: jsonData }); }); } restartApproval(callbackSuccess) { // Triggered when user asks for new approval after first approval has been declined var apiUrl=apiHost+'/csrd/measurement_approval/new/measurement/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['type']='NEW_MEASUREMENT'; // File required /* if (this.isApprovalFileRequired() && !this.approvalFileExists(this)) { Helper.showToastr('Fehler', 'Mindestens ein Freigabe-Dokument ist erforderlich.', 'error'); return; } */ let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENTAPPROVAL', 'OK', { apiUrl: apiUrl, type: postData['type'], requestDurationMs: Date.now()-tsStartApi, json: jsonData }); //if (data.status=='ok') { if ('pk_csrd_measurement_approvals' in data && data.pk_csrd_measurement_approvals!==null && data.pk_csrd_measurement_approvals!==undefined && data.pk_csrd_measurement_approvals!='') { Helper.showToastr('Erfolg', 'Die Freigabe wurde erfolgreich beantragt.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Freigabe wurde nicht beantragt, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENTAPPROVAL', 'ERROR_SYSTEM', { apiUrl: apiUrl, type: postData['type'], data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_NEW_CSRD_MEASUREMENTAPPROVAL', apiUrl, xhr, status, error, null, { type: postData['type'], json: jsonData }); }); } getCreatorUserId() { if ('userCreatorObj' in this && this.userCreatorObj!==null) return this.userCreatorObj.id; else return null; } getElementOuCombiObj() { var eocObj=null; for (let eoc of csrdElementOeCombinations) { for (let m2 of eoc.measurementsObjAry) { if (m2.id==this.id) { eocObj=eoc; } if (eocObj!==null) break; } if (eocObj!==null) break; } return eocObj; } static getNrOfSelectedFiles() { let filesCount=0; filesCount+=$('#measurementApprovalFileUpload').fileinput('getFilesCount'); filesCount+=$('#measurementApprovalFileUpload2').fileinput('getFilesCount'); filesCount+=$('#measurementApprovalFileUpload3').fileinput('getFilesCount'); return filesCount; } static loadActiveMeasurementsWithOpenApprovalsFromApi(callbackSuccess) { const tsStartApi=Date.now(); var apiUrl=apiHost+'/csrd/measurements/all_active_open/accountId/'+userObj.accountObj.id; $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { Logger.log('FRONTEND_CLIENT_API_GET_CSRD_ALLACTIVEOPENMEASUREMENTS', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let measuresAry=[]; if (dataFromApi!==null && dataFromApi.length>0) { for (let m of dataFromApi) { measuresAry.push(new MeasurementCSRD(m)); } } if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(measuresAry); } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_CSRD_ALLACTIVEOPENMEASUREMENTS', apiUrl, xhr, status, error); }); } static showMeasurementFromExternal(csrdMeasurementId) { externalCallCSRDMeasurementId=csrdMeasurementId; clickOnNav1Item(['nav1_csrd','nav1_csrd_measurements_measurement']); } static showMeasurementElementOUCombiFromExternal(elementOUCombiId) { externalCallCSRDElementOUCombiId=elementOUCombiId; clickOnNav1Item(['nav1_csrd','nav1_csrd_measurements_measurement']); } getValueStr(elementNode) { let m=this; let valueStr=null; try { if (m.valueMet1!==null) { valueStr=(valueStr!==null ? valueStr+' '+csrdValueSeparator+' ' : '')+Helper.formatMeasurementValue(m.valueMet1, elementNode.measurementValueType, (elementNode.inputUnit1=='%' ? true : false)); if (elementNode.inputUnit1!==null) valueStr+=' '+elementNode.inputUnit1; } if (m.valueMet2!==null) { valueStr=(valueStr!==null ? valueStr+' '+csrdValueSeparator+' ' : '')+Helper.formatMeasurementValue(m.valueMet2, elementNode.measurementValueType, (elementNode.inputUnit2=='%' ? true : false)); if (elementNode.inputUnit2!==null) valueStr+=' '+elementNode.inputUnit2; } if (m.valueMet3!==null) { valueStr=(valueStr!==null ? valueStr+' '+csrdValueSeparator+' ' : '')+Helper.formatMeasurementValue(m.valueMet3, elementNode.measurementValueType, (elementNode.inputUnit3=='%' ? true : false)); if (elementNode.inputUnit3!==null) valueStr+=' '+elementNode.inputUnit3; } if (valueStr===null) valueStr='-'; } catch (e) { Logger.log('FRONTEND_CLIENT_FORMATMEASUREMENTVALUE', 'ERROR_SYSTEM', { value: m.valueMet1, value2: m.valueMet2, value3: m.valueMet3, measurementValueType: elementNode.measurementValueType, flag: 'csrd' }); throw e; } return valueStr; } isActive() { if (this.timestampDeactivated!==undefined && this.timestampDeactivated!==null) return false; else return true; } isInAcquisitionPeriod(aap) { let tsUnixSec=(this.timestampPointUnixInSec!==null ? this.timestampPointUnixInSec : this.timestampRangeToUnixInSec ); if ( (aap.timestamp_from_incl!==null && aap.timestamp_to_incl!==null && tsUnixSec >= moment(aap.timestamp_from_incl).unix() && tsUnixSec <= moment(aap.timestamp_to_incl).unix()) || (aap.timestamp_from_incl===null && aap.timestamp_to_incl===null) ) { return true; } return false; } } class MeasurementApproval { constructor(apiMeasurementApprovalObj) { this.id=apiMeasurementApprovalObj.pk_measurement_approvals; this.timestampEmailSentToApprover=apiMeasurementApprovalObj.timestamp_email_sent_to_approver; this.timestampApproved=apiMeasurementApprovalObj.timestamp_approved; this.timestampDeclineEmailSentToCreator=apiMeasurementApprovalObj.timestamp_decline_email_sent_to_creator; this.timestampDeclined=apiMeasurementApprovalObj.timestamp_declined; this.type=apiMeasurementApprovalObj.type; if (apiMeasurementApprovalObj.users_approver!==undefined && apiMeasurementApprovalObj.users_approver!==null) { let ua=apiMeasurementApprovalObj.users_approver; // id, email, pwdSaltedMd5, role, firstname, lastname, title, department, privilegesObj, accountObj this.userApprover=new User(ua.pk_users, null, null, ua.firstname, ua.lastname, null, null, null, null, null); } this.userApproverActual=null; if (apiMeasurementApprovalObj.users_approver_actual!==undefined && apiMeasurementApprovalObj.users_approver_actual!==null) { let ua=apiMeasurementApprovalObj.users_approver_actual; // id, email, pwdSaltedMd5, role, firstname, lastname, title, department, privilegesObj, accountObj this.userApproverActual=new User(ua.pk_users, null, null, ua.firstname, ua.lastname, null, null, null, null, null); } this.approvalFiles=[]; if (apiMeasurementApprovalObj.measurementApprovalFiles!==undefined && apiMeasurementApprovalObj.measurementApprovalFiles!==null && Array.isArray(apiMeasurementApprovalObj.measurementApprovalFiles)) { for (let idx=0; idx b.pk_measures_structure) return 1; else return 0; }); var dataStructured=[]; let newlyCreatedMeasureStructure=null; if (dataUnstructured!==null && Array.isArray(dataUnstructured)) { for (let entryUn of dataUnstructured) { // For each MeasureStructure (as a flat array) - each MeasureStructure obj has a field with an array of Measures //console.log(entryUn); var level1Obj=null; var level2Obj=null; var level3Obj=null; var level4Obj=null; var level5Obj=null; // ### Check if structure path already exists (if not, create it) for (let entry of dataStructured) { if (entry.nodeId==entryUn.id_node_level1) { level1Obj=entry; if ('childs' in entry && Array.isArray(entry.childs)) { for (let entry2 of entry.childs) { if (entry2.nodeId==level1Obj.nodeId+'_'+entryUn.id_node_level2) { level2Obj=entry2; if ('childs' in entry2) { for (let entry3 of entry2.childs) { if (entry3.nodeId==level2Obj.nodeId+'_'+entryUn.id_node_level3) { level3Obj=entry3; if ('childs' in entry3) { for (let entry4 of entry3.childs) { if (entry4.nodeId==level3Obj.nodeId+'_'+entryUn.id_node_level4) { level4Obj=entry4; if ('childs' in entry4) { for (let entry5 of entry4.childs) { if (entry5.nodeId==level4Obj.nodeId+'_'+entryUn.id_node_level5) { level5Obj=entry5; // ... a 6th level could be added here if required } } } } } } } } } } } } } } // Create new nodes (if necessary) newlyCreatedMeasureStructure=null; if (level1Obj===null && entryUn.id_node_level1!==null) { //level1Obj={nameShort: entryUn.name_node_level1, nameLong: entryUn.name_node_level1, nodeId: entryUn.id_node_level1}; level1Obj=new MeasureStructure(entryUn); newlyCreatedMeasureStructure=level1Obj; level1Obj['nameShort']=entryUn.name_node_level1; level1Obj['nameLong']=entryUn.name_node_level1; level1Obj['nodeId']=entryUn.id_node_level1; dataStructured.push(level1Obj); } if (level2Obj===null && entryUn.id_node_level2!==null) { //level2Obj={nameShort: entryUn.name_node_level2, nameLong: entryUn.name_node_level2, nodeId: level1Obj.nodeId+'_'+entryUn.id_node_level2}; level2Obj=new MeasureStructure(entryUn); newlyCreatedMeasureStructure=level2Obj; level2Obj['nameShort']=entryUn.name_node_level2; level2Obj['nameLong']=entryUn.name_node_level2; level2Obj['nodeId']=level1Obj.nodeId+'_'+entryUn.id_node_level2; if (!('childs' in level1Obj)) level1Obj['childs']=[]; level1Obj['childs'].push(level2Obj); } if (level3Obj===null && entryUn.id_node_level3!==null) { //level3Obj={nameShort: entryUn.name_node_level3, nameLong: entryUn.name_node_level3, nodeId: level2Obj.nodeId+'_'+entryUn.id_node_level3}; level3Obj=new MeasureStructure(entryUn); newlyCreatedMeasureStructure=level3Obj; level3Obj['nameShort']=entryUn.name_node_level3; level3Obj['nameLong']=entryUn.name_node_level3; level3Obj['nodeId']=level2Obj.nodeId+'_'+entryUn.id_node_level3; if (!('childs' in level2Obj)) level2Obj['childs']=[]; level2Obj['childs'].push(level3Obj); } if (level4Obj===null && entryUn.id_node_level4!==null) { //level4Obj={nameShort: entryUn.name_node_level4, nameLong: entryUn.name_node_level4, nodeId: level3Obj.nodeId+'_'+entryUn.id_node_level4}; level4Obj=new MeasureStructure(entryUn); newlyCreatedMeasureStructure=level4Obj; level4Obj['nameShort']=entryUn.name_node_level4; level4Obj['nameLong']=entryUn.name_node_level4; level4Obj['nodeId']=level3Obj.nodeId+'_'+entryUn.id_node_level4; if (!('childs' in level3Obj)) level3Obj['childs']=[]; level3Obj['childs'].push(level4Obj); } /* if (level5Obj===null && entryUn.id_node_level5!==null) { //level5Obj={nameShort: entryUn.name_node_level5, nameLong: entryUn.name_node_level5, nodeId: level4Obj.nodeId+'_'+entryUn.id_node_level5}; level5Obj=new MeasureStructure(entryUn); level5Obj['nameShort']=entryUn.name_node_level5; level5Obj['nameLong']=entryUn.name_node_level5; level5Obj['nodeId']=level4Obj.nodeId+'_'+entryUn.id_node_level5; if (!('childs' in level4Obj)) level4Obj['childs']=[]; level4Obj['childs'].push(level5Obj); } */ // Fill measuresByFk with data for further usage if (newlyCreatedMeasureStructure!==null) { for (let m of newlyCreatedMeasureStructure.measuresObjAry) { measuresByFk[m.id]=m; } } } //console.log(measuresByFk); // Link child measures to parent measures let m=null; for (let key in measuresByFk) { m=measuresByFk[key]; if (m.fkMeasureParent!==null) { // m is a child measuresByFk[m.fkMeasureParent].childMeasures.push(m); } } } return dataStructured; } static createStructureTable(tableHtmlId, structureOEs, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit) { $('#'+tableHtmlId+' tbody').empty(); $('#'+tableHtmlId+' tbody').append(MeasureStructure.createStructureTableRow(structureOEs, null, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit)); Helper.createCollapsableTable(tableHtmlId, function(tableRow) { $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90").addClass("fa-rotate-90"); // Make sure chevron is shown correctly (i.e. is in OPEN state) }); } static createStructureTableRow(structureObj, levelStr=null, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit) { //console.log(callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit); var $returnJQueryObj=$(); var levelAry=[]; if (levelStr!==null) levelAry=levelStr.split('_'); var levelClass=''; if (levelAry.length==0) levelClass='level1'; else if (levelAry.length==1) levelClass='level2'; else if (levelAry.length==2) levelClass='level3'; else if (levelAry.length==3) levelClass='level4'; else if (levelAry.length==4) levelClass='level5'; if (structureObj!==null && Array.isArray(structureObj) && structureObj.length>0) { for (var i=0; i'); if (childsExist) $tr.append(' '+structureObj[i].nameLong+''); else $tr.append(''+structureObj[i].nameLong+''); if (active) { // De-Activate button if (levelAry.length>0) { // Do not allow deactivation of level1/root node let $trashIcon=$(''); $tr.append($('').append($trashIcon)); $trashIcon.on('click', function(event) { ////console.log('trash icon clicked ('+$(this).attr('data-id')+')'); var measureStructureObj=new MeasureStructure({ pk_measures_structure : $(this).attr('data-id')}); ////console.log($(this).attr('data-id'), measureStructureObj.id); measureStructureObj.deactivate(function() { ////console.log('deactiveate measure structure success'); //Update data MeasureStructure.getAllMeasures(function() { MeasureStructure.createStructureTable('tableMeasures', structureMeasures, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit); }); }); event.stopPropagation(); // To prevent the underlying event of the table row TR }); } else { $tr.append($('')); } let parentMeasureStructureObj=structureObj[i]; // "Create New" button if (levelAry.length<3) { // zero based index, i.e. 3 -> only levels 1, 2 and 3 are allowed to add child nodes let $btn=$(''); $btn.on('click', function(event) { event.stopPropagation(); // To prevent the underlying event of the table row TR ////console.log('new icon clicked ('+$(this).attr('data-id')+')', event, this, parentMeasureStructureObj); //openModalMeasureStructure(parentMeasureStructureObj); callbackOpenModalMeasureStructure(parentMeasureStructureObj); }); $tr.append($('').append($btn)); } else { $tr.append($('')); } // "Edit" button let $btnEdit=$(''); $btnEdit.on('click', function(event) { event.stopPropagation(); // To prevent the underlying event of the table row TR ////console.log('EDIT icon clicked ('+$(this).attr('data-id')+')', event, this, parentMeasureStructureObj); //openModalMeasureStructureForEdit(parentMeasureStructureObj); callbackOpenModalMeasureStructureForEdit(parentMeasureStructureObj); }); $tr.append($('').append($btnEdit)); } else { let $reactivateIcon=$(''); $tr.append($('').append($reactivateIcon).append('
    '+(structureObj[i].timestampDeactivated!==null ? Helper.timestampFormat(structureObj[i].timestampDeactivated, false, false) : '')+'')); $reactivateIcon.on('click', function(event) { ////console.log('reactivate icon clicked ('+$(this).attr('data-id')+')'); var measureStructureObj=new MeasureStructure({ pk_measures_structure : $(this).attr('data-id')}); ////console.log($(this).attr('data-id'), measureStructureObj.id); measureStructureObj.reactivate(function() { ////console.log('re-activeate measure structure success'); //Update data MeasureStructure.getAllMeasures(function() { MeasureStructure.createStructureTable('tableMeasures', structureMeasures, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit); }); }); event.stopPropagation(); // To prevent the underlying event of the table row TR }); $tr.append($('')); $tr.append($('')); } $returnJQueryObj=$returnJQueryObj.add($tr); if (childsExist) { $returnJQueryObj=$returnJQueryObj.add( MeasureStructure.createStructureTableRow( structureObj[i].childs , (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1)) , callbackOpenModalMeasureStructure , callbackOpenModalMeasureStructureForEdit ) ); } } } return $returnJQueryObj; } static createStructureTableRowForMultipleSelection(structureObj, levelStr=null) { var $returnJQueryObj=$(); var levelAry=[]; if (levelStr!==null) levelAry=levelStr.split('_'); var levelClass=''; if (levelAry.length==0) levelClass='level1'; else if (levelAry.length==1) levelClass='level2'; else if (levelAry.length==2) levelClass='level3'; else if (levelAry.length==3) levelClass='level4'; else if (levelAry.length==4) levelClass='level5'; if (structureObj!==null && Array.isArray(structureObj) && structureObj.length>0) { for (var i=0; i' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +''); $returnJQueryObj=$returnJQueryObj.add( MeasureStructure.createStructureTableRowForMultipleSelection(structureObj[i].childs, (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1))) ); } } } return $returnJQueryObj; } static createMultiSelectionTreeMeasureStructures(tableHtmlId, structureMeasureStructuresAry) { //////console.log(structureMeasureStructuresAry); $('#'+tableHtmlId+' tbody').empty(); $('#'+tableHtmlId+' tbody').append(MeasureStructure.createStructureTableRowForMultipleSelection(structureMeasureStructuresAry)); Helper.createCollapsableTable(tableHtmlId, function(tableRow) { $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90").addClass("fa-rotate-90"); // Make sure chevron is shown correctly (i.e. is in OPEN state) }); // Create event handler for checkboxes $("#"+tableHtmlId+" tbody tr input[type=checkbox]").change(function(event) { var $parentTr = $(this).closest('tr'); var isNowChecked = $(this).is(":checked"); var write=$(this).hasClass('write'); }); } saveNew(callbackSuccess) { if (this.idNodeLevel1===null || this.idNodeLevel1=='') { Helper.showToastr('Fehler', 'Level 1 ID fehlt.', 'error'); return; } if (this.nameNodeLevel1===null || this.nameNodeLevel1=='') { Helper.showToastr('Fehler', 'Level 1 Name fehlt.', 'error'); return; } if (this.fkAccounts===null || this.fkAccounts=='') { Helper.showToastr('Fehler', 'Account ID fehlt.', 'error'); return; } if (this.id!==undefined && this.id!==null) { Helper.showToastr('Fehler', 'Maßnahmen-Struktur ID ist gesetzt ('+this.id+') - ungültiger Zustand für neu anzulegende Maßnahmen-Strukturen.', 'error'); return; } if (this.idNodeLevel1===null && this.nameNodeLevel1!==null && this.nameNodeLevel1.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.idNodeLevel2===null && this.nameNodeLevel2!==null && this.nameNodeLevel2.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.idNodeLevel3===null && this.nameNodeLevel3!==null && this.nameNodeLevel3.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.idNodeLevel4===null && this.nameNodeLevel4!==null && this.nameNodeLevel4.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } //var apiUrl=apiHost+'/measures/structure/new?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/structure/new'; // !the keys have to equal the Java class fields! var postData={}; postData['fk_accounts']=this.fkAccounts; if (this.nameNodeLevel1!==null) { if (this.idNodeLevel1!==null) postData['id_node_level1']=this.idNodeLevel1; postData['name_node_level1']=this.nameNodeLevel1; if (this.nameNodeLevel2!==null) { if (this.idNodeLevel2!==null) postData['id_node_level2']=this.idNodeLevel2; postData['name_node_level2']=this.nameNodeLevel2; if (this.nameNodeLevel3!==null) { if (this.idNodeLevel3!==null) postData['id_node_level3']=this.idNodeLevel3; postData['name_node_level3']=this.nameNodeLevel3; if (this.nameNodeLevel4!==null) { if (this.idNodeLevel4!==null) postData['id_node_level4']=this.idNodeLevel4; postData['name_node_level4']=this.nameNodeLevel4; } } } } let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_MEASURESTRUCTURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if ('pk_measures_structure' in data && data.pk_measures_structure!==null && data.pk_measures_structure!==undefined && data.pk_measures_structure!='') { //Logger.log('info', 'api_call', {url: apiUrl, durationInMs: (Date.now()-tsStartApi)}); //Logger.log('info', 'admin_measurestructure_created', {data: data}); Helper.showToastr('Erfolg', 'Neue Maßnahmen-Struktur wurde gespeichert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { ////console.log(data); Logger.log('FRONTEND_CLIENT_API_NEW_MEASURESTRUCTURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); Helper.showToastr('Fehler', 'Fehler beim Speichern der Maßnahmen-Struktur: '+data.msg, 'error'); } }} ).fail(function(xhr, status, error) { ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Helper.showToastr('Fehler', 'Daten können nicht gespeichert werden ('+errorMsg+').', 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_MEASURESTRUCTURE', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg }); */ handleFailedApiCall('FRONTEND_CLIENT_API_NEW_MEASURESTRUCTURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } save(callbackSuccess) { //////console.log('save', this); if (this.nameNodeLevel1!==null && this.nameNodeLevel1.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.nameNodeLevel2!==null && this.nameNodeLevel2.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.nameNodeLevel3!==null && this.nameNodeLevel3.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.nameNodeLevel4!==null && this.nameNodeLevel4.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } // ### Check data consistency & assemble POST data obj var postData={}; if (this.nameNodeLevel1!==undefined && this.nameNodeLevel1!==null) postData['name_node_level1']=this.nameNodeLevel1; if (this.nameNodeLevel2!==undefined && this.nameNodeLevel2!==null) postData['name_node_level2']=this.nameNodeLevel2; if (this.nameNodeLevel3!==undefined && this.nameNodeLevel3!==null) postData['name_node_level3']=this.nameNodeLevel3; if (this.nameNodeLevel4!==undefined && this.nameNodeLevel4!==null) postData['name_node_level4']=this.nameNodeLevel4; // Other fields can be added, but are currently not required // ### Call API //var apiUrl=apiHost+'/measures/structure/edit/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/structure/edit/'+this.id; ////console.log(apiUrl, postData); let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); //Logger.log('info', 'admin_measurestructure_edited', {page: 'settings/profile', data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivate(callbackSuccess) { //var apiUrl=apiHost+'/measures/structure/edit/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/structure/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); ////console.log(apiUrl); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahmen-Struktur wurde erfolgreich deaktiviert.', 'success'); //Logger.log('info', 'admin_measurestructure_deactivated', {data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahmen-Struktur wurde nicht deaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } reactivate(callbackSuccess) { //var apiUrl=apiHost+'/measures/structure/edit/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/structure/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=null; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahmen-Struktur wurde erfolgreich reaktiviert.', 'success'); //Logger.log('info', 'admin_measurestructure_reactivated', {data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahmen-Struktur wurde nicht reaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASURESTRUCTURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } getDisplayTitle() { let s=""; if (this.nameNodeLevel1!==undefined && this.nameNodeLevel1!==null) s+=(s!='' ? ' / ' : '')+this.nameNodeLevel1; if (this.nameNodeLevel2!==undefined && this.nameNodeLevel2!==null) s+=(s!='' ? ' / ' : '')+this.nameNodeLevel2; if (this.nameNodeLevel3!==undefined && this.nameNodeLevel3!==null) s+=(s!='' ? ' / ' : '')+this.nameNodeLevel3; if (this.nameNodeLevel4!==undefined && this.nameNodeLevel4!==null) s+=(s!='' ? ' / ' : '')+this.nameNodeLevel4; return s; } getDisplayTitleShort() { if (this.nameNodeLevel4!==undefined && this.nameNodeLevel4!==null) return this.nameNodeLevel4; if (this.nameNodeLevel3!==undefined && this.nameNodeLevel3!==null) return this.nameNodeLevel3; if (this.nameNodeLevel2!==undefined && this.nameNodeLevel2!==null) return this.nameNodeLevel2; if (this.nameNodeLevel1!==undefined && this.nameNodeLevel1!==null) return this.nameNodeLevel1; return null; } getNodeId() { if (this.idNodeLevel1===null) return null; else { if (this.idNodeLevel2===null) return this.idNodeLevel1.toString(); else { if (this.idNodeLevel3===null) return this.idNodeLevel1+'_'+this.idNodeLevel2; else { if (this.idNodeLevel4===null) return this.idNodeLevel1+'_'+this.idNodeLevel2+'_'+this.idNodeLevel3; else return this.idNodeLevel1+'_'+this.idNodeLevel2+'_'+this.idNodeLevel3+'_'+this.idNodeLevel4; } } } } static isActive(measureStructureObj) { let active=true; let inactiveReason=null; let inactiveStr=null; let parentActiveObjAry=[]; // MeasureStructure itself if (measureStructureObj.timestampDeactivated!==null) { active=false; inactiveReason='measureStructure'; inactiveStr=Helper.timestampFormat(measureStructureObj.timestampDeactivated, false, false); } return { active: active, inactiveReason: inactiveReason, inactiveStr: inactiveStr, parentActiveObjAry: parentActiveObjAry}; } } class MeasureStructureCSRD { constructor(apiMeasureStructureObj) { this.id=null; if ('pk_csrd_measures_structure' in apiMeasureStructureObj && apiMeasureStructureObj.pk_csrd_measures_structure!==null) this.id=apiMeasureStructureObj.pk_csrd_measures_structure; this.idNodeLevel1=null; if ('id_node_level1' in apiMeasureStructureObj && apiMeasureStructureObj.id_node_level1!==null) this.idNodeLevel1=apiMeasureStructureObj.id_node_level1; this.idNodeLevel2=null; if ('id_node_level2' in apiMeasureStructureObj && apiMeasureStructureObj.id_node_level2!==null) this.idNodeLevel2=apiMeasureStructureObj.id_node_level2; this.idNodeLevel3=null; if ('id_node_level3' in apiMeasureStructureObj && apiMeasureStructureObj.id_node_level3!==null) this.idNodeLevel3=apiMeasureStructureObj.id_node_level3; this.idNodeLevel4=null; if ('id_node_level4' in apiMeasureStructureObj && apiMeasureStructureObj.id_node_level4!==null) this.idNodeLevel4=apiMeasureStructureObj.id_node_level4; this.nameNodeLevel1=null; if ('name_node_level1' in apiMeasureStructureObj && apiMeasureStructureObj.name_node_level1!==null) this.nameNodeLevel1=apiMeasureStructureObj.name_node_level1; this.nameNodeLevel2=null; if ('name_node_level2' in apiMeasureStructureObj && apiMeasureStructureObj.name_node_level2!==null) this.nameNodeLevel2=apiMeasureStructureObj.name_node_level2; this.nameNodeLevel3=null; if ('name_node_level3' in apiMeasureStructureObj && apiMeasureStructureObj.name_node_level3!==null) this.nameNodeLevel3=apiMeasureStructureObj.name_node_level3; this.nameNodeLevel4=null; if ('name_node_level4' in apiMeasureStructureObj && apiMeasureStructureObj.name_node_level4!==null) this.nameNodeLevel4=apiMeasureStructureObj.name_node_level4; this.fkAccounts=null; if ('fk_accounts' in apiMeasureStructureObj && apiMeasureStructureObj.fk_accounts!==null) this.fkAccounts=apiMeasureStructureObj.fk_accounts; this.timestampDeactivated=apiMeasureStructureObj.timestamp_deactivated; this.measuresObjAry=[]; if ('measures' in apiMeasureStructureObj && apiMeasureStructureObj.measures!==null && Array.isArray(apiMeasureStructureObj.measures)) { for (let m of apiMeasureStructureObj.measures) { this.measuresObjAry.push(new MeasureCSRD(m, this)); } } this.nodeId=null; } static getAllMeasures(callbackSuccess=null) { const tsStartApi=Date.now(); var apiUrl=apiHost+'/csrd/measures/accountId/'+userObj.accountObj.id; return $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { Logger.log('FRONTEND_CLIENT_API_GET_CSRD_ALLMEASURESTRUCTURES', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); csrdStructureMeasures=MeasureStructureCSRD.transformMeasureStructure(dataFromApi); if (callbackSuccess!==null) callbackSuccess(csrdStructureMeasures); } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_CSRD_ALLMEASURESTRUCTURES', apiUrl, xhr, status, error); }); } static transformMeasureStructure(dataUnstructured) { // dataUnstructured = Array of MeasureStructure objects each including an array of measures let measuresByFk={}; // Sort by MeasureStructure ID dataUnstructured.sort(function(a,b) { if (a.pk_csrd_measures_structure < b.pk_csrd_measures_structure) return -1; else if (a.pk_csrd_measures_structure > b.pk_csrd_measures_structure) return 1; else return 0; }); var dataStructured=[]; let newlyCreatedMeasureStructure=null; if (dataUnstructured!==null && Array.isArray(dataUnstructured)) { for (let entryUn of dataUnstructured) { // For each MeasureStructure (as a flat array) - each MeasureStructure obj has a field with an array of Measures var level1Obj=null; var level2Obj=null; var level3Obj=null; var level4Obj=null; var level5Obj=null; // ### Check if structure path already exists (if not, create it) for (let entry of dataStructured) { if (entry.nodeId==entryUn.id_node_level1) { level1Obj=entry; if ('childs' in entry && Array.isArray(entry.childs)) { for (let entry2 of entry.childs) { if (entry2.nodeId==level1Obj.nodeId+'_'+entryUn.id_node_level2) { level2Obj=entry2; if ('childs' in entry2) { for (let entry3 of entry2.childs) { if (entry3.nodeId==level2Obj.nodeId+'_'+entryUn.id_node_level3) { level3Obj=entry3; if ('childs' in entry3) { for (let entry4 of entry3.childs) { if (entry4.nodeId==level3Obj.nodeId+'_'+entryUn.id_node_level4) { level4Obj=entry4; if ('childs' in entry4) { for (let entry5 of entry4.childs) { if (entry5.nodeId==level4Obj.nodeId+'_'+entryUn.id_node_level5) { level5Obj=entry5; // ... a 6th level could be added here if required } } } } } } } } } } } } } } // Create new nodes (if necessary) newlyCreatedMeasureStructure=null; if (level1Obj===null && entryUn.id_node_level1!==null) { level1Obj=new MeasureStructureCSRD(entryUn); newlyCreatedMeasureStructure=level1Obj; level1Obj['nameShort']=entryUn.name_node_level1; level1Obj['nameLong']=entryUn.name_node_level1; level1Obj['nodeId']=entryUn.id_node_level1; dataStructured.push(level1Obj); } if (level2Obj===null && entryUn.id_node_level2!==null) { level2Obj=new MeasureStructureCSRD(entryUn); newlyCreatedMeasureStructure=level2Obj; level2Obj['nameShort']=entryUn.name_node_level2; level2Obj['nameLong']=entryUn.name_node_level2; level2Obj['nodeId']=level1Obj.nodeId+'_'+entryUn.id_node_level2; if (!('childs' in level1Obj)) level1Obj['childs']=[]; level1Obj['childs'].push(level2Obj); } if (level3Obj===null && entryUn.id_node_level3!==null) { level3Obj=new MeasureStructureCSRD(entryUn); newlyCreatedMeasureStructure=level3Obj; level3Obj['nameShort']=entryUn.name_node_level3; level3Obj['nameLong']=entryUn.name_node_level3; level3Obj['nodeId']=level2Obj.nodeId+'_'+entryUn.id_node_level3; if (!('childs' in level2Obj)) level2Obj['childs']=[]; level2Obj['childs'].push(level3Obj); } if (level4Obj===null && entryUn.id_node_level4!==null) { level4Obj=new MeasureStructureCSRD(entryUn); newlyCreatedMeasureStructure=level4Obj; level4Obj['nameShort']=entryUn.name_node_level4; level4Obj['nameLong']=entryUn.name_node_level4; level4Obj['nodeId']=level3Obj.nodeId+'_'+entryUn.id_node_level4; if (!('childs' in level3Obj)) level3Obj['childs']=[]; level3Obj['childs'].push(level4Obj); } // Fill measuresByFk with data for further usage if (newlyCreatedMeasureStructure!==null) { for (let m of newlyCreatedMeasureStructure.measuresObjAry) { measuresByFk[m.id]=m; } } } //console.log(measuresByFk); // Link child measures to parent measures let m=null; for (let key in measuresByFk) { m=measuresByFk[key]; if (m.fkMeasureParent!==null) { // m is a child measuresByFk[m.fkMeasureParent].childMeasures.push(m); } } } return dataStructured; } static createStructureTable(tableHtmlId, csrdStructureOEs, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit) { $('#'+tableHtmlId+' tbody').empty(); $('#'+tableHtmlId+' tbody').append(MeasureStructureCSRD.createStructureTableRow(csrdStructureOEs, null, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit)); Helper.createCollapsableTable(tableHtmlId, function(tableRow) { $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90").addClass("fa-rotate-90"); // Make sure chevron is shown correctly (i.e. is in OPEN state) }); } static createStructureTableRow(structureObj, levelStr=null, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit) { //console.log(callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit); var $returnJQueryObj=$(); var levelAry=[]; if (levelStr!==null) levelAry=levelStr.split('_'); var levelClass=''; if (levelAry.length==0) levelClass='level1'; else if (levelAry.length==1) levelClass='level2'; else if (levelAry.length==2) levelClass='level3'; else if (levelAry.length==3) levelClass='level4'; else if (levelAry.length==4) levelClass='level5'; if (structureObj!==null && Array.isArray(structureObj) && structureObj.length>0) { for (var i=0; i'); if (childsExist) $tr.append(' '+structureObj[i].nameLong+''); else $tr.append(''+structureObj[i].nameLong+''); if (active) { // De-Activate button if (levelAry.length>0) { // Do not allow deactivation of level1/root node let $trashIcon=$(''); $tr.append($('').append($trashIcon)); $trashIcon.on('click', function(event) { ////console.log('trash icon clicked ('+$(this).attr('data-id')+')'); var measureStructureObj=new MeasureStructureCSRD({ pk_csrd_measures_structure : $(this).attr('data-id')}); ////console.log($(this).attr('data-id'), measureStructureObj.id); measureStructureObj.deactivate(function() { ////console.log('deactiveate measure structure success'); //Update data MeasureStructureCSRD.getAllMeasures(function() { MeasureStructureCSRD.createStructureTable('tableMeasures', csrdStructureMeasures, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit); }); }); event.stopPropagation(); // To prevent the underlying event of the table row TR }); } else { $tr.append($('')); } let parentMeasureStructureObj=structureObj[i]; // "Create New" button if (levelAry.length<3) { // zero based index, i.e. 3 -> only levels 1, 2 and 3 are allowed to add child nodes let $btn=$(''); $btn.on('click', function(event) { event.stopPropagation(); // To prevent the underlying event of the table row TR ////console.log('new icon clicked ('+$(this).attr('data-id')+')', event, this, parentMeasureStructureObj); //openModalMeasureStructure(parentMeasureStructureObj); callbackOpenModalMeasureStructure(parentMeasureStructureObj); }); $tr.append($('').append($btn)); } else { $tr.append($('')); } // "Edit" button let $btnEdit=$(''); $btnEdit.on('click', function(event) { event.stopPropagation(); // To prevent the underlying event of the table row TR ////console.log('EDIT icon clicked ('+$(this).attr('data-id')+')', event, this, parentMeasureStructureObj); //openModalMeasureStructureForEdit(parentMeasureStructureObj); callbackOpenModalMeasureStructureForEdit(parentMeasureStructureObj); }); $tr.append($('').append($btnEdit)); } else { let $reactivateIcon=$(''); $tr.append($('').append($reactivateIcon).append('
    '+(structureObj[i].timestampDeactivated!==null ? Helper.timestampFormat(structureObj[i].timestampDeactivated, false, false) : '')+'')); $reactivateIcon.on('click', function(event) { ////console.log('reactivate icon clicked ('+$(this).attr('data-id')+')'); var measureStructureObj=new MeasureStructureCSRD({ pk_csrd_measures_structure : $(this).attr('data-id')}); ////console.log($(this).attr('data-id'), measureStructureObj.id); measureStructureObj.reactivate(function() { ////console.log('re-activeate measure structure success'); //Update data MeasureStructureCSRD.getAllMeasures(function() { MeasureStructureCSRD.createStructureTable('tableMeasures', csrdStructureMeasures, callbackOpenModalMeasureStructure, callbackOpenModalMeasureStructureForEdit); }); }); event.stopPropagation(); // To prevent the underlying event of the table row TR }); $tr.append($('')); $tr.append($('')); } $returnJQueryObj=$returnJQueryObj.add($tr); if (childsExist) { $returnJQueryObj=$returnJQueryObj.add( MeasureStructureCSRD.createStructureTableRow( structureObj[i].childs , (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1)) , callbackOpenModalMeasureStructure , callbackOpenModalMeasureStructureForEdit ) ); } } } return $returnJQueryObj; } static createStructureTableRowForMultipleSelection(structureObj, levelStr=null) { var $returnJQueryObj=$(); var levelAry=[]; if (levelStr!==null) levelAry=levelStr.split('_'); var levelClass=''; if (levelAry.length==0) levelClass='level1'; else if (levelAry.length==1) levelClass='level2'; else if (levelAry.length==2) levelClass='level3'; else if (levelAry.length==3) levelClass='level4'; else if (levelAry.length==4) levelClass='level5'; if (structureObj!==null && Array.isArray(structureObj) && structureObj.length>0) { for (var i=0; i' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +''); } } else { $returnJQueryObj=$returnJQueryObj.add('' +' '+structureObj[i].nameShort+'' //+' ' +' ' +(showCheckbox ? '' : ' ') +'' +''); $returnJQueryObj=$returnJQueryObj.add( MeasureStructureCSRD.createStructureTableRowForMultipleSelection(structureObj[i].childs, (levelStr===null ? dataLevelIdx.toString() : levelStr+'_'+(i+1))) ); } } } return $returnJQueryObj; } static createMultiSelectionTreeMeasureStructures(tableHtmlId, structureMeasureStructuresAry) { $('#'+tableHtmlId+' tbody').empty(); $('#'+tableHtmlId+' tbody').append(MeasureStructureCSRD.createStructureTableRowForMultipleSelection(structureMeasureStructuresAry)); Helper.createCollapsableTable(tableHtmlId, function(tableRow) { $(tableRow).find('span.fa-chevron-right').removeClass("fa-rotate-90").addClass("fa-rotate-90"); // Make sure chevron is shown correctly (i.e. is in OPEN state) }); // Create event handler for checkboxes $("#"+tableHtmlId+" tbody tr input[type=checkbox]").change(function(event) { var $parentTr = $(this).closest('tr'); var isNowChecked = $(this).is(":checked"); var write=$(this).hasClass('write'); }); } saveNew(callbackSuccess) { if (this.idNodeLevel1===null || this.idNodeLevel1=='') { Helper.showToastr('Fehler', 'Level 1 ID fehlt.', 'error'); return; } if (this.nameNodeLevel1===null || this.nameNodeLevel1=='') { Helper.showToastr('Fehler', 'Level 1 Name fehlt.', 'error'); return; } if (this.fkAccounts===null || this.fkAccounts=='') { Helper.showToastr('Fehler', 'Account ID fehlt.', 'error'); return; } if (this.id!==undefined && this.id!==null) { Helper.showToastr('Fehler', 'Maßnahmen-Struktur ID ist gesetzt ('+this.id+') - ungültiger Zustand für neu anzulegende Maßnahmen-Strukturen.', 'error'); return; } if (this.idNodeLevel1===null && this.nameNodeLevel1!==null && this.nameNodeLevel1.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.idNodeLevel2===null && this.nameNodeLevel2!==null && this.nameNodeLevel2.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.idNodeLevel3===null && this.nameNodeLevel3!==null && this.nameNodeLevel3.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.idNodeLevel4===null && this.nameNodeLevel4!==null && this.nameNodeLevel4.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } var apiUrl=apiHost+'/csrd/measures/structure/new'; // !the keys have to equal the Java class fields! var postData={}; postData['fk_accounts']=this.fkAccounts; if (this.nameNodeLevel1!==null) { if (this.idNodeLevel1!==null) postData['id_node_level1']=this.idNodeLevel1; postData['name_node_level1']=this.nameNodeLevel1; if (this.nameNodeLevel2!==null) { if (this.idNodeLevel2!==null) postData['id_node_level2']=this.idNodeLevel2; postData['name_node_level2']=this.nameNodeLevel2; if (this.nameNodeLevel3!==null) { if (this.idNodeLevel3!==null) postData['id_node_level3']=this.idNodeLevel3; postData['name_node_level3']=this.nameNodeLevel3; if (this.nameNodeLevel4!==null) { if (this.idNodeLevel4!==null) postData['id_node_level4']=this.idNodeLevel4; postData['name_node_level4']=this.nameNodeLevel4; } } } } let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASURESTRUCTURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if ('pk_csrd_measures_structure' in data && data.pk_csrd_measures_structure!==null && data.pk_csrd_measures_structure!==undefined && data.pk_csrd_measures_structure!='') { Helper.showToastr('Erfolg', 'Neue Maßnahmen-Struktur wurde gespeichert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASURESTRUCTURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); Helper.showToastr('Fehler', 'Fehler beim Speichern der Maßnahmen-Struktur: '+data.msg, 'error'); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_NEW_CSRD_MEASURESTRUCTURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } save(callbackSuccess) { //////console.log('save', this); if (this.nameNodeLevel1!==null && this.nameNodeLevel1.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.nameNodeLevel2!==null && this.nameNodeLevel2.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.nameNodeLevel3!==null && this.nameNodeLevel3.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.nameNodeLevel4!==null && this.nameNodeLevel4.trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } // ### Check data consistency & assemble POST data obj var postData={}; if (this.nameNodeLevel1!==undefined && this.nameNodeLevel1!==null) postData['name_node_level1']=this.nameNodeLevel1; if (this.nameNodeLevel2!==undefined && this.nameNodeLevel2!==null) postData['name_node_level2']=this.nameNodeLevel2; if (this.nameNodeLevel3!==undefined && this.nameNodeLevel3!==null) postData['name_node_level3']=this.nameNodeLevel3; if (this.nameNodeLevel4!==undefined && this.nameNodeLevel4!==null) postData['name_node_level4']=this.nameNodeLevel4; // Other fields can be added, but are currently not required // ### Call API var apiUrl=apiHost+'/csrd/measures/structure/edit/'+this.id; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivate(callbackSuccess) { var apiUrl=apiHost+'/csrd/measures/structure/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahmen-Struktur wurde erfolgreich deaktiviert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahmen-Struktur wurde nicht deaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } reactivate(callbackSuccess) { var apiUrl=apiHost+'/csrd/measures/structure/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=null; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahmen-Struktur wurde erfolgreich reaktiviert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahmen-Struktur wurde nicht reaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURESTRUCTURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } getDisplayTitle() { let s=""; if (this.nameNodeLevel1!==undefined && this.nameNodeLevel1!==null) s+=(s!='' ? ' / ' : '')+this.nameNodeLevel1; if (this.nameNodeLevel2!==undefined && this.nameNodeLevel2!==null) s+=(s!='' ? ' / ' : '')+this.nameNodeLevel2; if (this.nameNodeLevel3!==undefined && this.nameNodeLevel3!==null) s+=(s!='' ? ' / ' : '')+this.nameNodeLevel3; if (this.nameNodeLevel4!==undefined && this.nameNodeLevel4!==null) s+=(s!='' ? ' / ' : '')+this.nameNodeLevel4; return s; } getDisplayTitleShort() { if (this.nameNodeLevel4!==undefined && this.nameNodeLevel4!==null) return this.nameNodeLevel4; if (this.nameNodeLevel3!==undefined && this.nameNodeLevel3!==null) return this.nameNodeLevel3; if (this.nameNodeLevel2!==undefined && this.nameNodeLevel2!==null) return this.nameNodeLevel2; if (this.nameNodeLevel1!==undefined && this.nameNodeLevel1!==null) return this.nameNodeLevel1; return null; } getNodeId() { if (this.idNodeLevel1===null) return null; else { if (this.idNodeLevel2===null) return this.idNodeLevel1.toString(); else { if (this.idNodeLevel3===null) return this.idNodeLevel1+'_'+this.idNodeLevel2; else { if (this.idNodeLevel4===null) return this.idNodeLevel1+'_'+this.idNodeLevel2+'_'+this.idNodeLevel3; else return this.idNodeLevel1+'_'+this.idNodeLevel2+'_'+this.idNodeLevel3+'_'+this.idNodeLevel4; } } } } static isActive(measureStructureObj) { let active=true; let inactiveReason=null; let inactiveStr=null; let parentActiveObjAry=[]; // MeasureStructure itself if (measureStructureObj.timestampDeactivated!==null) { active=false; inactiveReason='measureStructure'; inactiveStr=Helper.timestampFormat(measureStructureObj.timestampDeactivated, false, false); } return { active: active, inactiveReason: inactiveReason, inactiveStr: inactiveStr, parentActiveObjAry: parentActiveObjAry}; } } class Measure { constructor(apiMeasureObj={}, parentMeasureStructureObj=null) { this.parentMeasureStructureObj=null; if (parentMeasureStructureObj!==null) this.parentMeasureStructureObj=parentMeasureStructureObj; this.id=null; if ('pk_measures' in apiMeasureObj && apiMeasureObj.pk_measures!==null) this.id=apiMeasureObj.pk_measures; this.fkMeasureParent=null; if ('fkMeasuresParent' in apiMeasureObj && apiMeasureObj.fkMeasuresParent!==null) this.fkMeasureParent=apiMeasureObj.fkMeasuresParent; this.childMeasures=[]; // Is filled during MeasureStructure.transformMeasureStructure(..) this.name=null; if ('name' in apiMeasureObj && apiMeasureObj.name!==null) this.name=String(apiMeasureObj.name); this.description=null; if ('description' in apiMeasureObj && apiMeasureObj.description!==null) this.description=String(apiMeasureObj.description); this.private_only=null; if ('private_only' in apiMeasureObj && apiMeasureObj.private_only!==null) this.private_only=apiMeasureObj.private_only; this.approved=null; if ('approved' in apiMeasureObj && apiMeasureObj.approved!==null) this.approved=apiMeasureObj.approved; this.budget=null; if ('budget' in apiMeasureObj && apiMeasureObj.budget!==null) this.budget=apiMeasureObj.budget; this.responsibleUserObj=null; if ('userResponsible' in apiMeasureObj && apiMeasureObj.userResponsible!==null) this.responsibleUserObj=User.createUserObjByApiData(apiMeasureObj.userResponsible); this.creatorUserObj=null; if ('userCreator' in apiMeasureObj && apiMeasureObj.userCreator!==null) this.creatorUserObj=User.createUserObjByApiData(apiMeasureObj.userCreator); this.lastEditorUserObj=null; if ('userLastEditor' in apiMeasureObj && apiMeasureObj.userLastEditor!==null) this.lastEditorUserObj=User.createUserObjByApiData(apiMeasureObj.userLastEditor); this.milestonesObjAry=[]; if ('measureMilestones' in apiMeasureObj && apiMeasureObj.measureMilestones!==null && Array.isArray(apiMeasureObj.measureMilestones)) { for (let m of apiMeasureObj.measureMilestones) { this.milestonesObjAry.push(new MeasureMilestone(m)); } } this.elementOuCombiValuesObjAry=[]; if ('measureValues' in apiMeasureObj && apiMeasureObj.measureValues!==null && Array.isArray(apiMeasureObj.measureValues)) { for (let v of apiMeasureObj.measureValues) { this.elementOuCombiValuesObjAry.push(new MeasureElementOuCombiValue(v, this)); } } // measureFiles this.files=[]; if (apiMeasureObj.measureFiles!==undefined && apiMeasureObj.measureFiles!==null && Array.isArray(apiMeasureObj.measureFiles)) { for (let idx=0; idx0) { Helper.showToastr('Fehler', 'Eine Kind-Maßnahme darf keine aktiven Wirkungen auf Messwerte besitzen.', 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_MEASURE', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Inconsistency: Child measure to be saved with >0 elementOuCombiValues' }); return; } else if (this.isChild() && this.isParentAlsoForIndirectInactiveChilds()) { Helper.showToastr('Fehler', 'Maßnahme darf nicht gleichzeitig Elter und Kind sein.', 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_MEASURE', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Inconsistency: Measure is both child and parent' }); return; } //var apiUrl=apiHost+'/measures/new?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/new'; // !the keys have to equal the Java class fields! var postData={}; postData['measureStructure']={ pk_measures_structure: this.parentMeasureStructureObj.id, fk_accounts: this.parentMeasureStructureObj.fkAccounts }; postData['userResponsible']={ pk_users: this.responsibleUserObj.id }; postData['name']=this.name; postData['description']=this.description; postData['private_only']=this.private_only; postData['approved']=this.approved; postData['budget']=this.budget; postData['fkMeasuresParent']=this.fkMeasureParent; // userCreator is added in backend // userLastEditor is added in backend //postData['measureMilestones']=this.milestonesObjAry; postData['measureMilestones']=[]; for (let ms of this.milestonesObjAry) { postData['measureMilestones'].push({ name: ms.name , timestamp_deadline: ms.timestampDeadline , status_bol: ms.status , timestamp_deactivated: ms.timestamp_deactivated }); } //postData['measureValues']=this.elementOuCombiValuesObjAry; postData['measureValues']=[]; for (let eocv of this.elementOuCombiValuesObjAry) { postData['measureValues'].push({ elementOeCombi: { pk_elements_organizational_units: eocv.elementOuCombiObj.id } , baselineMet: eocv.baselineMet , baselineBin: eocv.baselineBin , baselineCat: eocv.baselineCat , targetMet: eocv.targetMet , targetBin: eocv.targetBin , targetCat: eocv.targetCat , timestamp_effect_from: eocv.timestampEffectStart , timestamp_effect_to: eocv.timestampEffectEnd , timestamp_deactivated: eocv.timestamp_deactivated }); } ////console.log(postData); let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if ('pk_measures' in data && data.pk_measures!==null && data.pk_measures!==undefined && data.pk_measures!='') { //Logger.log('info', 'api_call', {url: apiUrl, durationInMs: (Date.now()-tsStartApi)}); //Logger.log('info', 'admin_measure_created', {data: data}); Helper.showToastr('Erfolg', 'Neue Maßnahme wurde gespeichert.', 'success'); //console.log(data); let measure=new Measure(data); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(measure); } else { ////console.log(data); Logger.log('FRONTEND_CLIENT_API_NEW_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); Helper.showToastr('Fehler', 'Fehler beim Speichern der Maßnahme: '+data.msg, 'error'); } }} ).fail(function(xhr, status, error) { ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Helper.showToastr('Fehler', 'Daten können nicht gespeichert werden ('+errorMsg+').', 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_MEASURE', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg }); */ handleFailedApiCall('FRONTEND_CLIENT_API_NEW_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } save(callbackSuccess) { if (this.name!==null && String(this.name).trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.responsibleUserObj!==null && this.responsibleUserObj.id===null) { Helper.showToastr('Fehler', 'Verantwortlicher User darf nicht leer sein.', 'error'); return; } if (this.parentMeasureStructureObj!==null && this.parentMeasureStructureObj.id===null) { Helper.showToastr('Fehler', 'Maßnahmen-Struktur darf nicht leer sein.', 'error'); return; } if (this.isChild() && this.getNrActiveCombis()>0) { Helper.showToastr('Fehler', 'Eine Kind-Maßnahme darf keine aktiven Wirkungen auf Messwerte besitzen.', 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Inconsistency: Child measure to be saved with >0 elementOuCombiValues' }); return; } else if (this.isChild() && this.isParentAlsoForIndirectInactiveChilds()) { Helper.showToastr('Fehler', 'Maßnahmen kann nicht gleichzeitig Elter und Kind sein.', 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Inconsistency: Measure is both child and parent' }); return; } // ### Check data consistency & assemble POST data obj var postData={}; if (this.name!==undefined && this.name!==null) postData['name']=this.name; if (this.description!==undefined && this.description!==null) postData['description']=this.description; if (this.private_only!==undefined && this.private_only!==null) postData['private_only']=this.private_only; if (this.approved!==undefined && this.approved!==null) postData['approved']=this.approved; if (this.budget!==undefined && this.budget!==null) postData['budget']=this.budget; if (this.fkMeasureParent!==undefined && this.fkMeasureParent!==null) postData['fkMeasuresParent']=this.fkMeasureParent; if (this.responsibleUserObj!==undefined && this.responsibleUserObj!==null) postData['userResponsible']=this.responsibleUserObj.id; if (this.parentMeasureStructureObj!=undefined && this.parentMeasureStructureObj!==null) postData['measureStructure']=this.parentMeasureStructureObj.id; if (this.milestonesObjAry!==null && this.milestonesObjAry.length>0) { postData['measureMilestones']=this.milestonesObjAry; } if (this.elementOuCombiValuesObjAry!==null && this.elementOuCombiValuesObjAry.length>0) { //postData['measureValues']=this.elementOuCombiValuesObjAry; postData['measureValues']=[]; for (let eocv of this.elementOuCombiValuesObjAry) { postData['measureValues'].push(eocv.getObjOfThisWithoutMeasureObj()); } } // ### Call API //var apiUrl=apiHost+'/measures/edit/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/edit/'+this.id; //console.log(apiUrl, postData); let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); //Logger.log('info', 'admin_measure_edited', {page: 'settings/profile', data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivate(callbackSuccess, addPostData=null) { //var apiUrl=apiHost+'/measures/edit/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 if (addPostData!==null && 'addCommand' in addPostData) postData['addCommand']=addPostData.addCommand; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); ////console.log(apiUrl); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahme wurde erfolgreich deaktiviert.', 'success'); //Logger.log('info', 'admin_measure_deactivated', {data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahme wurde nicht deaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg }); Helper.showToastr('Fehler', 'Daten können momentan nicht gespeichert werden ('+errorMsg+').', 'error'); */ handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivateInclChilds(callbackSuccess) { this.deactivate(callbackSuccess, { addCommand: 'deactivateInclChilds' }); } deactivateAndTransformChilds(callbackSuccess) { this.deactivate(callbackSuccess, { addCommand: 'deactivateAndTransformChilds' }); } reactivate(callbackSuccess) { // Not used //var apiUrl=apiHost+'/measures/edit/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=null; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahme wurde erfolgreich reaktiviert.', 'success'); //Logger.log('info', 'admin_measure_reactivated', {data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahme wurde nicht reaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } archive(callbackSuccess) { //var apiUrl=apiHost+'/measures/edit/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_archived']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); ////console.log(apiUrl); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahme wurde erfolgreich archiviert.', 'success'); //Logger.log('info', 'admin_measure_deactivated', {data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahme wurde nicht archiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } unarchive(callbackSuccess) { //var apiUrl=apiHost+'/measures/edit/'+this.id+'?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/measures/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_archived']=null; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahme wurde erfolgreich reaktiviert.', 'success'); //Logger.log('info', 'admin_measure_reactivated', {data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahme wurde nicht reaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { ////console.log(xhr); ////console.log(status); ////console.log(error); /* var errorMsg=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'message' in xhr.responseJSON) ? xhr.responseJSON.message : ''); var errorHttpCode=((xhr!==null && 'responseJSON' in xhr && xhr.responseJSON!==null && 'status' in xhr.responseJSON) ? xhr.responseJSON.status : null); Logger.log('FRONTEND_CLIENT_API_EDIT_MEASURE', (errorHttpCode==501 ? 'ERROR_USER_APIREQUEST' : 'ERROR_SYSTEM_APIREQUEST'), { apiUrl: apiUrl, errorMsg: errorMsg }); Helper.showToastr('Fehler', 'Daten können momentan nicht gespeichert werden ('+errorMsg+').', 'error'); */ handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } // An archived measure can be active! static isActive(measureObj) { let active=true; let inactiveReason=null; let inactiveStr=''; let parentActiveObjAry=[]; /* MEASURE IS NOT INACTIVE WHEN ALL MeasureElementOuCombiValues ARE INACTIVE, AS MEASURE CAN ALSO EXIST WITHOUT ANY MeasureElementOuCombiValue // MeasureElementOuCombiValues let counterActives=0; let activeTmp=true; let inactiveReasonTmp=null; let inactiveStrTmp=''; for (let eocv of measureObj.elementOuCombiValuesObjAry) { let activeObj=MeasureElementOuCombiValue.isActive(eocv); if (!activeObj.active) { activeTmp=activeObj.active; inactiveReasonTmp=activeObj.inactiveReason; inactiveStrTmp=activeObj.inactiveStr; } else counterActives++; parentActiveObjAry.push(activeObj); } if (counterActives==0 && measureObj.elementOuCombiValuesObjAry.length>0) { // >0 combis exist, but all are inactive (=0 are active) active=activeTmp; inactiveReason=inactiveReasonTmp; inactiveStr=inactiveStrTmp; } */ // Measure Structure let activeObj=MeasureStructure.isActive(measureObj.parentMeasureStructureObj); if (!activeObj.active) { active=activeObj.active; inactiveReason=activeObj.inactiveReason; inactiveStr=activeObj.inactiveStr; } parentActiveObjAry.push(activeObj); // Measure itself if (measureObj.timestampDeactivated!==null) { active=false; inactiveReason='measure'; inactiveStr=Helper.timestampFormat(measureObj.timestampDeactivated, false, false); } return { active: active, inactiveReason: inactiveReason, inactiveStr: inactiveStr, parentActiveObjAry: parentActiveObjAry}; } static checkIfElementOUObjIsAlreadyLinkedToAtLeast1Measure(elementOeCombiObj) { let structureMeasuresAsMapByNodeId=ElementOeSelector.getStructureAsMapByNodeId(structureMeasures); let returnObj={ active: null, tooltip: 'Dieser Messwert wurde bereits einer Maßnahme zugeordnet.', prefixHtml: '' }; /* !!! All logic in the next loop is also implemented in Java in backend! In case of changes, also change in backend !!! */ for (let msKey in structureMeasuresAsMapByNodeId) { // For each measure structure for (let m of structureMeasuresAsMapByNodeId[msKey].measuresObjAry) { // For each Measure ... // Check if measure active //////console.log(m); //if (m.timestampDeactivated===null) { // SHOULDN'T Measure.isActive() BE USED? if (Measure.isActive(m).active) { for (let eocv of m.elementOuCombiValuesObjAry) { // For each MeasureValue ... // Check if measure value active if (MeasureElementOuCombiValue.isActive(eocv).active) { // Check if elementOuCombi active if (eocv.elementOuCombiObj!==undefined && eocv.elementOuCombiObj!==null && ElementOuCombi.isActive(eocv.elementOuCombiObj).active) { if (eocv.elementOuCombiObj.id==elementOeCombiObj.id) { returnObj.active=false; //console.log(msKey, m, eocv); return returnObj; } } } } } } } returnObj.active=true; return returnObj; } static getMeasureById(id) { let structureMeasuresAsMapByNodeId=ElementOeSelector.getStructureAsMapByNodeId(structureMeasures); for (let msKey in structureMeasuresAsMapByNodeId) { let ms=structureMeasuresAsMapByNodeId[msKey]; for (let m of ms.measuresObjAry) { if (m.id==id) { return m; } } } return null; } checkIfElementOUObjIsAlreadyLinkedToThisMeasure(elementOeCombiObj) { let returnObj={ active: null, tooltip: 'Dieser Messwert wurde bereits dieser Maßnahme zugeordnet.', prefixHtml: '' }; for (let eocv of this.elementOuCombiValuesObjAry) { // For each MeasureValue ... // Check if measure value active if (eocv.timestamp_deactivated===null) { if (eocv.elementOuCombiObj.id==elementOeCombiObj.id) { returnObj.active=false; return returnObj; } } } returnObj.active=true; return returnObj; } /* static createMeasureWithParameters(parentMeasureStructureObj, id, name, responsibleUserObj, creatorUserObj, ) { } */ loadMeasureObjIntoThis(measureObj) { //measureObj && Object.assign(this, measureObj); if (measureObj.parentMeasureStructureObj!==undefined && measureObj.parentMeasureStructureObj!==null) this.parentMeasureStructureObj=measureObj.parentMeasureStructureObj; if (measureObj.id!==undefined && measureObj.id!==null) this.id=measureObj.id; //apiMeasureObj.pk_measures=measureObj.id; if (measureObj.name!==undefined && measureObj.name!==null) this.name=measureObj.name; //apiMeasureObj.pk_measures=measureObj.name; if (measureObj.fkMeasureParent!==undefined && measureObj.fkMeasureParent!==null) this.fkMeasureParent=measureObj.fkMeasureParent; if (measureObj.description!==undefined && measureObj.description!==null) this.description=measureObj.description; if (measureObj.private_only!==undefined && measureObj.private_only!==null) this.private_only=measureObj.private_only; if (measureObj.approved!==undefined && measureObj.approved!==null) this.approved=measureObj.approved; if (measureObj.budget!==undefined && measureObj.budget!==null) this.budget=measureObj.budget; if (measureObj.timestampDeactivated!==undefined && measureObj.timestampDeactivated!==null) this.timestampDeactivated=measureObj.timestampDeactivated; //apiMeasureObj.timestamp_deactivated=measureObj.timestampDeactivated; this.milestonesObjAry=[]; for (let mm of measureObj.milestonesObjAry) { let newMeasureMilestoneObj=new MeasureMilestone(); newMeasureMilestoneObj.loadMeasureMilestoneObjIntoThis(mm); this.milestonesObjAry.push(newMeasureMilestoneObj); } this.elementOuCombiValuesObjAry=[]; for (let v of measureObj.elementOuCombiValuesObjAry) { let newElementOuCombiValuesObj=new MeasureElementOuCombiValue(); newElementOuCombiValuesObj.loadMeasureElementOuCombiValueIntoThis(v); this.elementOuCombiValuesObjAry.push(newElementOuCombiValuesObj); } this.childMeasures=[]; for (let v of measureObj.childMeasures) { this.childMeasures.push(v); } // Here, the object can be re-used (instead of creating a new object), because the object's content will not be changed (instead the whole object might be replaced) if (measureObj.responsibleUserObj!==undefined && measureObj.responsibleUserObj!==null) this.responsibleUserObj=measureObj.responsibleUserObj; if (measureObj.creatorUserObj!==undefined && measureObj.creatorUserObj!==null) this.creatorUserObj=measureObj.creatorUserObj; if (measureObj.lastEditorUserObj!==undefined && measureObj.lastEditorUserObj!==null) this.lastEditorUserObj=measureObj.lastEditorUserObj; } getDisplayTitle() { return this.name; } getNrActiveCombis() { // If something changes here, also needs to be reflected in backend Measure.getNrActiveValues() let nrActiveCombis=0; for (let combi of this.elementOuCombiValuesObjAry) { if (MeasureElementOuCombiValue.isActive(combi).active) nrActiveCombis++; } return nrActiveCombis; } // Jumps to non-archived measures only static showMeasureFromExternal(measureId, archived=false) { externalCallMeasureId=measureId; if (archived===false) clickOnNav1Item(['measures','measures_my']); else clickOnNav1Item(['measures','measures_archive']); } calculateMilestonesImplementation() { // Return 0 (in plan), 1 (ahead of plan) or -1 (behind plan) let nrMilestonesToBeDone=0; let nrMilestonesToBeDoneAndActuallyDone=0; let nrMilestonesNotToBeDoneButActuallyDone=0; for (let ms of this.milestonesObjAry) { if (MeasureMilestone.isActive(ms).active) { //if (Helper.parseTimestampToUnixTimestampInMillis(ms.timestampDeadline).unix() < moment().unix()) { // Deadline is in the past if (Helper.parseTimestampToUnixTimestampInMillis(ms.timestampDeadline) < moment().tz('Europe/Berlin').unix()) { // Deadline is in the past nrMilestonesToBeDone++; if (ms.status===true) { nrMilestonesToBeDoneAndActuallyDone++; } else { /* nothing to do */ } } else { // Deadline is in the future if (ms.status===true) { nrMilestonesNotToBeDoneButActuallyDone++; } else { /* nothing to do */ } } } } if (nrMilestonesToBeDone>0 && nrMilestonesToBeDoneAndActuallyDone / nrMilestonesToBeDone < 1) return -1; // Not all due milestones done else { // All due milestones done if (nrMilestonesNotToBeDoneButActuallyDone > 0) return 1; // Additionally, some future milestones are also done else return 0; // In Plan } } toBeBlurred() { if (this.private_only!==true || userObj.role==3 || userObj.role==2 || userObj.id==this.responsibleUserObj.id) return false; else return true; } isChild() { // If something changes here, also needs to be reflected in backend Measure.isChild() if (this.fkMeasureParent!==undefined && this.fkMeasureParent!==null && this.fkMeasureParent!=='') return true; else return false; } isParent() { // If something changes here, also needs to be reflected in backend ApiService.checkConsistencyObjectMeasure(..) /* A measure is parent if child measures are linked to it. Child measures need to be active (=non deactivated) in order to count. Measures with only deactivated child measures are NOT parent. Child measure CAN be archived in order to count. BUT: A measure which is a child AND archived is not allowed (=invalid state). How to handle measures which are not directly deactivated, but indirectly through MeasureStructure? Currently, measures which are indirectly deactivated also count as deactivated/non-active. */ if (this.getActiveChildMeasures().length>0) return true; else return false; } isParentAlsoForIndirectInactiveChilds() { // If something changes here, also needs to be reflected in backend ApiService.checkConsistencyObjectMeasure(..) // Indirect inactive measures are not inactive themselves. But the measure structure is inactive. if (this.getActiveAndIndirectInactiveChildMeasures().length>0) return true; else return false; } isParentAlsoForIndirectInactiveApprovedChilds() { // If something changes here, also needs to be reflected in backend ApiService.checkConsistencyObjectMeasure(..) // Indirect inactive measures are not inactive themselves. But the measure structure is inactive. if (this.getActiveAndIndirectInactiveApprovedChildMeasures().length>0) return true; else return false; } getActiveChildMeasures() { let ary=[]; for (let cm of this.childMeasures) { if (Measure.isActive(cm).active) ary.push(cm); } return ary; } getActiveAndIndirectInactiveChildMeasures() { // Indirect inactive measures are not inactive themselves. But the measure structure is inactive. let ary=[]; for (let cm of this.childMeasures) { if (Measure.isActive(cm).active || Measure.isActive(cm).inactiveReason!='measure') ary.push(cm); } return ary; } getActiveAndIndirectInactiveApprovedChildMeasures() { // Indirect inactive measures are not inactive themselves. But the measure structure is inactive. let ary=[]; for (let cm of this.childMeasures) { if ((Measure.isActive(cm).active || Measure.isActive(cm).inactiveReason!='measure') && cm.approved) ary.push(cm); } return ary; } isBudgetEqualToSumOfChildBudgets() { if (this.isParent()) { let sumBudgetChilds=null; for (let cm of this.getActiveChildMeasures()) { if (cm.budget!==null) { if (sumBudgetChilds==null) sumBudgetChilds=cm.budget; else sumBudgetChilds+=cm.budget; } } //console.log('budget', sumBudgetChilds, m.budget); if (sumBudgetChilds!==null && this.budget!==null && sumBudgetChilds!=this.budget) return false; else return true; } else return true; } } class MeasureCSRD { constructor(apiMeasureObj={}, parentMeasureStructureObj=null) { this.parentMeasureStructureObj=null; if (parentMeasureStructureObj!==null) this.parentMeasureStructureObj=parentMeasureStructureObj; this.id=null; if ('pk_csrd_measures' in apiMeasureObj && apiMeasureObj.pk_csrd_measures!==null) this.id=apiMeasureObj.pk_csrd_measures; this.fkMeasureParent=null; if ('fkMeasuresParent' in apiMeasureObj && apiMeasureObj.fkMeasuresParent!==null) this.fkMeasureParent=apiMeasureObj.fkMeasuresParent; this.childMeasures=[]; // Is filled during MeasureStructure.transformMeasureStructure(..) this.name=null; if ('name' in apiMeasureObj && apiMeasureObj.name!==null) this.name=String(apiMeasureObj.name); this.description=null; if ('description' in apiMeasureObj && apiMeasureObj.description!==null) this.description=String(apiMeasureObj.description); this.private_only=null; if ('private_only' in apiMeasureObj && apiMeasureObj.private_only!==null) this.private_only=apiMeasureObj.private_only; this.approved=null; if ('approved' in apiMeasureObj && apiMeasureObj.approved!==null) this.approved=apiMeasureObj.approved; this.budget=null; if ('budget' in apiMeasureObj && apiMeasureObj.budget!==null) this.budget=apiMeasureObj.budget; this.responsibleUserObj=null; if ('userResponsible' in apiMeasureObj && apiMeasureObj.userResponsible!==null) this.responsibleUserObj=User.createUserObjByApiData(apiMeasureObj.userResponsible); this.creatorUserObj=null; if ('userCreator' in apiMeasureObj && apiMeasureObj.userCreator!==null) this.creatorUserObj=User.createUserObjByApiData(apiMeasureObj.userCreator); this.lastEditorUserObj=null; if ('userLastEditor' in apiMeasureObj && apiMeasureObj.userLastEditor!==null) this.lastEditorUserObj=User.createUserObjByApiData(apiMeasureObj.userLastEditor); this.milestonesObjAry=[]; if ('measureMilestones' in apiMeasureObj && apiMeasureObj.measureMilestones!==null && Array.isArray(apiMeasureObj.measureMilestones)) { for (let m of apiMeasureObj.measureMilestones) { this.milestonesObjAry.push(new MeasureMilestoneCSRD(m)); } } this.elementOuCombiValuesObjAry=[]; if ('measureValues' in apiMeasureObj && apiMeasureObj.measureValues!==null && Array.isArray(apiMeasureObj.measureValues)) { for (let v of apiMeasureObj.measureValues) { this.elementOuCombiValuesObjAry.push(new MeasureElementOuCombiValueCSRD(v, this)); } } // measureFiles this.files=[]; if (apiMeasureObj.measureFiles!==undefined && apiMeasureObj.measureFiles!==null && Array.isArray(apiMeasureObj.measureFiles)) { for (let idx=0; idx0) { Helper.showToastr('Fehler', 'Eine Kind-Maßnahme darf keine aktiven Wirkungen auf Messwerte besitzen.', 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASURE', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Inconsistency: Child measure to be saved with >0 elementOuCombiValues' }); return; } else if (this.isChild() && this.isParentAlsoForIndirectInactiveChilds()) { Helper.showToastr('Fehler', 'Maßnahme darf nicht gleichzeitig Elter und Kind sein.', 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASURE', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Inconsistency: Measure is both child and parent' }); return; } //var apiUrl=apiHost+'/measures/new?username='+userObj.email+'&pwdsaltedmd5='+userObj.pwdSaltedMd5; var apiUrl=apiHost+'/csrd/measures/new'; // !the keys have to equal the Java class fields! var postData={}; postData['measureStructure']={ pk_csrd_measures_structure: this.parentMeasureStructureObj.id, fk_accounts: this.parentMeasureStructureObj.fkAccounts }; postData['userResponsible']={ pk_users: this.responsibleUserObj.id }; postData['name']=this.name; postData['description']=this.description; postData['private_only']=this.private_only; postData['approved']=this.approved; postData['budget']=this.budget; postData['fkMeasuresParent']=this.fkMeasureParent; // userCreator is added in backend // userLastEditor is added in backend //postData['measureMilestones']=this.milestonesObjAry; postData['measureMilestones']=[]; for (let ms of this.milestonesObjAry) { postData['measureMilestones'].push({ name: ms.name , timestamp_deadline: ms.timestampDeadline , status_bol: ms.status , timestamp_deactivated: ms.timestamp_deactivated }); } //postData['measureValues']=this.elementOuCombiValuesObjAry; postData['measureValues']=[]; for (let eocv of this.elementOuCombiValuesObjAry) { postData['measureValues'].push({ elementOeCombi: { pk_csrd_elements_organizational_units: eocv.elementOuCombiObj.id } , baselineMet1: eocv.baselineMet1 , baselineMet2: eocv.baselineMet2 , baselineMet3: eocv.baselineMet3 //, baselineBin: eocv.baselineBin //, baselineCat: eocv.baselineCat , targetMet1: eocv.targetMet1 , targetMet2: eocv.targetMet2 , targetMet3: eocv.targetMet3 //, targetBin: eocv.targetBin //, targetCat: eocv.targetCat , timestamp_effect_from: eocv.timestampEffectStart , timestamp_effect_to: eocv.timestampEffectEnd , timestamp_deactivated: eocv.timestamp_deactivated }); } ////console.log(postData); let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if ('pk_csrd_measures' in data && data.pk_csrd_measures!==null && data.pk_csrd_measures!==undefined && data.pk_csrd_measures!='') { Helper.showToastr('Erfolg', 'Neue Maßnahme wurde gespeichert.', 'success'); //console.log(data); let measure=new MeasureCSRD(data); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(measure); } else { Logger.log('FRONTEND_CLIENT_API_NEW_CSRD_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); Helper.showToastr('Fehler', 'Fehler beim Speichern der Maßnahme: '+data.msg, 'error'); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_NEW_CSRD_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } save(callbackSuccess) { if (this.name!==null && String(this.name).trim()=='') { Helper.showToastr('Fehler', 'Name darf nicht leer sein.', 'error'); return; } if (this.responsibleUserObj!==null && this.responsibleUserObj.id===null) { Helper.showToastr('Fehler', 'Verantwortlicher User darf nicht leer sein.', 'error'); return; } if (this.parentMeasureStructureObj!==null && this.parentMeasureStructureObj.id===null) { Helper.showToastr('Fehler', 'Maßnahmen-Struktur darf nicht leer sein.', 'error'); return; } if (this.isChild() && this.getNrActiveCombis()>0) { Helper.showToastr('Fehler', 'Eine Kind-Maßnahme darf keine aktiven Wirkungen auf Messwerte besitzen.', 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Inconsistency: Child measure to be saved with >0 elementOuCombiValues' }); return; } else if (this.isChild() && this.isParentAlsoForIndirectInactiveChilds()) { Helper.showToastr('Fehler', 'Maßnahmen kann nicht gleichzeitig Elter und Kind sein.', 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Inconsistency: Measure is both child and parent' }); return; } // ### Check data consistency & assemble POST data obj var postData={}; if (this.name!==undefined && this.name!==null) postData['name']=this.name; if (this.description!==undefined && this.description!==null) postData['description']=this.description; if (this.private_only!==undefined && this.private_only!==null) postData['private_only']=this.private_only; if (this.approved!==undefined && this.approved!==null) postData['approved']=this.approved; if (this.budget!==undefined && this.budget!==null) postData['budget']=this.budget; if (this.fkMeasureParent!==undefined && this.fkMeasureParent!==null) postData['fkMeasuresParent']=this.fkMeasureParent; if (this.responsibleUserObj!==undefined && this.responsibleUserObj!==null) postData['userResponsible']=this.responsibleUserObj.id; if (this.parentMeasureStructureObj!=undefined && this.parentMeasureStructureObj!==null) postData['measureStructure']=this.parentMeasureStructureObj.id; if (this.milestonesObjAry!==null && this.milestonesObjAry.length>0) { postData['measureMilestones']=this.milestonesObjAry; } if (this.elementOuCombiValuesObjAry!==null && this.elementOuCombiValuesObjAry.length>0) { postData['measureValues']=[]; for (let eocv of this.elementOuCombiValuesObjAry) { postData['measureValues'].push(eocv.getObjOfThisWithoutMeasureObj()); } } // ### Call API var apiUrl=apiHost+'/csrd/measures/edit/'+this.id; //console.log(apiUrl, postData); let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivate(callbackSuccess, addPostData=null) { var apiUrl=apiHost+'/csrd/measures/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 if (addPostData!==null && 'addCommand' in addPostData) postData['addCommand']=addPostData.addCommand; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahme wurde erfolgreich deaktiviert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahme wurde nicht deaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivateInclChilds(callbackSuccess) { this.deactivate(callbackSuccess, { addCommand: 'deactivateInclChilds' }); } deactivateAndTransformChilds(callbackSuccess) { this.deactivate(callbackSuccess, { addCommand: 'deactivateAndTransformChilds' }); } reactivate(callbackSuccess) { // Not used var apiUrl=apiHost+'/csrd/measures/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_deactivated']=null; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahme wurde erfolgreich reaktiviert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahme wurde nicht reaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } archive(callbackSuccess) { var apiUrl=apiHost+'/csrd/measures/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_archived']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahme wurde erfolgreich archiviert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahme wurde nicht archiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } unarchive(callbackSuccess) { var apiUrl=apiHost+'/csrd/measures/edit/'+this.id; // !the keys have to equal the Java class fields! var postData={}; postData['timestamp_archived']=null; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Maßnahme wurde erfolgreich reaktiviert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Maßnahme wurde nicht reaktiviert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_MEASURE', apiUrl, xhr, status, error, null, { json: jsonData }); }); } // An archived measure can be active! static isActive(measureObj) { let active=true; let inactiveReason=null; let inactiveStr=''; let parentActiveObjAry=[]; /* MEASURE IS NOT INACTIVE WHEN ALL MeasureElementOuCombiValues ARE INACTIVE, AS MEASURE CAN ALSO EXIST WITHOUT ANY MeasureElementOuCombiValue // MeasureElementOuCombiValues let counterActives=0; let activeTmp=true; let inactiveReasonTmp=null; let inactiveStrTmp=''; for (let eocv of measureObj.elementOuCombiValuesObjAry) { let activeObj=MeasureElementOuCombiValue.isActive(eocv); if (!activeObj.active) { activeTmp=activeObj.active; inactiveReasonTmp=activeObj.inactiveReason; inactiveStrTmp=activeObj.inactiveStr; } else counterActives++; parentActiveObjAry.push(activeObj); } if (counterActives==0 && measureObj.elementOuCombiValuesObjAry.length>0) { // >0 combis exist, but all are inactive (=0 are active) active=activeTmp; inactiveReason=inactiveReasonTmp; inactiveStr=inactiveStrTmp; } */ // Measure Structure let activeObj=MeasureStructureCSRD.isActive(measureObj.parentMeasureStructureObj); if (!activeObj.active) { active=activeObj.active; inactiveReason=activeObj.inactiveReason; inactiveStr=activeObj.inactiveStr; } parentActiveObjAry.push(activeObj); // Measure itself if (measureObj.timestampDeactivated!==null) { active=false; inactiveReason='measure'; inactiveStr=Helper.timestampFormat(measureObj.timestampDeactivated, false, false); } return { active: active, inactiveReason: inactiveReason, inactiveStr: inactiveStr, parentActiveObjAry: parentActiveObjAry}; } static checkIfElementOUObjIsAlreadyLinkedToAtLeast1Measure(elementOeCombiObj) { let structureMeasuresAsMapByNodeId=ElementOeSelectorCSRD.getStructureAsMapByNodeId(csrdStructureMeasures); let returnObj={ active: null, tooltip: 'Dieser Messwert wurde bereits einer Maßnahme zugeordnet.', prefixHtml: '' }; /* !!! All logic in the next loop is also implemented in Java in backend! In case of changes, also change in backend !!! */ for (let msKey in structureMeasuresAsMapByNodeId) { // For each measure structure for (let m of structureMeasuresAsMapByNodeId[msKey].measuresObjAry) { // For each Measure ... // Check if measure active //if (m.timestampDeactivated===null) { // SHOULDN'T Measure.isActive() BE USED? if (Measure.isActive(m).active) { for (let eocv of m.elementOuCombiValuesObjAry) { // For each MeasureValue ... // Check if measure value active if (MeasureElementOuCombiValueCSRD.isActive(eocv).active) { // Check if elementOuCombi active if (eocv.elementOuCombiObj!==undefined && eocv.elementOuCombiObj!==null && ElementOuCombiCSRD.isActive(eocv.elementOuCombiObj).active) { if (eocv.elementOuCombiObj.id==elementOeCombiObj.id) { returnObj.active=false; return returnObj; } } } } } } } returnObj.active=true; return returnObj; } static getMeasureById(id) { let structureMeasuresAsMapByNodeId=ElementOeSelectorCSRD.getStructureAsMapByNodeId(csrdStructureMeasures); for (let msKey in structureMeasuresAsMapByNodeId) { let ms=structureMeasuresAsMapByNodeId[msKey]; for (let m of ms.measuresObjAry) { if (m.id==id) { return m; } } } return null; } checkIfElementOUObjIsAlreadyLinkedToThisMeasure(elementOeCombiObj) { let returnObj={ active: null, tooltip: 'Dieser Messwert wurde bereits dieser Maßnahme zugeordnet.', prefixHtml: '' }; for (let eocv of this.elementOuCombiValuesObjAry) { // For each MeasureValue ... // Check if measure value active if (eocv.timestamp_deactivated===null) { if (eocv.elementOuCombiObj.id==elementOeCombiObj.id) { returnObj.active=false; return returnObj; } } } returnObj.active=true; return returnObj; } loadMeasureObjIntoThis(measureObj) { //measureObj && Object.assign(this, measureObj); if (measureObj.parentMeasureStructureObj!==undefined && measureObj.parentMeasureStructureObj!==null) this.parentMeasureStructureObj=measureObj.parentMeasureStructureObj; if (measureObj.id!==undefined && measureObj.id!==null) this.id=measureObj.id; //apiMeasureObj.pk_measures=measureObj.id; if (measureObj.name!==undefined && measureObj.name!==null) this.name=measureObj.name; //apiMeasureObj.pk_measures=measureObj.name; if (measureObj.fkMeasureParent!==undefined && measureObj.fkMeasureParent!==null) this.fkMeasureParent=measureObj.fkMeasureParent; if (measureObj.description!==undefined && measureObj.description!==null) this.description=measureObj.description; if (measureObj.private_only!==undefined && measureObj.private_only!==null) this.private_only=measureObj.private_only; if (measureObj.approved!==undefined && measureObj.approved!==null) this.approved=measureObj.approved; if (measureObj.budget!==undefined && measureObj.budget!==null) this.budget=measureObj.budget; if (measureObj.timestampDeactivated!==undefined && measureObj.timestampDeactivated!==null) this.timestampDeactivated=measureObj.timestampDeactivated; //apiMeasureObj.timestamp_deactivated=measureObj.timestampDeactivated; this.milestonesObjAry=[]; for (let mm of measureObj.milestonesObjAry) { let newMeasureMilestoneObj=new MeasureMilestoneCSRD(); newMeasureMilestoneObj.loadMeasureMilestoneObjIntoThis(mm); this.milestonesObjAry.push(newMeasureMilestoneObj); } this.elementOuCombiValuesObjAry=[]; for (let v of measureObj.elementOuCombiValuesObjAry) { let newElementOuCombiValuesObj=new MeasureElementOuCombiValueCSRD(); newElementOuCombiValuesObj.loadMeasureElementOuCombiValueIntoThis(v); this.elementOuCombiValuesObjAry.push(newElementOuCombiValuesObj); } this.childMeasures=[]; for (let v of measureObj.childMeasures) { this.childMeasures.push(v); } // Here, the object can be re-used (instead of creating a new object), because the object's content will not be changed (instead the whole object might be replaced) if (measureObj.responsibleUserObj!==undefined && measureObj.responsibleUserObj!==null) this.responsibleUserObj=measureObj.responsibleUserObj; if (measureObj.creatorUserObj!==undefined && measureObj.creatorUserObj!==null) this.creatorUserObj=measureObj.creatorUserObj; if (measureObj.lastEditorUserObj!==undefined && measureObj.lastEditorUserObj!==null) this.lastEditorUserObj=measureObj.lastEditorUserObj; } getDisplayTitle() { return this.name; } getNrActiveCombis() { // If something changes here, also needs to be reflected in backend Measure.getNrActiveValues() let nrActiveCombis=0; for (let combi of this.elementOuCombiValuesObjAry) { if (MeasureElementOuCombiValueCSRD.isActive(combi).active) nrActiveCombis++; } return nrActiveCombis; } // Jumps to non-archived measures only static showMeasureFromExternal(measureId, archived=false) { externalCallCSRDMeasureId=measureId; if (archived===false) clickOnNav1Item(['nav1_csrd','nav1_csrd_measures_measures']); else clickOnNav1Item(['nav1_csrd','nav1_csrd_measures_archive']); } calculateMilestonesImplementation() { // Return 0 (in plan), 1 (ahead of plan) or -1 (behind plan) let nrMilestonesToBeDone=0; let nrMilestonesToBeDoneAndActuallyDone=0; let nrMilestonesNotToBeDoneButActuallyDone=0; for (let ms of this.milestonesObjAry) { if (MeasureMilestoneCSRD.isActive(ms).active) { //if (Helper.parseTimestampToUnixTimestampInMillis(ms.timestampDeadline).unix() < moment().unix()) { // Deadline is in the past if (Helper.parseTimestampToUnixTimestampInMillis(ms.timestampDeadline) < moment().tz('Europe/Berlin').unix()) { // Deadline is in the past nrMilestonesToBeDone++; if (ms.status===true) { nrMilestonesToBeDoneAndActuallyDone++; } else { /* nothing to do */ } } else { // Deadline is in the future if (ms.status===true) { nrMilestonesNotToBeDoneButActuallyDone++; } else { /* nothing to do */ } } } } if (nrMilestonesToBeDone>0 && nrMilestonesToBeDoneAndActuallyDone / nrMilestonesToBeDone < 1) return -1; // Not all due milestones done else { // All due milestones done if (nrMilestonesNotToBeDoneButActuallyDone > 0) return 1; // Additionally, some future milestones are also done else return 0; // In Plan } } toBeBlurred() { if (this.private_only!==true || userObj.role==3 || userObj.role==2 || userObj.id==this.responsibleUserObj.id) return false; else return true; } isChild() { // If something changes here, also needs to be reflected in backend Measure.isChild() if (this.fkMeasureParent!==undefined && this.fkMeasureParent!==null && this.fkMeasureParent!=='') return true; else return false; } isParent() { // If something changes here, also needs to be reflected in backend ApiService.checkConsistencyObjectMeasure(..) /* A measure is parent if child measures are linked to it. Child measures need to be active (=non deactivated) in order to count. Measures with only deactivated child measures are NOT parent. Child measure CAN be archived in order to count. BUT: A measure which is a child AND archived is not allowed (=invalid state). How to handle measures which are not directly deactivated, but indirectly through MeasureStructure? Currently, measures which are indirectly deactivated also count as deactivated/non-active. */ if (this.getActiveChildMeasures().length>0) return true; else return false; } isParentAlsoForIndirectInactiveChilds() { // If something changes here, also needs to be reflected in backend ApiService.checkConsistencyObjectMeasure(..) // Indirect inactive measures are not inactive themselves. But the measure structure is inactive. if (this.getActiveAndIndirectInactiveChildMeasures().length>0) return true; else return false; } isParentAlsoForIndirectInactiveApprovedChilds() { // If something changes here, also needs to be reflected in backend ApiService.checkConsistencyObjectMeasure(..) // Indirect inactive measures are not inactive themselves. But the measure structure is inactive. if (this.getActiveAndIndirectInactiveApprovedChildMeasures().length>0) return true; else return false; } getActiveChildMeasures() { let ary=[]; for (let cm of this.childMeasures) { if (MeasureCSRD.isActive(cm).active) ary.push(cm); } return ary; } getActiveAndIndirectInactiveChildMeasures() { // Indirect inactive measures are not inactive themselves. But the measure structure is inactive. let ary=[]; for (let cm of this.childMeasures) { if (MeasureCSRD.isActive(cm).active || MeasureCSRD.isActive(cm).inactiveReason!='measure') ary.push(cm); } return ary; } getActiveAndIndirectInactiveApprovedChildMeasures() { // Indirect inactive measures are not inactive themselves. But the measure structure is inactive. let ary=[]; for (let cm of this.childMeasures) { if ((MeasureCSRD.isActive(cm).active || MeasureCSRD.isActive(cm).inactiveReason!='measure') && cm.approved) ary.push(cm); } return ary; } isBudgetEqualToSumOfChildBudgets() { if (this.isParent()) { let sumBudgetChilds=null; for (let cm of this.getActiveChildMeasures()) { if (cm.budget!==null) { if (sumBudgetChilds==null) sumBudgetChilds=cm.budget; else sumBudgetChilds+=cm.budget; } } //console.log('budget', sumBudgetChilds, m.budget); if (sumBudgetChilds!==null && this.budget!==null && sumBudgetChilds!=this.budget) return false; else return true; } else return true; } } class MeasureMilestone { constructor(apiMeasureMilestoneObj={}) { //this.id=apiMeasureMilestoneObj.pk_measures_milestones; this.id=null; if ('pk_measures_milestones' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.pk_measures_milestones!==null) this.id=apiMeasureMilestoneObj.pk_measures_milestones; this.name=null; if ('name' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.name!==null) this.name=apiMeasureMilestoneObj.name; this.timestampDeadline=null; if ('timestamp_deadline' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.timestamp_deadline!==null) this.timestampDeadline=apiMeasureMilestoneObj.timestamp_deadline; this.status=null; if ('status_bol' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.status_bol!==null) this.status=apiMeasureMilestoneObj.status_bol; this.creatorUserObj=null; if ('userCreator' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.userCreator!==null) this.creatorUserObj=User.createUserObjByApiData(apiMeasureMilestoneObj.userCreator); this.lastEditorUserObj=null; if ('userLastEditor' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.userLastEditor!==null) this.lastEditorUserObj=User.createUserObjByApiData(apiMeasureMilestoneObj.userLastEditor); //this.timestamp_deactivated=apiMeasureMilestoneObj.timestamp_deactivated; this.timestamp_deactivated=null; if ('timestamp_deactivated' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.timestamp_deactivated!==null) this.timestamp_deactivated=apiMeasureMilestoneObj.timestamp_deactivated; } static isActive(measureMilestoneObj) { let active=true; let inactiveReason=null; let inactiveStr=null; let parentActiveObjAry=[]; // MeasureMilestone itself if (measureMilestoneObj.timestamp_deactivated!==null) { active=false; inactiveReason='measureMilestone'; inactiveStr=Helper.timestampFormat(measureMilestoneObj.timestamp_deactivated, false, false); } return { active: active, inactiveReason: inactiveReason, inactiveStr: inactiveStr, parentActiveObjAry: parentActiveObjAry}; } loadMeasureMilestoneObjIntoThis(measureMilestoneObj) { if (measureMilestoneObj.id!==undefined && measureMilestoneObj.id!==null) this.id=measureMilestoneObj.id; if (measureMilestoneObj.name!==undefined && measureMilestoneObj.name!==null) this.name=measureMilestoneObj.name; if (measureMilestoneObj.timestampDeadline!==undefined && measureMilestoneObj.timestampDeadline!==null) this.timestampDeadline=measureMilestoneObj.timestampDeadline; if (measureMilestoneObj.status!==undefined && measureMilestoneObj.status!==null) this.status=measureMilestoneObj.status; if (measureMilestoneObj.timestamp_deactivated!==undefined && measureMilestoneObj.timestamp_deactivated!==null) this.timestamp_deactivated=measureMilestoneObj.timestamp_deactivated; // Here, the object can be re-used (instead of creating a new object), because the object's content will not be changed (instead the whole object might be replaced) this.creatorUserObj=measureMilestoneObj.creatorUserObj; this.lastEditorUserObj=measureMilestoneObj.lastEditorUserObj; } } class MeasureMilestoneCSRD { constructor(apiMeasureMilestoneObj={}) { //this.id=apiMeasureMilestoneObj.pk_measures_milestones; this.id=null; if ('pk_csrd_measures_milestones' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.pk_csrd_measures_milestones!==null) this.id=apiMeasureMilestoneObj.pk_csrd_measures_milestones; this.name=null; if ('name' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.name!==null) this.name=apiMeasureMilestoneObj.name; this.timestampDeadline=null; if ('timestamp_deadline' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.timestamp_deadline!==null) this.timestampDeadline=apiMeasureMilestoneObj.timestamp_deadline; this.status=null; if ('status_bol' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.status_bol!==null) this.status=apiMeasureMilestoneObj.status_bol; this.creatorUserObj=null; if ('userCreator' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.userCreator!==null) this.creatorUserObj=User.createUserObjByApiData(apiMeasureMilestoneObj.userCreator); this.lastEditorUserObj=null; if ('userLastEditor' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.userLastEditor!==null) this.lastEditorUserObj=User.createUserObjByApiData(apiMeasureMilestoneObj.userLastEditor); //this.timestamp_deactivated=apiMeasureMilestoneObj.timestamp_deactivated; this.timestamp_deactivated=null; if ('timestamp_deactivated' in apiMeasureMilestoneObj && apiMeasureMilestoneObj.timestamp_deactivated!==null) this.timestamp_deactivated=apiMeasureMilestoneObj.timestamp_deactivated; } static isActive(measureMilestoneObj) { let active=true; let inactiveReason=null; let inactiveStr=null; let parentActiveObjAry=[]; // MeasureMilestone itself if (measureMilestoneObj.timestamp_deactivated!==null) { active=false; inactiveReason='measureMilestone'; inactiveStr=Helper.timestampFormat(measureMilestoneObj.timestamp_deactivated, false, false); } return { active: active, inactiveReason: inactiveReason, inactiveStr: inactiveStr, parentActiveObjAry: parentActiveObjAry}; } loadMeasureMilestoneObjIntoThis(measureMilestoneObj) { if (measureMilestoneObj.id!==undefined && measureMilestoneObj.id!==null) this.id=measureMilestoneObj.id; if (measureMilestoneObj.name!==undefined && measureMilestoneObj.name!==null) this.name=measureMilestoneObj.name; if (measureMilestoneObj.timestampDeadline!==undefined && measureMilestoneObj.timestampDeadline!==null) this.timestampDeadline=measureMilestoneObj.timestampDeadline; if (measureMilestoneObj.status!==undefined && measureMilestoneObj.status!==null) this.status=measureMilestoneObj.status; if (measureMilestoneObj.timestamp_deactivated!==undefined && measureMilestoneObj.timestamp_deactivated!==null) this.timestamp_deactivated=measureMilestoneObj.timestamp_deactivated; // Here, the object can be re-used (instead of creating a new object), because the object's content will not be changed (instead the whole object might be replaced) this.creatorUserObj=measureMilestoneObj.creatorUserObj; this.lastEditorUserObj=measureMilestoneObj.lastEditorUserObj; } } class MeasureElementOuCombiValue { constructor(apiMeasureElementOuCombiValueObj={}, measureObj=null) { //this.id=apiMeasureElementOuCombiValueObj.pk_measures_values; this.id=null; if ('pk_measures_values' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.pk_measures_values!==null) this.id=apiMeasureElementOuCombiValueObj.pk_measures_values; this.elementOuCombiObj=null; if ('elementOeCombi' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.elementOeCombi!==null) this.elementOuCombiObj=new ElementOuCombi(apiMeasureElementOuCombiValueObj.elementOeCombi); this.baselineMet=null; if ('baselineMet' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.baselineMet!==null) this.baselineMet=apiMeasureElementOuCombiValueObj.baselineMet; this.baselineBin=null; if ('baselineBin' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.baselineBin!==null) this.baselineBin=apiMeasureElementOuCombiValueObj.baselineBin; this.baselineCat=null; if ('baselineCat' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.baselineCat!==null) this.baselineCat=apiMeasureElementOuCombiValueObj.baselineCat; this.targetMet=null; if ('targetMet' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.targetMet!==null) this.targetMet=apiMeasureElementOuCombiValueObj.targetMet; this.targetBin=null; if ('targetBin' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.targetBin!==null) this.targetBin=apiMeasureElementOuCombiValueObj.targetBin; this.targetCat=null; if ('targetCat' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.targetCat!==null) this.targetCat=apiMeasureElementOuCombiValueObj.targetCat; this.timestampEffectStart=null; if ('timestamp_effect_from' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.timestamp_effect_from!==null) this.timestampEffectStart=apiMeasureElementOuCombiValueObj.timestamp_effect_from; this.timestampEffectEnd=null; if ('timestamp_effect_to' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.timestamp_effect_to!==null) this.timestampEffectEnd=apiMeasureElementOuCombiValueObj.timestamp_effect_to; //this.timestamp_deactivated=apiMeasureElementOuCombiValueObj.timestamp_deactivated; this.timestamp_deactivated=null; if ('timestamp_deactivated' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.timestamp_deactivated!==null) this.timestamp_deactivated=apiMeasureElementOuCombiValueObj.timestamp_deactivated; if (measureObj!==null) this.measureObj=measureObj; } getObjOfThisWithoutMeasureObj() { let obj={}; if (this.id!==null) obj.id=this.id; if (this.elementOuCombiObj!==null) obj.elementOuCombiObj=this.elementOuCombiObj; if (this.baselineMet!==null) obj.baselineMet=this.baselineMet; if (this.baselineBin!==null) obj.baselineBin=this.baselineBin; if (this.baselineCat!==null) obj.baselineCat=this.baselineCat; if (this.targetMet!==null) obj.targetMet=this.targetMet; if (this.targetBin!==null) obj.targetBin=this.targetBin; if (this.targetCat!==null) obj.targetCat=this.targetCat; if (this.timestampEffectStart!==null) obj.timestampEffectStart=this.timestampEffectStart; if (this.timestampEffectEnd!==null) obj.timestampEffectEnd=this.timestampEffectEnd; if (this.timestamp_deactivated!==null) obj.timestamp_deactivated=this.timestamp_deactivated; return obj; } static isActive(measureElementOuCombiValueObj) { let active=true; let inactiveReason=null; let inactiveStr=''; let parentActiveObjAry=[]; // ElementOuCombiValues let activeObj=ElementOuCombi.isActive(measureElementOuCombiValueObj.elementOuCombiObj); if (!activeObj.active) { active=activeObj.active; inactiveReason=activeObj.inactiveReason; inactiveStr=activeObj.deactivatedStr; } parentActiveObjAry.push(activeObj); // MeasureElementOuCombiValue itself if (measureElementOuCombiValueObj.timestamp_deactivated!==null) { active=false; inactiveReason='measureElementOuCombiValueObj'; inactiveStr=Helper.timestampFormat(measureElementOuCombiValueObj.timestamp_deactivated, false, false); } return { active: active, inactiveReason: inactiveReason, inactiveStr: inactiveStr, parentActiveObjAry: parentActiveObjAry}; } getDisplayTitle() { //////console.log(this.measureObj, this.elementOuCombiObj); if (this.measureObj!==null) return this.measureObj.getDisplayTitle()+' / '+this.elementOuCombiObj.getDisplayTitle(); else return 'n/a'; } /* Returns effect performance. Can also return NULL if no measurements exist yet. Can also return string 'measure_effect_timerange_not_yet_started' if effect time range has not yet started. */ calculateEffectPerformance() { //let target=null; //let baseline=null; let measurementValueLatestMet=null; let measurementValueLatestBin=null; let measurementValueLatestCat=null; // All timestamps in unix timestamp format in sec //let timestampEffectFrom=Helper.parseTimestampToUnixTimestampInMillis(this.timestampEffectStart).unix(); let timestampEffectFrom=Helper.parseTimestampToUnixTimestampInMillis(this.timestampEffectStart); //let timestampEffectTo=Helper.parseTimestampToUnixTimestampInMillis(this.timestampEffectEnd).unix(); let timestampEffectTo=Helper.parseTimestampToUnixTimestampInMillis(this.timestampEffectEnd); let timestampNow=moment().tz('Europe/Berlin').unix(); let effectDeviation=null; let measurementAsIs=null; let measurementToBe=null; let timeProgressPercent=null; // Check if (moment().tz('Europe/Berlin').unix() < timestampEffectFrom) { // Effect time range of measure has not yet started, i.e. do not include in performance analysis return 'measure_effect_timerange_not_yet_started'; } // Get latest measurement of ElementOuCombi let tsMax=null; for (let measurementObj of this.elementOuCombiObj.measurementsObjAry) { if (measurementObj.timestampDeactivated===null && measurementObj.getApprovalStatus().approved===true) { // not deleted and approved if (tsMax===null || tsMax < (measurementObj.timestampPointUnixInSec!==null ? measurementObj.timestampPointUnixInSec : measurementObj.timestampRangeToUnixInSec)) { tsMax=(measurementObj.timestampPointUnixInSec!==null ? measurementObj.timestampPointUnixInSec : measurementObj.timestampRangeToUnixInSec); measurementValueLatestMet=measurementObj.valueMet; measurementValueLatestBin=measurementObj.valueBin; measurementValueLatestCat=measurementObj.valueCat; //////console.log('Calc effect performance - latest measurement', measurementValueLatestMet, measurementValueLatestBin, measurementValueLatestCat, measurementObj, this); } } } // Check if (measurementValueLatestMet==null && measurementValueLatestBin==null && measurementValueLatestCat==null) { // No measurements exist yet return null; } // Calculate effect performance (= effect deviation) (+1 day as timestampEffectTo is inclusive; Example: 3 until 7 = 4, but has to be 5 (i.e. +1 day)) //timeProgressPercent = ((Math.min(Math.max(timestampNow, timestampEffectFrom), timestampEffectTo) - timestampEffectFrom) / (timestampEffectTo - timestampEffectFrom)); let dayInSec=24*60*60; timeProgressPercent = ((Math.min(Math.max(timestampNow, timestampEffectFrom), timestampEffectTo + dayInSec) - timestampEffectFrom) / (timestampEffectTo + dayInSec - timestampEffectFrom)); if (this.targetMet!==null) { // metric //target=this.targetMet; //baseline=this.baselineMet; if (this.targetMet==this.baselineMet) { Logger.log('FRONTEND_CLIENT_CONSISTENCECHECK', 'ERROR_SYSTEM', { msg: 'baseline equals target', target: this.targetMet, baseline: this.baselineMet }); return 'target_equals_baseline'; // Should not happen (would be an error) and the taken care of in frontend and backend } else { // standard case let valueRangeEffect = Number(this.targetMet) - Number(this.baselineMet); measurementAsIs = measurementValueLatestMet - Number(this.baselineMet); measurementToBe = timeProgressPercent * valueRangeEffect; effectDeviation = (measurementAsIs - measurementToBe) / valueRangeEffect; } } else if (this.targetBin!==null) { // binary //target=this.targetBin; //baseline=this.baselineBin; measurementAsIs = measurementValueLatestBin; measurementToBe = this.targetBin; // ALT 1 /* if (measurementAsIs==measurementToBe) effectDeviation = 1*(1-timeProgressPercent); else effectDeviation = -1*timeProgressPercent; */ // ALT 2 (advantage: effectDeviation does not change over time) if (timeProgressPercent>=1) { if (measurementAsIs==measurementToBe) effectDeviation = 0; else effectDeviation = -1; } else { effectDeviation = 0; } // ALT 3 /* if (timeProgressPercent>0.5) { measurementToBe = target; } else { measurementToBe = baseline; } if (measurementAsIs==measurementToBe) effectDeviation = 0; else effectDeviation = -1*; */ } else if (this.targetCat!==null) { // categoric //target=this.targetCat; //baseline=this.baselineCat; measurementAsIs = measurementValueLatestCat; measurementToBe = this.targetCat; // ALT 2 (advantage: effectDeviation does not change over time) if (timeProgressPercent>=1) { if (measurementAsIs==measurementToBe) effectDeviation = 0; else effectDeviation = -1; } else { effectDeviation = 0; } } ////console.log('Calc effect performance', 'target', target, 'baseline', baseline, 'measurementAsIs', measurementAsIs, 'measurementToBe', measurementToBe, 'effectDeviation', effectDeviation, 'timeProgressPercent', timeProgressPercent, this); /* if (effectDeviation > 0.05) return 1; else if (effectDeviation < -0.05) return -1; else return 0; */ return effectDeviation; } /* Returns filling grade. Can also return NULL if no measurements exist yet. Can also return string 'measure_effect_timerange_not_yet_started' if effect time range has not yet started. */ calculateFillingGrade() { // Calculate filling grade function calcFillingGradeByMeasurementType(measureElementOuCombiValueObj, measurementValueLatestMet, measurementValueLatestBin, measurementValueLatestCat) { let target=null; let baseline=null; let fillingGrade=null; if (measureElementOuCombiValueObj.targetMet!==null) { // metric target=measureElementOuCombiValueObj.targetMet; baseline=measureElementOuCombiValueObj.baselineMet; if (target==baseline) { Logger.log('FRONTEND_CLIENT_CONSISTENCECHECK', 'ERROR_SYSTEM', { msg: 'baseline equals target', target: target, baseline: baseline }); return 'target_equals_baseline'; // Should not happen (would be an error) and the taken care of in frontend and backend } else { // standard case fillingGrade=(measurementValueLatestMet-baseline)/(target-baseline); } } else if (measureElementOuCombiValueObj.targetBin!==null) { // binary target=measureElementOuCombiValueObj.targetBin; baseline=measureElementOuCombiValueObj.baselineBin; if (target===true && measurementValueLatestBin===true) fillingGrade=1; else if (target===false && measurementValueLatestBin===false) fillingGrade=1; else fillingGrade=0; } else if (measureElementOuCombiValueObj.targetCat!==null) { // categoric target=measureElementOuCombiValueObj.targetCat; baseline=measureElementOuCombiValueObj.baselineCat; if (target==measurementValueLatestCat) fillingGrade=1; //else if (target==measurementValueLatestCat) fillingGrade=1; else fillingGrade=0; } return fillingGrade; } let measurementValueLatestMet=null; let measurementValueLatestBin=null; let measurementValueLatestCat=null; // All timestamps in unix timestamp format in sec //let timestampEffectFrom=Helper.parseTimestampToUnixTimestampInMillis(this.timestampEffectStart).unix(); let timestampEffectFrom=Helper.parseTimestampToUnixTimestampInMillis(this.timestampEffectStart); let timestampNow=moment().tz('Europe/Berlin').unix(); let historicFillingGrades=[]; // Check if (moment().tz('Europe/Berlin').unix() < timestampEffectFrom) { // Effect time range of measure has not yet started, i.e. do not include in performance analysis return 'measure_effect_timerange_not_yet_started'; } // Get latest measurement of ElementOuCombi & calculate historic filling grade steps let tsMax=null; let ts=null; for (let measurementObj of this.elementOuCombiObj.measurementsObjAry) { if (measurementObj.timestampDeactivated===null && measurementObj.getApprovalStatus().approved===true) { // not deleted and approved if (measurementObj.getApprovalStatus().approved) { // only approved measurements are considered ts=(measurementObj.timestampPointUnixInSec!==null ? measurementObj.timestampPointUnixInSec : measurementObj.timestampRangeToUnixInSec); // Latest timestamp if (tsMax===null || tsMax < ts) { tsMax=ts; measurementValueLatestMet=measurementObj.valueMet; measurementValueLatestBin=measurementObj.valueBin; measurementValueLatestCat=measurementObj.valueCat; } // Calc historic filling grades if (ts < timestampNow) { historicFillingGrades.push({timestampUnixInSec: ts, fillingGrade: calcFillingGradeByMeasurementType(this, measurementObj.valueMet, measurementObj.valueBin, measurementObj.valueCat)}); } } } } // Check if (measurementValueLatestMet==null && measurementValueLatestBin==null && measurementValueLatestCat==null) { // No measurements exist yet return null; } // Calc last filling grade let fillingGrade=calcFillingGradeByMeasurementType(this, measurementValueLatestMet, measurementValueLatestBin, measurementValueLatestCat); ////console.log('historicFillingGrades', historicFillingGrades); return { fillingGrade: fillingGrade, historicFillingGrades: historicFillingGrades, measurementValueLatestMet: measurementValueLatestMet, measurementValueLatestCat: measurementValueLatestCat, measurementValueLatestBin: measurementValueLatestBin }; } loadMeasureElementOuCombiValueIntoThis(meocvObj) { if (meocvObj.id!==undefined && meocvObj.id!==null) this.id=meocvObj.id; if (meocvObj.baselineMet!==undefined && meocvObj.baselineMet!==null) this.baselineMet=meocvObj.baselineMet; if (meocvObj.baselineBin!==undefined && meocvObj.baselineBin!==null) this.baselineBin=meocvObj.baselineBin; if (meocvObj.baselineCat!==undefined && meocvObj.baselineCat!==null) this.baselineCat=meocvObj.baselineCat; if (meocvObj.targetMet!==undefined && meocvObj.targetMet!==null) this.targetMet=meocvObj.targetMet; if (meocvObj.targetBin!==undefined && meocvObj.targetBin!==null) this.targetBin=meocvObj.targetBin; if (meocvObj.targetCat!==undefined && meocvObj.targetCat!==null) this.targetCat=meocvObj.targetCat; if (meocvObj.timestampEffectStart!==undefined && meocvObj.timestampEffectStart!==null) this.timestampEffectStart=meocvObj.timestampEffectStart; if (meocvObj.timestampEffectEnd!==undefined && meocvObj.timestampEffectEnd!==null) this.timestampEffectEnd=meocvObj.timestampEffectEnd; if (meocvObj.timestamp_deactivated!==undefined && meocvObj.timestamp_deactivated!==null) this.timestamp_deactivated=meocvObj.timestamp_deactivated; // Here, the object can be re-used (instead of creating a new object), because the object's content will not be changed (instead the whole object might be replaced) this.elementOuCombiObj=meocvObj.elementOuCombiObj; this.measureObj=meocvObj.measureObj; } } class MeasureElementOuCombiValueCSRD { constructor(apiMeasureElementOuCombiValueObj={}, measureObj=null) { this.id=null; if ('pk_csrd_measures_values' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.pk_csrd_measures_values!==null) this.id=apiMeasureElementOuCombiValueObj.pk_csrd_measures_values; this.elementOuCombiObj=null; if ('elementOeCombi' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.elementOeCombi!==null) this.elementOuCombiObj=new ElementOuCombiCSRD(apiMeasureElementOuCombiValueObj.elementOeCombi); this.baselineMet1=null; if ('baselineMet1' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.baselineMet1!==null) this.baselineMet1=apiMeasureElementOuCombiValueObj.baselineMet1; this.baselineMet2=null; if ('baselineMet2' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.baselineMet2!==null) this.baselineMet2=apiMeasureElementOuCombiValueObj.baselineMet2; this.baselineMet3=null; if ('baselineMet3' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.baselineMet3!==null) this.baselineMet3=apiMeasureElementOuCombiValueObj.baselineMet3; this.targetMet1=null; if ('targetMet1' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.targetMet1!==null) this.targetMet1=apiMeasureElementOuCombiValueObj.targetMet1; this.targetMet2=null; if ('targetMet2' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.targetMet2!==null) this.targetMet2=apiMeasureElementOuCombiValueObj.targetMet2; this.targetMet3=null; if ('targetMet3' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.targetMet3!==null) this.targetMet3=apiMeasureElementOuCombiValueObj.targetMet3; this.timestampEffectStart=null; if ('timestamp_effect_from' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.timestamp_effect_from!==null) this.timestampEffectStart=apiMeasureElementOuCombiValueObj.timestamp_effect_from; this.timestampEffectEnd=null; if ('timestamp_effect_to' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.timestamp_effect_to!==null) this.timestampEffectEnd=apiMeasureElementOuCombiValueObj.timestamp_effect_to; this.timestamp_deactivated=null; if ('timestamp_deactivated' in apiMeasureElementOuCombiValueObj && apiMeasureElementOuCombiValueObj.timestamp_deactivated!==null) this.timestamp_deactivated=apiMeasureElementOuCombiValueObj.timestamp_deactivated; if (measureObj!==null) this.measureObj=measureObj; } getObjOfThisWithoutMeasureObj() { let obj={}; if (this.id!==null) obj.id=this.id; if (this.elementOuCombiObj!==null) obj.elementOuCombiObj=this.elementOuCombiObj; if (this.baselineMet1!==null) obj.baselineMet1=this.baselineMet1; if (this.baselineMet2!==null) obj.baselineMet2=this.baselineMet2; if (this.baselineMet3!==null) obj.baselineMet3=this.baselineMet3; if (this.targetMet1!==null) obj.targetMet1=this.targetMet1; if (this.targetMet2!==null) obj.targetMet2=this.targetMet2; if (this.targetMet3!==null) obj.targetMet3=this.targetMet3; if (this.timestampEffectStart!==null) obj.timestampEffectStart=this.timestampEffectStart; if (this.timestampEffectEnd!==null) obj.timestampEffectEnd=this.timestampEffectEnd; if (this.timestamp_deactivated!==null) obj.timestamp_deactivated=this.timestamp_deactivated; return obj; } static isActive(measureElementOuCombiValueObj) { let active=true; let inactiveReason=null; let inactiveStr=''; let parentActiveObjAry=[]; // ElementOuCombiValues let activeObj=ElementOuCombiCSRD.isActive(measureElementOuCombiValueObj.elementOuCombiObj); if (!activeObj.active) { active=activeObj.active; inactiveReason=activeObj.inactiveReason; inactiveStr=activeObj.deactivatedStr; } parentActiveObjAry.push(activeObj); // MeasureElementOuCombiValue itself if (measureElementOuCombiValueObj.timestamp_deactivated!==null) { active=false; inactiveReason='measureElementOuCombiValueObj'; inactiveStr=Helper.timestampFormat(measureElementOuCombiValueObj.timestamp_deactivated, false, false); } return { active: active, inactiveReason: inactiveReason, inactiveStr: inactiveStr, parentActiveObjAry: parentActiveObjAry}; } getDisplayTitle() { if (this.measureObj!==null) return this.measureObj.getDisplayTitle()+' / '+this.elementOuCombiObj.getDisplayTitle(); else return 'n/a'; } // This method returns the index 1, 2 or 3 of the Measurement data entry which is used in this relation to a measure getIdxOfUsedQuantMeasurementPoint() { if (this.targetMet1!==null) return 1; else if (this.targetMet2!==null) return 2; else if (this.targetMet3!==null) return 3; else return null; } /* Returns effect performance. Can also return NULL if no measurements exist yet. Can also return string 'measure_effect_timerange_not_yet_started' if effect time range has not yet started. */ calculateEffectPerformance() { let measurementValueLatestMet1=null; let measurementValueLatestMet2=null; let measurementValueLatestMet3=null; // All timestamps in unix timestamp format in sec let timestampEffectFrom=Helper.parseTimestampToUnixTimestampInMillis(this.timestampEffectStart); let timestampEffectTo=Helper.parseTimestampToUnixTimestampInMillis(this.timestampEffectEnd); let timestampNow=moment().tz('Europe/Berlin').unix(); let effectDeviation=null; let measurementAsIs=null; let measurementToBe=null; let timeProgressPercent=null; // Check if (moment().tz('Europe/Berlin').unix() < timestampEffectFrom) { // Effect time range of measure has not yet started, i.e. do not include in performance analysis return 'measure_effect_timerange_not_yet_started'; } // Get latest measurement of ElementOuCombi let tsMax=null; if (this.elementOuCombiObj.elementObj.measurementValueType=='quant') { // Consider quantative elements only for (let measurementObj of this.elementOuCombiObj.measurementsObjAry) { if (measurementObj.timestampDeactivated===null && measurementObj.getApprovalStatus().approved===true) { // not deleted and approved if (tsMax===null || tsMax < (measurementObj.timestampPointUnixInSec!==null ? measurementObj.timestampPointUnixInSec : measurementObj.timestampRangeToUnixInSec)) { tsMax=(measurementObj.timestampPointUnixInSec!==null ? measurementObj.timestampPointUnixInSec : measurementObj.timestampRangeToUnixInSec); measurementValueLatestMet1=measurementObj.valueMet1; measurementValueLatestMet2=measurementObj.valueMet2; measurementValueLatestMet3=measurementObj.valueMet3; } } } } //console.log(measurementValueLatestMet1, measurementValueLatestMet2, measurementValueLatestMet3); // Check if (measurementValueLatestMet1==null && measurementValueLatestMet2==null && measurementValueLatestMet3==null) { // No measurements exist yet return null; } // Get inputNr let inputNr=null; let baselineMet=null; let targetMet=null; let measurementValueLatestMet=null; if (this.baselineMet1!==null && measurementValueLatestMet1!==null) { inputNr=1; baselineMet=this.baselineMet1; targetMet=this.targetMet1; measurementValueLatestMet=measurementValueLatestMet1; } if (this.baselineMet2!==null && measurementValueLatestMet2!==null) { inputNr=2; baselineMet=this.baselineMet2; targetMet=this.targetMet2; measurementValueLatestMet=measurementValueLatestMet2; } if (this.baselineMet3!==null && measurementValueLatestMet3!==null) { inputNr=3; baselineMet=this.baselineMet3; targetMet=this.targetMet3; measurementValueLatestMet=measurementValueLatestMet3; } // Calculate effect performance (= effect deviation) (+1 day as timestampEffectTo is inclusive; Example: 3 until 7 = 4, but has to be 5 (i.e. +1 day)) let dayInSec=24*60*60; timeProgressPercent = ((Math.min(Math.max(timestampNow, timestampEffectFrom), timestampEffectTo + dayInSec) - timestampEffectFrom) / (timestampEffectTo + dayInSec - timestampEffectFrom)); if (targetMet!==null) { // metric if (targetMet==baselineMet) { Logger.log('FRONTEND_CLIENT_CONSISTENCECHECK', 'ERROR_SYSTEM', { msg: 'baseline equals target', inputNr: inputNr, target: targetMet, baseline: baselineMet, flag: 'csrd' }); return 'target_equals_baseline'; // Should not happen (would be an error) and the taken care of in frontend and backend } else { // standard case let valueRangeEffect = Number(targetMet) - Number(baselineMet); measurementAsIs = measurementValueLatestMet - Number(baselineMet); measurementToBe = timeProgressPercent * valueRangeEffect; effectDeviation = (measurementAsIs - measurementToBe) / valueRangeEffect; } } return effectDeviation; } /* Returns filling grade. Can also return NULL if no measurements exist yet. Can also return string 'measure_effect_timerange_not_yet_started' if effect time range has not yet started. */ calculateFillingGrade() { // Calculate filling grade function calcFillingGradeByMeasurementType(measureElementOuCombiValueObj, measurementValueLatestMet1, measurementValueLatestMet2, measurementValueLatestMet3) { let target=null; let baseline=null; let fillingGrade=null; if (measureElementOuCombiValueObj.getIdxOfUsedQuantMeasurementPoint()==1) { target=measureElementOuCombiValueObj.targetMet1; baseline=measureElementOuCombiValueObj.baselineMet1; fillingGrade=(measurementValueLatestMet1-baseline)/(target-baseline); //console.log(measureElementOuCombiValueObj, measurementValueLatestMet1, baseline, target); } else if (measureElementOuCombiValueObj.getIdxOfUsedQuantMeasurementPoint()==2) { target=measureElementOuCombiValueObj.targetMet2; baseline=measureElementOuCombiValueObj.baselineMet2; fillingGrade=(measurementValueLatestMet2-baseline)/(target-baseline); //console.log(measurementValueLatestMet2, baseline, target); } else if (measureElementOuCombiValueObj.getIdxOfUsedQuantMeasurementPoint()==3) { target=measureElementOuCombiValueObj.targetMet3; baseline=measureElementOuCombiValueObj.baselineMet3; fillingGrade=(measurementValueLatestMet3-baseline)/(target-baseline); //console.log(measurementValueLatestMet3, baseline, target); } if (target==baseline) { Logger.log('FRONTEND_CLIENT_CONSISTENCECHECK', 'ERROR_SYSTEM', { msg: 'baseline equals target', target: target, baseline: baseline, flag: 'csrd' }); return 'target_equals_baseline'; // Should not happen (would be an error) and the taken care of in frontend and backend } return fillingGrade; } let measurementValueLatestMet1=null; let measurementValueLatestMet2=null; let measurementValueLatestMet3=null; // All timestamps in unix timestamp format in sec let timestampEffectFrom=Helper.parseTimestampToUnixTimestampInMillis(this.timestampEffectStart); let timestampNow=moment().tz('Europe/Berlin').unix(); let historicFillingGrades=[]; // Check if (moment().tz('Europe/Berlin').unix() < timestampEffectFrom) { // Effect time range of measure has not yet started, i.e. do not include in performance analysis return 'measure_effect_timerange_not_yet_started'; } // Get latest measurement of ElementOuCombi & calculate historic filling grade steps let tsMax=null; let ts=null; if (this.elementOuCombiObj.elementObj.measurementValueType=='quant') { // Consider quantative elements only for (let measurementObj of this.elementOuCombiObj.measurementsObjAry) { if (measurementObj.timestampDeactivated===null && measurementObj.getApprovalStatus().approved===true) { // not deleted and approved if (measurementObj.getApprovalStatus().approved) { // only approved measurements are considered ts=(measurementObj.timestampPointUnixInSec!==null ? measurementObj.timestampPointUnixInSec : measurementObj.timestampRangeToUnixInSec); // Latest timestamp if (tsMax===null || tsMax < ts) { tsMax=ts; if (measurementObj.valueMet1!==null) measurementValueLatestMet1=measurementObj.valueMet1; if (measurementObj.valueMet2!==null) measurementValueLatestMet2=measurementObj.valueMet2; if (measurementObj.valueMet3!==null) measurementValueLatestMet3=measurementObj.valueMet3; } // Calc historic filling grades if (ts < timestampNow) { historicFillingGrades.push({ timestampUnixInSec: ts , fillingGrade: calcFillingGradeByMeasurementType(this, measurementObj.valueMet1, measurementObj.valueMet2, measurementObj.valueMet3)}); } } } } } // Check if (measurementValueLatestMet1==null && measurementValueLatestMet2==null && measurementValueLatestMet3==null) { // No measurements exist yet return null; } // Calc last filling grade //console.log(this, measurementValueLatestMet1, measurementValueLatestMet2, measurementValueLatestMet3); let fillingGrade=calcFillingGradeByMeasurementType(this, measurementValueLatestMet1, measurementValueLatestMet2, measurementValueLatestMet3); return { fillingGrade: fillingGrade , historicFillingGrades: historicFillingGrades , measurementValueLatestMet1: measurementValueLatestMet1 , measurementValueLatestMet2: measurementValueLatestMet2 , measurementValueLatestMet3: measurementValueLatestMet3 //, measurementValueLatestMet: measurementValueLatestMet //, measurementValueLatestCat: measurementValueLatestCat //, measurementValueLatestBin: measurementValueLatestBin }; } loadMeasureElementOuCombiValueIntoThis(meocvObj) { if (meocvObj.id!==undefined && meocvObj.id!==null) this.id=meocvObj.id; if (meocvObj.baselineMet1!==undefined && meocvObj.baselineMet1!==null) this.baselineMet1=meocvObj.baselineMet1; if (meocvObj.baselineMet2!==undefined && meocvObj.baselineMet2!==null) this.baselineMet2=meocvObj.baselineMet2; if (meocvObj.baselineMet3!==undefined && meocvObj.baselineMet3!==null) this.baselineMet3=meocvObj.baselineMet3; if (meocvObj.targetMet1!==undefined && meocvObj.targetMet1!==null) this.targetMet1=meocvObj.targetMet1; if (meocvObj.targetMet2!==undefined && meocvObj.targetMet2!==null) this.targetMet2=meocvObj.targetMet2; if (meocvObj.targetMet3!==undefined && meocvObj.targetMet3!==null) this.targetMet3=meocvObj.targetMet3; if (meocvObj.timestampEffectStart!==undefined && meocvObj.timestampEffectStart!==null) this.timestampEffectStart=meocvObj.timestampEffectStart; if (meocvObj.timestampEffectEnd!==undefined && meocvObj.timestampEffectEnd!==null) this.timestampEffectEnd=meocvObj.timestampEffectEnd; if (meocvObj.timestamp_deactivated!==undefined && meocvObj.timestamp_deactivated!==null) this.timestamp_deactivated=meocvObj.timestamp_deactivated; // Here, the object can be re-used (instead of creating a new object), because the object's content will not be changed (instead the whole object might be replaced) this.elementOuCombiObj=meocvObj.elementOuCombiObj; this.measureObj=meocvObj.measureObj; } } class MeasureFile { constructor(apiMeasureFileObj) { this.id=apiMeasureFileObj.pk_measures_files; this.filename=apiMeasureFileObj.filename; this.documentType=apiMeasureFileObj.document_type; this.sizeInBytes=apiMeasureFileObj.size; this.timestampCreation=apiMeasureFileObj.timestamp_creation; this.timestampDeactivated=apiMeasureFileObj.timestamp_deactivated; } deactivate(callbackSuccess) { var apiUrl=apiHost+'/measure/file/deactivate/'+this.id; const tsStartApi=Date.now(); $.ajax({type:'GET', url:apiUrl, headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_FILE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Das Dokument wurde erfolgreich gelöscht.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Das Dokument wurde nicht gelöscht, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_FILE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_FILE', apiUrl, xhr, status, error); }); } isActive() { var active=true; if (this.timestampDeactivated===undefined) throw Error('timestampDeactivated not given for MeasureFile.'); if (this.timestampDeactivated!==null) active=false; return active; } } class MeasureFileCSRD { constructor(apiMeasureFileObj) { this.id=apiMeasureFileObj.pk_csrd_measures_files; this.filename=apiMeasureFileObj.filename; this.documentType=apiMeasureFileObj.document_type; this.sizeInBytes=apiMeasureFileObj.size; this.timestampCreation=apiMeasureFileObj.timestamp_creation; this.timestampDeactivated=apiMeasureFileObj.timestamp_deactivated; } deactivate(callbackSuccess) { var apiUrl=apiHost+'/csrd/measure/file/deactivate/'+this.id; const tsStartApi=Date.now(); $.ajax({type:'GET', url:apiUrl, headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_FILE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Das Dokument wurde erfolgreich gelöscht.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Das Dokument wurde nicht gelöscht, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CSRD_FILE', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CSRD_FILE', apiUrl, xhr, status, error); }); } isActive() { var active=true; if (this.timestampDeactivated===undefined) throw Error('timestampDeactivated not given for MeasureFile.'); if (this.timestampDeactivated!==null) active=false; return active; } } class ConsumptionEntityCategory { constructor(apiObj) { this.id=null; if (apiObj.pk_consumption_entities_categories!==undefined) this.id=apiObj.pk_consumption_entities_categories; this.fkAccounts=null; if (apiObj.fk_accounts!==undefined) this.fkAccounts=apiObj.fk_accounts; this.name=null; if (apiObj.name!==undefined) this.name=apiObj.name; /* Would create infinite loop this.consumptionEntities=[]; if (apiObj.consumption_entities!==undefined && apiObj.consumption_entities!==null) { for (let consumptionEntity of apiObj.consumption_entities) { this.consumptionEntities.push(new ConsumptionEntity(consumptionEntity)); } } */ this.consumptionHierarchies=[]; if (apiObj.consumption_hierarchies!==undefined && apiObj.consumption_hierarchies!==null) { for (let consumptionHierarchy of apiObj.consumption_hierarchies) { this.consumptionHierarchies.push(new ConsumptionHierarchy(consumptionHierarchy, this)); } } this.customFieldSpecs=[]; if (apiObj.customFieldSpecs!==undefined && apiObj.customFieldSpecs!==null) { for (let customFieldSpec of apiObj.customFieldSpecs) { this.customFieldSpecs.push(new ConsumptionCustomFieldSpecCEC(customFieldSpec)); } } this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } getAutomCalcForCVH(cvhId) { let cac=null; for (let customAutoCalc of this.customAutoCalcs) { if (customAutoCalc.targetConsumptionHierarchyID==cvhId && customAutoCalc.isActive()) { if (cac!==null) { // Error: Only max. 1 formula should exist per CVH (otherwise: how to decide which formula to use?) Logger.log('FRONTEND_CLIENT', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: "Multiple formulas for single CVH available - Not allowed, as system cannot decide which formula to use", cvhId: cvhId }); Helper.showToastr('Fehler', 'Inkonsistente Konfiguration - Bitte Adminsitrator benachrichtigen.', 'error'); throw new Error('Multiple formulas for single CVH available - Not allowed, as system cannot decide which formula to use ('+cvhId+')'); } cac=customAutoCalc; } } return cac; } getSortedCustomFieldSpecs() { // Copy CustomFieldSpecs in separate array for sorting (avpoids sorting the original array) let cfsAry=[]; for (let cfs of this.customFieldSpecs) { if (cfs.showInVETable===true) cfsAry.push(cfs); } // Sort array cfsAry.sort(function(a,b) { if (a.displayOrder!==null && b.displayOrder!==null) { if (a.displayOrder > b.displayOrder) return 1; else if (a.displayOrder < b.displayOrder) return -1; else return 0; } else { if (a.name > b.name) return 1; else if (a.name < b.name) return -1; else return 0; } }); return cfsAry; } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; //else if (this.account!==null && !this.account.isActive()) active=false; return active; } static createSelectionList(tableHtmlId, consumptionCategoriesAry) { $('#'+tableHtmlId+' tbody').empty(); for (let ccObj of consumptionCategoriesAry) { let $tr=$(''); $tr.append($('').append(ccObj.name)); $tr.append($('').append('')); $('#'+tableHtmlId+' tbody').append($tr); } // Create event handler for checkboxes /* $("#"+tableHtmlId+" tbody tr input[type=checkbox]").change(function(event) { // What are these 3 variables used for? var $parentTr = $(this).closest('tr'); var isNowChecked = $(this).is(":checked"); var write=$(this).hasClass('write'); }); */ } static loadActiveConsumptionCategoriesOfAccountFromApi(fkAccounts, callbackSuccessAry=null) { const tsStartApi=Date.now(); var apiUrl=apiHost+'/consumption/entity_categories/accountId/'+fkAccounts; if (fkAccounts===undefined || fkAccounts===null) { Helper.showToastr('Fehler', 'Account ID fehlt.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYCRITERIAS', 'ERROR_SYSTEM_PARAMETER', { apiUrl: apiUrl }); return; } $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { //console.log(dataFromApi); if (dataFromApi!==null && Array.isArray(dataFromApi)) { Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYCRITERIAS', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let cecs=[]; for (let cec of dataFromApi) { let cecObj=new ConsumptionEntityCategory(cec); if (cecObj.isActive()) cecs.push(cecObj); } //console.log(cecs); if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(cecs); } } } else { Helper.showToastr('Fehler', 'Daten konnten nicht korrekt geladen werden.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYCRITERIAS', 'ERROR_SYSTEM_DATALOAD', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); } } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYCRITERIAS', apiUrl, xhr, status, error); }); } static loadActiveConsumptionCategoriesWithoutEntitiesOfAccountFromApi(fkAccounts, callbackSuccessAry=null) { const tsStartApi=Date.now(); var apiUrl=apiHost+'/consumption/entity_categories_without_entities/accountId/'+fkAccounts; if (fkAccounts===undefined || fkAccounts===null) { Helper.showToastr('Fehler', 'Account ID fehlt.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYCRITERIAS', 'ERROR_SYSTEM_PARAMETER', { apiUrl: apiUrl }); return; } $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { //console.log(dataFromApi); if (dataFromApi!==null && Array.isArray(dataFromApi)) { Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYCRITERIAS', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let cecs=[]; for (let cec of dataFromApi) { let cecObj=new ConsumptionEntityCategory(cec); if (cecObj.isActive()) cecs.push(cecObj); } //console.log(cecs); if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(cecs); } } } else { Helper.showToastr('Fehler', 'Daten konnten nicht korrekt geladen werden.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYCRITERIAS', 'ERROR_SYSTEM_DATALOAD', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); } } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYCRITERIAS', apiUrl, xhr, status, error); }); } getCustomFieldSpecObjById(id) { for (let customFieldSpec of this.customFieldSpecs) { if (customFieldSpec.id==id) return customFieldSpec; } return null; } getConsumptionHierarchyById(cvhId) { //console.log(this.consumptionHierarchies); for (let cvh of this.consumptionHierarchies) { if (cvh.id==cvhId) return cvh; } return null; } isActiveForCurrentAccount() { if (userObj.accountObj!==null) { if (userObj.accountObj.consumption_settings!==null) { if (userObj.accountObj.consumption_settings.active_consumption_entities_categories_pks!==null) { if (userObj.accountObj.consumption_settings.active_consumption_entities_categories_pks.includes(this.id)) { return true; } } } } return false; } } /* class ConsumptionCustomAutoCalcCEC { constructor(apiObj, cec=null) { this.consumptionEntityCategory=null; if (cec!==null && cec!==undefined) this.consumptionEntityCategory=cec; this.targetConsumptionHierarchyID=null; if (apiObj.targetConsumptionHierarchyID!==undefined) this.targetConsumptionHierarchyID=apiObj.targetConsumptionHierarchyID; this.calculationFormula=null; if (apiObj.calculationFormula!==undefined) this.calculationFormula=apiObj.calculationFormula; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; return active; } formula2Ary() { if (this.calculationFormula!==null) { return this.calculationFormula.split(' '); } else return null; } getCustomFieldIDsFromFormula() { let fAyr=this.formula2Ary(); let idAry=[]; for (let id of fAyr) { if (id!='+' && id!='-' && id!='*' && id!='/' && id!='(' && id!=')') idAry.push(id); } return idAry; } checkIfCustomFieldsExistAndAreNumbers() { if (this.consumptionEntityCategory!==null) { // Get customFieldIds let aryCustomFieldIds=[]; for (let cfs of this.consumptionEntityCategory.customFieldSpecs) { if (cfs.type=='integer' || cfs.type=='decimal') aryCustomFieldIds.push(cfs.id); } // Check if customFieldIDs in math formula exist for (let customFieldId of this.formula2Ary()) { if (customFieldId!='+' && customFieldId!='-' && customFieldId!='*' && customFieldId!='/' && customFieldId!='(' && customFieldId!=')') { if (!aryCustomFieldIds.includes(customFieldId.trim())) { return false; } } } return true; } else return null; } } */ class ConsumptionCustomAutoCalcCVH { constructor(apiObj, cvh=null) { this.consumptionHierarchy=null; if (cvh!==null && cvh!==undefined) this.consumptionHierarchy=cvh; this.calculationFormula=null; if (apiObj.calculationFormula!==undefined) this.calculationFormula=apiObj.calculationFormula; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; return active; } formula2Ary() { if (this.calculationFormula!==null) { return this.calculationFormula.split(' '); } else return null; } getCustomFieldIDsFromFormula() { let fAyr=this.formula2Ary(); let idAry=[]; for (let id of fAyr) { if (id!='+' && id!='-' && id!='*' && id!='/' && id!='(' && id!=')') idAry.push(id); } return idAry; } checkIfCustomFieldsExistAndAreNumbers() { if (this.consumptionHierarchy!==null) { // Get customFieldIds let aryCustomFieldIds=[]; for (let cfs of this.consumptionHierarchy.customFieldSpecs) { if (cfs.type=='integer' || cfs.type=='decimal') aryCustomFieldIds.push(cfs.id); } // Check if customFieldIDs in math formula exist for (let customFieldId of this.formula2Ary()) { if (customFieldId!='+' && customFieldId!='-' && customFieldId!='*' && customFieldId!='/' && customFieldId!='(' && customFieldId!=')') { if (!aryCustomFieldIds.includes(customFieldId.trim())) { return false; } } } return true; } else return null; } } class ConsumptionEntity { constructor(apiObj) { //console.log('ConsumptionEntity', apiObj); this.id=null; if (apiObj.pk_consumption_entities!==undefined) this.id=apiObj.pk_consumption_entities; this.consumptionEntityCategory=null; if (apiObj.consumption_entity_category!==undefined && apiObj.consumption_entity_category!==null) this.consumptionEntityCategory=new ConsumptionEntityCategory(apiObj.consumption_entity_category); this.fkAccounts=null; if (apiObj.fk_accounts!==undefined) this.fkAccounts=apiObj.fk_accounts; this.notes=null; if (apiObj.notes!==undefined) this.notes=apiObj.notes; this.customId=null; if (apiObj.custom_id!==undefined) this.customId=apiObj.custom_id; this.customFieldValue=[]; if (apiObj.customFieldValues!==undefined && apiObj.customFieldValues!==null) { for (let customFieldValue of apiObj.customFieldValues) { this.customFieldValue.push(new ConsumptionCustomFieldValue(customFieldValue)); } } this.timeranges=[]; if (apiObj.consumption_values_timerange!==undefined && apiObj.consumption_values_timerange!==null) { for (let timerange of apiObj.consumption_values_timerange) { this.timeranges.push(new ConsumptionValuesTimerange(timerange, this)); } } this.entity2hierarchy=[]; if (apiObj.consumption_entity2hierarchies!==undefined && apiObj.consumption_entity2hierarchies!==null) { for (let entity2hierarchy of apiObj.consumption_entity2hierarchies) { this.entity2hierarchy.push(new ConsumptionEntity2Hierarchy(entity2hierarchy, this)); } } //this.organizationalUnit=null; if (apiObj.organizational_unit!==undefined && apiObj.organizational_unit!==null) this.organizationalUnit=new OE(apiObj.organizational_unit); this.fkOrganizationalUnits=null; if (apiObj.fk_organizational_units!==undefined && apiObj.fk_organizational_units!==null) this.fkOrganizationalUnits=apiObj.fk_organizational_units; this.timestampArchived=null; if (apiObj.timestamp_archived!==undefined && apiObj.timestamp_archived!==null) this.timestampArchived=apiObj.timestamp_archived; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; //this.timestampArchived=apiObj.timestamp_archived; //this.timestampDeactivated=apiObj.timestamp_deactivated; //this.timestampCreation=apiObj.timestampCreation; // Transient (in backend pre-calculated data) this.lastActiveTimerangeFrom=null; if (apiObj.lastTimerangeFrom!==undefined && apiObj.lastTimerangeFrom!==null) this.lastActiveTimerangeFrom=apiObj.lastTimerangeFrom; this.lastActiveTimerangeTo=null; if (apiObj.lastTimerangeTo!==undefined && apiObj.lastTimerangeTo!==null) this.lastActiveTimerangeTo=apiObj.lastTimerangeTo; this.statusConsumptionValues=null; if (apiObj.statusConsumptionValues!==undefined) this.statusConsumptionValues=apiObj.statusConsumptionValues; } /* createConcumptionEntity(id, consumptionEntityCategory, fkAccounts, notes, customFieldValue, timeranges, entity2hierarchy, organizationalUnit, timestampArchived, timestampDeactivated, timestampCreation, lastActiveTimerangeFrom, lastActiveTimerangeTo, statusConsumptionValues) { this.id=id; this.consumptionEntityCategory=consumptionEntityCategory; this.fkAccounts=fkAccounts; this.notes=notes; this.customFieldValue=customFieldValue; this.timeranges=timeranges; this.entity2hierarchy=entity2hierarchy; this.organizationalUnit=organizationalUnit; this.timestampArchived=timestampArchived; this.timestampDeactivated=timestampDeactivated; this.timestampCreation=timestampCreation; this.lastActiveTimerangeFrom=lastActiveTimerangeFrom; this.lastActiveTimerangeTo=lastActiveTimerangeTo; this.statusConsumptionValues=statusConsumptionValues; } */ static createNewEmptyConsumptionEntity(consumptionEntityCategoryObj) { let ce=new ConsumptionEntity({}); ce.consumptionEntityCategory=consumptionEntityCategoryObj; return ce; } isActive() { var active=true; let ouObj=null; if (this.fkOrganizationalUnits!==null) ouObj=OEMeasurements.getOEById(this.fkOrganizationalUnits); if (this.timestampDeactivated!==null) active=false; else if (this.consumptionEntityCategory!==null && !this.consumptionEntityCategory.isActive()) active=false; //else if (this.account!==null && !this.account.isActive()) active=false; //else if (this.organizationalUnit!==null && !Elemnt.isActive(this.organizationalUnit).active) active=false; else if (ouObj!==null && !Elemnt.isActive(ouObj).active) active=false; return active; } isNew() { if (this.id===null) return true; else return false; } saveNew(callbackSuccess=null) { // Set Spinner Helper.showFullScreenProcessingBackdrop(); // ### Consistency checks let mandatoryFieldsMissing=[]; for (let cfs of this.consumptionEntityCategory.customFieldSpecs) { if (cfs.mandatory===true) { for (let cfv of this.customFieldValue) { if (cfs.id==cfv.id && (cfv.value===null || cfv.value=='')) { mandatoryFieldsMissing.push(cfs); break; } } } } if (mandatoryFieldsMissing.length > 0) { let missingFieldNames=''; for (let cfs of mandatoryFieldsMissing) { if (missingFieldNames!='') missingFieldNames+=', '; missingFieldNames+=cfs.name; } Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Folgende Mussfelder sind nicht befüllt: '+missingFieldNames, 'error'); return; } // Check timestamp fields which automatically create a timerange let inputAutomaticTimerangeCreationFrom=null; let inputAutomaticTimerangeCreationTo=null; for (let cfs of this.consumptionEntityCategory.customFieldSpecs) { for (let cfv of this.customFieldValue) { if (cfs.id==cfv.id) { if (cfs.inputAutomaticTimerangeCreationFrom) { inputAutomaticTimerangeCreationFrom=cfv.value; break; } if (cfs.inputAutomaticTimerangeCreationTo) { inputAutomaticTimerangeCreationTo=cfv.value; break; } } } } if (inputAutomaticTimerangeCreationFrom!==null && inputAutomaticTimerangeCreationTo!==null) { if (!moment(inputAutomaticTimerangeCreationFrom).isBefore(moment(inputAutomaticTimerangeCreationTo))) { Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Das Datum-Von-Feld muss vor dem Datum-Bis-Feld liegen', 'error'); return; } } // Check if all custom input fields for automatic calculations are filled /* for (let cac of this.consumptionEntityCategory.customAutoCalcs) { if (cac.isActive()) { let idAry=cac.getCustomFieldIDsFromFormula(); for (let id of idAry) { for (let cfv of this.customFieldValue) { if (cfv.id==id) { // if (cfv.value===null || cfv.value=='') { Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Ein individuelles Feld ('+cfv.id+') wird für die automatische Berechnung von Verbrauchswerten benötigt, ist aber nicht gefüllt', 'error'); return; } } } } } } */ // ### Prepare API var apiUrl=apiHost+'/consumption/entity/new'; // !The keys have to equal the Java class fields! var postData={}; let customEFsByTempId={}; postData['fk_accounts']=userObj.accountObj.id; postData['notes']=this.notes; //postData['organizational_unit']={ pk_organizational_units: this.fkOrganizationalUnits }; postData['fk_organizational_units']=this.fkOrganizationalUnits; postData['customFieldValues']=this.customFieldValue; postData['consumption_entity_category']={ pk_consumption_entities_categories: this.consumptionEntityCategory.id }; postData['consumption_entity2hierarchies']=[]; for (let e2h of this.entity2hierarchy) { if (e2h.isActive()) { // Only store active ones // Create E2H let e2hNew={ fk_consumption_hierarchies: e2h.fkConsumptionHierarchies , consumption_custom_emissionsfactors: [] , consumption_entity2hierarchy2eocs: [] , consumption_entity2hierarchy2eocs_co2: [] // timestamp_archived, timestamp_deactivated not required for saveNew }; postData['consumption_entity2hierarchies'].push(e2hNew); // Select Custom EFs for (let customEF of e2h.customEFs) { if (customEF.isActive()) { if (moment(customEF.timestampTo).isBefore(moment(customEF.timestampFrom))) { Helper.showToastr('Fehler', 'Individuelle Emissionsfaktoren: "Gültig bis" darf zeitlich nicht vor "Gültig von" liegen.', 'error'); return; } let tempId=moment().valueOf()+'_'+Helper.getRandomString(10); e2hNew.consumption_custom_emissionsfactors.push({ type: customEF.type , value: customEF.value , timestamp_from: customEF.timestampFrom , timestamp_to: customEF.timestampTo // timestamp_deactivated not required for saveNew , temporary_id: tempId // Temporary ID is requried to make EF object identifyable for file upload , source: customEF.source }); customEFsByTempId[tempId]=customEF; } } // Select EOC targets for (let entity2hierarchy2eoc of e2h.entity2hierarchy2eocs) { if (entity2hierarchy2eoc.isActive()) { e2hNew.consumption_entity2hierarchy2eocs.push({ fk_elements_organizational_units: entity2hierarchy2eoc.fkEoc // timestamp_deactivated not required for saveNew }); } } // Select EOC-CO2 targets for (let entity2hierarchy2eoc_co2 of e2h.entity2hierarchy2eoc_co2s) { if (entity2hierarchy2eoc_co2.isActive()) { e2hNew.consumption_entity2hierarchy2eocs_co2.push({ fk_elements_organizational_units: entity2hierarchy2eoc_co2.fkEoc // timestamp_deactivated not required for saveNew }); } } } } // consumption_values_timerange, timestamp_archived, timestamp_deactivated not required for saveNew // ### Execute API let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { // Returns just saved CE object JSON Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITY', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if ('pk_consumption_entities' in data && data.pk_consumption_entities!==null && data.pk_consumption_entities!==undefined && data.pk_consumption_entities!='') { Helper.showToastr('Erfolg', 'Neue Verbrauchs-Entität wurde gespeichert.', 'success'); //console.log(data); let ceObj=new ConsumptionEntity(data); // Upload files fileUploadSuccessCounter=0; let nrFileUploads=0; for (let e2hObj of ceObj.entity2hierarchy) { // Iterate each custom EF of just stored CE if (e2hObj.isActive()) { for (let customEFObj of e2hObj.customEFs) { if (customEFObj.isActive()) { // Find files to be uploaded in frontend data if (customEFObj.temporaryId in customEFsByTempId) { let customEF=customEFsByTempId[customEFObj.temporaryId]; //console.log('#### customEF #####', customEF); //console.log(customEF.tempFileObj); if ('tempFileObj' in customEF) { // Set upload destination customEF.tempFileObj.fileinput().data().fileinput.uploadUrl=function() { return apiHost+'/consumption/entity/custom_ef/file/upload/'+customEFObj.id; }; // Upload if (customEF.tempFileObj.fileinput('getFilesCount')>0) { nrFileUploads++; customEF.tempFileObj.fileinput('upload'); } } } else { // Should not happen Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITY', 'ERROR_SYSTEM', { errorMsg: 'Temporary ID was not found in array', customEFObjId: customEFObj.id, temporaryId: customEFObj.temporaryId }); } } } } } // Wait for all uploads to be successfully done and call callback only then (required to show uploaded documents in frontend) Helper.wait( 100 // ms to wait per loop , 100 // max nr loops , function() { // Check if all files were uploaded (100 loops * 100ms = 10sec max waiting time) if (fileUploadSuccessCounter>=nrFileUploads) return true; else return false; }, function() { // callbackPositiveCheck Helper.hideFullScreenProcessingBackdrop(); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(ceObj); }, function() { // callbackFinishedWithoutPositiveCallbackCheck Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Das hochladen der Dateien hat zu lange gedauert. Seite bitte neu laden.', 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITY', 'ERROR_SYSTEM', { ceId: ceObj.id }); } ); } else { Helper.hideFullScreenProcessingBackdrop(); Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITY', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); Helper.showToastr('Fehler', 'Fehler beim Speichern der Verbrauchs-Entität: '+data.msg, 'error'); } }} ).fail(function(xhr, status, error) { Helper.hideFullScreenProcessingBackdrop(); handleFailedApiCall('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITY', apiUrl, xhr, status, error, null, { json: jsonData }); }); } save(callbackSuccess=null) { // Set Spinner Helper.showFullScreenProcessingBackdrop(); // ### Consistency checks //if (this.parentMeasureStructureObj===null || this.parentMeasureStructureObj===undefined) { Helper.showToastr('Fehler', 'Maßnahmen-Struktur fehlt.', 'error'); return; } //if (this.responsibleUserObj===null || this.responsibleUserObj===undefined) { Helper.showToastr('Fehler', 'Verantwortlicher User fehlt.', 'error'); return; } //if (this.name===null || this.name===undefined || this.name=='') { Helper.showToastr('Fehler', 'Maßnahmen-Name fehlt.', 'error'); return; } //if (this.approved===null || this.approved===undefined) { Helper.showToastr('Fehler', 'Freigabe-Wert fehlt.', 'error'); return; } //if (this.consumptionEntityCategory===null || this.consumptionEntityCategory===undefined) { Helper.showToastr('Fehler', 'Die Verbrauchswerte-Kategorie ist nicht gesetzt.', 'error'); return; } let mandatoryFieldsMissing=[]; for (let cfs of this.consumptionEntityCategory.customFieldSpecs) { if (cfs.mandatory===true) { for (let cfv of this.customFieldValue) { if (cfs.id==cfv.id && (cfv.value===null || cfv.value=='')) { mandatoryFieldsMissing.push(cfs); break; } } } } if (mandatoryFieldsMissing.length > 0) { let missingFieldNames=''; for (let cfs of mandatoryFieldsMissing) { if (missingFieldNames!='') missingFieldNames+=', '; missingFieldNames+=cfs.name; } Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Folgende Mussfelder sind nicht befüllt: '+missingFieldNames, 'error'); return; } // ### Prepare API var apiUrl=apiHost+'/consumption/entity/edit'; // !The keys have to equal the Java class fields! var postData={}; let customEFsByTempId={}; postData['pk_consumption_entities']=this.id; postData['notes']=this.notes; postData['custom_id']=this.customId; postData['fk_organizational_units']=this.fkOrganizationalUnits; postData['customFieldValues']=this.customFieldValue; postData['consumption_entity_category']={ pk_consumption_entities_categories: this.consumptionEntityCategory.id }; postData['consumption_entity2hierarchies']=[]; for (let e2h of this.entity2hierarchy) { if (e2h.id!==null || e2h.isActive()) { // Only store active or already existing ones // Create E2H let e2hNew={ pk_consumption_entities2hierarchies: e2h.id , fk_consumption_hierarchies: e2h.fkConsumptionHierarchies , consumption_custom_emissionsfactors: [] , consumption_entity2hierarchy2eocs: [] , consumption_entity2hierarchy2eocs_co2: [] , timestamp_deactivated: e2h.timestampDeactivated }; postData['consumption_entity2hierarchies'].push(e2hNew); // Select Custom EFs for (let customEF of e2h.customEFs) { if (customEF.id!==null || customEF.isActive()) { if (moment(customEF.timestampTo).isBefore(moment(customEF.timestampFrom))) { Helper.showToastr('Fehler', 'Individuelle Emissionsfaktoren: "Gültig bis" darf zeitlich nicht vor "Gültig von" liegen.', 'error'); return; } let customEF_APIObj={ pk_consumption_custom_emissionfactors: customEF.id , type: customEF.type , value: customEF.value , timestamp_from: customEF.timestampFrom , timestamp_to: customEF.timestampTo , timestamp_deactivated: customEF.timestampDeactivated , source: customEF.source }; if (customEF.id===null) { // New CustomEF object (Store some ID to link upload file to this customEF object) let tempId=moment().valueOf()+'_'+Helper.getRandomString(10); customEF_APIObj['temporary_id']=tempId; customEFsByTempId[tempId]=customEF; } e2hNew.consumption_custom_emissionsfactors.push(customEF_APIObj); } } // Select EOC targets for (let entity2hierarchy2eoc of e2h.entity2hierarchy2eocs) { if (entity2hierarchy2eoc.id!==null || entity2hierarchy2eoc.isActive()) { e2hNew.consumption_entity2hierarchy2eocs.push({ pk_consumption_entities2hierarchies2eoc: entity2hierarchy2eoc.id , fk_elements_organizational_units: entity2hierarchy2eoc.fkEoc , timestamp_deactivated: entity2hierarchy2eoc.timestampDeactivated }); } } // Select EOC-CO2 targets for (let entity2hierarchy2eoc_co2 of e2h.entity2hierarchy2eoc_co2s) { if (entity2hierarchy2eoc_co2.id!==null || entity2hierarchy2eoc_co2.isActive()) { e2hNew.consumption_entity2hierarchy2eocs_co2.push({ pk_consumption_entities2hierarchies2eoc_co2: entity2hierarchy2eoc_co2.id , fk_elements_organizational_units: entity2hierarchy2eoc_co2.fkEoc , timestamp_deactivated: entity2hierarchy2eoc_co2.timestampDeactivated }); } } } } // consumption_values_timerange, timestamp_archived, timestamp_deactivated not required for saveNew //console.log('save post data >', postData); // ### Execute API let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { // Returns just saved CE object JSON Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITY', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); //if (data.status=='ok') { if ('pk_consumption_entities' in data && data.pk_consumption_entities!==null && data.pk_consumption_entities!==undefined && data.pk_consumption_entities!='') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); //console.log(data); let ceObj=new ConsumptionEntity(data); // Upload files (only for all new CustomEF objects; as files and customEF objects always go together) fileUploadSuccessCounter=0; let nrFileUploads=0; for (let e2hObj of ceObj.entity2hierarchy) { // Iterate each custom EF of just stored CE if (e2hObj.isActive()) { for (let customEFObj of e2hObj.customEFs) { if (customEFObj.isActive()) { // Find files to be uploaded in frontend data if (customEFObj.temporaryId in customEFsByTempId) { // Only new CustomEFs let customEF=customEFsByTempId[customEFObj.temporaryId]; //console.log('#### customEF #####', customEF); //console.log(customEF.tempFileObj); if ('tempFileObj' in customEF) { // Set upload destination customEF.tempFileObj.fileinput().data().fileinput.uploadUrl=function() { return apiHost+'/consumption/entity/custom_ef/file/upload/'+customEFObj.id; }; // Upload if (customEF.tempFileObj.fileinput('getFilesCount')>0) { nrFileUploads++; customEF.tempFileObj.fileinput('upload'); } } } /*else { // Should not happen Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITY', 'ERROR_SYSTEM', { errorMsg: 'Temporary ID was not found in array', customEFObjId: customEFObj.id, temporaryId: customEFObj.temporaryId }); }*/ } } } } // Wait for all uploads to be successfully done and call callback only then (required to show uploaded documents in frontend) Helper.wait( 100 // ms to wait per loop , 100 // max nr loops , function() { // Check if all files were uploaded (100 loops * 100ms = 10sec max waiting time) if (fileUploadSuccessCounter>=nrFileUploads) return true; else return false; }, function() { // callbackPositiveCheck Helper.hideFullScreenProcessingBackdrop(); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(ceObj); }, function() { // callbackFinishedWithoutPositiveCallbackCheck Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Das hochladen der Dateien hat zu lange gedauert. Seite bitte neu laden.', 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITY', 'ERROR_SYSTEM', { ceId: ceObj.id }); } ); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITY', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { Helper.hideFullScreenProcessingBackdrop(); handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITY', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivate(callbackSuccess=null) { // ### Consistency checks // None // ### Prepare API var apiUrl=apiHost+'/consumption/entity/edit'; // !The keys have to equal the Java class fields! var postData={}; postData['pk_consumption_entities']=this.id; postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInISO8601Format(); //console.log('save post data >', postData); // ### Execute API let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { // Returns just saved CE object JSON Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITY', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); //if (data.status=='ok') { if ('pk_consumption_entities' in data && data.pk_consumption_entities!==null && data.pk_consumption_entities!==undefined && data.pk_consumption_entities!='') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); //Logger.log('info', 'admin_measure_edited', {page: 'settings/profile', data: data}); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITY', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITY', apiUrl, xhr, status, error, null, { json: jsonData }); }); } duplicate(nrOfDuplicates, callbackSuccess=null) { // Set Spinner Helper.showFullScreenProcessingBackdrop(); // Checks if (isNaN(nrOfDuplicates)) { Helper.showToastr('Fehler', 'Die Übergebene Anzahl ('+nrOfDuplicates+') ist keine Zahl.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } if (nrOfDuplicates<1) { Helper.showToastr('Fehler', 'Die Übergebene Anzahl ('+nrOfDuplicates+') muss >= 1 sein.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } if (nrOfDuplicates>9) { Helper.showToastr('Fehler', 'Die Übergebene Anzahl ('+nrOfDuplicates+') darf nicht >= 10 sein.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } // ### Prepare API var apiUrl=apiHost+'/consumption/entity/'+this.id+'/duplicate/'+nrOfDuplicates; // ### Execute API const tsStartApi=Date.now(); $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { // Returns just saved CE object JSON Logger.log('FRONTEND_CLIENT_API_DUPLICATE_CONSUMPTIONENTITY', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); Helper.hideFullScreenProcessingBackdrop(); //if ('pk_consumption_entities' in data && data.pk_consumption_entities!==null && data.pk_consumption_entities!==undefined && data.pk_consumption_entities!='') { if ('status' in data && data.status=='ok') { Helper.showToastr('Erfolg', 'Die Duplikate wurden angelegt.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Duplikate angelegt, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_DUPLICATE_CONSUMPTIONENTITY', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data }); } }} ).fail(function(xhr, status, error) { Helper.hideFullScreenProcessingBackdrop(); handleFailedApiCall('FRONTEND_CLIENT_API_DUPLICATE_CONSUMPTIONENTITY', apiUrl, xhr, status, error, null, { }); }); } static loadConsumptionEntityByConsumptionValueFromApi(consumptionValueId, callbackSuccessAry=null) { //Helper.showFullScreenProcessingBackdrop(); const tsStartApi=Date.now(); var apiUrl=apiHost+'/consumption/entities/consumption/value/'+consumptionValueId; $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { //console.log(dataFromApi); //Helper.hideFullScreenProcessingBackdrop(); if ('pk_consumption_entities' in dataFromApi && dataFromApi.pk_consumption_entities!==null) { Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY_BY_CONSUMPTIONVALUE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(new ConsumptionEntity(dataFromApi)); } } } else { Helper.showToastr('Fehler', 'Daten konnten nicht korrekt geladen werden.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY_BY_CONSUMPTIONVALUE', 'ERROR_SYSTEM_DATALOAD', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); } } }).fail(function(xhr, status, error){ Helper.hideFullScreenProcessingBackdrop(); handleFailedApiCall('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY_BY_CONSUMPTIONVALUE', apiUrl, xhr, status, error); }); } static createTimerangesAlert(consumptionValueTimerangeObjs) { // Check for gaps among timeranges consumptionValueTimerangeObjs.sort(function(a,b) { if (moment(a.timestampFrom).isAfter(moment(b.timestampFrom))) return 1; else return -1; }); //console.log(consumptionValueTimerangeObjs); //for (let trObj of consumptionValueTimerangeObjs) { for (let i=0; i90000000 || diffMilliSec<82800000) { // Summer/winter time change considered (90000000 ^= 25h; 86400000 ^= 24h; 82800000 ^= 23h) //return $(' Es existieren Lücken zwischen den Zeiträumen'); return ['Es existieren Lücken zwischen den Zeiträumen']; } } } return []; } static loadActiveConsumptionEntitesOfAccountFromApi(filterCEObj, callbackSuccessAry=null) { const tsStartApi=Date.now(); let ouIds=(!('oeIdsAry' in filterCEObj) || filterCEObj.oeIdsAry===null || filterCEObj.oeIdsAry.length==0 ? 'null' : filterCEObj.oeIdsAry.join(',')); var apiUrl=apiHost+'/consumption/entities' +'/accountId/'+userObj.accountObj.id +'/categoryId/'+(!('cecObj' in filterCEObj) || filterCEObj.cecObj===null ? '-1' : filterCEObj.cecObj.id) +'/ouIds/'+ouIds +'/timerange_from_unix/'+(!('tsFromUnixSec' in filterCEObj) || filterCEObj.tsFromUnixSec===null ? '-1' : filterCEObj.tsFromUnixSec) +'/timerange_to_unix/'+(!('tsToUnixSec' in filterCEObj) || filterCEObj.tsToUnixSec===null ? '-1' : filterCEObj.tsToUnixSec) ; if (userObj.accountObj.id===undefined || userObj.accountObj.id===null) { Helper.showToastr('Fehler', 'Account ID fehlt.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIES', 'ERROR_SYSTEM_PARAMETER', { apiUrl: apiUrl }); return; } $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { //console.log(dataFromApi); if (dataFromApi!==null && Array.isArray(dataFromApi)) { Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIES', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let ces=[]; for (let ce of dataFromApi) { let ceObj=new ConsumptionEntity(ce); if (ceObj.isActive()) ces.push(ceObj); } //console.log(ces); if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(ces); } } } else { Helper.showToastr('Fehler', 'Daten konnten nicht korrekt geladen werden.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIES', 'ERROR_SYSTEM_DATALOAD', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); } } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIES', apiUrl, xhr, status, error); }); } // index is zero-based getCustomField(index) { // Copy CustomFieldSpecs in separate array for sorting (avpoids sorting the original array) let cfsAry=this.consumptionEntityCategory.getSortedCustomFieldSpecs(); let counter=0; for (let cfs of cfsAry) { //if (cfs.showInVETable===true) { if (index==counter) { // Get Custom Field Value let cfv=null; for (let customField of this.customFieldValue) { if (customField.id==cfs.id) { cfv=customField; break; } } // Create return obj let returnObj={ name: cfs.name, valueStr: null }; if (cfv!==null && cfv.value!==null) { //console.log(cfv); if (cfs.type=='date') returnObj.valueStr=moment(cfv.value).format('DD.MM.YYYY'); else returnObj.valueStr=cfv.value; } else { returnObj.valueStr=''; } return returnObj; } else counter++; //} } return null; } getCustomFieldValuesHTMLString() { // Sort array var parent=this; this.customFieldValue.sort(function(a,b) { let aSpec=parent.consumptionEntityCategory.getCustomFieldSpecObjById(a.id); let bSpec=parent.consumptionEntityCategory.getCustomFieldSpecObjById(b.id); if (aSpec!==null && bSpec!==null) { if (aSpec.name > bSpec.name) return 1; else if (aSpec.name < bSpec.name) return -1; else return 0; } else return 0; }); let str=""; for (let customField of this.customFieldValue) { if (customField.value!==null) { let customFieldSpec=this.consumptionEntityCategory.getCustomFieldSpecObjById(customField.id); if (customFieldSpec!==null && customFieldSpec.showInVETable===true) { if (str!="") str=str+"
    "; str=str+customFieldSpec.name+" = ";//+customField.value; if (customFieldSpec.type=='date') str+=moment(customField.value).format('DD.MM.YYYY'); else str+=customField.value; } else { Logger.log('FRONTEND_CLIENT_CONSISTENCECHECK', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'CustomFieldValue ID of CE was not found among CustomFieldSpec of CEC', customFieldValueId: customField.id }); } } } return str; } static loadConsumptionEntityFromApi(ceId, callbackSuccessAry=null) { Helper.showFullScreenProcessingBackdrop(); const tsStartApi=Date.now(); var apiUrl=apiHost+'/consumption/entity/entityId/'+ceId; if (userObj.accountObj.id===undefined || userObj.accountObj.id===null) { Helper.showToastr('Fehler', 'Account ID fehlt.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY', 'ERROR_SYSTEM_PARAMETER', { apiUrl: apiUrl }); Helper.hideFullScreenProcessingBackdrop(); return; } if (ceId===null) { Helper.showToastr('Fehler', 'Verbrauchs-Entität ID fehlt.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY', 'ERROR_SYSTEM_PARAMETER', { apiUrl: apiUrl }); Helper.hideFullScreenProcessingBackdrop(); return; } $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { Helper.hideFullScreenProcessingBackdrop(); //console.log(dataFromApi); if (dataFromApi!==null) { Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let ceObj=new ConsumptionEntity(dataFromApi); //console.log(ceObj); if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(ceObj); } } } else { Helper.showToastr('Fehler', 'Daten konnten nicht korrekt geladen werden.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY', 'ERROR_SYSTEM_DATALOAD', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); } } }).fail(function(xhr, status, error){ Helper.hideFullScreenProcessingBackdrop(); handleFailedApiCall('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITY', apiUrl, xhr, status, error); }); } getConsumptionEntities2HierarchiesById(e2hId) { for (let e2h of this.entity2hierarchy) { if (e2h.id==e2hId) return e2h; } return null; } getActiveConsumptionEntities2HierarchiesByConsumptionHierarchyId(cvhId) { let e2hObj=null; for (let e2h of this.entity2hierarchy) { if (e2h.fkConsumptionHierarchies==cvhId && e2h.isActive()) { if (e2hObj!==null) { //throw Error('Multiple active ConsumptionEntity2Hierarchy objects found'); // Only exactly one e2h object is supposed to be found Logger.log('FRONTEND_CLIENT_CONSISTENCECHECK', 'ERROR_SYSTEM', { errorMsg: 'Multiple active ConsumptionEntity2Hierarchy objects found', cvhId: cvhId }); } e2hObj=e2h; } } return e2hObj; } /* getCurrentCustomConsumptionEmissionFactor(type) { // type = CO2, CH4, N2O (CHANGES HERE NEED TO BE REFLECTED IN BACKEND ALSO) let customEFReturn=null; let timestampNow=moment(); for (let e2h of this.entity2hierarchy) { if (e2h.isActive()) { for (let customEF of e2h.customEFs) { if (customEF.type==type && customEF.isActive()) { if (customEF.timestampTo===null) { if (moment(customEF.timestampFrom).isBefore(timestampNow) || moment(customEF.timestampFrom).isSame(timestampNow)) { customEFReturn=customEF; break; } } else if ((moment(customEF.timestampFrom).isBefore(timestampNow) || moment(customEF.timestampFrom).isSame(timestampNow)) && (moment(customEF.timestampTo).isAfter(timestampNow) || moment(customEF.timestampTo).isSame(timestampNow))) { customEFReturn=customEF; break; } } } } } return customEFReturn; } */ } class ConsumptionEntityFilter { constructor(cecObj, oeIdsAry) { this.cecObj=null; if (cecObj!==undefined) this.cecObj=cecObj; this.oeIdsAry=null; if (oeIdsAry!==undefined) this.oeIdsAry=oeIdsAry; } } class ConsumptionValueTimerangeFilter { constructor(ceObj, timerangeFrom, timerangeTo, order) { this.ceObj=null; if (ceObj!==undefined) this.ceObj=ceObj; this.timerangeFrom=null; if (timerangeFrom!==undefined) this.timerangeFrom=timerangeFrom; // Moment object this.timerangeTo=null; if (timerangeTo!==undefined) this.timerangeTo=timerangeTo; // Moment object this.order=null; if (order!==undefined) this.order=order; } } class ConsumptionHierarchy { constructor(apiObj, consumptionEntityCategory=null) { //console.log(apiObj); this.id=null; if (apiObj.pk_consumption_hierarchies!==undefined) this.id=apiObj.pk_consumption_hierarchies; //this.consumptionEntityCategory=null; if (apiObj.consumption_entity_category!==undefined && apiObj.consumption_entity_category!==null) this.consumptionEntityCategory=new ConsumptionEntityCategory(apiObj.consumption_entity_category); this.consumptionEntityCategory=consumptionEntityCategory; this.level1NodeId=null; if (apiObj.level1_node_id!==undefined) this.level1NodeId=apiObj.level1_node_id; this.level2NodeId=null; if (apiObj.level2_node_id!==undefined) this.level2NodeId=apiObj.level2_node_id; this.level3NodeId=null; if (apiObj.level3_node_id!==undefined) this.level3NodeId=apiObj.level3_node_id; this.level1=null; if (apiObj.level1!==undefined) this.level1=apiObj.level1; this.level2=null; if (apiObj.level2!==undefined) this.level2=apiObj.level2; this.level3=null; if (apiObj.level3!==undefined) this.level3=apiObj.level3; this.unit=null; if (apiObj.unit!==undefined) this.unit=apiObj.unit; this.scope=null; if (apiObj.scope!==undefined) this.scope=apiObj.scope; /* this.entity2hierarchy=[]; if (apiObj.consumption_entity2hierarchies!==undefined && apiObj.consumption_entity2hierarchies!==null) { for (let entity2hierarchy of apiObj.consumption_entity2hierarchies) { this.entity2hierarchy.push(new ConsumptionEntity2Hierarchy(entity2hierarchy)); } } */ /* this.emissionFactors=[]; if (apiObj.consumption_emissionfactors!==undefined && apiObj.consumption_emissionfactors!==null) { for (let ef of apiObj.consumption_emissionfactors) { this.emissionFactors.push(new ConsumptionEF(ef, this)); } } */ this.currentDefaultEF_CO2=null; if (apiObj.currentDefaultConsumptionEmissionFactorCO2!==undefined && apiObj.currentDefaultConsumptionEmissionFactorCO2!==null) this.currentDefaultEF_CO2=new ConsumptionEF(apiObj.currentDefaultConsumptionEmissionFactorCO2, this); this.currentDefaultEF_CH4=null; if (apiObj.currentDefaultConsumptionEmissionFactorCH4!==undefined && apiObj.currentDefaultConsumptionEmissionFactorCH4!==null) this.currentDefaultEF_CH4=new ConsumptionEF(apiObj.currentDefaultConsumptionEmissionFactorCH4, this); this.currentDefaultEF_N2O=null; if (apiObj.currentDefaultConsumptionEmissionFactorN2O!==undefined && apiObj.currentDefaultConsumptionEmissionFactorN2O!==null) this.currentDefaultEF_N2O=new ConsumptionEF(apiObj.currentDefaultConsumptionEmissionFactorN2O, this); this.currentDefaultEF_CO2E=null; if (apiObj.currentDefaultConsumptionEmissionFactorCO2E!==undefined && apiObj.currentDefaultConsumptionEmissionFactorCO2E!==null) this.currentDefaultEF_CO2E=new ConsumptionEF(apiObj.currentDefaultConsumptionEmissionFactorCO2E, this); this.customFieldSpecs=[]; if (apiObj.customFieldSpecs!==undefined && apiObj.customFieldSpecs!==null) { for (let customFieldSpec of apiObj.customFieldSpecs) { this.customFieldSpecs.push(new ConsumptionCustomFieldSpecCVH(customFieldSpec)); } } this.customAutoCalc=null; if (apiObj.customAutoCalc!==undefined && apiObj.customAutoCalc!==null) { /* for (let customFieldSpec of apiObj.customAutoCalcs) { let ccac=new ConsumptionCustomAutoCalcCVH(customFieldSpec, this); if (!ccac.checkIfCustomFieldsExistAndAreNumbers()) { Logger.log('FRONTEND_CLIENT', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Custom field ID given in automatic caluclation formula does not exist', cecId: this.id }); Helper.showToastr('Fehler', 'Inkonsistente Konfiguration - Bitte Adminsitrator benachrichtigen.', 'error'); throw Error('Custom field ID given in automatic caluclation formula does not exist (cecId: '+this.id+')'); } this.customAutoCalcs.push(ccac); } */ let ccac=new ConsumptionCustomAutoCalcCVH(apiObj.customAutoCalc, this); if (!ccac.checkIfCustomFieldsExistAndAreNumbers()) { Logger.log('FRONTEND_CLIENT', 'ERROR_SYSTEM_DATA_INCONSISTENT', { errorMsg: 'Custom field ID given in automatic caluclation formula does not exist', cecId: this.id }); Helper.showToastr('Fehler', 'Inkonsistente Konfiguration - Bitte Adminsitrator benachrichtigen.', 'error'); throw Error('Custom field ID given in automatic caluclation formula does not exist (cecId: '+this.id+')'); } this.customAutoCalc=ccac; } this.timestampArchived=null; if (apiObj.timestamp_archived!==undefined && apiObj.timestamp_archived!==null) this.timestampArchived=apiObj.timestamp_archived; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; else if (this.consumptionEntityCategory!==null && !this.consumptionEntityCategory.isActive()) active=false; return active; } doesAutomaticCalcExist() { if (this.customAutoCalc!==null && this.customAutoCalc.timestampDeactivated===null) return true; else return false; } /* getCurrentDefaultEF(type) { // Sort EFs ascending by timestampFrom this.emissionFactors.sort(function(a,b){ if (Helper.parseTimestampToUnixTimestampInMillis(a.timestampFrom) > Helper.parseTimestampToUnixTimestampInMillis(b.timestampFrom)) return 1; else if (Helper.parseTimestampToUnixTimestampInMillis(a.timestampFrom) < Helper.parseTimestampToUnixTimestampInMillis(b.timestampFrom)) return -1; else return 0; }); // Select current EF let currentEF=null; for (let ef of this.emissionFactors) { if (ef.type==type && ef.isActive() && (ef.timestampFrom==null || Helper.parseTimestampToUnixTimestampInMillis(ef.timestampFrom) <= moment().tz('Europe/Berlin').unix())) { currentEF=ef; } } return currentEF; } */ } class ConsumptionEntity2Hierarchy { constructor(apiObj, consumptionEntity=null) { //console.log(apiObj); this.id=null; if (apiObj.pk_consumption_entities2hierarchies!==undefined) this.id=apiObj.pk_consumption_entities2hierarchies; //this.consumptionEntity=null; if (apiObj.consumption_entity!==undefined && apiObj.consumption_entity!==null) this.consumptionEntity=new ConsumptionEntity(apiObj.consumption_entity); this.consumptionEntity=consumptionEntity; //this.consumptionHierarchy=null; if (apiObj.consumption_hierarchy!==undefined && apiObj.consumption_hierarchy!==null) this.consumptionHierarchy=new ConsumptionHierarchy(apiObj.consumption_hierarchy); this.fkConsumptionHierarchies=null; if (apiObj.fk_consumption_hierarchies!==undefined) this.fkConsumptionHierarchies=apiObj.fk_consumption_hierarchies; //this.eoc=null; if (apiObj.element_oe_combi!==undefined && apiObj.element_oe_combi!==null) this.eoc=new ElementOuCombi(apiObj.element_oe_combi); this.entity2hierarchy2eocs=[]; if (apiObj.consumption_entity2hierarchy2eocs!==undefined && apiObj.consumption_entity2hierarchy2eocs!==null) { for (let x of apiObj.consumption_entity2hierarchy2eocs) { this.entity2hierarchy2eocs.push(new ConsumptionEntity2Hierarchy2EOC(x, this)); } } this.entity2hierarchy2eoc_co2s=[]; if (apiObj.consumption_entity2hierarchy2eocs_co2!==undefined && apiObj.consumption_entity2hierarchy2eocs_co2!==null) { for (let x of apiObj.consumption_entity2hierarchy2eocs_co2) { this.entity2hierarchy2eoc_co2s.push(new ConsumptionEntity2Hierarchy2EOC_CO2(x, this)); } } this.customEFs=[]; if (apiObj.consumption_custom_emissionsfactors!==undefined && apiObj.consumption_custom_emissionsfactors!==null) { for (let x of apiObj.consumption_custom_emissionsfactors) { this.customEFs.push(new ConsumptionCustomEF(x, this)); } } this.currentCustomEF_CO2=null; if (apiObj.currentCustomConsumptionEmissionFactorCO2!==undefined && apiObj.currentCustomConsumptionEmissionFactorCO2!==null) this.currentCustomEF_CO2=new ConsumptionCustomEF(apiObj.currentCustomConsumptionEmissionFactorCO2, this); this.currentCustomEF_CH4=null; if (apiObj.currentCustomConsumptionEmissionFactorCH4!==undefined && apiObj.currentCustomConsumptionEmissionFactorCH4!==null) this.currentCustomEF_CH4=new ConsumptionCustomEF(apiObj.currentCustomConsumptionEmissionFactorCH4, this); this.currentCustomEF_N2O=null; if (apiObj.currentCustomConsumptionEmissionFactorN2O!==undefined && apiObj.currentCustomConsumptionEmissionFactorN2O!==null) this.currentCustomEF_N2O=new ConsumptionCustomEF(apiObj.currentCustomConsumptionEmissionFactorN2O, this); this.currentCustomEF_CO2E=null; if (apiObj.currentCustomConsumptionEmissionFactorCO2E!==undefined && apiObj.currentCustomConsumptionEmissionFactorCO2E!==null) this.currentCustomEF_CO2E=new ConsumptionCustomEF(apiObj.currentCustomConsumptionEmissionFactorCO2E, this); this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; else if (this.consumptionEntity!==null && !this.consumptionEntity.isActive()) active=false; if (this.fkConsumptionHierarchies!==null && this.consumptionEntity!==null && this.consumptionEntity.consumptionEntityCategory!==null) { for (let cvh of this.consumptionEntity.consumptionEntityCategory.consumptionHierarchies) { if (cvh.id==this.fkConsumptionHierarchies) { if (!cvh.isActive()) active=false; break; } } } return active; } createDeepCopy() { let e2h=new ConsumptionEntity2Hierarchy({}); e2h.id=this.id; e2h.consumptionEntity=this.consumptionEntity; e2h.fkConsumptionHierarchies=this.fkConsumptionHierarchies; e2h.entity2hierarchy2eocs=[]; for (let e2hEoc of this.entity2hierarchy2eocs) { e2h.entity2hierarchy2eocs.push(e2hEoc.createDeepCopy(e2h)); } e2h.entity2hierarchy2eoc_co2s=[]; for (let e2hEoc_co2 of this.entity2hierarchy2eoc_co2s) { e2h.entity2hierarchy2eoc_co2s.push(e2hEoc_co2.createDeepCopy(e2h)); } e2h.customEFs=[]; for (let customEF of this.customEFs) { e2h.customEFs.push(customEF.createDeepCopy(e2h)); } e2h.currentCustomEF_CO2=this.currentCustomEF_CO2; e2h.currentCustomEF_CH4=this.currentCustomEF_CH4; e2h.currentCustomEF_N2O=this.currentCustomEF_N2O; e2h.currentCustomEF_CO2E=this.currentCustomEF_CO2E; e2h.timestampDeactivated=this.timestampDeactivated; e2h.timestampCreation=this.timestampCreation; return e2h; } getCurrentCustomConsumptionEmissionFactor(type) { // type = CO2, CH4, N2O (CHANGES HERE NEED TO BE REFLECTED IN BACKEND ALSO) let customEFReturn=null; let timestampNow=moment(); if (this.isActive()) { for (let customEF of this.customEFs) { if (customEF.type==type && customEF.isActive()) { if (customEF.timestampTo===null) { if (moment(customEF.timestampFrom).isBefore(timestampNow) || moment(customEF.timestampFrom).isSame(timestampNow)) { customEFReturn=customEF; break; } } else if ((moment(customEF.timestampFrom).isBefore(timestampNow) || moment(customEF.timestampFrom).isSame(timestampNow)) && (moment(customEF.timestampTo).isAfter(timestampNow) || moment(customEF.timestampTo).isSame(timestampNow))) { customEFReturn=customEF; break; } } } } return customEFReturn; } existsConsumptionValue(cvtObj) { // Get CV (if exists) let cvObj=null; for (let cv of cvtObj.values) { if (cv.isActive()) { if (cv.fkConsumptionEntities2Hierarchies==this.id) { cvObj=cv; break; } } } if (cvObj===null) return false; else if (cvObj.consumption!==null) return true; else return false; } } class ConsumptionEntity2Hierarchy2EOC { constructor(apiObj, entity2hierarchy=null) { this.id=null; if (apiObj.pk_consumption_entities2hierarchies2eoc!==undefined) this.id=apiObj.pk_consumption_entities2hierarchies2eoc; //this.entity2hierarchy=null; if (apiObj.consumption_entity2hierarchy!==undefined && apiObj.consumption_entity2hierarchy!==null) this.entity2hierarchy=new ConsumptionEntity2Hierarchy(apiObj.consumption_entity2hierarchy); this.entity2hierarchy=entity2hierarchy; //this.eoc=null; if (apiObj.element_oe_combi!==undefined && apiObj.element_oe_combi!==null) this.eoc=new ElementOuCombi(apiObj.element_oe_combi); this.fkEoc=null; if (apiObj.fk_elements_organizational_units!==undefined && apiObj.fk_elements_organizational_units!==null) this.fkEoc=apiObj.fk_elements_organizational_units; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } isActive() { var active=true; //console.log('this.eoc', this.eoc); let eocObj=null; if (this.fkEoc!==null) eocObj=ElementOuCombi.getElementOuCombiById(this.fkEoc); if (this.timestampDeactivated!==null) active=false; else if (this.entity2hierarchy!==null && !this.entity2hierarchy.isActive()) active=false; //else if (this.eoc!==null && !this.eoc.isActive()) active=false; //else if (this.eoc!==null && !ElementOuCombi.isActive(this.eoc).active) active=false; //getElementOuCombiById(id) else if (eocObj!==null && !ElementOuCombi.isActive(eocObj).active) active=false; return active; } createDeepCopy(e2hObj=null) { let ce2hEoc=new ConsumptionEntity2Hierarchy2EOC({}); ce2hEoc.id=this.id; ce2hEoc.entity2hierarchy=e2hObj; ce2hEoc.fkEoc=this.fkEoc; ce2hEoc.timestampDeactivated=this.timestampDeactivated; ce2hEoc.timestampCreation=this.timestampCreation; return ce2hEoc; } } class ConsumptionEntity2Hierarchy2EOC_CO2 { constructor(apiObj, entity2hierarchy=null) { this.id=null; if (apiObj.pk_consumption_entities2hierarchies2eoc_co2!==undefined) this.id=apiObj.pk_consumption_entities2hierarchies2eoc_co2; //this.entity2hierarchy=null; if (apiObj.consumption_entity2hierarchy!==undefined && apiObj.consumption_entity2hierarchy!==null) this.entity2hierarchy=new ConsumptionEntity2Hierarchy(apiObj.consumption_entity2hierarchy); this.entity2hierarchy=entity2hierarchy; //this.eoc=null; if (apiObj.element_oe_combi!==undefined && apiObj.element_oe_combi!==null) this.eoc=new ElementOuCombi(apiObj.element_oe_combi); this.fkEoc=null; if (apiObj.fk_elements_organizational_units!==undefined && apiObj.fk_elements_organizational_units!==null) this.fkEoc=apiObj.fk_elements_organizational_units; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } isActive() { var active=true; let eocObj=null; if (this.fkEoc!==null) eocObj=ElementOuCombi.getElementOuCombiById(this.fkEoc); if (this.timestampDeactivated!==null) active=false; else if (this.entity2hierarchy!==null && !this.entity2hierarchy.isActive()) active=false; //else if (this.eoc!==null && !this.eoc.isActive()) active=false; //else if (this.eoc!==null && !ElementOuCombi.isActive(this.eoc).active) active=false; else if (eocObj!==null && !ElementOuCombi.isActive(eocObj).active) active=false; return active; } createDeepCopy(e2hObj=null) { let ce2hEoc=new ConsumptionEntity2Hierarchy2EOC_CO2({}); ce2hEoc.id=this.id; ce2hEoc.entity2hierarchy=e2hObj; ce2hEoc.fkEoc=this.fkEoc; ce2hEoc.timestampDeactivated=this.timestampDeactivated; ce2hEoc.timestampCreation=this.timestampCreation; return ce2hEoc; } } class ConsumptionValuesTimerange { constructor(apiObj, consumptionEntity=null) { //console.log('ConsumptionValuesTimerange', apiObj); this.id=null; if (apiObj.pk_consumption_values_timeranges!==undefined) this.id=apiObj.pk_consumption_values_timeranges; //this.consumptionEntity=null; if (apiObj.consumption_entity!==undefined && apiObj.consumption_entity!==null) this.consumptionEntity=new ConsumptionEntity(apiObj.consumption_entity); this.consumptionEntity=consumptionEntity; this.values=[]; if (apiObj.consumption_values!==undefined && apiObj.consumption_values!==null) { for (let value of apiObj.consumption_values) { this.values.push(new ConsumptionValue(value, this)); } } this.timestampFrom=null; if (apiObj.timestamp_from!==undefined) this.timestampFrom=apiObj.timestamp_from; this.timestampTo=null; if (apiObj.timestamp_to!==undefined) this.timestampTo=apiObj.timestamp_to; this.automaticallyCreated=null; if (apiObj.automaticallyCreated!==undefined) this.automaticallyCreated=apiObj.automaticallyCreated; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } static createNewEmptyConsumptionValuesTimerange(consumptionEntityObj) { let cvt=new ConsumptionValuesTimerange({}, consumptionEntityObj); return cvt; } replaceConsumptionValueObj(newCvObj) { for (let i = 0; i < this.values.length; i++) { if (this.values[i].id==newCvObj.id) { newCvObj.timerange=this; this.values.splice(i, 1); this.values.push(newCvObj); break; } } } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; else if (this.consumptionEntity!==null && !this.consumptionEntity.isActive()) active=false; return active; } isNew() { if (this.id===null) return true; else return false; } createDeepCopy(ceObj=null) { let cvt=new ConsumptionValuesTimerange({}); cvt.id=this.id; if (ceObj!==null) cvt.consumptionEntity=ceObj; else cvt.consumptionEntity=this.consumptionEntity; cvt.values=[]; for (let value of this.values) { cvt.values.push(value.createDeepCopy(cvt)); } cvt.timestampFrom=this.timestampFrom; cvt.timestampTo=this.timestampTo; cvt.timestampDeactivated=this.timestampDeactivated; cvt.timestampCreation=this.timestampCreation; return cvt; } getActiveChildValues() { let activeConsumptionValues=[]; for (let cv of this.values) { if (cv.isActive()) activeConsumptionValues.push(cv); } return activeConsumptionValues; } static loadActiveConsumptionValueTimerangesOfCEFromApi(filterCVTimerangeObj, callbackSuccessAry=null) { // Quality checks if (filterCVTimerangeObj===undefined || filterCVTimerangeObj===null) { Helper.showToastr('Fehler', 'Filter Objekt fehlt.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM_PARAMETER', { errorMsg: 'CVT filter object missing' }); return; } if (userObj.accountObj===undefined || userObj.accountObj===null || userObj.accountObj.id===undefined || userObj.accountObj.id===null) { Helper.showToastr('Fehler', 'Account ID fehlt.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM_PARAMETER', { errorMsg: 'Account object or ID missing' }); return; } if (filterCVTimerangeObj.ceObj===undefined || filterCVTimerangeObj.ceObj===null || filterCVTimerangeObj.ceObj.id===undefined || filterCVTimerangeObj.ceObj.id===null) { Helper.showToastr('Fehler', 'Verbrauchs-Entität ID fehlt.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM_PARAMETER', { errorMsg: 'CE object or ID missing' }); return; } // Assemble API url const tsStartApi=Date.now(); let timerangeFrom=(filterCVTimerangeObj.timerangeFrom===null ? 0 : filterCVTimerangeObj.timerangeFrom.unix()); let timerangeTo=(filterCVTimerangeObj.timerangeTo===null ? 2000000000 : filterCVTimerangeObj.timerangeTo.unix()); // 2000000000 as integer would overflow otherwise let order=filterCVTimerangeObj.order; var apiUrl=apiHost+'/consumption/entity/entityId/'+filterCVTimerangeObj.ceObj.id+'/timeranges/accountId/'+userObj.accountObj.id +'/timerangeFromUnixSec/'+timerangeFrom +'/timerangeToUnixSec/'+timerangeTo +'/order/'+order ; // Call API $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { //console.log(dataFromApi); if (dataFromApi!==null && Array.isArray(dataFromApi)) { Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIYTIMERANGES', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let cvts=[]; for (let cvt of dataFromApi) { //console.log('loadActiveCVTFromAPI cvt', cvt); let cvtObj=new ConsumptionValuesTimerange(cvt, filterCVTimerangeObj.ceObj); if (cvtObj.isActive()) cvts.push(cvtObj); } //console.log(cvts); if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(cvts); } } } else { Helper.showToastr('Fehler', 'Daten konnten nicht korrekt geladen werden.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM_DATALOAD', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); } } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITIYTIMERANGES', apiUrl, xhr, status, error); }); } saveNew(callbackSuccess=null, ceObj=null) { //console.log(this); // Set Spinner Helper.showFullScreenProcessingBackdrop(); // ### Consistency checks if (this.consumptionEntity===null || this.consumptionEntity===undefined) { Helper.showToastr('Fehler', 'Die Verbrauchs-Entität ist nicht gesetzt.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } if (this.timestampFrom===null || this.timestampFrom===undefined) { Helper.showToastr('Fehler', 'Das Zeitraum-Datum "von" fehlt.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } if (this.timestampTo===null || this.timestampTo===undefined) { Helper.showToastr('Fehler', 'Das Zeitraum-Datum "bis" fehlt.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } if (moment(this.timestampTo).isBefore(moment(this.timestampFrom))) { Helper.showToastr('Fehler', '"Zeitraum bis" darf zeitlich nicht vor "Zeitraum von" liegen.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } let trAry=[]; if (ceObj!==null) { trAry.push(this); // Check for overlaps for (let cvtObj of ceObj.timeranges) { // For each existing timerange ... if (cvtObj.isActive()) { if (Helper.isOverlappingIncl( moment(cvtObj.timestampFrom) , moment(cvtObj.timestampTo) , moment(this.timestampFrom) , moment(this.timestampTo)) ) { Helper.showToastr('Fehler', 'Eine Überlappung mit einem vorhandenen Zeitraum ist nicht erlaubt.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } trAry.push(cvtObj); } } } let parent=this; let fApiCall=function() { // ### Prepare API var apiUrl=apiHost+'/consumption/entity/entityId/'+parent.consumptionEntity.id+'/timerange/new'; // !The keys have to equal the Java class fields! var postData={}; let valuesByTempId={}; postData['timestamp_from']=parent.timestampFrom; //moment.unix(this.timestampFrom).tz('Europe/Berlin').format(); postData['timestamp_to']=parent.timestampTo; //moment.unix(this.timestampTo).tz('Europe/Berlin').format(); postData['consumption_values']=[]; for (let value of parent.values) { let tempId=moment().valueOf()+'_'+Helper.getRandomString(10); valuesByTempId[tempId]=value; let valueJson=value.getApiJsonObj(); valueJson['temporary_id']=tempId; //valueJson['usersCreator']={ pk_users: userObj.id }; //if (value.consumption!==null) { postData['consumption_values'].push(valueJson); //} } //console.log('saveNew post data >', postData); // ### Execute API let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { // Returns just saved CE object JSON Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITIYTIMERANGES', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if ('pk_consumption_values_timeranges' in data && data.pk_consumption_values_timeranges!==null && data.pk_consumption_values_timeranges!==undefined && data.pk_consumption_values_timeranges!='') { Helper.showToastr('Erfolg', 'Neuer Verbrauchswert-Zeitraum wurde gespeichert.', 'success'); //console.log(data); let cvtObj=new ConsumptionValuesTimerange(data); // Upload files fileUploadSuccessCounter=0; let nrFileUploads=0; for (let cvObj of cvtObj.values) { // Iterate each CV of just stored CVT if (cvObj.isActive()) { //for (let cvfObj of cvObj.files) { // if (cvfObj.isActive()) { //console.log(cvObj); // Find files to be uploaded in frontend data if (cvObj.temporaryId in valuesByTempId) { let cvObjFrontend=valuesByTempId[cvObj.temporaryId]; //console.log('#### cvObjFrontend #####', cvObjFrontend); for (let file of cvObjFrontend.files) { if (file.isActive()) { //console.log(file.tempFileObj); if ('tempFileObj' in file) { // Set upload destination file.tempFileObj.fileinput().data().fileinput.uploadUrl=function() { return apiHost+'/consumption/value/file/upload/'+cvObj.id; }; // Upload if (file.tempFileObj.fileinput('getFilesCount')>0) { nrFileUploads++; file.tempFileObj.fileinput('upload'); } } } } } else { // Should not happen Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM', { errorMsg: 'Temporary ID was not found in array', cvObj: cvObj.id, temporaryId: cvObj.temporaryId }); } // } //} } } // Wait for all uploads to be successfully done and call callback only then (required to show uploaded documents in frontend) Helper.wait( 100 // ms to wait per loop , 100 // max nr loops , function() { // Check if all files were uploaded (100 loops * 100ms = 10sec max waiting time) if (fileUploadSuccessCounter>=nrFileUploads) return true; else return false; }, function() { // callbackPositiveCheck Helper.hideFullScreenProcessingBackdrop(); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(cvtObj); }, function() { // callbackFinishedWithoutPositiveCallbackCheck Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Das hochladen der Dateien hat zu lange gedauert. Seite bitte neu laden.', 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM', { cvtId: cvtObj.id }); } ); } else { Helper.hideFullScreenProcessingBackdrop(); Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); Helper.showToastr('Fehler', 'Fehler beim Speichern des Verbrauchswert-Zeitraums: '+data.msg, 'error'); } }} ).fail(function(xhr, status, error) { Helper.hideFullScreenProcessingBackdrop(); handleFailedApiCall('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITIYTIMERANGES', apiUrl, xhr, status, error, null, { json: jsonData }); }); } //console.log('trAry', trAry); if (trAry.length) { // Check for gaps let trAlertAry=ConsumptionEntity.createTimerangesAlert(trAry); if (trAlertAry.length) { Helper.hideFullScreenProcessingBackdrop(); Helper.confirmModal('Nach dem Hinzufügen dieses Zeitraums wird eine Lücke existieren. Soll der Zeitraum wirklich in dieser Form hinzugefügt werden?' , 'Zeitraum speichern' , function() { Helper.showFullScreenProcessingBackdrop(); fApiCall(); } , 'Zeitraum speichern' , true , function () { //Helper.showToastr('Fehler', 'Eine Überlappung mit einem vorhandenen Zeitraum ist nicht erlaubt.', 'error'); return; } ); } else { fApiCall(); } } else { fApiCall(); } } save(callbackSuccess=null, ceObj=null) { //console.log(this); // Set Spinner Helper.showFullScreenProcessingBackdrop(); // ### Consistency checks if (this.consumptionEntity===null || this.consumptionEntity===undefined) { Helper.showToastr('Fehler', 'Die Verbrauchs-Entität ist nicht gesetzt.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } if (this.timestampFrom===null || this.timestampFrom===undefined) { Helper.showToastr('Fehler', 'Das Zeitraum-Datum "von" fehlt.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } if (this.timestampTo===null || this.timestampTo===undefined) { Helper.showToastr('Fehler', 'Das Zeitraum-Datum "bis" fehlt.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } if (moment(this.timestampTo).isBefore(moment(this.timestampFrom))) { Helper.showToastr('Fehler', '"Zeitraum bis" darf zeitlich nicht vor "Zeitraum von" liegen.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } if (ceObj!==null) { for (let cvtObj of ceObj.timeranges) { if (cvtObj.isActive() && cvtObj.id!=this.id) { if (Helper.isOverlappingIncl( moment(cvtObj.timestampFrom) , moment(cvtObj.timestampTo) , moment(this.timestampFrom) , moment(this.timestampTo)) ) { Helper.showToastr('Fehler', 'Eine Überlappung mit einem vorhandenen Zeitraum ist nicht erlaubt.', 'error'); Helper.hideFullScreenProcessingBackdrop(); return; } } } } // TODO ... /* let mandatoryFieldsMissing=[]; for (let cfs of this.consumptionEntityCategory.customFieldSpecs) { if (cfs.mandatory===true) { for (let cfv of this.customFieldValue) { if (cfs.id==cfv.id && (cfv.value===null || cfv.value=='')) { mandatoryFieldsMissing.push(cfs); break; } } } } if (mandatoryFieldsMissing.length > 0) { let missingFieldNames=''; for (let cfs of mandatoryFieldsMissing) { if (missingFieldNames!='') missingFieldNames+=', '; missingFieldNames+=cfs.name; } Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Folgende Mussfelder sind nicht befüllt: '+missingFieldNames, 'error'); return; } */ // ### Prepare API var apiUrl=apiHost+'/consumption/entity/timerange/edit'; // !The keys have to equal the Java class fields! var postData={}; let valuesByTempId={}; let valuesByPersistedId={}; postData['pk_consumption_values_timeranges']=this.id; postData['timestamp_from']=this.timestampFrom; // Later change of timerange is not allowed postData['timestamp_to']=this.timestampTo; // Later change of timerange is not allowed postData['consumption_values']=[]; for (let value of this.values) { let valueJson=value.getApiJsonObj(); if (value.id===null) { // New CV object (Store some ID to link upload file to this CV object) let tempId=moment().valueOf()+'_'+Helper.getRandomString(10); valuesByTempId[tempId]=value; valueJson['temporary_id']=tempId; } else { valuesByPersistedId[value.id]=value; } //valueJson['usersCreator']={ pk_users: userObj.id }; //if (value.consumption!==null) { postData['consumption_values'].push(valueJson); //} } //console.log('save post data >', postData); // ### Execute API let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { // Returns just saved CE object JSON Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITIYTIMERANGES', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if ('pk_consumption_values_timeranges' in data && data.pk_consumption_values_timeranges!==null && data.pk_consumption_values_timeranges!==undefined && data.pk_consumption_values_timeranges!='') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); //console.log(data); let cvtObj=new ConsumptionValuesTimerange(data); // Upload files fileUploadSuccessCounter=0; let nrFileUploads=0; for (let cvObj of cvtObj.values) { // Iterate each CV of just stored CVT if (cvObj.isActive()) { //for (let cvfObj of cvObj.files) { // if (cvfObj.isActive()) { //console.log(cvObj); // Find files to be uploaded in frontend data let cvObjFrontend=null; if (cvObj.temporaryId in valuesByTempId) { // New CVs cvObjFrontend=valuesByTempId[cvObj.temporaryId]; } else if (cvObj.id in valuesByPersistedId) { // Existing CVs cvObjFrontend=valuesByPersistedId[cvObj.id]; /* for (let value of this.values) { if (value.id!==null && value.id==cvObj.id) { cvObjFrontend=value; } } */ } else { // Should not happen Logger.log('FRONTEND_CLIENT_CONSISTENCECHECK', 'ERROR_SYSTEM', { errorMsg: 'No matching CV object from frontend found', cvObjId: cvObj.id, temporaryId: cvObj.temporaryId }); throw Error('No matching CV object from frontend found'); } //console.log('#### cvObjFrontend #####', cvObjFrontend); for (let file of cvObjFrontend.files) { if (file.isActive() && file.id===null) { // Only new files //console.log(file.tempFileObj); if ('tempFileObj' in file) { // Set upload destination file.tempFileObj.fileinput().data().fileinput.uploadUrl=function() { return apiHost+'/consumption/value/file/upload/'+cvObj.id; }; // Upload if (file.tempFileObj.fileinput('getFilesCount')>0) { nrFileUploads++; file.tempFileObj.fileinput('upload'); } } } } // } //} } } // Wait for all uploads to be successfully done and call callback only then (required to show uploaded documents in frontend) Helper.wait( 100 // ms to wait per loop , 100 // max nr loops , function() { // Check if all files were uploaded (100 loops * 100ms = 10sec max waiting time) if (fileUploadSuccessCounter>=nrFileUploads) return true; else return false; }, function() { // callbackPositiveCheck Helper.hideFullScreenProcessingBackdrop(); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(cvtObj); }, function() { // callbackFinishedWithoutPositiveCallbackCheck Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Das hochladen der Dateien hat zu lange gedauert. Seite bitte neu laden.', 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM', { cvtId: cvtObj.id }); } ); //if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.hideFullScreenProcessingBackdrop(); Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { Helper.hideFullScreenProcessingBackdrop(); handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITIYTIMERANGES', apiUrl, xhr, status, error, null, { json: jsonData }); }); } deactivate(callbackSuccess=null) { //console.log(this); // ### Prepare API var apiUrl=apiHost+'/consumption/entity/timerange/edit'; // !The keys have to equal the Java class fields! var postData={}; postData['pk_consumption_values_timeranges']=this.id; postData['timestamp_deactivated']=Helper.getCurrentTimestampInUTCInISO8601Format(); //console.log('save post data >', postData); // ### Execute API let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { // Returns just saved CE object JSON Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITIYTIMERANGES', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); //console.log(data); //if (data.status=='ok') { if ('pk_consumption_values_timeranges' in data && data.pk_consumption_values_timeranges!==null && data.pk_consumption_values_timeranges!==undefined && data.pk_consumption_values_timeranges!='') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITIYTIMERANGES', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONENTITIYTIMERANGES', apiUrl, xhr, status, error, null, { json: jsonData }); }); } existAllConsumptionValues() { for (let e2hObj of this.consumptionEntity.entity2hierarchy) { if (!e2hObj.existsConsumptionValue(this)) { // At least 1 CV does not yetg exists > create alert return false; } } return true; } getCVByCVHID(ceObj, cvhId) { let cvObj=null; for (let cv of this.values) { if (cv.isActive()) { let e2hObj=ceObj.getConsumptionEntities2HierarchiesById(cv.fkConsumptionEntities2Hierarchies); if (e2hObj!==null && e2hObj.isActive()) { //console.log(ceObj, e2hObj, cv, cv.fkConsumptionEntities2Hierarchies); if (e2hObj.fkConsumptionHierarchies==cvhId) { cvObj=cv; break; } } } } return cvObj; } } class ConsumptionValue { constructor(apiObj, timerange=null) { //console.log('ConsumptionValue', apiObj); this.id=null; if (apiObj.pk_consumption_values!==undefined) this.id=apiObj.pk_consumption_values; this.usersCreator=null; if (apiObj.usersCreator!==undefined && apiObj.usersCreator!==null) { let u=apiObj.usersCreator; this.usersCreator=new User(u.pk_users, null, null, u.firstname, u.lastname, null, null, null, null, null); } this.consumption=null; if (apiObj.consumption!==undefined) this.consumption=apiObj.consumption; //this.timerange=null; if (apiObj.consumption_values_timerange!==undefined && apiObj.consumption_values_timerange!==null) this.timerange=new ConsumptionValuesTimerange(apiObj.consumption_values_timerange); this.timerange=timerange; //this.entity2hierarchy=null; if (apiObj.consumption_entity2hierarchy!==undefined && apiObj.consumption_entity2hierarchy!==null) this.entity2hierarchy=new ConsumptionEntity2Hierarchy(apiObj.consumption_entity2hierarchy); this.fkConsumptionEntities2Hierarchies=null; if (apiObj.fk_consumption_entities2hierarchies!==undefined) this.fkConsumptionEntities2Hierarchies=apiObj.fk_consumption_entities2hierarchies; this.approved=null; if (apiObj.approved!==undefined) this.approved=apiObj.approved; this.files=[]; if (apiObj.consumption_value_files!==undefined && apiObj.consumption_value_files!==null) { for (let f of apiObj.consumption_value_files) { this.files.push(new ConsumptionValueFile(f, this)); } } /* this.approvals=[]; if (apiObj.consumptionValueApprovals!==undefined && apiObj.consumptionValueApprovals!==null && Array.isArray(apiObj.consumptionValueApprovals)) { for (let idx=0; idx0 ? this.customFieldValue : null) }; for (let f of this.files) { if (f.id!==null) json.consumption_value_files.push(f.getApiJsonObj()); } return json; } createDeepCopy(cvtObj=null) { let cv=new ConsumptionValue({}); cv.id=this.id; cv.usersCreator=this.usersCreator; cv.consumption=this.consumption; if (cvtObj===null) cv.timerange=this.timerange; else cv.timerange=cvtObj; cv.fkConsumptionEntities2Hierarchies=this.fkConsumptionEntities2Hierarchies; cv.approved=this.approved; cv.files=[]; for (let file of this.files) { cv.files.push(file.createDeepCopy(cv)); } cv.emissionCO2=this.emissionCO2; cv.emissionCH4=this.emissionCH4; cv.emissionN2O=this.emissionN2O; cv.emissionCO2E=this.emissionCO2E; cv.customFieldValue=[]; for (let cfv of this.customFieldValue) { cv.customFieldValue.push(cfv.createDeepCopy()); } /* cv.approvals=[]; for (let a of this.approvals) { cv.approvals.push(a.createDeepCopy()); } */ if (this.latestConsumptionValueApproval!==null) cv.latestConsumptionValueApproval=this.latestConsumptionValueApproval.createDeepCopy(); cv.timestampDeactivated=this.timestampDeactivated; cv.timestampCreation=this.timestampCreation; return cv; } static showConsumptionValueFromExternal(consumptionValueId) { externalCallConsumptionValueId=consumptionValueId; clickOnNav1Item(['consumption','consumption_values']); } getApprovalStatus() { /* // Sort decending by timestamp this.approvals.sort(function(a,b) { let tsA=null; let tsB=null; if (a.timestampApproved!==null) tsA=moment(a.timestampApproved).tz('Europe/Berlin'); else if (a.timestampDeclined!==null) tsA=moment(a.timestampDeclined).tz('Europe/Berlin'); if (b.timestampApproved!==null) tsB=moment(b.timestampApproved).tz('Europe/Berlin'); else if (b.timestampDeclined!==null) tsB=moment(b.timestampDeclined).tz('Europe/Berlin'); if (tsA===null) return -1; // Push a to front (newer) else if (tsB===null) return 1; // Push a to back (older) else if (tsA.isBefore(tsB)) return 1; // Push a to back (older) else return -1; // Push a to front (newer) }); // Select first active approval obj let a=null; for (let a2 of this.approvals) { if (a2.isActive()) { a=a2; break; } } */ let a=this.latestConsumptionValueApproval; if (a!==null) { //let a=this.approvals[0]; if (a.timestampApproved===null && a.timestampDeclined===null) { // Approval is pending return { approved: false , declined: false , user: a.userApprover , consumptionValueApprovalId: a.id , consumptionValueObj: this , consumptionValueApprovalObj: a }; } else if (a.timestampApproved!==null) { // Approved return { approved: true , declined: false , timestampUnixInSec: moment(a.timestampApproved).tz('Europe/Berlin').unix() , user: a.userApproverActual , consumptionValueApprovalId: a.id , consumptionValueObj: this , consumptionValueApprovalObj: a }; } else if (a.timestampDeclined!==null) { // Declined return { approved: false , declined: true , timestampUnixInSec: moment(a.timestampDeclined).tz('Europe/Berlin').unix() , user: a.userApproverActual , consumptionValueApprovalId: a.id , consumptionValueObj: this , consumptionValueApprovalObj: a }; } } return { approved: false, declined: false, consumptionValueObj: this }; } getApprovalStatusOLD() { let approvedObj=null; let breakAtEndOfLoop=false; // For each new approval ... for (let a of this.approvals) { if (a.isActive()) { if (a.type=='NEW_CONSUMPTION_VALUE') { if (a.timestampApproved===null && a.timestampDeclined===null) { // Approval is pending approvedObj={ approved: false , declined: false , user: a.userApprover , consumptionValueApprovalId: a.id , consumptionValueObj: this , consumptionValueApprovalObj: a }; return approvedObj; //breakAtEndOfLoop=true; // Break immediately, as there must be only 1 pending approval } else { // Approval is not pending let ts=null; if (a.timestampApproved!==null) ts=a.timestampApproved; else if (a.timestampDeclined!==null) ts=a.timestampDeclined; if (approvedObj===null || (ts!==null && moment(ts).tz('Europe/Berlin').unix() > approvedObj.timestampUnixInSec)) { // If approval is newer ... if (a.timestampApproved!==null) { approvedObj={ approved: true , declined: false , timestampUnixInSec: moment(a.timestampApproved).tz('Europe/Berlin').unix() , user: a.userApproverActual , consumptionValueApprovalId: a.id , consumptionValueObj: this , consumptionValueApprovalObj: a }; } else if (a.timestampDeclined!==null) { approvedObj={ approved: false , declined: true , timestampUnixInSec: moment(a.timestampDeclined).tz('Europe/Berlin').unix() , user: a.userApproverActual , consumptionValueApprovalId: a.id , consumptionValueObj: this , consumptionValueApprovalObj: a }; } } } if (breakAtEndOfLoop===true) break; } } } if (approvedObj===null) approvedObj={ approved: false, declined: false, consumptionValueObj: this }; breakAtEndOfLoop=false; // For each delete approval ... for (let a of this.approvals) { if (a.isActive()) { if (a.type=='CONSUMPTION_VALUE_DELETE') { if (a.timestampApproved===null) { // Not yet approved approvedObj['deleteApproval']={ approved: false , user: a.userApprover , consumptionValueApprovalId: a.id }; breakAtEndOfLoop=true; } else { // Is approved if (!('deleteApproval' in approvedObj) || !('approved' in approvedObj['deleteApproval']) || moment(a.timestampApproved).tz('Europe/Berlin').unix() > approvedObj.timestampUnixInSec) { approvedObj['deleteApproval']={ approved: true , timestampUnixInSec: moment(a.timestampApproved).tz('Europe/Berlin').unix() , user: a.userApproverActual , consumptionValueApprovalId: a.id }; } } if (breakAtEndOfLoop===true) break; } } } //if (approvedObj===null) return { approved: false, declined: false, consumptionValueObj: this }; //else return approvedObj; return approvedObj; } deactivateApprovalRequest(callbackSuccess) { // Triggered when an already approved Measurement shall be deleted (a deletion approval request is initiated) var apiUrl=apiHost+'/consumption/value/approval/new/consumption/value/'+this.id; let pkStr='pk_consumption_value_approvals'; // !the keys have to equal the Java class fields! var postData={}; postData['type']='CONSUMPTION_VALUE_DELETE'; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL', 'OK', { apiUrl: apiUrl, type: postData['type'], requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (pkStr in data && data[pkStr]!==null && data[pkStr]!==undefined && data[pkStr]!='') { Helper.showToastr('Erfolg', 'Die Lösch-Freigabe wurde erfolgreich beantragt.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Lösch-Freigabe wurde nicht beantragt, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL', 'ERROR_SYSTEM', { apiUrl: apiUrl, type: postData['type'], data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL', apiUrl, xhr, status, error, null, { type: postData['type'], json: jsonData }); }); } restartApprovalRequest(callbackSuccess) { // Triggered when user asks for new approval after first approval has been declined //if (this.consumption===null || this.consumption=='') { Helper.showToastr('Fehler', 'Verbrauchswert fehlt.', 'error'); return; } var apiUrl=apiHost+'/consumption/value/approval/new/consumption/value/'+this.id; let pkStr='pk_consumption_value_approvals'; // !the keys have to equal the Java class fields! var postData={}; postData['type']='NEW_CONSUMPTION_VALUE'; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL', 'OK', { apiUrl: apiUrl, type: postData['type'], requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (pkStr in data && data[pkStr]!==null && data[pkStr]!==undefined && data[pkStr]!='') { Helper.showToastr('Erfolg', 'Die Freigabe wurde erfolgreich beantragt.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Freigabe wurde nicht beantragt, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL', 'ERROR_SYSTEM', { apiUrl: apiUrl, type: postData['type'], data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL', apiUrl, xhr, status, error, null, { type: postData['type'], json: jsonData }); }); } startApprovalRequest(callbackSuccess) { //if (this.consumption===null || this.consumption=='') { Helper.showToastr('Fehler', 'Verbrauchswert fehlt.', 'error'); return; } var apiUrl=apiHost+'/consumption/value/approval/new/consumption/value/'+this.id; let pkStr='pk_consumption_value_approvals'; // !the keys have to equal the Java class fields! var postData={}; postData['type']='NEW_CONSUMPTION_VALUE'; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL', 'OK', { apiUrl: apiUrl, type: postData['type'], requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (pkStr in data && data[pkStr]!==null && data[pkStr]!==undefined && data[pkStr]!='') { Helper.showToastr('Erfolg', 'Die Freigabe wurde erfolgreich beantragt.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Die Freigabe wurde nicht beantragt, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL', 'ERROR_SYSTEM', { apiUrl: apiUrl, type: postData['type'], data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_NEW_CONSUMPTIONVALUEAPPROVAL', apiUrl, xhr, status, error, null, { type: postData['type'], json: jsonData }); }); } loadConsumptionValueApprovalsFromApi(callbackSuccessAry=null) { //Helper.showFullScreenProcessingBackdrop(); const tsStartApi=Date.now(); var apiUrl=apiHost+'/consumption/value/approval/consumption/value/'+this.id; $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { //console.log(dataFromApi); //Helper.hideFullScreenProcessingBackdrop(); if (dataFromApi!==null && Array.isArray(dataFromApi)) { Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYAPPROVALS', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); let consumptionValueApprovals=[]; for (let cvaJson of dataFromApi) { consumptionValueApprovals.push(new ConsumptionValueApproval(cvaJson, this)); } if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(consumptionValueApprovals); } } } else { Helper.showToastr('Fehler', 'Daten konnten nicht korrekt geladen werden.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYAPPROVALS', 'ERROR_SYSTEM_DATALOAD', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); } } }).fail(function(xhr, status, error){ Helper.hideFullScreenProcessingBackdrop(); handleFailedApiCall('FRONTEND_CLIENT_API_GET_CONSUMPTIONENTITYAPPROVALS', apiUrl, xhr, status, error); }); } loadConsumptionValueFromApi(callbackSuccessAry=null) { //Helper.showFullScreenProcessingBackdrop(); const tsStartApi=Date.now(); var apiUrl=apiHost+'/consumption/value/'+this.id; $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { //console.log(dataFromApi); //Helper.hideFullScreenProcessingBackdrop(); if (dataFromApi!==null && 'pk_consumption_values' in dataFromApi && dataFromApi.pk_consumption_values!==null) { Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONVALUE', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); if (callbackSuccessAry!==undefined && callbackSuccessAry!==null && Array.isArray(callbackSuccessAry)) { for (let callback of callbackSuccessAry) { if (callback!==undefined && callback!==null) callback(new ConsumptionValue(dataFromApi)); } } } else { Helper.showToastr('Fehler', 'Daten konnten nicht korrekt geladen werden.', 'error'); Logger.log('FRONTEND_CLIENT_API_GET_CONSUMPTIONVALUE', 'ERROR_SYSTEM_DATALOAD', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); } } }).fail(function(xhr, status, error){ Helper.hideFullScreenProcessingBackdrop(); handleFailedApiCall('FRONTEND_CLIENT_API_GET_CONSUMPTIONVALUE', apiUrl, xhr, status, error); }); } getCreatorUserId() { if ('usersCreator' in this && this.usersCreator!==null) return this.usersCreator.id; else return null; } } class ConsumptionValueFile { constructor(apiObj, consumptionValue=null) { this.id=null; if (apiObj.pk_consumption_values_files!==undefined) this.id=apiObj.pk_consumption_values_files; this.consumptionValue=consumptionValue; this.filename=null; if (apiObj.filename!==undefined) this.filename=apiObj.filename; this.documentType=null; if (apiObj.document_type!==undefined) this.documentType=apiObj.document_type; this.sizeInBytes=null; if (apiObj.size!==undefined) this.sizeInBytes=apiObj.size; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; return active; } getApiJsonObj() { let json={ pk_consumption_values_files: this.id , filename: this.filename , document_type: this.documentType , size: this.sizeInBytes , timestamp_deactivated: this.timestampDeactivated }; return json; } createDeepCopy(cvObj=null) { let cvf=new ConsumptionValueFile({}); cvf.id=this.id; cvf.consumptionValue=cvObj; cvf.filename=this.filename; cvf.documentType=this.documentType; cvf.sizeInBytes=this.sizeInBytes; cvf.timestampDeactivated=this.timestampDeactivated; cvf.timestampCreation=this.timestampCreation; if ('tempFileObj' in this) { cvf.tempFileObj=this.tempFileObj; } return cvf; } } class ConsumptionValueApproval { constructor(apiJsonObj, cvObj=null) { //console.log(apiJsonObj); this.id=apiJsonObj.pk_consumption_value_approvals; this.consumptionValue=null; if (cvObj!==null) this.consumptionValue=cvObj; this.timestampEmailSentToApprover=apiJsonObj.timestamp_email_sent_to_approver; this.timestampApproved=apiJsonObj.timestamp_approved; this.timestampDeclineEmailSentToCreator=apiJsonObj.timestamp_decline_email_sent_to_creator; this.timestampDeclined=apiJsonObj.timestamp_declined; this.type=apiJsonObj.type; if (apiJsonObj.users_approver!==undefined && apiJsonObj.users_approver!==null) { let ua=apiJsonObj.users_approver; // id, email, pwdSaltedMd5, role, firstname, lastname, title, department, privilegesObj, accountObj this.userApprover=new User(ua.pk_users, null, null, ua.firstname, ua.lastname, null, null, null, null, null); } this.userApproverActual=null; if (apiJsonObj.users_approver_actual!==undefined && apiJsonObj.users_approver_actual!==null) { let ua=apiJsonObj.users_approver_actual; // id, email, pwdSaltedMd5, role, firstname, lastname, title, department, privilegesObj, accountObj this.userApproverActual=new User(ua.pk_users, null, null, ua.firstname, ua.lastname, null, null, null, null, null); } this.timestampDeactivated=null; if (apiJsonObj.timestamp_deactivated!==undefined && apiJsonObj.timestamp_deactivated!==null) this.timestampDeactivated=apiJsonObj.timestamp_deactivated; } isActive() { if (this.timestampDeactivated!==null) return false; else return true; } createDeepCopy() { let cva=new ConsumptionValueApproval({}); cva.id=this.id; cva.consumptionValue=this.consumptionValue; cva.timestampEmailSentToApprover=this.timestampEmailSentToApprover; cva.timestampApproved=this.timestampApproved; cva.timestampDeclineEmailSentToCreator=this.timestampDeclineEmailSentToCreator; cva.timestampDeclined=this.timestampDeclined; cva.type=this.type; cva.userApprover=this.userApprover; cva.userApproverActual=this.userApproverActual; cva.timestampDeactivated=this.timestampDeactivated; return cva; } saveApproval(callbackSuccess) { // ### Check data consistency & assemble POST data obj var postData={}; postData['timestamp_approved']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 // ### Call API var apiUrl=apiHost+'/consumption/value/approval/edit/consumption/value/'+this.id; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONVALUEAPPROVAL', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONVALUEAPPROVAL', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONVALUEAPPROVAL', apiUrl, xhr, status, error, null, { json: jsonData }); }); } saveDecline(msgToCreator, callbackSuccess) { // ### Check data consistency & assemble POST data obj var postData={}; postData['timestamp_declined']=Helper.getCurrentTimestampInUTCInISO8601Format(); // Format: 2014-09-08T08:02:17+02:00 if (msgToCreator!==undefined && msgToCreator!==null) postData['decline_msg_to_creator']=msgToCreator; // ### Call API var apiUrl=apiHost+'/consumption/value/approval/edit/consumption/value/'+this.id; let jsonData=JSON.stringify(postData); const tsStartApi=Date.now(); $.ajax({type:'POST', url:apiUrl, data:jsonData, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (data) { Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONVALUEAPPROVAL', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi, json: jsonData }); if (data.status=='ok') { Helper.showToastr('Erfolg', 'Die Änderungen wurden gespeichert.', 'success'); if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(); } else { Helper.showToastr('Fehler', 'Es wurden keine Änderungen gespeichert, da ein Fehler aufgetreten ist: '+data.msg, 'error'); Logger.log('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONVALUEAPPROVAL', 'ERROR_SYSTEM', { apiUrl: apiUrl, data: data, json: jsonData }); } }} ).fail(function(xhr, status, error) { handleFailedApiCall('FRONTEND_CLIENT_API_EDIT_CONSUMPTIONVALUEAPPROVAL', apiUrl, xhr, status, error, null, { json: jsonData }); }); } static loadActiveConsumptionValuesWithOpenApprovalsFromApi(callbackSuccess) { const tsStartApi=Date.now(); var apiUrl=apiHost+'/consumption/value/approval/all_active_open2/accountId/'+userObj.accountObj.id; $.ajax({type:'GET', url:apiUrl, contentType: "application/json; charset=utf-8", dataType: 'JSON', headers: { 'Authorization': 'Bearer '+jwtToken }, success: function (dataFromApi) { Logger.log('FRONTEND_CLIENT_API_GET_ALLACTIVEOPENCONSUMPTIONVALUES', 'OK', { apiUrl: apiUrl, requestDurationMs: Date.now()-tsStartApi }); //console.log(dataFromApi); let ceAry=[]; if (dataFromApi!==null && dataFromApi.length>0) { for (let ce of dataFromApi) { ceAry.push(new ConsumptionEntity(ce)); } } if (callbackSuccess!==undefined && callbackSuccess!==null) callbackSuccess(ceAry); } }).fail(function(xhr, status, error){ handleFailedApiCall('FRONTEND_CLIENT_API_GET_ALLACTIVEOPENCONSUMPTIONVALUES', apiUrl, xhr, status, error); }); } } class ConsumptionCustomEF { // Custom emission factor constructor(apiObj, entity2hierarchy=null) { //console.log('ConsumptionCustomEF apiObj', apiObj); this.id=null; if (apiObj.pk_consumption_custom_emissionfactors!==undefined) this.id=apiObj.pk_consumption_custom_emissionfactors; this.type=null; if (apiObj.type!==undefined) this.type=apiObj.type; //this.entity2hierarchy=null; if (apiObj.consumption_entity2hierarchy!==undefined && apiObj.consumption_entity2hierarchy!==null) this.entity2hierarchy=new ConsumptionEntity2Hierarchy(apiObj.consumption_entity2hierarchy); this.entity2hierarchy=entity2hierarchy; this.value=null; if (apiObj.value!==undefined) this.value=apiObj.value; this.timestampFrom=null; if (apiObj.timestamp_from!==undefined) this.timestampFrom=apiObj.timestamp_from; this.timestampTo=null; if (apiObj.timestamp_to!==undefined) this.timestampTo=apiObj.timestamp_to; this.filename=null; if (apiObj.filename!==undefined) this.filename=apiObj.filename; this.documentType=null; if (apiObj.document_type!==undefined) this.documentType=apiObj.document_type; this.sizeInBytes=null; if (apiObj.size!==undefined) this.sizeInBytes=apiObj.size; this.source=null; if (apiObj.source!==undefined) this.source=apiObj.source; this.temporaryId=null; if (apiObj.temporary_id!==undefined) this.temporaryId=apiObj.temporary_id; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; else if (this.entity2hierarchy!==null && !this.entity2hierarchy.isActive()) active=false; return active; } isNew() { if (this.id===null) return true; else return false; } getDisplayString() { if (this.value!==null) return Helper.number_format(this.value, null, ',', '.', false, 10); else return ''; } createDeepCopy(e2hObj=null) { let ccEf=new ConsumptionCustomEF({}); ccEf.id=this.id; ccEf.type=this.type; ccEf.entity2hierarchy=e2hObj; ccEf.value=this.value; ccEf.timestampFrom=this.timestampFrom; ccEf.timestampTo=this.timestampTo; ccEf.filename=this.filename; ccEf.documentType=this.documentType; ccEf.sizeInBytes=this.sizeInBytes; if ('tempFileObj' in this) ccEf.tempFileObj=this.tempFileObj; ccEf.source=this.source; ccEf.temporaryId=this.temporaryId; ccEf.timestampDeactivated=this.timestampDeactivated; ccEf.timestampCreation=this.timestampCreation; return ccEf; } } class ConsumptionEF { // Emission factor constructor(apiObj, consumptionHierarchy=null) { this.id=null; if (apiObj.pk_consumption_emissionfactors!==undefined) this.id=apiObj.pk_consumption_emissionfactors; //this.consumptionHierarchy=null; if (apiObj.consumption_hierarchy!==undefined && apiObj.consumption_hierarchy!==null) this.consumptionHierarchy=new ConsumptionHierarchy(apiObj.consumption_hierarchy); this.consumptionHierarchy=consumptionHierarchy; this.timestampFrom=null; if (apiObj.timestamp_from!==undefined) this.timestampFrom=apiObj.timestamp_from; this.type=null; if (apiObj.type!==undefined) this.type=apiObj.type; this.factor=null; if (apiObj.factor!==undefined) this.factor=apiObj.factor; this.source=null; if (apiObj.source!==undefined) this.source=apiObj.source; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; else if (this.consumptionHierarchy!==null && !this.consumptionHierarchy.isActive()) active=false; return active; } getDisplayString() { if (this.factor!==null) return Helper.number_format(this.factor, null, ',', '.', false, 10); else return ''; } getDisplayStringWithSource() { if (this.factor!==null) return Helper.number_format(this.factor, null, ',', '.', false, 10)+'
    (Quelle: '+(this.source!==null ? this.source : 'n/a')+')'; else return ''; } } class ConsumptionCO2Factor { // NOT SURE IF THIS IS REQUIRED HERE IN FRONTEND OR IF CALCULATIONS ARE TO BE MADE IN BACKEND constructor(apiObj) { this.id=null; if (apiObj.pk_consumption_co2e_factors!==undefined) this.id=apiObj.pk_consumption_co2e_factors; this.timestampFrom=null; if (apiObj.timestamp_from!==undefined) this.timestampFrom=apiObj.timestamp_from; this.type=null; if (apiObj.type!==undefined) this.type=apiObj.type; this.factor=null; if (apiObj.factor!==undefined) this.factor=apiObj.factor; this.timestampDeactivated=null; if (apiObj.timestamp_deactivated!==undefined && apiObj.timestamp_deactivated!==null) this.timestampDeactivated=apiObj.timestamp_deactivated; this.timestampCreation=null; if (apiObj.timestampCreation!==undefined && apiObj.timestampCreation!==null) this.timestampCreation=apiObj.timestampCreation; } isActive() { var active=true; if (this.timestampDeactivated!==null) active=false; return active; } } class ConsumptionCustomFieldSpecCEC { constructor(apiObj) { this.type=null; if (apiObj.type!==undefined) this.type=apiObj.type; // text, integer, decimal or date this.id=null; if (apiObj.id!==undefined) this.id=apiObj.id; this.name=null; if (apiObj.name!==undefined) this.name=apiObj.name; this.layoutRowIdx=null; if (apiObj.layoutRowIdx!==undefined) this.layoutRowIdx=apiObj.layoutRowIdx; this.layoutRowHeadline=null; if (apiObj.layoutRowHeadline!==undefined) this.layoutRowHeadline=apiObj.layoutRowHeadline; this.layoutColIdx=null; if (apiObj.layoutColIdx!==undefined) this.layoutColIdx=apiObj.layoutColIdx; this.groupNameId=null; if (apiObj.groupNameId!==undefined) this.groupNameId=apiObj.groupNameId; this.showInVETable=null; if (apiObj.showInVETable!==undefined) this.showInVETable=apiObj.showInVETable; this.displayOrder=null; if (apiObj.displayOrder!==undefined) this.displayOrder=apiObj.displayOrder; this.displayIdentifier=null; if (apiObj.displayIdentifier!==undefined) this.displayIdentifier=apiObj.displayIdentifier; this.inputAutomaticTimerangeCreationFrom=null; if (apiObj.inputAutomaticTimerangeCreationFrom!==undefined) this.inputAutomaticTimerangeCreationFrom=apiObj.inputAutomaticTimerangeCreationFrom; this.inputAutomaticTimerangeCreationTo=null; if (apiObj.inputAutomaticTimerangeCreationTo!==undefined) this.inputAutomaticTimerangeCreationTo=apiObj.inputAutomaticTimerangeCreationTo; this.mandatory=null; if (apiObj.mandatory!==undefined) this.mandatory=apiObj.mandatory; } } class ConsumptionCustomFieldSpecCVH { constructor(apiObj) { this.type=null; if (apiObj.type!==undefined) this.type=apiObj.type; // text, integer, decimal or date this.id=null; if (apiObj.id!==undefined) this.id=apiObj.id; this.name=null; if (apiObj.name!==undefined) this.name=apiObj.name; this.unit=null; if (apiObj.unit!==undefined) this.unit=apiObj.unit; this.mandatory=null; if (apiObj.mandatory!==undefined) this.mandatory=apiObj.mandatory; } } class ConsumptionCustomFieldValue { constructor(apiObj) { this.id=null; if (apiObj.id!==undefined) this.id=apiObj.id; this.value=null; if (apiObj.value!==undefined) this.value=apiObj.value; } createDeepCopy() { return new ConsumptionCustomFieldValue({ id: this.id , value: this.value }); } }