From b67f39496c0d0e8008eac4078f0c71bd0f4b8781 Mon Sep 17 00:00:00 2001
From: "a.schindlbeck" <a.schindlbeck@adito.de>
Date: Mon, 10 Sep 2018 11:07:20 +0200
Subject: [PATCH] Calendar Setup

---
 .../_____SYSTEM_APPLICATION.aod               |  18 +
 .../_____SYSTEM_APPLICATION_NEON.aod          |   2 +
 .../company/iconProcess.js                    |   0
 .../_____SYSTEM_CALENDAR_RIBBON.aod           |  14 +
 .../_____SYSTEM_CALENDAR_RIBBON_NEON.aod      |   3 +
 .../_____SYSTEM_INDEXSEARCH_RIBBON.aod        |  14 +
 .../Appointment_entity/Appointment_entity.aod |  49 +++
 entity/Appointment_entity/contentProcess.js   |  58 +++
 .../entityfields/summary/valueProcess.js      |   5 +
 entity/Appointment_entity/onDelete.js         |  17 +
 entity/Appointment_entity/onInsert.js         | 359 +++++++++++++++++
 entity/Appointment_entity/onUpdate.js         | 368 ++++++++++++++++++
 .../Appointment_context.aod                   |  22 ++
 neonContext/Org_context/Org_context.aod       |   1 +
 neonContext/Org_context/iconProcess.js        |   0
 .../AppointmentEdit_view.aod                  |  24 ++
 .../AppointmentPreview_view.aod               |  22 ++
 .../_____PREFERENCES_PROJECT.aod              |   2 +-
 .../openCalendarProzess.aod                   |   6 +
 process/openCalendarProzess/process.js        |   8 +
 20 files changed, 991 insertions(+), 1 deletion(-)
 create mode 100644 application/_____SYSTEM_APPLICATION/_____SYSTEM_APPLICATION.aod
 create mode 100644 application/_____SYSTEM_APPLICATION_NEON/company/iconProcess.js
 create mode 100644 application/_____SYSTEM_CALENDAR_RIBBON/_____SYSTEM_CALENDAR_RIBBON.aod
 create mode 100644 application/_____SYSTEM_INDEXSEARCH_RIBBON/_____SYSTEM_INDEXSEARCH_RIBBON.aod
 create mode 100644 entity/Appointment_entity/Appointment_entity.aod
 create mode 100644 entity/Appointment_entity/contentProcess.js
 create mode 100644 entity/Appointment_entity/entityfields/summary/valueProcess.js
 create mode 100644 entity/Appointment_entity/onDelete.js
 create mode 100644 entity/Appointment_entity/onInsert.js
 create mode 100644 entity/Appointment_entity/onUpdate.js
 create mode 100644 neonContext/Appointment_context/Appointment_context.aod
 create mode 100644 neonContext/Org_context/iconProcess.js
 create mode 100644 neonView/AppointmentEdit_view/AppointmentEdit_view.aod
 create mode 100644 neonView/AppointmentPreview_view/AppointmentPreview_view.aod
 create mode 100644 process/openCalendarProzess/openCalendarProzess.aod
 create mode 100644 process/openCalendarProzess/process.js

diff --git a/application/_____SYSTEM_APPLICATION/_____SYSTEM_APPLICATION.aod b/application/_____SYSTEM_APPLICATION/_____SYSTEM_APPLICATION.aod
new file mode 100644
index 00000000000..dc4b0517fc5
--- /dev/null
+++ b/application/_____SYSTEM_APPLICATION/_____SYSTEM_APPLICATION.aod
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/application/1.1.8">
+  <name>_____SYSTEM_APPLICATION</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <entityNode name="_____SYSTEM_COMPANY" kind="200">
+    <node name="Group" kind="123" title="">
+      <node name="Group2" kind="123" title="">
+        <node name="openCalendarProzess" kind="103" />
+        <node name="Util_lib" kind="103" />
+        <node name="INTERNAL_ADMINISTRATOR" kind="159" />
+      </node>
+    </node>
+  </entityNode>
+  <company>
+    <name>company</name>
+    <backgroundColor v="0xff83cbd8" />
+  </company>
+</application>
diff --git a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
index 27b4cde697b..5a9a2413668 100644
--- a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
+++ b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
@@ -7,6 +7,7 @@
       <icon>VAADIN:STAR</icon>
       <node name="Group1" kind="123" title="">
         <node name="Vertriebsdashboard" kind="10090" />
+        <node name="Calendar_context" kind="10077" />
         <node name="Org_context" kind="10077" />
         <node name="Pers_context" kind="10077" />
         <node name="History_context" kind="10077" />
@@ -16,5 +17,6 @@
   </entityNode>
   <company>
     <name>company</name>
+    <iconProcess>%aditoprj%/application/_____SYSTEM_APPLICATION_NEON/company/iconProcess.js</iconProcess>
   </company>
 </application>
diff --git a/application/_____SYSTEM_APPLICATION_NEON/company/iconProcess.js b/application/_____SYSTEM_APPLICATION_NEON/company/iconProcess.js
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/application/_____SYSTEM_CALENDAR_RIBBON/_____SYSTEM_CALENDAR_RIBBON.aod b/application/_____SYSTEM_CALENDAR_RIBBON/_____SYSTEM_CALENDAR_RIBBON.aod
new file mode 100644
index 00000000000..59f4edfc613
--- /dev/null
+++ b/application/_____SYSTEM_CALENDAR_RIBBON/_____SYSTEM_CALENDAR_RIBBON.aod
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/application/1.1.8">
+  <name>_____SYSTEM_CALENDAR_RIBBON</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <entityNode name="_____SYSTEM_COMPANY" kind="200" />
+  <calendarRibbon>
+    <name>calendarRibbon</name>
+    <ribbonTasks>
+      <ribbonTask>
+        <name>TASK_CALENDAR</name>
+      </ribbonTask>
+    </ribbonTasks>
+  </calendarRibbon>
+</application>
diff --git a/application/_____SYSTEM_CALENDAR_RIBBON_NEON/_____SYSTEM_CALENDAR_RIBBON_NEON.aod b/application/_____SYSTEM_CALENDAR_RIBBON_NEON/_____SYSTEM_CALENDAR_RIBBON_NEON.aod
index 216dd1b6553..430c1600fa5 100644
--- a/application/_____SYSTEM_CALENDAR_RIBBON_NEON/_____SYSTEM_CALENDAR_RIBBON_NEON.aod
+++ b/application/_____SYSTEM_CALENDAR_RIBBON_NEON/_____SYSTEM_CALENDAR_RIBBON_NEON.aod
@@ -5,5 +5,8 @@
   <entityNode name="_____SYSTEM_COMPANY" kind="200" />
   <neonCalendarRibbon>
     <name>neonCalendarRibbon</name>
