feat: add lease end page and resolution forms with necessary services and components
- Implemented LeaseEndPage component for managing lease end processes. - Created LeaseEndResolutionForms component for handling agreement and closure submissions. - Added civil date formatting utilities for French date representation. - Developed styles for lease end resolution forms and rent due correction components. - Integrated HTTP service for lease end operations including notice recording, withdrawal acceptance, and closure. - Added unit tests for new components and services to ensure functionality.
This commit is contained in:
1 parent
3d42c9a256
commit
c1e6b905d5
114 files changed
+6582
-345
No files matched your search
@@ -0,0 +1,212 @@
|
||||
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { FileDownloadService } from './file-download.service';
|
||||
|
||||
export type LeaseEndPhase =
|
||||
'ACTIVE' | 'NOTICE_PERIOD' | 'AWAITING_CLOSURE' | 'UNAUTHORIZED_OCCUPANCY' | 'ARCHIVED';
|
||||
|
||||
export type NoticeDeliveryMode = 'REGISTERED_LETTER' | 'BAILIFF' | 'HAND_DELIVERY' | 'OTHER';
|
||||
|
||||
export interface LeaseEndEvidence {
|
||||
version: number;
|
||||
fileName: string;
|
||||
contentType: string;
|
||||
size: number;
|
||||
sha256: string;
|
||||
reason: string | null;
|
||||
authorId: string;
|
||||
recordedAt: string;
|
||||
}
|
||||
|
||||
export interface LeaseEndAudit {
|
||||
authorId: string;
|
||||
recordedAt: string;
|
||||
}
|
||||
|
||||
export interface LeaseEndNotice {
|
||||
id: string;
|
||||
status: 'ACTIVE' | 'WITHDRAWN' | 'INVALIDATED';
|
||||
receivedOn: string;
|
||||
requestedDepartureOn: string;
|
||||
deliveryMode: NoticeDeliveryMode;
|
||||
otherDeliveryMode: string | null;
|
||||
noticeMonths: number;
|
||||
minimumEndOn: string;
|
||||
ruleVersion: string;
|
||||
recordedWithoutEvidenceConfirmed: boolean;
|
||||
authorId: string;
|
||||
recordedAt: string;
|
||||
evidenceVersions: LeaseEndEvidence[];
|
||||
withdrawal: (LeaseEndAudit & { acceptedOn: string; reason: string }) | null;
|
||||
invalidation: (LeaseEndAudit & { invalidatedOn: string; reason: string }) | null;
|
||||
}
|
||||
|
||||
export interface LeaseEndState {
|
||||
leaseId: string;
|
||||
supported: boolean;
|
||||
unsupportedReason: string | null;
|
||||
phase: LeaseEndPhase;
|
||||
leaseType: 'STANDARD' | 'STUDENT';
|
||||
fixedEndOn: string | null;
|
||||
effectiveEndOn: string | null;
|
||||
correctionRequired: boolean;
|
||||
notices: LeaseEndNotice[];
|
||||
agreedEarlyEnds: LeaseEndAgreement[];
|
||||
agreedEarlyEnd: LeaseEndAgreement | null;
|
||||
closure: {
|
||||
keysReturnedOn: string;
|
||||
authorId: string;
|
||||
recordedAt: string;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export interface LeaseEndAgreement {
|
||||
endOn: string;
|
||||
reason: string;
|
||||
authorId: string;
|
||||
recordedAt: string;
|
||||
}
|
||||
|
||||
export interface RecordNoticeRequest {
|
||||
timeZone: string;
|
||||
receivedOn: string;
|
||||
requestedDepartureOn: string;
|
||||
deliveryMode: NoticeDeliveryMode;
|
||||
otherDeliveryMode?: string;
|
||||
lateRegistrationConfirmed: boolean;
|
||||
nonStandardDeliveryConfirmed: boolean;
|
||||
missingEvidenceConfirmed: boolean;
|
||||
evidence?: File;
|
||||
}
|
||||
|
||||
export interface AcceptWithdrawalRequest {
|
||||
timeZone: string;
|
||||
acceptedOn: string;
|
||||
reason: string;
|
||||
}
|
||||
|
||||
export interface InvalidateNoticeRequest {
|
||||
timeZone: string;
|
||||
invalidatedOn: string;
|
||||
reason: string;
|
||||
}
|
||||
|
||||
export interface AppendEvidenceRequest {
|
||||
timeZone: string;
|
||||
evidence: File;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export interface AgreedEarlyEndRequest {
|
||||
timeZone: string;
|
||||
endOn: string;
|
||||
reason: string;
|
||||
}
|
||||
|
||||
export interface CloseLeaseRequest {
|
||||
timeZone: string;
|
||||
keysReturnedOn: string;
|
||||
confirmed: true;
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LeaseEndService {
|
||||
private readonly http = inject(HttpClient);
|
||||
private readonly downloads = inject(FileDownloadService);
|
||||
|
||||
getState(leaseId: string, timeZone: string): Observable<LeaseEndState> {
|
||||
const params = new HttpParams().set('timeZone', timeZone);
|
||||
return this.http.get<LeaseEndState>(`/api/leases/${leaseId}/end`, { params });
|
||||
}
|
||||
|
||||
recordNotice(leaseId: string, request: RecordNoticeRequest): Observable<LeaseEndState> {
|
||||
return this.http.post<LeaseEndState>(
|
||||
`/api/leases/${leaseId}/end/notices`,
|
||||
noticeFormData(request),
|
||||
);
|
||||
}
|
||||
|
||||
acceptWithdrawal(
|
||||
leaseId: string,
|
||||
noticeId: string,
|
||||
request: AcceptWithdrawalRequest,
|
||||
): Observable<LeaseEndState> {
|
||||
return this.http.post<LeaseEndState>(
|
||||
`/api/leases/${leaseId}/end/notices/${noticeId}/withdrawals`,
|
||||
request,
|
||||
);
|
||||
}
|
||||
|
||||
invalidateNotice(
|
||||
leaseId: string,
|
||||
noticeId: string,
|
||||
request: InvalidateNoticeRequest,
|
||||
): Observable<LeaseEndState> {
|
||||
return this.http.post<LeaseEndState>(
|
||||
`/api/leases/${leaseId}/end/notices/${noticeId}/invalidations`,
|
||||
request,
|
||||
);
|
||||
}
|
||||
|
||||
appendEvidence(
|
||||
leaseId: string,
|
||||
noticeId: string,
|
||||
request: AppendEvidenceRequest,
|
||||
): Observable<LeaseEndState> {
|
||||
const formData = new FormData();
|
||||
formData.append('timeZone', request.timeZone);
|
||||
formData.append('evidence', request.evidence);
|
||||
if (request.reason) formData.append('reason', request.reason);
|
||||
return this.http.post<LeaseEndState>(
|
||||
`/api/leases/${leaseId}/end/notices/${noticeId}/evidence`,
|
||||
formData,
|
||||
);
|
||||
}
|
||||
|
||||
downloadEvidence(leaseId: string, noticeId: string, version: number, fileName: string): void {
|
||||
const key = this.evidenceDownloadKey(leaseId, noticeId, version);
|
||||
this.downloads.download(
|
||||
key,
|
||||
this.http.get(`/api/leases/${leaseId}/end/notices/${noticeId}/evidence/${version}`, {
|
||||
responseType: 'blob',
|
||||
}),
|
||||
fileName,
|
||||
'Impossible de télécharger cette preuve.',
|
||||
);
|
||||
}
|
||||
|
||||
evidenceDownloading(leaseId: string, noticeId: string, version: number): boolean {
|
||||
return this.downloads.isPending(this.evidenceDownloadKey(leaseId, noticeId, version));
|
||||
}
|
||||
|
||||
evidenceDownloadError(leaseId: string, noticeId: string, version: number): string {
|
||||
return this.downloads.error(this.evidenceDownloadKey(leaseId, noticeId, version));
|
||||
}
|
||||
|
||||
recordAgreedEarlyEnd(leaseId: string, request: AgreedEarlyEndRequest): Observable<LeaseEndState> {
|
||||
return this.http.post<LeaseEndState>(`/api/leases/${leaseId}/end/agreed-early-end`, request);
|
||||
}
|
||||
|
||||
close(leaseId: string, request: CloseLeaseRequest): Observable<LeaseEndState> {
|
||||
return this.http.post<LeaseEndState>(`/api/leases/${leaseId}/end/closure`, request);
|
||||
}
|
||||
|
||||
private evidenceDownloadKey(leaseId: string, noticeId: string, version: number): string {
|
||||
return `lease-end-evidence:${leaseId}:${noticeId}:${version}`;
|
||||
}
|
||||
}
|
||||
|
||||
function noticeFormData(request: RecordNoticeRequest): FormData {
|
||||
const formData = new FormData();
|
||||
formData.append('timeZone', request.timeZone);
|
||||
formData.append('receivedOn', request.receivedOn);
|
||||
formData.append('requestedDepartureOn', request.requestedDepartureOn);
|
||||
formData.append('deliveryMode', request.deliveryMode);
|
||||
if (request.otherDeliveryMode) formData.append('otherDeliveryMode', request.otherDeliveryMode);
|
||||
formData.append('lateRegistrationConfirmed', String(request.lateRegistrationConfirmed));
|
||||
formData.append('nonStandardDeliveryConfirmed', String(request.nonStandardDeliveryConfirmed));
|
||||
formData.append('missingEvidenceConfirmed', String(request.missingEvidenceConfirmed));
|
||||
if (request.evidence) formData.append('evidence', request.evidence);
|
||||
return formData;
|
||||
}
|
||||
Reference in new issue
Block a user