Hotfolder

Dokumente, die in einen Hotfolder geschoben werden, werden automatisch in docs365 documents archiviert. Der Hotfolder kann an beliebiger Stelle im Dateisystem angelegt werden und einen beliebigen Namen haben. Er muss händisch angelegt werden und wird nicht etwa erzeugt, wenn Sie ihn in der hotfolder.ini beschreiben. In der Hotfolder-Anwendung kann jeweils die aktuelle Version abgerufen werden.

Nach der ersten Ausführung enthält der Hotfolder die Unterverzeichnisse _Completed, _Failed und _Processing.

In der Hotfolder-Verarbeitung werden zusätzlich die im Archiv eingestellten Vorgabewerte eines Datenfelds beachtet, insofern das nicht über die neue Option ArchiveDefaults = false deaktiviert wird. Die in der hotfolder.ini in [<Sektion>/defaults] eingestellt Vorgabewerte überschreiben die aus der Archivkonfiguration.

Bei der Hotfolder-Verarbeitung ist es einfach, Fehler zu erkennen und zu analysieren. Einerseits wird der Status der Log-Ausgabe (INFO oder ERROR) farblich hervorgehoben, andererseits werden die eigentlichen Fehlermeldungen nun in einer eigenen Zeile abgesetzt und gut formatiert angezeigt:

../_images/hotfolder-hotfolderansicht.png

Auch in den Ereignisprotokollen werden die Fehlermeldungen nun besser formatiert:

../_images/hotfolder-fehlermeldung.png

Konfiguration der hotfolder.ini

Konfiguration: URL und Token pro Sektion

Bemerkung

Die Zugangsdaten für den Hotfolder wurden aus der [Hotfolder]-Sektion der settings.ini in eine [DEFAULT]-Sektion der hotfolder.ini migriert. Die Zugangsdaten, die in der settings.ini hinterlegt sind, werden weiterhin beachtet, falls die hotfolder.ini keine konfigurierten Zugangsdaten enthält.

Das Anlegen von unterschiedlichen Zugangsdaten pro Sektion wird nun unterstützt. Standardmäßig wird der Zugang aus [DEFAULT] verwendet, sofern keine sektionsspezifischen Daten hinterlegt sind.

Beispiel für unterschiedliche Konfigurationen:

[DEFAULT]
URL = http://documents.example.com:5050/
Token = bs9fMWw7c4ctgMgyRSB7y8U8qlksGOto

[DOCX]
; keine Zugangsdaten
Directory = ...
...

[CSV]
; Verwendung einer anderen URL
URL = http://documents.example.com:8551/
...

[PDF]
; Verwendung eines anderen Hotfolders
Token = 8Z6USm5wWfUu27UlQHQC351wwrqHfzJZ
...

[XML]
; Eigene URL und Token
URL = http://documents.example.com:8551/
Token = 8Z6USm5wWfUu27UlQHQC351wwrqHfzJZ
...

Wie ein Hotfolder funktioniert, wird in der hotfolder.ini im config-Verzeichnis festgelegt. Legen Sie für jeden Hotfolder eine Sektion in eckigen Klammern an. Der Name der Sektion kann frei gewählt werden. Unterhalb jeder Sektion können verschiedene Parameter und Untersektionen eingegeben werden

Parameter

Type

Pflichtfeld. Beschreibt die Art des Hotfolders. Gültige Werte sind xml, pdf, capture und importservice.

Directory

Pflichtfeld. Das Verzeichnis, in dem der Hotfolder die abgelegten Dateien sucht. Das Verzeichnis muss bereits existieren und wird nicht automatisch angelegt.

Archive

Pflichtfeld. Das Archiv, in das die Dateien des Hotfolders gespeichert werden. Mögliche Werte sind

  • der Kurzname eines Archivs

  • (bei PDF-Hotfoldern) eine Format-Beschreibung zur Ermittlung des Archivnamens aus den Feldwerten (siehe Untersektionen [Test/archive]).

