216 lines
6.4 KiB
TypeScript
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;
|
|
}
|