Auftragsverwaltung (Ordermanagement) V1 — Funktionsumfang & V2-Gap-Analyse¶
Stand: 2026-07-20 · Scope: Auftragsverwaltung („Ordermanagement") in calServer V1 (Yii 1.1, Kerntabelle
booking) — vollständiger Funktionsumfang inkl. Kundenrollen (Rechnungs-/Lieferkunde), Preismanagement, Sammelrechnung, Teillieferung/-rechnung und der Auftrags-Reportpipeline (Angebot → Auftrag → Lieferung → Rechnung) — verglichen mit dem aktuellen V2-Stand (Laravel 13 + Nuxt 3).Kurzfazit: Ein V1-Auftrag trägt über seinen Statusworkflow den gesamten Lebenszyklus von Angebot über Auftragsbestätigung, Lieferschein und Rechnung bis zur Fertigstellung — mit drei getrennten Kundenrollen (Hauptkunde, Lieferkunde, Rechnungskunde) samt eigener Kontakte, Preisfindung über Preisgruppen und einer Jasper-Reportpipeline, die alle vier Dokumenttypen aus demselben Auftrag erzeugt. V2 hat den Kern bereits nachgebaut (CRUD, Statusworkflow, Positionen, Sammelaufträge, Preise,
order-document-Report) — deutlich mehr, als die veraltetev1-v2-analysis.mdausweist. Es verbleiben sechs konkrete, belegbare Lücken (Abschnitt 12), u. a. das nicht ausgewertete Kunden-Sichtbarkeitsmodell, fehlende Schnellerfassungswege und ein V2-Ordertemplate, das Liefer-/Rechnungsadresse und W41xx-Felder noch nicht rendert.Dieses Dokument ergänzt die
v2-roadmap.mdund ersetzt inhaltlich den Auftrags-Abschnitt (§2.8) der veraltetenv1-v2-analysis.md.
Inhaltsverzeichnis¶
- Zweck, Scope und Methodik
- Architektur-Überblick V1
- Datenmodell
- Kundenrollen und Adresslogik
- Lebenszyklus und Statusworkflow
- Positionen (article)
- Preismanagement
- Sammelrechnung, Teillieferung und Teilrechnung
- Reports und Dokumenttypen
- Nebenfunktionen
- W41xx-Feldkatalog
- Gap-Analyse V1 → V2 und Backlog
- Anhang
1. Zweck, Scope und Methodik¶
Zweck: Referenzdokument für die (Re-)Implementierung der Auftragsverwaltung in V2. Es beantwortet zwei Fragen: Was kann V1 vollständig? und Was davon fehlt in V2 noch? Die Gap-Tabelle in Abschnitt 12 ist als direkt umsetzbarer Backlog formuliert.
Scope:
- V1-Modul Auftragsverwaltung: Tabelle
bookingmit Positionen (article), Preismanagement (prices,price_category,standard_article), Sammelrechnungen (collective_invoices), Statusworkflow (status,audit) und der Auftrags-Reportpipeline. - V2-Gegenstücke in
laravel/undfrontend-v2/sowie die Report-Templates im Schwester-Repo calServer-reports und die Produktions-Templates unterhttpdocs/reports/orders/.
Abgrenzung: Das V1-Modell FrontendArticle in diesem Kontext bezeichnet
Auftragspositionen (Tabelle article mit booking_uID-FK). Das davon
unabhängige News-/CMS-Modul („Artikel" im Sinne von Beiträgen,
FrontendArticleController teilt sich den Namen) ist kein Bestandteil des
Ordermanagements und wird hier nur zur Verwechslungsvermeidung erwähnt; sein
V2-Gap wird in der v2-roadmap.md separat geführt.
Methodik: Codeanalyse von V1 (httpdocs/protected/), V2 (laravel/,
frontend-v2/, report-runner/) und den Report-Templates (calServer-reports:
ORDER-SAMPLE, ORDER-JSON-SAMPLE, DELIVERY-JSON-SAMPLE;
Produktion: httpdocs/reports/orders/). Alle Aussagen sind mit pfad:zeile
belegt. Zeilenangaben beziehen sich auf den Stand dieses Dokuments und können
mit der Zeit driften — die Methoden-/Konstantennamen bleiben der stabile Anker.
2. Architektur-Überblick V1¶
Die Auftragsverwaltung ist im Frontend-Modul implementiert; es gibt kein eigenes Yii-Submodul. Lesepfad für Entwickler:
| Baustein | Datei | Umfang |
|---|---|---|
| Fachmodell Auftrag | httpdocs/protected/modules/frontend/models/FrontendBooking.php |
3316 Zeilen: Relationen, Kundenrollen-Auflösung, Nummernkreise, Reportgenerierung, Statuslogik |
| Basismodell (generiert) | httpdocs/protected/modules/frontend/models/base/BaseFrontendBooking.php |
Schema-Docblock, Defaults, Feldrechte |
| Controller | httpdocs/protected/modules/frontend/controllers/FrontendBookingController.php |
4499 Zeilen, ~70 Aktionen (vollständige Tabelle in Anhang A) |
| Views | httpdocs/protected/modules/frontend/views/frontendBooking/ |
Grid, Detail (view.php, 76 KB), Assign-Dialoge, Mail, Export |
| Positionen | httpdocs/protected/modules/frontend/models/FrontendArticle.php (+ Base) |
Tabelle article, drei Positionstypen |
| Preise | FrontendPrices, FrontendPriceCategory, FrontendStandardArticle (+ FrontendPriceController, FrontendArticleController) |
Preisgruppen-Matrix, Katalogartikel |
| Sammelrechnung | FrontendCollectiveInvoices |
Pivot collective_invoices |
| Status | FrontendStatus (+ base/BaseFrontendStatus.php) |
status-Zeilen mit type='booking' |
| Reports | FrontendBooking::exportMasterReport() + Adminpanel (AdminReportSetting, AdminReportVariable) |
JasperReports (JRXML) |
Der Detail-Screen (views/frontendBooking/view.php) gliedert sich in obere
Tabs (Auftragsdaten / Kunde / Rechnungsadresse / Lieferadresse / Kategorie,
view.php:147-267) und untere Tabs (Übersicht / Geräte / Artikel / Typen /
Dokumente / Historie / Aktionen / Weitere Aufträge, view.php:288-434).
3. Datenmodell¶
3.1 Beteiligte Tabellen¶
| Tabelle | Zweck | V1-Modell | V2-Stand |
|---|---|---|---|
booking |
Auftragskopf (eine Zeile = ein Auftrag über den ganzen Lebenszyklus) | FrontendBooking |
Neue Tabelle bookings mit lesbaren Spalten (laravel/database/migrations/2026_02_28_500001_create_booking_table.php) |
article |
Auftragspositionen | FrontendArticle |
V1-Schema beibehalten (laravel/app/Models/Article.php) |
prices |
Preisliste (Gerätetyp × Preisgruppe) | FrontendPrices |
V2-Migration (2026_02_28_600000_create_price_tables.php) |
price_category |
Preisgruppen | FrontendPriceCategory |
V2-Migration (ebd.) |
standard_article |
Katalogartikel | FrontendStandardArticle |
V2-Migration (2026_02_28_500006_create_standard_article_table.php) |
collective_invoices |
Sammelrechnungs-Pivot | FrontendCollectiveInvoices |
V1-Schema beibehalten (laravel/app/Models/CollectiveInvoice.php) |
status (type='booking') |
Statusdefinitionen inkl. Zähler/Automatiken | FrontendStatus |
Status::TYPE_BOOKING |
audit |
Statushistorie, Durchlaufzeiten | FrontendAudit |
Audit-Infrastruktur vorhanden (Booking nutzt Auditable) |
booking_type |
Auftragsvorlagen (vorbelegte Positionslisten) | — (Grid-Konfig m170215_102753) |
kein dediziertes V2-Gegenstück gefunden |
customers, contact |
Kundenstamm + Ansprechpartner | FrontendCustomer, FrontendContact |
Customer (V2-Tabelle), Contact (V1-Schema) |
3.2 Auftragskopf booking¶
Spalten laut Basismodell (base/BaseFrontendBooking.php:18-54) und
Install-Migration (httpdocs/protected/migrations/m130220_194523_install.php:33-49):
| Spalte | Typ | Bedeutung |
|---|---|---|
uID |
varchar(36), PK | UUID, vergeben via Uuid::create() (BaseFrontendBooking.php:85) |
customer_KTAG |
varchar(80) | Hauptkunde (Besteller) |
number |
varchar | Auftragsnummer (Pflichtfeld, BaseFrontendBooking.php:88), aus Nummernkreis (Abschnitt 5.3) |
date |
date | Auftragsdatum, Default heute (BaseFrontendBooking.php:92-94) |
customer_contact_id |
varchar(36) | Ansprechpartner Hauptkunde (m170630_094135_add_contact_field_for_customer_booking.php) |
delivery_contact_id, invoice_contact_id |
varchar(36) | Ansprechpartner Liefer-/Rechnungsempfänger (m170327_092359_add_different_customer_contact_for_booking_table.php) |
delivery_customer_KTAG, invoice_customer_KTAG |
varchar | Abweichender Liefer-/Rechnungskunde (m220328_033736_update_customer_fields_for_booking_table.php) |
status |
varchar(100) | Statustitel (referenziert status.title mit type='booking') |
comment |
text | Freitext |
delivery_costs |
double | Versandkosten auf Kopfebene (m160929_092258_add_delivery_costs_field_to_booking_table.php) |
delivery_condition |
varchar | Lieferbedingung, Default 'shipping' (BaseFrontendBooking.php:96-98) |
modified, modified_by |
int, varchar | Änderungsstempel |
W4101–W4122 |
varchar(255) | Frei konfigurierbare Zusatzfelder (Abschnitt 11); eingeführt via m150818_031621_insert_batch_column_into_booking_table.php (W4101–W4111 string, W4112–W4122 double), vereinheitlicht auf VARCHAR(255) in m180207_083600_change_W41xx_fields_to_VARCHAR_255.php |
V2-Mapping: Die neue Tabelle bookings übernimmt die Struktur mit
lesbaren Spaltennamen und UUID-PK; die drei Kontakt- und zwei
Zusatzkunden-Spalten existieren 1:1 (customer_contact_id,
delivery_contact_id, invoice_contact_id, delivery_customer_id,
invoice_customer_id, 2026_02_28_500001_create_booking_table.php:23-27),
delivery_costs als decimal(13,2) und delivery_condition ebenfalls
(:30-31). Die W41xx-Felder sind in eine JSON-Spalte custom_fields
konsolidiert (:34), angebunden über den HasDynamicFields-Trait und die
field_definitions-Registry (laravel/app/Services/FieldManagement/FieldDefinitionService.php,
TABLE_MAP mappt bookings/booking → table_name='booking').
3.3 Relationen des Auftrags¶
FrontendBooking::relations() (FrontendBooking.php:419-599):
customer(BELONGS_TOFrontendCustomerviacustomer_KTAG),deliveryCustomer/invoiceCustomer(viadelivery_customer_KTAG/invoice_customer_KTAG,:427-428)contact/delivery_contact/invoice_contact(via die drei*_contact_id,:424-426)articles(HAS_MANYFrontendArticleviabooking_uID, eager-loadinventory,:429-435);inventories(dasselbe gefiltert aufarticle_type='inventory',:436-443)statusModel(HAS_ONEFrontendStatusauftitle=status AND type='booking' AND active=1,:444-449)otherOrders(HAS_MANYFrontendCollectiveInvoicesviainvoice_uID) undotherArticles(Positionen der eingebundenen Aufträge,:451-459)categoryItems(Kategorien,:460-463),modifiedUser(:464)- Dynamische Dokument-Relationen aus
AdminFileSetting::getDocumentRelations("booking")(:471-480) und Status-Zeitstempel-Relationen aus deraudit-Tabelle für Durchlaufzeit-Auswertungen (:482-596)
Das V2-Modell laravel/app/Models/Booking.php bildet dieselben Relationen ab
(customer, customerContact, deliveryContact, invoiceContact,
deliveryCustomer, invoiceCustomer, articles, collectiveInvoices,
collectiveArticles, modifiedBy).
4. Kundenrollen und Adresslogik¶
Das ist der vom Nutzer besonders hervorgehobene Kern: Ein Auftrag kennt drei Kundenrollen mit je eigenem Ansprechpartner.
4.1 Rollen und Fallback-Präzedenz¶
| Rolle | Kunde | Kontakt | Fallback |
|---|---|---|---|
| Besteller (Hauptkunde) | customer_KTAG |
customer_contact_id |
— |
| Rechnungskunde | invoice_customer_KTAG |
invoice_contact_id |
Hauptkunde |
| Lieferkunde | delivery_customer_KTAG |
delivery_contact_id |
Hauptkunde |
getBillingCustomer()(FrontendBooking.php:1053-1093) nutztinvoice_customer_KTAGund fällt bei Leere aufcustomer_KTAGzurück; angezeigt wird der Name (K4602) samt Info-Button, der u. a. die Preisgruppe des Kunden (price_cat_uID,getGroupName()) trägt — Rechnungskunde und Preisfindung sind also gekoppelt (Abschnitt 7).getDeliveryCustomer()(:1101-1141) analog für den Lieferkunden.getActiveContactsByType()(:1149-1205) liefert die Kontaktauswahl je Rolle: fürTYPE_INVOICEdieactiveInvoiceContactsdes Rechnungskunden (sonst des Hauptkunden), fürTYPE_DELIVERYdieactiveDeliveryContactsdes Lieferkunden, sonstactiveContacts.- Grid-Pseudofelder:
fieldMap(:198-202) mapptbilling_customer→[invoice_customer_KTAG, customer_KTAG]unddelivery_customer→[delivery_customer_KTAG, customer_KTAG], sodass Suche/Sortierung im Grid die Fallback-Logik berücksichtigt. Gruppenkopf-Varianten:getBillingCustomerForGroupHeader()/getDeliveryCustomerForGroupHeader()(:653-700).
4.2 Zuweisungs- und Adressaktionen¶
actionAssignCustomer()(FrontendBookingController.php:746-803): Weiche überconnectCustomer=FrontendCustomer::MAIN_CUSTOMER(setztcustomer_KTAGund nullt alle drei Kontakte),DELIVERY_CUSTOMER(setztdelivery_customer_KTAG), sonst Rechnungskunde.actionAssignDeliveryContact()(:862) /actionAssignInvoiceContact()(:893)- Adresspflege direkt aus dem Auftrag:
actionGetCompanyAddress()(:2404),actionRefreshAddress()(:2421),actionResetAddress()(:3206),actionAddNewAddress()(:2337),actionSaveContact()(:2266),actionCloneContact()(:2305). - Kunden-Popups:
actionGetCustomerDetail()(:3249),actionGetCustomerDetailToView()(:3288). - Die Adressfelder des Kunden (
K4601–K4640) sind als externe Spalten am Auftragsmodell deklariert und gelabelt (FrontendBooking.php:24-65,136-221), damit Grid/Report sie direkt anzeigen können (K4602=Name, K4613=Vorname, K4614=Firma, K4615=Abteilung, K4619=E-Mail).
4.3 Empfängerauflösung für Mailversand¶
getTokenValues() (FrontendBooking.php:2066-2146) wählt für
Rechnungs-Statusarten bevorzugt invoice_contact/invoiceCustomer, sonst den
Hauptkunden, und erzeugt die Mail-Platzhalter [FIRSTNAME], [LASTNAME],
[FULLNAME], [EMAIL], [FIRM], [NUMBER], [STATUS] (+
Kleinschreibvarianten) für die Statusmailvorlagen (Abschnitt 10.4).
4.4 V2-Stand¶
Schema, Modellrelationen, Validierung und UI sind vorhanden: Die
Booking-Detailseite (frontend-v2/pages/booking/[id].vue) zeigt Kontaktkarten
für alle drei Rollen inkl. resetContact('delivery'|'invoice');
OrderDocumentDataBuilder löst die drei Adressrollen mit V1-identischer
Fallback-Präzedenz für Reports auf. Aber: Die Kundenauswahl selbst hängt am
Kundenstamm, dessen V1-Sichtbarkeitsmodell (zuweisungsbasiert via map_user,
group_customer, user_group, customer_filter) in V2 nicht ausgewertet
wird — jeder Nutzer mit customers_view sieht alle Kunden. Details und Belege:
CUSTOMER_HANDLING_V1_V2_REVIEW.md.
Für die Auftragsverwaltung heißt das: Liefer-/Rechnungskunden-Picker zeigen
aktuell mehr Kunden, als der Nutzer sehen dürfte (Gap G1 in Abschnitt 12).
5. Lebenszyklus und Statusworkflow¶
5.1 Statuskette¶
Ein Auftrag durchläuft den Lebenszyklus als Statuswechsel derselben Zeile —
Angebot, Auftragsbestätigung, Lieferschein und Rechnung sind keine getrennten
Entitäten. Kanonische Statusgruppen (FrontendBooking.php:91-118):
| Konstante | Werte | Dokumenttyp |
|---|---|---|
OFFER_STATUS |
Offer, Angebot | Angebot |
ORDER_STATUS |
Order, Auftrag | Auftragsbestätigung |
ORDER_IN_HOUSE_STATUS |
Order_in_house, Auftrag im Haus | interner Zwischenstatus (Geräte eingetroffen) |
DELIVERY_STATUS |
Delivery, Lieferung | Lieferschein |
BILLING_STATUS |
Billing, Invoice, Rechnung | Rechnung |
STATUS_PART |
Billing/Invoice/Rechnung + Delivery/Lieferung | Statusarten mit Teil-Logik (Abschnitt 8.2) |
Die Übersetzung der Statusnamen ist in
FrontendArticle::getTranslatedStatus() (FrontendArticle.php:524-563) bzw.
FrontendBooking::getTranslatedStatus() (:1255) hinterlegt (u. a.
Normalisierung Billing → Invoice). Ein zusätzlicher „NEW"-Status wurde mit
m170410_081147_add_NEW_status_for_booking_type.php eingeführt. Die konkreten
Statuszeilen sind konfigurierbar (Tabelle status, type='booking') —
Installationen können weitere Zwischenstatus definieren; die Konstanten decken
die dokumentrelevanten Gruppen ab.
5.2 Status als Automatisierungsträger¶
Eine Statuszeile (base/BaseFrontendStatus.php:17-40) trägt neben Titel,
Kurzzeichen, Farbe/Icon und Sortierung eine Reihe von Automatik-Flags.
Korrektur (2026-08). Eine frühere Fassung dieses Abschnitts hat diese Flags als Auftragsautomatik beschrieben. Das ist am Code widerlegt: beim Auftrags-Statuswechsel wertet V1 von ihnen kein einziges als Aktion aus.
actionChangeStatus()(FrontendBookingController.php:3697-3775) liest ausschließlichgetMandatoryFields(),getFieldsAreEmptyNow()undgetFieldsHaveDefaultValue()— alles ausadditional_field, nichts ausstatus.Die Zuordnung steht in
FrontendStatusController::actionGetStatus(:228-240), dem einzigen Endpunkt, der die Flag-Gruppe ausliefert:Dass die Flags auch an einer
type='booking'-Zeile stehen, ist ein Artefakt der übertypegeteiltenstatus-Tabelle, kein Feature.
| Flag | Gilt für | Wirkung |
|---|---|---|
counter |
Auftrag (u. a.) | Laufnummer für Nummernkreise (Abschnitt 5.3). Das einzige Flag, das im Auftragspfad wirklich zieht. |
mailer_template_id |
Auftrag, nur Oberfläche | Belegt die Mailvorlage im manuellen Versanddialog vor (FrontendBookingController.php:3062). Kein Statuswechsel-Effekt. FrontendBooking::getEmailTemplateId() (:2027) liest es ebenfalls, hat aber keinen Aufrufer. |
mailer_report |
Inventar-Status | Zeilenfilter des Fälligkeits-/Kritisch-Mailers: = 0 blendet Geräte mit diesem Inventarstatus aus dem Report aus (MailerSender.php:629,677, emailPrint.php:91-92). Tri-state — NULL verhält sich wie 1, deshalb ein Select statt einer Checkbox. |
new_order |
Inventar-Statusmaske | Blendet den Block „Create or Assign to Order" ein; bei gesetztem Schalter entsteht aus der Gerätemaske ein neuer Auftrag mit Status draft samt Positionen (FrontendInventoryController.php:2809-2878, :3076-3109). |
set_remember_date |
Inventar-Statusmaske | Legt je Gerät einen notepad-Eintrag (Wiedervorlage) an, sofern Datum, Zeit und Kommentar gefüllt sind (:2977). |
set_new_location |
Inventar-Statusmaske | Legt bzw. aktualisiert je Gerät einen location-Datensatz; fehlende Pflichtfelder rollen die Transaktion zurück (:3006, :3041-3048). |
check_new_inventory |
Inventar-Statusmaske | Beim Batch-Einlesen gescannter Seriennummern: = 1 bietet unbekannte Nummern zur Neuanlage an, = 0 verwirft sie stillschweigend (:2745). |
check_edit_inventory |
Inventar-Statusmaske | Reine Blocksichtbarkeit (apply_status.php:1413), keine Serverlogik. |
new_article |
Inventar-Statusmaske | Reine Blocksichtbarkeit (apply_status.php:1415). Das Anlegen der article-Zeilen hängt an bookings_details_edit, nicht an diesem Flag. |
new_calibration |
Inventar-Statusmaske | Reine Blocksichtbarkeit (apply_status.php:1414). In BaseFrontendStatus nicht einmal deklariert; der Zugriff funktioniert nur über das AR-Schema. |
close_metteam_calibration |
Kalibrier-Status | Schließt nach dem MSSQL-Sync den verknüpften MET/TEAM-Arbeitsauftrag (FrontendCalibrationController.php:592 u. a.). Wird im Booking-Kontext nie ausgewertet. |
active, hide |
alle | Sichtbarkeit |
5.3 Nummernkreise¶
Auftrags-/Belegnummern entstehen aus Templates mit Tokens
[STATUS_NAME]/[STATUS_SHORT]/[STATUS_COUNT] bzw.
[CATEGORY_*] (components/InventoryHelper.php:28-29,1149-1152,1978-1998):
actionCreateNewBookingNumber()(FrontendBookingController.php:1119) →getNewBookingNumberFromStatus()/getNewBookingNumberFromCategory()(FrontendBooking.php:1675-1740): löst das Template überInventoryHelper::getDefaultValue('booking','number',…)auf und inkrementiert bei Kollision denstatus.counterbzw.category.countermit Retry.- Konfliktsichere Zählervergabe:
components/CounterService.php+CounterReservation.php. - Beispiel-Template aus dem Default-Feldkatalog:
[STATUS_SHORT]-[YYYY]-[STATUS_COUNT]→AN-2026-0042(Abschnitt 11).
V2: BookingController::generateNumber +
laravel/app/Services/Booking/BookingNumberService.php decken den
Status-Nummernkreis ab.
5.4 Statuswechsel-Semantik¶
actionChangeStatus() (FrontendBookingController.php:3697-3775; Link-Variante
actionSetStatus() :1441):
- Validiert den Zielstatus und prüft
statusModel->getMandatoryFields(); fehlende Pflichtfelder öffnen ein Modal, das überactionSaveAdditionalFields()(:3904) nachträgt. - Speichert und schreibt Änderungshistorie (
saveChangesHistory(),FrontendBooking::saveHistory():2193) in dieaudit-Tabelle. - Wendet Status-Feldregeln an:
getFieldsAreEmptyNow()leert definierte Felder,getFieldsHaveDefaultValue()berechnet Defaults neu (viaInventoryHelper::getDefaultValue) — so bekommt z. B. die Rechnung beim Statuswechsel ihre eigene Belegnummer in ein W41xx-Feld (Abschnitt 11). - Implizit über
FrontendBooking::afterSave()(:743-752) →assignStatus()(components/Model.php:3400-3428): trägt das Nummern-Template ein[STATUS_COUNT]-Token, reserviertCounterReservation::reserveStatusCounter()die nächste Laufnummer. Das ist der einzige flaggesteuerte Seiteneffekt des Auftrags-Statuswechsels.
Dieselbe Semantik dupliziert der Inline-Edit im Grid (actionUpdateField(),
:1679-1734, Zweig $field == 'status') samt reload-Handling für
hasStatusInDefaultValue().
actionSetStatus() ist trotz der Bezeichnung „Link-Variante" kein
Äquivalent: keine Pflichtfeldprüfung, keine empty_now-/Default-Regeln, dafür
ein Property-basierter Mailversand
(settings/booking/notification_subject|notification_body) — nicht
flaggesteuert.
5.5 Durchlaufzeiten / Fertigstellung¶
Aus der audit-Historie baut das Modell pro Status Start-/Stopp-Zeitstempel
als dynamische Relationen (FrontendBooking.php:482-596) und aggregiert
Durchlaufzeiten (getProcessingTime() :2906) — die Grundlage für
SLA-/Fertigstellungs-Auswertungen im Grid und Dashboard
(Widget ORDER_ENTRIES_BY_STATUS, :88-89).
V2: Booking nutzt HasStatusTransitions + Auditable;
BookingController::changeStatus/saveAdditionalFields/audits bilden
den Workflow ab (Pflichtfeld-Prüfung inklusive).
6. Positionen (article)¶
Positionen sind Zeilen der Tabelle article mit FK booking_uID
(m130220_194523_install.php:11-23).
6.1 Drei Positionstypen¶
FrontendArticle (FrontendArticle.php:19-21):
article_type |
Quelle | Verknüpfung |
|---|---|---|
inventory |
Ein konkretes Gerät (FrontendInventory) |
article_ID = MTAG des Geräts |
article |
Katalogartikel (FrontendStandardArticle) |
article_ID = standard_article.uID |
type |
Gerätetyp-Leistung mit Preisliste (FrontendTypes + FrontendPrices) |
article_ID → Typ, Preis via typePrice-Relation |
Polymorphe Relationen und Namensauflösung je Typ:
FrontendArticle.php:204-212, getArticleName() :393-435.
6.2 Positionsfelder¶
base/BaseFrontendArticle.php:17-36: quantity, price (Ablage in
Cent!, Kommentar in m130220_194523_install.php:16), discount (%),
costs, delivery_costs (positionsbezogen), tax (MwSt.-Satz je Position),
unit, pos_number (auto max+1 je Auftrag, beforeSave()
FrontendArticle.php:229-241), complexity, calibration_type, comment,
delivery_date/billing_date, billing_part/delivery_part
(Teil-Zuordnung, Abschnitt 8.2) sowie eigene Zusatzfelder A4301–A4320
(BaseFrontendArticle.php:148-167). Währung, Steuer und Einheit kamen mit
m160929_031423/m160930_022717 in Feldkonfiguration und Tabelle.
6.3 Erfassungswege im UI¶
- Geräte zuordnen:
actionAssignInventoryUpdate()(FrontendBookingController.php:655), MehrfachübernahmeactionAddArticles($booking_id,$inventory_ids)(:808), Barcode-Lookup über die Inventarsuche. - Katalogartikel:
actionAssignStandardArticle()(:2183) bzw. aus dem Artikel-ModulFrontendArticleController::actionAssignStandardArticle(FrontendArticleController.php:447). - Typ-Positionen:
actionAssignType()(:2221bzw.FrontendArticleController.php:502). - Listen/Lookups:
actionListArticles()(:2051),actionListStandardArticles()(:2098),actionListTypes()(:2138).
6.4 Rückverweis am Gerät¶
calibration.C2314 = „letzte Auftragsnummer" verknüpft Gerätehistorie und
Auftrag (m170925_034912_add_last_order_number_C2314_for_inventory_grid.php;
Suche/Sortierung FrontendCalibration.php:1153-1163). Das Inventar-Grid
bietet last_order_number, last_delivery_customer, last_location_customer
(FrontendBookingController.php:661-665).
V2: Article-Modell (V1-Schema inkl. A43xx, polymorph auf
Inventory/StandardArticle) + ArticleController (CRUD) +
BookingController::assignStandardArticle sind vorhanden.
7. Preismanagement¶
7.1 Preisliste prices¶
base/BaseFrontendPrices.php:19-31: Ein Preis gilt je Gerätetyp
(type_tID) und Preisgruppe (price_cat_uID) mit price, complexity
(Aufwandsstufe), price_min/price_max, zeitlicher Gültigkeit
(start_date/end_date), costs, quantity, unit, discount, tax.
Validierungen: Preis ≥ 0, min ≤ max, start ≤ end (:73-117). Angelegt mit
m170208_040802_add_table_for_price_mamagement.php (Rollen:
m170208_071943).
7.2 Preisgruppen price_category¶
FrontendPriceCategory (uID, name, description): Kundensegmentierung —
jeder Kunde referenziert seine Preisgruppe über customers.price_cat_uID.
Die Preisfindung einer Typ-Position läuft damit: Rechnungskunde → Preisgruppe →
prices-Zeile des Gerätetyps (sichtbar im Info-Button des Rechnungskunden,
getBillingCustomer(), Abschnitt 4.1).
7.3 Katalogartikel standard_article¶
FrontendStandardArticle: article_name (unique), quantity, price,
discount, delivery_costs, tax, unit, pos_number, calibration_type,
comment — wiederverwendbare Positionen (Dienstleistungen, Pauschalen,
Versandartikel).
7.4 Pflege-UI¶
FrontendPriceController: Preislisten-Grid (actionAdmin:209), Preisgruppen (actionCategory:170+ CRUD-Aktionen), Anlegen/Ändern/ Duplizieren (actionCreate/actionUpdate/actionClone:333/:403/:444), Inline-Edit, Lookups (actionAjaxTypeName:721,actionAjaxPriceGroup:745).FrontendArticleController: Katalogartikel-CRUD (actionStandardArticle:268ff.) undactionActualize(:555): aktualisiert Preise bereits zugeordneter Positionen aus den Stammdaten (Preis-Refresh im Auftrag).- Preise für Geräte-Positionen in Aufträgen:
m241218_043547_insert_prices_for_inventory_in_orders.php; Zusatzfelder für die Preistabelle:m251002_073125_add_prices_table_for_add_field_configuration.php.Korrektur 2026-08-03: Hier standen
procedure_provision,quality_provisionundquality_provision_detail(m190221_020751,m190221_095402) als „Leistungs-/Qualitätszuschläge auf Verfahrensebene, die in die Preisfindung von Kalibrierleistungen einfließen". Das ist falsch.quality_provisionist ein Katalog von Qualitätsvorgaben, das Detail trägt Messbereich, Modus, Unsicherheit und Auflösung (range_start,range_end,uncertainty,resolution), undprocedure_provisionist eine reine n:m-Zuordnung Prozedur ↔ Vorgabe mit genau zwei Spalten (procedure_uID,provision_uID, sieheBaseFrontendProcedureProvision). Kein Betrag, kein Prozentsatz, kein Preisbezug. V1 kennt keine Preiszuschläge. Der Irrtum war nachkonzept-preisverwaltung-v2.md§6.3 weitergewandert und ist dort ebenfalls korrigiert.
7.5 V2-Stand¶
Price/PriceCategory/StandardArticle-Modelle und -Controller (CRUD,
duplicate, bulkDestroy; RBAC price_*, price_category_*, article_*)
sowie Frontend-Seiten frontend-v2/pages/price/,
pages/price-category/ und pages/standard-article/ existieren.
Lücke (Stand 2026-07-27): Katalogartikel und Preisgruppen sind inzwischen
voll pflegbar (SettingsGrid), die Preisliste selbst hat aber kein
Anlegen und kein Bearbeiten — pages/price/index.vue bietet nur
Massenlöschen, pages/price/[id].vue ist reine Leseansicht, obwohl
POST /prices, PUT /prices/{id} und POST /prices/{id}/duplicate
serverseitig existieren. Ausbauplan:
konzept-preisverwaltung-v2.md.
8. Sammelrechnung, Teillieferung und Teilrechnung¶
8.1 Sammelrechnung (collective_invoices)¶
Pivot-Tabelle (m170929_022104_add_collective_invoices_table.php) mit
invoice_uID (der Rechnungs-Auftrag) und other_booking_uID (ein
eingebundener Auftrag):
- Zuordnung:
actionAssignOrder()(FrontendBookingController.php:3305) /actionUnAssignOrder()(:3347); UI im Tab „Weitere Aufträge" (views/frontendBooking/assignOrder/,other_order/). - Positions-Vereinigung: Die Artikelsuche unioniert Positionen der
eingebundenen Aufträge in den Rechnungs-Auftrag
(
FrontendArticle.php:753-755:… OR t.booking_uID IN (SELECT other_booking_uID FROM {{collective_invoices}} WHERE invoice_uID=…)). - Helfer:
hasOtherOrder()(FrontendBooking.php:1555). - Die Rechnungsnummer ist die
booking.numberdes Rechnungs-Auftrags (bzw. ein W41xx-Belegnummernfeld, Abschnitt 11); Kopf-delivery_costsunddelivery_conditionfließen in die Summenbildung des Reports ein.
8.2 Teillieferung / Teilrechnung¶
Für Statusarten in STATUS_PART (Lieferung, Rechnung) lassen sich Positionen
in Teile aufspalten:
- Flags
billing_part/delivery_partje Position (m180330_044639_add_part_delivery_and_part_billing_for_article.php); Filterung inFrontendArticle::search()(:758-765). - Dialog-Aktionen:
actionGetArticlesForPart()(:3390),actionSaveNewPart()(:3443),actionGetParts()(:3468). - Modell-Helfer:
getMaxOrderPart(),saveNewPart(),getPartsForReport()(FrontendBooking.php:2808-2905). - Der Report erhält den Teil als Parameter
Report_part(Abschnitt 9.1) und druckt dann nur die Positionen des gewählten Teil-Lieferscheins bzw. der Teilrechnung.
8.3 V2-Stand¶
CollectiveInvoice-Modell, BookingController::collectiveOrders/assignOrder/
unassignOrder, Frontend-Tab „Sammelaufträge" sowie Teil-Reports über
BookingReportController (part=ALL|PARTIAL) sind vorhanden.
9. Reports und Dokumenttypen¶
Der Auftragsreport ist das zentrale Ausgabeinstrument: ein Template erzeugt je nach Status Angebot, Auftragsbestätigung, Lieferschein oder Rechnung.
9.1 V1-Pipeline¶
Reportdefinitionen liegen in AdminReportSetting (Adminpanel, Grid-Name
booking). Kern: FrontendBooking::exportMasterReport($part,$report)
(FrontendBooking.php:1314-1483):
- Ermittelt den JRXML-Pfad (
getMainReportFilePath, VariantenresolveVariantPath():1493,getJrxmlFilePath():1517). - Setzt die Jasper-Parameter (
:1350-1420):Reportpath,Auftragsnummer,Auftragsid(uID),Sprache(Deutsch/Englisch),Dokumenttyp(übersetzter Status),Report_part(Teil-Nr. für Teillieferung/-rechnung),Articletype1..3(Filter der Positionstypen). - Wählt die statusabhängige Beschreibungsvariable
(
AdminReportVariable::getVariableContent(),:1381-1393): - Offer/Angebot →
booking_offer_report_description(Angebot) - Order/Auftrag →
booking_order_report_description(Auftragsbestätigung) - Billing/Rechnung →
booking_billing_report_description(Rechnung) - Delivery/Lieferung + Order_in_house →
booking_delivery_report_description(Lieferschein) - Merged alle Reportvariablen, rendert via Jasper und liefert die Datei.
Aufrufwege im Controller: actionViewMasterReport() (:2708),
actionPrintOrderReport() (:2859), actionDetailsPrint() (:1886),
actionDeliveryFormPrint() (:1907), Listen-Druck (actionListPrint()
:1964), Signatur (actionSign() :3611), DMS-Ablage (actionSaveToDms()
:2958), Versand (actionSendReport() :3039, Abschnitt 10.4).
REPORT_PARAMETERS (FrontendBooking.php:130-134) mappt
Order_View.jrxml → [P_OrderID].
9.2 Templates¶
- Produktion (
httpdocs/reports/orders/):Angebot_V0.8,Angebot_V0.8_Billing,Angebot_V0.8_Billing_Group,Angebot_V0.8_Delivery,Order_View— jeweils mitStatistics/Statistics_Billing-Subreports. Das ist die maßgebliche Referenz für Layout, Adressrollen-Verwendung und W41xx-Einsatz. - Community/V1 (calServer-reports,
ORDER-SAMPLE/): genericisierte Kopie — ein Template für alle vier Dokumenttypen, geschaltet über$P{Dokumenttyp}; eingebettetes SQL jointbooking,article,collective_invoices,customersdreifach (Haupt-/Rechnungs-/Lieferkunde),contactdreifach,standard_article,prices,types,inventory. SubreportStatistics.jrxml: Netto/Steuergruppen/Rabatt/Brutto, Gesamtrabatt aus W4114. - Community/V2 (calServer-reports,
ORDER-JSON-SAMPLE/,DELIVERY-JSON-SAMPLE/): SQL-frei, JSON-Datasource, gerendert vomreport-runner(Java/JasperReports,report-runner/…/JsonDataSources.java). - Abgrenzung:
DELIVERY-STANDALONE(calServer-reports) ist eine ältere, inventarbasierte Übergabeliste (Free_Delivery.jrxml) außerhalb des Auftragsflusses; V1 nutzt sie für den Schnellauftrag (Abschnitt 10.1).
9.3 V2-Datenvertrag order-document v1.0¶
Serverseitig baut laravel/app/Services/Report/OrderDocumentDataBuilder.php
(Contract-Konstante order-document, :38) den Datensatz; abrufbar auch als
GET /api/v2/bookings/{id}/report-dataset
(BookingController::reportDataset). Struktur (Beleg:
ORDER-JSON-SAMPLE/main_reports/sample-data.json):
meta { contract, schema_version, generated_at, locale }
document { number, date, status, comment, delivery_condition,
delivery_costs, description, custom_fields{ W41xx… } }
customer { name, customer_number, street, zip, city, country, contact{…} }
delivery { … eigene Lieferadresse, optional contact } ← Fallback: customer
invoice { … eigene Rechnungsadresse } ← Fallback: customer
positions[] { pos_number, name, article_type, quantity, unit,
price, discount, tax, line_net }
statistics { tax_groups[{rate, net, vat}], net_total,
order_discount_percent, discount_amount,
net_after_discount, vat_total, gross_total }
Die Steuergruppen-Aggregation und Summenbildung geschieht serverseitig
(Jasper kann JSON-Arrays nicht gruppieren); der Gesamtrabatt kommt aus dem
dynamischen Feld W4114 (OrderDocumentDataBuilder.php:44-45,263-265).
Bekannte Lücke (Gap G5): Das aktuelle V2-Template
ORDER-JSON-SAMPLE/main_reports/order-json-sample.jrxml bindet nur
document.*, customer.* und statistics.* — die im Contract vorhandenen
Blöcke delivery, invoice, document.delivery_condition/delivery_costs
und custom_fields werden nicht gerendert. Das V1-Template
(ORDER-SAMPLE bzw. Angebot_V0.8_Billing/_Delivery) druckt genau diese
Rollen — hier fehlt V2 also sichtbare Funktion, obwohl die Daten fließen.
DELIVERY-JSON-SAMPLE nutzt denselben Contract als schlanke Variante
(nur delivery-Rolle + Positionen ohne Preise) und belegt die
Adressrollen-Trennung mit abweichender Lieferanschrift.
Es existiert kein JSON-Schema für den Payload — der Contract ist nur über
READMEs, sample-data.json und die JSONPath-Bindings der JRXMLs dokumentiert
(calServer-reports schema/report-parameters.schema.json beschreibt nur die
Parameter-Manifeste).
10. Nebenfunktionen¶
10.1 Alternative Erfassungswege¶
Neben dem Standardformular (actionCreate() :952, createBooking()
:1077) bietet V1 drei Schnellwege:
| Weg | Aktion | Verhalten |
|---|---|---|
| Aus Notizzettel | actionCreateFromNotepad() (:1225) |
Erzeugt einen Auftrag aus einer Notepad-Geräteauswahl |
| Mit Geräten | actionCreateWithInventories() (:1299) |
Auftrag anlegen und Geräte in einem Schritt als Positionen übernehmen |
| Schnellauftrag | actionCreateFastOrder() (:3784) |
Create-or-Update inkl. sofortigem Free_Delivery.jrxml-Report (Ordner individual_delivery, :3814-3818) und DMS-Ablage (Yii::app()->dms->add(…,'booking',…), :3839); eigenes Recht fast_add_order |
Dazu Auftragsvorlagen (booking_type): vordefinierte Positionslisten mit
Preisgruppen-Anbindung (m171024_064355), Views booking_type/,
templateArticle/.
10.2 DMS-Integration¶
Generierte Belege werden dem Auftrag als Dokumente zugeordnet
(actionSaveToDms() :2958, Dokument-Tab, dynamische Relationen
FrontendBooking.php:471-480); der Schnellauftrag legt seinen Lieferschein
automatisch ab.
10.3 Digitale Signatur¶
actionSign() (:3611) signiert Auftragsreports;
getSignature()/hasSignature() (FrontendBooking.php:3011-3061);
Migrations m181212_020223, m190418_035341. V2:
BookingController::sign + ReportSignatureService + Freigabe-Workflow
(BookingReportController::release).
10.4 E-Mail-Versand und Mail-Logs¶
actionSendReport() (:3039-3201): komponiert eine AdminMailerMessage
(link_table=BOOKING), zieht die Mailvorlage aus
statusModel->mailer_template_id, hängt den generierten Report an, ersetzt
die Platzhalter aus getTokenValues() (Abschnitt 4.3), versendet, legt den
Anhang optional ins DMS und protokolliert im Aktionen-Tab
(actionListMailLogs() :3492 ff.). V2: BookingReportController::send +
BookingController::mailLogs.
Korrektur (2026-08). Hier stand „Statusgesteuerte Auto-Mails über
status.mailer_report". Das ist falsch:mailer_reportkommt im gesamten Booking-Pfad nicht vor, es filtert Gerätezeilen im Fälligkeitsmailer (Abschnitt 5.2). Statusgesteuerte Auto-Mails für Aufträge gibt es in V1 nicht. Der Versand ist immer manuell;status.mailer_template_idbelegt im Dialog nur die Vorlage vor.
10.5 Export / Import¶
CSV/XLS/PDF-Export mit Spaltenauswahl (actionExport() :4072,
getDataForExport() :4090, actionUpdateExportColumns() :4028;
Spalten-Setup m220607_035616_add_fields_for_export_xls_and_pdf.php). Import
über das generische TableImport-Framework (FrontendTableImportSetting/
FrontendTableImportTemplate). V2: BookingController::export.
10.6 Grid, Filter, Statistik, Barcode¶
Haupt-Grid booking-grid (FrontendBooking::GRID_VIEW_ID :74): Spalten aus
FrontendProperty::getGridViewColumns('booking')
(views/frontendBooking/_columns.php:6), Spaltendialog EColumnsDialog
(_columns.php:75-102), gespeicherte Sichten (FrontendTableViews),
Standard-Sortierung (FrontendGridSortDefault), erweiterte Filter
(FrontendAdvancedFilter, getBookingForAdvancedFilter()
FrontendBooking.php:3212), Dashboard-Widget „Aufträge nach Status"
(ORDER_ENTRIES_BY_STATUS, :88-89, getListBookingOfStatistics()
:3096). Barcode-Suche kommt aus dem Inventarmodul und wird bei der
Gerätezuordnung genutzt.
10.7 Rechte und Konfiguration¶
Rollen im accessRules() (FrontendBookingController.php:53-199):
| Recht | Deckt ab |
|---|---|
bookings_view |
Grid, Detail, Reports ansehen, Signieren, DMS, Mailversand, Sammelauftrag-Zuordnung (:111-144) |
bookings_edit |
Anlegen/Ändern, Feld-Inline-Edit, Zuweisungen, Statuswechsel (:66-90) |
bookings_delete |
Löschen/Massenlöschen (:145-153) |
bookings_details_view |
Positions-Zuordnung Geräte/Katalogartikel/Typen (:176-184) |
booking_actions_view |
Mail-Logs (:185-194) |
fast_add_order |
Schnellauftrag (:91-110) |
individual_delivery_report |
Freie Lieferschein-Zuordnung (:91-100) |
status_reader |
Report-Druck/Listenzugriff für Leserollen (:166-175) |
Positionsrechte hängen zusätzlich am Typ (inventory_view, article_edit,
types_view; FrontendArticle.php:591-616); Feld-Sichtbarkeit/-Pflicht je
Rolle über AdminUserRolesField::getLimitColumnNames()
(base/BaseFrontendBooking.php:109-123). Konfigurationsschalter u. a.:
booking_grid_editable (Seed m150818_035821…:11), complexity_default
(:810 im Controller), Auftrags-Kategorien (m220323_071240),
Tab-Konfiguration (m170228_072726), Report-Kopfreihenfolge
(m160901_022650). V2: RBAC-Operationen bookings_*, article_*,
price_*, price_category_* sind registriert.
11. W41xx-Feldkatalog¶
11.1 Mechanik: konfigurierbar, nicht semantisch fixiert¶
W4101–W4122 sind frei konfigurierbare Zusatzfelder des Auftragskopfs.
Labels, Feldtypen, Sichtbarkeit und Default-Werte kommen aus der Tabelle
field_configuration (Seed je Spalte:
m150818_035821_booking_column_configuration_field.php); Pflicht/Sichtbarkeit
je Rolle aus AdminUserRolesField. Die Sprachdateien liefern nur
Durchreich-Defaults — einzige Ausnahme: W4101 = „Posten-Nr"
(httpdocs/protected/messages/de/booking.php:27). Die Bedeutung eines
W41xx-Felds ist damit installationsspezifisch.
11.2 Belegte Bedeutungen aus zwei Quellen¶
Zwei Referenz-Konfigurationen im Repo-Bestand widersprechen sich teilweise — ein Beleg dafür, dass Installationen die Felder unterschiedlich belegen:
| Feld | Default-Feldkatalog (laravel/database/sql/field_configuration.sql, Grid booking) |
Annahme im Community-Template ORDER-SAMPLE (Report-SQL) |
Bewertung |
|---|---|---|---|
| W4101 | Freifeld (DE-Label „Posten-Nr") | Wird im Kopf-Metablock gedruckt, Label unbelegt | unklar, nicht raten |
| W4102 | StatusCounter „AN" (Angebotsnummer, Template [STATUS_SHORT]-[YYYY]-[STATUS_COUNT]) |
selektiert, aber nicht erkennbar gerendert | Widerspruch |
| W4103 | StatusCounter „AU" (Auftragsnummer) | Angebots-Gültigkeit in Tagen (DATE_ADD(CURDATE(), INTERVAL W4103 DAY) → „Angebot gültig bis") |
Widerspruch |
| W4104 | StatusCounter „LI" (Lieferscheinnummer) | Kundenreferenz/Bestellnummer („Ihre Referenz"/„Ihre Bestellnummer") | Widerspruch |
| W4105 | StatusCounter „RE" (Rechnungsnummer) | Bestelldatum des Kunden („Ihr Bestelldatum") | Widerspruch |
| W4106 | Freifeld | Angebotsrevision (Suffix an Angebotsnummer) | nur Template-Beleg |
| W4108 | Freifeld | Rechnungsnummer ("Rechnung " + W4108, Fallback Auftragsnummer) |
nur Template-Beleg |
| W4109 | Freifeld | Liefer-/Leistungsdatum | nur Template-Beleg |
| W4114 | Freifeld | Gesamtrabatt in % (treibt Statistics.jrxml; V2 liest ihn identisch: OrderDocumentDataBuilder.php:44-45) |
konsistent belegt |
| W4107, W4110–W4113, W4115–W4122 | Freifelder | in keinem Report verwendet | unbelegt |
Beide Quellen sind „echt": Der Feldkatalog beschreibt eine
Auslieferungskonfiguration mit Belegnummern in W4102–W4105; das
Community-Template setzt eine gelebte Kundenkonfiguration mit
Referenz-/Datumsfeldern voraus. Zusätzlich pflegt der Katalog eigene
Konfigurationszeilen für die Booking-Untergrids customer_booking,
inventory_booking, other_booking, assign_other_booking
(FrontendBooking.php Konstanten TABLES :124-130).
11.3 Konsequenzen für V2¶
- Nichts hartkodieren. V2 konsolidiert W41xx korrekt in
bookings.custom_fields(JSON) überHasDynamicFields+field_definitions-Registry — die Bedeutung muss aus der Felddefinition kommen, nie aus Code oder Template. - Seed fehlt (Gap G4):
laravel/database/data/default_field_definitions.jsonenthält praktisch keine Booking-W41xx-Definitionen; ohne V1-Sync startet eine frische V2-Installation ohne benannte Auftrags-Zusatzfelder. - Template-Rendering generisch machen (Teil von Gap G5): Das
V2-Ordertemplate sollte
custom_fieldsals Label/Wert-Paare rendern (Labels aus der Felddefinition in den Payload aufnehmen), statt einzelne W-Felder zu verdrahten. - Doku-Hinweis für Template-Autoren: Community-Templates wie
ORDER-SAMPLEsetzen eine bestimmte W41xx-Belegung voraus und müssen bei abweichender Installation angepasst werden.
12. Gap-Analyse V1 → V2 und Backlog¶
12.1 Was V2 bereits abdeckt¶
Zur Einordnung (Belege: laravel/app/Http/Controllers/Api/V2/BookingController.php,
BookingReportController.php, frontend-v2/pages/booking/,
v2-roadmap.md §1): CRUD inkl. Duplizieren/Stornieren/
Massenlöschen/Export, Nummernkreis, Statusworkflow mit Pflichtfeldern,
drei Kundenrollen + Kontakte im Schema/Modell/UI, Positionen (article inkl.
A43xx), Katalogartikel-API, Preislisten + Preisgruppen (API + Preise-Seite),
Sammelaufträge, Mail-Logs, Signatur/Freigabe, DMS-Ablage, Auftrags-Reports
über den order-document-Contract inkl. Teil-Reports. Die Detailtabelle über
alle ~70 V1-Aktionen steht in Anhang A.
12.2 Lücken¶
| # | Funktion | V1-Verhalten (Beleg) | V2-Stand (Beleg) | Gap | Empfehlung | Prio |
|---|---|---|---|---|---|---|
| G1 | Kunden-Sichtbarkeit in Auftrags-Pickern | Zuweisungsbasierte Sichtbarkeit via map_user/group_customer/customer_filter (InventoryHelper::isAllCustomers) |
Tabellen migriert, aber kein Lesepfad wertet sie aus — alle Kunden sichtbar (CUSTOMER_HANDLING_V1_V2_REVIEW.md) |
Funktions- und Datenschutz-Regression; betrifft Haupt-, Liefer- und Rechnungskunden-Auswahl im Auftrag | Sichtbarkeitsmodell zentral im CustomerController-Query-Pfad verdrahten; Auftrags-Picker erben es automatisch |
Hoch |
| G2 | Schnellerfassung | actionCreateFastOrder (FrontendBookingController.php:3784, inkl. Sofort-Lieferschein + DMS), actionCreateFromNotepad (:1225), actionCreateWithInventories (:1299) |
Nur Basis-store im BookingController |
Drei produktive Erfassungswege fehlen komplett | Zuerst createWithInventories (Auftrag + Geräte in einem Call), dann FastOrder (mit Report+DMS), Notepad-Weg nach Notepad-V2-Stand priorisieren |
Mittel–Hoch |
| G3 | Stammdaten-UI Preise | Preislisten-Grid mit Anlegen/Ändern/Duplizieren/Inline-Edit (FrontendPriceController.php:333/403/444/660) |
pages/price-category/ und pages/standard-article/ sind inzwischen voll-CRUD (SettingsGrid); pages/price/ bleibt lesend + löschend, obwohl POST/PUT /prices und duplicate serverseitig existieren |
Preise sind über die Oberfläche weder anlegbar noch änderbar | Anlegen/Bearbeiten/Duplizieren nach CrudModal-Muster nachziehen, Preisgruppe zum Einstieg der Preisbearbeitung machen (Matrix, Gruppe duplizieren) — Plan: konzept-preisverwaltung-v2.md |
Hoch |
| G4 | W41xx-Felddefinitionen | Seed je Spalte via m150818_035821…; Bedeutungen installationsspezifisch (Abschnitt 11) |
custom_fields-Mechanik fertig, aber default_field_definitions.json ohne Booking-W41xx-Einträge |
Frische V2-Installation hat keine benannten Auftrags-Zusatzfelder | Default-Felddefinitionen für booking seeden (Basis: laravel/database/sql/field_configuration.sql), Belegnummern-Felder als StatusCounter-Äquivalent kennzeichnen |
Mittel |
| G5 | Order-Template-Vollständigkeit | Produktions-Templates drucken Rechnungs-/Lieferadresse, Lieferbedingung/-kosten und W-Felder (httpdocs/reports/orders/Angebot_V0.8_Billing/_Delivery; ORDER-SAMPLE) |
Contract order-document liefert alles, aber ORDER-JSON-SAMPLE-Template bindet nur customer + Summen (Abschnitt 9.3) |
Gedruckte Belege ohne abweichende Liefer-/Rechnungsadresse, Lieferkondition und Zusatzfelder | V2-Template erweitern: invoice-Block auf Rechnungen, delivery-Block auf Lieferscheinen, delivery_condition/delivery_costs in der Summenbox, generischer custom_fields-Abschnitt; zusätzlich JSON-Schema für den Contract publizieren |
Hoch |
| G6 | Abgrenzung News/Artikel-CMS | FrontendArticleController mischt Katalogartikel und News-CMS |
Booking-Positionen und Katalogartikel vorhanden; News-CMS fehlt (separates Thema, v2-roadmap.md) |
Kein Ordermanagement-Gap — nur Namensverwechslung vermeiden | In V2-Doku/Code konsequent „StandardArticle/Katalogartikel" vs. „News" trennen | Info |
12.3 Backlog-Vorschlag (priorisiert)¶
- G5a — Order-Template:
ORDER-JSON-SAMPLEuminvoice/delivery-Blöcke, Lieferkondition/-kosten und generischescustom_fields-Rendering erweitern (reine Template-Arbeit, Daten fließen bereits; Wirkung sofort sichtbar). - G1 — Kunden-Sichtbarkeit: Umsetzung gemäß Empfehlung in
CUSTOMER_HANDLING_V1_V2_REVIEW.md; danach automatisch wirksam in allen Auftrags-Pickern. - G4 — W41xx-Seed: Booking-Felddefinitionen in
default_field_definitions.jsonaufnehmen; Label-Quelle in denorder-document-Payload aufnehmen (für G5a). - G2 —
createWithInventories+ FastOrder: alsBookingController- Endpunkte mit Frontend-Einstieg (Inventar-Grid-Massenaktion „Auftrag erstellen"); Notepad-Variante nachziehen, sobald Notepad-V2 steht. - G3 — Preisliste bearbeitbar machen: Anlegen/Bearbeiten/Duplizieren in
pages/price/(Katalogartikel- und Preisgruppen-Seiten sind erledigt); Ausbau gemäßkonzept-preisverwaltung-v2.md. - G5b — Contract-Schema: JSON-Schema für
order-documentv1.0 in calServer-reportsschema/publizieren (Absicherung für Template-Autoren und denreport-runner).
13. Anhang¶
Anhang A — Referenz: Controller-Aktionen FrontendBookingController¶
Zeilenangaben: httpdocs/protected/modules/frontend/controllers/FrontendBookingController.php.
V2-Spalte: ✔ vorhanden · ◐ teilweise/indirekt · ✖ fehlt (Stand 2026-07-20).
| Aktion | Zeile | Zweck | Recht | V2 |
|---|---|---|---|---|
| actionAdmin | 292 | Haupt-Grid | bookings_view | ✔ index |
| actionView | 521 | Detailseite | bookings_view | ✔ show |
| actionViewDetail | 3268 | Detail-Popup | bookings_view | ◐ über show |
| actionAutoComplete | 460 | Nummern-Suche | bookings_view | ◐ Grid-Suche |
| actionAjaxField | 576 | Feld-Lookup | bookings_view | ◐ |
| actionAjaxCustomerGrid | 1779 | Kunden-Lookup-Grid | bookings_view | ◐ Customer-API |
| actionLoadColumns | 4465 | Grid-Spalten laden | bookings_view | ✔ Grid-Infra |
| actionCreate | 952 | Auftrag anlegen | bookings_edit | ✔ store |
| actionUpdate | 1479 | Auftrag ändern | bookings_edit | ✔ update |
| actionUpdateField | 1562 | Inline-Feld-Edit | bookings_edit | ◐ update |
| actionDelete | 1805 | Löschen | bookings_delete | ✔ destroy |
| actionMultiDelete | 1825 | Massenlöschen | bookings_delete | ✔ bulkDestroy |
| actionCancel | 926 | Stornieren | bookings_edit | ✔ cancel |
| actionCreateNewBookingNumber | 1119 | Nummer aus Nummernkreis | bookings_edit | ✔ generateNumber |
| actionGetDefaultValuesFromStatus | 1144 | Status-Defaults | bookings_edit | ◐ |
| actionGetDefaultValuesFromCategory | 1186 | Kategorie-Defaults | bookings_edit | ◐ |
| actionCreateFromNotepad | 1225 | Auftrag aus Notizzettel | bookings_edit | ✖ |
| actionCreateWithInventories | 1299 | Auftrag + Geräte in einem Schritt | bookings_edit | ✖ |
| actionCreateFastOrder | 3784 | Schnellauftrag + Sofort-Lieferschein | fast_add_order | ✖ |
| actionSetStatus | 1441 | Statuswechsel (Link) | bookings_edit | ✔ changeStatus |
| actionChangeStatus | 3697 | Statuswechsel (AJAX, Pflichtfelder) | bookings_edit | ✔ changeStatus |
| actionSaveAdditionalFields | 3904 | Pflichtfelder nachtragen | bookings_edit | ✔ saveAdditionalFields |
| actionAssignCustomer | 746 | Kunde zuordnen (Haupt/Liefer/Rechnung) | bookings_edit | ✔ store/update |
| actionAssignDeliveryContact | 862 | Lieferkontakt | bookings_edit | ✔ update |
| actionAssignInvoiceContact | 893 | Rechnungskontakt | bookings_edit | ✔ update |
| actionGetCompanyAddress | 2404 | Firmenadresse holen | bookings_edit | ◐ Customer-API |
| actionRefreshAddress | 2421 | Adresse aktualisieren | bookings_edit | ◐ |
| actionResetAddress | 3206 | Adresse zurücksetzen | bookings_edit | ✔ resetContact (UI) |
| actionAddNewAddress | 2337 | Neue Adresse anlegen | bookings_edit | ◐ Contact-API |
| actionSaveContact | 2266 | Kontakt speichern | bookings_edit | ◐ Contact-API |
| actionCloneContact | 2305 | Kontakt duplizieren | bookings_edit | ✖ |
| actionGetCustomerDetail | 3249 | Kunden-Popup | bookings_view | ◐ |
| actionGetCustomerDetailToView | 3288 | Kunden-Popup (Detail) | bookings_view | ◐ |
| actionAssignInventoryUpdate | 655 | Geräte-Zuordnungs-Grid | bookings_details_view | ◐ ArticleController::store |
| actionAddArticles | 808 | Geräte als Positionen übernehmen | bookings_details_view | ◐ |
| actionAssignStandardArticle | 2183 | Katalogartikel zuordnen | bookings_details_view | ✔ assignStandardArticle |
| actionAssignType | 2221 | Typ-Position zuordnen | bookings_details_view | ◐ |
| actionListAllArticles | 482 | Positionsliste (alle) | bookings_view | ✔ Articles-API |
| actionListArticles | 2051 | Positionsliste | bookings_view | ✔ Articles-API |
| actionListStandardArticles | 2098 | Katalogartikel-Liste | bookings_view | ✔ StandardArticle-API |
| actionListTypes | 2138 | Typenliste | bookings_view | ✔ Types-API |
| actionGetListArticles | 2475 | Positionsliste (Reader) | status_reader | ◐ |
| actionGetOrderDetails | 2575 | Auftragsdetails (FastOrder) | fast_add_order | ✖ |
| actionGetArticlesForPart | 3390 | Positionen je Teil | bookings_edit | ◐ Teil-Reports |
| actionSaveNewPart | 3443 | Neuen Teil speichern | bookings_edit | ◐ |
| actionGetParts | 3468 | Teile auflisten | bookings_view | ◐ |
| actionAssignOrder | 3305 | Auftrag in Sammelrechnung einbinden | bookings_view | ✔ assignOrder |
| actionUnAssignOrder | 3347 | Einbindung lösen | bookings_view | ✔ unassignOrder |
| actionDetailsPrint | 1886 | Detail-Druck | bookings_view | ✔ Report-API |
| actionDeliveryFormPrint | 1907 | Lieferschein-Druck | bookings_view | ✔ Report-API |
| actionListBooking / actionListPrint | 1930 / 1964 | Listen-Druck | bookings_view | ◐ Export |
| actionGetDetailPrint | 2033 | Druckpfad Detail | bookings_view | ✔ Report-API |
| actionViewDetailReport | 2653 | Detail-Report anzeigen | bookings_view | ✔ preview |
| actionViewMasterReport | 2708 | Master-Report (Beleg) anzeigen | bookings_view | ✔ preview/generate |
| actionPrintOrderReport | 2859 | Beleg drucken | status_reader | ✔ generate |
| actionGetReportLabelPath / actionGetReportPrintPath | 2777 / 2817 | Label-/Druckpfade | bookings_view | ◐ useReports |
| actionViewFile / actionDownloadFile | 2923 / 2620 | Reportdatei anzeigen/laden | bookings_view | ✔ Documents-API |
| actionSaveToDms | 2958 | Beleg ins DMS | bookings_view | ✔ saveToDms |
| actionSign | 3611 | Beleg signieren | bookings_view | ✔ sign + release |
| actionSendReport | 3039 | Beleg per Mail versenden | bookings_view | ✔ send |
| actionNotification | 2006 | Benachrichtigung | bookings_view | ◐ |
| actionListMailLogs | 3492 | Mail-Log-Liste | booking_actions_view | ✔ mailLogs |
| actionViewMailLog | 3527 | Mail-Log ansehen | booking_actions_view | ✔ mailLogs |
| actionDeleteMailLog / actionMultiDeleteMailLog | 3548 / 3571 | Mail-Logs löschen | booking_actions_view | ◐ |
| actionExport | 4072 | CSV/XLS/PDF-Export | bookings_view | ✔ export |
| actionUpdateExportColumns | 4028 | Export-Spaltenauswahl | bookings_view | ◐ |
Anhang B — Quellenverzeichnis¶
V1 (calserver-yii, httpdocs/protected/):
modules/frontend/models/FrontendBooking.php,
modules/frontend/models/base/BaseFrontendBooking.php,
modules/frontend/models/FrontendArticle.php (+ Base),
modules/frontend/models/FrontendPrices.php, FrontendPriceCategory.php,
FrontendStandardArticle.php, FrontendCollectiveInvoices.php,
FrontendStatus.php (+ base/BaseFrontendStatus.php),
modules/frontend/controllers/FrontendBookingController.php,
FrontendPriceController.php, FrontendArticleController.php,
modules/frontend/views/frontendBooking/, components/InventoryHelper.php,
components/CounterService.php, messages/de/booking.php, Migrations
(m130220_194523_install.php, m150818_031621, m150818_035821,
m160929_092258, m170208_040802, m170327_092359, m170929_022104,
m180330_044639, m220328_033736 u. a.), Produktions-Templates
httpdocs/reports/orders/.
V2 (calserver-yii):
laravel/app/Http/Controllers/Api/V2/BookingController.php,
BookingReportController.php, ArticleController.php,
StandardArticleController.php, PriceController.php,
PriceCategoryController.php, laravel/app/Models/Booking.php,
Article.php, CollectiveInvoice.php,
laravel/app/Services/Report/OrderDocumentDataBuilder.php,
laravel/app/Services/Booking/BookingNumberService.php,
laravel/app/Models/Concerns/HasDynamicFields.php,
laravel/app/Services/FieldManagement/FieldDefinitionService.php,
laravel/database/migrations/2026_02_28_500001_create_booking_table.php,
laravel/database/sql/field_configuration.sql,
laravel/database/data/default_field_definitions.json,
frontend-v2/pages/booking/, frontend-v2/composables/useReports.ts,
report-runner/.
Report-Templates (calserver-reports):
ORDER-SAMPLE/ (+ subreports/Statistics.jrxml), ORDER-JSON-SAMPLE/
(+ main_reports/sample-data.json, parameters.json),
DELIVERY-JSON-SAMPLE/, DELIVERY-STANDALONE/,
schema/report-parameters.schema.json.
Verwandte Dokumente: v2-roadmap.md (aktueller
V2-Stand), CUSTOMER_HANDLING_V1_V2_REVIEW.md
(Sichtbarkeitsmodell), v1-v2-analysis.md (veraltete
Gesamt-Gap-Analyse, durch dieses Dokument für den Auftrags-Teil ersetzt),
evaluierung-jasper-reports-v2.md,
konzept-report-parameter-katalog.md.