Dateien können auch stattdessen im Eingang eines Benutzers abgelegt werden. Dafür wird das allgemeine Format <archive>@<user> verwendet. Wenn ein @ vorkommt und dahinter ein Benutzername steht, werden die Daten aus dem Hotfolder nicht direkt in ein Archiv geschrieben, sondern im Eingang des angegebenen Benutzers abgelegt. Die Angabe eines Archivs ist in diesem Fall optional. Falls ein Archiv angegeben ist, wird dieses Archiv im Eingang vorausgewählt und es ist möglich, Index-Daten für den späteren Archivierungs-Vorgang zwischenzuspeichern.

Beispiele für gültige Archive-Werte:

invoice

Es wird in das Archiv mit dem Kurznamen invoice archiviert.

@schmidt

Die Dateien werden im Eingang des Benutzers mit dem Login-Namen schmidt abgelegt.

invoice@schmidt

Die Dateien werden im Eingang des Benutzers mit dem Login-Namen schmidt abgelegt, das Archiv mit dem Kurznamen invoice ist vorausgewählt.

Hotfolder können Dokumente auch direkt in einem Gruppeneingang ablegen.

Analog zur bisherigen Syntax <archive>@<user> (legt das Dokument in den Eingang des Benutzers mit dem Login-Namen benutzer und setzt das Archiv mit dem Kurznamen archiv als Voreinstellung) wird das Dokument bei #Gruppenname in die Gruppe mit den Namen Gruppenname gelegt. Auch hier kann ein Archiv über den Kurznamen vor dem # voreingestellt werden.

Active

Wird der Wert auf false oder 0 gesetzt, wird der entsprechende Hotfolder bei der Verarbeitung ignoriert.

DeleteCompleted

Ein ganzzahliger Wert, der angibt, nach wie vielen Tagen archivierte Dateien aus dem Completed-Verzeichnis gelöscht werden. 0 bedeutet sofort nach dem Archivieren löschen, -1 löscht Dateien nie. Ist der Wert gar nicht gesetzt, wird als Standard -1 angenommen.

MinFilesize

Die minimale Dateigröße in Bytes, ab der der Hotfolder die Dateien beachtet. Der Vorgabewert für diese Einstellung ist 1, sodass 0 Byte große Dateien standardmäßig ignoriert werden.

Postbox

Optional. Ermöglicht die Angabe von Login-Namen in einer kommagetrennten Liste. Die hier konfigurierten Benutzer erhalten beim Import den Vorgang zusätzlich ins Postfach. Wenn im Archiv Mandanten aktiviert sind, werden Benutzer, die auf den Mandanten des Vorgang keinen Zugriff haben, im System-Ereignisprotokoll vermerkt.

[Demo-Archiv]
...
Postbox=admin, testuser

Ein neues Attribut result.postbox ist nun aufrufbar. Hier können Benutzer als Strings hinzugefügt werden. Falls das Attribut nicht definiert wird, verwendet die Direktive Postbox=... stattdessen.

import importservice

class ImportService(importservice.Base):
    def process(self, file, result):
        result.postbox = ["admin", "testuser"]

Wichtig

Im Falle einer Postbox-Konfiguration sollten die Benutzer dem ausgewählten Mandaten im Archiv zugewiesen sein, da sie den Vorgang andernfalls nicht ins Postfach bekommen und vom Hotfolder stattdessen eine Warnung ausgegeben wird.

Mehr Informationen zur Bedienung:

Wenn der Typ PDF ist, gibt es weitere Parameter:

Pattern

Pflichtfeld. Ein regulärer Ausdruck, der den Feldschlüssel der Metadaten in der PDF-Datei beschreibt. Beispielsweise sucht C2[0-9]{4} im PDF-Text nach Feldern, die mit C2 beginnen und von vier weiteren Zahlen gefolgt werden, z.B. C29876.

SplitMark

