AB-PDF: Bausteine der Auftragsbestätigung mit Höhen und Zusammenhalt
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4706f232b5
commit
f71e3e8345
2 files changed
+125
No files matched your search
@@ -205,6 +205,63 @@ export const BEREICHE = Object.freeze({
|
||||
})
|
||||
|
||||
|
||||
const atom = (id, typ, hoehe, extra = {}) => ({ id, typ, hoehe, abstandDavor: 0, haengtAnNaechstem: false, umbruchDavor: false, kopf: null, ...extra })
|
||||
|
||||
/** Alle Bausteine der AB in Zeichenreihenfolge. messe(text, stil, breite) liefert die Texthöhe in pt. */
|
||||
export function baueAtome(daten, messe) {
|
||||
const b = daten.beschriftung
|
||||
const B = INHALT_BREITE
|
||||
const atome = []
|
||||
const absatz = (id, text, extra = {}, stil = STIL.text) => atome.push(atom(id, 'absatz', messe(text, stil, B), { text, stil: stil === STIL.klein ? 'klein' : 'text', abstandDavor: 6, ...extra }))
|
||||
const ueberschrift = (id, text) => atome.push(atom(id, 'ueberschrift', messe(text, STIL.ueberschrift, B) + 5, { text, abstandDavor: 14, haengtAnNaechstem: true }))
|
||||
|
||||
// Briefkopf (nur Seite 1): Logo, Absender, Anschrift, Angaben, Titel
|
||||
const infoZeilen = [[b.nummer, daten.nummer], [b.datum, daten.datum], ...(daten.kundennummer ? [[b.kundennummer, daten.kundennummer]] : [])]
|
||||
const adresseHoehe = messe(daten.empfaenger.join('\n'), STIL.adresse, MASSE.adresseBreite)
|
||||
const blockEnde = MASSE.adresseY + Math.max(adresseHoehe, infoZeilen.length * MASSE.infoZeile)
|
||||
const titelY = blockEnde + 22
|
||||
const projektY = titelY + STIL.titel.groesse * 1.2 + 6
|
||||
const projektHoehe = messe(`${b.projekt}: ${daten.projekt}`, STIL.projekt, B)
|
||||
atome.push(atom('briefkopf', 'briefkopf', projektY + projektHoehe + 4, { haengtAnNaechstem: true, masse: { titelY, projektY, projektHoehe, infoZeilen } }))
|
||||
|
||||
absatz('einleitung', daten.einleitung, { abstandDavor: 8 })
|
||||
const l = daten.leistung
|
||||
ueberschrift('leistung', l.ueberschrift)
|
||||
if (l.art === 'festpreis') {
|
||||
const kopf = atom('tabellenkopf', 'tabellenkopf', MASSE.kopfHoehe, { haengtAnNaechstem: true, spalten: b.spalten })
|
||||
atome.push(kopf)
|
||||
l.positionen.forEach((p, i) => {
|
||||
const text = messe(p.beschreibung, STIL.text, SPALTEN[1] - 2 * ZELLEN_RAND)
|
||||
const eineZeile = messe('X', STIL.text, SPALTEN[1])
|
||||
atome.push(atom(`zeile-${i + 1}`, 'zeile', Math.max(text, eineZeile) + 2 * ZELLEN_RAND, { zelle: p, kopf, haengtAnNaechstem: i === l.positionen.length - 1 }))
|
||||
})
|
||||
atome.push(atom('summe', 'summe', MASSE.summeHoehe, { label: l.gesamt.label, betrag: l.gesamt.betrag, haengtAnNaechstem: true }))
|
||||
} else {
|
||||
atome.push(atom('aufwand', 'absatz', messe(l.aufwandText, STIL.text, B - 2 * MASSE.kastenRand) + 2 * MASSE.kastenRand, { text: l.aufwandText, stil: 'text', kasten: true, haengtAnNaechstem: true }))
|
||||
}
|
||||
absatz('kleinunternehmer', daten.kleinunternehmer, { abstandDavor: 8 }, STIL.klein)
|
||||
for (const a of daten.abschnitte) {
|
||||
ueberschrift(`${a.id}-kopf`, a.ueberschrift)
|
||||
absatz(a.id, a.text, { abstandDavor: 0 })
|
||||
}
|
||||
absatz('agb', daten.agb, { abstandDavor: 12 })
|
||||
if (daten.ersetzt) absatz('ersetzt', daten.ersetzt, { abstandDavor: 8 })
|
||||
absatz('gruss', daten.gruss, { abstandDavor: 14 })
|
||||
|
||||
if (daten.widerruf) {
|
||||
const { belehrung, formular } = daten.widerruf
|
||||
atome.push(atom('widerruf-titel', 'ueberschrift', messe(belehrung.titel, STIL.titel, B) + 8, { text: belehrung.titel, stil: 'titel', umbruchDavor: true, haengtAnNaechstem: true }))
|
||||
belehrung.abschnitte.forEach((a, i) => {
|
||||
ueberschrift(`widerruf-${i + 1}-kopf`, a.ueberschrift)
|
||||
a.absaetze.forEach((t, k) => absatz(`widerruf-${i + 1}-${k + 1}`, t, { abstandDavor: k === 0 ? 0 : 5 }))
|
||||
})
|
||||
atome.push(atom('formular-titel', 'ueberschrift', messe(formular.titel, STIL.ueberschrift, B) + 5, { text: formular.titel, abstandDavor: 20, haengtAnNaechstem: true }))
|
||||
absatz('formular-einleitung', formular.einleitung, { abstandDavor: 0, haengtAnNaechstem: true }, STIL.klein)
|
||||
formular.zeilen.forEach((t, i) => absatz(`formular-${i + 1}`, t, { abstandDavor: 8, haengtAnNaechstem: i < formular.zeilen.length - 1 }))
|
||||
}
|
||||
return atome
|
||||
}
|
||||
|
||||
/** Teilt Bausteine auf Seiten auf (Ketten bleiben zusammen, Tabellenkopf wiederholt sich). */
|
||||
export function paginiere(atome, bereiche = BEREICHE) {
|
||||
const seiten = []
|
||||
|
||||
Reference in new issue
Block a user