Files
lmnp-organizer/frontend/src/app/services/lease-end.service.ts
T

216 lines
6.4 KiB
TypeScript

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;
exitConditionReport: {
occurredOn: string;
finalized: boolean;
} | null;
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;
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;
}