Standardmäßig werden PDF-Dateien in einzelne Seiten aufgeteilt und anschließend so gruppiert, dass ein neues Dokument beginnt, wenn auf einer Seite Felder existieren, die dem angegebenen Pattern entsprechen. Seiten ohne eigene Felder werden dem letzten Dokument angehängt. Wenn allerdings SplitMark angegeben wird, wird nur dann ein neues Dokument angenommen, wenn sich der Wert im angegebenen Feld geändert hat. Der Wert von SplitMark muss dem Pattern entsprechen, d.h. beim Pattern C2[0-9]{4} kann SplitMark den Wert C29876 haben, nicht aber Test.

Filemask

Ermöglicht das Filtern der zu verarbeitenden Dateien im Hotfolder mit Hilfe von Platzhaltern. Wenn z.B. nur PDF-Dateien beachtet werden sollen, deren Dateiname mit SOEPR beginnt, muss dieser Parameter auf den Wert SOEPR*.pdf gesetzt werden. Wenn dieser Parameter fehlt, wird standardmäßig nach *.pdf gesucht.

Split

Das Aufteilen von PDF-Dateien in einzelne Seiten und anschließendes Gruppieren ist standardmäßig aktiviert. Wenn allerdings Split den Wert false oder 0 enthält, wird dieses Verfahren deaktiviert. Die PDF-Datei wird ohne weitere Nachbearbeitung direkt archiviert (die Metadaten aus den Feldern aber dennoch extrahiert).

Client

Pflichtfeld, wenn im Archiv Mandanten konfiguriert sind, ansonsten ohne Auswirkung. In dieser Option wird das Kürzel des Mandanten eingestellt, der neuen Vorgängen zugewiesen wird.

[Demo-Archiv]
...
Client = docs 365

In Import-Services kann der Mandant über result.client dyamisch überschrieben werden und im XML-Hotfolder über das Tag <client>. Auch hier muss jeweils das Kürzel des Mandanten angegeben werden.

import importservice

class ImportService(importservice.Base):
    def process(self, file, result):
        result.client = "docs 365 AG"
Smartindexing

Optional. Führt Smartindexing in der Hotfolder-Verarbeitung aus. Wird aktuell bei folgenden Dateiformaten unterstützt: * PDF-Dateien, die einfach extrahierbaren Text enthalten. * DOCX-Dateien

Ist die Option Client gesetzt, wird ein mandantenspezifisches Smartindexing durchgeführt.

OnSmartindexingEvent

Optional. Führt zusätzlich zum Smartindexing das on_smartindexing-Event in der Hotfolder-Verarbeitung aus. Standardmäßig ist diese Einstellung auf false.

ArchiveDefaults

Optional. Standardmäßig werden in der Hotfolder-Verarbeitung die im Archiv konfigurierten Vorgabewerte eines Datenfelds beachtet und zusätzlich bereitgestellt. Werte aus einer Untersektion [<Sektion>/defaults] überschreiben die durch diese Option geladenen Vorgabewerte.

Untersektionen

Eine Untersektion wird unterhalb einer Sektion mit eckigen Klammern und einem Schrägstrich geschrieben; wenn die Sektion z. B. [Test] heißt, kann eine Untersektion folgendermaßen heißen:

  • [Test/defaults],

  • [Test/fields] oder

  • [Test/archive]

Im ersten Fall wird für ein Datenfeld im Archiv ein Standardwert festgelegt, es sei denn, für dieses Feld gibt es Metadaten. Im folgenden Beispiel wird die Spalte belegart mit dem Wert Rechnung gefüllt:

[Test/defaults]
belegart=Rechnung

Im zweiten Fall kann man die Metadaten aus der PDF-Datei mit Datenfeldern aus dem Archiv verknüpfen (Feldzuordnung). Der linke Wert beschreibt den Schlüssel des Feldes in der PDF-Datei und der rechte Wert die Kurz-ID des Datenfelds im Archiv:

[Test/fields]
C21003=datum
C21004=firmennummer
C21005=jahr

Im dritten Fall kann man aus den Metadaten der PDF-Datei das Zielarchiv automatisch ermitteln (Archivzuordnung). Angenommen, die Metadaten einer PDF-Datei enthalten ein Feld mit dem Schlüssel C21005, dass das Jahr einer Rechnung als Wert hat.

