From ce11053413bd48ba5af62bbfe5dda1f4cf16e2c1 Mon Sep 17 00:00:00 2001
From: Johannes Goderbauer <j.goderbauer@adito.de>
Date: Fri, 20 Mar 2020 08:18:19 +0000
Subject: [PATCH] Merge branch '#1051513_Missing_ActionStatus' into '2020.0'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

#1051513 Setzen von  X-Header für StausAction im Kalender

See merge request xrm/basic!160

(cherry picked from commit 02f9f4aef44784f08e0ee3c4240c01f35ef801a3)

dd47a27c #1051513 Im Kalender (Appointment_entity) setzen von X-Header
af49cc33 #1051513 removed log call and added more documentation
---
 .../Appointment_entity/Appointment_entity.aod |   6 ++
 .../children/accept/onActionProcess.js        |   1 +
 .../children/decline/onActionProcess.js       |   1 +
 .../children/tentative/onActionProcess.js     |   1 +
 .../recordcontainers/jdito/contentProcess.js  |   3 +-
 .../recordcontainers/jdito/onUpdate.js        | 100 ++++++++++++++++++
 6 files changed, 111 insertions(+), 1 deletion(-)

diff --git a/entity/Appointment_entity/Appointment_entity.aod b/entity/Appointment_entity/Appointment_entity.aod
index f63a8013b1..c48e801ff5 100644
--- a/entity/Appointment_entity/Appointment_entity.aod
+++ b/entity/Appointment_entity/Appointment_entity.aod
@@ -242,6 +242,9 @@
       <tooltip>New activity</tooltip>
       <tooltipProcess>%aditoprj%/entity/Appointment_entity/entityfields/newactivity/tooltipProcess.js</tooltipProcess>
     </entityActionField>
+    <entityField>
+      <name>STATUS_ACTION</name>
+    </entityField>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
@@ -324,6 +327,9 @@
         <jDitoRecordFieldMapping>
           <name>MASTEREND.value</name>
         </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>STATUS_ACTION.value</name>
+        </jDitoRecordFieldMapping>
       </recordFieldMappings>
     </jDitoRecordContainer>
   </recordContainers>
diff --git a/entity/Appointment_entity/entityfields/partstatactiongroup/children/accept/onActionProcess.js b/entity/Appointment_entity/entityfields/partstatactiongroup/children/accept/onActionProcess.js
index d8b40a8d06..0a3bd6581e 100644
--- a/entity/Appointment_entity/entityfields/partstatactiongroup/children/accept/onActionProcess.js
+++ b/entity/Appointment_entity/entityfields/partstatactiongroup/children/accept/onActionProcess.js
@@ -19,4 +19,5 @@ else
     var currentAttendees = vars.get("$field.ATTENDEES");
     var updatedAttendees = AppointmentUtils.setPartStat(currentUserUri, currentAttendees, newState);
     neon.setFieldValue("$field.ATTENDEES", updatedAttendees);
+    neon.setFieldValue("$field.STATUS_ACTION", calendars.STATUS_ACCEPTED)
 }
diff --git a/entity/Appointment_entity/entityfields/partstatactiongroup/children/decline/onActionProcess.js b/entity/Appointment_entity/entityfields/partstatactiongroup/children/decline/onActionProcess.js
index a6828aaf7a..20b2e975da 100644
--- a/entity/Appointment_entity/entityfields/partstatactiongroup/children/decline/onActionProcess.js
+++ b/entity/Appointment_entity/entityfields/partstatactiongroup/children/decline/onActionProcess.js
@@ -19,4 +19,5 @@ else
     var currentAttendees = vars.get("$field.ATTENDEES");
     var updatedAttendees = AppointmentUtils.setPartStat(currentUserUri, currentAttendees, newState);
     neon.setFieldValue("$field.ATTENDEES", updatedAttendees);
+    neon.setFieldValue("$field.STATUS_ACTION", calendars.STATUS_DECLINED);
 }
diff --git a/entity/Appointment_entity/entityfields/partstatactiongroup/children/tentative/onActionProcess.js b/entity/Appointment_entity/entityfields/partstatactiongroup/children/tentative/onActionProcess.js
index 2915c893e5..a82f2e460d 100644
--- a/entity/Appointment_entity/entityfields/partstatactiongroup/children/tentative/onActionProcess.js
+++ b/entity/Appointment_entity/entityfields/partstatactiongroup/children/tentative/onActionProcess.js
@@ -19,4 +19,5 @@ else
     var currentAttendees = vars.get("$field.ATTENDEES");
     var updatedAttendees = AppointmentUtils.setPartStat(currentUserUri, currentAttendees, newState);
     neon.setFieldValue("$field.ATTENDEES", updatedAttendees);
