diff --git a/apps/backend/src/domain/entities/csv-booking.entity.spec.ts b/apps/backend/src/domain/entities/csv-booking.entity.spec.ts index 01edc3a..025a81f 100644 --- a/apps/backend/src/domain/entities/csv-booking.entity.spec.ts +++ b/apps/backend/src/domain/entities/csv-booking.entity.spec.ts @@ -315,6 +315,41 @@ describe('CsvBooking Entity', () => { }); }); + describe('isDeletable', () => { + it('allows deleting a booking whose commission is still unpaid', () => { + const booking = createValidBooking(); + booking.status = CsvBookingStatus.PENDING_PAYMENT; + + expect(booking.isDeletable()).toBe(true); + }); + + it.each([ + // Paye : la reservation est partie chez le transporteur. + CsvBookingStatus.PENDING, + CsvBookingStatus.ACCEPTED, + CsvBookingStatus.REJECTED, + CsvBookingStatus.CANCELLED, + // Virement declare : il peut etre en cours d'acheminement. + CsvBookingStatus.PENDING_BANK_TRANSFER, + ])('refuses to delete a %s booking', status => { + const booking = createValidBooking(); + booking.status = status; + + expect(booking.isDeletable()).toBe(false); + }); + + it('stops being deletable once the payment is completed', () => { + const booking = createValidBooking(); + booking.status = CsvBookingStatus.PENDING_PAYMENT; + expect(booking.isDeletable()).toBe(true); + + booking.markPaymentCompleted(); + + expect(booking.status).toBe(CsvBookingStatus.PENDING); + expect(booking.isDeletable()).toBe(false); + }); + }); + describe('Expiration Logic', () => { it('should not be expired for recent bookings', () => { const booking = createValidBooking(); diff --git a/apps/backend/src/domain/entities/csv-booking.entity.ts b/apps/backend/src/domain/entities/csv-booking.entity.ts index c6c3ee1..d5f725e 100644 --- a/apps/backend/src/domain/entities/csv-booking.entity.ts +++ b/apps/backend/src/domain/entities/csv-booking.entity.ts @@ -14,6 +14,12 @@ export enum CsvBookingStatus { CANCELLED = 'CANCELLED', // User cancelled the booking } +/** + * Statuts dans lesquels aucun paiement n'a ete encaisse : la reservation peut + * alors etre supprimee. Voir `CsvBooking.isDeletable()`. + */ +export const DELETABLE_STATUSES: readonly CsvBookingStatus[] = [CsvBookingStatus.PENDING_PAYMENT]; + /** * Document Interface * @@ -276,6 +282,24 @@ export class CsvBooking { } } + /** + * Can this booking be deleted outright? + * + * Une reservation impayee n'engage personne : elle n'est pas partie chez le + * transporteur et ne porte aucune trace comptable. La supprimer est donc sans + * consequence, la ou une reservation payee doit rester tracable et ne peut + * qu'etre annulee. + * + * `PENDING_BANK_TRANSFER` est volontairement exclu : le virement declare peut + * etre en cours d'acheminement, et supprimer la reservation priverait + * l'administration de ce qu'elle doit rapprocher a sa reception. Etendre la + * regle a ce statut est une decision comptable, pas technique : il suffirait + * de l'ajouter a `DELETABLE_STATUSES`. + */ + isDeletable(): boolean { + return DELETABLE_STATUSES.includes(this.status); + } + /** * Cancel the booking (by user) *