Wenn nun Archive den Wert rechnungen_{C21005} enthält (den Feldschlüssel in geschweiften Klammern) und das Feld C21005 den Wert 2014, wird als Archiv-ID automatisch rechnungen_2014 angenommen.

Dieser Archiv-ID kann nun zusätzlich über die Untersektion archive explizit eine andere Archiv-ID zugewiesen werden:

[Test/archive]
rechnungen_2013 = alte_rechnungen
rechnungen_2014 = 00531718-f5e4-f94c-7b38-d9d17c54c215

Existiert in dieser Untersektion keine Zuordnung, wird der vorher ermittelte Wert selbst als Archiv-ID verwendet.

Beispiel einer hotfolder.ini

[ERP]
Directory=D:\Data\Hotfolder
Archive=verdienstnachweise
Active=True
Type=pdf
Filemask=SOEPR*.pdf
Pattern=C2[0-9]{4}
SplitMark=C21011
Split=1
Postbox=admin, testuser
Client=demomandant
Smartindexing=1

[ERP/fields]
C21003=datum
C21004=firmennummer
C21005=jahr
C21011=name
C21014=periode_von
C21015=periode_bis
C21016=personalnummer
C21030=belegart
C21041=benutzer

[ERP/defaults]
belegart=Rechnung

Es ist möglich, für größere Flexibilität mehrere Regeln auf einmal zu definieren und mit Ausnahmen zu kombinieren:

Filemask=*.pdf|*.xml|*.DOCX
FilemaskExclusion=tmp*.pdf|Desktop.ini

In diesem Beispiel werden alle Dateien mit der Endung pdf, xml oder docx verarbeitet, jedoch nicht die Datei Desktop.ini oder alle PDF-Dateien, deren Name mit „tmp“ beginnt. Grundsätzlich wird eine Datei immer dann verarbeitet,

  • wenn mindestens eine Regel in Filemask auf sie zutrifft. Die Option Filemask kann auch weggelassen werden, dann wird die Voreinstellung des jeweiligen Hotfolder-Typs verwendet (beispielsweise nur *.xml im XML-Hotfolder oder alle Dateien im Hotfolder-Typ file).

  • wenn keine der Regeln in FilemaskExclusion auf sie zutrifft.

Des Weiteren erhalten nach dem Import-Vorgang die Benutzer admin und testuser die neuen Vorgänge ins Postfach gelegt.

Tipp

Leerzeichen um das | sollten vermieden werden, da die Leerzeichen dann Teil der Regel werden und nur Dateien beachten, die mit einem Leerzeichen beginnen bzw. enden.

Ausführung über pa_hotfolder.exe

Selektive Ausführung von Sektionen

Die pa_hotfolder.exe unterstützt nun ein neues Kommando --section bzw. -s, mit dem spezifische Sektionen der hotfolder.ini angegeben werden können. Nur diese angegebenen Abschnitte werden berücksichtigt, während die nicht angegebenen ausgelassen werden. Die Sektionen können ohne Beachtung der Groß- oder Kleinschreibung angegeben werden.

pa_hotfolder.exe --section pdf csv

Die Verarbeitung der Dateien im Hotfolder muss angestoßen werden durch die pa_hotfolder.exe im bin-Verzeichnis. Geben Sie am Prompt pa_hotfolder.exe ein.

../_images/hotfolder-pa-hotfolder.png

Abbildung 2 pa_hotfolder.exe

