chore: apply ESLint auto-fix across entire backend
Build and Push Multi-Platform Images / build-and-push (push) Successful in 41s
Build and Push Multi-Platform Images / build-and-push (push) Successful in 41s
Reformats code style (line breaks, indentation, type annotations) without changing logic. Also includes minor feature additions bundled in the same lint run (stats service, user-settings groups, agrarmonitor polling improvements). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
4c75a1ded2
commit
dad0136365
74 files changed
+4022
-1052
No files matched your search
@@ -10,10 +10,15 @@ export class ExportService {
|
||||
private readonly logger = new Logger(ExportService.name);
|
||||
|
||||
constructor(
|
||||
@InjectRepository(ExportTarget) private readonly targetRepo: Repository<ExportTarget>,
|
||||
@InjectRepository(ExportTarget)
|
||||
private readonly targetRepo: Repository<ExportTarget>,
|
||||
) {}
|
||||
|
||||
async exportFile(targetId: number, filename: string, content: Buffer): Promise<void> {
|
||||
async exportFile(
|
||||
targetId: number,
|
||||
filename: string,
|
||||
content: Buffer,
|
||||
): Promise<void> {
|
||||
const target = await this.targetRepo.findOneByOrFail({ Id: targetId });
|
||||
|
||||
if (!target.IsActive) {
|
||||
@@ -32,7 +37,9 @@ export class ExportService {
|
||||
}
|
||||
}
|
||||
|
||||
async testConnection(targetId: number): Promise<{ success: boolean; message: string }> {
|
||||
async testConnection(
|
||||
targetId: number,
|
||||
): Promise<{ success: boolean; message: string }> {
|
||||
const target = await this.targetRepo.findOneByOrFail({ Id: targetId });
|
||||
|
||||
try {
|
||||
@@ -44,7 +51,10 @@ export class ExportService {
|
||||
await this.testWebDav(target);
|
||||
break;
|
||||
default:
|
||||
return { success: false, message: `Unbekanntes Protokoll: ${target.Protocol}` };
|
||||
return {
|
||||
success: false,
|
||||
message: `Unbekanntes Protokoll: ${target.Protocol}`,
|
||||
};
|
||||
}
|
||||
return { success: true, message: 'Verbindung erfolgreich.' };
|
||||
} catch (err: any) {
|
||||
@@ -52,7 +62,11 @@ export class ExportService {
|
||||
}
|
||||
}
|
||||
|
||||
private async uploadFtp(target: ExportTarget, filename: string, content: Buffer): Promise<void> {
|
||||
private async uploadFtp(
|
||||
target: ExportTarget,
|
||||
filename: string,
|
||||
content: Buffer,
|
||||
): Promise<void> {
|
||||
const client = new ftp.Client();
|
||||
try {
|
||||
await client.access({
|
||||
@@ -89,7 +103,11 @@ export class ExportService {
|
||||
}
|
||||
}
|
||||
|
||||
private async uploadWebDav(target: ExportTarget, filename: string, content: Buffer): Promise<void> {
|
||||
private async uploadWebDav(
|
||||
target: ExportTarget,
|
||||
filename: string,
|
||||
content: Buffer,
|
||||
): Promise<void> {
|
||||
const client = this.createWebDavClient(target);
|
||||
const remotePath = `${target.RemotePath || '/'}/${filename}`;
|
||||
await client.putFileContents(remotePath, content);
|
||||
|
||||
@@ -25,12 +25,24 @@ export class MailService {
|
||||
body: string;
|
||||
html?: string;
|
||||
attachments?: { filename: string; content: Buffer }[];
|
||||
smtpOverride?: { host: string; port: number; secure: boolean; user: string; pass: string; from: string };
|
||||
smtpOverride?: {
|
||||
host: string;
|
||||
port: number;
|
||||
secure: boolean;
|
||||
user: string;
|
||||
pass: string;
|
||||
from: string;
|
||||
};
|
||||
}): Promise<void> {
|
||||
let transporter = this.transporter;
|
||||
const globalFromEmail = this.configService.get<string>('SMTP_FROM', 'paperless@localhost');
|
||||
const globalFromEmail = this.configService.get<string>(
|
||||
'SMTP_FROM',
|
||||
'paperless@localhost',
|
||||
);
|
||||
const globalFromName = this.configService.get<string>('SMTP_FROM_NAME', '');
|
||||
let from = globalFromName ? `"${globalFromName}" <${globalFromEmail}>` : globalFromEmail;
|
||||
let from = globalFromName
|
||||
? `"${globalFromName}" <${globalFromEmail}>`
|
||||
: globalFromEmail;
|
||||
|
||||
if (options.smtpOverride) {
|
||||
const o = options.smtpOverride;
|
||||
@@ -53,7 +65,7 @@ export class MailService {
|
||||
subject: options.subject,
|
||||
text: options.body,
|
||||
html: options.html,
|
||||
attachments: options.attachments?.map(a => ({
|
||||
attachments: options.attachments?.map((a) => ({
|
||||
filename: a.filename,
|
||||
content: a.content,
|
||||
})),
|
||||
|
||||
@@ -11,7 +11,12 @@ import { PaperlessModule } from '../paperless/paperless.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Postprocessing, PostprocessingAction, PostprocessingLog, ExportTarget]),
|
||||
TypeOrmModule.forFeature([
|
||||
Postprocessing,
|
||||
PostprocessingAction,
|
||||
PostprocessingLog,
|
||||
ExportTarget,
|
||||
]),
|
||||
forwardRef(() => PaperlessModule),
|
||||
],
|
||||
providers: [PostprocessingService, MailService, ExportService],
|
||||
|
||||
@@ -6,12 +6,39 @@ import { PostprocessingAction } from '../database/entities/postprocessing-action
|
||||
import { PaperlessService } from '../paperless/paperless.service';
|
||||
|
||||
const mockRules: Partial<Postprocessing>[] = [
|
||||
{ Id: 1, Name: 'Rule1', DocumentTypeId: 5, CorrespondentId: null, OwnerId: null, TagId: null, Order: 1, IsActive: true, NoFurther: false },
|
||||
{ Id: 2, Name: 'StopRule', DocumentTypeId: null, CorrespondentId: null, OwnerId: null, TagId: null, Order: 2, IsActive: true, NoFurther: true },
|
||||
{
|
||||
Id: 1,
|
||||
Name: 'Rule1',
|
||||
DocumentTypeId: 5,
|
||||
CorrespondentId: null,
|
||||
OwnerId: null,
|
||||
TagId: null,
|
||||
Order: 1,
|
||||
IsActive: true,
|
||||
NoFurther: false,
|
||||
},
|
||||
{
|
||||
Id: 2,
|
||||
Name: 'StopRule',
|
||||
DocumentTypeId: null,
|
||||
CorrespondentId: null,
|
||||
OwnerId: null,
|
||||
TagId: null,
|
||||
Order: 2,
|
||||
IsActive: true,
|
||||
NoFurther: true,
|
||||
},
|
||||
];
|
||||
|
||||
const mockActions: Partial<PostprocessingAction>[] = [
|
||||
{ Id: 1, PostprocessingId: 1, ActionType: 2, Content: '99', Order: 1, IsActive: true },
|
||||
{
|
||||
Id: 1,
|
||||
PostprocessingId: 1,
|
||||
ActionType: 2,
|
||||
Content: '99',
|
||||
Order: 1,
|
||||
IsActive: true,
|
||||
},
|
||||
];
|
||||
|
||||
describe('PostprocessingService', () => {
|
||||
@@ -29,7 +56,10 @@ describe('PostprocessingService', () => {
|
||||
providers: [
|
||||
PostprocessingService,
|
||||
{ provide: getRepositoryToken(Postprocessing), useValue: ppRepo },
|
||||
{ provide: getRepositoryToken(PostprocessingAction), useValue: ppActionRepo },
|
||||
{
|
||||
provide: getRepositoryToken(PostprocessingAction),
|
||||
useValue: ppActionRepo,
|
||||
},
|
||||
{ provide: PaperlessService, useValue: paperlessService },
|
||||
],
|
||||
}).compile();
|
||||
@@ -58,7 +88,9 @@ describe('PostprocessingService', () => {
|
||||
where: { PostprocessingId: 1, IsActive: true },
|
||||
order: { Order: 'ASC' },
|
||||
});
|
||||
expect(paperlessService.updateDocument).toHaveBeenCalledWith(100, { tags: [99] });
|
||||
expect(paperlessService.updateDocument).toHaveBeenCalledWith(100, {
|
||||
tags: [99],
|
||||
});
|
||||
});
|
||||
|
||||
it('evaluate stops at NoFurther rule', async () => {
|
||||
@@ -72,7 +104,11 @@ describe('PostprocessingService', () => {
|
||||
it('evaluate skips non-matching rules', async () => {
|
||||
// documentTypeId=999 doesn't match Rule1 (requires 5) but matches Rule2 (no filter)
|
||||
ppActionRepo.find.mockResolvedValue([]);
|
||||
await service.evaluate({ documentId: 100, documentTypeId: 999, tagIds: [] });
|
||||
await service.evaluate({
|
||||
documentId: 100,
|
||||
documentTypeId: 999,
|
||||
tagIds: [],
|
||||
});
|
||||
|
||||
// Rule1 skipped, Rule2 matched → only 1 action lookup
|
||||
expect(ppActionRepo.find).toHaveBeenCalledTimes(1);
|
||||
|
||||
@@ -2,7 +2,11 @@ import { Injectable, Logger, Inject, forwardRef } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Postprocessing, type FilterGroup, type FilterCondition } from '../database/entities/postprocessing.entity';
|
||||
import {
|
||||
Postprocessing,
|
||||
type FilterGroup,
|
||||
type FilterCondition,
|
||||
} from '../database/entities/postprocessing.entity';
|
||||
import { PostprocessingAction } from '../database/entities/postprocessing-action.entity';
|
||||
import { PostprocessingLog } from '../database/entities/postprocessing-log.entity';
|
||||
import { PaperlessService } from '../paperless/paperless.service';
|
||||
@@ -20,15 +24,22 @@ export class PostprocessingService {
|
||||
private documentTypesCache: { data: any[]; expires: number } | null = null;
|
||||
|
||||
constructor(
|
||||
@InjectRepository(Postprocessing) private readonly ppRepo: Repository<Postprocessing>,
|
||||
@InjectRepository(PostprocessingAction) private readonly actionRepo: Repository<PostprocessingAction>,
|
||||
@InjectRepository(PostprocessingLog) private readonly logRepo: Repository<PostprocessingLog>,
|
||||
@InjectRepository(Postprocessing)
|
||||
private readonly ppRepo: Repository<Postprocessing>,
|
||||
@InjectRepository(PostprocessingAction)
|
||||
private readonly actionRepo: Repository<PostprocessingAction>,
|
||||
@InjectRepository(PostprocessingLog)
|
||||
private readonly logRepo: Repository<PostprocessingLog>,
|
||||
private readonly configService: ConfigService,
|
||||
@Inject(forwardRef(() => PaperlessService)) private readonly paperlessService: PaperlessService,
|
||||
@Inject(forwardRef(() => PaperlessService))
|
||||
private readonly paperlessService: PaperlessService,
|
||||
private readonly mailService: MailService,
|
||||
private readonly exportService: ExportService,
|
||||
) {
|
||||
this.errorTagId = this.configService.get<number>('POSTPROCESSING_ERROR_TAG', 0);
|
||||
this.errorTagId = this.configService.get<number>(
|
||||
'POSTPROCESSING_ERROR_TAG',
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
async evaluate(doc: any): Promise<void> {
|
||||
@@ -40,19 +51,29 @@ export class PostprocessingService {
|
||||
// Enrich doc with resolved names (once per evaluation)
|
||||
await this.enrichDocWithNames(doc);
|
||||
|
||||
this.logger.log(`[Postprocessing] Dokument ${doc.id} wird gegen ${rules.length} Regel(n) geprüft`);
|
||||
this.logger.log(
|
||||
`[Postprocessing] Dokument ${doc.id} wird gegen ${rules.length} Regel(n) geprüft`,
|
||||
);
|
||||
|
||||
for (const rule of rules) {
|
||||
if (!this.hasConditions(rule.FilterJson)) {
|
||||
this.logger.warn(`[Postprocessing] Regel "${rule.Name}" (ID: ${rule.Id}) hat keine Bedingungen – wird übersprungen.`);
|
||||
this.logger.warn(
|
||||
`[Postprocessing] Regel "${rule.Name}" (ID: ${rule.Id}) hat keine Bedingungen – wird übersprungen.`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
this.logger.debug(`[Postprocessing] Prüfe Regel "${rule.Name}" (ID: ${rule.Id}) für Dokument ${doc.id}`);
|
||||
this.logger.debug(
|
||||
`[Postprocessing] Prüfe Regel "${rule.Name}" (ID: ${rule.Id}) für Dokument ${doc.id}`,
|
||||
);
|
||||
const matches = this.matchesFilter(rule.FilterJson, doc);
|
||||
this.logger.log(`[Postprocessing] Regel "${rule.Name}" (ID: ${rule.Id}) → ${matches ? 'TRIFFT ZU' : 'trifft nicht zu'}`);
|
||||
this.logger.log(
|
||||
`[Postprocessing] Regel "${rule.Name}" (ID: ${rule.Id}) → ${matches ? 'TRIFFT ZU' : 'trifft nicht zu'}`,
|
||||
);
|
||||
if (!matches) continue;
|
||||
|
||||
this.logger.log(`[Postprocessing] Regel "${rule.Name}" trifft zu für Dokument ${doc.id}`);
|
||||
this.logger.log(
|
||||
`[Postprocessing] Regel "${rule.Name}" trifft zu für Dokument ${doc.id}`,
|
||||
);
|
||||
|
||||
const actions = await this.actionRepo.find({
|
||||
where: { PostprocessingId: rule.Id, IsActive: true },
|
||||
@@ -63,10 +84,18 @@ export class PostprocessingService {
|
||||
for (const action of actions) {
|
||||
try {
|
||||
await this.executeAction(action, doc);
|
||||
await this.log(rule.Id, action.Id, doc.id, 'success', `Aktion ${action.ActionType} erfolgreich`);
|
||||
await this.log(
|
||||
rule.Id,
|
||||
action.Id,
|
||||
doc.id,
|
||||
'success',
|
||||
`Aktion ${action.ActionType} erfolgreich`,
|
||||
);
|
||||
} catch (err: any) {
|
||||
hasError = true;
|
||||
this.logger.error(`Fehler bei Aktion ${action.Id} (Typ ${action.ActionType}) für Dokument ${doc.id}: ${err.message}`);
|
||||
this.logger.error(
|
||||
`Fehler bei Aktion ${action.Id} (Typ ${action.ActionType}) für Dokument ${doc.id}: ${err.message}`,
|
||||
);
|
||||
await this.log(rule.Id, action.Id, doc.id, 'error', err.message);
|
||||
}
|
||||
}
|
||||
@@ -75,9 +104,13 @@ export class PostprocessingService {
|
||||
try {
|
||||
const currentTags = new Set<number>(doc.tags || []);
|
||||
currentTags.add(this.errorTagId);
|
||||
await this.paperlessService.updateDocument(doc.id, { tags: Array.from(currentTags) });
|
||||
await this.paperlessService.updateDocument(doc.id, {
|
||||
tags: Array.from(currentTags),
|
||||
});
|
||||
} catch (tagErr: any) {
|
||||
this.logger.error(`Konnte Error-Tag ${this.errorTagId} nicht setzen für Dokument ${doc.id}: ${tagErr.message}`);
|
||||
this.logger.error(
|
||||
`Konnte Error-Tag ${this.errorTagId} nicht setzen für Dokument ${doc.id}: ${tagErr.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,8 +125,8 @@ export class PostprocessingService {
|
||||
|
||||
private hasConditions(filter: FilterGroup): boolean {
|
||||
if (!filter || !filter.rules || filter.rules.length === 0) return false;
|
||||
return filter.rules.some(rule => {
|
||||
if ('combinator' in rule) return this.hasConditions(rule as FilterGroup);
|
||||
return filter.rules.some((rule) => {
|
||||
if ('combinator' in rule) return this.hasConditions(rule);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -101,11 +134,11 @@ export class PostprocessingService {
|
||||
private matchesFilter(filter: FilterGroup, doc: any): boolean {
|
||||
if (!filter || !filter.rules || filter.rules.length === 0) return false;
|
||||
|
||||
const results = filter.rules.map(rule => {
|
||||
const results = filter.rules.map((rule) => {
|
||||
if ('combinator' in rule) {
|
||||
return this.matchesFilter(rule as FilterGroup, doc);
|
||||
return this.matchesFilter(rule, doc);
|
||||
}
|
||||
return this.evaluateCondition(rule as FilterCondition, doc);
|
||||
return this.evaluateCondition(rule, doc);
|
||||
});
|
||||
|
||||
return filter.combinator === 'AND'
|
||||
@@ -139,7 +172,9 @@ export class PostprocessingService {
|
||||
if (cond.field === 'tag') {
|
||||
result = Array.isArray(actual) && actual.includes(Number(expected));
|
||||
} else {
|
||||
result = String(actual ?? '').toLowerCase().includes(String(expected ?? '').toLowerCase());
|
||||
result = String(actual ?? '')
|
||||
.toLowerCase()
|
||||
.includes(String(expected ?? '').toLowerCase());
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -147,7 +182,9 @@ export class PostprocessingService {
|
||||
if (cond.field === 'tag') {
|
||||
result = !Array.isArray(actual) || !actual.includes(Number(expected));
|
||||
} else {
|
||||
result = !String(actual ?? '').toLowerCase().includes(String(expected ?? '').toLowerCase());
|
||||
result = !String(actual ?? '')
|
||||
.toLowerCase()
|
||||
.includes(String(expected ?? '').toLowerCase());
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -173,7 +210,7 @@ export class PostprocessingService {
|
||||
}
|
||||
|
||||
this.logger.debug(
|
||||
`[Postprocessing] Bedingung: ${cond.field} ${cond.operator} "${expected}" | Istwert: "${Array.isArray(actual) ? actual.join(',') : actual}" → ${result ? 'WAHR' : 'FALSCH'}`
|
||||
`[Postprocessing] Bedingung: ${cond.field} ${cond.operator} "${expected}" | Istwert: "${Array.isArray(actual) ? actual.join(',') : actual}" → ${result ? 'WAHR' : 'FALSCH'}`,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
@@ -196,7 +233,9 @@ export class PostprocessingService {
|
||||
// Custom field: "custom_field_<id>"
|
||||
if (field.startsWith('custom_field_')) {
|
||||
const fieldId = parseInt(field.replace('custom_field_', ''), 10);
|
||||
const cf = (doc.custom_fields || []).find((f: any) => f.field === fieldId);
|
||||
const cf = (doc.custom_fields || []).find(
|
||||
(f: any) => f.field === fieldId,
|
||||
);
|
||||
return cf?.value ?? null;
|
||||
}
|
||||
return null;
|
||||
@@ -205,7 +244,10 @@ export class PostprocessingService {
|
||||
|
||||
// ── Action Execution ─────────────────────────────────────────────
|
||||
|
||||
private async executeAction(action: PostprocessingAction, doc: any): Promise<void> {
|
||||
private async executeAction(
|
||||
action: PostprocessingAction,
|
||||
doc: any,
|
||||
): Promise<void> {
|
||||
const content = action.Content;
|
||||
|
||||
switch (action.ActionType) {
|
||||
@@ -233,15 +275,26 @@ export class PostprocessingService {
|
||||
}
|
||||
|
||||
private async getCachedCorrespondents(): Promise<any[]> {
|
||||
if (!this.correspondentsCache || Date.now() > this.correspondentsCache.expires) {
|
||||
const response = await this.paperlessService.getCorrespondents({ page_size: 9999 });
|
||||
this.correspondentsCache = { data: response.results, expires: Date.now() + CACHE_TTL_MS };
|
||||
if (
|
||||
!this.correspondentsCache ||
|
||||
Date.now() > this.correspondentsCache.expires
|
||||
) {
|
||||
const response = await this.paperlessService.getCorrespondents({
|
||||
page_size: 9999,
|
||||
});
|
||||
this.correspondentsCache = {
|
||||
data: response.results,
|
||||
expires: Date.now() + CACHE_TTL_MS,
|
||||
};
|
||||
}
|
||||
return this.correspondentsCache.data;
|
||||
}
|
||||
|
||||
private async getCachedDocumentTypes(): Promise<any[]> {
|
||||
if (!this.documentTypesCache || Date.now() > this.documentTypesCache.expires) {
|
||||
if (
|
||||
!this.documentTypesCache ||
|
||||
Date.now() > this.documentTypesCache.expires
|
||||
) {
|
||||
const data = await this.paperlessService.getDocumentTypes();
|
||||
this.documentTypesCache = { data, expires: Date.now() + CACHE_TTL_MS };
|
||||
}
|
||||
@@ -272,13 +325,18 @@ export class PostprocessingService {
|
||||
'{titel}': doc.title ?? '',
|
||||
'{korrespondent}': String(doc.correspondent ?? ''),
|
||||
'{absender}': String(doc.correspondent ?? ''),
|
||||
'{korrespondent_name}': doc._correspondentName ?? String(doc.correspondent ?? ''),
|
||||
'{absender_name}': doc._correspondentName ?? String(doc.correspondent ?? ''),
|
||||
'{korrespondent_name}':
|
||||
doc._correspondentName ?? String(doc.correspondent ?? ''),
|
||||
'{absender_name}':
|
||||
doc._correspondentName ?? String(doc.correspondent ?? ''),
|
||||
'{dokumenttyp}': String(doc.document_type ?? ''),
|
||||
'{dokumenttyp_name}': doc._documentTypeName ?? String(doc.document_type ?? ''),
|
||||
'{dokumenttyp_name}':
|
||||
doc._documentTypeName ?? String(doc.document_type ?? ''),
|
||||
'{besitzer}': String(doc.owner ?? ''),
|
||||
'{ablagenummer}': String(doc.archive_serial_number ?? ''),
|
||||
'{datum}': created ? `${created.getFullYear()}-${String(created.getMonth() + 1).padStart(2, '0')}-${String(created.getDate()).padStart(2, '0')}` : '',
|
||||
'{datum}': created
|
||||
? `${created.getFullYear()}-${String(created.getMonth() + 1).padStart(2, '0')}-${String(created.getDate()).padStart(2, '0')}`
|
||||
: '',
|
||||
'{jahr}': created ? String(created.getFullYear()) : '',
|
||||
'{monat}': created ? String(created.getMonth() + 1).padStart(2, '0') : '',
|
||||
'{tag}': created ? String(created.getDate()).padStart(2, '0') : '',
|
||||
@@ -289,7 +347,7 @@ export class PostprocessingService {
|
||||
};
|
||||
|
||||
// Custom Fields: {custom_field_<id>}
|
||||
for (const cf of (doc.custom_fields || [])) {
|
||||
for (const cf of doc.custom_fields || []) {
|
||||
replacements[`{custom_field_${cf.field}}`] = String(cf.value ?? '');
|
||||
}
|
||||
|
||||
@@ -310,16 +368,32 @@ export class PostprocessingService {
|
||||
return `${doc.title || `document_${doc.id}`}.pdf`;
|
||||
}
|
||||
|
||||
private async handleExport(content: Record<string, any>, doc: any): Promise<void> {
|
||||
private async handleExport(
|
||||
content: Record<string, any>,
|
||||
doc: any,
|
||||
): Promise<void> {
|
||||
const fileType = content.fileType || 'archive';
|
||||
const buffer = await this.paperlessService.downloadDocument(doc.id, fileType);
|
||||
const buffer = await this.paperlessService.downloadDocument(
|
||||
doc.id,
|
||||
fileType,
|
||||
);
|
||||
const filename = this.buildFilename(content.filenameTemplate, doc);
|
||||
await this.exportService.exportFile(content.exportTargetId, filename, buffer);
|
||||
await this.exportService.exportFile(
|
||||
content.exportTargetId,
|
||||
filename,
|
||||
buffer,
|
||||
);
|
||||
}
|
||||
|
||||
private async handleMail(content: Record<string, any>, doc: any): Promise<void> {
|
||||
private async handleMail(
|
||||
content: Record<string, any>,
|
||||
doc: any,
|
||||
): Promise<void> {
|
||||
const fileType = content.fileType || 'archive';
|
||||
const buffer = await this.paperlessService.downloadDocument(doc.id, fileType);
|
||||
const buffer = await this.paperlessService.downloadDocument(
|
||||
doc.id,
|
||||
fileType,
|
||||
);
|
||||
const filename = this.buildFilename(content.filenameTemplate, doc);
|
||||
|
||||
const subject = content.subject
|
||||
@@ -337,18 +411,26 @@ export class PostprocessingService {
|
||||
});
|
||||
}
|
||||
|
||||
private async handleTags(content: Record<string, any>, doc: any): Promise<void> {
|
||||
private async handleTags(
|
||||
content: Record<string, any>,
|
||||
doc: any,
|
||||
): Promise<void> {
|
||||
const currentTags = new Set<number>(doc.tags || []);
|
||||
const addTags: number[] = content.addTags || [];
|
||||
const removeTags: number[] = content.removeTags || [];
|
||||
|
||||
addTags.forEach(t => currentTags.add(t));
|
||||
removeTags.forEach(t => currentTags.delete(t));
|
||||
addTags.forEach((t) => currentTags.add(t));
|
||||
removeTags.forEach((t) => currentTags.delete(t));
|
||||
|
||||
await this.paperlessService.updateDocument(doc.id, { tags: Array.from(currentTags) });
|
||||
await this.paperlessService.updateDocument(doc.id, {
|
||||
tags: Array.from(currentTags),
|
||||
});
|
||||
}
|
||||
|
||||
private async handleCustomField(content: Record<string, any>, doc: any): Promise<void> {
|
||||
private async handleCustomField(
|
||||
content: Record<string, any>,
|
||||
doc: any,
|
||||
): Promise<void> {
|
||||
const customFields = [...(doc.custom_fields || [])];
|
||||
const existing = customFields.find((f: any) => f.field === content.fieldId);
|
||||
|
||||
@@ -358,13 +440,23 @@ export class PostprocessingService {
|
||||
customFields.push({ field: content.fieldId, value: content.value });
|
||||
}
|
||||
|
||||
await this.paperlessService.updateDocument(doc.id, { custom_fields: customFields });
|
||||
await this.paperlessService.updateDocument(doc.id, {
|
||||
custom_fields: customFields,
|
||||
});
|
||||
}
|
||||
|
||||
private async handleWebhook(content: Record<string, any>, doc: any): Promise<void> {
|
||||
private async handleWebhook(
|
||||
content: Record<string, any>,
|
||||
doc: any,
|
||||
): Promise<void> {
|
||||
const method = (content.method || 'POST').toUpperCase();
|
||||
const headers = content.headers || {};
|
||||
const body = { documentId: doc.id, title: doc.title, tags: doc.tags, ...(content.body || {}) };
|
||||
const body = {
|
||||
documentId: doc.id,
|
||||
title: doc.title,
|
||||
tags: doc.tags,
|
||||
...(content.body || {}),
|
||||
};
|
||||
|
||||
await axios({
|
||||
method,
|
||||
@@ -378,7 +470,10 @@ export class PostprocessingService {
|
||||
this.logger.log(`Webhook ${method} → ${content.url}`);
|
||||
}
|
||||
|
||||
private async handleNote(content: Record<string, any>, doc: any): Promise<void> {
|
||||
private async handleNote(
|
||||
content: Record<string, any>,
|
||||
doc: any,
|
||||
): Promise<void> {
|
||||
if (!content.note) return;
|
||||
const resolvedNote = this.resolveTemplate(content.note, doc);
|
||||
await this.paperlessService.addNote(doc.id, resolvedNote);
|
||||
@@ -386,7 +481,13 @@ export class PostprocessingService {
|
||||
|
||||
// ── Logging ──────────────────────────────────────────────────────
|
||||
|
||||
private async log(ppId: number, actionId: number | null, docId: number, status: string, message: string): Promise<void> {
|
||||
private async log(
|
||||
ppId: number,
|
||||
actionId: number | null,
|
||||
docId: number,
|
||||
status: string,
|
||||
message: string,
|
||||
): Promise<void> {
|
||||
const entry = this.logRepo.create({
|
||||
PostprocessingId: ppId,
|
||||
ActionId: actionId,
|
||||
|
||||
Reference in new issue
Block a user