feat(export): Bestandsbuch für Tierarzneimittel nach Art. 108 VO (EU) 2019/6

- Treatment records supplier, purchase proof and prescribing vet, and
  keeps the apiary the colony stood at on the treatment day.
- Holder name and address in site settings (never in public output;
  regression test in public.service.spec).
- treatment-log.pdf: one sheet per apiary, identical treatments grouped,
  missing mandatory fields printed as FEHLT, uncertain locations marked.
- Shared PDF table helpers extracted from the record card.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-09-28 11:10:07 +02:00
1 parent f263ec79f2
commit 0d23963f07
24 files changed
+941 -113

No files matched your search

@@ -1,5 +1,11 @@
import { ApiPropertyOptional } from '@nestjs/swagger';
import { IsOptional, IsUrl, MaxLength, ValidateIf } from 'class-validator';
import {
IsOptional,
IsString,
IsUrl,
MaxLength,
ValidateIf,
} from 'class-validator';
// An empty string clears the link (stored as null); anything else must be a
// real URL - ValidateIf skips the @IsUrl check only for the empty-string
@@ -32,4 +38,18 @@ export class UpdateSiteSettingsDto {
@IsUrl({ require_protocol: true })
@MaxLength(300)
websiteUrl?: string;
@ApiPropertyOptional({ description: 'Name des Bienenhalters (Bestandsbuch)' })
@IsOptional()
@IsString()
@MaxLength(200)
holderName?: string;
@ApiPropertyOptional({
description: 'Anschrift des Bienenhalters (Bestandsbuch)',
})
@IsOptional()
@IsString()
@MaxLength(300)
holderAddress?: string;
}
@@ -52,6 +52,14 @@ export class SiteSettingsService {
dto.websiteUrl !== undefined
? emptyToNull(dto.websiteUrl)
: undefined,
holderName:
dto.holderName !== undefined
? emptyToNull(dto.holderName.trim())
: undefined,
holderAddress:
dto.holderAddress !== undefined
? emptyToNull(dto.holderAddress.trim())
: undefined,
},
});
await this.auditLog.record({