Die pa_hotfolder.exe verwendet die normale Web-API, was einige Vorteile hat:

  • Die pa_hotfolder.exe muss nicht unbedingt auf dem gleichen Computer ausgeführt werden, auf dem auch docs365 documents installiert ist. Es wird eine separate pa_hotfolder.exe-Anwendung (siehe unten) bereitgestellt, die man auf beliebig vielen Computern installieren kann, die dann alle gleichzeig in eine einzige Documents-Installation archivieren.

  • Obwohl docs365 documents eine reine 64-Bit-Anwendung ist, können damit auch 32-Bit-ODBC-Datenquellen verwendet werden, da die separate pa_hotfolder.exe-Anwendung auch in einer 32-Bit-Version bereitgestellt wird.

  • Auch wenn die pa_hotfolder.exe direkt in der Documents-Installation ausgeführt wird, ist es nicht zwingend erforderlich, dass sie unter einem Benutzerkonto läuft, das Schreibrechte auf die Speicher hat. Es reicht aus, wenn die pa_hotfolder.exe lesend auf die settings.ini und hotfolder.ini zugreifen kann.

- Dienstbenutzer für die Hotfolder-Archivierung

Eine Folge dieses neuen Verfahrens ist, dass sich nun auch der Hotfolder bei der Web-API als Benutzer authentifizieren muss, selbst wenn die in der regulären Documents-Installation enthaltene pa_hotfolder.exe über localhost archiviert.

Für diesen Zweck gibt es den Benutzertyp „Dienstbenutzer“:

../_images/hotfolder-dienstbenutzer.png

Dienstbenutzer unterscheiden sich von normalen Benutzern darin, dass sie sich nicht in der Benutzer-Oberfläche anmelden können und anstatt eines Login-Namens und Passworts nur ein vom Server generiertes API-Token für die Authentifizierung kennen. Das API-Token kann in der Administrationsoberfläche invalidiert werden, indem man im Token-Feld auf das „X“ klickt und anschließend speichert. Der Server generiert dann ein neues Token, sodass das alte nicht mehr gültig ist.

Auch Dienstbenutzern müssen Rollen zugewiesen werden, damit sie auf Archive zugreifen können. Somit ist es möglich, den Zugriff so weit einzuschränken, dass eine pa_hotfolder.exe auf einem externen Computer zwar in ein bestimmtes Archiv archivieren, mit dem Token aber nicht die Daten aus anderen Archiven über die API auslesen kann.

Die URL des Servers und das API-Token müssen wie folgt in der settings.ini in der neuen Sektion [Hotfolder] eingetragen werden:

[Hotfolder]
URL = http://documents.example.com:8551/
Token = ArRwFYljbSKYZHaBX2VpVhp6oHak56Ju

Diese Sektion wird in der settings.ini automatisch eingetragen, dafür wird ebenfalls automatisch ein erster Dienstbenutzer mit dem Namen Hotfolder erzeugt, der einer neuen Rolle Hotfolder zugewiesen wird, die zunächst einmal Schreibrechte auf alle Archive hat.

Separate pa_hotfolder.exe``-Anwendung:

Es werden noch zwei zusätzliche Dateien mit ausgeliefert:

  • pa_hotfolder-2.1.0-x86.zip (32-Bit)

  • pa_hotfolder-2.1.0-x64.zip (64-Bit)

Diese beiden Dateien enthalten die separate pa_hotfolder.exe-Anwendung jeweils in einer 32-Bit- und einer 64-Bit-Version. Der Inhalt dieser ZIP-Dateien kann ohne Installation in einem beliebigen Dateipfad entpackt werden, um von dort aus Archivierungen über Hotfolder durchzuführen. Dafür müssen in dem config-Verzeichnis eine minimale settings.ini (mit der Sektion [Hotfolder] wie oben angeben) und eine hotfolder.ini eingerichtet werden.

- Notwendige Anpassungen in Import-Services

Durch die Verwendung der Web-API gibt es in der post_process-Methode von Import-Services eine nicht rückwärtskompatible Änderung, die eine eventuelle Anpassung der Import-Services erfordert (z.B. im index-from-db-Import-Service).

Der Parameter record, der den erzeugten Vorgang repräsentiert, ist ein Python-dict, dessen Inhalt die Antwort der JSON-Web-API ist und auf dessen Eigenschaft über dict-Schlüssel zugegriffen werden kann.

Beispiel:

# Vorher:
def post_process(self, record):
    for attachment in record.attachments:
        id = attachment.id

