feat: implement backend label print agent system for remote label rendering and job management
Build and Push Multi-Platform Images / build-and-push (push) Successful in 33s
Build and Push Multi-Platform Images / build-and-push (push) Successful in 33s
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
NotFoundException,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Post,
|
||||
Query,
|
||||
Res,
|
||||
StreamableFile,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import type { Response } from 'express';
|
||||
import { JwtOrApiKeyGuard } from '../auth/jwt-or-apikey.guard';
|
||||
import { RequirePermissions } from '../auth/permissions.decorator';
|
||||
import { Permission } from '../auth/permissions.enum';
|
||||
import { LabelPrintAgentService } from './label-print-agent.service';
|
||||
|
||||
@Controller('api/label-print-agent')
|
||||
@UseGuards(JwtOrApiKeyGuard)
|
||||
export class LabelPrintAgentController {
|
||||
constructor(private readonly service: LabelPrintAgentService) {}
|
||||
|
||||
// Manuell einen Job anlegen (Frontend → Backend)
|
||||
@Post('jobs')
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@RequirePermissions(Permission.VIEW_SCANNER)
|
||||
async createJob(
|
||||
@Body() body: { templateId: number; fieldValues?: Record<string, string> },
|
||||
) {
|
||||
const job = await this.service.createJob(body.templateId, body.fieldValues ?? {});
|
||||
return { jobId: String(job.Id) };
|
||||
}
|
||||
|
||||
// Agent: nächsten Job abholen (Polling)
|
||||
@Get('jobs/next')
|
||||
async getNextJob(@Query('agentId') agentId: string, @Res({ passthrough: true }) res: Response) {
|
||||
const job = await this.service.claimNextJob(agentId ?? 'unknown');
|
||||
if (!job) {
|
||||
res.status(HttpStatus.NO_CONTENT).send();
|
||||
return;
|
||||
}
|
||||
return {
|
||||
jobId: String(job.Id),
|
||||
labelImageBase64: job.LabelImageData ? job.LabelImageData.toString('base64') : null,
|
||||
labelImageContentType: 'image/png',
|
||||
labelWidthMm: job.LabelWidthMm,
|
||||
labelHeightMm: job.LabelHeightMm,
|
||||
};
|
||||
}
|
||||
|
||||
// Agent: Bild separat abrufen
|
||||
@Get('jobs/:id/image')
|
||||
async getImage(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Res({ passthrough: true }) res: Response,
|
||||
): Promise<StreamableFile> {
|
||||
const buf = await this.service.getJobImage(id);
|
||||
if (!buf) throw new NotFoundException('Bild nicht gefunden');
|
||||
const { Readable } = await import('stream');
|
||||
res.setHeader('Content-Type', 'image/png');
|
||||
return new StreamableFile(Readable.from(buf));
|
||||
}
|
||||
|
||||
// Agent: Druck erfolgreich
|
||||
@Post('jobs/:id/printed')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async markPrinted(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Body() body: { agentId?: string; printerName?: string },
|
||||
) {
|
||||
await this.service.markPrinted(id, body.agentId ?? 'unknown', body.printerName ?? '');
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
// Agent: Druckfehler
|
||||
@Post('jobs/:id/error')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async markError(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Body() body: { agentId?: string; printerName?: string; errorMessage?: string },
|
||||
) {
|
||||
await this.service.markError(id, body.agentId ?? 'unknown', body.printerName ?? '', body.errorMessage ?? '');
|
||||
return { ok: true };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user