feat(#23): use landlord profiles in PDFs

This commit is contained in:
nessar committed 2026-08-17 14:18:15 +02:00
1 parent ac5a7942c9
commit 668680e844
17 files changed
+221 -39

No files matched your search

@@ -1,6 +1,7 @@
import { Injectable, signal } from '@angular/core';
import { finalize, Observable } from 'rxjs';
import { withoutRecordKey, withoutSetValue } from './immutable-state';
import { httpErrorMessage } from './http-error-message';
@Injectable({ providedIn: 'root' })
export class FileDownloadService {
@@ -23,10 +24,29 @@ export class FileDownloadService {
.pipe(finalize(() => this.pendingKeys.update((keys) => withoutSetValue(keys, key))))
.subscribe({
next: (blob) => this.save(blob, fileName),
error: () => this.errors.update((errors) => ({ ...errors, [key]: errorMessage })),
error: (error) => this.recordError(key, error, errorMessage),
});
}
private recordError(key: string, error: unknown, fallback: string): void {
if (this.hasBlobBody(error)) {
void error.error
.text()
.then((body) => this.setError(key, httpErrorMessage({ error: JSON.parse(body) }, fallback)))
.catch(() => this.setError(key, fallback));
return;
}
this.setError(key, httpErrorMessage(error, fallback));
}
private hasBlobBody(error: unknown): error is { error: Blob } {
return typeof error === 'object' && error !== null && 'error' in error && error.error instanceof Blob;
}
private setError(key: string, message: string): void {
this.errors.update((errors) => ({ ...errors, [key]: message }));
}
private save(blob: Blob, fileName: string): void {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
@@ -0,0 +1,11 @@
export function httpErrorMessage(error: unknown, fallback: string): string {
return typeof error === 'object' &&
error !== null &&
'error' in error &&
typeof error.error === 'object' &&
error.error !== null &&
'message' in error.error &&
typeof error.error.message === 'string'
? error.error.message
: fallback;
}
@@ -4,6 +4,7 @@ import { finalize } from 'rxjs';
import { FileDownloadService } from './file-download.service';
import { TenantAttachment, TenantService } from './tenant.service';
import { withoutRecordKey, withoutSetValue } from './immutable-state';
import { httpErrorMessage } from './http-error-message';
@Injectable({ providedIn: 'root' })
export class TenantAttachmentTransferService {
@@ -54,7 +55,7 @@ export class TenantAttachmentTransferService {
}
},
error: (error: unknown) => {
const message = this.errorMessage(error, 'Impossible d’envoyer cette pièce jointe.');
const message = httpErrorMessage(error, 'Impossible d’envoyer cette pièce jointe.');
this.errors.update((errors) => ({ ...errors, [tenantId]: message }));
},
});
@@ -98,15 +99,4 @@ export class TenantAttachmentTransferService {
return `attachment:${attachmentId}`;
}
private errorMessage(error: unknown, fallback: string): string {
return typeof error === 'object' &&
error !== null &&
'error' in error &&
typeof error.error === 'object' &&
error.error !== null &&
'message' in error.error &&
typeof error.error.message === 'string'
? error.error.message
: fallback;
}
}
@@ -415,4 +415,21 @@ describe('WorkspaceService', () => {
'Impossible d’envoyer cette pièce jointe.',
);
});
it('keeps profile-completion guidance returned as a blocked PDF download blob', async () => {
const service = TestBed.inject(WorkspaceService);
leases.downloadPdf.mockReturnValueOnce(
throwError(() => ({
error: new Blob(['{"message":"Complétez votre profil dans les réglages."}'], {
type: 'application/json',
}),
})),
);
service.downloadLeasePdf(lease);
await vi.waitFor(() =>
expect(service.leaseDownloadError(lease.id)).toBe('Complétez votre profil dans les réglages.'),
);
});
});