# Nachher:
def post_process(self, record):
    for attachment in record['attachments']:
        id = attachment['id']

Dokumente über Import-Services an bestehende Vorgänge anhängen

Import-Services können ebenfalls dazu verwendet werden, über einen Hotfolder Dokumente an bereits bestehende Vorgänge anzuhängen. Dafür muss im result-Objekt anstatt result.archive die ID des zu erweiternden Vorgangs in result.record geschrieben werden.

Der ImportService stellt eine Hilfsfunktion self.find_records(archive, query) bereit, mit denen nach Vorgängen gesucht werden kann. Der Parameter archive ist die ID oder der Kurzname des zu verwendenen Archivs und query ein Such-Filter mit der gleichen Syntax, die auch in den gefilterten Archiven oder der Spaltensuche verwendet wird. Der Rückgabewert ist eine Liste von gefundenen Vorgängen als dict, die ID kann über den Schlüssel id extrahiert werden:

class ImportService(importservice.Base):
    def process(self, file, result):
        result.add_file(file)
        # Vorgang im Archiv "rechnungen" suchen, dessen
        # Belegnummer "ABC123" ist.
        records = self.find_records('rechnungen', '_belegnr = "ABC123"')
        if len(records) != 1:
            raise RuntimeError('Es wurde genau ein Vorgang erwartet.')
        result.record = records[0]['id']

Beim Aufruf von find_records sollte grundsätzlich die Länge der zurückgegebenen Liste geprüft werden, da bei Filtern auch gar keine oder mehrere Vorgänge zurückgegeben werden. Die maximale Anzahl der gefundenen Vorgänge ist auf 100 beschränkt.

Parallele Hotfolder-Verarbeitung

Für eine bessere Performance verarbeitet die pa_hotfolder.exe mehrere Dateien zeitgleich, was sich insbesondere bei der Hotfolder-Verarbeitung auf einem separaten Computer über eine langsame Netzwerkverbindung bemerkbar macht. Standardmäßig werden acht Dateien gleichzeitig verarbeitet, was über einen Parameter der pa_hotfolder.exe angepasst werden kann:

pa_hotfolder.exe --threads 2

Hotfolder-Typ file

Der Hotfolder-Typ file importiert alle (evtl. durch die Filemask gefilterten) Dateien aus dem Hotfolder direkt in den Eingang eines Benutzers. Da dieser Hotfolder-Typ keine direkte Archivierung unterstützt, muss in dem Archive-Parameter zwingend ein Benutzer-Eingang angegeben werden.

Beispiel:

[Files]
Directory = D:\Hotfolder\Files
Type = file
Filemask = *.docx
Archive = @user

Hotfolder-Typ csv

Mit dem Hotfolder-Typ csv kann man zu importierende Dateien über eine einzelne CSV-Datei beschreiben. Diese CSV-Datei kann viele Vorgänge auf einmal beschreiben und hat folgendes Format:

0;D:\Import\demo1.pdf;demo1;_field1;Test;_field2;2015-02-23
0;D:\Import\demo2.pdf;
1;PDFs\test.pdf;demo2;_field1;Test

Die Spalten in der CSV-Datei haben folgende Bedeutung:

  1. Eine laufende Nummer, die pro Vorgang hochzählen muss. Wenn mehrere Zeilen die gleiche Nummer haben, generiert die erste Zeile einen neuen Vorgang und alle weiteren Zeilen mit dieser Nummer werden als zusätzliche Dokumente an diesen Vorgang angehängt (die daher auch nur noch eine Datei definieren müssen und kein Archiv).

  2. Ein Dateipfad. Dieser kann wahlweise absolut oder relativ sein, wobei letztere relativ zum Hotfolder-Verzeichnis ist.

  3. Ein Archiv-Kurzname.

  4. Anschließend folgen beliebig viele Spaltenpaare von Spalten-Kurzname (mit einem Unterstrich als Präfix) und Wert.

