Vis prosjektversjonen i et internkontrollfelt på forsiden #2

Open
bl wants to merge 1 commits from prosjektversjon-i-rapporten into main
pull from: prosjektversjon-i-rapporten
6 changed files with 152 additions and 4 deletions
Showing only changes of commit bef3bb1090 - Show all commits

No files matched your search

+14 -2
View File
@@ -103,7 +103,7 @@ Typst må være installert for PDF-rapporten. Uten Typst kjører du med `--ingen
| `enok klima --kommune Oslo` | Viser nøkkeltall for ett klimasted | | `enok klima --kommune Oslo` | Viser nøkkeltall for ett klimasted |
| `enok skala smaahus --areal 140` | Viser karakterskalaen med arealkorreksjon | | `enok skala smaahus --areal 140` | Viser karakterskalaen med arealkorreksjon |
Nyttige valg til `beregn`: `--tillegg FIL`, `--ingen-pdf`, `--ingen-timeserie`, `--enova-xml`, Nyttige valg til `beregn`: `--tillegg FIL`, `--versjon VERSJON`, `--ingen-pdf`, `--ingen-timeserie`, `--enova-xml`,
`--uten-scenarier`, `--ut KATALOG`. `--uten-scenarier`, `--ut KATALOG`.
### Utdata ### Utdata
@@ -188,6 +188,18 @@ logo = "logo.svg" # vises øverst på forsiden
farge = "#880000" # aksentfarge i overskrifter og tabeller farge = "#880000" # aksentfarge i overskrifter og tabeller
avsender = "Firma · Adresse · Org.nr. 000 000 000" avsender = "Firma · Adresse · Org.nr. 000 000 000"
skrift_overskrift = "Futura Now Headline" skrift_overskrift = "Futura Now Headline"
versjon = "v1.4.0" # prosjektets versjon, se nedenfor
```
Forsiden har et internkontrollfelt med hvilket prosjekt rapporten hører til, hvilken versjon
av prosjektet den er laget fra, oppdragsgiver og energirådgiver, datoen og hvilken
enok-versjon som regnet den. Opplysningene står der én gang, ikke i bunnteksten på hver side.
Prosjektversjonen settes i `rapport.versjon`, eller med `--versjon` på `beregn`. Da kan
byggeserveren sende taggen på utgivelsen uten at noen fil må endres:
```sh
enok beregn modell.ifc --tillegg prosjekt.toml --versjon "$GITHUB_REF_NAME"
``` ```
Scenarier flettes inn i bygningsbeskrivelsen: tabeller flettes rekursivt, elementer i lister Scenarier flettes inn i bygningsbeskrivelsen: tabeller flettes rekursivt, elementer i lister
@@ -425,7 +437,7 @@ jobs:
- name: Lag rapporten - name: Lag rapporten
run: | run: |
chmod +x enok chmod +x enok
./enok beregn bygning.toml --ut dist ./enok beregn bygning.toml --ut dist --versjon "$GITHUB_REF_NAME"
``` ```
## Kontroll av beregningen ## Kontroll av beregningen
+9 -1
View File
@@ -61,6 +61,10 @@ struct Beregn {
/// Tilleggsfil som flettes inn: det modellen ikke beskriver, og rettelser. /// Tilleggsfil som flettes inn: det modellen ikke beskriver, og rettelser.
#[arg(short, long, value_name = "FIL")] #[arg(short, long, value_name = "FIL")]
tillegg: Option<PathBuf>, tillegg: Option<PathBuf>,
/// Prosjektets versjon, som vises i internkontrollfeltet på forsiden. Overstyrer
/// `rapport.versjon`. Byggeserveren sender gjerne taggen på utgivelsen.
#[arg(long, value_name = "VERSJON")]
versjon: Option<String>,
} }
#[derive(Args)] #[derive(Args)]
@@ -174,7 +178,11 @@ fn les_modell(
} }
fn beregn(a: Beregn, kilde: &Datakilde) -> Result<()> { fn beregn(a: Beregn, kilde: &Datakilde) -> Result<()> {
let (bygning, merknader, modell) = les_modell(&a.fil, a.tillegg.as_deref())?; let (mut bygning, merknader, modell) = les_modell(&a.fil, a.tillegg.as_deref())?;
if let Some(v) = &a.versjon {
bygning.rapport.versjon = Some(v.clone());
}
let bygning = bygning;
for m in &merknader { for m in &merknader {
eprintln!(" · {m}"); eprintln!(" · {m}");
} }
+4
View File
@@ -102,6 +102,10 @@ pub struct Rapport {
/// Skrift for overskrifter. Utelatt: enoks egen. /// Skrift for overskrifter. Utelatt: enoks egen.
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
pub skrift_overskrift: Option<String>, pub skrift_overskrift: Option<String>,
/// Prosjektets versjon, typisk taggen på utgivelsen rapporten hører til, for eksempel
/// «v0.3.12». Vises i internkontrollfeltet på forsiden. Kan settes med `--versjon`.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub versjon: Option<String>,
} }
#[derive(Deserialize, Serialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]
+30 -1
View File
@@ -165,6 +165,35 @@ fn kilde(r: &Resultat, scenarier: &[(String, Resultat)]) -> String {
} }
s.push_str(" ]\n)\n\n#v(0.6cm)\n"); s.push_str(" ]\n)\n\n#v(0.6cm)\n");
// Internkontroll: hvilket prosjekt rapporten hører til, hvilken versjon av det, og
// hva den er laget med. Står på forsiden i stedet for i bunnteksten på hver side.
let mut felter: Vec<(String, String)> = Vec::new();
// Adressen står allerede under tittelen på forsiden.
felter.push(("Prosjekt".into(), l.navn.clone()));
if let Some(v) = &rap.versjon {
felter.push(("Prosjektversjon".into(), v.clone()));
}
if let Some(o) = &b.oppdragsgiver {
felter.push(("Oppdragsgiver".into(), o.clone()));
}
if let Some(ra) = &b.energiraadgiver {
felter.push(("Energirådgiver".into(), ra.clone()));
}
felter.push(("Dato".into(), i_dag()));
felter.push((
"Beregnet med".into(),
format!("enok {}", env!("CARGO_PKG_VERSION")),
));
s.push_str("#internkontroll((\n");
for (navn, verdi) in &felter {
s.push_str(&format!(
" (\"{}\", \"{}\"),\n",
streng(navn),
streng(verdi)
));
}
s.push_str("))\n\n#v(0.6cm)\n");
// Nøkkeltall. // Nøkkeltall.
let nøkkel = vec![ let nøkkel = vec![
("Bygningskategori".to_string(), e(&k.kategorinavn)), ("Bygningskategori".to_string(), e(&k.kategorinavn)),
@@ -828,7 +857,7 @@ fn bunntekst(r: &Resultat) -> String {
if let Some(e) = &b.energiraadgiver { if let Some(e) = &b.energiraadgiver {
deler.push(e.clone()); deler.push(e.clone());
} }
deler.push(format!("enok {} · {}", env!("CARGO_PKG_VERSION"), i_dag())); // Versjon og dato står i internkontrollfeltet på forsiden, ikke på hver side.
deler.join(" · ") deler.join(" · ")
} }
+69
View File
@@ -0,0 +1,69 @@
//! Kontroll av opplysningene rapporten skal bære: hvilket prosjekt, hvilken versjon og når.
use enok::data::Datakilde;
use enok::{inndata, kjor, rapport};
use std::path::{Path, PathBuf};
fn rapportkilde(versjon: Option<&str>, katalog: &str) -> String {
let mut b = inndata::les_bygning(Path::new("eksempler/referansebygg/smaahus.toml")).unwrap();
b.rapport.versjon = versjon.map(str::to_string);
let r = kjor::kjor(&b, &Datakilde::default()).unwrap();
let ut: PathBuf = std::env::temp_dir().join(katalog);
rapport::typst_ut::skriv(&r, &ut, &[]).unwrap();
std::fs::read_to_string(ut.join("rapport.typ")).unwrap()
}
fn oppsettlinjen(kilde: &str) -> String {
kilde
.lines()
.find(|l| l.starts_with("#show: oppsett.with("))
.unwrap_or_default()
.to_string()
}
/// Prosjektversjonen hører hjemme i internkontrollfeltet på forsiden.
#[test]
fn prosjektversjonen_staar_i_internkontrollfeltet() {
let kilde = rapportkilde(Some("v0.3.12"), "enok-rapport-med-versjon");
assert!(
kilde.contains("#internkontroll(("),
"mangler internkontrollfeltet"
);
assert!(
kilde.contains("(\"Prosjektversjon\", \"v0.3.12\")"),
"mangler prosjektversjonen"
);
assert!(kilde.contains("(\"Prosjekt\","), "mangler prosjektnavnet");
assert!(kilde.contains("(\"Dato\","), "mangler datoen");
assert!(
kilde.contains("(\"Beregnet med\", \"enok "),
"mangler enok-versjonen"
);
}
/// Uten oppgitt versjon står feltet der, men uten en tom versjonslinje.
#[test]
fn uten_versjon_staar_ingen_versjonslinje() {
let kilde = rapportkilde(None, "enok-rapport-uten-versjon");
assert!(kilde.contains("#internkontroll(("));
assert!(
!kilde.contains("Prosjektversjon"),
"skal ikke stå tom versjon"
);
}
/// Versjon og dato skal stå ett sted, på forsiden, ikke på hver eneste side.
#[test]
fn bunnteksten_gjentar_ikke_versjon_og_dato() {
let kilde = rapportkilde(Some("v0.3.12"), "enok-rapport-bunntekst");
let linje = oppsettlinjen(&kilde);
assert!(!linje.is_empty(), "fant ikke oppsettlinjen");
assert!(
!linje.contains("enok "),
"bunnteksten gjentar enok-versjonen: {linje}"
);
assert!(
!linje.contains("v0.3.12"),
"bunnteksten gjentar prosjektversjonen"
);
}
+26
View File
@@ -107,6 +107,32 @@
)[#tekst] )[#tekst]
} }
// Internkontrollfelt på forsiden: hvilket prosjekt, hvilken versjon og når.
#let internkontroll(rader) = context {
block(
width: 100%,
inset: 9pt,
radius: 4pt,
fill: lys,
stroke: 0.4pt + kantlinje,
stack(
spacing: 6pt,
text(
font: overskriftsskrift(),
size: 7.5pt,
fill: aksent-valgt.get(),
tracking: 0.8pt,
)[INTERNKONTROLL],
..rader.map(rad => grid(
columns: (3.8cm, 1fr),
gutter: 6pt,
text(size: 8.5pt, fill: mid)[#rad.at(0)],
text(size: 8.5pt)[#rad.at(1)],
)),
),
)
}
// Stor karakterrute på forsiden. // Stor karakterrute på forsiden.
#let karakterrute(bokstav, verdi, farge) = { #let karakterrute(bokstav, verdi, farge) = {
box( box(