update()

Aktualisiert ein bestehendes Objekt auf dem Server. Intern wird dms.XMLUpdate verwendet. Die übergebene Modell-Instanz wird nicht verändert.

ECM-Modell-Referenz — vollständige Beschreibung von system.is_modified, system.modified_fields, system.modified_table_fields, system.has_removed_table_rows, system.requires_table_field_replacement und der Änderungsverfolgung.

Wurden keine Felder geändert und keine Dateien übergeben, wird der Server-Aufruf standardmäßig übersprungen. Mit force=True kann der Aufruf erzwungen werden.

Wird die aktualisierte Instanz direkt nach dem Speichern benötigt, ist update_and_get() die kompaktere Alternative.

1. Signatur

  • Sync

  • Async

ecm.dms.update(
    model: T,
    files: list[JobRequestFile] | None = None,
    replace_files: bool = True,
    force: bool = False,
    *,
    check_mandatory: bool = True,
) -> None
await ecm.dms.update(
    model: T,
    files: list[JobRequestFile] | None = None,
    replace_files: bool = True,
    force: bool = False,
    *,
    check_mandatory: bool = True,
) -> None

2. Parameter

Name Typ Beschreibung

model

ECMFolderModel | ECMRegisterModel | ECMDocumentModel

Die zu aktualisierende Modell-Instanz. Muss vom Server geladen worden sein, damit model.system.id gesetzt ist.

files

list[JobRequestFile] | None

Optionale Dateiliste für das Dokument. Nur für ECMDocumentModel erlaubt — bei Ordner- oder Register-Modellen wird TypeError geworfen. Standard: None.

replace_files

bool

Wenn True (Standard) und files übergeben wurden, ersetzen die neuen Dateien die vorhandenen Dokumentdateien (REPLACEFILES=1). Wenn False, werden die Dateien den bestehenden hinzugefügt. Nur wirksam für ECMDocumentModel mit files.

force

bool

Wenn True, wird der Server-Aufruf immer ausgeführt, auch wenn keine Änderungen erkannt wurden. Standard: False.

check_mandatory

bool

Wenn True (Standard), wird clientseitig geprüft, ob alle als mandatory=True deklarierten ECMField-Felder einen Wert haben. Bei False wird die client- und serverseitige Pflichtfeldprüfung deaktiviert (CHECKOBLIGATION=0).

3. Rückgabewert

None

4. Automatisches Überspringen

Wenn alle der folgenden Bedingungen zutreffen, wird der Server-Aufruf ohne Fehler übersprungen:

  • force=False (Standard)

  • model.system.is_modified ist False — keine Felder wurden geändert

  • files ist None

Das Änderungsprotokoll (is_modified, modified_fields, modified_table_fields) wird vom Modell automatisch beim Setzen von Feldwerten geführt. Nur diese tatsächlich geänderten Felder werden serialisiert — unveränderte Felder bleiben dem Server fern und werden nicht überschrieben.

Tabellenfelder werden differenziert behandelt:

  • Wurde eine geladene Zeile verändert, entfernt oder ersetzt (d. h. system.requires_table_field_replacement ist True), wird das Tabellenfeld komplett neu übertragen und der Server-Aufruf erhält automatisch REPLACETABLEFIELDS=1, sodass der Server die gesamte Tabelle ersetzt.

  • Wurden nur neue Zeilen angefügt, werden ausschließlich diese neuen Zeilen übertragen — der Server-Default „APPEND" verhindert Duplikate der geladenen Zeilen.

  • Tabellenfelder ohne Änderung werden gar nicht in der XML aufgenommen und bleiben serverseitig unangetastet.

5. Schreibbare Systemfelder

