Microsoft Planner-integrasjon¶
PlannerSyncAdapter synker ePortal-prosjekter til Microsoft Planner-planer: prosjekter → planer, buckets → buckets, oppgaver → oppgaver (tittel, prioritet, frist, prosent). Sjekklister og tildelinger er beskrevet i adapterens klasse-kommentar som planlagt, men SyncTask overfører dem ikke i dag. Adapteren bruker app-only-autentisering (Client Credentials) mot Microsoft Graph slik at sync kjører som bakgrunnsjobb uavhengig av påloggede brukere.
Type: Microsoft Graph API-sync (bidirectional med last-write-wins) Modul i ePortal: Konfigureres i Konti Connect, bruker Prosjekt-modulen og Microsoft 365-integrasjonen Karakteristisk: App-only via
IMicrosoftGraphAuthService; ETag-basert konflikthåndtering; Planner-grenser (300 oppgaver per plan, 20 sjekklist-items per oppgave)
Hva integrasjonen synker¶
| Retning | Entitet | Frekvens |
|---|---|---|
| ePortal → Planner | Prosjekt → Plan (tittel) | Per scheduler-konfigurasjon |
| ePortal → Planner | Buckets → Buckets (navn) | Per scheduler-konfigurasjon |
| ePortal → Planner | Oppgaver → Tasks (tittel, prioritet, frist, prosent) | Per scheduler-konfigurasjon |
| ePortal → Planner | Sjekklist-items → Task checklist | Ikke aktiv i dag — SyncTask overfører kun tittel, prioritet, frist og prosent |
| Planner → ePortal | Status-endringer (begrenset pull-back) | Sammen med push |
Implementasjon: PlannerSyncAdapter.cs (basert på BaseGraphAdapter.cs)
Tilgang¶
| Hvem | Hva trengs |
|---|---|
| Hos kunden | Microsoft 365-lisens med Planner aktivert; en Microsoft 365-gruppe (Group / Team) som eier planene |
| Hos Konti | Administrator-tilgang til Konti Connect; app-registrering i Entra ID med rette permissions (se under) |
Forutsetninger¶
- M365 Graph-integrasjon er aktivert i ePortal (
M365Graph.Enabled = truevia Microsoft 365-innstillinger) - App-registrering i Entra ID med Application permissions (admin consent):
Group.ReadWrite.All(for å opprette/oppdatere Planner-planer eid av M365-grupper)Tasks.ReadWrite.All(for Planner-oppgaver)- Standard M365-gruppe-ID lagret i
M365Graph.DefaultGroupId(innstillingen leses viaISettingsService) - Prosjekter som skal synke har en rad i
ProjectExternalSync-tabellen som linker ePortal-prosjektet til en Planner-plan (eller en tom rad som markerer at adapteren skal opprette plan ved første kjøring)
Konfigurasjon — feltforklaring¶
Adapteren har lite per-integrasjon-konfigurasjon fordi det meste styres av M365 Graph-innstillinger (sentralt) og av ProjectExternalSync-tabellen per prosjekt.
| Felt | Sted | Type | Påkrevd | Hva det betyr |
|---|---|---|---|---|
M365Graph.Enabled |
Innstillinger (sentralt) | Boolean | Ja | Master-switch for hele M365 Graph-integrasjonen. Hvis false: adapteren returnerer med warning |
M365Graph.DefaultGroupId |
Innstillinger (sentralt) | String (GUID) | Ja | ID-en til M365-gruppen som eier nyopprettede Planner-planer |
M365Graph.TenantId |
Innstillinger (sentralt) | String (GUID) | Ja | Azure AD-tenant |
M365Graph.ClientId |
Innstillinger (sentralt) | String (GUID) | Ja | App-registreringens client_id |
M365Graph.ClientSecret |
Innstillinger (sentralt) | String (hemmelighet) | Ja | App-registreringens client_secret. Krypteres |
(per-integrasjon ConfigurationJson) |
— | — | — | Ingen påkrevde felt. Scheduler-frekvens styrer hvor ofte adapteren kjører |
Eksempel ConfigurationJson:
{
"_comment": "Planner-sync har ingen per-integrasjon-credentials. Auth og default-gruppe leses fra sentrale M365Graph-innstillinger. Per-prosjekt-mapping styres av ProjectExternalSync-tabellen."
}
Du kan la ConfigurationJson være tom eller bare inneholde en kommentar — adapteren leser ikke ut spesifikke felter.
ProjectExternalSync-rader (per prosjekt)¶
Hver ePortal-prosjekt som skal synke må ha en rad i ProjectExternalSync med:
| Kolonne | Verdi |
|---|---|
LocalEntityId |
projectID |
LocalEntityType |
"Project" |
ExternalSystem |
"M365Planner" |
ExternalId |
Planner Plan ID (tom ved opprettelse — settes av adapteren etter første sync) |
ExternalETag |
Planner ETag (for konfliktdeteksjon) |
LastSyncDate |
Stempel ved siste sync |
SyncStatus |
"Synced" eller "Conflict" |
Tilsvarende rader opprettes for Bucket og Task. Adapteren oppretter rader automatisk ved første sync av nye entiteter.
Hemmelig håndtering:
ClientSecretlagres kryptert sentralt (ikke per integrasjon). Token cacheres iIMicrosoftGraphAuthServiceper kundemiljø — mellomlageret deles ikke på tvers av kunder (se Microsoft 365-integrasjon); cachen invalideres automatisk ved 401, og kun for kundemiljøet som fikk 401.
Slik gjør du — oppsett¶
1. Registrer Azure AD-applikasjon for app-only Graph-tilgang¶
Følg trinnene i Microsoft 365-integrasjon for å registrere appen. Aktiver i tillegg:
- Application permissions:
Group.ReadWrite.AllTasks.ReadWrite.All- Klikk Grant admin consent — uten dette får adapteren 403 ved første kall
2. Lagre credentials i ePortal¶
Innstillinger → Konti Connect → Microsoft Graph-innstillinger (modal):
TenantId,ClientId,ClientSecretDefaultGroupId(ID-en til M365-gruppen som skal eie nye Planner-planer)- Aktiver
M365Graph.Enabled = true
3. Opprett integrasjon i Konti Connect¶
- Innstillinger → Konti Connect → Ny integrasjon
- Type: M365Planner
ConfigurationJsonkan stå tom eller inneholde en kommentar- Sett scheduler — typisk hvert 15.–30. minutt for aktiv bruk
- Lagre
4. Aktiver sync per prosjekt¶
For hvert prosjekt som skal synke til Planner:
- Opprett en rad i
ProjectExternalSyncmedExternalSystem = "M365Planner"ogLocalEntityId = projectID - La
ExternalIdstå tom — adapteren oppretter Planner-planen ved første sync og fyller den inn - Alternativt: hvis planen allerede finnes i Planner, sett
ExternalIdtil Planner Plan ID
5. Test første kjøring¶
- Bruk Kjør nå
- Følg kjøringsloggen:
- "Planner sync completed: N/M projects synced"
- Per-prosjekt: opprettet plan / oppdatert plan / konflikt
- Verifiser i Microsoft Planner at planen er opprettet i M365-gruppen
- Sjekk at buckets og oppgaver er på plass
Mapping-detaljer¶
| ePortal | Planner | Forklaring |
|---|---|---|
Project.ProjectTitle |
Plan.title |
Plan-tittel |
Bucket.BucketName |
Bucket.name |
Bucket-navn |
Task.TaskTitle |
Task.title |
Oppgavetittel |
Task.PercentComplete |
Task.percentComplete |
0–100 |
Task.TaskPriority |
Task.priority |
Mappet via MapPriorityToPlanner() (ePortal 1–9 → Planner 0–10) |
Task.DueDate |
Task.dueDateTime |
Frist |
Task.Assignees |
Task.assignments |
Ikke synket i dag — SyncTask overfører ikke tildelinger |
| Sjekklist-items | Task.details.checklist |
Ikke synket i dag — SyncTask overfører ikke sjekkliste-items (klasse-kommentaren beskriver det som planlagt) |
Konflikt-håndtering¶
- ETag-basert: Hvert PATCH-kall sender
If-Match: <etag>header - Hvis Planner svarer 409 Conflict: adapteren logger som warning, setter
SyncStatus = "Conflict"påProjectExternalSync, og fortsetter til neste entitet - Last write wins ved konfliktløsning — manuell intervensjon må til hvis sync skal "vinne" eller "tape"
- Etter sync oppdateres
ExternalETagogLastSyncDate
Frekvens og volum¶
- Anbefalt scheduler: hvert 15.–30. minutt for aktiv bruk, hver time for sjeldnere endringer
- Planner-grenser (Microsoft):
- 300 oppgaver per plan — adapteren stopper når grensen er nådd
- 20 sjekklist-items per oppgave
- 40 buckets per plan
- Rate limiting (429): adapteren respekterer
Retry-After-header (3 retries) - 503/504: eksponentiell backoff (2s, 4s, 8s)
Sikkerhet¶
ClientSecretlagres kryptert sentralt- Tokenet caches i
IMicrosoftGraphAuthServiceper kundemiljø og invalideres automatisk ved 401 - App-only-tilgang krever Microsoft-tenant-admin consent — kjør kun mot kunder hvor dette er avklart
- All Graph-tilgang loggføres i Azure AD audit-log (Microsoft-side)
Vanlige problemer¶
M365 Graph integration is disabled. Enable via M365Graph.Enabled setting.¶
Master-switch er av. Slå på via Konti Connect → Microsoft Graph-innstillinger.
Authentication failed: 401¶
Token utløpt eller ugyldig. Adapteren invaliderer cachen automatisk; hvis problemet vedvarer:
- Sjekk
TenantId,ClientId,ClientSecreti sentrale innstillinger - Sjekk at app-registreringen ikke er slettet/expired i Entra ID
403 Forbidden på Planner-API¶
Manglende admin consent på Application permissions. Gå til Entra ID → App registrations → API permissions → "Grant admin consent".
Planen opprettes ikke¶
- Sjekk
DefaultGroupId— må peke på en eksisterende M365-gruppe - App-registreringen trenger
Group.ReadWrite.All-permission - Bruker som opprettet gruppen må ha riktig lisens
ETag conflict on PATCH¶
Noen har endret entiteten direkte i Planner mellom to sync-kjøringer. Sett SyncStatus = "Conflict". Bestem manuelt hvilken side som skal "vinne" og oppdater ExternalETag deretter.
Oppgaver mangler — har truffet 300-grensen¶
Planner-grensen. Splitt prosjektet i flere planer eller arkiver gamle oppgaver.
Tildelte brukere kommer ikke med¶
Microsoft Planner krever Azure AD-bruker-ID (oid) for å tildele. Hvis ePortal-brukerens userName ikke matcher en UPN i Entra ID, hopper adapteren over tildelingen og logger warning.