Commit Graph
8 Commits
Author SHA1 Message Date
David Malinowski 384378b605 chore(msp): Dev-/Test-Helfer für Supplier-Import (nur Entwicklungs-Hilfsmittel)
Nicht-produktive Helper-Module im importers/-Paket, mit Unterstrich-Präfix
markiert. Werden von keiner Produktiv-Codebasis aufgerufen, sondern nur
manuell über `bench execute`:

- _smoke_test: parst eine CSV und gibt Verteilungsstatistiken aus
  (distinct customers/products, enums).
- _runner: Convenience-Wrapper, um einen bestehenden Import-Run per
  Namen zu starten.
- _inspect: liefert kompakte JSON-Übersicht über einen Import-Run
  (Status, Statistik, erste Zeilen) zur Fehlersuche.
- _batchtest: importiert mehrere CSVs chronologisch und summiert
  Subscription-/Event-Zahlen.
- _cleanup: löscht alles, was vom neuen Importer erzeugt wurde. Nur für
  Dev-/Test-Instanzen gedacht; prüft vorab auf test-DB oder
  developer_mode.
2026-04-14 12:41:48 +02:00
David Malinowski 687a1faac0 feat(msp): Parser-Framework + DocumentBuilder + Run-Orchestrator
Implementiert das eigentliche Import-Framework im Paket msp.importers/:

- base.py: abstrakte BaseSupplierParser-Klasse + CanonicalRow-Dataclass
  (lieferantenneutrale Repräsentation einer Rechnungsposition) sowie
  Helfer für deutsche Dezimal-/Datums-Parser und Enum-Normalisierung
  (Monthly/Annual/Triennial, P1M/P1Y/P3Y, New/Renewal/Billing/Upgrade/
  Cancel).
- registry.py: Parser-Registry, über parser_key aufgelöst. Neue
  Lieferanten bringen einen eigenen Parser mit und registrieren sich
  per @register-Dekorator.
- adn_monthly_csv.py: Parser für ADNs monatliche Rechnungs-CSV.
  Extrahiert alle relevanten Felder strukturiert, inklusive
  SUBSCRIPTION_ID_EXTERNAL, BILLINGPLAN, VERTRAGSDAUER, WARTUNGSBEGINN/
  -ENDE und BUCHUNGSTYP — Daten, die der alte adnconnect-Importer
  verworfen oder nur in HTML-Descriptions vergraben hatte.
- resolution.py: Lookups für Customer + Item und die Output-Mode-
  Selektion (Run-Override → Customer.billing_mode → Profil-Default).
- subscriptions.py: Upsert-Logik für Supply Subscription + Event,
  inklusive Deduplizierung per (subscription_external_id, period).
- builder.py: DocumentBuilder, der sowohl Sales Invoices als auch
  Delivery Notes aus kanonischen Zeilen erzeugt. Rechnungspreise werden
  per unit_price × qty gesetzt (mit Rabatt in description) — korrekt
  gemäß ADN-POSITIONSPREIS statt adnconnects fehlerhafter Listenpreis/
  discount_percentage-Kombination.
- run_orchestrator.py: verdrahtet das Ganze und wird aus dem
  Supplier-Import-Run-Controller über die Whitelisted-Methode do_import
  aufgerufen.
2026-04-14 12:41:37 +02:00
David Malinowski b399b6f37d feat(msp): Supply Subscription data model + Supplier Import scaffolding
Führt ein lieferantenagnostisches Lizenzmodell ein, das den Weg für den
künftigen Ersatz der adnconnect-App ebnet:

- Supply Subscription: Golden Record pro Subscription-Lifecycle, unique
  über die externe Vendor-Subscription-ID (z. B. Microsoft Subscription-ID).
  Denormalisierte Felder current_period_end, qty_current, last_event_date
  werden aus den Events gepflegt.
- Supply Subscription Event: Eine Episode pro Abrechnungszeitraum, mit
  Rück-Links auf Sales Invoice, Delivery Note, Purchase Invoice und
  Supplier Import Line.
- Supplier Import Profile / Run / Line: Modulares Import-Framework, in dem
  pro Lieferant (ADN, künftig ALSO/Ingram/…) ein Profil mit parser_key +
  Defaults konfigurierbar ist. Ein Run bündelt einen konkreten Import
  inklusive Kanonik-Zeilen und Statistiken.
- Custom Field „supply_subscription" auf Sales Invoice Item und Delivery
  Note Item — das ist das einzige Standard-ERPNext-Feld, das unabhängig
  vom Lieferanten hinzukommt. Alle weiteren Attribute werden über den
  Link erreichbar.

Die Importer-Logik liegt separat (nächster Commit).
2026-04-14 12:41:14 +02:00
David MalinowskiandClaude Opus 4.6 b014ed596b feat: add Git fields on IT Object, Contact custom fields, translations
- IT Object: git_remote_url, git_branch, git_path_on_host (visible
  only when type = Git Repository)
- Contact custom fields: teams_user_id, is_external_contractor,
  contractor_for (via fixtures)
- Remove x509_certificate hooks from hooks.py (moved to DocType controller)
- Add Custom Field fixture export filter to hooks.py
- German translations (de.csv) for all new DocTypes and fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:05:58 +02:00
David MalinowskiandClaude Opus 4.6 382be5fa33 feat: add Worklog Mapping DocType
- Maps work tracker projects, local directories, chat participants
  to customers for automated work time attribution
- Fields: customer, source_type, pattern (glob), employee, note

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:05:58 +02:00
David MalinowskiandClaude Opus 4.6 549963affd feat: replace x509_certificate with SSL Certificate DocType
- Rename x509_certificate → SSL Certificate (DocType, table, files)
- Rename child tables to SSL Certificate Domain/Installation
- ZIP import: extracts .crt.pem, .key.pem, .ca.pem, .csr.pem
- Auto-parse: CN, issuer, SANs, validity, wildcard, cert type
- Private key stored encrypted (Password field)
- Download buttons: cert, key, fullchain, cert+key, CA, CSR
- Copy-to-clipboard with HTTP fallback
- Certificate details as HTML table
- Key verification (signature check) and CA chain validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:05:58 +02:00
David MalinowskiandClaude Opus 4.6 7f5f7a5236 feat: add IT Domain DocType with import wizard and enrichment
- New DocType IT Domain for centralized domain management
- Hetzner CSV import (domains + handles with registrant data)
- DomainReselling.de API import (live domain + contact fetch)
- DNS/HTTP/SSL enrichment (IP, MX, website title, SSL info)
- Customer suggestion engine (handle, registrant, title, domain matching)
- Interactive assignment dialog with bulk-assign
- Colored badges for DNS hosting and MX routing in list view
- German translations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:05:58 +02:00
David MalinowskiandClaude Opus 4.6 4bf40ff70a fix: apply_ohne_berechnung sets values directly to avoid async recalculation conflicts
frappe.model.set_value in a loop triggered ERPNext pricing recalculation per item,
causing values to be overwritten. Now sets values on locals objects directly and
triggers a single recalculation at the end.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 14:07:40 +01:00