+    neon.setFieldValue("$field.STATUS_ACTION", calendars.STATUS_TENTATIVE);
 }
\ No newline at end of file
diff --git a/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js b/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js
index 700dad726e..ee80cd3135 100644
--- a/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js
@@ -119,6 +119,7 @@ function buildEntry(pEntry, pMasterentry)
             recurrenceID, 
             null, 
             masterBegin, 
-            masterEnd
+            masterEnd,
+            null
         ];
 }
diff --git a/entity/Appointment_entity/recordcontainers/jdito/onUpdate.js b/entity/Appointment_entity/recordcontainers/jdito/onUpdate.js
index a394b2e212..d9c947a770 100644
--- a/entity/Appointment_entity/recordcontainers/jdito/onUpdate.js
+++ b/entity/Appointment_entity/recordcontainers/jdito/onUpdate.js
@@ -59,6 +59,9 @@ if(event)
         if(event[calendars.RRULE])
             event[calendars.RRULE] = [fields["RRULE.value"]];
         
+        // Adds the required X-Header for status actions needed by Exchange and Domino
+        addStatusAction(event, fields);
+        
         calendars.updateEntry(event);
 }
 
@@ -90,4 +93,101 @@ function areEventAndFieldsDifferent(event){
         }
     
     return different;
+}
+
+/**
+ * Summary. Sets the "X-ADITO-STATUSACTION" - header which is needed for Exchange and Domino to process changes.
+ * 
+ * Description. Checks if the backendType requires a special X-Header to handle certain updates. Currently 
+ *              only Domino (calendars.BACKEND_DOMINO_REST) and Exchange (calendars.BACKEND_EXCHANGEWS) require this header.
+ *              <br/>
+ *              The required status action needs to be stored in the entityField <tt>STATUS_ACTION</tt> 
+ *              in order to set the header correctly.
+ *              <br/>
+ *              The X-Header <tt>X-ADITO-STATUSACTION</tt> is an internal placeholder for setting 
+ *              the status action for certain calendar backends. The required value depends on the backend used.
+ *              <br/>
+ *              The X-Header is added to the given calender event.
+ * 
+ * 
+ * @param {JSON} pEvent the calendar event for the update
+ * @param {Array} pFields the current field values of the entity
+ * 
+ * @see calendars.getBackendType
+ * @see _getExchangeStatusAction
+ * @see _getDominoStatusAction
+ */
+function addStatusAction (pEvent, pFields)
+{
+    var statusAction = pFields["STATUS_ACTION.value"];
+    var backendType = calendars.getBackendType();
+    
+    if(statusAction != null 
+        && ( backendType == calendars.BACKEND_EXCHANGEWS || backendType == calendars.BACKEND_DOMINO_REST ))
+    {
+        statusAction = statusAction.toUpperCase();
+        
+        if(backendType == calendars.BACKEND_EXCHANGEWS)
+        {
+            statusAction = _getExchangeStatusAction(statusAction);
+        }
+        else if(backendType == calendars.BACKEND_DOMINO_REST)
+        {
+            statusAction = _getDominoStatusAction(statusAction);
+        }
+        
+        if(statusAction != null)
+            pEvent["X-ADITO-STATUSACTION"] = statusAction;
+    }
+}
+
+/**
+ * Translates the given action into a status action for ExchangeWS.
+ * 
+ * @param {String} pStatusAction the general Key for the status action
+ * @return {String} The specific value for the specified Exchange status action.
+ */
+function _getExchangeStatusAction(pStatusAction)
+{
+    switch (pStatusAction)
+    {
+        case calendars.STATUS_ACCEPTED:
+            return "ACCEPT";
+        case calendars.STATUS_TENTATIVE:
+            return "TENTATIVELYACCEPT";
+        case calendars.STATUS_DECLINED:
+            return "DECLINE";
+        case calendars.STATUS_CANCELLED:
+            return "CANCEL_MEETING";
+        default:
+            return null;
+    }
+}
+
+/**
+ * Translates the given action into a status action for Domino.
+ * 
+ * @param {String} pStatusAction the general Key for the status action
+ * @return {String} The specific value for the specified Domino status action.
+ */
+function _getDominoStatusAction(pStatusAction)
+{
+    switch (pStatusAction)
+    {
+        case calendars.STATUS_ACCEPTED:
+            return "accept";
+        case calendars.STATUS_TENTATIVE:
+            return "tentative";
+        case calendars.STATUS_DECLINED:
+            return "decline";
+        case calendars.STATUS_CANCELLED:
+            return "cancel";
+//        Not needed.
+//        Entries are deleted using the system.calendars own delte method
+//        
+//        case "DELETED":
+//            return "delete";
+        default:
+            return null;
+    }
 }
\ No newline at end of file
-- 
GitLab