- Introduced SYNC_STRATEGY_ARCHIVE.md detailing the sync process, status values, and flow for updating entities from EspoCRM to Advoware and vice versa. - Created SYNC_TEMPLATE.md as a guide for implementing new syncs, including field definitions, mapper examples, sync utilities, event handlers, and cron jobs. - Added README_SYNC.md for the Beteiligte sync event handler, outlining its functionality, event subscriptions, optimizations, error handling, and performance metrics.
287 lines
8.1 KiB
Markdown
287 lines
8.1 KiB
Markdown
# Entity-Mapping: EspoCRM CBeteiligte ↔ Advoware Beteiligte
|
|
|
|
Basierend auf dem Vergleich von:
|
|
- **EspoCRM**: CBeteiligte Entity ID `68e4af00172be7924`
|
|
- **Advoware**: Beteiligter ID `104860`
|
|
|
|
## Gemeinsame Felder (direkte Übereinstimmung)
|
|
|
|
| EspoCRM Feld | Advoware Feld | Typ | Notes |
|
|
|--------------|---------------|-----|-------|
|
|
| `name` | `name` | string | Vollständiger Name |
|
|
| `rechtsform` | `rechtsform` | string | Rechtsform (z.B. "GmbH", "Frau") |
|
|
| `id` | `id` | mixed | **Achtung:** EspoCRM=string, Advoware=int |
|
|
|
|
## Namenfelder
|
|
|
|
| EspoCRM Feld | Advoware Feld | Mapping |
|
|
|--------------|---------------|---------|
|
|
| `firstName` | `vorname` | ✓ Direkt |
|
|
| `lastName` | `name` | ✓ Bei Personen |
|
|
| `middleName` | - | ❌ Kein direktes Mapping |
|
|
| `firmenname` | `name` | ✓ Bei Firmen |
|
|
| - | `geburtsname` | ← Nur in Advoware |
|
|
| - | `kurzname` | ← Nur in Advoware |
|
|
|
|
## Kontaktdaten
|
|
|
|
| EspoCRM Feld | Advoware Feld | Mapping |
|
|
|--------------|---------------|---------|
|
|
| `emailAddress` | `emailGesch` | ✓ Geschäftlich |
|
|
| `emailAddressData` (array) | `email` | ⚠️ Komplex: Array vs. String |
|
|
| `phoneNumber` | `telGesch` | ✓ Geschäftstelefon |
|
|
| `phoneNumberData` (array) | `telPrivat` | ⚠️ Komplex |
|
|
| - | `mobil` | ← Nur in Advoware |
|
|
| - | `faxGesch` / `faxPrivat` | ← Nur in Advoware |
|
|
| - | `autotelefon` | ← Nur in Advoware |
|
|
| - | `internet` | ← Nur in Advoware |
|
|
|
|
**Hinweis**: Advoware hat zusätzlich `kommunikation` Array mit strukturierten Kontaktdaten.
|
|
|
|
## Adressdaten
|
|
|
|
| EspoCRM Feld | Advoware Feld | Mapping |
|
|
|--------------|---------------|---------|
|
|
| `adressensIds` / `adressensNames` | `adressen` (array) | ⚠️ Beziehung |
|
|
| - | `strasse` | ← Hauptadresse in Advoware Root |
|
|
| - | `plz` | ← Hauptadresse in Advoware Root |
|
|
| - | `ort` | ← Hauptadresse in Advoware Root |
|
|
| - | `anschrift` | ← Formatierte Adresse |
|
|
|
|
**Hinweis**:
|
|
- EspoCRM: Adressen als Related Entities (IDs/Names)
|
|
- Advoware: Hauptadresse im Root-Objekt + `adressen` Array für zusätzliche
|
|
|
|
## Anrede & Titel
|
|
|
|
| EspoCRM Feld | Advoware Feld | Mapping |
|
|
|--------------|---------------|---------|
|
|
| `salutationName` | `anrede` | ✓ (z.B. "Frau", "Herr") |
|
|
| - | `bAnrede` | ← Briefanrede ("Sehr geehrte...") |
|
|
| - | `titel` | ← Titel (Dr., Prof., etc.) |
|
|
| - | `zusatz` | ← Namenszusatz |
|
|
|
|
## Geburtsdaten
|
|
|
|
| EspoCRM Feld | Advoware Feld | Mapping |
|
|
|--------------|---------------|---------|
|
|
| `dateOfBirth` | `geburtsdatum` | ✓ Direkt |
|
|
| - | `sterbedatum` | ← Nur in Advoware |
|
|
| - | `familienstand` | ← Nur in Advoware |
|
|
|
|
## Handelsregister (für Firmen)
|
|
|
|
| EspoCRM Feld | Advoware Feld | Mapping |
|
|
|--------------|---------------|---------|
|
|
| `handelsregisterNummer` | `handelsRegisterNummer` | ✓ Direkt |
|
|
| `handelsregisterArt` (z.B. "HRB") | - | ❌ Nur in EspoCRM |
|
|
| - | `registergericht` | ← Nur in Advoware |
|
|
|
|
## Bankverbindungen
|
|
|
|
| EspoCRM Feld | Advoware Feld | Mapping |
|
|
|--------------|---------------|---------|
|
|
| `bankverbindungensIds` / Names | `bankkverbindungen` (array) | ⚠️ Related Entity vs. Array |
|
|
|
|
## Beteiligungen/Akten
|
|
|
|
| EspoCRM Feld | Advoware Feld | Mapping |
|
|
|--------------|---------------|---------|
|
|
| - | `beteiligungen` (array) | ← Nur in Advoware |
|
|
|
|
**Hinweis**: Advoware speichert die Akten-Beteiligungen direkt beim Beteiligten.
|
|
|
|
## EspoCRM-spezifische Felder
|
|
|
|
| Feld | Zweck |
|
|
|------|-------|
|
|
| `betnr` | Beteiligten-Nummer (= Advoware `betNr`) |
|
|
| `advowareLastSync` | Zeitstempel der letzten Synchronisation |
|
|
| `syncStatus` | Status: "clean", "dirty", "syncing" |
|
|
| `disgTyp` | DISC-Persönlichkeitstyp |
|
|
| `description` | Notizen/Beschreibung |
|
|
| `createdAt` / `createdById` / `createdByName` | Audit-Felder |
|
|
| `modifiedAt` / `modifiedById` / `modifiedByName` | Audit-Felder |
|
|
| `assignedUserId` / `assignedUserName` | Zuweisungen |
|
|
| `teamsIds` / `teamsNames` | Team-Zugehörigkeit |
|
|
| `deleted` | Soft-Delete Flag |
|
|
| `isFollowed` / `followersIds` | Social Features |
|
|
|
|
## Advoware-spezifische Felder
|
|
|
|
| Feld | Zweck |
|
|
|------|-------|
|
|
| `betNr` | Interne Beteiligten-Nummer |
|
|
| `rowId` | Datenbank Row-ID |
|
|
| `art` | Beteiligten-Art |
|
|
| `angelegtAm` / `angelegtVon` | Erstellt |
|
|
| `geaendertAm` / `geaendertVon` | Geändert |
|
|
| `kontaktpersonen` (array) | Kontaktpersonen bei Firmen |
|
|
| `ePost` / `bea` | Spezielle Kommunikationskanäle |
|
|
|
|
## Mapping-Strategie
|
|
|
|
### 1. Person (Natürliche Person)
|
|
|
|
```python
|
|
espocrm_to_advoware = {
|
|
'firstName': 'vorname',
|
|
'lastName': 'name',
|
|
'dateOfBirth': 'geburtsdatum',
|
|
'rechtsform': 'rechtsform', # z.B. "Herr", "Frau"
|
|
'salutationName': 'anrede',
|
|
'emailAddress': 'emailGesch',
|
|
'phoneNumber': 'telGesch',
|
|
}
|
|
```
|
|
|
|
### 2. Firma (Juristische Person)
|
|
|
|
```python
|
|
espocrm_to_advoware = {
|
|
'firmenname': 'name',
|
|
'rechtsform': 'rechtsform', # z.B. "GmbH", "AG"
|
|
'handelsregisterNummer': 'handelsRegisterNummer',
|
|
'emailAddress': 'emailGesch',
|
|
'phoneNumber': 'telGesch',
|
|
}
|
|
```
|
|
|
|
### 3. Adressen
|
|
|
|
**EspoCRM → Advoware**:
|
|
- Lade Related Entity `Adressen` via `adressensIds`
|
|
- Mappe Hauptadresse zu Root-Feldern `strasse`, `plz`, `ort`
|
|
- Zusätzliche Adressen in `adressen` Array
|
|
|
|
**Advoware → EspoCRM**:
|
|
- Hauptadresse aus Root-Feldern
|
|
- `adressen` Array → Related Entities in EspoCRM
|
|
|
|
### 4. Kontaktdaten (Komplex)
|
|
|
|
**EspoCRM `emailAddressData`**:
|
|
```json
|
|
[
|
|
{
|
|
"emailAddress": "primary@example.com",
|
|
"primary": true,
|
|
"optOut": false,
|
|
"invalid": false
|
|
}
|
|
]
|
|
```
|
|
|
|
**Advoware `kommunikation`**:
|
|
```json
|
|
[
|
|
{
|
|
"id": 88002,
|
|
"kommArt": 0, // 0=Telefon, 1=Email, etc.
|
|
"tlf": "0511/12345-60",
|
|
"online": false
|
|
}
|
|
]
|
|
```
|
|
|
|
**Mapping**: Erfordert Transformation basierend auf `kommArt`.
|
|
|
|
## Sync-Richtungen
|
|
|
|
### EspoCRM → Advoware (Webhook-getrieben)
|
|
|
|
1. Webhook empfängt `CBeteiligte` create/update/delete
|
|
2. Mappe Felder gemäß Tabelle oben
|
|
3. `POST /api/v1/advonet/Beteiligte` (create) oder
|
|
`PUT /api/v1/advonet/Beteiligte/{betNr}` (update)
|
|
4. Update `advowareLastSync` und `syncStatus` in EspoCRM
|
|
|
|
### Advoware → EspoCRM (Polling oder Webhook)
|
|
|
|
1. Überwache Änderungen in Advoware
|
|
2. Mappe Felder zurück
|
|
3. `PUT /api/v1/CBeteiligte/{id}` in EspoCRM
|
|
4. Setze `syncStatus = "clean"`
|
|
|
|
## Konflikte & Regeln
|
|
|
|
| Szenario | Regel |
|
|
|----------|-------|
|
|
| Beide Systeme geändert | Advoware als Master (führendes System) |
|
|
| Feld nur in EspoCRM | Ignorieren beim Export, behalten |
|
|
| Feld nur in Advoware | Null/Leer in EspoCRM setzen |
|
|
| `betnr` vs. `betNr` | Sync-Link: Muss identisch sein |
|
|
|
|
## ID-Mapping
|
|
|
|
**Problem**: EspoCRM und Advoware haben unterschiedliche ID-Systeme.
|
|
|
|
**Lösung**:
|
|
- EspoCRM `betnr` Feld = Advoware `betNr`
|
|
- Dies ist der Sync-Link zwischen beiden Systemen
|
|
- Bei Create in EspoCRM: `betnr` erst nach Advoware-Insert setzen
|
|
- Bei Create in Advoware: EspoCRM ID in Custom Field speichern?
|
|
|
|
## Nächste Schritte
|
|
|
|
1. **Mapper-Modul erstellen**: `bitbylaw/services/espocrm_mapper.py`
|
|
- `map_cbeteiligte_to_advoware(espo_data) -> advo_data`
|
|
- `map_advoware_to_cbeteiligte(advo_data) -> espo_data`
|
|
|
|
2. **Sync-Event-Step implementieren**: `bitbylaw/steps/vmh/beteiligte_sync_event_step.py`
|
|
- Subscribe to `vmh.beteiligte.create/update/delete`
|
|
- Fetch full entity from EspoCRM
|
|
- Transform via Mapper
|
|
- Write to Advoware
|
|
- Update sync metadata
|
|
|
|
3. **Testing**:
|
|
- Unit Tests für Mapper
|
|
- Integration Tests mit Sandbox-Daten
|
|
- Konflikt-Szenarien testen
|
|
|
|
4. **Error Handling**:
|
|
- Retry-Logic bei API-Fehlern
|
|
- Validation vor dem Sync
|
|
- Rollback bei Fehlern?
|
|
- Logging aller Sync-Operationen
|
|
|
|
5. **Performance**:
|
|
- Batch-Processing für mehrere Beteiligte
|
|
- Rate Limiting beachten
|
|
- Caching von Lookup-Daten
|
|
|
|
## Beispiel-Transformation
|
|
|
|
### EspoCRM CBeteiligte:
|
|
```json
|
|
{
|
|
"id": "68e4af00172be7924",
|
|
"firstName": "Angela",
|
|
"lastName": "Mustermanns",
|
|
"rechtsform": "Frau",
|
|
"emailAddress": "angela@example.com",
|
|
"phoneNumber": "0511/12345",
|
|
"betnr": 104860,
|
|
"handelsregisterNummer": null
|
|
}
|
|
```
|
|
|
|
### Advoware Beteiligter:
|
|
```json
|
|
{
|
|
"betNr": 104860,
|
|
"vorname": "Angela",
|
|
"name": "Mustermanns",
|
|
"rechtsform": "Frau",
|
|
"anrede": "Frau",
|
|
"emailGesch": "angela@example.com",
|
|
"telGesch": "0511/12345"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
**Generiert am**: 2026-02-07
|
|
**Basierend auf**: Real-Daten-Vergleich mit `scripts/compare_beteiligte.py`
|