feat(okr): etatsstyringsmoete-underlag fra syklusdata
This commit is contained in:
parent
77031b0c9a
commit
052e4d4e86
5 changed files with 203 additions and 26 deletions
|
|
@ -296,3 +296,108 @@ export function arsrapportDelIII(syklus, opts = {}) {
|
|||
|
||||
return `${ut.join('\n').replace(/\n+$/, '')}\n`;
|
||||
}
|
||||
|
||||
// --- Etatsstyringsmoete-underlag (steg 12) ---
|
||||
//
|
||||
// Bygget paa styringsdialog-kapittelet i okr-offentlig-governance.md:96-114.
|
||||
// Etatsstyringsmoetet er det sentrale moetepunktet mellom departement og
|
||||
// virksomhet, og OKR-settet gir det en fast struktur: hva flyttet seg, hva
|
||||
// stoppet opp, hva ber vi om.
|
||||
//
|
||||
// Generatoren tar IKKE stilling til kadens. F-j fjernet paastanden om «2-4
|
||||
// etatsstyringsmoeter per aar» nettopp fordi den ikke lot seg verifisere; antall
|
||||
// og form fastsettes i departementets hovedinstruks. Et underlag som foregrep
|
||||
// kadensen ville gjeninnfoert den samme uverifiserte paastanden i maskinform.
|
||||
|
||||
// Avvik er committed-only. Predikatet er det samme som Avvik-kolonnen bruker --
|
||||
// via beregnScore, aldri naa >= target -- saa listen og kolonnen ikke kan gi
|
||||
// ulikt svar om samme KR.
|
||||
function avvikListe(okrer) {
|
||||
const rader = [];
|
||||
for (const okr of okrer) {
|
||||
for (const kr of okr.krer) {
|
||||
if (kr.type !== 'committed' || formatAvvik(kr, true) !== 'Ja') continue;
|
||||
rader.push(
|
||||
`- ${okr.tittel}: ${kr.navn} -- naa ${kr.naa} mot krav ${kr.target} `
|
||||
+ `(score ${formatScore(beregnScore(kr))})`,
|
||||
);
|
||||
}
|
||||
}
|
||||
return rader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bygger underlaget til et etatsstyringsmoete for en syklus lest av lesSyklus().
|
||||
*
|
||||
* @param {object} syklus struktur fra lesSyklus()
|
||||
* @param {{naa?: string}} [opts]
|
||||
* @returns {string} markdown
|
||||
*/
|
||||
export function etatsstyringsunderlag(syklus, opts = {}) {
|
||||
krevSyklus(syklus, 'etatsstyringsunderlag');
|
||||
|
||||
const naa = klokke(opts);
|
||||
const antallKr = syklus.okrer.reduce((n, okr) => n + okr.krer.length, 0);
|
||||
if (antallKr === 0) {
|
||||
throw new Error(`etatsstyringsunderlag: syklusen ${syklus.id} inneholder ingen KR aa rapportere`);
|
||||
}
|
||||
|
||||
const ut = [
|
||||
`# Etatsstyringsmoete - underlag (${syklus.id})`,
|
||||
'',
|
||||
`Generert: ${naa}`,
|
||||
'',
|
||||
'Antall og form paa etatsstyringsmoetene fastsettes i departementets',
|
||||
'hovedinstruks. Dette underlaget tar ikke stilling til kadensen; det gir',
|
||||
'moetet en struktur bygget paa syklusens egne tall.',
|
||||
'',
|
||||
...SKALAFORKLARING,
|
||||
];
|
||||
|
||||
for (const okr of syklus.okrer) {
|
||||
ut.push(`## ${okr.tittel}`, '');
|
||||
for (const [type, erCommitted, overskrift] of [
|
||||
['committed', true, '### Committed Key Results'],
|
||||
['aspirational', false, '### Aspirational Key Results'],
|
||||
]) {
|
||||
const krer = okr.krer.filter((kr) => kr.type === type);
|
||||
if (krer.length === 0) continue;
|
||||
ut.push(overskrift, '', ...krTabell(krer, erCommitted), '');
|
||||
}
|
||||
}
|
||||
|
||||
const avvik = avvikListe(syklus.okrer);
|
||||
ut.push(
|
||||
'## Avvik som krever departementets oppmerksomhet',
|
||||
'',
|
||||
...(avvik.length > 0
|
||||
? avvik
|
||||
: ['Ingen committed KR ligger under kravet i denne syklusen.']),
|
||||
'',
|
||||
);
|
||||
|
||||
// Hjemmelen for at tildelingsbrevet SKAL inneholde styringsparametere er
|
||||
// bestemmelser om oekonomistyring i staten («bestemmelsene») punkt 1.5,
|
||||
// gjengitt i DFOe-notat 2026:2 s. 49 (fn. 228). Generatoren leser ikke
|
||||
// tildelingsbrevet -- den har bare syklusdataene -- saa koblingen er et felt
|
||||
// den RESERVERER. En generator som gjettet hvilket krav et Objective svarer
|
||||
// paa, ville laget styringsinformasjon ingen har vedtatt.
|
||||
ut.push(
|
||||
'## Styringsparametere mot tildelingsbrevets krav',
|
||||
'',
|
||||
'Tildelingsbrevet skal sette styringsparametere for aa kunne vurdere',
|
||||
'maaloppnaaelse og resultater (bestemmelsene punkt 1.5). Koblingen mellom',
|
||||
'syklusens Objectives og disse parameterne staar her:',
|
||||
'',
|
||||
'| Objective | Styringsparameter i tildelingsbrevet | Krav |',
|
||||
'|-----------|--------------------------------------|------|',
|
||||
...syklus.okrer.map((okr) => `| ${okr.tittel} | | |`),
|
||||
'',
|
||||
'[Fylles ut av virksomheten: styringsparameter og krav hentes fra',
|
||||
'tildelingsbrevet. Generatoren leser bare syklusdataene og gjetter ikke',
|
||||
'hvilket krav et Objective svarer paa.]',
|
||||
'',
|
||||
);
|
||||
|
||||
return `${ut.join('\n').replace(/\n+$/, '')}\n`;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue