This commit is contained in:
Bastian Wagner
2026-03-14 09:31:47 +01:00
parent 0d30e01a5f
commit ef4485115d
15 changed files with 157 additions and 48 deletions

View File

@@ -1,17 +1,17 @@
export class KeyHandoverPDFDataDto {
handoverId!: string;
handoverDate!: Date;
place!: string;
export class KeyHandoutPDFDataDto {
handoverId: string;
handoverDate: Date;
place: string;
giverName!: string;
giverAddress?: string;
giverName: string;
giverAddress: string;
receiverName!: string;
receiverAddress?: string;
receiverName: string;
receiverAddress: string;
keyType!: string;
keyNumber?: string;
quantity!: number;
objectDescription?: string;
notes?: string;
keyType: string;
keyNumber: string;
quantity: number;
objectDescription: string;
notes: string;
}

View File

@@ -5,3 +5,4 @@ export * from './customer.entity';
export * from './key-handout.entity';
export * from './activity.entity';
export * from './user';
export * from './key-handout-pdf-data.entity';

View File

@@ -0,0 +1,52 @@
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
import { KeyHandout } from "./key-handout.entity";
@Entity()
export class KeyHandoutPdfDataEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@ManyToOne(() => KeyHandout, handout => handout.pdfs)
handout: KeyHandout
@Column({ type: 'date' })
handoverDate: Date;
@Column({ name: 'giver_name' })
giverName: string;
@Column({ name: 'giver_address', nullable: true })
giverAddress: string;
@Column({ name: 'receiver_name' })
receiverName: string;
@Column({ name: 'receiver_address', nullable: true })
receiverAddress: string;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@Column({ name: 'file_name', nullable: true })
fileName: string;
@Column({ name: 'key_nr' })
keyNumber: string;
@Column({ type: 'int', default: 1 })
quantity: number;
@Column({ name: 'object_description', nullable: true })
objectDescription: string;
@Column({ nullable: true })
notes: string;
@UpdateDateColumn({ name: 'updatet_at' })
updatedAt: Date;
}

View File

