Grupper Synkronisering
Oversikt
Grupper (lokallag) synkroniseres fra Cornerstone (kilde) til ClickUp og WordPress (mål). Systemet bruker entity_map som eneste kilde for global synkronisering.
Sync-retning
Cornerstone → ClickUp → WordPress
Cornerstone er kilden for gruppedata. Endringer i Cornerstone synkroniseres til ClickUp og WordPress.
Entity Mapping System
Hver gruppe har en entity_uuid som kobler sammen:
- cornerstone_id - ID i Cornerstone
- clickup_id - Task ID i ClickUp
- wp_post_id - Post ID i WordPress
- display_name - Visningsnavn
Global Sync Flyt
Trigger
Global sync kan trigges på tre måter:
1. Scheduled: Daglig kl 02:00 (via scheduler)
2. Manual: POST /lokallag/global-sync
3. Webhook: POST /webhook?task_id={id}
Prosess
flowchart TD
Start[Global Sync Start] --> FetchEntities[Hent alle group entities fra entity_map]
FetchEntities --> FetchCS[Fetch Cornerstone groups EN GANG]
FetchCS --> BuildMap[Bygg lookup map: cornerstone_id → payload]
BuildMap --> LoopStart[For hver entity]
LoopStart --> CheckCS{Har cornerstone_id?}
CheckCS -->|Nei| Skip1[Skip - log warning]
CheckCS -->|Ja| FindGroup{Finnes i Cornerstone?}
FindGroup -->|Nei| Skip2[Skip - log warning]
FindGroup -->|Ja| ComputeHash[Beregn hash over synced fields]
ComputeHash --> CompareHash{Hash endret?}
CompareHash -->|Nei| Skip3[Skip - ingen endringer]
CompareHash -->|Ja| SyncEngine[SyncEngine.sync_entity]
SyncEngine --> FetchData[LokallagHandler.fetch_source_data]
FetchData --> Transform[Transform data]
Transform --> SyncClickUp[Sync til ClickUp]
SyncClickUp --> SyncWP[Sync til WordPress]
SyncWP --> UpdateHash[Oppdater hash og timestamps]
UpdateHash --> Success[Success]
Skip1 --> NextEntity[Neste entity]
Skip2 --> NextEntity
Skip3 --> NextEntity
Success --> NextEntity
NextEntity --> MoreEntities{Flere entities?}
MoreEntities -->|Ja| LoopStart
MoreEntities -->|Nei| End[Sync ferdig]
Steg-for-steg
- Hent entities: Få alle
entity_type='group'fraentity_map - Fetch Cornerstone: En enkelt GraphQL-spørring for alle grupper (optimalisert)
- Bygg lookup map:
cornerstone_id→ group payload - Iterer over entities:
- Skip hvis mangler
cornerstone_id - Skip hvis gruppe ikke finnes i Cornerstone
- Beregn hash for å oppdage endringer
- Skip hvis uendret (hash match)
- Kall
SyncEngine.sync_entity()medsource='cornerstone' - Spor resultater: Tell prosesserte, suksesser, feil
Sync Engine Flyt
LokallagHandler
sequenceDiagram
participant GS as Global Sync
participant SE as SyncEngine
participant LH as LokallagHandler
participant CS as Cornerstone
participant CU as ClickUp
participant WP as WordPress
participant EM as Entity Map
GS->>SE: sync_entity(entity_uuid, source='cornerstone')
SE->>EM: get_entity_by_uuid()
EM-->>SE: entity (med entity_type='group')
SE->>LH: fetch_source_data(entity, 'cornerstone')
LH->>CS: fetch_graphql_data()
CS-->>LH: group data
LH-->>SE: source_data
SE->>LH: transform_data(source_data)
LH-->>SE: transformed_data (clickup + wordpress)
SE->>LH: sync_to_targets(entity, data)
LH->>CU: Update custom fields
CU-->>LH: success
LH->>WP: Update via registry API
WP-->>LH: success
LH-->>SE: success
SE-->>GS: SyncResult(success=True)
Data Transformasjon
Fra Cornerstone:
{
"id": "123",
"name": "Lokallag Navn",
"bankAccountNo": "12345678901",
"leader": {
"email": "leder@example.com",
"name": "Leder Navn",
"mobile": "12345678"
},
"annualReports": [{
"membersAccepted": 50
}]
}
Til ClickUp:
- bank_account → Custom field
- email → Custom field
- name → Custom field
- mobile → Custom field
- members_accepted → Custom field
- entity_uuid → Custom field
Til WordPress:
- cornerstone_group_id → Meta field
- clickup_task_id → Meta field
- entity_uuid → Meta field
- display_name → Post title
- telefon, epost, hovedleder, antall_medlemmer → Meta fields
Incremental Sync
Systemet bruker hash-basert endringsdeteksjon:
- Beregner hash over alle synced fields
- Sammenligner med lagret cornerstone_source_hash
- Skipper uendrede entities (hash match)
- Oppdaterer last_seen_at timestamp
Dette reduserer unødvendige API-kall og forbedrer ytelsen.
Individual Sync
Enkelt gruppe kan synkroniseres via:
- POST /applications/sync-lokallag/{task_id}
Flyt:
1. Hent task data fra ClickUp
2. Sjekk om entity finnes i entity_map
3. Hvis ikke: Opprett ny lokallag i alle systemer
4. Hvis ja: Bruk SyncEngine for å synkronisere
Error Handling
Manglende Cornerstone ID
- Logger warning til
sync_errors - Skipper entity (fortsetter med andre)
- Oppdaterer
last_seen_atfor debugging
Manglende Cornerstone Payload
- Group ID finnes i
entity_mapmen ikke i Cornerstone - Logger warning med kontekst
- Registrerer last-seen forsøk
Sync-feil
- Logger feil med entity-kontekst
- Fortsetter prosessering av andre entities
- Oppdaterer ClickUp sync status til 'error'
Monitoring
- Sporer sync history i
sync_historytabell - Logger feil med entity-kontekst
- Oppdaterer entity stamps etter vellykket sync
- Oppdaterer ClickUp sync status field
Performance
- Prosesserer entities sekvensielt
- En enkelt Cornerstone-fetch per run
- Hash-basert endringsdeteksjon
- Skipper uendrede entities