From 41bfc9b8ae537b14937bc793bd205a8e864f5735 Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Thu, 4 Dec 2025 17:13:16 +0100 Subject: [PATCH 1/3] added generation function for generate pdf --- .../deliverery-note-table.ts | 21 +++++++-- .../purchase-order-table.html | 2 +- .../purchase-order-table.ts | 19 ++++++-- .../quotation-table/quotation-table.html | 2 +- .../quotation-table/quotation-table.ts | 19 +++++++- .../services/api/api/deliverynotes.service.ts | 43 +++++++++++++++++++ .../api/api/purchaseorders.service.ts | 43 +++++++++++++++++++ .../services/api/api/quotations.service.ts | 43 +++++++++++++++++++ src/app/services/file.service.ts | 31 +++++++++++++ 9 files changed, 214 insertions(+), 9 deletions(-) create mode 100644 src/app/services/file.service.ts diff --git a/src/app/components/deliverery-note-table/deliverery-note-table.ts b/src/app/components/deliverery-note-table/deliverery-note-table.ts index 3a88398..cc8e179 100644 --- a/src/app/components/deliverery-note-table/deliverery-note-table.ts +++ b/src/app/components/deliverery-note-table/deliverery-note-table.ts @@ -10,6 +10,8 @@ import {DeliverynotesService, GetDeliveryNoteDto} from "../../services/api"; import {NzNotificationService} from "ng-zorro-antd/notification"; import {firstValueFrom} from "rxjs"; import {format} from "date-fns"; +import {HttpResponse} from "@angular/common/http"; +import {FileService} from "../../services/file.service"; @Component({ selector: 'app-deliverery-note-table', @@ -27,7 +29,8 @@ import {format} from "date-fns"; }) export class DelivereryNoteTable implements OnInit { private deliveryNotesService = inject(DeliverynotesService); - private notificationService = inject(NzNotificationService) + private notificationService = inject(NzNotificationService); + private fileService = inject(FileService); deliveryNotes = signal([]); deliveryNotesLoading = signal(false); @@ -95,7 +98,19 @@ export class DelivereryNoteTable implements OnInit { await this.fetchDeliveryNotes() } - export(deliveryNote: number) { - return + async export(deliveryNoteId: number) { + try { + const pdf = await firstValueFrom( + this.deliveryNotesService.getDeliveryNotePdfEndpoint(deliveryNoteId, "response") + ); + this.fileService.downloadBlob(pdf) + } catch (e) { + console.error(e); + this.notificationService.error( + 'Erreur', + 'Impossible de générer un PDF' + ); + } } + } diff --git a/src/app/components/purchase-order-table/purchase-order-table.html b/src/app/components/purchase-order-table/purchase-order-table.html index 820d935..2779a74 100644 --- a/src/app/components/purchase-order-table/purchase-order-table.html +++ b/src/app/components/purchase-order-table/purchase-order-table.html @@ -67,7 +67,7 @@
- +
diff --git a/src/app/components/purchase-order-table/purchase-order-table.ts b/src/app/components/purchase-order-table/purchase-order-table.ts index f02072f..82f3c18 100644 --- a/src/app/components/purchase-order-table/purchase-order-table.ts +++ b/src/app/components/purchase-order-table/purchase-order-table.ts @@ -8,6 +8,7 @@ import {ModalButton} from "../modal-button/modal-button"; import {GetPurchaseOrderDto, PurchaseordersService} from "../../services/api"; import {NzNotificationService} from "ng-zorro-antd/notification"; import {firstValueFrom} from "rxjs"; +import {FileService} from "../../services/file.service"; @Component({ selector: 'app-purchase-order-table', @@ -24,7 +25,8 @@ import {firstValueFrom} from "rxjs"; }) export class PurchaseOrderTable implements OnInit { private purchaseOrdersService = inject(PurchaseordersService); - private notificationService = inject(NzNotificationService) + private notificationService = inject(NzNotificationService); + private fileService = inject(FileService); purchaseOrders = signal([]); purchaseOrdersLoading = signal(false); @@ -63,8 +65,19 @@ export class PurchaseOrderTable implements OnInit { await this.fetchPurchaseOrder(); } - export(){ - return + async export(purchaseOrderId: number){ + try { + const pdf = await firstValueFrom( + this.purchaseOrdersService.getPurchaseOrderPdfEndpoint(purchaseOrderId, "response") + ); + this.fileService.downloadBlob(pdf) + } catch (e) { + console.error(e); + this.notificationService.error( + 'Erreur', + 'Impossible de générer un PDF' + ); + } } transfer() { diff --git a/src/app/components/quotation-table/quotation-table.html b/src/app/components/quotation-table/quotation-table.html index 0e879db..84ede4d 100644 --- a/src/app/components/quotation-table/quotation-table.html +++ b/src/app/components/quotation-table/quotation-table.html @@ -65,7 +65,7 @@
- +
diff --git a/src/app/components/quotation-table/quotation-table.ts b/src/app/components/quotation-table/quotation-table.ts index 8bcb142..6c1f551 100644 --- a/src/app/components/quotation-table/quotation-table.ts +++ b/src/app/components/quotation-table/quotation-table.ts @@ -8,6 +8,7 @@ import {QuotationForm} from "../quotation-form/quotation-form"; import {GetQuotationDto, QuotationsService} from "../../services/api"; import {NzNotificationService} from "ng-zorro-antd/notification"; import {firstValueFrom} from "rxjs"; +import {FileService} from "../../services/file.service"; @Component({ selector: 'app-quotation-table', @@ -25,7 +26,8 @@ import {firstValueFrom} from "rxjs"; export class QuotationTable implements OnInit { private quotationsService = inject(QuotationsService); - private notificationService = inject(NzNotificationService) + private notificationService = inject(NzNotificationService); + private fileService = inject(FileService); quotations = signal([]); quotationsLoading = signal(false); @@ -63,5 +65,20 @@ export class QuotationTable implements OnInit { } await this.fetchQuotations(); } + + async export(quotationId: number){ + try { + const pdf = await firstValueFrom( + this.quotationsService.getQuotationPdfEndpoint(quotationId, "response") + ); + this.fileService.downloadBlob(pdf) + } catch (e) { + console.error(e); + this.notificationService.error( + 'Erreur', + 'Impossible de générer un PDF' + ); + } + } } diff --git a/src/app/services/api/api/deliverynotes.service.ts b/src/app/services/api/api/deliverynotes.service.ts index a2d7d7b..ea29226 100644 --- a/src/app/services/api/api/deliverynotes.service.ts +++ b/src/app/services/api/api/deliverynotes.service.ts @@ -260,6 +260,49 @@ export class DeliverynotesService extends BaseService { ); } + /** + * @endpoint get /API/deliveryNotes/{id}/pdf + * @param id + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public getDeliveryNotePdfEndpoint(id: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable; + public getDeliveryNotePdfEndpoint(id: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable>; + public getDeliveryNotePdfEndpoint(id: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable>; + public getDeliveryNotePdfEndpoint(id: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable { + if (id === null || id === undefined) { + throw new Error('Required parameter id was null or undefined when calling getDeliveryNotePdfEndpoint.'); + } + + let localVarHeaders = this.defaultHeaders; + + const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([ + 'application/pdf' + ]); + if (localVarHttpHeaderAcceptSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected); + } + + const localVarHttpContext: HttpContext = options?.context ?? new HttpContext(); + + const localVarTransferCache: boolean = options?.transferCache ?? true; + + + let localVarPath = `/API/deliveryNotes/${this.configuration.encodeParam({name: "id", value: id, in: "path", style: "simple", explode: false, dataType: "number", dataFormat: "int32"})}/pdf`; + const { basePath, withCredentials } = this.configuration; + return this.httpClient.request('get', `${basePath}${localVarPath}`, + { + context: localVarHttpContext, + responseType: "blob", + ...(withCredentials ? { withCredentials } : {}), + headers: localVarHeaders, + observe: observe, + ...(localVarTransferCache !== undefined ? { transferCache: localVarTransferCache } : {}), + reportProgress: reportProgress + } + ); + } + /** * @endpoint patch /API/deliveryNotes/{id} * @param id diff --git a/src/app/services/api/api/purchaseorders.service.ts b/src/app/services/api/api/purchaseorders.service.ts index 6aeaf5a..117aff2 100644 --- a/src/app/services/api/api/purchaseorders.service.ts +++ b/src/app/services/api/api/purchaseorders.service.ts @@ -194,6 +194,49 @@ export class PurchaseordersService extends BaseService { ); } + /** + * @endpoint get /API/purchaseOrders/{id}/pdf + * @param id + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public getPurchaseOrderPdfEndpoint(id: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable; + public getPurchaseOrderPdfEndpoint(id: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable>; + public getPurchaseOrderPdfEndpoint(id: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable>; + public getPurchaseOrderPdfEndpoint(id: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable { + if (id === null || id === undefined) { + throw new Error('Required parameter id was null or undefined when calling getPurchaseOrderPdfEndpoint.'); + } + + let localVarHeaders = this.defaultHeaders; + + const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([ + 'application/pdf' + ]); + if (localVarHttpHeaderAcceptSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected); + } + + const localVarHttpContext: HttpContext = options?.context ?? new HttpContext(); + + const localVarTransferCache: boolean = options?.transferCache ?? true; + + + let localVarPath = `/API/purchaseOrders/${this.configuration.encodeParam({name: "id", value: id, in: "path", style: "simple", explode: false, dataType: "number", dataFormat: "int32"})}/pdf`; + const { basePath, withCredentials } = this.configuration; + return this.httpClient.request('get', `${basePath}${localVarPath}`, + { + context: localVarHttpContext, + responseType: "blob", + ...(withCredentials ? { withCredentials } : {}), + headers: localVarHeaders, + observe: observe, + ...(localVarTransferCache !== undefined ? { transferCache: localVarTransferCache } : {}), + reportProgress: reportProgress + } + ); + } + /** * @endpoint patch /API/purchaseOrders/{id}/PurchaseConditions * @param id diff --git a/src/app/services/api/api/quotations.service.ts b/src/app/services/api/api/quotations.service.ts index 752b39f..f26e058 100644 --- a/src/app/services/api/api/quotations.service.ts +++ b/src/app/services/api/api/quotations.service.ts @@ -194,6 +194,49 @@ export class QuotationsService extends BaseService { ); } + /** + * @endpoint get /API/quotations/{id}/pdf + * @param id + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public getQuotationPdfEndpoint(id: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable; + public getQuotationPdfEndpoint(id: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable>; + public getQuotationPdfEndpoint(id: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable>; + public getQuotationPdfEndpoint(id: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/pdf', context?: HttpContext, transferCache?: boolean}): Observable { + if (id === null || id === undefined) { + throw new Error('Required parameter id was null or undefined when calling getQuotationPdfEndpoint.'); + } + + let localVarHeaders = this.defaultHeaders; + + const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([ + 'application/pdf' + ]); + if (localVarHttpHeaderAcceptSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected); + } + + const localVarHttpContext: HttpContext = options?.context ?? new HttpContext(); + + const localVarTransferCache: boolean = options?.transferCache ?? true; + + + let localVarPath = `/API/quotations/${this.configuration.encodeParam({name: "id", value: id, in: "path", style: "simple", explode: false, dataType: "number", dataFormat: "int32"})}/pdf`; + const { basePath, withCredentials } = this.configuration; + return this.httpClient.request('get', `${basePath}${localVarPath}`, + { + context: localVarHttpContext, + responseType: "blob", + ...(withCredentials ? { withCredentials } : {}), + headers: localVarHeaders, + observe: observe, + ...(localVarTransferCache !== undefined ? { transferCache: localVarTransferCache } : {}), + reportProgress: reportProgress + } + ); + } + /** * @endpoint patch /API/quotations/{id}/saleConditions * @param id diff --git a/src/app/services/file.service.ts b/src/app/services/file.service.ts new file mode 100644 index 0000000..3828709 --- /dev/null +++ b/src/app/services/file.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import {HttpResponse} from "@angular/common/http"; + +@Injectable({ + providedIn: 'root', +}) +export class FileService { + getFilenameFromHttpResponse(httpResponse: HttpResponse) { + const contentDispositionHeader = httpResponse.headers.get('Content-Disposition'); + // console.log(contentDispositionHeader); + let result = contentDispositionHeader.split(';')[1].trim().split('=')[1]; + // Removing the " from the after trim operation + result = result.replace(/"/g, ''); + // Removing . from filename + // return result.replace(/./g, '_'); + + return result; + } + + downloadBlob(data: HttpResponse) { + const url = window.URL.createObjectURL(data.body); + const anchor = document.createElement('a'); + + anchor.download = this.getFilenameFromHttpResponse(data); + anchor.href = url; + anchor.click(); + anchor.remove(); + + window.URL.revokeObjectURL(url); + } +} From f812ce856cbd4f8707e68dfb9cdb34c3c528c692 Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Thu, 4 Dec 2025 17:45:20 +0100 Subject: [PATCH 2/3] added loading function --- .../deliverery-note-table/deliverery-note-table.ts | 10 ++++++---- .../purchase-order-table/purchase-order-table.ts | 4 ++++ src/app/components/quotation-table/quotation-table.ts | 4 ++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/app/components/deliverery-note-table/deliverery-note-table.ts b/src/app/components/deliverery-note-table/deliverery-note-table.ts index cc8e179..15f9380 100644 --- a/src/app/components/deliverery-note-table/deliverery-note-table.ts +++ b/src/app/components/deliverery-note-table/deliverery-note-table.ts @@ -10,7 +10,6 @@ import {DeliverynotesService, GetDeliveryNoteDto} from "../../services/api"; import {NzNotificationService} from "ng-zorro-antd/notification"; import {firstValueFrom} from "rxjs"; import {format} from "date-fns"; -import {HttpResponse} from "@angular/common/http"; import {FileService} from "../../services/file.service"; @Component({ @@ -40,7 +39,6 @@ export class DelivereryNoteTable implements OnInit { async fetchDeliveryNotes() { this.deliveryNotesLoading.set(true) - try { const deliveryNotes = await firstValueFrom(this.deliveryNotesService.getAllDeliveryNoteEndpoint()) this.deliveryNotes.set(deliveryNotes); @@ -54,6 +52,7 @@ export class DelivereryNoteTable implements OnInit { } async delete(deliveryNote:number) { + this.deliveryNotesLoading.set(true) try { await firstValueFrom(this.deliveryNotesService.deleteDeliveryNoteEndpoint(deliveryNote)); this.notificationService.success( @@ -66,10 +65,12 @@ export class DelivereryNoteTable implements OnInit { 'Impossible de supprimer la ligne' ) } + this.deliveryNotesLoading.set(false) await this.fetchDeliveryNotes(); } async validate(deliveryNote:number) { + this.deliveryNotesLoading.set(true) try { const PatchRealDate = { realDeliveryDate: format(new Date(), 'yyyy-MM-dd') @@ -94,11 +95,12 @@ export class DelivereryNoteTable implements OnInit { 'Erreur d\'actualisation de la date' ) } - + this.deliveryNotesLoading.set(false) await this.fetchDeliveryNotes() } async export(deliveryNoteId: number) { + this.deliveryNotesLoading.set(true) try { const pdf = await firstValueFrom( this.deliveryNotesService.getDeliveryNotePdfEndpoint(deliveryNoteId, "response") @@ -111,6 +113,6 @@ export class DelivereryNoteTable implements OnInit { 'Impossible de générer un PDF' ); } + this.deliveryNotesLoading.set(false) } - } diff --git a/src/app/components/purchase-order-table/purchase-order-table.ts b/src/app/components/purchase-order-table/purchase-order-table.ts index 82f3c18..b3eac7f 100644 --- a/src/app/components/purchase-order-table/purchase-order-table.ts +++ b/src/app/components/purchase-order-table/purchase-order-table.ts @@ -50,6 +50,7 @@ export class PurchaseOrderTable implements OnInit { } async delete(purchaseOrderId:number) { + this.purchaseOrdersLoading.set(true) try { await firstValueFrom(this.purchaseOrdersService.deletePurchaseOrderEndpoint(purchaseOrderId)) this.notificationService.success( @@ -62,10 +63,12 @@ export class PurchaseOrderTable implements OnInit { 'Impossible de supprimer la ligne' ) } + this.purchaseOrdersLoading.set(false) await this.fetchPurchaseOrder(); } async export(purchaseOrderId: number){ + this.purchaseOrdersLoading.set(true) try { const pdf = await firstValueFrom( this.purchaseOrdersService.getPurchaseOrderPdfEndpoint(purchaseOrderId, "response") @@ -78,6 +81,7 @@ export class PurchaseOrderTable implements OnInit { 'Impossible de générer un PDF' ); } + this.purchaseOrdersLoading.set(false) } transfer() { diff --git a/src/app/components/quotation-table/quotation-table.ts b/src/app/components/quotation-table/quotation-table.ts index 6c1f551..125499a 100644 --- a/src/app/components/quotation-table/quotation-table.ts +++ b/src/app/components/quotation-table/quotation-table.ts @@ -51,6 +51,7 @@ export class QuotationTable implements OnInit { } async delete(quotation:number) { + this.quotationsLoading.set(true) try { await firstValueFrom(this.quotationsService.deleteQuotationEndpoint(quotation)) this.notificationService.success( @@ -63,10 +64,12 @@ export class QuotationTable implements OnInit { 'Impossible de supprimer la ligne' ) } + this.quotationsLoading.set(false) await this.fetchQuotations(); } async export(quotationId: number){ + this.quotationsLoading.set(true) try { const pdf = await firstValueFrom( this.quotationsService.getQuotationPdfEndpoint(quotationId, "response") @@ -79,6 +82,7 @@ export class QuotationTable implements OnInit { 'Impossible de générer un PDF' ); } + this.quotationsLoading.set(false) } } From a3a6b6d626f37691316ea0a56ff141e3d8bbdc35 Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Thu, 11 Dec 2025 15:30:12 +0100 Subject: [PATCH 3/3] update delivery note components --- .../deliverery-note-form.ts | 9 +++++---- .../deliverery-note-table.html | 17 ++++------------- .../deliverery-note-table.ts | 3 ++- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/app/components/deliverery-note-form/deliverery-note-form.ts b/src/app/components/deliverery-note-form/deliverery-note-form.ts index 0b69c02..67e5e35 100644 --- a/src/app/components/deliverery-note-form/deliverery-note-form.ts +++ b/src/app/components/deliverery-note-form/deliverery-note-form.ts @@ -1,11 +1,11 @@ -import {Component, inject, signal} from '@angular/core'; +import {Component, effect, inject, input, OnInit, signal} from '@angular/core'; import {FormControl, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms"; import {NzFormControlComponent, NzFormDirective, NzFormItemComponent, NzFormLabelComponent} from "ng-zorro-antd/form"; import {NzColDirective} from "ng-zorro-antd/grid"; import {NzFlexDirective} from "ng-zorro-antd/flex"; import {NzDatePickerComponent} from "ng-zorro-antd/date-picker"; import {NzOptionComponent, NzSelectComponent} from "ng-zorro-antd/select"; -import {DeliverersService, GetDelivererDto} from "../../services/api"; +import {DeliverersService, GetDelivererDto, GetDeliveryNoteDto} from "../../services/api"; import {NzNotificationService} from "ng-zorro-antd/notification"; import {firstValueFrom} from "rxjs"; @@ -21,13 +21,14 @@ import {firstValueFrom} from "rxjs"; ReactiveFormsModule, NzDatePickerComponent, NzSelectComponent, - NzOptionComponent + NzOptionComponent, ], templateUrl: './deliverery-note-form.html', styleUrl: './deliverery-note-form.css', }) -export class DelivereryNoteForm { +export class DelivereryNoteForm implements OnInit { deliveryNoteForm: FormGroup = new FormGroup({ + trackingNumber: new FormControl("TRK-" + Date.now), deliverer: new FormControl(null,[Validators.required]), expeditionDate: new FormControl(null,[Validators.required]), estimatedDate: new FormControl(null), diff --git a/src/app/components/deliverery-note-table/deliverery-note-table.html b/src/app/components/deliverery-note-table/deliverery-note-table.html index 801f261..1c164ca 100644 --- a/src/app/components/deliverery-note-table/deliverery-note-table.html +++ b/src/app/components/deliverery-note-table/deliverery-note-table.html @@ -48,24 +48,15 @@
-
- -
+ - - - + -
- -
- -
- -
+
} + diff --git a/src/app/components/deliverery-note-table/deliverery-note-table.ts b/src/app/components/deliverery-note-table/deliverery-note-table.ts index 15f9380..d5b093d 100644 --- a/src/app/components/deliverery-note-table/deliverery-note-table.ts +++ b/src/app/components/deliverery-note-table/deliverery-note-table.ts @@ -1,4 +1,4 @@ -import {Component, inject, OnInit, signal} from '@angular/core'; +import {Component, inject, OnInit, signal, viewChild} from '@angular/core'; import {DatePipe} from "@angular/common"; import {ModalButton} from "../modal-button/modal-button"; import {ModalNav} from "../modal-nav/modal-nav"; @@ -32,6 +32,7 @@ export class DelivereryNoteTable implements OnInit { private fileService = inject(FileService); deliveryNotes = signal([]); deliveryNotesLoading = signal(false); + modal = viewChild.required('modalNav'); async ngOnInit() { await this.fetchDeliveryNotes();