Sync Ops

Søknader Synkronisering

Oversikt

Søknader (funding) synkroniseres fra ClickUp (kilde) til Cornerstone og WordPress (mål). Systemet bruker entity_map som eneste kilde for global synkronisering.

Sync-retning

ClickUp → Cornerstone → WordPress

ClickUp er kilden for søknadsdata. Endringer i ClickUp synkroniseres til Cornerstone og WordPress.

Entity Mapping System

Hver søknad har en entity_uuid som kobler sammen: - clickup_id - Task ID i ClickUp - cornerstone_id - Funding ID i Cornerstone (nullable) - wp_post_id - Post ID i WordPress (nullable) - display_name - Prosjektnavn

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 /clickup-webhook/funding?task_id={id}

Prosess

flowchart TD
    Start[Global Sync Start] --> FetchEntities[Hent alle funding entities fra entity_map]
    FetchEntities --> LoopStart[For hver entity]
    LoopStart --> CheckCU{Har clickup_id?}
    CheckCU -->|Nei| Skip1[Skip - orphaned entity]
    CheckCU -->|Ja| SyncEngine[SyncEngine.sync_entity]
    SyncEngine --> FetchTask[FundingHandler.fetch_source_data]
    FetchTask --> GetClickUp[Hent task data fra ClickUp]
    GetClickUp --> Transform[Transform data]
    Transform --> CheckEligible{Er funding type eligible?}
    CheckEligible -->|Nei| SyncWPOnly[Sync kun til WordPress]
    CheckEligible -->|Ja| CheckStatus{Er status approved?}
    CheckStatus -->|Nei| SyncWPOnly
    CheckStatus -->|Ja| CheckExists{Finnes i Cornerstone?}
    CheckExists -->|Ja| UpdateCS[Oppdater i Cornerstone]
    CheckExists -->|Nei| CreateCS[Opprett i Cornerstone]
    UpdateCS --> SyncWP[Sync til WordPress]
    CreateCS --> SyncWP
    SyncWPOnly --> UpdateEntity[Oppdater entity mapping]
    SyncWP --> UpdateEntity
    UpdateEntity --> Success[Success]
    Skip1 --> NextEntity[Neste entity]
    Success --> NextEntity
    NextEntity --> MoreEntities{Flere entities?}
    MoreEntities -->|Ja| LoopStart
    MoreEntities -->|Nei| End[Sync ferdig]

Steg-for-steg

  1. Hent entities: Få alle entity_type='funding' fra entity_map
  2. Iterer over entities:
  3. Skip hvis mangler clickup_id (orphaned)
  4. Hent task data fra ClickUp
  5. Transform data for Cornerstone og WordPress
  6. Sjekk eligibility (funding type)
  7. Sjekk ClickUp status (må være approved)
  8. Hvis eligible: Opprett/oppdater i Cornerstone
  9. Alltid: Sync til WordPress
  10. Oppdater entity mapping med IDs
  11. Spor resultater: Tell prosesserte, suksesser, feil

Sync Engine Flyt

FundingHandler

sequenceDiagram
    participant GS as Global Sync/Webhook
    participant SE as SyncEngine
    participant FH as FundingHandler
    participant CU as ClickUp
    participant CS as Cornerstone
    participant WP as WordPress
    participant EM as Entity Map

    GS->>SE: sync_entity(entity_uuid, source='clickup')
    SE->>EM: get_entity_by_uuid()
    EM-->>SE: entity (med entity_type='funding')
    SE->>FH: fetch_source_data(entity, 'clickup')
    FH->>CU: get_task_details(clickup_id)
    CU-->>FH: task data
    FH-->>SE: source_data
    SE->>FH: transform_data(source_data)
    FH-->>SE: transformed_data (cornerstone + wordpress)
    SE->>FH: sync_to_targets(entity, data)
    FH->>FH: Check eligibility & status
    alt Eligible & Approved
        FH->>CS: Create/Update funding
        CS-->>FH: funding_id
        FH->>EM: Update entity.cornerstone_id
    end
    FH->>WP: Create/Update 'soknader' post
    WP-->>FH: wp_post_id
    FH->>EM: Update entity.wp_post_id
    FH-->>SE: success
    SE-->>GS: SyncResult(success=True)

