commit 59e17af2ab165f2e2db22ff3831822d17ba8b8ff
Author: SebastianDiel <sebastian.diel@web.de>
Date:   Mon Jan 2 17:40:38 2017 +0100

    Trying to set up a test case for #629, new problem with "silent" crash

diff --git a/samples/example/models/pupil.h b/samples/example/models/pupil.h
index c3dc9db..33b1440 100644
--- a/samples/example/models/pupil.h
+++ b/samples/example/models/pupil.h
@@ -4,6 +4,7 @@
 
 class Pupil : public Person {
     Q_OBJECT
+    EM_MACRO(Pupil)
     Q_PROPERTY(QString legalGuardianNote READ getLegalGuardianNote WRITE
                setLegalGuardianNote)
   public:
diff --git a/samples/simple/address.cpp b/samples/simple/address.cpp
new file mode 100644
index 0000000..a000d55
--- /dev/null
+++ b/samples/simple/address.cpp
@@ -0,0 +1,69 @@
+#include "address.h"
+#include "pupil.h"
+
+Address::Address(QString label, QString street, QString postcode,
+                 QString city) {
+    this->label = label;
+    this->street = street;
+    this->postcode = postcode;
+    this->city = city;
+}
+
+QString Address::getLabel() const {
+    return label;
+}
+
+void Address::setLabel(const QString &value) {
+    label = value;
+}
+
+QString Address::getStreet() const {
+    return street;
+}
+
+void Address::setStreet(const QString &value) {
+    street = value;
+}
+
+QString Address::getPostcode() const {
+    return postcode;
+}
+
+void Address::setPostcode(const QString &value) {
+    postcode = value;
+}
+
+QString Address::getCity() const {
+    return city;
+}
+
+void Address::setCity(const QString &value) {
+    city = value;
+}
+
+QList<QSharedPointer<Person> > Address::getPersons() const {
+    return persons;
+}
+
+void Address::setPersons(const QList<QSharedPointer<Person> > &value) {
+    persons = value;
+}
+
+const QHash<QString, CuteEntityManager::Relation> Address::getRelations()
+const {
+    auto hash = Entity::getRelations();
+    hash.insert("persons", CuteEntityManager::Relation("persons",
+                RelationType::MANY_TO_MANY,
+                QString("addresses")));
+    return hash;
+}
+
+QList<QSharedPointer<Pupil> > Address::getPupils() const {
+    return pupils;
+}
+
+void Address::setPupils(const QList<QSharedPointer<Pupil> > &value) {
+    pupils = value;
+}
+
+
diff --git a/samples/simple/address.h b/samples/simple/address.h
new file mode 100644
index 0000000..dc2ee5d
--- /dev/null
+++ b/samples/simple/address.h
@@ -0,0 +1,54 @@
+#ifndef ADDRESS_H
+#define ADDRESS_H
+
+#include <QString>
+#include <QHash>
+#include "entity.h"
+
+class Person;
+class Relation;
+class Pupil;
+class Address: public CuteEntityManager::Entity {
+    Q_OBJECT
+    EM_MACRO(Address)
+    Q_PROPERTY(QString label READ getLabel WRITE setLabel)
+    Q_PROPERTY(QString street READ getStreet WRITE setStreet)
+    Q_PROPERTY(QString postcode READ getPostcode WRITE setPostcode)
+    Q_PROPERTY(QString city READ getCity WRITE setCity)
+    Q_PROPERTY(QList<QSharedPointer<Person>> persons READ
+               getPersons WRITE setPersons)
+
+  public:
+    Q_INVOKABLE Address() {}
+    Address(QString label, QString street, QString postcode, QString city);
+
+    QString getLabel() const;
+    void setLabel(const QString &value);
+
+    QString getStreet() const;
+    void setStreet(const QString &value);
+
+    QString getPostcode() const;
+    void setPostcode(const QString &value);
+
+    QString getCity() const;
+    void setCity(const QString &value);
+
+    QList<QSharedPointer<Person> > getPersons() const;
+    void setPersons(const QList<QSharedPointer<Person> > &value);
+
+    const QHash<QString, CuteEntityManager::Relation> getRelations() const override;
+
+    QList<QSharedPointer<Pupil> > getPupils() const;
+    void setPupils(const QList<QSharedPointer<Pupil> > &value);
+
+protected:
+    QString label;
+    QString street;
+    QString postcode;
+    QString city;
+    QList<QSharedPointer<Person>> persons;
+    QList<QSharedPointer<Pupil>> pupils;
+};
+
+#endif // ADDRESS_H
diff --git a/samples/simple/contact.cpp b/samples/simple/contact.cpp
new file mode 100644
index 0000000..8e88d50
--- /dev/null
+++ b/samples/simple/contact.cpp
@@ -0,0 +1,56 @@
+#include "contact.h"
+#include "pupil.h"
+
+Contact::Contact(QString label, Category category, QString content) {
+    this->label = label;
+    this->category = category;
+    this->content = content;
+}
+
+const QHash<QString, CuteEntityManager::Relation> Contact::getRelations()
+const {
+    auto hash = Entity::getRelations();
+    hash.insert("persons", CuteEntityManager::Relation("persons",
+                RelationType::MANY_TO_MANY,
+                QString("contacts")));
+    return hash;
+}
+
+QString Contact::getContent() const {
+    return content;
+}
+
+void Contact::setContent(const QString &value) {
+    content = value;
+}
+
+QString Contact::getLabel() const {
+    return label;
+}
+
+void Contact::setLabel(const QString &value) {
+    label = value;
+}
+Contact::Category Contact::getCategory() const {
+    return category;
+}
+
+void Contact::setCategory(const Category &value) {
+    category = value;
+}
+
+QList<QSharedPointer<Person> > Contact::getPersons() const {
+    return persons;
+}
+
+void Contact::setPersons(const QList<QSharedPointer<Person> > &value) {
+    persons = value;
+}
+
+QList<QSharedPointer<Pupil> > Contact::getPupils() const {
+    return pupils;
+}
+
+void Contact::setPupils(const QList<QSharedPointer<Pupil> > &value) {
+    pupils = value;
+}
diff --git a/samples/simple/contact.h b/samples/simple/contact.h
new file mode 100644
index 0000000..736ab80
--- /dev/null
+++ b/samples/simple/contact.h
@@ -0,0 +1,49 @@
+#ifndef CONTACT_H
+#define CONTACT_H
+
+#include <QString>
+#include "entity.h"
+
+class Relation;
+class Person;
+class Pupil;
+class Contact: public CuteEntityManager::Entity {
+    Q_OBJECT
+    EM_MACRO(Contact)
+    Q_PROPERTY(QString content READ getContent WRITE setContent)
+    Q_PROPERTY(Category category READ getCategory WRITE setCategory)
+    Q_PROPERTY(QString label READ getLabel WRITE setLabel)
+    Q_PROPERTY(QList<QSharedPointer<Person>> persons READ
+               getPersons WRITE setPersons)
+
+  public:
+    enum Category {EMAIL, MOBILE, LANDLINE, MESSENGER, EXTRA} ;
+    Q_INVOKABLE Contact() {}
+    Contact(QString label, Category category, QString content);
+    const QHash<QString, CuteEntityManager::Relation> getRelations() const
+    override;
+
+    QString getContent() const;
+    void setContent(const QString &value);
+
+    QString getLabel() const;
+    void setLabel(const QString &value);
+
+    Category getCategory() const;
+    void setCategory(const Category &value);
+
+    QList<QSharedPointer<Person> > getPersons() const;
+    void setPersons(const QList<QSharedPointer<Person> > &value);
+
+    QList<QSharedPointer<Pupil> > getPupils() const;
+    void setPupils(const QList<QSharedPointer<Pupil> > &value);
+
+protected:
+    QString content;
+    Category category;
+    QString label;
+    QList<QSharedPointer<Person>> persons;
+    QList<QSharedPointer<Pupil>> pupils;
+};
+
+#endif // CONTACT_H
diff --git a/samples/simple/datacreation.cpp b/samples/simple/datacreation.cpp
new file mode 100644
index 0000000..c89a50a
--- /dev/null
+++ b/samples/simple/datacreation.cpp
@@ -0,0 +1,289 @@
+#include "datacreation.h"
+#include "ratingmarksystem.h"
+
+
+DataCreation::DataCreation()
+{
+
+}
+
+QList<QSharedPointer<Entity> > DataCreation::createRatingEntities()
+{
+    QList<QSharedPointer<Entity>> resultList;
+
+
+    QSharedPointer<RatingMarkSystem>ratingSystem2;
+    ratingSystem2 = QSharedPointer<RatingMarkSystem>(new RatingMarkSystem());
+    ratingSystem2->setName("15 bis 0 Punkte als 1+ bis 6");
+    ratingSystem2->setPanelColumns(4);
+    ratingSystem2->setPanelRows(6);
+    ratingSystem2->setValuesComputable(true);
+    ratingSystem2->setDigits(0);
+    ratingSystem2->setHigherValueBetter(true);
+    resultList.append(ratingSystem2);
+
+    QList<QSharedPointer<RatingMarkDefinition>> rateSystem2Definitions;
+
+    QSharedPointer<RatingMarkDefinition>def2_1p;
+    def2_1p = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_1p->setSymbol("1+");
+    def2_1p->setMinValue(14.5);
+    def2_1p->setValueEquivalent(15);
+    def2_1p->setMinPercent(95);
+    def2_1p->setPercentEquivalent(97.5);
+    def2_1p->setRateable(true);
+    def2_1p->setRatingMarkSystem(ratingSystem2);
+    def2_1p->setPanelColumn(1);
+    def2_1p->setPanelRow(1);
+    resultList.append(def2_1p);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_1;
+    def2_1 = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_1->setSymbol("1");
+    def2_1->setMinValue(13.5);
+    def2_1->setValueEquivalent(14);
+    def2_1->setMinPercent(90);
+    def2_1->setPercentEquivalent(92.5);
+    def2_1->setRateable(true);
+    def2_1->setRatingMarkSystem(ratingSystem2);
+    def2_1->setPanelColumn(2);
+    def2_1->setPanelRow(1);
+    resultList.append(def2_1);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_1m;
+    def2_1m = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_1m->setSymbol("1-");
+    def2_1m->setMinValue(12.5);
+    def2_1m->setValueEquivalent(13);
+    def2_1m->setMinPercent(85);
+    def2_1m->setPercentEquivalent(87.5);
+    def2_1m->setRateable(true);
+    def2_1m->setRatingMarkSystem(ratingSystem2);
+    def2_1m->setPanelColumn(3);
+    def2_1m->setPanelRow(1);
+    resultList.append(def2_1m);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_2p;
+    def2_2p = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_2p->setSymbol("2+");
+    def2_2p->setMinValue(11.5);
+    def2_2p->setValueEquivalent(12);
+    def2_2p->setMinPercent(80);
+    def2_2p->setPercentEquivalent(82.5);
+    def2_2p->setRateable(true);
+    def2_2p->setRatingMarkSystem(ratingSystem2);
+    def2_2p->setPanelColumn(1);
+    def2_2p->setPanelRow(2);
+    resultList.append(def2_2p);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_2;
+    def2_2 = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_2->setSymbol("2");
+    def2_2->setMinValue(10.5);
+    def2_2->setValueEquivalent(11);
+    def2_2->setMinPercent(75);
+    def2_2->setPercentEquivalent(77.5);
+    def2_2->setRateable(true);
+    def2_2->setRatingMarkSystem(ratingSystem2);
+    def2_2->setPanelColumn(2);
+    def2_2->setPanelRow(2);
+    resultList.append(def2_2);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_2m;
+    def2_2m = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_2m->setSymbol("2-");
+    def2_2m->setMinValue(9.5);
+    def2_2m->setValueEquivalent(10);
+    def2_2m->setMinPercent(70);
+    def2_2m->setPercentEquivalent(72.5);
+    def2_2m->setRateable(true);
+    def2_2m->setRatingMarkSystem(ratingSystem2);
+    def2_2m->setPanelColumn(3);
+    def2_2m->setPanelRow(2);
+    resultList.append(def2_2m);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_3p;
+    def2_3p = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_3p->setSymbol("3+");
+    def2_3p->setMinValue(8.5);
+    def2_3p->setValueEquivalent(9);
+    def2_3p->setMinPercent(65);
+    def2_3p->setPercentEquivalent(67.5);
+    def2_3p->setRateable(true);
+    def2_3p->setRatingMarkSystem(ratingSystem2);
+    def2_3p->setPanelColumn(1);
+    def2_3p->setPanelRow(3);
+    resultList.append(def2_3p);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_3;
+    def2_3 = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_3->setSymbol("3");
+    def2_3->setMinValue(7.5);
+    def2_3->setValueEquivalent(8);
+    def2_3->setMinPercent(60);
+    def2_3->setPercentEquivalent(62.5);
+    def2_3->setRateable(true);
+    def2_3->setRatingMarkSystem(ratingSystem2);
+    def2_3->setPanelColumn(2);
+    def2_3->setPanelRow(3);
+    resultList.append(def2_3);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_3m;
+    def2_3m = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_3m->setSymbol("3-");
+    def2_3m->setMinValue(6.5);
+    def2_3m->setValueEquivalent(7);
+    def2_3m->setMinPercent(55);
+    def2_3m->setPercentEquivalent(57.5);
+    def2_3m->setRateable(true);
+    def2_3m->setRatingMarkSystem(ratingSystem2);
+    def2_3m->setPanelColumn(3);
+    def2_3m->setPanelRow(3);
+    resultList.append(def2_3m);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_4p;
+    def2_4p = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_4p->setSymbol("4+");
+    def2_4p->setMinValue(5.5);
+    def2_4p->setValueEquivalent(6);
+    def2_4p->setMinPercent(50);
+    def2_4p->setPercentEquivalent(52.5);
+    def2_4p->setRateable(true);
+    def2_4p->setRatingMarkSystem(ratingSystem2);
+    def2_4p->setPanelColumn(1);
+    def2_4p->setPanelRow(4);
+    resultList.append(def2_4p);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_4;
+    def2_4 = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_4->setSymbol("4");
+    def2_4->setMinValue(4.5);
+    def2_4->setValueEquivalent(5);
+    def2_4->setMinPercent(45);
+    def2_4->setPercentEquivalent(47.5);
+    def2_4->setRateable(true);
+    def2_4->setRatingMarkSystem(ratingSystem2);
+    def2_4->setPanelColumn(2);
+    def2_4->setPanelRow(4);
+    resultList.append(def2_4);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_4m;
+    def2_4m = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_4m->setSymbol("4-");
+    def2_4m->setMinValue(3.5);
+    def2_4m->setValueEquivalent(4);
+    def2_4m->setMinPercent(39);
+    def2_4m->setPercentEquivalent(42);
+    def2_4m->setRateable(true);
+    def2_4m->setRatingMarkSystem(ratingSystem2);
+    def2_4m->setPanelColumn(3);
+    def2_4m->setPanelRow(4);
+    resultList.append(def2_4m);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_5p;
+    def2_5p = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_5p->setSymbol("5+");
+    def2_5p->setMinValue(2.5);
+    def2_5p->setValueEquivalent(3);
+    def2_5p->setMinPercent(33);
+    def2_5p->setPercentEquivalent(36);
+    def2_5p->setRateable(true);
+    def2_5p->setRatingMarkSystem(ratingSystem2);
+    def2_5p->setPanelColumn(1);
+    def2_5p->setPanelRow(5);
+    resultList.append(def2_5p);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_5;
+    def2_5 = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_5->setSymbol("5");
+    def2_5->setMinValue(1.5);
+    def2_5->setValueEquivalent(2);
+    def2_5->setMinPercent(27);
+    def2_5->setPercentEquivalent(30);
+    def2_5->setRateable(true);
+    def2_5->setRatingMarkSystem(ratingSystem2);
+    def2_5->setPanelColumn(2);
+    def2_5->setPanelRow(5);
+    resultList.append(def2_5);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_5m;
+    def2_5m = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_5m->setSymbol("5-");
+    def2_5m->setMinValue(0.5);
+    def2_5m->setValueEquivalent(1);
+    def2_5m->setMinPercent(20);
+    def2_5m->setPercentEquivalent(23.5);
+    def2_5m->setRateable(true);
+    def2_5m->setRatingMarkSystem(ratingSystem2);
+    def2_5m->setPanelColumn(3);
+    def2_5m->setPanelRow(5);
+    resultList.append(def2_5m);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_6;
+    def2_6 = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_6->setSymbol("6");
+    def2_6->setMinValue(0);
+    def2_6->setValueEquivalent(0);
+    def2_6->setMinPercent(0);
+    def2_6->setPercentEquivalent(10);
+    def2_6->setRateable(true);
+    def2_6->setRatingMarkSystem(ratingSystem2);
+    def2_6->setPanelColumn(0);
+    def2_6->setPanelRow(5);
+    resultList.append(def2_6);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    QSharedPointer<RatingMarkDefinition>def2_NotRated;
+    def2_NotRated = QSharedPointer<RatingMarkDefinition>(new RatingMarkDefinition());
+    def2_NotRated->setSymbol("NB");
+    def2_NotRated->setMinValue(9999);
+    def2_NotRated->setValueEquivalent(9999);
+    def2_NotRated->setMinPercent(9999);
+    def2_NotRated->setPercentEquivalent(9999);
+    def2_NotRated->setRateable(false);
+    def2_NotRated->setRatingMarkSystem(ratingSystem2);
+    def2_NotRated->setPanelColumn(0);
+    def2_NotRated->setPanelRow(4);
+    resultList.append(def2_NotRated);
+    rateSystem2Definitions.append(resultList.last().objectCast<RatingMarkDefinition>());
+
+    ratingSystem2->setRatingMarkDefinitions(rateSystem2Definitions);
+
+
+
+
+//    QSharedPointer<AppRatingData>appRatingData = QSharedPointer<AppRatingData>(new AppRatingData());
+//    appRatingData->setRatingMarkSystem(ratingSystem2);
+//    appRatingData->setIconName("ratingIcon.svg");
+//    appRatingData->setAllowMultipleRatingsPerLesson(true);
+
+//    appRatingData->setName("Bewertung1-6");
+//    appRatingData->setTeachersDeskPosition(4);
+//    resultList.append(appRatingData);
+
+
+    ratingSystem2->setAdditionalInfo("sys2");
+    auto now = QDateTime::currentDateTime();
+    ratingSystem2->setBookedAt(now);
+    ratingSystem2->setBookedFor(now);
+
+    return resultList;
+
+
+
+}
diff --git a/samples/simple/datacreation.h b/samples/simple/datacreation.h
new file mode 100644
index 0000000..c46c8d4
--- /dev/null
+++ b/samples/simple/datacreation.h
@@ -0,0 +1,28 @@
+#ifndef DATACREATION_H
+#define DATACREATION_H
+
+#include <QSharedPointer>
+
+#include "entitymanager.h"
+//#include "src/model/persons/group.h"
+//#include "src/controller/appcontroller.h"
+
+//class StandardLesson;
+//class TimeEntity;
+//class CalendarEvent;
+//class Room;
+//class AppController;
+//class AppSeatingData;
+//class AppMediaData;
+
+using namespace CuteEntityManager;
+
+class DataCreation
+{
+public:
+    DataCreation();
+    static QList<QSharedPointer<Entity>> createRatingEntities();
+
+};
+
+#endif // DATACREATION_H
diff --git a/samples/simple/enums.h b/samples/simple/enums.h
new file mode 100644
index 0000000..f36c2ec
--- /dev/null
+++ b/samples/simple/enums.h
@@ -0,0 +1,394 @@
+#ifndef ENUMS_H
+#define ENUMS_H
+
+#include <QObject>
+#include <QDate>
+#include <QMetaEnum>
+#include <QDebug>
+#include <QMetaObject>
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * Do NOT change any number assignments, as that might/will
+ * invalidate existing dataBases!
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * When creating new types, check for enum doublettes as
+ * we do not have strong types in qml - Enums is the
+ * common space and the last Enum's number is taken.
+ * Better keep numbers synchronized (see
+ * DataFieldPosition vs IconPosition)
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * Always do:
+ * Q_ENUM beneath class
+ * Q_DECLARE_METATYPE (see below) for QML<->C++ (slots/invokables)
+ * qRegisterMetaType (main.cpp) for QML<->C++ (slots/invokables)
+ * (Registration for use in QML is already done by qmlRegisterType<Enums>)
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+class Enums: public QObject
+{
+    Q_OBJECT
+
+public:
+    static constexpr qreal EPSILON_CALCULATION = 0.001;
+    static constexpr qreal EPSILON_SCREEN = 0.001;
+
+    enum class Gender {
+        MALE = 0,
+        FEMALE = 1,
+        UNKNOWNGENDER = -1
+    };
+    Q_ENUM(Gender)
+
+    enum class IncidentRetrievalPolicy {
+        NEW_PER_LESSON = 1,         // if recent: return same Incident, else: create new (entirely)
+                                    //      (Example: "Attendance" App)
+        CHANGE_PER_LESSON = 2,      // if recent: return same Incident, else: clone a new (based on last)
+                                    //      (Example: cycling "Status" App)
+        NEW = 3,                    // create a new (entirely), allows multiple entries per lesson
+                                    //      (Example: grading multiple contributions with "Grade" App)
+        CHANGE = 4                  // clone a new (based on last), allows logging of multiple changes per lesson
+                                    //      (Example: logging disturbances with a "count" App)
+                                    //      (unsuitable for cyclic status apps)
+///@todo        SINGLETON = 5               // only one Incident per pupil and group shall exist.
+    };
+    Q_ENUM(IncidentRetrievalPolicy)
+
+    enum class AttendanceState {
+        PRESENT=1,
+        MISSING=2,
+        LATE=3,
+        ATSCHOOL=4,
+        UNDEFINED=-1
+    };
+    Q_ENUM(AttendanceState)
+
+//    enum class CalendarEventType {
+//        STANDARDLESSON=0,
+//        LESSON=1,
+//        SCHOOLPERSONAL=2,
+//        SCHOOLGENERAL=3,
+//        PERSONAL=4
+//    };
+//    Q_ENUM(CalendarEventType)
+    enum class CalendarPlacementResult {
+        OFFBEFORE=-1,
+        OFFAFTER=-2,
+        FITSIN=0,
+        CUTATSTART=1,
+        CUTATEND=2,
+        CUTATBOTH=3
+    };
+    Q_ENUM(CalendarPlacementResult)
+
+    enum class DayOfWeek {
+        SUNDAY=0,
+        MONDAY=1,
+        TUESDAY=2,
+        WEDNESDAY=3,
+        THURSDAY=4,
+        FRIDAY=5,
+        SATURDAY=6,
+        UNDEFINED=-1
+    };
+    Q_ENUM(DayOfWeek)
+
+    enum class Orientation {
+        LANDSCAPE,
+        PORTRAIT,
+        LANDSCAPE_180,
+        PORTRAIT_180
+    };
+    Q_ENUM(Orientation)
+
+    enum class NameOrder {
+        FIRST_FAMILY=0,
+        FAMILY_FIRST=1
+    };
+    Q_ENUM(NameOrder)
+
+    enum class AppMode {
+        SEATINGPLAN=1,
+        TABLE=2,
+        CALENDAR=3,
+        SPECIAL=0,
+        UNDEFINED=-1
+    }; //APPBUTTONS,GROUPBUTTONS,ROOMEDIT,SEATEDIT, SCHEDULE
+    Q_ENUM(AppMode)
+
+    enum class AppType {
+        NOAPP=-1,
+        ATTENDANCE=1,
+        HOMEWORK=2,
+        RATING=3,
+        STATUS=4,
+        CHECKLIST=5,
+        GROUPS=6,
+        APPS=7,
+        ROOMS=8,
+        SEATS=9,
+        COUNT=10,
+        BASEDATA=11,
+        SCHEDULE=12,
+        GRADES=13,
+        MEDIA=14
+
+    };
+    Q_ENUM(AppType)
+
+    enum class ToolType {
+        UNDEFINED=-1,
+        RANDOM_PUPIL=0,
+        ADD_MEDIA=1,
+        TOGGLE_RASTER=2,
+    };
+    Q_ENUM(ToolType)
+
+    enum class DataFieldPosition {
+        // always keep numbers synchronized with IconPosition,
+        // as in qml mix-up confusion is possible (not strongly typed there)
+
+        // ordinality is important. These fields are being iterated!
+        TOP_LEFT=0,
+        TOP=1,
+        TOP_RIGHT=2,
+        UPPER_LEFT=3,
+        UPPER=4,
+        UPPER_RIGHT=5,
+        LOWER_LEFT=6,
+        LOWER=7,
+        LOWER_RIGHT=8,
+        BOTTOM_LEFT=9,
+        BOTTOM=10,
+        BOTTOM_RIGHT=11,
+        CENTER=12
+    };
+    Q_ENUM(Enums::DataFieldPosition)
+
+    enum class IconPosition {
+        // always keep numbers synchronized with DataFieldPosition,
+        // as in qml mix-up confusion is possible (not strongly typed there)
+        TOP_LEFT=0,
+//        TOP=1,
+        TOP_RIGHT=2,
+//        UPPER_LEFT=3,
+//        UPPER=4,
+//        UPPER_RIGHT=5,
+//        LOWER_LEFT=6,
+//        LOWER=7,
+//        LOWER_RIGHT=8,
+        BOTTOM_LEFT=9,
+//        BOTTOM=10,
+        BOTTOM_RIGHT=11,
+//        CENTER=12
+
+
+    };
+    Q_ENUM(IconPosition)
+
+    enum class RecurrencePatternType {
+        DAILY=0,
+        WEEKLY=1,
+        ABSOLUTEMONTHLY=2,
+        RELATIVEMONTHLY=3,
+        ABSOLUTEYEARLY=4,
+        RELATIVEYEARLY=5
+    };
+    Q_ENUM(RecurrencePatternType)
+
+    enum class RecurrenceRangeType {
+        ENDDATE=0,
+        NOEND=1,
+        NUMBERED=2
+    };
+    Q_ENUM(RecurrenceRangeType)
+
+    enum class ShadowPosition {
+        TOP_LEFT_SHADOW=0,
+        TOP_RIGHT_SHADOW=1,
+        BOTTOM_LEFT_SHADOW=2,
+        BOTTOM_RIGHT_SHADOW=3,
+        INVALID_SHADOW=-1
+    };
+    Q_ENUM(ShadowPosition)
+
+    enum class WeekIndex {
+        FIRST=0,
+        SECOND=1,
+        THIRD=2,
+        FOURTH=3,
+        LAST=4
+    };
+    Q_ENUM(WeekIndex)
+
+    enum class RoundingOption {
+        ROUND = 0,
+        CEILING = 1,
+        FLOOR = 2
+    };
+    Q_ENUM(RoundingOption)
+
+
+    enum class RandomPersonMode {
+        UNDEFINED = -1,
+        FREE_RANDOM = 0,
+        ONLY_ONCE = 1,
+        ONLY_ONCE_BEFORE_SECOND = 2,
+        WEIGHED_RANDOM = 3
+    };
+    Q_ENUM(RandomPersonMode)
+
+//    enum class RatingMarkIntendedEntry {
+//        VALUE=0,
+//        SYMBOL=1,
+//        PERCENT=2,
+//        UNRATEABLE=3,
+//        UNDEFINED=-1
+//    };
+//    Q_ENUM(RatingMarkIntendedEntry)
+
+    static DayOfWeek dayOfWeek(QDate date) {
+        Q_ASSERT(date.isValid());
+        if (!date.isValid()) {
+             return DayOfWeek::UNDEFINED;
+        }
+        switch (date.dayOfWeek()) {
+            case 1: return DayOfWeek::MONDAY;
+        case 2: return DayOfWeek::TUESDAY;
+        case 3: return DayOfWeek::WEDNESDAY;
+        case 4: return DayOfWeek::THURSDAY;
+        case 5: return DayOfWeek::FRIDAY;
+        case 6: return DayOfWeek::SATURDAY;
+        case 7: return DayOfWeek::SUNDAY;
+        default: return DayOfWeek::UNDEFINED;
+        }
+
+    }
+
+    static QMap<int, QString> toGenericStringMap(QString enumClassName) {
+        QMap<int, QString> resultMap;
+        const QMetaObject &mo = Enums::staticMetaObject;
+        int index = mo.indexOfEnumerator(enumClassName.toLocal8Bit());
+        QMetaEnum metaEnum = mo.enumerator(index);
+        //Enums::AttendanceState test = Enums::AttendanceState::UNDEFINED;
+        //QString enumString = metaEnum.valueToKey(static_cast<int>(test));
+        for (int i=0; i<metaEnum.keyCount();i++) {
+            resultMap.insert(metaEnum.value(i),metaEnum.key(i));
+        }
+        return resultMap;
+    }
+
+    template<class T>
+    static QMap<int, QString> toStringMap(QString enumClassName, bool omitValuesUnderZero = false) {
+        QMap<int, QString> resultMap;
+        const QMetaObject &mo = Enums::staticMetaObject;
+        int index = mo.indexOfEnumerator(enumClassName.toLocal8Bit());
+        QMetaEnum metaEnum = mo.enumerator(index);
+        try {
+            for (int i=0; i<metaEnum.keyCount();i++) {
+                if (metaEnum.value(i) >= 0 || !omitValuesUnderZero) {
+                    T instance = static_cast<T>(metaEnum.value(i));
+                    resultMap.insert(metaEnum.value(i),toString(instance));
+                }
+            }
+        } catch (...) {
+            resultMap.clear();
+        }
+        Q_ASSERT (!resultMap.isEmpty());
+        return resultMap;
+    }
+};
+Q_DECLARE_METATYPE(Enums::AttendanceState)
+Q_DECLARE_METATYPE(Enums::Orientation)
+Q_DECLARE_METATYPE(Enums::AppMode)
+Q_DECLARE_METATYPE(Enums::AppType)
+Q_DECLARE_METATYPE(Enums::DataFieldPosition)
+Q_DECLARE_METATYPE(Enums::IconPosition)
+Q_DECLARE_METATYPE(Enums::ShadowPosition)
+Q_DECLARE_METATYPE(Enums::Gender)
+Q_DECLARE_METATYPE(Enums::ToolType)
+Q_DECLARE_METATYPE(Enums::RandomPersonMode)
+
+inline Enums::DayOfWeek &operator++( Enums::DayOfWeek &d, int ) {
+    if (d == Enums::DayOfWeek::UNDEFINED) {
+        return d;
+    }
+    int nr = static_cast<int>(d) + 1;
+    if (nr > 6) {
+        nr = 0;
+    }
+    d = static_cast<Enums::DayOfWeek>(nr);
+  return d;
+}
+
+inline QString toString(Enums::DayOfWeek day, int limitLength=0) {
+    if (limitLength == 0) {
+        limitLength=100;
+    }
+    switch (day) {
+        case Enums::DayOfWeek::MONDAY: return(QString("Montag").left(limitLength));
+        case Enums::DayOfWeek::TUESDAY: return(QString("Dienstag").left(limitLength));
+        case Enums::DayOfWeek::WEDNESDAY: return(QString("Mittwoch").left(limitLength));
+        case Enums::DayOfWeek::THURSDAY: return(QString("Donnerstag").left(limitLength));
+        case Enums::DayOfWeek::FRIDAY: return(QString("Freitag").left(limitLength));
+        case Enums::DayOfWeek::SATURDAY: return(QString("Samstag").left(limitLength));
+        case Enums::DayOfWeek::SUNDAY: return(QString("Sonntag").left(limitLength));
+    default:
+        return QString();
+    }
+}
+inline QString toString(Enums::AppType appType, int limitLength=0) {
+    if (limitLength == 0) {
+        limitLength=100;
+    }
+    switch (appType) {
+        case Enums::AppType::NOAPP: return(QString("Keine App").left(limitLength));
+        case Enums::AppType::ATTENDANCE: return(QString("Anwesenheit").left(limitLength));
+        case Enums::AppType::HOMEWORK: return(QString("Hausaufgaben").left(limitLength));
+        case Enums::AppType::RATING: return(QString("Bewertung").left(limitLength));
+        case Enums::AppType::STATUS: return(QString("Status").left(limitLength));
+        case Enums::AppType::CHECKLIST: return(QString("Checkliste").left(limitLength));
+        case Enums::AppType::GROUPS: return(QString("Gruppen").left(limitLength));
+        case Enums::AppType::APPS: return(QString("Apps").left(limitLength));
+        case Enums::AppType::ROOMS: return(QString("Raumbau").left(limitLength));
+        case Enums::AppType::SEATS: return(QString("Sitzplan").left(limitLength));
+        case Enums::AppType::COUNT: return(QString("Zählen").left(limitLength));
+        case Enums::AppType::BASEDATA: return(QString("Basisdaten").left(limitLength));
+        case Enums::AppType::SCHEDULE: return(QString("Termine").left(limitLength));
+        case Enums::AppType::GRADES: return(QString("Zensuren").left(limitLength));
+        case Enums::AppType::MEDIA: return(QString("Medien").left(limitLength));
+    default:
+        return QString();
+    }
+}
+
+inline QString toString(Enums::AttendanceState state) {
+    switch (state) {
+    case Enums::AttendanceState::ATSCHOOL: return(QString("Schulisch abwesend"));
+    case Enums::AttendanceState::LATE: return(QString("Verspätet"));
+    case Enums::AttendanceState::MISSING: return(QString("Fehlstunde(n)"));
+    case Enums::AttendanceState::PRESENT: return(QString("Anwesend"));
+    case Enums::AttendanceState::UNDEFINED: return(QString("Nicht definiert"));
+    default:
+        return QString();
+    }
+}
+
+template <class T> inline T fromString(QString stateString, QString className) {
+    const QMetaObject &mo = Enums::staticMetaObject;
+    int index = mo.indexOfEnumerator(className.toLocal8Bit()); // watch out during refactorings
+    QMetaEnum metaEnum = mo.enumerator(index);
+    for (int i = 0; i < metaEnum.keyCount(); i++) {
+        int val = metaEnum.value(i);
+        T enumVal = static_cast<T>(val);
+        if (toString(enumVal) == stateString) {
+            return enumVal;
+        }
+    }
+    return static_cast<T>(-1);;
+}
+
+#endif // ENUMS_H
diff --git a/samples/simple/group.cpp b/samples/simple/group.cpp
new file mode 100644
index 0000000..120fa7d
--- /dev/null
+++ b/samples/simple/group.cpp
@@ -0,0 +1,64 @@
+#include "group.h"
+#include "../samples/example/models/pupil.h"
+#include <QDebug>
+
+Group::Group() : Entity() {
+
+}
+
+const QHash<QString, CuteEntityManager::Relation> Group::getRelations() const {
+    auto hash = QHash<QString, CuteEntityManager::Relation>();
+    hash.insert("persons", CuteEntityManager::Relation("persons",
+                RelationType::MANY_TO_MANY));
+    hash.insert("pupils", CuteEntityManager::Relation("pupils",
+                RelationType::MANY_TO_MANY, QString("groups")));
+    hash.insert("mainTeacher", CuteEntityManager::Relation("mainTeacher",
+                RelationType::MANY_TO_ONE));
+    return hash;
+}
+
+QString Group::getName() const {
+    return name;
+}
+
+void Group::setName(const QString &value) {
+    name = value;
+}
+QList<QSharedPointer<Pupil> > Group::getPupils() const {
+    return pupils;
+}
+
+void Group::setPupils(const QList<QSharedPointer<Pupil> > &value) {
+    pupils = value;
+}
+
+void Group::addPupil(Pupil *pupil) {
+    this->pupils.append(QSharedPointer<Pupil>(pupil));
+}
+
+QSharedPointer<Pupil> Group::pupilAt(int i) {
+    return this->pupils.at(i);
+}
+
+QSharedPointer<Person> Group::getMainTeacher() const {
+    return mainTeacher;
+}
+
+void Group::setMainTeacher(const QSharedPointer<Person> &value) {
+    mainTeacher = value;
+}
+QList<QSharedPointer<Person> > Group::getPersons() const {
+    return persons;
+}
+
+void Group::addPerson(Person *person) {
+    this->persons.append(QSharedPointer<Person>(person));
+}
+
+void Group::setPersons(const QList<QSharedPointer<Person> > &value) {
+    persons = value;
+}
+
+
+
+
diff --git a/samples/simple/group.h b/samples/simple/group.h
new file mode 100644
index 0000000..2222109
--- /dev/null
+++ b/samples/simple/group.h
@@ -0,0 +1,48 @@
+#ifndef GROUP_H
+#define GROUP_H
+#include "entity.h"
+#include <QDebug>
+
+class Teacher;
+class Person;
+class Pupil;
+//class Relation;
+using namespace CuteEntityManager;
+
+class Group: public CuteEntityManager::Entity {
+    Q_OBJECT
+    EM_MACRO(Group)
+    Q_PROPERTY(QList<QSharedPointer<Pupil>> pupils READ getPupils WRITE setPupils)
+    Q_PROPERTY(QList<QSharedPointer<Person>> persons READ getPersons WRITE
+               setPersons)
+    Q_PROPERTY(QString name READ getName WRITE setName)
+    Q_PROPERTY(QSharedPointer<Person> mainTeacher READ getMainTeacher WRITE
+               setMainTeacher)
+
+  public:
+    Q_INVOKABLE Group();
+    const QHash<QString, CuteEntityManager::Relation> getRelations() const override;
+
+    QString getName() const;
+    void setName(const QString &value);
+
+    QList<QSharedPointer<Pupil> > getPupils() const;
+    void setPupils(const QList<QSharedPointer<Pupil> > &value);
+    void addPupil(Pupil *pupil);
+    QSharedPointer<Pupil> pupilAt(int i);
+
+    QSharedPointer<Person> getMainTeacher() const;
+    void setMainTeacher(const QSharedPointer<Person> &value);
+
+    QList<QSharedPointer<Person> > getPersons() const;
+    void addPerson(Person *person);
+    void setPersons(const QList<QSharedPointer<Person> > &value);
+
+  protected:
+    QList<QSharedPointer<Pupil>> pupils;
+    QList<QSharedPointer<Person>> persons;
+    QSharedPointer<Person> mainTeacher;
+    QString name;
+};
+
+#endif // GROUP_H
diff --git a/samples/simple/incident.cpp b/samples/simple/incident.cpp
new file mode 100644
index 0000000..ff68cb3
--- /dev/null
+++ b/samples/simple/incident.cpp
@@ -0,0 +1,198 @@
+#include "incident.h"
+//#include "src/model/appdata/appdata.h"
+//#include "src/trivia/errorhandling.h"
+
+Incident::Incident() :
+    Entity()
+{
+
+}
+
+void Incident::initIncident(const QSharedPointer<Pupil> pupil,
+        const QSharedPointer<Group> group,
+        const QDateTime dateTime)
+{
+    this->setPupil(pupil);
+    this->setGroup(group);
+//    this->setRoom(room);
+//    this->setAppData(appData);
+    this->setBookedFor(dateTime);
+    this->setBookedAt(dateTime);
+    this->setCancelledAt(QDateTime());
+    this->setLocked(false);
+    this->setPredecessor(QSharedPointer<Incident>());
+}
+
+QDateTime Incident::bookedFor() const
+{
+    return m_bookedFor;
+}
+
+void Incident::setBookedFor(const QDateTime &bookedFor)
+{
+    m_bookedFor = bookedFor;
+}
+
+QDateTime Incident::bookedAt() const
+{
+    return m_bookedAt;
+}
+
+void Incident::setBookedAt(const QDateTime &bookedAt)
+{
+    m_bookedAt = bookedAt;
+}
+
+QDateTime Incident::cancelledAt() const
+{
+    return m_cancelledAt;
+}
+
+void Incident::setCancelledAt(const QDateTime &cancelledAt, bool forceOverwrite)
+{
+    if (m_cancelledAt.isValid() && !forceOverwrite) {
+        // sometimes an EntityManager metacall reaches this, too. Immediately after setting it manually. (<= 1ms?)
+        // reproduce: change attendanceIncident, ok, change again
+        qint64 diff = qAbs(m_cancelledAt.secsTo(cancelledAt));
+        if (diff > 10) { // giving some delay headroom for a possible double call
+            Q_ASSERT(!m_cancelledAt.isValid());
+//            THROW_MODERATE_ERROR_CIT("Das Canceln eines Ereignisses ist fehlgeschlagen, das Ereignis war bereits vorher gecancelt!");
+        }
+    }
+    m_cancelledAt = cancelledAt;
+}
+
+QSharedPointer<Pupil> Incident::pupil() const
+{
+    return m_pupil;
+}
+
+void Incident::setPupil(const QSharedPointer<Pupil> &pupil)
+{
+    m_pupil = pupil;
+}
+
+//QSharedPointer<AppData> Incident::appData() const
+//{
+//    return m_appData;
+//}
+
+//void Incident::setAppData(const QSharedPointer<AppData> &appData)
+//{
+//    m_appData = appData;
+//}
+
+QSharedPointer<Group> Incident::group() const
+{
+    return m_group;
+}
+
+void Incident::setGroup(const QSharedPointer<Group> &group)
+{
+    m_group = group;
+}
+
+bool Incident::cancelled(QDateTime dateTime) const
+{
+    if (!m_cancelledAt.isValid()) {
+        return false;
+    }
+    return (dateTime>cancelledAt());
+}
+
+bool Incident::locked() const
+{
+    return m_locked;
+}
+
+void Incident::setLocked(bool locked)
+{
+    m_locked = locked;
+}
+
+//QSharedPointer<Room> Incident::room() const
+//{
+//    return m_room;
+//}
+
+//void Incident::setRoom(const QSharedPointer<Room> &room)
+//{
+//    m_room = room;
+//}
+
+QString Incident::additionalInfo() const
+{
+    return m_additionalInfo;
+}
+
+void Incident::setAdditionalInfo(const QString &additionalInfo)
+{
+    m_additionalInfo = additionalInfo;
+}
+
+const QHash<QString, Relation> Incident::getRelations() const
+{
+    auto hash = QHash<QString, CuteEntityManager::Relation>();
+
+    hash.insert("pupil",CuteEntityManager::Relation(
+                    "pupil",CuteEntityManager::RelationType::MANY_TO_ONE));
+//    hash.insert("appData",CuteEntityManager::Relation(
+//                    "appData",CuteEntityManager::RelationType::MANY_TO_ONE));
+    hash.insert("group",CuteEntityManager::Relation(
+                    "group",CuteEntityManager::RelationType::MANY_TO_ONE));
+//    hash.insert("room",CuteEntityManager::Relation(
+//                    "room",CuteEntityManager::RelationType::MANY_TO_ONE));
+//    hash.insert("seatingPlan", CuteEntityManager::Relation(
+//                    "seatingPlan",CuteEntityManager::RelationType::MANY_TO_ONE));
+    hash.insert("predecessor", CuteEntityManager::Relation("predecessor", true, CuteEntityManager::RelationType::ONE_TO_ONE));
+    return hash;
+}
+
+//QSharedPointer<SeatingPlan> Incident::seatingPlan() const
+//{
+//    return m_seatingPlan;
+//}
+
+//void Incident::setSeatingPlan(const QSharedPointer<SeatingPlan> &seatingPlan)
+//{
+//    m_seatingPlan = seatingPlan;
+//}
+
+QSharedPointer<Incident> Incident::predecessor() const
+{
+    return m_predecessor;
+}
+
+void Incident::setPredecessor(const QSharedPointer<Incident> &predecessor)
+{
+    m_predecessor = predecessor;
+}
+
+bool  Incident::lessThanBookedFor(const QSharedPointer<Incident> &a, const QSharedPointer<Incident> &b) {
+        return a->bookedFor() < b->bookedFor();
+}
+
+bool  Incident::moreThanBookedFor(const QSharedPointer<Incident> &a, const QSharedPointer<Incident> &b) {
+        return a->bookedFor() > b->bookedFor();
+}
+
+bool Incident::lessThanBookedAt(const QSharedPointer<Incident> &a, const QSharedPointer<Incident> &b) {
+        return a->bookedAt() < b->bookedAt();
+}
+
+bool Incident::moreThanBookedAt(const QSharedPointer<Incident> &a, const QSharedPointer<Incident> &b) {
+        return a->bookedAt() > b->bookedAt();
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/simple/incident.h b/samples/simple/incident.h
new file mode 100644
index 0000000..456887a
--- /dev/null
+++ b/samples/simple/incident.h
@@ -0,0 +1,108 @@
+#ifndef INCIDENT_H
+#define INCIDENT_H
+#include <QDateTime>
+#include <QObject>
+
+#include "entity.h"
+
+//#include "src/enums.h"
+
+using namespace CuteEntityManager;
+
+//class AppData;
+class Pupil;
+class Group;
+//class Room;
+//class SeatingPlan;
+
+class Incident : public Entity
+{
+    Q_OBJECT
+    EM_MACRO(Incident)
+    Q_PROPERTY(bool locked READ locked WRITE setLocked) // i.e.: has had impacts on not undoable events
+
+    Q_PROPERTY(QDateTime bookedFor READ bookedFor WRITE setBookedFor)
+    Q_PROPERTY(QDateTime bookedAt READ bookedAt WRITE setBookedAt)
+    Q_PROPERTY(QDateTime cancelledAt READ cancelledAt WRITE setCancelledAt)
+
+    Q_PROPERTY(QSharedPointer<Pupil> pupil READ pupil WRITE setPupil)
+//    Q_PROPERTY(QSharedPointer<AppData> appData READ appData WRITE setAppData)
+    Q_PROPERTY(QSharedPointer<Group> group READ group WRITE setGroup)
+//    Q_PROPERTY(QSharedPointer<Room> room READ room WRITE setRoom)
+//    Q_PROPERTY(QSharedPointer<SeatingPlan> seatingPlan READ seatingPlan WRITE setSeatingPlan)
+
+    Q_PROPERTY(QString additionalInfo READ additionalInfo WRITE setAdditionalInfo)
+    Q_PROPERTY(QSharedPointer<Incident> predecessor READ predecessor WRITE setPredecessor)
+
+public:
+    Q_INVOKABLE Incident();
+
+    void initIncident(
+            const QSharedPointer<Pupil> pupil,
+            const QSharedPointer<Group> group,
+//            const QSharedPointer<Room> room,
+//            const QSharedPointer<AppData> appData,
+            const QDateTime dateTime);
+
+//    virtual Enums::AppType appType() {return Enums::AppType::NOAPP; }
+
+    QDateTime bookedFor() const;
+    void setBookedFor(const QDateTime &bookedFor);
+
+    QDateTime bookedAt() const;
+    void setBookedAt(const QDateTime &bookedAt);
+
+    QDateTime cancelledAt() const;
+    void setCancelledAt(const QDateTime &cancelledAt, bool forceOverwrite = false);
+
+    QSharedPointer<Pupil> pupil() const;
+    void setPupil(const QSharedPointer<Pupil> &pupil);
+
+//    QSharedPointer<AppData> appData() const;
+//    void setAppData(const QSharedPointer<AppData> &appData);
+
+    QSharedPointer<Group> group() const;
+    void setGroup(const QSharedPointer<Group> &group);
+
+    bool cancelled(QDateTime dateTime) const;
+
+    bool locked() const;
+    void setLocked(bool locked);
+
+//    QSharedPointer<Room> room() const;
+//    void setRoom(const QSharedPointer<Room> &room);
+
+    QString additionalInfo() const;
+    void setAdditionalInfo(const QString &additionalInfo);
+
+    virtual const QHash<QString, CuteEntityManager::Relation> getRelations() const override;
+
+//    QSharedPointer<SeatingPlan> seatingPlan() const;
+//    void setSeatingPlan(const QSharedPointer<SeatingPlan> &seatingPlan);
+
+    QSharedPointer<Incident> predecessor() const;
+    void setPredecessor(const QSharedPointer<Incident> &predecessor);
+
+    static bool lessThanBookedFor(const QSharedPointer<Incident> &a, const QSharedPointer<Incident> &b);
+    static bool moreThanBookedFor(const QSharedPointer<Incident> &a, const QSharedPointer<Incident> &b);
+    static bool lessThanBookedAt(const QSharedPointer<Incident> &a, const QSharedPointer<Incident> &b);
+    static bool moreThanBookedAt(const QSharedPointer<Incident> &a, const QSharedPointer<Incident> &b);
+protected:
+    QDateTime m_bookedFor;
+    QDateTime m_bookedAt;
+    QDateTime m_cancelledAt;
+    QSharedPointer<Pupil> m_pupil;
+//    QSharedPointer<AppData> m_appData;
+    QSharedPointer<Group> m_group;
+//    QSharedPointer<Room> m_room;
+//    QSharedPointer<SeatingPlan> m_seatingPlan;
+    bool m_cancelled = false;
+    bool m_locked = false;
+    QString m_additionalInfo;
+    QSharedPointer<Incident> m_predecessor;
+
+
+
+};
+
+#endif // INCIDENT_H
diff --git a/samples/simple/main.cpp b/samples/simple/main.cpp
index 8793e19..41bcfc6 100644
--- a/samples/simple/main.cpp
+++ b/samples/simple/main.cpp
@@ -1,28 +1,77 @@
 #include <QCoreApplication>
 #include <QDir>
 #include <QDebug>
-#include "article.h"
 #include "entitymanager.h"
-#include "entityinstancefactory.h"
+
+#include "person.h"
+#include "pupil.h"
+#include "group.h"
+#include "address.h"
+#include "contact.h"
+
+#include "occasion.h"
+#include "ratingmarkdefinition.h"
+#include "ratingmarksystem.h"
+#include "ratingmarkincident.h"
+#include "datacreation.h"
+#include "incident.h"
 
 
 using namespace CuteEntityManager;
 int main(int argc, char *argv[]) {
-    Q_UNUSED(argc) Q_UNUSED(argv)
-    EntityInstanceFactory::registerClass<Article>();
+    Q_UNUSED(argc) Q_UNUSED(argv);
+    EntityInstanceFactory::registerClass<Address>();
+    EntityInstanceFactory::registerClass<Contact>();
+    EntityInstanceFactory::registerClass<Person>();
+    EntityInstanceFactory::registerClass<Pupil>();
+    EntityInstanceFactory::registerClass<Group>();
+    EntityInstanceFactory::registerClass<Occasion>();
+    EntityInstanceFactory::registerClass<Incident>();
+    EntityInstanceFactory::registerClass<RatingMarkDefinition>();
+    EntityInstanceFactory::registerClass<RatingMarkIncident>();
+    EntityInstanceFactory::registerClass<RatingMarkSystem>();
+
+
+
     QSharedPointer<CuteEntityManager::EntityManager> e =
         QSharedPointer<CuteEntityManager::EntityManager>(new
                 CuteEntityManager::EntityManager("QSQLITE",
                         QDir::currentPath() + "/db.sqlite"));
-    QStringList inits = QStringList() << "Article";
+    qDebug()<<QDir::currentPath();
+    QStringList inits = QStringList() << "Address" << "Contact" << "Person" << "Pupil" << "Group" << "Incident" << "Occasion" << "RatingMarkDefinition" << "RatingMarkIncident" << "RatingMarkSystem";
     e->startup("0.1", inits);
-    QSharedPointer<Article> a = QSharedPointer<Article>(new Article(5.0,
-                                "muesli"));
-    auto ep = a.objectCast<CuteEntityManager::Entity>();
-    qDebug() << e->create(ep, true, true); //INSERT on database
-    a->setPrice(6.0); //inflation
-    a->setName("muesli improved"); //1337 muesli upgrade
-    qDebug() << e->save(ep); //UPDATE on database
-    qDebug() << e->remove(ep); //REMOVE on database
+
+
+    auto entities = DataCreation::createRatingEntities();
+    e->save(entities);
+
+//    QSharedPointer<Pupil> pupil = QSharedPointer<Pupil>(new Pupil("Vorname","Nachname","","","Keks"));
+//    e->save(pupil);
+
+    QSharedPointer<Pupil> pupil = QSharedPointer<Pupil>(new Pupil());
+    pupil->setLegalGuardianNote("note");
+    e->save(pupil);
+
+//    QSharedPointer<Person> person = QSharedPointer<Person>(new Person("Vorname","Nachname","","","Keks"));
+//    e->save(person);
+
+
+
+    QSharedPointer<Occasion> occasion = QSharedPointer<Occasion>(new Occasion("IrgendeinAnlass"));
+    QSharedPointer<RatingMarkIncident> inc = QSharedPointer<RatingMarkIncident>(new RatingMarkIncident());
+    inc->setAdditionalInfo("addInf");
+    inc->setBookedAt(QDateTime::currentDateTime());
+    inc->setBookedFor(QDateTime::currentDateTime());
+    inc->setOccasion(occasion);
+//    inc->setPupil(pupil);
+    inc->setRateable(true);
+//    inc->setRatingMarkSystem(system);
+    inc->setSymbol("z");
+    inc->setValue(23);
+
+    e->save(inc);
+
+
+
     return 0;
 }
diff --git a/samples/simple/occasion.cpp b/samples/simple/occasion.cpp
new file mode 100644
index 0000000..5b2583f
--- /dev/null
+++ b/samples/simple/occasion.cpp
@@ -0,0 +1,22 @@
+#include "occasion.h"
+
+Occasion::Occasion() : Entity()
+{
+    m_text.clear();
+}
+
+Occasion::Occasion(QString text)
+{
+    m_text=text;
+}
+QString Occasion::text()
+{
+    return m_text;
+}
+
+void Occasion::setText(QString &text)
+{
+    m_text = text;
+}
+
+
diff --git a/samples/simple/occasion.h b/samples/simple/occasion.h
new file mode 100644
index 0000000..ca3354d
--- /dev/null
+++ b/samples/simple/occasion.h
@@ -0,0 +1,25 @@
+#ifndef OCCASION_H
+#define OCCASION_H
+
+#include "entity.h"
+#include <QObject>
+
+using namespace CuteEntityManager;
+class Occasion : public Entity
+{
+    Q_OBJECT
+    EM_MACRO(Occasion)
+    Q_PROPERTY(QString text READ text WRITE setText)
+public:
+    Q_INVOKABLE explicit Occasion();
+    Occasion(QString text);
+    QString text();
+    void setText(QString &text);
+
+protected:
+    QString m_text;
+
+};
+
+#endif // OCCASION_H
+
diff --git a/samples/simple/person.cpp b/samples/simple/person.cpp
new file mode 100644
index 0000000..8f42a50
--- /dev/null
+++ b/samples/simple/person.cpp
@@ -0,0 +1,134 @@
+#include "person.h"
+#include "contact.h"
+#include "address.h"
+
+Person::Person(QObject *parent): Entity(parent) {
+}
+Person::Person(QString firstName, QString familyName,
+               QString customPictureFileName, QString namePrefix, QString nickName,
+               QDate birthday, QObject *parent): Entity(parent) {
+    setFirstName(firstName);
+    setFamilyName(familyName);
+    setNamePrefix(namePrefix);
+    setNickName(nickName);
+    setBirthday(birthday);
+    setCustomPictureFileName(customPictureFileName);
+}
+
+const QHash<QString, CuteEntityManager::Relation> Person::getRelations() const {
+    auto hash = QHash<QString, CuteEntityManager::Relation>();
+    hash.insert("groups", CuteEntityManager::Relation("groups",
+                RelationType::MANY_TO_MANY,
+                QString("persons")));
+    hash.insert("maintainedGroups", CuteEntityManager::Relation("maintainedGroups",
+                RelationType::ONE_TO_MANY,
+                QString("mainTeacher")));
+    hash.insert("contacts", CuteEntityManager::Relation("contacts",
+                RelationType::MANY_TO_MANY));
+    hash.insert("addresses", CuteEntityManager::Relation("addresses",
+                RelationType::MANY_TO_MANY));
+    return hash;
+}
+
+QString Person::fullName(NameOrder nameOrder) const {
+    QString name = QString();
+    if (nameOrder == NameOrder::FAMILY_FIRST_NAME_ORDER) {
+        name += this->getFamilyName();
+        name += ", ";
+        if (!this->getNamePrefix().isEmpty()) {
+            name += this->getNamePrefix();
+            name += " ";
+        }
+        name += this->getFirstName();
+    } else {
+        name += this->getFirstName();
+        name += " ";
+        name += this->getFamilyName();
+        if (!this->getNamePrefix().isEmpty()) {
+            name += ", ";
+            name += this->getNamePrefix();
+        }
+    }
+    return name;
+}
+QString Person::getFirstName() const {
+    return firstName;
+}
+
+void Person::setFirstName(const QString &value) {
+    firstName = value;
+}
+QString Person::getFamilyName() const {
+    return familyName;
+}
+
+void Person::setFamilyName(const QString &value) {
+    familyName = value;
+}
+QString Person::getNamePrefix() const {
+    return namePrefix;
+}
+
+void Person::setNamePrefix(const QString &value) {
+    namePrefix = value;
+}
+QString Person::getNickName() const {
+    return nickName;
+}
+
+void Person::setNickName(const QString &value) {
+    nickName = value;
+}
+QDate Person::getBirthday() const {
+    return birthday;
+}
+
+void Person::setBirthday(const QDate &value) {
+    birthday = value;
+}
+QString Person::getCustomPictureFileName() const {
+    return customPictureFileName;
+}
+
+void Person::setCustomPictureFileName(const QString &value) {
+    customPictureFileName = value;
+}
+QList<QSharedPointer<Contact> > Person::getContacts() const {
+    return contacts;
+}
+
+void Person::setContacts(const QList<QSharedPointer<Contact> > &value) {
+    contacts = value;
+}
+QList<QSharedPointer<Address> > Person::getAddresses() const {
+    return addresses;
+}
+
+void Person::setAddresses(const QList<QSharedPointer<Address> > &value) {
+    addresses = value;
+}
+QList<QSharedPointer<Group> > Person::getGroups() const {
+    return groups;
+}
+
+void Person::setGroups(const QList<QSharedPointer<Group> > &value) {
+    groups = value;
+}
+
+void Person::addContact(Contact *contact) {
+    this->contacts.append(QSharedPointer<Contact>(contact));
+}
+
+void Person::addAddress(Address *address) {
+    this->addresses.append(QSharedPointer<Address>(address));
+}
+
+QList<QSharedPointer<Group> > Person::getMaintainedGroups() const {
+    return maintainedGroups;
+}
+
+void Person::setMaintainedGroups(const QList<QSharedPointer<Group> > &value) {
+    maintainedGroups = value;
+
+}
+
diff --git a/samples/simple/person.h b/samples/simple/person.h
new file mode 100644
index 0000000..a5a7ac1
--- /dev/null
+++ b/samples/simple/person.h
@@ -0,0 +1,96 @@
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QDateTime>
+#include <QString>
+#include <QList>
+#include <QObject>
+#include <QAbstractListModel>
+#include <QDebug>
+#include "entity.h"
+
+using namespace CuteEntityManager;
+class Group;
+class Contact;
+class Address;
+
+class Person: public Entity {
+    Q_OBJECT
+    EM_MACRO(Person)
+    Q_PROPERTY(QString firstName READ getFirstName WRITE setFirstName)
+    Q_PROPERTY(QString familyName READ getFamilyName WRITE setFamilyName)
+    Q_PROPERTY(QString namePrefix READ getNamePrefix WRITE setNamePrefix)
+    Q_PROPERTY(QString nickName READ getNickName WRITE setNickName)
+    Q_PROPERTY(QString customPictureFileName READ getCustomPictureFileName WRITE
+               setCustomPictureFileName)
+    Q_PROPERTY(QDate birthday READ getBirthday WRITE setBirthday)
+    Q_PROPERTY(QList<QSharedPointer<Group>> groups READ getGroups WRITE setGroups)
+    Q_PROPERTY(QList<QSharedPointer<Group>> maintainedGroups READ
+               getMaintainedGroups WRITE setMaintainedGroups)
+    Q_PROPERTY(QList<QSharedPointer<Contact>> contacts READ getContacts WRITE
+               setContacts)
+    Q_PROPERTY(QList<QSharedPointer<Address>> addresses READ
+               getAddresses WRITE setAddresses)
+
+  public:
+    enum class NameOrder {FIRST_FAMILY_NAME_ORDER, FAMILY_FIRST_NAME_ORDER};
+    Q_INVOKABLE explicit Person(QObject *parent = 0);
+    Person(QString firstName, QString familyName,
+           QString customPictureFileName = QString(), QString namePrefix = QString(),
+           QString nickName = QString(), QDate birthday = QDate(), QObject *parent = 0);
+
+    virtual const QHash<QString, CuteEntityManager::Relation> getRelations() const override;
+
+    bool isPresent(QDateTime date = QDateTime::currentDateTime());
+    QString fullName(NameOrder nameOrder = NameOrder::FAMILY_FIRST_NAME_ORDER)
+    const;
+
+    QString getFirstName() const;
+    void setFirstName(const QString &value);
+
+    QString getFamilyName() const;
+    void setFamilyName(const QString &value);
+
+    QString getNamePrefix() const;
+    void setNamePrefix(const QString &value);
+
+    QString getNickName() const;
+    void setNickName(const QString &value);
+
+    QDate getBirthday() const;
+    void setBirthday(const QDate &value);
+
+    QString getCustomPictureFileName() const;
+    void setCustomPictureFileName(const QString &value);
+
+    QList<QSharedPointer<Contact> > getContacts() const;
+    void setContacts(const QList<QSharedPointer<Contact> > &value);
+
+    QList<QSharedPointer<Address> > getAddresses() const;
+    void setAddresses(const QList<QSharedPointer<Address> > &value);
+
+    QList<QSharedPointer<Group> > getGroups() const;
+    void setGroups(const QList<QSharedPointer<Group> > &value);
+
+    void addContact(Contact *contact);
+    void addAddress(Address *address);
+
+    QList<QSharedPointer<Group> > getMaintainedGroups() const;
+    void setMaintainedGroups(const QList<QSharedPointer<Group> > &value);
+
+  protected:
+    QString firstName;
+    QString familyName;
+    QString namePrefix;
+    QString nickName;
+    QDate birthday;
+    QString customPictureFileName;
+    QList <QSharedPointer<Contact>> contacts;
+    QList <QSharedPointer<Address>> addresses;
+    QList <QSharedPointer<Group>> groups;
+    QList <QSharedPointer<Group>> maintainedGroups;
+
+};
+
+
+#endif // PERSON_H
diff --git a/samples/simple/pupil.cpp b/samples/simple/pupil.cpp
new file mode 100644
index 0000000..2532914
--- /dev/null
+++ b/samples/simple/pupil.cpp
@@ -0,0 +1,34 @@
+#include "pupil.h"
+
+Pupil::Pupil() : Person() {
+
+}
+
+Pupil::Pupil(QString firstName, QString familyName,
+             QString customPictureFileName, QString namePrefix, QString nickName,
+             QDate birthday, QString legalGuardianNote, QObject *parent)
+    : Person(firstName, familyName, customPictureFileName, namePrefix,
+             nickName, birthday, parent) {
+    setFirstName(firstName);
+    setFamilyName(familyName);
+    setNamePrefix(namePrefix);
+    setNickName(nickName);
+    setBirthday(birthday);
+    setCustomPictureFileName(customPictureFileName);
+    this->setLegalGuardianNote(legalGuardianNote);
+}
+
+QString Pupil::getLegalGuardianNote() const {
+    return legalGuardianNote;
+}
+
+void Pupil::setLegalGuardianNote(const QString &value) {
+    legalGuardianNote = value;
+}
+
+const QHash<QString, Relation> Pupil::getRelations() const {
+    auto hash = Person::getRelations();
+    hash.insert("groups", CuteEntityManager::Relation("groups",
+                RelationType::MANY_TO_MANY));
+    return hash;
+}
diff --git a/samples/simple/pupil.h b/samples/simple/pupil.h
new file mode 100644
index 0000000..ecff139
--- /dev/null
+++ b/samples/simple/pupil.h
@@ -0,0 +1,28 @@
+#ifndef PUPIL_H
+#define PUPIL_H
+#include "person.h"
+
+class Pupil : public Person {
+    Q_OBJECT
+    EM_MACRO(Pupil)
+    Q_PROPERTY(QString legalGuardianNote READ getLegalGuardianNote WRITE
+               setLegalGuardianNote)
+  public:
+    Q_INVOKABLE Pupil();
+    Pupil(QString firstName, QString familyName,
+          QString customPictureFileName = QString(), QString namePrefix = QString(),
+          QString nickName = QString(), QDate birthday = QDate(), QString legalGuardianNote = "", QObject *parent = 0);
+
+    QString getLegalGuardianNote() const;
+    void setLegalGuardianNote(const QString &value);
+    virtual const QHash<QString, CuteEntityManager::Relation> getRelations() const override;
+
+    QString getForm() const;
+    void setForm(const QString &value);
+
+  protected:
+    QString legalGuardianNote;
+
+};
+
+#endif // PUPIL_H
diff --git a/samples/simple/ratingmarkdefinition.cpp b/samples/simple/ratingmarkdefinition.cpp
new file mode 100644
index 0000000..9e6611c
--- /dev/null
+++ b/samples/simple/ratingmarkdefinition.cpp
@@ -0,0 +1,118 @@
+#include "ratingmarkdefinition.h"
+
+RatingMarkDefinition::RatingMarkDefinition()
+    :Incident()
+{
+    m_ratingMarkSystem = QSharedPointer<RatingMarkSystem>();
+    m_symbol = QString();
+    m_valueEquivalent = -999;
+    m_minValue = -999;
+    m_percentEquivalent = -999;
+    m_minPercent = -999;
+    m_rateable = true;
+    m_panelColumn = -1;
+    m_panelRow = -1;
+}
+
+QSharedPointer<RatingMarkSystem> RatingMarkDefinition::ratingMarkSystem() const
+{
+    return m_ratingMarkSystem;
+}
+
+void RatingMarkDefinition::setRatingMarkSystem(const QSharedPointer<RatingMarkSystem> &ratingMarkSystem)
+{
+    m_ratingMarkSystem = ratingMarkSystem;
+}
+
+QString RatingMarkDefinition::symbol() const
+{
+    return m_symbol;
+}
+
+void RatingMarkDefinition::setSymbol(const QString &symbol)
+{
+    m_symbol = symbol;
+}
+
+qreal RatingMarkDefinition::valueEquivalent() const
+{
+    return m_valueEquivalent;
+}
+
+void RatingMarkDefinition::setValueEquivalent(const qreal &valueEquivalent)
+{
+    m_valueEquivalent = valueEquivalent;
+}
+
+qreal RatingMarkDefinition::minValue() const
+{
+    return m_minValue;
+}
+
+void RatingMarkDefinition::setMinValue(const qreal &minValue)
+{
+    m_minValue = minValue;
+}
+
+qreal RatingMarkDefinition::percentEquivalent() const
+{
+    return m_percentEquivalent;
+}
+
+void RatingMarkDefinition::setPercentEquivalent(const qreal &percentEquivalent)
+{
+    m_percentEquivalent = percentEquivalent;
+}
+
+qreal RatingMarkDefinition::minPercent() const
+{
+    return m_minPercent;
+}
+
+void RatingMarkDefinition::setMinPercent(const qreal &minimumPercent)
+{
+    m_minPercent = minimumPercent;
+}
+
+bool RatingMarkDefinition::rateable() const
+{
+    return m_rateable;
+}
+
+void RatingMarkDefinition::setRateable(bool rateable)
+{
+    m_rateable = rateable;
+}
+
+int RatingMarkDefinition::panelColumn() const
+{
+    return m_panelColumn;
+}
+
+void RatingMarkDefinition::setPanelColumn(int panelColumn)
+{
+    m_panelColumn = panelColumn;
+}
+
+int RatingMarkDefinition::panelRow() const
+{
+    return m_panelRow;
+}
+
+void RatingMarkDefinition::setPanelRow(int panelRow)
+{
+    m_panelRow = panelRow;
+}
+
+const QHash<QString, Relation> RatingMarkDefinition::getRelations() const
+{
+        auto hash = Incident::getRelations();
+        hash.insert("ratingMarkSystem",Relation("ratingMarkSystem",CuteEntityManager::RelationType::MANY_TO_ONE));
+
+        return hash;
+}
+
+bool RatingMarkDefinition::lessThanPercent(const QSharedPointer<RatingMarkDefinition> &a, const QSharedPointer<RatingMarkDefinition> &b)
+{
+    return a->percentEquivalent() < b->percentEquivalent();
+}
diff --git a/samples/simple/ratingmarkdefinition.h b/samples/simple/ratingmarkdefinition.h
new file mode 100644
index 0000000..c65eabb
--- /dev/null
+++ b/samples/simple/ratingmarkdefinition.h
@@ -0,0 +1,80 @@
+#ifndef RATINGMARKDEFINITION_H
+#define RATINGMARKDEFINITION_H
+
+#include <QObject>
+
+#include "entity.h"
+#include "incident.h"
+#include "enums.h"
+
+class RatingMarkSystem;
+
+using namespace CuteEntityManager;
+
+/**
+ * @brief The RatingMarkDefinition class
+ *
+ */
+class RatingMarkDefinition : public Incident
+{
+    Q_OBJECT
+    EM_MACRO(RatingMarkDefinition)
+    Q_PROPERTY(QSharedPointer<RatingMarkSystem> ratingMarkSystem READ ratingMarkSystem WRITE setRatingMarkSystem)
+    Q_PROPERTY(QString symbol READ symbol WRITE setSymbol)
+    Q_PROPERTY(qreal valueEquivalent READ valueEquivalent WRITE setValueEquivalent)
+    Q_PROPERTY(qreal minValue READ minValue WRITE setMinValue)
+    Q_PROPERTY(qreal percentEquivalent READ percentEquivalent WRITE setPercentEquivalent)
+    Q_PROPERTY(qreal minPercent READ minPercent WRITE setMinPercent)
+    Q_PROPERTY(bool rateable READ rateable WRITE setRateable)
+    Q_PROPERTY(int panelColumn READ panelColumn WRITE setPanelColumn)
+    Q_PROPERTY(int panelRow READ panelRow WRITE setPanelRow)
+
+public:
+    Q_INVOKABLE RatingMarkDefinition();
+
+    QSharedPointer<RatingMarkSystem> ratingMarkSystem() const;
+    void setRatingMarkSystem(const QSharedPointer<RatingMarkSystem> &ratingMarkSystem);
+
+    QString symbol() const;
+    void setSymbol(const QString &symbol);
+
+    qreal valueEquivalent() const;
+    void setValueEquivalent(const qreal &valueEquivalent);
+
+    qreal minValue() const;
+    void setMinValue(const qreal &minValue);
+
+    qreal percentEquivalent() const;
+    void setPercentEquivalent(const qreal &percentEquivalent);
+
+    qreal minPercent() const;
+    void setMinPercent(const qreal &minPercent);
+
+    bool rateable() const;
+    void setRateable(bool rateable);
+
+    int panelColumn() const;
+    void setPanelColumn(int panelColumn);
+
+    int panelRow() const;
+    void setPanelRow(int panelRow);
+
+    virtual const QHash<QString, CuteEntityManager::Relation> getRelations() const override;
+    virtual InheritanceStrategy getInheritanceStrategy() const override { return InheritanceStrategy::PER_CLASS_TABLE; }
+
+
+    static bool lessThanPercent(const QSharedPointer<RatingMarkDefinition> &a, const QSharedPointer<RatingMarkDefinition> &b);
+
+protected:
+    QSharedPointer<RatingMarkSystem> m_ratingMarkSystem;
+    QString m_symbol;
+    qreal m_valueEquivalent;
+    qreal m_minValue;
+    qreal m_percentEquivalent;
+    qreal m_minPercent;
+    bool m_rateable;
+    int m_panelColumn;
+    int m_panelRow;
+};
+
+#endif // RATINGMARKDEFINITION_H
diff --git a/samples/simple/ratingmarkincident.cpp b/samples/simple/ratingmarkincident.cpp
new file mode 100644
index 0000000..21b132c
--- /dev/null
+++ b/samples/simple/ratingmarkincident.cpp
@@ -0,0 +1,94 @@
+#include "ratingmarkincident.h"
+
+RatingMarkIncident::RatingMarkIncident()
+{
+
+}
+
+QString RatingMarkIncident::symbol() const
+{
+    return m_symbol;
+}
+
+void RatingMarkIncident::setSymbol(const QString &symbol)
+{
+    m_symbol = symbol;
+}
+
+qreal RatingMarkIncident::value() const
+{
+    return m_value;
+}
+
+void RatingMarkIncident::setValue(const qreal &value)
+{
+    m_value = value;
+}
+
+qreal RatingMarkIncident::percentValue() const
+{
+    return m_percentValue;
+}
+
+void RatingMarkIncident::setPercentValue(const qreal &percentValue)
+{
+    m_percentValue = percentValue;
+}
+
+qreal RatingMarkIncident::weight() const
+{
+    return m_weight;
+}
+
+void RatingMarkIncident::setWeight(const qreal &weight)
+{
+    m_weight = weight;
+}
+
+bool RatingMarkIncident::rateable() const
+{
+    return m_rateable;
+}
+
+void RatingMarkIncident::setRateable(bool rateable)
+{
+    m_rateable = rateable;
+}
+
+QSharedPointer<Occasion> RatingMarkIncident::occasion() const
+{
+    return m_occasion;
+}
+
+void RatingMarkIncident::setOccasion(const QSharedPointer<Occasion> &occasion)
+{
+    m_occasion = occasion;
+}
+
+const QHash<QString, Relation> RatingMarkIncident::getRelations() const
+{
+    auto hash = Incident::getRelations();
+    hash.insert("occasion",Relation("occasion",CuteEntityManager::RelationType::MANY_TO_ONE));
+    hash.insert("ratingMarkSystem", Relation("ratingMarkSystem",RelationType::MANY_TO_ONE));
+    return hash;
+}
+
+QSharedPointer<RatingMarkSystem> RatingMarkIncident::ratingMarkSystem() const
+{
+    return m_ratingMarkSystem;
+}
+
+void RatingMarkIncident::setRatingMarkSystem(const QSharedPointer<RatingMarkSystem> &ratingMarkSystem)
+{
+    m_ratingMarkSystem = ratingMarkSystem;
+}
+
+bool RatingMarkIncident::signatureNeeded() const
+{
+    return m_signatureNeeded;
+}
+
+void RatingMarkIncident::setSignatureNeeded(bool signatureNeeded)
+{
+    m_signatureNeeded = signatureNeeded;
+}
diff --git a/samples/simple/ratingmarkincident.h b/samples/simple/ratingmarkincident.h
new file mode 100644
index 0000000..b649a0f
--- /dev/null
+++ b/samples/simple/ratingmarkincident.h
@@ -0,0 +1,69 @@
+#ifndef RATINGMARKINCIDENT_H
+#define RATINGMARKINCIDENT_H
+
+#include <QObject>
+
+#include "incident.h"
+#include "occasion.h"
+#include "ratingmarksystem.h"
+
+class AppData;
+class RatingMarkIncident : public Incident
+{
+    Q_OBJECT
+    EM_MACRO(RatingMarkIncident)
+    Q_PROPERTY(QString symbol READ symbol WRITE setSymbol)
+    Q_PROPERTY(qreal value READ value WRITE setValue)
+    Q_PROPERTY(qreal percentValue READ percentValue WRITE setPercentValue)
+    Q_PROPERTY(qreal weight READ weight WRITE setWeight)
+    Q_PROPERTY(bool rateable READ rateable WRITE setRateable)
+    Q_PROPERTY(bool signatureNeeded READ signatureNeeded WRITE setSignatureNeeded)
+    Q_PROPERTY(QSharedPointer<Occasion> occasion READ occasion WRITE setOccasion)
+    // ratingMarkSystem scheint auf den ersten Blick ein Duplikat zu sein, da man es aus AppData
+    // (zu AppRatingData gecastet) ermitteln könnte. In der TimeMachine ist es jedoch wichtig, dass
+    // bei einem für die App geänderten RatingMarkSystem ein alter RatingMarkIncident noch sein
+    // ursprüngliches RatingMarkSystem kennt.
+    Q_PROPERTY(QSharedPointer<RatingMarkSystem> ratingMarkSystem READ ratingMarkSystem WRITE setRatingMarkSystem)
+public:
+    Q_INVOKABLE RatingMarkIncident();
+
+    QString symbol() const;
+    void setSymbol(const QString &symbol);
+
+    qreal value() const;
+    void setValue(const qreal &value);
+
+    qreal percentValue() const;
+    void setPercentValue(const qreal &percentValue);
+
+    qreal weight() const;
+    void setWeight(const qreal &weight);
+
+    bool rateable() const;
+    void setRateable(bool rateable);
+
+    QSharedPointer<Occasion> occasion() const;
+    void setOccasion(const QSharedPointer<Occasion> &occasion);
+
+    virtual const QHash<QString, CuteEntityManager::Relation> getRelations() const override;
+    virtual InheritanceStrategy getInheritanceStrategy() const override { return InheritanceStrategy::PER_CLASS_TABLE; }
+
+
+    QSharedPointer<RatingMarkSystem> ratingMarkSystem() const;
+    void setRatingMarkSystem(const QSharedPointer<RatingMarkSystem> &ratingMarkSystem);
+
+    bool signatureNeeded() const;
+    void setSignatureNeeded(bool signatureNeeded);
+
+protected:
+    QString m_symbol = QString();
+    qreal m_value = 0;
+    qreal m_percentValue = 0;
+    qreal m_weight = 1;
+    bool m_rateable = true;
+    bool m_signatureNeeded = false;
+    QSharedPointer<Occasion> m_occasion = QSharedPointer<Occasion>();
+    QSharedPointer<RatingMarkSystem> m_ratingMarkSystem = QSharedPointer<RatingMarkSystem>();
+};
+
+#endif // RATINGMARK_H
diff --git a/samples/simple/ratingmarksystem.cpp b/samples/simple/ratingmarksystem.cpp
new file mode 100644
index 0000000..6a82dc0
--- /dev/null
+++ b/samples/simple/ratingmarksystem.cpp
@@ -0,0 +1,273 @@
+#include "ratingmarksystem.h"
+#include "ratingmarkincident.h"
+#include "occasion.h"
+
+#include <QDebug>
+#include <QtMath>
+
+RatingMarkSystem::RatingMarkSystem()
+{
+
+}
+
+QString RatingMarkSystem::name() const
+{
+    return m_name;
+}
+
+void RatingMarkSystem::setName(const QString &name)
+{
+    m_name = name;
+}
+
+QList<QSharedPointer<RatingMarkDefinition> > RatingMarkSystem::ratingMarkDefinitions() const
+{
+    return m_ratingMarkDefinitions;
+}
+
+void RatingMarkSystem::setRatingMarkDefinitions(const QList<QSharedPointer<RatingMarkDefinition> > &ratingMarkDefinitions)
+{
+    m_ratingMarkDefinitions = ratingMarkDefinitions;
+}
+
+bool RatingMarkSystem::valuesComputable() const
+{
+    return m_valuesComputable;
+}
+
+void RatingMarkSystem::setValuesComputable(bool valuesComputable)
+{
+    m_valuesComputable = valuesComputable;
+}
+
+bool RatingMarkSystem::higherValueBetter() const
+{
+    return m_higherValueBetter;
+}
+
+void RatingMarkSystem::setHigherValueBetter(bool value)
+{
+    m_higherValueBetter = value;
+}
+
+int RatingMarkSystem::digits() const
+{
+    return m_digits;
+}
+
+void RatingMarkSystem::setDigits(int value)
+{
+    m_digits = value;
+}
+
+const QHash<QString, Relation> RatingMarkSystem::getRelations() const
+{
+        auto hash = Incident::getRelations();
+        hash.insert("ratingMarkDefinitions",Relation("ratingMarkDefinitions",CuteEntityManager::RelationType::ONE_TO_MANY,QString("ratingMarkSystem")));
+
+        return hash;
+}
+
+QSharedPointer<RatingMarkDefinition> RatingMarkSystem::ratingMarkDefinitionAtPanelPosition(int col, int row)
+{
+    for (int i = 0; i < this->ratingMarkDefinitions().count(); i++) {
+        QSharedPointer<RatingMarkDefinition> rmd = this->ratingMarkDefinitions().at(i);
+        if (rmd->panelColumn() == col) {
+            if (rmd->panelRow() == row) {
+                return rmd;
+            }
+        }
+    }
+    return QSharedPointer<RatingMarkDefinition>();
+}
+
+int RatingMarkSystem::panelColumns() const
+{
+    return m_panelColumns;
+}
+
+void RatingMarkSystem::setPanelColumns(int panelColumns)
+{
+    m_panelColumns = panelColumns;
+}
+
+int RatingMarkSystem::panelRows() const
+{
+    return m_panelRows;
+}
+
+void RatingMarkSystem::setPanelRows(int panelRows)
+{
+    m_panelRows = panelRows;
+}
+
+bool RatingMarkSystem::lessThanPercent(const QSharedPointer<RatingMarkIncident> &a, const QSharedPointer<RatingMarkIncident> &b)
+{
+    return a->percentValue() < b->percentValue();
+}
+bool RatingMarkSystem::moreThanPercent(const QSharedPointer<RatingMarkIncident> &a, const QSharedPointer<RatingMarkIncident> &b)
+{
+    return a->percentValue() > b->percentValue();
+}
+bool RatingMarkSystem::lessThanValue(const QSharedPointer<RatingMarkIncident> &a, const QSharedPointer<RatingMarkIncident> &b)
+{
+    return a->value() < b->value();
+}
+bool RatingMarkSystem::moreThanValue(const QSharedPointer<RatingMarkIncident> &a, const QSharedPointer<RatingMarkIncident> &b)
+{
+    return a->value() > b->value();
+}
+QList<QSharedPointer<RatingMarkIncident> > RatingMarkSystem::sortPercent(QList<QSharedPointer<RatingMarkIncident> > list, Qt::SortOrder sortOrder)
+{
+    if (sortOrder == Qt::AscendingOrder) {
+        std::sort(list.begin(),list.end(),RatingMarkSystem::lessThanPercent);
+    } else {
+        std::sort(list.begin(),list.end(),RatingMarkSystem::moreThanPercent);
+    }
+    return list;
+}
+
+QList<QSharedPointer<RatingMarkIncident> > RatingMarkSystem::sortValue(QList<QSharedPointer<RatingMarkIncident> > list, Qt::SortOrder sortOrder)
+{
+    if (sortOrder == Qt::AscendingOrder) {
+        std::sort(list.begin(),list.end(),RatingMarkSystem::lessThanValue);
+    } else {
+        std::sort(list.begin(),list.end(),RatingMarkSystem::moreThanValue);
+    }
+    return list;
+}
+
+bool RatingMarkSystem::shallBeCalculated(QSharedPointer<RatingMarkIncident> inc, QSharedPointer<Occasion> occasion, bool respectRateabilityProperty) {
+    if (!occasion.isNull() && (occasion != inc->occasion())) {
+        return false;
+    }
+    if (respectRateabilityProperty && !inc->rateable()) {
+        return false;
+    }
+    return true;
+
+}
+
+qreal RatingMarkSystem::averageSomeFloatProperty(QList<QSharedPointer<RatingMarkIncident> > list,
+                                                 QString propertyName,
+                                                 QSharedPointer<Occasion> occasion,
+                                                 int digits,
+                                                 Enums::RoundingOption rounding,
+                                                 bool respectWeight,
+                                                 bool respectRateabilityProperty)
+{
+    qreal sum = 0;
+    qreal weightSum = 0;
+    QListIterator<QSharedPointer<RatingMarkIncident> > iter(list);
+    bool ok = true;
+
+    while (ok && iter.hasNext()) {
+        QSharedPointer<RatingMarkIncident> inc = iter.next();
+        qreal addValue;
+        QVariant var = inc->getProperty(propertyName);
+        if (var.isValid() && !var.isNull()) {
+            addValue = var.toFloat(&ok);
+            if (!ok) {
+                qDebug()<<"RatingMarkSystem::averageSomeFloatProperty:  Float conversion of "<<propertyName<<" was not successful. ";
+            }
+        } else {
+            ok = false;
+            qDebug()<<"RatingMarkSystem::averageSomeFloatProperty:  "<<propertyName<<" was not found - typo?";
+        }
+        if (ok && this->shallBeCalculated(inc, occasion, respectRateabilityProperty)) {
+            qreal weight = respectWeight ? inc->weight() : 1;
+            if (weight < -Enums::EPSILON_CALCULATION) {
+                ok = true;
+            }
+            sum += weight * addValue;
+            weightSum += weight;
+        }
+    }
+    Q_ASSERT(ok);
+    return !ok? -1 : ((qAbs(weightSum) < Enums::EPSILON_CALCULATION)? -1 : this->shortenNumber(sum / weightSum, digits, rounding));
+}
+
+qreal RatingMarkSystem::averagePercent(const QList<QSharedPointer<RatingMarkIncident> > list,
+                                       QSharedPointer<Occasion> occasion,
+                                       int digits,
+                                       Enums::RoundingOption rounding,
+                                       bool respectWeight,
+                                       bool respectRateabilityProperty)
+{
+    return this->averageSomeFloatProperty(list,"percentValue", occasion, digits, rounding, respectWeight, respectRateabilityProperty);
+}
+
+qreal RatingMarkSystem::averageValueSimple(QList<QSharedPointer<RatingMarkIncident> > list,
+                                           QSharedPointer<Occasion> occasion,
+                                           int digits,
+                                           Enums::RoundingOption rounding,
+                                           bool respectWeight,
+                                           bool respectRateabilityProperty)
+{
+    return this->averageSomeFloatProperty(list,"value", occasion, digits, rounding, respectWeight, respectRateabilityProperty);
+}
+
+qreal RatingMarkSystem::symbolToPercent(QString symbol)
+{
+    QListIterator<QSharedPointer<RatingMarkDefinition>>iter (this->ratingMarkDefinitions());
+    bool found = false;
+    QSharedPointer<RatingMarkDefinition> def;
+    while (!found && iter.hasNext()) {
+        def = iter.next();
+        if (def->symbol() == symbol) {
+            found = true;
+        }
+    }
+    return found? def->percentEquivalent() : -1;
+}
+
+QString RatingMarkSystem::percentToSymbol(qreal percent)
+{
+    QListIterator<QSharedPointer<RatingMarkDefinition>>iter (this->ratingMarkDefinitions());
+    QSharedPointer<RatingMarkDefinition> candidate;
+    while (iter.hasNext()) {
+       QSharedPointer<RatingMarkDefinition> def;
+       def = iter.next();
+        if (def->minPercent() <= percent){
+            if (candidate.isNull()) {
+                candidate = def;
+            } else {
+                if (def->minPercent() > candidate->minPercent()) {
+                    candidate = def;
+                }
+            }
+        }
+
+    }
+    return candidate.isNull()? QString() : candidate->symbol();
+}
+
+qreal RatingMarkSystem::shortenNumber(qreal nr, int digits, Enums::RoundingOption rounding)
+{
+    if (digits >= 0) {
+        int factor = 1;
+        if (digits > 0) {
+            factor = qPow(10, digits);
+            nr *= factor;
+        }
+        qDebug()<<"Factor: "<<factor;
+        switch (rounding) {
+        case Enums::RoundingOption::ROUND:
+            nr = qRound(nr);
+            break;
+        case Enums::RoundingOption::CEILING:
+            nr = qCeil(nr);
+            break;
+        case Enums::RoundingOption::FLOOR:
+            nr = qFloor(nr);
+            break;
+        }
+        if (digits > 0) {
+            nr /= factor;
+        }
+    }
+    return nr;
+}
+
+
+
diff --git a/samples/simple/ratingmarksystem.h b/samples/simple/ratingmarksystem.h
new file mode 100644
index 0000000..e20b98e
--- /dev/null
+++ b/samples/simple/ratingmarksystem.h
@@ -0,0 +1,117 @@
+#ifndef RATINGMARKSYSTEM_H
+#define RATINGMARKSYSTEM_H
+
+#include "ratingmarkdefinition.h"
+
+class RatingMarkIncident;
+class Occasion;
+////////////////////////////////////////////////
+/// \brief The RatingMarkSystem class
+///
+/// A rating mark system defines a set of rating marks that are able
+/// to evaluate the achievement of pupils.
+/// Rating marks can base on numbers or plain symbols, they not have to
+/// be equidistant, not even ordinal.
+///
+/// "ratingMarkDefinitions" keeps the actual symbols, values and boundaries
+///
+/// "valuesComputable" means that intermediate values can be calculated,
+/// e.g. 1.3 and 1.0 could be averaged to a value of 1.15.
+///
+/// "digits" states, how many digits after the decimal point are to be
+/// kept and taken into calculation
+///
+/// "higherValueBetter" is true for a system, where a higher value means
+/// a better mark (greater achievement).
+///
+/// "panelColumns" and "panelRows" give QML information about the layout of the input panel for this system
+
+class RatingMarkSystem : public Incident
+{
+    Q_OBJECT
+    EM_MACRO(RatingMarkSystem)
+    Q_PROPERTY(QList<QSharedPointer<RatingMarkDefinition>> ratingMarkDefinitions READ ratingMarkDefinitions WRITE setRatingMarkDefinitions)
+    Q_PROPERTY(QString name READ name WRITE setName)
+    Q_PROPERTY(bool valuesComputable READ valuesComputable WRITE setValuesComputable)
+    Q_PROPERTY(int digits READ digits WRITE setDigits)
+    Q_PROPERTY(bool higherValueBetter READ higherValueBetter WRITE setHigherValueBetter)
+    Q_PROPERTY(int panelColumns READ panelColumns WRITE setPanelColumns)
+    Q_PROPERTY(int panelRows READ panelRows WRITE setPanelRows)
+public:
+    Q_INVOKABLE RatingMarkSystem();
+
+
+    QString name() const;
+    void setName(const QString &name);
+
+    QList<QSharedPointer<RatingMarkDefinition> > ratingMarkDefinitions() const;
+    void setRatingMarkDefinitions(const QList<QSharedPointer<RatingMarkDefinition> > &ratingMarkDefinitions);
+
+    bool valuesComputable() const;
+    void setValuesComputable(bool valuesComputable);
+
+    bool higherValueBetter() const;
+    void setHigherValueBetter(bool value);
+
+    int digits() const;
+    void setDigits(int value);
+
+    virtual const QHash<QString, CuteEntityManager::Relation> getRelations() const override;
+    virtual InheritanceStrategy getInheritanceStrategy() const override { return InheritanceStrategy::PER_CLASS_TABLE; }
+
+
+    QSharedPointer<RatingMarkDefinition>ratingMarkDefinitionAtPanelPosition(int col, int row);
+
+    int panelColumns() const;
+    void setPanelColumns(int panelColumns);
+
+    int panelRows() const;
+    void setPanelRows(int panelRows);
+
+    static bool lessThanPercent(const QSharedPointer<RatingMarkIncident> &a, const QSharedPointer<RatingMarkIncident> &b);
+    static bool moreThanPercent(const QSharedPointer<RatingMarkIncident> &a, const QSharedPointer<RatingMarkIncident> &b);
+    static bool lessThanValue(const QSharedPointer<RatingMarkIncident> &a, const QSharedPointer<RatingMarkIncident> &b);
+    static bool moreThanValue(const QSharedPointer<RatingMarkIncident> &a, const QSharedPointer<RatingMarkIncident> &b);
+    virtual QList<QSharedPointer<RatingMarkIncident>> sortPercent(QList<QSharedPointer<RatingMarkIncident>> list, Qt::SortOrder sortOrder);
+    virtual QList<QSharedPointer<RatingMarkIncident>> sortValue(QList<QSharedPointer<RatingMarkIncident>> list, Qt::SortOrder sortOrder);
+
+
+    virtual qreal averagePercent(QList<QSharedPointer<RatingMarkIncident>> list,
+                                 QSharedPointer<Occasion> occasion,
+                                 int digits = -1,
+                                 Enums::RoundingOption rounding = Enums::RoundingOption::ROUND,
+                                 bool respectWeight = true,
+                                 bool respectRateabilityProperty = true);
+    virtual qreal averageValueSimple(QList<QSharedPointer<RatingMarkIncident>> list,
+                                 QSharedPointer<Occasion> occasion,
+                                 int digits = -1,
+                                 Enums::RoundingOption rounding = Enums::RoundingOption::ROUND,
+                                 bool respectWeight = true,
+                                 bool respectRateabilityProperty = true);
+    virtual bool shallBeCalculated(QSharedPointer<RatingMarkIncident> inc,
+                           QSharedPointer<Occasion> occasion,
+                           bool respectRateabilityProperty = true);
+
+
+    qreal symbolToPercent(QString symbol);
+    QString percentToSymbol(qreal percent);
+    qreal shortenNumber(qreal nr, int digits, Enums::RoundingOption rounding);
+protected:
+    qreal averageSomeFloatProperty(QList<QSharedPointer<RatingMarkIncident>> list,
+                                       QString propertyName,
+                                       QSharedPointer<Occasion> occasion,
+                                       int digits = -1,
+                                       Enums::RoundingOption rounding = Enums::RoundingOption::ROUND,
+                                       bool respectWeight = true,
+                                       bool respectRateabilityProperty = true);
+
+    QString m_name;
+    QList<QSharedPointer<RatingMarkDefinition>> m_ratingMarkDefinitions;
+    bool m_valuesComputable = false;
+    bool m_higherValueBetter = true;
+    int m_digits = -1;
+    int m_panelColumns = -1;
+    int m_panelRows = -1;
+};
+
+#endif // RATINGMARKSYSTEM_H
diff --git a/samples/simple/simple.pro b/samples/simple/simple.pro
index 4ea8f88..4414fdc 100644
--- a/samples/simple/simple.pro
+++ b/samples/simple/simple.pro
@@ -15,8 +15,29 @@ CONFIG   -= app_bundle
 TEMPLATE = app
 
 HEADERS += \
-    article.h
+    ratingmarkincident.h \
+    incident.h \
+    ratingmarksystem.h \
+    ratingmarkdefinition.h \
+    enums.h \
+    occasion.h \
+    datacreation.h \
+    address.h \
+    contact.h \
+    group.h \
+    person.h \
+    pupil.h
 
 SOURCES += \
     main.cpp \
-    article.cpp
+    ratingmarkincident.cpp \
+    incident.cpp \
+    ratingmarksystem.cpp \
+    ratingmarkdefinition.cpp \
+    occasion.cpp \
+    datacreation.cpp \
+    address.cpp \
+    contact.cpp \
+    group.cpp \
+    person.cpp \
+    pupil.cpp
