Initial commit with Email Import Wizard and Task Processor updates
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Logger,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Post,
|
||||
Put,
|
||||
BadRequestException,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BarcodeTemplate, type BarcodeActionType } from '../database/entities/barcode-template.entity';
|
||||
import { RequirePermissions } from '../auth/permissions.decorator';
|
||||
import { Permission } from '../auth/permissions.enum';
|
||||
import { BarcodeScannerService } from './barcode-scanner.service';
|
||||
|
||||
const VALID_ACTIONS: BarcodeActionType[] = ['SEND_TO_PAPERLESS', 'SEND_BY_EMAIL'];
|
||||
|
||||
interface UpsertDto {
|
||||
Name?: string;
|
||||
Regex?: string;
|
||||
SplitBefore?: boolean;
|
||||
DateinameTemplate?: string | null;
|
||||
Actions?: BarcodeActionType[];
|
||||
}
|
||||
|
||||
function validate(dto: UpsertDto, partial = false): void {
|
||||
if (!partial || dto.Name !== undefined) {
|
||||
if (typeof dto.Name !== 'string' || !dto.Name.trim()) {
|
||||
throw new BadRequestException('Name ist erforderlich');
|
||||
}
|
||||
}
|
||||
if (!partial || dto.Regex !== undefined) {
|
||||
if (typeof dto.Regex !== 'string' || !dto.Regex.trim()) {
|
||||
throw new BadRequestException('Regex ist erforderlich');
|
||||
}
|
||||
try {
|
||||
new RegExp(dto.Regex);
|
||||
} catch {
|
||||
throw new BadRequestException('Regex ist ungültig');
|
||||
}
|
||||
}
|
||||
if (dto.SplitBefore !== undefined && typeof dto.SplitBefore !== 'boolean') {
|
||||
throw new BadRequestException('SplitBefore muss ein Boolean sein');
|
||||
}
|
||||
if (dto.DateinameTemplate !== undefined && dto.DateinameTemplate !== null &&
|
||||
typeof dto.DateinameTemplate !== 'string') {
|
||||
throw new BadRequestException('DateinameTemplate muss ein String sein');
|
||||
}
|
||||
if (!partial || dto.Actions !== undefined) {
|
||||
if (!Array.isArray(dto.Actions)) {
|
||||
throw new BadRequestException('Actions muss eine Liste sein');
|
||||
}
|
||||
for (const a of dto.Actions) {
|
||||
if (!VALID_ACTIONS.includes(a)) {
|
||||
throw new BadRequestException(`Unbekannte Aktion: ${a}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Controller('api/barcode-templates')
|
||||
@RequirePermissions(Permission.MANAGE_SETTINGS)
|
||||
export class BarcodeTemplatesController {
|
||||
private readonly logger = new Logger(BarcodeTemplatesController.name);
|
||||
|
||||
constructor(
|
||||
@InjectRepository(BarcodeTemplate)
|
||||
private readonly repo: Repository<BarcodeTemplate>,
|
||||
private readonly scanner: BarcodeScannerService,
|
||||
) {}
|
||||
|
||||
private triggerRescan(): void {
|
||||
this.scanner.rescanAll().catch((err) => {
|
||||
this.logger.error(`Rescan nach Template-Änderung fehlgeschlagen: ${err.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
@Get()
|
||||
async list() {
|
||||
return this.repo.find({ order: { Id: 'ASC' } });
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@Body() dto: UpsertDto) {
|
||||
validate(dto);
|
||||
const entity = this.repo.create({
|
||||
Name: dto.Name!.trim(),
|
||||
Regex: dto.Regex!,
|
||||
SplitBefore: dto.SplitBefore ?? false,
|
||||
DateinameTemplate: dto.DateinameTemplate ?? null,
|
||||
Actions: dto.Actions!,
|
||||
});
|
||||
const saved = await this.repo.save(entity);
|
||||
this.scanner.invalidateTemplates();
|
||||
this.triggerRescan();
|
||||
return saved;
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
async update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpsertDto) {
|
||||
validate(dto, true);
|
||||
const existing = await this.repo.findOneBy({ Id: id });
|
||||
if (!existing) throw new NotFoundException('Vorlage nicht gefunden');
|
||||
|
||||
const regexChanged = dto.Regex !== undefined && dto.Regex !== existing.Regex;
|
||||
|
||||
if (dto.Name !== undefined) existing.Name = dto.Name.trim();
|
||||
if (dto.Regex !== undefined) existing.Regex = dto.Regex;
|
||||
if (dto.SplitBefore !== undefined) existing.SplitBefore = dto.SplitBefore;
|
||||
if (dto.DateinameTemplate !== undefined) existing.DateinameTemplate = dto.DateinameTemplate ?? null;
|
||||
if (dto.Actions !== undefined) existing.Actions = dto.Actions;
|
||||
|
||||
const saved = await this.repo.save(existing);
|
||||
this.scanner.invalidateTemplates();
|
||||
if (regexChanged) {
|
||||
// Nur bei Regex-Änderungen rescannen — Name/Aktionen ändern nichts am Match-Set.
|
||||
this.triggerRescan();
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async remove(@Param('id', ParseIntPipe) id: number) {
|
||||
const res = await this.repo.delete(id);
|
||||
if (!res.affected) throw new NotFoundException('Vorlage nicht gefunden');
|
||||
this.scanner.invalidateTemplates();
|
||||
this.triggerRescan();
|
||||
return { ok: true };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user