Eligibility Check

Kun visse funding types synkroniseres til Cornerstone:

Eligible: - Prosjekt - Oppstart - Direkte

Not Eligible (WordPress only): - Tale - Musiker

Status Check: Kun søknader med approved status synkroniseres til Cornerstone: - Utbetalt - Skal utbetales

Webhook Processing

ClickUp Webhook

flowchart TD
    Webhook[Webhook Received] --> ExtractID[Extract task_id]
    ExtractID --> Idempotency{Allerede prosessert?}
    Idempotency -->|Ja| Return200[Return 200 - already processed]
    Idempotency -->|Nei| FetchTask[Hent task data fra ClickUp]
    FetchTask --> CheckEntity{Finnes i entity_map?}
    CheckEntity -->|Nei| CreateEntity[Opprett entity mapping]
    CheckEntity -->|Ja| UseEntity[Bruk eksisterende entity]
    CreateEntity --> SyncEngine[SyncEngine.sync_entity]
    UseEntity --> SyncEngine
    SyncEngine --> MarkProcessed[Marker som prosessert]
    MarkProcessed --> ReturnSuccess[Return 200 - success]

Idempotency

Systemet bruker idempotency_keys tabell for å forhindre duplikat prosessering: - Event key: clickup:funding:{task_id}:{timestamp} - Sjekker før prosessering - Duplikat events returnerer 200 uten prosessering

Data Transformasjon

Fra ClickUp:

{
  "id": "86c5gephm",
  "name": "Prosjekt Navn",
  "custom_fields": [
    {"name": "Prosjektbeskrivelse", "value": "Beskrivelse"},
    {"name": "Søknadssum", "value": 50000},
    {"name": "Innvilget sum", "value": 40000},
    {"name": "Type støtte", "value": 0}
  ]
}

Til Cornerstone: - funding_amount → Innvilget sum - funding_description → Prosjektbeskrivelse - funding_date → Dato prosjekt - funding_type → Type støtte (Prosjekt/Oppstart/Direkte)

Til WordPress: - prosjektbeskrivelse → Post content - soknadssum → Meta field - innvilget_sum → Meta field - dato_soknad, dato_innvilget, dato_prosjekt → Meta fields - funding_type → Taxonomy

Entity Relationships

Søknader må linkes til en lokallag (gruppe): - Henter linked lokallag fra ClickUp relationship field - Slår opp lokallag i entity_map for å få cornerstone_id - Bruker lokallag's Cornerstone ID når søknad opprettes

Individual Sync

Enkelt søknad kan synkroniseres via: - POST /applications/funding (med task_id) - POST /clickup-webhook/funding?task_id={id}

Flyt: 1. Hent task data fra ClickUp 2. Sjekk om entity finnes i entity_map 3. Hvis ikke: Opprett entity mapping med ClickUp ID 4. Bruk SyncEngine for å synkronisere 5. Oppdater ClickUp med cornerstone_id og entity_uuid

Error Handling

  • Søknad mangler link til lokallag
  • Logger feil, sync feiler
  • WordPress sync fortsetter

Entity Not Found

  • Auto-oppretter entity mapping
  • Fortsetter med sync

Cornerstone Creation Fails

  • Logger feil med kontekst
  • WordPress sync fortsetter
  • Oppdaterer ClickUp sync status til 'error'

Eligibility Check Fails

  • Logger info-melding
  • WordPress sync fortsetter
  • Returnerer success (WordPress synced)

Monitoring

  • Sporer sync history i sync_history tabell
  • Logger feil med entity-kontekst
  • Oppdaterer entity stamps etter vellykket sync
  • Oppdaterer ClickUp sync status field
  • Legger til kommentarer i ClickUp ved feil/suksess

WordPress Sync

WordPress sync skjer alltid, uavhengig av: - Funding type - Cornerstone eligibility - ClickUp status

Dette sikrer at alle søknader er synlige på nettsiden, selv om de ikke er synkronisert til Cornerstone.