+    <entity>
+      <name>entity</name>
+    </entity>
   </neonCalendarRibbon>
 </application>
diff --git a/application/_____SYSTEM_INDEXSEARCH_RIBBON/_____SYSTEM_INDEXSEARCH_RIBBON.aod b/application/_____SYSTEM_INDEXSEARCH_RIBBON/_____SYSTEM_INDEXSEARCH_RIBBON.aod
new file mode 100644
index 00000000000..6e55b830c5b
--- /dev/null
+++ b/application/_____SYSTEM_INDEXSEARCH_RIBBON/_____SYSTEM_INDEXSEARCH_RIBBON.aod
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/application/1.1.8">
+  <name>_____SYSTEM_INDEXSEARCH_RIBBON</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <entityNode name="_____SYSTEM_COMPANY" kind="200" />
+  <indexSearchRibbon>
+    <name>indexSearchRibbon</name>
+    <ribbonTasks>
+      <ribbonTask>
+        <name>TASK_INDEXSEARCH</name>
+      </ribbonTask>
+    </ribbonTasks>
+  </indexSearchRibbon>
+</application>
diff --git a/entity/Appointment_entity/Appointment_entity.aod b/entity/Appointment_entity/Appointment_entity.aod
new file mode 100644
index 00000000000..bd143b765e1
--- /dev/null
+++ b/entity/Appointment_entity/Appointment_entity.aod
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.0.3" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.0.3">
+  <name>Appointment_entity</name>
+  <title>Termin</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <alias>Data_alias</alias>
+  <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
+  <fields>
+    <element>UID</element>
+    <element>BACKGROUNDCOLOR</element>
+    <element>FONTCOLOR</element>
+    <element>ATTENDEESLENGTH</element>
+    <element>STARTDATE</element>
+    <element>ENDDATE</element>
+    <element>SUBJECT</element>
+    <element>ORGANIZER</element>
+    <element>ATTENDEES</element>
+    <element>STATUS</element>
+    <element>LINKS</element>
+    <element>DESCRIPTION</element>
+    <element>LOCATION</element>
+    <element>ICON</element>
+  </fields>
+  <contentProcess>%aditoprj%/entity/Appointment_entity/contentProcess.js</contentProcess>
+  <onInsert>%aditoprj%/entity/Appointment_entity/onInsert.js</onInsert>
+  <onUpdate>%aditoprj%/entity/Appointment_entity/onUpdate.js</onUpdate>
+  <onDelete>%aditoprj%/entity/Appointment_entity/onDelete.js</onDelete>
+  <recordContainerType>JDITO</recordContainerType>
+  <caption>Termin</caption>
+  <entityFields>
+    <entityField>
+      <name>SUMMARY</name>
+      <fieldName>SUBJECT</fieldName>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/summary/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>entry</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>DESCRIPTION</name>
+      <fieldName>DESCRIPTION</fieldName>
+    </entityField>
+    <entityField>
+      <name>STARTEND</name>
+    </entityField>
+  </entityFields>
+</entity>
diff --git a/entity/Appointment_entity/contentProcess.js b/entity/Appointment_entity/contentProcess.js
new file mode 100644
index 00000000000..6457081b568
--- /dev/null
+++ b/entity/Appointment_entity/contentProcess.js
@@ -0,0 +1,58 @@
+import("system.result");
+import("system.vars");
+import("system.calendars");
+import("system.datetime");
+import("system.eMath");
+
+if(vars.exists("$image.entry"))
+{
+    var entry = vars.get("$image.entry");
+
+    var uid = entry[calendars.ID];    
+    var summary = entry[calendars.SUMMARY];
+    var affectedusers = entry[calendars.AFFECTEDUSERS];
+    var attendees = entry[calendars.ATTENDEES];
+    var startdate = entry[calendars.DTSTART];
+    var enddate = entry[calendars.DTEND];
+    var links = entry[calendars.LINKS];
+    var description = entry[calendars.DESCRIPTION];
+    var organizer = entry[calendars.ORGANIZER2];
+    var status = entry[calendars.STATUS];
+    var location = entry[calendars.LOCATION];
+    var reminder = entry[calendars.REMINDER];
+    var remindercheck = entry[calendars.HASREMINDER]
+  
+    //@TODO Icon 
+  
+    result.object([
+        [uid, '', '', attendees.length, startdate, enddate, summary, organizer, attendees, status, links, description, location, ''] //, location, reminder, remindercheck
+        ]);
+}
+else
+{
+     
+    
+    var filter = ( vars.exists("$param.p_filter") 
+                    && vars.get("$param.p_filter") != null 
+                    && vars.get("$param.p_filter") != undefined) ? vars.get("$param.p_filter") : "";
+
+    //For the Tableview in Task_Date
+    //var events = getEvents(filter);
+    var cond = {
+        TYPE_1: calendars.VEVENT
+        ,USER_1: vars.get("$sys.user")
+        ,COUNT: "1"
+        };
+    var entries = calendars.getExpandedEntries(cond, new Long(datetime.date()), new Long(eMath.addInt(datetime.date(), datetime.ONE_DAY * 7)));
+
+    for (i = 0; i < events.length; i++) 
+    {
+        events[i].push([""])
+        var count = events[i][3];
+        var iconInfo = (count > 1 ? "gruppentermin" : "einzeltermin");
+        var icon = (getIcon("termine_aufgaben", iconInfo));
+        events[i] = events[i].concat(icon);
+    }
+    result.object(events);        
+    
+}
\ No newline at end of file
diff --git a/entity/Appointment_entity/entityfields/summary/valueProcess.js b/entity/Appointment_entity/entityfields/summary/valueProcess.js
new file mode 100644
index 00000000000..e8dc52cb185
--- /dev/null
+++ b/entity/Appointment_entity/entityfields/summary/valueProcess.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("system.vars");
+
+var sum = vars.getString("$field.SUMMARY");
+result.string(sum);
\ No newline at end of file
diff --git a/entity/Appointment_entity/onDelete.js b/entity/Appointment_entity/onDelete.js
new file mode 100644
index 00000000000..21038088ed6
--- /dev/null
+++ b/entity/Appointment_entity/onDelete.js
@@ -0,0 +1,17 @@
+import("system.neon");
+import("system.calendars");
+import("system.vars");
+
+if (vars.exists("$image.entry"))
+{
+    var entry = vars.get("$image.entry"); 
+    var reccurenceid = entry[calendars.RECURRENCEID];
+    if (reccurenceid == undefined) reccurenceid = null;
+    calendars.removeEntryByUID(calendars.VEVENT, vars.get("$sys.user"), entry[calendars.ID], reccurenceid)
+}
+
+if(vars.exists("$sys.ancestorimageuid") && vars.get("$sys.ancestorimageuid") != null)
+{
+    neon.closeImage(vars.getString("$sys.currentimage"), true);
+    neon.refresh(vars.get("$sys.ancestorimageuid"));
+}
\ No newline at end of file
diff --git a/entity/Appointment_entity/onInsert.js b/entity/Appointment_entity/onInsert.js
new file mode 100644
index 00000000000..0dd49954c32
--- /dev/null
+++ b/entity/Appointment_entity/onInsert.js
@@ -0,0 +1,359 @@
+import("system.neon");
+import("system.calendars");
+import("system.vars");
+import("system.question");
+import("system.translate");
+import("system.text");
+import("system.datetime");
+import("system.db");
+import("system.result");
+import("system.tools");
+
+// Dieser Prozess speichert die im Frame angezeigten Daten
+// Je nach Modus (INSERT, EDIT) wird ein neuer Datensatz angelegt oder der alte editiert
+var event = vars.get("$image.entry");
+
+var ok = false;
+
+event[calendars.TYPE] = calendars.VEVENT;
+event[calendars.STATUS] = vars.getString("$field.STATUS");
+event[calendars.SUMMARY] = vars.getString("$field.SUBJECT");
+event[calendars.LOCATION] = vars.get("$field.LOCATION");
+event[calendars.DESCRIPTION] = vars.get("$field.DESCRIPTION");
+event[calendars.DTSTART] = vars.get("$field.STARTDATE");
+event[calendars.DTEND] = vars.get("$field.ENDDATE");
+event[calendars.HASREMINDER] = "false";
+var hasReminder = vars.get("$field.REMINDER_CHECK");
+if (hasReminder == "true")
+{
+    // Absolut nur, wenn auch gesetzt. Default ist relativ
+    if ( event[calendars.REMINDER_ABSOLUT] == "true")
+    {
+        var reminder_date = vars.get("$field.REMINDER");
+        if ( reminder_date != "" )
+        {
+            event[calendars.HASREMINDER] = "true";
+            event[calendars.REMINDER_DATE] = reminder_date;
+        }
+    }
+//        else
+//        {
+//            var reminder_duration = vars.getString("$field.reminder_duration");
+//            if ( reminder_duration != "")
+//            {
+//                event[calendars.HASREMINDER] = "true";
+//                event[calendars.REMINDER_DURATION] = reminder_duration;
+//            }
+//        }
+}
+event[calendars.CLASSIFICATION] = vars.get("$field.CLASSIFICATION");
+//    event[calendars.TRANSPARENCY] = vars.get("$field.transparency");
+event[calendars.AFFECTEDUSERS] = getAffectedUsers( event );   
+//    event[calendars.CATEGORIES] = vars.get("$field.categories");
+//calcrecurrence(event);
+//if (event[calendars.RRULE] != undefined)     recurrencend(event);
+// Links updaten
+//    swing.saveTableEdit("$field.links");
+// Entweder jetzt neu anlegen oder nur updaten
+event[calendars.ID] = calendars.insert([event])[0];
+vars.set("$image.editmode", calendars.MODE_UPDATE);
+ok = true;
+
+////Zwischenspeichern
+//if(vars.exists("$image.dontClose") && vars.get("$image.dontClose") )    ok = false; //Maske offen lassen
+//vars.set("$image.dontClose",  false); // zurücksetzen, damit Klick auf Speichern noch funktioniert
+
+if(vars.exists("$sys.ancestorimageuid") && vars.get("$sys.ancestorimageuid") != null)
+{
+    neon.closeImage(vars.getString("$sys.currentimage"), true);
+    neon.refresh(vars.get("$sys.ancestorimageuid"));
+}
+
+
+// Liefert die AffectedUsers
+function getAffectedUsers( pEvent )
+{
+    var affectedusers = vars.get("$image.affectedusers");    
+    var attendess = pEvent[calendars.ATTENDEES]
+    var calendarusers = [];
+    for ( var i = 0; i < affectedusers.length; i++)   
+    {
+        var insert = true;
+        for ( var y = 0; y < attendess.length; y++)
+        {
+            // Teilnehmer schon vorhanden
+            if ( text.encodeMS( [attendess[y]["paramvalue"], "CN:" + attendess[y]["cn"]] ) == affectedusers[i][0] )
+            {
+                var userparts = [attendess[y]["paramvalue"]];
+                if ( affectedusers[i][1] != "" && affectedusers[i][1] != "UNKNOWN" )  attendess[y]["partstat"] = affectedusers[i][1];
+                for ( var part in attendess[y] )   if ( part != "paramvalue")  userparts.push(part + ":" + attendess[y][part] )
+                calendarusers.push( text.encodeMS(userparts) );
+                insert = false;
+                break;
+            }
+        }
+        if ( insert ) // Teilnehmer noch nicht im Termin vorhanden
+        {
+            var resource = db.cell("select THEME from THEME where THEMEID = '" + affectedusers[i][0] + "'");
+            if( resource != "" && tools.existUsers(resource) )   
+                calendarusers.push(text.encodeMS(text.decodeMS(calendars.getCalendarUser(resource)).concat("CUTYPE:RESOURCE")));
+            else    calendarusers.push(affectedusers[i][0]);
+        }
+    }
+    //    a.showMessage(calendarusers.join("\n"))
+    return text.encodeMS( calendarusers );
+}
+
+// Liefert die Benutzer zurück, auf die keine Schreibrechte bestehen
+function getReadOnlyUser()
+{
+    var writeable = calendars.getFullCalendarUsers(calendars.RIGHT_WRITE);	
+    var affectedusers = vars.get("$image.affectedusers");
+    var readonly = new Array();
+
+    for ( i = 0; i < affectedusers.length; i++)
+    {
+        var user = affectedusers[i][0];
+        if (!isWriteable(user, writeable))
+            readonly.push(affectedusers[i][3]);
+    }	
+    return readonly;	
+}
+
+// Liefert TRUE, wenn der Benutzer bei denen mit Schreibberechtigungen enthalten ist
+function isWriteable(user, writeable)
+{
+    for (var i = 0; i < writeable.length; i++)
+    {
+        if (writeable[i][0] == calendars.getCalendarUser(user))		
+            return true;
+    }	
+    return false;
+}
+
+// Berechnet das Ende der Recurrence
+function recurrencend(event)
+{
+    var rec_end = vars.getString("$field.rec_end");
+
+    // Automatische Erkennung, was gewollt ist
+    if (rec_end == "")
+    {
+        if (vars.get("$field.rec_end_count") != "")
+            rec_end = "Endet nach Anzahl Terminen";
+        else if (vars.get("$field.rec_end_date") != "")
+            rec_end = "Endet am";
+    }
+
+    if (rec_end == "" || rec_end == "Kein Enddatum")
+    {
+    // Nichts
+    }
+    else if (rec_end == "Endet nach Anzahl Terminen")
+    {
+        event[calendars.RRULE][0] += (";COUNT=" + vars.get("$field.rec_end_count"));
+    }
+    else if (rec_end == "Endet am")
+    {
+        var dat = vars.get("$field.rec_end_date");
+        var start = vars.get("$field.start_date");
+        var localTime = datetime.toDate(dat, translate.text("yyyyMMdd")) + datetime.toDate(start, "HHmmss");
+        var utcTime = datetime.toLong(localTime, "yyyyMMddHHmmss");
+        event[calendars.RRULE][0] += (";UNTIL=" + datetime.toDate(utcTime, "yyyyMMdd\'T\'HHmmss\'Z\'", "UTC"));
+    }
+}
+
+/**
+ * Berechnet die Wiederholung
+ *
+ * @param event Das fertige Event. Hier die Reccurrence speichern
+ */
+function calcrecurrence(event)
+{
+    var rec_type = vars.get("$field.rec_type");
+
+    if (rec_type == "")
+    {
+    // Nichts
+    }
+    else if (rec_type == "Keine")
+    {
+    }
+    else if (rec_type == "Täglich")
+    {
+        rec_daily(event);
+    }
+    else if (rec_type == "Wöchentlich")
+    {
+        rec_weekly(event);
+    }
+    else if (rec_type == "Monatlich")
+    {
+        rec_monthly(event);
+    }
+    else if (rec_type == "Jährlich")
+    {
+        rec_yearly(event);
+    }
+    else
+    {
+        question.showMessage("Internal (1) " + rec_type);
+    }
+}
+/***********************/
+function rec_yearly(event)
+{
+    var rec_year = vars.get("$field.rec_yearly");
+    var rec_yearly_month = vars.get("$field.rec_yearly_month");
+    var rec_yearly_day = vars.get("$field.rec_yearly_day");
+    var month;
+    var day;
+
+    if (rec_year == "")
+    {
+        if (rec_yearly_month != "" && rec_yearly_day != "")
+            rec_year = "Jeden # #";
+        else if (rec_yearly_month != "" && vars.get("$field.rec_yearly_day2") != "" && vars.get("$field.rec_yearly_number2") != "")
+            rec_year = "Am #. # im #";
+    }
+
+    if (rec_year == "" || (rec_yearly_month == "" && rec_yearly_day == "" ))
+    {
+        question.showMessage(translate.text("Jährliche Serie nicht genauer spezifiziert. Ignoriere Serie."));
+    }
+    else if (rec_year == "Jeden # #")
+    {
+        month = rec_yearly_month;
+        day = rec_yearly_day;
+        event[calendars.RRULE] = new Array("FREQ=YEARLY;BYMONTHDAY="+day+";BYMONTH="+month);
+    }
+    else if (rec_year == "Am #. # im #")
+    {
+        month = vars.get("$field.rec_yearly_month2");
+        day = vars.get("$field.rec_yearly_day2");
+        var number = vars.get("$field.rec_yearly_number2");
+        event[calendars.RRULE] = new Array("FREQ=YEARLY;BYMONTH="+month+";BYDAY="+number+day);
+    }
+}
+/***********************/
+function rec_monthly(event)
+{
+    var rec_month = vars.get("$field.rec_month");
+    var rec_monthly_day = vars.get("$field.rec_monthly_day");
+    var rec_monthly_interval = vars.get("$field.rec_monthly_interval");
+    var day;
+    var interval;
+
+    if (rec_month == "")
+
+    {
+        if (rec_monthly_day != "" && rec_monthly_interval != "")
+            rec_month = "Am #. jedes #. Monat";
+        else if (vars.get("$field.rec_monthly_day2") != "" && vars.get("$field.rec_monthly_interval2") != "" && vars.get("$field.rec_monthly_weekday2") != "")
+            rec_month = "Am #. # jeden #. Monat";
+    }
+
+    if (rec_month == "" || (rec_monthly_day == "" && rec_monthly_interval != ""))
+    {
+        question.showMessage(translate.text("Monatliche Serie nicht genauer spezifiziert. Ignoriere Serie."));
+    }
+    else if (rec_month == "Am #. jedes #. Monat")
+    {
+        day = rec_monthly_day;
+        interval = rec_monthly_interval;
+        event[calendars.RRULE] = new Array("FREQ=MONTHLY;INTERVAL=" + interval + ";BYMONTHDAY=" + day);
+    }
+    else if(rec_month == "Am #. # jeden #. Monat")
+    {
+        day = vars.get("$field.rec_monthly_day2");
+        interval = vars.get("$field.rec_monthly_interval2");
+        var weekday = vars.get("$field.rec_monthly_weekday2");
+        event[calendars.RRULE] = new Array("FREQ=MONTHLY;INTERVAL=" + interval + ";BYDAY=" + day + weekday);
+    }
+}
+/***********************/
+function rec_weekly(event)
+{
+
+    var rec_weekly_intervall = vars.get("$field.rec_weekly_intervall");
+    if (rec_weekly_intervall == "")
+        rec_weekly_intervall = "1";
+
+    var days = new Array();
+    var count = 0;
+    if (vars.get("$field.rec_weekly_mo") == "true")
+    {
+        days[count] = "MO";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_di") == "true")
+    {
+        days[count] = "TU";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_mi") == "true")
+    {
+        days[count] = "WE";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_do") == "true")
+    {
+        days[count] = "TH";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_fr") == "true")
+    {
+        days[count] = "FR";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_sa") == "true")
+    {
+        days[count] = "SA";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_so") == "true")
+    {
+        days[count] = "SU";
+        count++;
+    }
+    if (count > 0)
+    {
+        event[calendars.RRULE] = new Array("FREQ=WEEKLY;INTERVAL=" + rec_weekly_intervall + ";WKST=MO;BYDAY=");
+        for (var i = 0; i < count; i++)
+        {
+            event[calendars.RRULE][0] += days[i];
+            if (i+1 < count)
+            {
+                event[calendars.RRULE][0] += ",";
+            }
+        }
+    }
+}
+/***********************/
+function rec_daily(event)
+{
+    var rec_dailytype = vars.get("$field.rec_dailytype");
+    var rec_dailydays = vars.get("$field.rec_daily_days");
+    if (rec_dailytype == "")
+    {
+        if (rec_dailydays != "")
+            rec_dailytype = "Alle # Tage";
+    }
+
+    if (rec_dailytype == "" || rec_dailydays == "")
+    {
+        question.showMessage(translate.text("Tägliche Serie nicht genauer spezifiziert. Ignoriere Serie."));
+    }
+    else if (rec_dailytype == "Alle # Tage")
+    {
+        event[calendars.RRULE] = new Array("FREQ=DAILY;INTERVAL=" + rec_dailydays);
+    }
+    else if (rec_dailytype == "Jeden Arbeitstag")
+    {
+        event[calendars.RRULE][0] = new Array("FREQ=WEEKLY;WKST=MO;BYDAY=MO,TU,WE,TH,FR");
+    }
+    else
+    {
+        question.showMessage(translate.text("Internal (2)") + " " + rec_dailytype);
+    }
+}
\ No newline at end of file
diff --git a/entity/Appointment_entity/onUpdate.js b/entity/Appointment_entity/onUpdate.js
new file mode 100644
index 00000000000..77ab68ffa79
--- /dev/null
+++ b/entity/Appointment_entity/onUpdate.js
@@ -0,0 +1,368 @@
+import("system.neon");
+import("system.calendars");
+import("system.vars");
+import("system.question");
+import("system.translate");
+import("system.text");
+import("system.swing");
+import("system.datetime");
+import("system.db");
+import("system.result");
+import("system.tools");
+
+// Dieser Prozess speichert die im Frame angezeigten Daten
+// Je nach Modus (INSERT, EDIT) wird ein neuer Datensatz angelegt oder der alte editiert
+if(vars.exists("$image.entry"))
+{
+    var event = vars.get("$image.entry");
+
+    var ok = false;
+    if ( calendars.getBackendType() == calendars.BACKEND_EXCHANGEWS  && event[calendars.ORGANIZER2]["cn"] != event[calendars.USER2]["cn"])
+    {
+        question.showMessage(translate.text("Ein Gruppentermin kann nur durch den Organisator bearbeitet werden."));
+        ok = true;
+    }
+    else
+    {
+        event[calendars.TYPE] = calendars.VEVENT;
+        event[calendars.STATUS] = vars.getString("$field.STATUS");
+        event[calendars.SUMMARY] = vars.getString("$field.SUBJECT");
+        event[calendars.LOCATION] = vars.get("$field.LOCATION");
+        event[calendars.DESCRIPTION] = vars.get("$field.DESCRIPTION");
+        event[calendars.DTSTART] = vars.get("$field.STARTDATE");
+        event[calendars.DTEND] = vars.get("$field.ENDDATE");
+        event[calendars.HASREMINDER] = "false";
+        var hasReminder = vars.get("$field.REMINDER_CHECK");
+        if (hasReminder == "true")
+        {
+            // Absolut nur, wenn auch gesetzt. Default ist relativ
+            if ( event[calendars.REMINDER_ABSOLUT] == "true")
+            {
+                var reminder_date = vars.get("$field.REMINDER");
+                if ( reminder_date != "" )
+                {
+                    event[calendars.HASREMINDER] = "true";
+                    event[calendars.REMINDER_DATE] = reminder_date;
+                }
+            }
+        //        else
+        //        {
+        //            var reminder_duration = vars.getString("$comp.reminder_duration");
+        //            if ( reminder_duration != "")
+        //            {
+        //                event[calendars.HASREMINDER] = "true";
+        //                event[calendars.REMINDER_DURATION] = reminder_duration;
+        //            }
+        //        }
+        }
+            event[calendars.CLASSIFICATION] = vars.get("$field.CLASSIFICATION");
+        //    event[calendars.TRANSPARENCY] = vars.get("$comp.transparency");  
+            //event[calendars.AFFECTEDUSERS] = getAffectedUsers( event ); 
+        //    event[calendars.CATEGORIES] = vars.get("$comp.categories");
+        //    calcrecurrence(event);
+        //    if (event[calendars.RRULE] != undefined)     recurrencend(event);
+        // Links updaten
+        //swing.saveTableEdit("$comp.links");
+        // Entweder jetzt neu anlegen oder nur updaten
+
+        calendars.updateEntry(event);
+         
+        ok = true;
+    }
+    //    //Zwischenspeichern
+    //    if(vars.exists("$image.dontClose") && vars.get("$image.dontClose") )    ok = false; //Maske offen lassen
+    //    vars.set("$image.dontClose",  false); // zurücksetzen, damit Klick auf Speichern noch funktioniert
+
+    
+   if(vars.exists("$sys.ancestorimageuid") && vars.get("$sys.ancestorimageuid") != null)
+    {
+        neon.closeImage(vars.getString("$sys.currentimage"), true);
+        neon.refresh(vars.get("$sys.ancestorimageuid"));
+    }
+}
+// Liefert die AffectedUsers
+function getAffectedUsers( pEvent )
+{
+        var affectedusers = vars.get("$image.affectedusers");   
+        var attendess = pEvent[calendars.ATTENDEES]
+        var calendarusers = [];
+        for ( var i = 0; i < affectedusers.length; i++)   
+        {
+            var insert = true;
+            for ( var y = 0; y < attendess.length; y++)
+            {
+                // Teilnehmer schon vorhanden
+                if ( text.encodeMS( [attendess[y]["paramvalue"], "CN:" + attendess[y]["cn"]] ) == affectedusers[i][0] )
+                {
+                    var userparts = [attendess[y]["paramvalue"]];
+                    if ( affectedusers[i][1] != "" && affectedusers[i][1] != "UNKNOWN" )  attendess[y]["partstat"] = affectedusers[i][1];
+                    for ( var part in attendess[y] )   if ( part != "paramvalue")  userparts.push(part + ":" + attendess[y][part] )
+                    calendarusers.push( text.encodeMS(userparts) );
+                    insert = false;
+                    break;
+                }
+            }
+            if ( insert ) // Teilnehmer noch nicht im Termin vorhanden
+            {
+                var resource = db.cell("select THEME from THEME where THEMEID = '" + affectedusers[i][0] + "'");
+                if( resource != "" && tools.existUsers(resource) )   
+                    calendarusers.push(text.encodeMS(text.decodeMS(calendars.getCalendarUser(resource)).concat("CUTYPE:RESOURCE")));
+                else    calendarusers.push(affectedusers[i][0]);
+            }
+        }
+        return text.encodeMS( calendarusers );
+    }
+
+// Liefert die Benutzer zurück, auf die keine Schreibrechte bestehen
+function getReadOnlyUser()
+{
+    var writeable = calendars.getFullCalendarUsers(calendars.RIGHT_WRITE);	
+    var affectedusers = vars.get("$image.affectedusers");
+    var readonly = new Array();
+
+    for ( i = 0; i < affectedusers.length; i++)
+    {
+        var user = affectedusers[i][0];
+        if (!isWriteable(user, writeable))
+            readonly.push(affectedusers[i][3]);
+    }	
+    return readonly;	
+}
+
+// Liefert TRUE, wenn der Benutzer bei denen mit Schreibberechtigungen enthalten ist
+function isWriteable(user, writeable)
+{
+    for (var i = 0; i < writeable.length; i++)
+    {
+        if (writeable[i][0] == calendars.getCalendarUser(user))		
+            return true;
+    }	
+    return false;
+}
+
+// Berechnet das Ende der Recurrence
+function recurrencend(event)
+{
+    var rec_end = vars.getString("$comp.rec_end");
+
+    // Automatische Erkennung, was gewollt ist
+    if (rec_end == "")
+    {
+        if (vars.get("$comp.rec_end_count") != "")
+            rec_end = "Endet nach Anzahl Terminen";
+        else if (vars.get("$comp.rec_end_date") != "")
+            rec_end = "Endet am";
+    }
+
+    if (rec_end == "" || rec_end == "Kein Enddatum")
+    {
+    // Nichts
+    }
+    else if (rec_end == "Endet nach Anzahl Terminen")
+    {
+        event[calendars.RRULE][0] += (";COUNT=" + vars.get("$comp.rec_end_count"));
+    }
+    else if (rec_end == "Endet am")
+    {
+        var dat = vars.get("$comp.rec_end_date");
+        var start = vars.get("$comp.start_date");
+        var localTime = datetime.toDate(dat, translate.text("yyyyMMdd")) + datetime.toDate(start, "HHmmss");
+        var utcTime = datetime.toLong(localTime, "yyyyMMddHHmmss");
+        event[calendars.RRULE][0] += (";UNTIL=" + datetime.toDate(utcTime, "yyyyMMdd\'T\'HHmmss\'Z\'", "UTC"));
+    }
+}
+
+/**
+ * Berechnet die Wiederholung
+ *
+ * @param event Das fertige Event. Hier die Reccurrence speichern
+ */
+function calcrecurrence(event)
+{
+    var rec_type = vars.get("$comp.rec_type");
+
+    if (rec_type == "")
+    {
+    // Nichts
+    }
+    else if (rec_type == "Keine")
+    {
+    }
+    else if (rec_type == "Täglich")
+    {
+        rec_daily(event);
+    }
+    else if (rec_type == "Wöchentlich")
+    {
+        rec_weekly(event);
+    }
+    else if (rec_type == "Monatlich")
+    {
+        rec_monthly(event);
+    }
+    else if (rec_type == "Jährlich")
+    {
+        rec_yearly(event);
+    }
+    else
+    {
+        question.showMessage("Internal (1) " + rec_type);
+    }
+}
+/***********************/
+function rec_yearly(event)
+{
+    var rec_year = vars.get("$comp.rec_yearly");
+    var rec_yearly_month = vars.get("$comp.rec_yearly_month");
+    var rec_yearly_day = vars.get("$comp.rec_yearly_day");
+    var month;
+    var day;
+
+    if (rec_year == "")
+    {
+        if (rec_yearly_month != "" && rec_yearly_day != "")
+            rec_year = "Jeden # #";
+        else if (rec_yearly_month != "" && vars.get("$comp.rec_yearly_day2") != "" && vars.get("$comp.rec_yearly_number2") != "")
+            rec_year = "Am #. # im #";
+    }
+
+    if (rec_year == "" || (rec_yearly_month == "" && rec_yearly_day == "" ))
+    {
+        question.showMessage(translate.text("Jährliche Serie nicht genauer spezifiziert. Ignoriere Serie."));
+    }
+    else if (rec_year == "Jeden # #")
+    {
+        month = rec_yearly_month;
+        day = rec_yearly_day;
+        event[calendars.RRULE] = new Array("FREQ=YEARLY;BYMONTHDAY="+day+";BYMONTH="+month);
+    }
+    else if (rec_year == "Am #. # im #")
+    {
+        month = vars.get("$comp.rec_yearly_month2");
+        day = vars.get("$comp.rec_yearly_day2");
+        var number = vars.get("$comp.rec_yearly_number2");
+        event[calendars.RRULE] = new Array("FREQ=YEARLY;BYMONTH="+month+";BYDAY="+number+day);
+    }
+}
+/***********************/
+function rec_monthly(event)
+{
+    var rec_month = vars.get("$comp.rec_month");
+    var rec_monthly_day = vars.get("$comp.rec_monthly_day");
+    var rec_monthly_interval = vars.get("$comp.rec_monthly_interval");
+    var day;
+    var interval;
+
+    if (rec_month == "")
+
+    {
+        if (rec_monthly_day != "" && rec_monthly_interval != "")
+            rec_month = "Am #. jedes #. Monat";
+        else if (vars.get("$comp.rec_monthly_day2") != "" && vars.get("$comp.rec_monthly_interval2") != "" && vars.get("$comp.rec_monthly_weekday2") != "")
+            rec_month = "Am #. # jeden #. Monat";
+    }
+
+    if (rec_month == "" || (rec_monthly_day == "" && rec_monthly_interval != ""))
+    {
+        question.showMessage(translate.text("Monatliche Serie nicht genauer spezifiziert. Ignoriere Serie."));
+    }
+    else if (rec_month == "Am #. jedes #. Monat")
+    {
+        day = rec_monthly_day;
+        interval = rec_monthly_interval;
+        event[calendars.RRULE] = new Array("FREQ=MONTHLY;INTERVAL=" + interval + ";BYMONTHDAY=" + day);
+    }
+    else if(rec_month == "Am #. # jeden #. Monat")
+    {
+        day = vars.get("$comp.rec_monthly_day2");
+        interval = vars.get("$comp.rec_monthly_interval2");
+        var weekday = vars.get("$comp.rec_monthly_weekday2");
+        event[calendars.RRULE] = new Array("FREQ=MONTHLY;INTERVAL=" + interval + ";BYDAY=" + day + weekday);
+    }
+}
+/***********************/
+function rec_weekly(event)
+{
+
+    var rec_weekly_intervall = vars.get("$comp.rec_weekly_intervall");
+    if (rec_weekly_intervall == "")
+        rec_weekly_intervall = "1";
+
+    var days = new Array();
+    var count = 0;
+    if (vars.get("$comp.rec_weekly_mo") == "true")
+    {
+        days[count] = "MO";
+        count++;
+    }
+    if (vars.get("$comp.rec_weekly_di") == "true")
+    {
+        days[count] = "TU";
+        count++;
+    }
+    if (vars.get("$comp.rec_weekly_mi") == "true")
+    {
+        days[count] = "WE";
+        count++;
+    }
+    if (vars.get("$comp.rec_weekly_do") == "true")
+    {
+        days[count] = "TH";
+        count++;
+    }
+    if (vars.get("$comp.rec_weekly_fr") == "true")
+    {
+        days[count] = "FR";
+        count++;
+    }
+    if (vars.get("$comp.rec_weekly_sa") == "true")
+    {
+        days[count] = "SA";
+        count++;
+    }
+    if (vars.get("$comp.rec_weekly_so") == "true")
+    {
+        days[count] = "SU";
+        count++;
+    }
+    if (count > 0)
+    {
+        event[calendars.RRULE] = new Array("FREQ=WEEKLY;INTERVAL=" + rec_weekly_intervall + ";WKST=MO;BYDAY=");
+        for (var i = 0; i < count; i++)
+        {
+            event[calendars.RRULE][0] += days[i];
+            if (i+1 < count)
+            {
+                event[calendars.RRULE][0] += ",";
+            }
+        }
+    }
+}
+/***********************/
+function rec_daily(event)
+{
+    var rec_dailytype = vars.get("$comp.rec_dailytype");
+    var rec_dailydays = vars.get("$comp.rec_daily_days");
+    if (rec_dailytype == "")
+    {
+        if (rec_dailydays != "")
+            rec_dailytype = "Alle # Tage";
+    }
+
+    if (rec_dailytype == "" || rec_dailydays == "")
+    {
+        question.showMessage(translate.text("Tägliche Serie nicht genauer spezifiziert. Ignoriere Serie."));
+    }
+    else if (rec_dailytype == "Alle # Tage")
+    {
+        event[calendars.RRULE] = new Array("FREQ=DAILY;INTERVAL=" + rec_dailydays);
+    }
+    else if (rec_dailytype == "Jeden Arbeitstag")
+    {
+        event[calendars.RRULE][0] = new Array("FREQ=WEEKLY;WKST=MO;BYDAY=MO,TU,WE,TH,FR");
+    }
+    else
+    {
+        question.showMessage(translate.text("Internal (2)") + " " + rec_dailytype);
+    }
+}
\ No newline at end of file
diff --git a/neonContext/Appointment_context/Appointment_context.aod b/neonContext/Appointment_context/Appointment_context.aod
new file mode 100644
index 00000000000..96cb8c162a3
--- /dev/null
+++ b/neonContext/Appointment_context/Appointment_context.aod
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.0.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.0.0">
+  <name>Appointment_context</name>
+  <title>Termin</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <icon>VAADIN:CALENDAR</icon>
+  <mainview>AppointmentEdit_view</mainview>
+  <filterview>AppointmentPreview_view</filterview>
+  <editview>AppointmentEdit_view</editview>
+  <preview>AppointmentPreview_view</preview>
+  <entity>Appointment_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>90fe74fe-9bc6-4f63-9c06-52e1b0ccfcb3</name>
+      <view>AppointmentEdit_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>9cf48e57-ca02-4cee-911c-20b09e36637d</name>
+      <view>AppointmentPreview_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonContext/Org_context/Org_context.aod b/neonContext/Org_context/Org_context.aod
index cb19560598e..c9a5b204f3b 100644
--- a/neonContext/Org_context/Org_context.aod
+++ b/neonContext/Org_context/Org_context.aod
@@ -4,6 +4,7 @@
   <title>Company</title>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <icon>VAADIN:BUILDING</icon>
+  <iconProcess>%aditoprj%/neonContext/Org_context/iconProcess.js</iconProcess>
   <mainview>OrgMain_view</mainview>
   <filterview>OrgFilter_view</filterview>
   <editview>OrgEdit_view</editview>
diff --git a/neonContext/Org_context/iconProcess.js b/neonContext/Org_context/iconProcess.js
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/neonView/AppointmentEdit_view/AppointmentEdit_view.aod b/neonView/AppointmentEdit_view/AppointmentEdit_view.aod
new file mode 100644
index 00000000000..8bb02c87b7b
--- /dev/null
+++ b/neonView/AppointmentEdit_view/AppointmentEdit_view.aod
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.0.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.0.0">
+  <name>AppointmentEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <appointmentEditViewTemplate>
+      <name>AppointmentEditTemplate</name>
+      <summaryField>SUMMARY</summaryField>
+      <beginField>SUMMARY</beginField>
+      <endField>SUMMARY</endField>
+      <affectedUsersField>SUMMARY</affectedUsersField>
+      <attendeesField>SUMMARY</attendeesField>
+      <privateField>SUMMARY</privateField>
+      <statusField>SUMMARY</statusField>
+      <locationField>SUMMARY</locationField>
+      <entityField>#ENTITY</entityField>
+    </appointmentEditViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/AppointmentPreview_view/AppointmentPreview_view.aod b/neonView/AppointmentPreview_view/AppointmentPreview_view.aod
new file mode 100644
index 00000000000..2d360e85afc
--- /dev/null
+++ b/neonView/AppointmentPreview_view/AppointmentPreview_view.aod
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.0.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.0.0">
+  <name>AppointmentPreview_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <appointmentPreviewViewTemplate>
+      <name>AppointmentPreviewTemplate</name>
+      <summaryField>SUMMARY</summaryField>
+      <periodField>SUMMARY</periodField>
+      <affectedUsersField>SUMMARY</affectedUsersField>
+      <attendeesField>SUMMARY</attendeesField>
+      <privateField>SUMMARY</privateField>
+      <statusField>SUMMARY</statusField>
+      <entityField>#ENTITY</entityField>
+    </appointmentPreviewViewTemplate>
+  </children>
+</neonView>
diff --git a/preferences/_____PREFERENCES_PROJECT/_____PREFERENCES_PROJECT.aod b/preferences/_____PREFERENCES_PROJECT/_____PREFERENCES_PROJECT.aod
index 0b8e255da51..2e9d98b454f 100644
--- a/preferences/_____PREFERENCES_PROJECT/_____PREFERENCES_PROJECT.aod
+++ b/preferences/_____PREFERENCES_PROJECT/_____PREFERENCES_PROJECT.aod
@@ -2,7 +2,7 @@
 <preferences xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="3.0.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/preferences/3.0.1">
   <name>_____PREFERENCES_PROJECT</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
-  <projectName>xRM-Basic-5</projectName>
+  <projectName>xRM-Basic 5</projectName>
   <jditoMaxContentSize v="57671680" />
   <clientSearchOptimizedForSpeed v="true" />
   <clientSearchExcludeForIgnorecase v="true" />
diff --git a/process/openCalendarProzess/openCalendarProzess.aod b/process/openCalendarProzess/openCalendarProzess.aod
new file mode 100644
index 00000000000..fe47bdfc013
--- /dev/null
+++ b/process/openCalendarProzess/openCalendarProzess.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.7" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.1.7">
+  <name>openCalendarProzess</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/openCalendarProzess/process.js</process>
+</process>
diff --git a/process/openCalendarProzess/process.js b/process/openCalendarProzess/process.js
new file mode 100644
index 00000000000..806b2cf096d
--- /dev/null
+++ b/process/openCalendarProzess/process.js
@@ -0,0 +1,8 @@
+import("system.swing");
+import("system.calendars");
+
+var windowmode;//value of this variable is defined by the ADITO-kernel automatically;
+if (windowmode == undefined)
+	  windowmode = swing.WINDOW_CURRENT;
+
+swing.openCalendar(windowmode, calendars.SHOW_CAL | calendars.SHOW_DATE | calendars.SHOW_USER, calendars.VIEWMODE_DEFAULT, false , [], [], true);
\ No newline at end of file
-- 
GitLab