Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -258,39 +258,42 @@ async function create() {
|
|||||||
const fieldWidth2 = 380
|
const fieldWidth2 = 380
|
||||||
const labelOffset = 0
|
const labelOffset = 0
|
||||||
// place SEPA inputs 1cm left (≈28.35pt) from previous and slightly up; adjust to align with labels
|
// place SEPA inputs 1cm left (≈28.35pt) from previous and slightly up; adjust to align with labels
|
||||||
const inputX = sepaLeft + 220 - 28.35
|
const inputX = sepaLeft + 220 - 28.35
|
||||||
// reduce vertical raise so inputs sit on same baseline as labels (previously too high)
|
// reduce vertical raise so inputs sit on same baseline as labels (previously too high)
|
||||||
const inputYAdjust = 6
|
const inputYAdjust = 6 + 5.67 // Move SEPA inputs (except date) up by additional 2mm (≈5.67pt)
|
||||||
|
// adjust page2DownShift so inputs move up by 0.75mm (net)
|
||||||
|
// 0.75mm = 0.075cm -> ~2.12625 pt
|
||||||
|
const page2DownShift = 0.075 * 28.35 // 0.075 cm -> ~2.12625 pt
|
||||||
|
|
||||||
// apply labelsShift only to the SEPA form labels/inputs so paragraphs remain unaffected
|
// apply labelsShift only to the SEPA form labels/inputs so paragraphs remain unaffected
|
||||||
let syFields = sy + labelsShift
|
let syFields = sy + labelsShift
|
||||||
page2.drawText('Mitglied (Vorname und Name)', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
page2.drawText('Mitglied (Vorname und Name)', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
||||||
form.createTextField('sepa_mitglied').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
form.createTextField('sepa_mitglied').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust - page2DownShift, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
||||||
syFields -= lineGap * 1.1
|
syFields -= lineGap * 1.1
|
||||||
|
|
||||||
page2.drawText('Kontoinhaber (Vorname und Name):', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
page2.drawText('Kontoinhaber (Vorname und Name):', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
||||||
form.createTextField('sepa_kontoinhaber').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
form.createTextField('sepa_kontoinhaber').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust - page2DownShift, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
||||||
syFields -= lineGap * 1.1
|
syFields -= lineGap * 1.1
|
||||||
|
|
||||||
page2.drawText('Straße und Hausnummer:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
page2.drawText('Straße und Hausnummer:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
||||||
form.createTextField('sepa_strasse').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
form.createTextField('sepa_strasse').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust - page2DownShift, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
||||||
syFields -= lineGap * 1.1
|
syFields -= lineGap * 1.1
|
||||||
|
|
||||||
page2.drawText('PLZ und Ort:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
page2.drawText('PLZ und Ort:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
||||||
form.createTextField('sepa_plz_ort').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
form.createTextField('sepa_plz_ort').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust - page2DownShift, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
||||||
syFields -= lineGap * 1.1
|
syFields -= lineGap * 1.1
|
||||||
|
|
||||||
page2.drawText('Kreditinstitut:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
page2.drawText('Kreditinstitut:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
||||||
form.createTextField('sepa_bank').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
form.createTextField('sepa_bank').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust - page2DownShift, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
||||||
syFields -= lineGap * 1.1
|
syFields -= lineGap * 1.1
|
||||||
|
|
||||||
page2.drawText('IBAN:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
page2.drawText('IBAN:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
||||||
form.createTextField('sepa_iban').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
form.createTextField('sepa_iban').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust - page2DownShift, width: Math.round(fieldWidth2 * fieldShrinkFactor), height: fieldHeight2, font: helv })
|
||||||
syFields -= lineGap * 1.1
|
syFields -= lineGap * 1.1
|
||||||
|
|
||||||
page2.drawText('BIC:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
page2.drawText('BIC:', { x: sepaLeft + labelOffset, y: syFields, size: small, font: helv })
|
||||||
// BIC remains full width as requested
|
// BIC remains full width as requested
|
||||||
form.createTextField('sepa_bic').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust, width: 220, height: fieldHeight2, font: helv })
|
form.createTextField('sepa_bic').addToPage(page2, { x: inputX, y: syFields - fieldHeight2 + 2 + inputYAdjust - page2DownShift, width: 220, height: fieldHeight2, font: helv })
|
||||||
syFields -= lineGap * 1.1
|
syFields -= lineGap * 1.1
|
||||||
|
|
||||||
// add signature and date lines 2cm below last field
|
// add signature and date lines 2cm below last field
|
||||||
@@ -444,6 +447,66 @@ Das Vereinsmitglied trifft die Entscheidung zur Veröffentlichung seiner Daten i
|
|||||||
py = drawWrappedOnPage3('folgende allgemeine Daten zu meiner Person:', leftX, py, normalSize, helv)
|
py = drawWrappedOnPage3('folgende allgemeine Daten zu meiner Person:', leftX, py, normalSize, helv)
|
||||||
py -= blockSpacing
|
py -= blockSpacing
|
||||||
|
|
||||||
|
// Rebuild a simple, single-column, non-overlapping form area on page 3
|
||||||
|
const formLeft = leftX
|
||||||
|
const formFieldW = 360
|
||||||
|
const formFieldH = 14
|
||||||
|
const formGap = 22
|
||||||
|
// start a bit lower to separate from the block text
|
||||||
|
py -= 28
|
||||||
|
// Row layout
|
||||||
|
const colGap = 220
|
||||||
|
// Shifts (in points): 1 cm = ~28.35 pt
|
||||||
|
const leftColShift = 0.3 * 28.35 // 0.3 cm -> ~8.505 pt
|
||||||
|
const vornameLabelShift = 1.0 * 28.35 // 1.0 cm -> ~28.35 pt
|
||||||
|
const vornameFieldShift = 1.3 * 28.35 // 1.3 cm -> ~36.855 pt
|
||||||
|
const leftColX = formLeft + leftColShift
|
||||||
|
const rightColX = formLeft + colGap
|
||||||
|
|
||||||
|
// Row 1: Name (left) and Vorname (right)
|
||||||
|
// Keep the left label at the original formLeft, move only the input field slightly right by 0.1cm
|
||||||
|
const leftInputShift = 0.35 * 28.35 // 0.35 cm -> ~9.9225 pt
|
||||||
|
// extra small horizontal nudge for all non-date inputs: 1mm
|
||||||
|
const extraHShift = 0.1 * 28.35 // 0.1 cm (1 mm) -> ~2.835 pt
|
||||||
|
// vertical shift for all input fields (including date): 0.6 cm up
|
||||||
|
const verticalFieldShift = 0.6 * 28.35 // 0.6 cm -> ~17.01 pt
|
||||||
|
// downward nudge for non-date inputs requested now: 0.2 cm -> ~5.67 pt
|
||||||
|
const nonDateDownShift = 0.2 * 28.35 // 0.2 cm -> ~5.67 pt
|
||||||
|
page3.drawText('Name:', { x: formLeft, y: py, size: normalSize, font: helv })
|
||||||
|
form.createTextField('page3_name').addToPage(page3, { x: formLeft + 70 + leftInputShift + extraHShift, y: py - formFieldH + verticalFieldShift - nonDateDownShift, width: 160, height: formFieldH, font: helv })
|
||||||
|
// Vorname label and field moved further right as requested
|
||||||
|
page3.drawText('Vorname:', { x: rightColX + vornameLabelShift, y: py, size: normalSize, font: helv })
|
||||||
|
form.createTextField('page3_vorname').addToPage(page3, { x: rightColX + 70 + vornameFieldShift + extraHShift, y: py - formFieldH + verticalFieldShift - nonDateDownShift, width: 160, height: formFieldH, font: helv })
|
||||||
|
py -= formGap
|
||||||
|
// Anschrift (full width)
|
||||||
|
page3.drawText('Anschrift:', { x: formLeft, y: py, size: normalSize, font: helv })
|
||||||
|
form.createTextField('page3_anschrift').addToPage(page3, { x: formLeft + 70 + leftInputShift + extraHShift, y: py - formFieldH + verticalFieldShift - nonDateDownShift, width: formFieldW + 40, height: formFieldH, font: helv })
|
||||||
|
py -= formGap
|
||||||
|
// Row 3: Telefonnummer (left) and E-Mail (right)
|
||||||
|
// Keep left label at formLeft, shift only the input field by leftInputShift
|
||||||
|
page3.drawText('Telefonnummer:', { x: formLeft, y: py, size: normalSize, font: helv })
|
||||||
|
form.createTextField('page3_telefon').addToPage(page3, { x: formLeft + 70 + leftInputShift + extraHShift, y: py - formFieldH + verticalFieldShift - nonDateDownShift, width: 160, height: formFieldH, font: helv })
|
||||||
|
page3.drawText('E-Mail-Adresse:', { x: rightColX + vornameLabelShift, y: py, size: normalSize, font: helv })
|
||||||
|
form.createTextField('page3_email').addToPage(page3, { x: rightColX + 70 + vornameFieldShift + extraHShift, y: py - formFieldH + verticalFieldShift - nonDateDownShift, width: 180, height: formFieldH, font: helv })
|
||||||
|
py -= formGap
|
||||||
|
// remove fax field/label per request (space preserved)
|
||||||
|
py -= formGap
|
||||||
|
py -= formGap
|
||||||
|
// Date and signature line
|
||||||
|
const dateFieldW = 120
|
||||||
|
page3.drawText('Frankfurt/Main-Harheim, den', { x: formLeft, y: py, size: normalSize, font: helv })
|
||||||
|
const dateX = formLeft + helv.widthOfTextAtSize('Frankfurt/Main-Harheim, den ', normalSize)
|
||||||
|
// date field also moves up by verticalFieldShift (but not horizontally shifted by extraHShift)
|
||||||
|
// now move the date and signature line 0.2cm down as requested
|
||||||
|
const dateFieldY = py - formFieldH + verticalFieldShift - nonDateDownShift
|
||||||
|
form.createTextField('page3_datum').addToPage(page3, { x: dateX, y: dateFieldY, width: dateFieldW, height: formFieldH, font: helv })
|
||||||
|
// signature line starts directly under the (moved) date field
|
||||||
|
page3.drawRectangle({ x: dateX, y: dateFieldY - 6, width: 300, height: 1, color: rgb(0,0,0) })
|
||||||
|
// label under signature line
|
||||||
|
const sigLabel = 'Datum, Unterschrift (bei Jugendlichen gesetzlicher Vertreter)'
|
||||||
|
const sigLabelSize = 10
|
||||||
|
page3.drawText(sigLabel, { x: dateX, y: dateFieldY - 18, size: sigLabelSize, font: helv })
|
||||||
|
|
||||||
const pdfBytes = await pdfDoc.save()
|
const pdfBytes = await pdfDoc.save()
|
||||||
fs.writeFileSync('server/templates/mitgliedschaft-fillable.pdf', pdfBytes)
|
fs.writeFileSync('server/templates/mitgliedschaft-fillable.pdf', pdfBytes)
|
||||||
console.log('Wrote server/templates/mitgliedschaft-fillable.pdf')
|
console.log('Wrote server/templates/mitgliedschaft-fillable.pdf')
|
||||||
|
|||||||
100
scripts/fill-sample-template.js
Normal file
100
scripts/fill-sample-template.js
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import fs from 'fs'
|
||||||
|
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib'
|
||||||
|
|
||||||
|
async function fill() {
|
||||||
|
const templatePath = 'server/templates/mitgliedschaft-fillable.pdf'
|
||||||
|
if (!fs.existsSync(templatePath)) {
|
||||||
|
console.error('Template not found:', templatePath)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingPdfBytes = fs.readFileSync(templatePath)
|
||||||
|
const pdfDoc = await PDFDocument.load(existingPdfBytes)
|
||||||
|
const form = pdfDoc.getForm()
|
||||||
|
|
||||||
|
// Simple sample data
|
||||||
|
const sample = {
|
||||||
|
nachname: 'Müller',
|
||||||
|
vorname: 'Anna',
|
||||||
|
strasse: 'Hauptstr. 12',
|
||||||
|
plz_ort: '60389 Frankfurt',
|
||||||
|
geburtsdatum: '01.01.1990',
|
||||||
|
telefon: '069 123456',
|
||||||
|
email: 'anna.mueller@example.de',
|
||||||
|
telefon_mobil: '0151 2345678',
|
||||||
|
mitglied_aktiv: true,
|
||||||
|
mitglied_passiv: false,
|
||||||
|
sepa_mitglied: 'Anna Müller',
|
||||||
|
sepa_kontoinhaber: 'Anna Müller',
|
||||||
|
sepa_strasse: 'Hauptstr. 12',
|
||||||
|
sepa_plz_ort: '60389 Frankfurt',
|
||||||
|
sepa_bank: 'Sparkasse',
|
||||||
|
sepa_iban: 'DE00123456781234567890',
|
||||||
|
sepa_bic: 'PBNKDEFF',
|
||||||
|
sepa_datum: '23.10.2025',
|
||||||
|
sign_datum: '23.10.2025',
|
||||||
|
page3_name: 'Müller',
|
||||||
|
page3_vorname: 'Anna',
|
||||||
|
page3_anschrift: 'Hauptstr. 12, 60389 Frankfurt',
|
||||||
|
page3_telefon: '069 123456',
|
||||||
|
page3_fax: '069 654321',
|
||||||
|
page3_email: 'anna.mueller@example.de',
|
||||||
|
page3_datum: '23.10.2025'
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeSetText(name, value) {
|
||||||
|
try {
|
||||||
|
const f = form.getTextField(name)
|
||||||
|
f.setText(value)
|
||||||
|
} catch (e) {
|
||||||
|
// ignore missing fields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
safeSetText('nachname', sample.nachname)
|
||||||
|
safeSetText('vorname', sample.vorname)
|
||||||
|
safeSetText('strasse', sample.strasse)
|
||||||
|
safeSetText('plz_ort', sample.plz_ort)
|
||||||
|
safeSetText('geburtsdatum', sample.geburtsdatum)
|
||||||
|
safeSetText('telefon', sample.telefon)
|
||||||
|
safeSetText('email', sample.email)
|
||||||
|
safeSetText('telefon_mobil', sample.telefon_mobil)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cbA = form.getCheckBox('mitglied_aktiv')
|
||||||
|
if (sample.mitglied_aktiv) cbA.check(); else cbA.uncheck()
|
||||||
|
} catch(e) {}
|
||||||
|
try {
|
||||||
|
const cbP = form.getCheckBox('mitglied_passiv')
|
||||||
|
if (sample.mitglied_passiv) cbP.check(); else cbP.uncheck()
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
safeSetText('sepa_mitglied', sample.sepa_mitglied)
|
||||||
|
safeSetText('sepa_kontoinhaber', sample.sepa_kontoinhaber)
|
||||||
|
safeSetText('sepa_strasse', sample.sepa_strasse)
|
||||||
|
safeSetText('sepa_plz_ort', sample.sepa_plz_ort)
|
||||||
|
safeSetText('sepa_bank', sample.sepa_bank)
|
||||||
|
safeSetText('sepa_iban', sample.sepa_iban)
|
||||||
|
safeSetText('sepa_bic', sample.sepa_bic)
|
||||||
|
safeSetText('sepa_datum', sample.sepa_datum)
|
||||||
|
safeSetText('sign_datum', sample.sign_datum)
|
||||||
|
|
||||||
|
// page3 fields
|
||||||
|
safeSetText('page3_name', sample.page3_name)
|
||||||
|
safeSetText('page3_vorname', sample.page3_vorname)
|
||||||
|
safeSetText('page3_anschrift', sample.page3_anschrift)
|
||||||
|
safeSetText('page3_telefon', sample.page3_telefon)
|
||||||
|
safeSetText('page3_fax', sample.page3_fax)
|
||||||
|
safeSetText('page3_email', sample.page3_email)
|
||||||
|
safeSetText('page3_datum', sample.page3_datum)
|
||||||
|
|
||||||
|
// flatten all fields
|
||||||
|
try { form.flatten() } catch (e) {}
|
||||||
|
|
||||||
|
const out = await pdfDoc.save()
|
||||||
|
if (!fs.existsSync('temp')) fs.mkdirSync('temp')
|
||||||
|
fs.writeFileSync('temp/mitgliedschaft-sample-filled.pdf', out)
|
||||||
|
console.log('Wrote temp/mitgliedschaft-sample-filled.pdf')
|
||||||
|
}
|
||||||
|
|
||||||
|
fill().catch(e => { console.error(e); process.exit(1) })
|
||||||
Binary file not shown.
BIN
temp/mitgliedschaft-sample-filled.pdf
Normal file
BIN
temp/mitgliedschaft-sample-filled.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user