@@ -4,11 +4,13 @@ import {
CreateDateColumn,
Entity,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Key } from './key.entity';
import { Customer } from './customer.entity';
import { User } from './user';
import { KeyHandoutPdfDataEntity } from './key-handout-pdf-data.entity';
@Entity()
export class KeyHandout {
@@ -34,8 +36,8 @@ export class KeyHandout {
user: User;
@Column({ nullable: true })
pdfFormKey: string;
@OneToMany(() => KeyHandoutPdfDataEntity, pdf => pdf.handout)
pdfs: KeyHandoutPdfDataEntity[];
@BeforeInsert()
insertTimestamp() {

View File

@@ -7,3 +7,4 @@ export * from './key.repository';
export * from './customer.repository';
export * from './activity.repository';
export * from './user.settings.repository';
export * from './key-handout-pdf-data.repository';

View File

@@ -0,0 +1,10 @@
import { Injectable } from '@nestjs/common';
import { Repository, DataSource } from 'typeorm';
import { KeyHandoutPdfDataEntity } from '../entitites';
@Injectable()
export class KeyHandoutPdfDataEntityRepository extends Repository<KeyHandoutPdfDataEntity> {
constructor(dataSource: DataSource) {
super(KeyHandoutPdfDataEntity, dataSource.createEntityManager());
}
}

View File

@@ -8,7 +8,6 @@ import {
Put,
Req,
Res,
Sse,
UseGuards,
} from '@nestjs/common';
import { Response } from 'express';
@@ -16,7 +15,7 @@ import { KeyService } from './key.service';
import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface';
import { AuthGuard } from 'src/core/guards/auth.guard';
import { Key } from 'src/model/entitites';
import { KeyHandoverPDFDataDto } from 'src/model/dto/key-handover.dto';
import { KeyHandoutPDFDataDto } from 'src/model/dto/key-handover.dto';
@UseGuards(AuthGuard)
@@ -91,7 +90,7 @@ export class KeyController {
}
@Post('pdf')
async generatePdf(@Body() dto: KeyHandoverPDFDataDto, @Res() res: Response) {
async generatePdf(@Body() dto: KeyHandoutPDFDataDto, @Res() res: Response) {
const { pdf, response } = await this.service.createPdf(dto);
res.setHeader(

View File

@@ -2,8 +2,8 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { Customer, Cylinder, Key, User } from 'src/model/entitites';
import {
CylinderRepository,
KeyHandoutPdfDataEntityRepository,
KeyRepository,
KeySystemRepository,
} from 'src/model/repositories';
import { KeyHandoutRepository } from 'src/model/repositories/key-handout.repository';
import { ActivityHelperService } from 'src/shared/service/activity.logger.service';
@@ -12,9 +12,7 @@ import { FindOperator, IsNull, Not } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { MailService } from '../mail/mail.service';
import { SseService } from '../realtime/sse/sse.service';
import { KeyHandoverPDFDataDto } from 'src/model/dto/key-handover.dto';
import { firstValueFrom } from 'rxjs';
import { HttpService } from '@nestjs/axios';
import { KeyHandoutPDFDataDto } from 'src/model/dto/key-handover.dto';
import { PdfService } from 'src/shared/storage/services/pdf/pdf.service';
import { AxiosResponse } from 'axios';
@@ -29,8 +27,11 @@ export class KeyService {
private readonly configService: ConfigService,
private readonly mailService: MailService,
private readonly sseService: SseService,
private readonly pdfService: PdfService
) { }
private readonly pdfService: PdfService,
private readonly handoutPDFRepo: KeyHandoutPdfDataEntityRepository
) {
// this.getLatestHandoverPDF('a4f4f32b-96de-4f20-b5bd-ac3a128da121')
}
get isDevelopMode(): boolean {
return (this.configService.get('DEVELOP_MODE') || '').toLowerCase() == 'true';
@@ -168,7 +169,7 @@ export class KeyService {
timestamp: { direction: 'DESC' },
created: { direction: 'DESC' },
},
relations: ['customer'],
relations: ['customer', 'pdfs'],
});
}
@@ -234,12 +235,34 @@ export class KeyService {
return k;
}
async createPdf(dto: KeyHandoverPDFDataDto): Promise<{ pdf: Buffer, response: AxiosResponse}> {
const x = await this.pdfService.generatePDF(dto)
return x;
async createPdf(dto: KeyHandoutPDFDataDto): Promise<{ pdf: Buffer, response: AxiosResponse}> {
const handout = await this.handoverRepo.findOneByOrFail({ id: dto.handoverId })
const data = {
...dto,
handout
}
data.handoverDate = new Date(data.handoverDate);
const entity = await this.handoutPDFRepo.save(this.handoutPDFRepo.create(data));
const fileName = await this.pdfService.generatePDF(dto);
entity.createdAt = new Date();
entity.fileName = fileName;
await this.handoutPDFRepo.save(entity);
const file = await this.pdfService.getPDFByHandoverKey(fileName);
return file;
}
async getPdf(handoverId: string): Promise<{ pdf: Buffer, response: AxiosResponse}> {
return this.pdfService.getPDFByHandoverKey(handoverId);
}
async getLatestHandoverPDF(handoverId: string) {
const pdf = await this.handoutPDFRepo.findOne({
where: { handout: { id: handoverId}},
order: {createdAt: 'DESC' },
});
console.log(pdf)
}
}

View File

@@ -6,6 +6,7 @@ import {
Cylinder,
Key,
KeyHandout,
KeyHandoutPdfDataEntity,
Role,
SSOUser,
User,
@@ -18,6 +19,7 @@ import {
ActivityRepository,
CustomerRepository,
CylinderRepository,
KeyHandoutPdfDataEntityRepository,
KeyRepository,
KeySystemRepository,
RoleRepository,
@@ -41,7 +43,8 @@ const ENTITIES = [
Activity,
EmailLog,
UserSettings,
Impersonation
Impersonation,
KeyHandoutPdfDataEntity
];
const REPOSITORIES = [
UserRepository,
@@ -55,7 +58,8 @@ const REPOSITORIES = [
ActivityRepository,
EmailLogRepository,
UserSettingsRepository,
ImpersonationRepository
ImpersonationRepository,
KeyHandoutPdfDataEntityRepository
];
@Module({

View File

@@ -1,9 +1,9 @@
import { HttpService } from '@nestjs/axios';
import { Injectable } from '@nestjs/common';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AxiosResponse } from 'axios';
import { firstValueFrom } from 'rxjs';
import { KeyHandoverPDFDataDto } from 'src/model/dto/key-handover.dto';
import { KeyHandoutPDFDataDto } from 'src/model/dto/key-handover.dto';
import { KeyHandoutRepository } from 'src/model/repositories/key-handout.repository';
@Injectable()
@@ -13,17 +13,13 @@ export class PdfService {
constructor(
private readonly configService: ConfigService,
private readonly httpService: HttpService,
private readonly handoverRepo: KeyHandoutRepository
private readonly httpService: HttpService
) { }
public async generatePDF(dto: KeyHandoverPDFDataDto): Promise<{ pdf: Buffer, response: AxiosResponse}> {
const h = await this.handoverRepo.findOneByOrFail({ id: dto.handoverId });
public async generatePDF(dto: KeyHandoutPDFDataDto): Promise<string> {
const response = await this.post(`${this.STORAGESERVER}/pdf/keyhandover`, dto);
if (response?.data == null) { return; }
h.pdfFormKey = response.data;
await this.handoverRepo.save(h);
return this.getPDFByHandoverKey(response.data)
if (response?.data == null) { throw new HttpException('Konnte nicht erstellt werden', HttpStatus.INTERNAL_SERVER_ERROR) }
return response.data;
}

View File

@@ -3,10 +3,9 @@ import { StorageService } from './storage.service';
import { HttpModule } from '@nestjs/axios';
import { ConfigModule } from '@nestjs/config';
import { PdfService } from './services/pdf/pdf.service';
import { DatabaseModule } from '../database/database.module';
@Module({
imports: [HttpModule, ConfigModule, DatabaseModule],
imports: [HttpModule, ConfigModule],
providers: [StorageService, PdfService ],
exports: [ StorageService, PdfService ]
})

View File

@@ -1,3 +1,8 @@
@if(isLoading) {
<div class="loading-overlay">
<mat-spinner></mat-spinner>
</div>
}
<h2 mat-dialog-title>Übergabeprotokoll</h2>
<mat-dialog-content>
<div class="text" style="margin: 0 0 24px 0;">

View File

@@ -8,10 +8,11 @@ import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { IKeyHandoverPDF } from '../../../../model/interface/handover-pdf.interface';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
@Component({
selector: 'app-create-handover-pdf-dialog',
imports: [MatDialogModule, FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, MatInputModule, MatButtonModule, MatIconModule],
imports: [MatDialogModule, FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, MatInputModule, MatButtonModule, MatIconModule, MatProgressSpinnerModule],
templateUrl: './create-handover-pdf-dialog.component.html',
styleUrl: './create-handover-pdf-dialog.component.scss',
})

View File

@@ -83,11 +83,11 @@ export class HandoverDialogComponent extends AgGridContainerComponent {
{
colId: 'download',
headerName: 'PDF',
field: 'pdfFormKey',
field: 'pdfs',
width: 60,
tooltipValueGetter: () => 'Übergabeprotokoll herunterladen',
cellRenderer: () => '',
cellClass: (data: any) => data.value ? 'download-pdf' : '',
cellClass: (data: any) => data.value.length ? 'download-pdf' : '',
onCellClicked: (event) => {
this.downloadHandoverPDF(event.value)
},
@@ -232,9 +232,10 @@ export class HandoverDialogComponent extends AgGridContainerComponent {
//this.downloadHandoverPDF('5b1f92d9-c66c-49ad-b654-b9a9a6a59752')
}
downloadHandoverPDF(key: string) {
if (!key) { return; }
this.api.getHandoverPdf(key)
downloadHandoverPDF(pdfs: any[]) {
if (!pdfs || pdfs.length < 1) { return; }
this.api.getHandoverPdf(pdfs[0]['fileName'])
}
}

View File

@@ -246,4 +246,19 @@ div.ag-row {
display: flex;
justify-content: space-between;
gap: 12px;
}
.loading-overlay {
position: absolute;
height: 100%;
width: 100%;
overflow: hidden;
padding: 0;
margin: 0;
box-sizing: border-box;
z-index: 2;
background: rgba(255, 255, 255, 0.5);
display: flex;
align-items: center;
justify-content: center;
}