import { Injectable, Logger, ForbiddenException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { DocumentType } from '../database/entities/document-type.entity'; import { PaperlessService } from '../paperless/paperless.service'; const FREIGABE_FIELD_ID = 15; const ZAHLUNG_FIELD_ID = 16; const FREIGABE_WERT_FREIGEGEBEN = 'freigegeben'; export type ZahlungFilter = 'ausstehend' | 'freigegeben' | 'alle'; @Injectable() export class ZahlungService { private readonly logger = new Logger(ZahlungService.name); constructor( @InjectRepository(DocumentType) private readonly documentTypeRepo: Repository, private readonly paperlessService: PaperlessService, ) {} async getZahlungDocuments( page: number, pageSize: number, filter: ZahlungFilter, ) { const docTypes = await this.documentTypeRepo.find({ where: { FreigabeErforderlich: true as any }, }); if (docTypes.length === 0) { return { count: 0, results: [] }; } const docTypeIds = docTypes.map((dt) => dt.DocumentTypeId).join(','); const params: Record = { page: 1, page_size: 9999, document_type__id__in: docTypeIds, ordering: '-created', truncate_content: true, }; let allDocs: any[]; try { const result = await this.paperlessService.getDocuments(params); allDocs = result.results ?? []; } catch (err: any) { this.logger.warn( 'Fehler beim Laden der Belege für Zahlung', err?.message, ); return { count: 0, results: [] }; } const filtered = this.applyFilter(allDocs, filter); const start = (page - 1) * pageSize; return { count: filtered.length, results: filtered.slice(start, start + pageSize), }; } private applyFilter(docs: any[], filter: ZahlungFilter): any[] { if (filter === 'alle') return docs; return docs.filter((doc: any) => { const freigabeValue = this.getCfValue(doc, FREIGABE_FIELD_ID); const istFreigegeben = freigabeValue === FREIGABE_WERT_FREIGEGEBEN; if (filter === 'freigegeben') return istFreigegeben; // 'ausstehend': freigegeben aber noch nicht bezahlt const zahlungValue = this.getCfValue(doc, ZAHLUNG_FIELD_ID); return istFreigegeben && !zahlungValue; }); } private getCfValue(doc: any, fieldId: number): string | null { const cf = (doc.custom_fields ?? []).find((f: any) => f.field === fieldId); if (!cf || cf.value === null || cf.value === undefined || cf.value === '') return null; if (typeof cf.value === 'object') { return ( String(cf.value?.id ?? cf.value?.value ?? cf.value?.label ?? '') || null ); } return String(cf.value); } async setZahlung(documentId: number, value: string | null) { const doc = await this.paperlessService.getDocument(documentId); const freigabeValue = this.getCfValue(doc, FREIGABE_FIELD_ID); if (freigabeValue !== FREIGABE_WERT_FREIGEGEBEN) { throw new ForbiddenException( 'Zahlung kann nur für freigegebene Belege gesetzt werden', ); } const customFields: any[] = [...(doc.custom_fields ?? [])]; const existing = customFields.find( (f: any) => f.field === ZAHLUNG_FIELD_ID, ); if (existing) { existing.value = value; } else if (value !== null && value !== '') { customFields.push({ field: ZAHLUNG_FIELD_ID, value }); } await this.paperlessService.updateDocument(documentId, { custom_fields: customFields, }); return { success: true }; } async getZahlungOptions(): Promise<{ id: string; label: string }[]> { const fields = await this.paperlessService.getCustomFields(); const field = fields.find((f: any) => f.id === ZAHLUNG_FIELD_ID); if (!field) return []; const rawOptions: any[] = field.extra_data?.select_options ?? []; return rawOptions .filter((o) => o !== null && o !== undefined && o !== '') .map((o) => { if (typeof o === 'object') { return { id: String(o.id ?? o.value ?? o.label ?? ''), label: String(o.label ?? o.name ?? o.id ?? ''), }; } return { id: String(o), label: String(o) }; }) .filter((o) => o.id !== ''); } }