enhancement
major
minor
major
minor
minor
#29959
Persönliche Einstellungen werden nicht gespeichert, wenn der Benutzer eine verletzte Modell-Bedingung hat (z. B. root ohne Kontaktdaten)
Problem
Persönliche Einstellungen (PersonalConfiguration.storePersonalConfiguration()) gehen verloren, wenn das Personen-Objekt des Benutzers eine Bedingung des Modells verletzt, die mit der Einstellung nichts zu tun hat. Der Commit schlägt fehl, und die Einstellung wird nicht gespeichert.
Beobachtet in tl-factory-app: Bei jeder gesendeten Chat-Nachricht protokolliert tl-chat
WARN ApprovalChoice - Approval choice could not be stored: Cannot store, constraints violated Invalid value in attribute "Contact data" of "root": The value must not be empty.
Der Benutzer root hat dort keine Kontaktdaten. Die Wahl der Freigabe-Art im Chat (ApprovalChoice.save) wird deshalb nie gespeichert. Dasselbe gilt für jede andere persönliche Einstellung dieses Benutzers und für jeden Benutzer mit einem unvollständigen Pflichtattribut.
Ursache
Commit-Prüfung: Die Modell-Prüfung beim Commit (ModelService.checkCommit) prüfte neben den angelegten und geänderten Objekten die Quelle jeder angelegten, geänderten oder gelöschten Assoziation – vollständig, mit allen Bedingungen ihres Typs. Das Speichern der persönlichen Einstellungen legt das Einstellungs-Objekt neu an und dazu eine Assoziation hasPersonalConfiguration, deren Quelle die Person ist. Damit wurde die gesamte Person geprüft, obwohl an ihr kein Modell-Attribut geändert wurde. Umgekehrt wurde bei einer Referenz, die in der Zeile des referenzierten Objekts gespeichert ist (inline-set-storage), der Besitzer der Referenz gar nicht geprüft.
Fehlende Kontaktdaten: Auf einer frischen Datenbank erhält jedes Konto (auch root) Kontaktdaten durch ContactPersonManager.initUser(). Kommt das Modul tl-contact aber zu einer bestehenden Datenbank hinzu (bei tl-factory-app mit #29953 über tl-ai-core), fügt das Modell-Upgrade die Pflicht-Referenz tl.accounts:Person#contact ohne Wert für alle bestehenden Konten hinzu. Diese Konten blieben ungültig, jede Bearbeitung des Kontos scheiterte.
Erwartet
Persönliche Einstellungen werden unabhängig vom übrigen Zustand der Person gespeichert. Konten ohne Kontaktdaten werden repariert.
Lösung
Commit-Prüfung: Beim Commit werden zusätzlich zu den angelegten und geänderten Objekten genau die Objekte geprüft, deren Modell-Attributwerte in einer anderen Tabellenzeile als ihrer eigenen geändert wurden. Ob eine Zeile einen Attributwert speichert und welchem Objekt er gehört, beschreibt das Modell bereits über die AssociationStorageDescriptor`s der Attribute (`ModelTables.getDescriptorsForTable()); ChangedValueOwners bildet die Zeilen-Änderungen eines UpdateEvent auf die Besitzer ab.
- ModelService.findChangedValueOwners(UpdateEvent) (tl-core) ist überschreibbar; die Standard-Implementierung prüft weiterhin die Quellen der Assoziationen.
- ElementModelService (tl-element, Basis von DynamicModelService) überschreibt sie mit ChangedValueOwners. Technische Verknüpfungen ohne Modell-Attribut (wie hasPersonalConfiguration) ziehen ihre Quelle nicht mehr in die Prüfung; Referenzen mit Speicherung in der Zeile des Ziels prüfen ihren Besitzer.
- Das UpdateEvent trägt den ChangeSet bereits vor der Prüfung; Änderungen am Modell in derselben Transaktion sind in den ModelTables der Transaktion sichtbar.
Kontaktdaten: ContactPersonManager weist beim Start jedem Konto ohne Kontaktdaten welche zu (repairAccountsWithoutContact(), über initUser(), d. h. mit Wiederverwendung eines freien Kontakts gleichen Anmeldenamens). Jedes Konto wird in einer eigenen Transaktion repariert; ein Konto, das aus anderem Grund nicht gespeichert werden kann, wird protokolliert und blockiert den Start nicht.
Nebenbei: tl-factory-app startete nicht mehr (Client resource 'tl-factory-css' requires unknown resource 'tl-react-controls-css', Ressource mit #29914 entfernt). tl-factory-css setzt jetzt tl-design-system-components voraus.
Test
- test.com.top_logic.element.meta.TestCheckValueOwners: Persönliche Einstellungen eines ungültigen Kontos werden gespeichert; Ändern einer link- oder inline-gespeicherten Referenz eines ungültigen Objekts scheitert weiterhin; Ändern eines referenzierten Objekts prüft den Referenzierenden nicht; Referenz und Wert in derselben Transaktion.
- test.com.top_logic.contact.layout.person.TestContactPersonManager: Reparatur mit neuem und mit wiederverwendetem Kontakt, nichts zu reparieren.
- tl-factory-app auf frischer Datenbank: Start ohne Fehler, root hat Kontaktdaten; nach Entfernen der Kontaktdaten von root in der Datenbank weist der Start sie wieder zu.