Job options

Every dms.XML* server job accepts a semicolon-separated Options string such as INITFIELDS=0;CHECKKEYFIELDS=0. The option classes model those options in a typed way: one method per option, and each class offers only the options its job actually accepts.

The most common options are also available as dedicated parameters (check_mandatory, hard_delete, copy_cascading, …). The option objects complement those, they do not replace them.

1. Classes

Class Job Used by

ECMInsertOptions

dms.XMLInsert

insert(), insert_and_get(), insert_variant(), insert_variant_and_get()

ECMUpdateOptions

dms.XMLUpdate

update(), update_and_get()

ECMUpsertOptions

dms.XMLImport

upsert() — the union of the insert and update sets, because XMLImport takes either branch depending on the search result

ECMDeleteOptions

dms.XMLDelete

delete()

ECMMoveOptions

dms.XMLMove

move()

ECMCopyOptions

dms.XMLCopy

copy()

2. Usage

The objects are immutable: every method returns a new object, so calls can be chained.

  • Sync

  • Async

from ecmind_blue_client.ecm import ECMInsertOptions

object_id, _ = ecm.dms.insert(
    InvoiceDocument(Title="Invoice no. 42"),
    folder_id=folder.system.id,
    options=ECMInsertOptions().init_fields(False).check_key_fields(False),
)
from ecmind_blue_client.ecm import ECMInsertOptions

object_id, _ = await ecm.dms.insert(
    InvoiceDocument(Title="Invoice no. 42"),
    folder_id=folder.system.id,
    options=ECMInsertOptions().init_fields(False).check_key_fields(False),
)

On the upsert builder it is a builder method:

from ecmind_blue_client.ecm import ECMUpsertOptions

object_id, type_id, hits, action = (
    ecm.dms.upsert(InvoiceFolder(Title="Invoice 2024"))
    .search(InvoiceFolder.Title == "Invoice 2024")
    .options(ECMUpsertOptions().init_fields(False))
    .execute()
)

3. Precedence

Options derived from the typed parameters and options from the option object are merged. On conflict the option object wins:

# check_mandatory=False would send CHECKOBLIGATION=0,
# the option object sets it back to 1.
ecm.dms.insert(model, check_mandatory=False, options=ECMInsertOptions().check_obligation(True))
# sent: CHECKOBLIGATION=1

That is how you skip the client-side mandatory check without also disabling the server-side one.

4. Worked example: import from a legacy system

The most common reason to reach for job options is an import that carries all values itself and therefore trips over the server’s automatic behaviour. Three things typically collide: the object type has key fields the server wants to initialise and check for uniqueness, catalog values show up that are not maintained yet, and individual strings are longer than the field length allows.

from ecmind_blue_client.ecm import ECMInsertOptions, ECMUpdateOptions

# Build once, reuse inside the loop: the objects are immutable.
IMPORT_INSERT = (
    ECMInsertOptions()
    .init_fields(False)        # the import supplies the values itself
    .check_key_fields(False)   # the invoice number is a key field and already unique
    .check_catalogue(False)    # cost centres are not maintained in the catalog yet
    .truncate_values(True)     # truncate overlong legacy data instead of rejecting it
)
IMPORT_UPDATE = ECMUpdateOptions().check_catalogue(False).truncate_values(True)

for record in legacy_records:
    hits = (
        ecm.dms.select(InvoiceDocument)
        .where(InvoiceDocument.InvoiceNumber == record.number)
        .execute()
    )
    if hits:
        doc = hits[0]
        doc.Title = record.title
        ecm.dms.update(doc, options=IMPORT_UPDATE)
    else:
        ecm.dms.insert(
            InvoiceDocument(Title=record.title, InvoiceNumber=record.number),
            folder_id=target_folder,
            options=IMPORT_INSERT,
        )

Every one of these options disables a check that exists for a reason. They belong in a deliberately scoped import or migration path, not in ordinary application code. check_key_fields(False), for instance, allows duplicates in a key field unless uniqueness is guaranteed elsewhere.

5. Turning off key field handling only

When only the key field automation is in the way:

options=ECMInsertOptions().init_fields(False).check_key_fields(False)

6. Options without a dedicated method

Server options that have no method of their own (newly added ones, for instance) are set through raw():

ECMInsertOptions().raw("SOMENEWOPTION", True)

raw() applies no job scoping — the caller is responsible for passing an option the target job knows.

An existing option string can be taken over:

ECMInsertOptions.from_string("INITFIELDS=0;CHECKKEYFIELDS=0")

7. Relation to the Options class

ecmind_blue_client.Options belongs to the deprecated legacy API (Client.xml_import()). It is flat, carries no job scoping, and should not be used in new code.

8. See also