Skip to content

Manuelle Sortierung Modul ​

Das Modul dient zur manuellen Erfassung von Sortierergebnissen. Sortierklassen werden pro Warengruppe aus dem EDBS geladen und beim Erstellen eines Auftrags anhand der Warengruppe der Partie zugewiesen. Über eine Admin-Konfigurationsseite kann festgelegt werden, welche EDBS-Klassen pro Warengruppe aktiv sind.

Architektur ​

Modulstruktur ​

src/modules/manualSorting/
├── controllers/
│   ├── SortingController.php              # Web-Ansicht für Sortierergebnisse
│   ├── admin/
│   │   └── ConfigController.php           # Admin: Sortierklassen-Konfiguration
│   └── api/
│       └── SupplierController.php         # Select2-Suche für Lieferanten
├── messages/
│   └── de/
│       └── manualsorting.php              # Übersetzungen
├── migrations/                            # Namespace: app\modules\manualSorting\migrations
│   ├── M260223075838AddManualSortingLicense.php
│   ├── M260223075858CreateManualSortingResultsTable.php
│   ├── M260223075926AddManualSortingUsedSortClassSetting.php
│   ├── M260223091644AddTimestampsToManualSortingResults.php
│   ├── M260223092035AddSettingForCurrentSortNumber.php
│   ├── M260223094957AddCompletedFlagToManualSortingResults.php
│   ├── M260223100040AddSortingJobPositionTableAndRenameManualSortingResults.php
│   ├── M260223101752AddForeignKeyForSortingJobs.php
│   ├── M260224075803ChangeAvailableClassesSettingToJsonType.php
│   ├── M260224095600ChangeChargeNumberToPartieNr.php
│   ├── M260225074054AddSortingJobDtoHtmlTemplateSetting.php
│   ├── M260225125753AdjustDataStructureToEDBSRRequirements.php
│   ├── M260303062016AddEdbsFetchedColumnsToTables.php
│   ├── M260316075051RemoveAvailableClassesSetting.php
│   ├── M260318073638AddInfoFieldsToManualSortingTables.php
│   ├── M260407135243AddWgColumn.php
│   ├── M260408072100AddColumnArtikelGrpKurz.php
│   ├── M260408090047AddActiveClassesSetting.php
│   └── M260408110723AddAverageWeightPerPackageColumn.php
├── models/
│   ├── ManualSortingJob.php               # Sortierauftrag (Job)
│   └── SortingJobPosition.php             # Einzelne Sortierklasse pro Job
├── views/
│   ├── sorting/
│   │   ├── index.php                      # GridView Sortierergebnisse
│   │   ├── edit.php                       # Sortierauftrag bearbeiten
│   │   └── _positions.php                 # Positionen-Teilansicht (ExpandRow)
│   └── admin/
│       └── config/
│           └── classes.php                # Admin: Sortierklassen-Konfiguration
├── modules/
│   └── rest/
│       ├── Module.php                     # REST-Submodul Bootstrap
│       ├── controllers/
│       │   └── SortingController.php      # REST API Endpunkte
│       └── models/
│           └── dto/
│               └── SortingJobDTO.php      # API-Serialisierung
└── Module.php                             # Modul-Bootstrap, Sidebar, i18n

Datenmodell ​

manual_sorting_job ​

Enthält die Sortieraufträge. Jeder Auftrag referenziert eine Partie aus dem EDBS.

SpalteTypBeschreibung
idintPrimary Key
sortNumberstring(45)Eindeutige Sortiernummer (z.B. 260014)
partieNrstring(255)Partienummer aus dem EDBS
sortDatedateDatum der Sortierung
modifieddatetimeAutomatischer Timestamp bei Änderung
completedboolean0 = offen, 1 = abgeschlossen
countintGebindeanzahl
supplierNrstringLieferantennummer
supplierNamestringLieferantenname
fruitInfostringFrucht/Artikelgruppe
commentstringSortierbemerkung
WarenGrpKurzstring(45)Warengruppe Kurzbezeichnung
ArtikelGrpKurzstring(45)Artikelgruppe Kurzbezeichnung
averageWeightPerPackagedecimalDurchschnittliches Gewicht pro Gebinde
edbs_fetched_datedatetimeZeitpunkt des EDBS-Datenabrufs