Im obigen Beispiel werden durch die CSV-Datei zwei Vorgänge angelegt: In das Archiv demo1 wird ein Vorgang mit zwei Dokumenten (demo1.pdf und demo2.pdf) erzeugt, der Werte für die Datenfelder field1 und field2 hat. In das Archiv demo2 wird ein Dokument mit einem Wert für das Datenfeld field1 importiert. Der csv-Hotfolder verschiebt importierte Dokumente nicht in die Verzeichnisse _ Completed und _ Failed des Hotfolders, es werden dort jedoch CSV-Dateien angelegt, die die erfolgreich importierten bzw. fehlgeschlagenen Zeilen der CSV-Datei enthalten. Die CSV-Datei im _ Failed-Verzeichnis enthält eine zusätzliche Spalte #ERROR#, hinter der eine Fehlermeldung steht. Die importierten Dokumente selbst werden entweder am Originalpfad stehen gelassen (DeleteCompleted = -1; Standard-Einstellung) oder sofort gelöscht (DeleteCompleted = 0).

Standardmäßig werden vom Hotfolder alle Dateien mit der Endung csv bearbeitet (Filemask = *.csv).

Alternative Hotfolder .ini

Beim Aufruf der pa_hotfolder.exe kann über den Parameter –ini eine alternative hotfolder.ini angegeben werden. Somit ist es beispielsweise möglich, über eine Aufteilung der Hotfolder auf mehrere INI-Dateien zu verschiedenen Zeiten nur bestimmte Hotfolder zu verarbeiten.

Wird als Parameter nur ein einfacher Dateiname verwendet, wird die INI-Datei im config-Verzeichnis der Installation (wo auch die hotfolder.ini liegt) gesucht:

# Verwendet die Datei config\h2.ini
pa_hotfolder.exe --ini h2.ini

Wenn im Parameter mindestens ein Verzeichnisseparator enthalten ist (\ oder /), wird die Datei relativ zum aktuellen Verzeichnis verwendet:

# Verwendet die Datei h3.ini im aktuellen Verzeichnis
pa_hotfolder.exe --ini .\h3.ini

# Verwendet die Datei im absoluten Pfad D:\h4.ini
pa_hotfolder.exe --ini D:\h4.ini

Leere Verzeichnisse und Unterverzeichnisse

Mit der neuen Hotfolder-Option DeleteEmptyDirectories werden nach Abschluss der Hotfolder-Verarbeitung rekursiv alle leeren Unterverzeichnisse entfernt, mit Ausnahme der Ordner _Completed, _Failed und _Processing. Standardmäßig ist diese Option auf false gesetzt.

DeleteEmptyDirectories = true

Methode write_viewable()

Analog zur Methode write_attachment der Export- und Import-Services steht nun im HTTP-Client und den beiden Services die Methode write_viewable zur Verfügung.

class ImportService(importservice.Base):
    def process(self, file, result):
        # Datei-Typ z.B. TIFF, DOCX
        result.add_file(file)

    def post_process(self, record):
        record = self.client.jget("records/" + record["id"])
        # Vorschau-Datei herunterladen in ein lokales Verzeichnis
        self.write_viewable(record["attachments"][0], r"D:\Documents"))

In diesem Beispiel wird die verarbeitete PDF automatisch zum Vorgang hinzugefügt und anschließend wieder in ein lokales Verzeichnis heruntergeladen. Im Unterschied zu write_attachment wird hier die Vorschau-PDF-Datei heruntergeladen. Sollte keine Vorschau existieren, dann ist der Rückgabewert der Methode None und es wird kein Download gestartet.

Unterordner berücksichtigen

In der Hotfolder-Konfiguration wird nun eine neue Optionen Subdirectories angeboten. Sobald der Wert auf true gesetzt wird, aktiviert sich das Iterieren durch Unterordner. Analog zu Filemask und FilemaskExclusion können anhand mehrerer Regeln und Ausnahmen, Dateien während des Durchlaufs ausgeschlossen werden. Eine |-getrennte Liste SubdirectoriesExclusion ermöglicht diese Ausnahmen. In der hotfolder.ini können die Konfigurationen wie folgt aussehen:

Subdirectories = true
SubdirectoriesExclusion = Test/** | C:\Users\User\Import\ExclusionFolder | a/b/c

Verzeichnisse, die von der Hotfolder-Verarbeitung ausgeschlossen werden sollen, können entweder als absolute oder relative Pfade angegeben werden oder anhand einiger Platzhalterzeichen zu einem Wildcard-Ausdruck kombiniert werden. Relative Pfade werden relativ zum Hotfolder-Verzeichnis ausgewertet, Pfade oder Muster ausserhalb des Hotfolder-Verzeichnisses werden aussortiert.

Beispiel Verzeichnis-Struktur mit Dateien:

A/
├── file1.tiff
├── file2.txt
├── test.tiff
├── AB/
│   └── file3.txt
└── AC/
    └── test123.txt

Definition mit Beispielen basierend auf den Verzeichnissen:

Platzhalter *

Entspricht einer beliebigen Anzahl von Zeichen (einschließlich keiner Zeichen).

Beispiele:

  • *B schließt die Ordner „B“ und „AB“ oder prinizpiell alle Ordner, die auf „B“ enden, aus.

  • AC/* schließt direkte Unterverzeichnisse von Ordner „AC“ aus.

  • */AC schließt das Unterverzeichnis „AC“ aus, das unmittelbar unter dem Hotfolder-Verzeichnis liegt.

Platzhalter **

Ein rekursiver Platzhalter. Deckt eine unbegrenzte Anzahl an Elementen/Verzeichnissen ab.

Beispiel:

  • **/B schließt jeden Ordner aus, dessen Name „B“ ist, unabhängig von seiner Tiefe im Verzeichnisbaum.

Platzhalter ?

Entspricht genau einem (beliebigen) Zeichen.

Beispiele:

  • ?B schließt Ordner aus, dessen Name mit einem beliebigen Zeichen beginnt, gefolgt von „B“. In diesem Fall trifft es aus das Verzeichnis „AB“ zu.

Verarbeitete Dateien aus Unterverzeichnissen werden eins-zu-eins im _Completed-Ordner hinterlegt.

Beispiel:

  • Vor der Verarbeitung unter ./Import/OrdnerA/OrdnerAB/file3.txt

  • Nach der Verarbeitung unter ./Import/_Completed/test_20240101/OrdnerA/OrdnerAB/file3.txt

Im Import-Service können über die Liste self.subdirectory_exclusions weitere Ausnahmen hinzugefügt werden. Die pre_process-Methode eignet sich dafür, da die Verarbeitung hier noch nicht stattgefunden hat.

class ImportService(importservice.Base):
    def pre_process(self):
        # Unterordner als Ausnahmen, die in der Hotfolder-Verarbeitung übersprungen werden.
        self.subdirectory_exclusions.append("foo/*")

        absolute_path = os.path.join(self.hotfolder.directory, "a/b/a")
        self.subdirectory_exclusions.append(absolute_path)

on_smartindexing-Event in run_smartindexing

Sollte im Design-Formular eines Archivs ein on_smartindexing-Event konfiguriert sein, wird bei der Ausführung eines Hotfolders mit der Option Smartindexing = true dieses aufgerufen und bei der Vorgangs-Erstellung mitverarbeitet. Mit der Methode self.run_smartindexing aus dem Import-Service wird nun der Inhalt mit den aktualisierten Werten aus dem on_smartindexing-Event bereitgestellt.

Neue Variable $importservice bei on_save

Im on_save-Event steht nun eine zusätzliche Variable bereit:

$importservice

Ist true, wenn das on_save-Event für einen gerade neu angelegten oder einen bestehenden Vorgang aus dem Import-Service heraus ausgelöst wird, ansonsten false. Solange der Vorgang innerhalb der process-Methode erstellt oder aktualisiert wurde, gilt $importservice = true.

if $importservice and $new then
    _imported = "Neuer Vorgang über den Import-Service"
elseif $importservice and $update then
    _imported = "Aktualisierter Vorgang über den Import-Service"
end