Systemfelder (SystemFields-Enum) werden standardmäßig aus der dms.XMLUpdate-XML herausgefiltert, da der enaio-Server fast alle mit ECMAccessDeniedException („The specified system field cannot be changed by the user") ablehnt. Eine Allowlist WRITABLE_SYSTEM_FIELDS (in ecmind_blue_client.const) listet die wenigen Felder, die der Server tatsächlich akzeptiert:

Feld Verhalten

OBJECT_FOREIGNID

String-Feld. Insert + Update. Hält die Referenz auf das Dokument im externen Archivsystem; in Kombination mit OBJECT_SYSTEMID wird ein Dokument zum Referenzdokument („grüner Pfeil" wenn system_id=0). Beliebige String-Werte zulässig — manche Archiv-Konfigurationen erzwingen serverseitig eine numerische Spalte und casten dann zu '0'. Über das Attribut field_function="NULL" auf dem <Field> clearbar.

OBJECT_SYSTEMID

Int-Feld. Nur Update. Beim Insert verlangt der Server, dass OBJECT_FOREIGNID zusätzlich gesetzt ist (sonst Fehler -1013 „A system ID was specified but no foreign ID").

OBJECT_USERGUID

String-Feld (Owner). Insert + Update. Der Wert muss der Benutzername sein (z. B. "ROOT"), nicht die GUID-Hex. Der Server löst den Benutzer auf und speichert die GUID, die beim nächsten Read zurückkommt. Eine GUID-Hex direkt zu senden schlägt mit Fehler -1019 („The specified owner could not be determined") fehl.

Nicht über <Field> verfügbar, sondern als XML-Attribute auf <Object>/<ObjectType> gepflegt und über andere APIs (z. B. insert(), move()) gesteuert: OBJECT_MAIN (= maintype), OBJECT_CO (= cotype), OBJECT_ID (= object_id), SDSTA_ID/SDREG_ID/FOLDERID/REGISTERID/… (= folder_id/register_id/…). Diese liefern als <Field> ebenfalls ECMAccessDeniedException zurück.

Weitere bislang nicht entdeckte schreibbare Systemfelder können nachträglich in WRITABLE_SYSTEM_FIELDS ergänzt werden, ohne Modelländerungen.

from ecmind_blue_client import WRITABLE_SYSTEM_FIELDS
# Programmatisch erweitern (Run-time; persistiert nicht):
WRITABLE_SYSTEM_FIELDS.add("OBJECT_AVID")

6. Ausnahmen

ValueError

model.system.id ist None (Objekt wurde nicht vom Server geladen) oder check_mandatory=True und ein Pflichtfeld ist nicht gesetzt, oder ein schreibgeschütztes Feld (ECMField(read_only=…)) wurde geändert — siehe ECM-Modell.

TypeError

files wurde für ein Ordner- oder Register-Modell übergeben.

7. Beispiele

7.1. Einfaches Feldupdate

  • Sync

  • Async

folder = ecm.dms.get(InvoiceFolder, 12345)
folder.Title = "Rechnung 2024 (aktualisiert)"
ecm.dms.update(folder)
folder = await ecm.dms.get(InvoiceFolder, 12345)
folder.Title = "Rechnung 2024 (aktualisiert)"
await ecm.dms.update(folder)

7.2. Dokument mit Datei ersetzen

  • Sync

  • Async

from ecmind_blue_client.rpc import JobRequestFileFromPath

doc = ecm.dms.get(InvoiceDocument, 42)
doc.Title = "Rechnung Nr. 42 (korrigiert)"
ecm.dms.update(
    doc,
    files=[JobRequestFileFromPath("/tmp/rechnung_v2.pdf")],
    replace_files=True,  # vorhandene Dateien ersetzen (Standard)
)
from ecmind_blue_client.rpc import JobRequestFileFromPath

doc = await ecm.dms.get(InvoiceDocument, 42)
doc.Title = "Rechnung Nr. 42 (korrigiert)"
await ecm.dms.update(
    doc,
    files=[JobRequestFileFromPath("/tmp/rechnung_v2.pdf")],
    replace_files=True,
)

7.3. Datei anhängen statt ersetzen

  • Sync

  • Async

from ecmind_blue_client.rpc import JobRequestFileFromPath

doc = ecm.dms.get(InvoiceDocument, 42)
ecm.dms.update(
    doc,
    files=[JobRequestFileFromPath("/tmp/anhang.pdf")],
    replace_files=False,  # Datei hinzufügen, bestehende behalten
)
from ecmind_blue_client.rpc import JobRequestFileFromPath

doc = await ecm.dms.get(InvoiceDocument, 42)
await ecm.dms.update(
    doc,
    files=[JobRequestFileFromPath("/tmp/anhang.pdf")],
    replace_files=False,
)

7.4. Update erzwingen

Nützlich, wenn externe Logik eine Neuübermittlung erfordert, obwohl keine Felder geändert wurden:

  • Sync

  • Async

folder = ecm.dms.get(InvoiceFolder, 12345)
# keine Feldänderung — ohne force=True würde der Aufruf übersprungen
ecm.dms.update(folder, force=True)
folder = await ecm.dms.get(InvoiceFolder, 12345)
await ecm.dms.update(folder, force=True)

7.5. Pflichtfeldprüfung deaktivieren

  • Sync

  • Async

folder = ecm.dms.get(InvoiceFolder, 12345)
folder.Title = None  # Pflichtfeld leeren
# check_mandatory=False: kein Fehler, Pflichtfeldprüfung auch serverseitig deaktiviert
ecm.dms.update(folder, check_mandatory=False)
folder = await ecm.dms.get(InvoiceFolder, 12345)
folder.Title = None
await ecm.dms.update(folder, check_mandatory=False)

8. Siehe auch

  • update_and_get() — kombiniert update() und get() in einem Aufruf, wenn die aktualisierte Instanz benötigt wird

  • insert() — legt ein neues Objekt an

  • get() — lädt ein einzelnes Objekt vom Server