sorting_job_position ​

Positionen eines Sortierauftrags. Pro aktiver Klasse der Warengruppe wird eine Position erstellt.

SpalteTypBeschreibung
idintPrimary Key
sortingJobIdintFK zu manual_sorting_job.id (CASCADE)
sortClassstring(255)Name der Sortierklasse (z.B. "Klasse I 65-75")
edbsFruitClassIDintSortierklassen-ID aus dem EDBS
sortResultdecimal(10,2)Erfasstes Ergebnis (NULL = noch nicht erfasst)
modifieddatetimeAutomatischer Timestamp bei Änderung

Beziehungen ​

manual_sorting_job 1 ──── * sorting_job_position
                          FK: sortingJobId → id (CASCADE/CASCADE)

Sortiernummer-Vergabe ​

Eine Sortiernummer ist eine eindeutige Nummer, welche einen manuellen Sortierauftrag beschreibt. Sortiernummern werden sequentiell vergeben und im Setting current_sort_number gespeichert. Das Format ist JJNNNN:

  • JJ = zweistelliges Jahr
  • NNNN = vierstellige, aufsteigende Sequenz
php
// ManualSortingJob::createNewSortNumber()
$sortNumber = Yii::$app->settings->getSetting('current_sort_number', 'manualSorting');
$seq = substr($sortNumber, 2);
$sortNumber = (new DateTime())->format('y') . str_pad((int)$seq + 1, 4, '0', STR_PAD_LEFT);
Yii::$app->settings->saveSetting($sortNumber, 'current_sort_number', 'manualSorting');

Beispiel: 260001, 260002, ..., 269999.

Auftragserstellung ​

Die Erstellung eines Sortierauftrags erfolgt über ManualSortingJob::createNewJob($partieNr, $count):

  1. Die Warengruppe der Partie wird aus dem EDBS gelesen (USWLager::findOne)
  2. Alle Sortierklassen für diese Warengruppe werden aus dem EDBS geladen (SortierKlasse::findEdbs($key))
  3. Die aktiven Klassen werden anhand des activeClasses-Settings gefiltert (siehe Aktive Sortierklassen)
  4. Dabei wird geprüft, ob die konfigurierten aktiven Klassen tatsächlich noch im EDBS existieren (Schnittmenge)
  5. Ein neuer ManualSortingJob mit generierter sortNumber wird angelegt
  6. Für jede aktive Klasse wird eine SortingJobPosition erstellt

Wenn keine Klassen für die Warengruppe im EDBS existieren oder nach dem Filtern keine aktiven Klassen übrig bleiben, wird eine InvalidDataException geworfen.

Aktive Sortierklassen ​

Sortierklassen werden aus dem EDBS geladen (SortierKlasse::findEdbs). Da nicht immer alle EDBS-Klassen in iScan benötigt werden, kann pro Warengruppe konfiguriert werden, welche Klassen aktiv sind.

Setting activeClasses ​

KeyModulTypBeschreibung
activeClassesmanualSortingjsonAktive Sortierklassen-IDs pro Warengruppe

Die Struktur ist ein JSON-Objekt mit Warengruppen-Kurzbezeichnungen als Schlüssel und Arrays von sortierklasseID-Werten:

json
{
  "01": ["1", "3", "5"],
  "10": ["2", "4"],
  "010": ["10", "12", "15"]
}

Wichtig: Warengruppen-Nummern werden immer als Strings behandelt, da numerisch ähnliche Kombinationen (z.B. "10" und "010") unterschiedliche Warengruppen darstellen. json_decode konvertiert numerische String-Schlüssel zu Integers — beim Auslesen müssen die Schlüssel daher explizit zurück zu Strings gecastet werden (siehe ConfigController::getActiveClasses()).

Wenn für eine Warengruppe kein Eintrag im Setting existiert, werden alle EDBS-Klassen als aktiv betrachtet.

Admin-Konfigurationsseite ​

Erreichbar unter /manualSorting/admin/config/classes (nur für Benutzer mit admin-Rolle).

