feat: add rent payment history and reversal dialogs

- Implemented RentPaymentHistoryServiceTest to validate payment retrieval with refunds and reversals.
- Created ReverseRentPaymentServiceTest to ensure correct handling of payment reversals and allocation releases.
- Developed rent-payment-allocation-dialog component with form for surplus allocation.
- Added rent-payment-refund-dialog component for processing refunds with validation.
- Introduced rent-payment-reversal-dialog component for reversing payments with reason input.
- Implemented utility functions for formatting Euro values and handling date formatting.
- Enhanced rent-payment-dialogs.spec.ts to cover new dialog functionalities and error handling.
This commit is contained in:
nessar committed 2026-08-17 14:18:15 +02:00
1 parent e02ad54bcb
commit b9e99348f7
76 files changed
+3141 -1531

No files matched your search

@@ -2,18 +2,66 @@ import { HttpClient } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
export type RentPaymentStatus = 'PAID' | 'LATE' | 'UPCOMING';
export type RentPaymentStatus = 'CONFIRMED' | 'REVERSED';
export interface PaymentAllocation {
id: string;
rentDueId: string;
amount: number;
allocatedAt: string;
}
export interface RentPaymentRefund {
id: string;
amount: number;
refundedAt: string;
version: number;
}
export interface RentPaymentReversal {
id: string;
reversedAt: string;
reason: string;
reversedAllocations: PaymentAllocation[];
}
export interface RentPayment {
id: string;
leaseId: string;
month: string;
dueDate: string;
rent: number;
charges: number;
total: number;
receivedAt: string;
amount: number;
status: RentPaymentStatus;
paidAt: string | null;
allocations: PaymentAllocation[];
allocatedAmount: number;
refundedAmount: number;
unallocatedBalance: number;
confirmedAt: string;
version: number;
refunds: RentPaymentRefund[];
reversal: RentPaymentReversal | null;
}
export interface RecordRentPaymentRequest {
operationId: string;
rentDueId: string;
rentDueVersion: number;
receivedAt: string;
amount: number;
}
export interface AllocateRentPaymentRequest {
operationId: string;
paymentVersion: number;
rentDueId: string;
rentDueVersion: number;
amount: number;
}
export interface RefundRentPaymentRequest {
operationId: string;
paymentVersion: number;
amount: number;
refundedAt: string;
}
@Injectable({ providedIn: 'root' })
@@ -24,8 +72,23 @@ export class RentPaymentService {
return this.http.get<RentPayment[]>('/api/rent-payments');
}
markPaid(id: string, rent: number, charges: number): Observable<RentPayment> {
return this.http.put<RentPayment>(`/api/rent-payments/${id}/paid`, { rent, charges });
record(request: RecordRentPaymentRequest): Observable<RentPayment> {
return this.http.post<RentPayment>('/api/rent-payments', request);
}
allocate(paymentId: string, request: AllocateRentPaymentRequest): Observable<RentPayment> {
return this.http.post<RentPayment>(`/api/rent-payments/${paymentId}/allocations`, request);
}
refund(paymentId: string, request: RefundRentPaymentRequest): Observable<RentPayment> {
return this.http.post<RentPayment>(`/api/rent-payments/${paymentId}/refunds`, request);
}
reverse(paymentId: string, paymentVersion: number, reason: string): Observable<RentPayment> {
return this.http.post<RentPayment>(`/api/rent-payments/${paymentId}/reversal`, {
paymentVersion,
reason,
});
}
downloadReceipt(id: string): Observable<Blob> {