Ablauf:

  1. Warengruppe aus Dropdown auswählen (Daten aus ProductGroups::findEdbs())
  2. Alle Sortierklassen der gewählten Warengruppe werden aus dem EDBS geladen
  3. Klassen werden als GridView mit Checkboxen angezeigt (aktiviert = in iScan sichtbar)
  4. Beim Speichern wird geprüft, ob die ausgewählten Klassen-IDs noch im EDBS vorhanden sind
  5. Nicht mehr existierende Klassen werden mit einer Fehlermeldung gemeldet und nicht gespeichert

Validierung bei Auftragserstellung ​

Beim Erstellen eines neuen Auftrags (createNewJob) werden die aktiven Klassen gegen die aktuellen EDBS-Klassen validiert. Nur Klassen, die sowohl im activeClasses-Setting als auch im EDBS vorhanden sind, werden als Positionen erstellt.

Settings ​

KeyModulTypBeschreibung
current_sort_numbermanualSortingstringAktuelle Sortiernummer für Sequenz
activeClassesmanualSortingjsonAktive Sortierklassen-IDs pro Warengruppe

REST API ​

Authentifizierung via Bearer Token. Alle Endpunkte erfordern einen authentifizierten Benutzer (@).

MethodeEndpunktBeschreibung
GET/manualSorting/rest/sorting/get-job?sortNumber=Einzelnen Auftrag mit Positionen laden
GET/manualSorting/rest/sorting/list-open-jobsAlle offenen Aufträge auflisten
POST/manualSorting/rest/sorting/create-new-job?partieNr=Neuen Auftrag für Partie erstellen
PUT/manualSorting/rest/sorting/update-positionsPositionen eines Auftrags aktualisieren
POST/manualSorting/rest/sorting/complete-job?sortNumber=Auftrag abschließen

create-new-job ​

Erstellt einen neuen Auftrag basierend auf der Partienummer. Liest die Warengruppe aus dem EDBS, filtert die Sortierklassen anhand der activeClasses-Konfiguration und erstellt Positionen für alle aktiven Klassen. Gibt den Auftrag mit Positionen als SortingJobDTO zurück.

update-positions ​

Erwartet im Body ein Objekt mit id (Job-ID) und positions-Array. Jede Position muss id, sortingJobId und sortResult enthalten. Validiert, dass alle Positionen zum angegebenen Job gehören.

complete-job ​

Schließt einen Auftrag ab. Prüft vorher, ob alle Positionen ein Ergebnis haben (sortResult !== null). Gibt einen Fehler zurück, wenn Positionen ohne Ergebnis existieren.

Web-Controller ​

SortingController ​

ActionMethodeBeschreibung
actionIndexGETGridView mit allen Sortieraufträgen (mit Datumsbereichsfilter, Lieferanten-Select2, Fruchtsuche) und expandierbaren Positionen
actionExpandDetailPOST (AJAX)Positionen eines Auftrags als Teilansicht laden (für ExpandRowColumn)
actionEditGET/POSTSortierauftrag bearbeiten (Positionen, Kommentar, etc.)
actionCompletePOSTAuftrag abschließen (mit Validierung), Redirect auf Index

admin/ConfigController ​

ActionMethodeBeschreibung
actionClassesGETKonfigurationsseite für aktive Sortierklassen anzeigen
actionClassesPOSTAktive Sortierklassen für eine Warengruppe speichern (mit EDBS-Validierung)

Das Modul registriert Sidebar-Einträge in Module::initSideBar():

Hauptnavigation (für alle Benutzer mit Lizenz):

  • Gruppe "Manuelle Sortierung" (m_manualsorting, Gewicht 650)
  • Kind "Sortierergebnisse" → /manualSorting/sorting/index

Admin-Bereich (nur für admin-Rolle, unter "Modulkonfiguration"):

  • Gruppe "Manuelle Sortierung" (m_manualsorting_admin)
  • Kind "Sortierklassen" → /manualSorting/admin/config/classes

Internationalisierung ​

Übersetzungskategorie: manualsorting Basispfad: @app/modules/manualSorting/messages Konfiguriert in Module::initConfig().

Lizenzierung ​

Das Modul ist lizenzbasiert. Die Lizenz manualSorting muss in der Tabelle licenses aktiviert sein. Sidebar-Einträge und Scanner-Modul werden nur angezeigt, wenn die Lizenz aktiv ist.

ITeas iScan Applikation Dokumentation

Version: dev-develop Version: dev-develop
Commit: 242a1f0d
Deployed at: 2026-09-22T13:57:56Z