Outils pour utilisateurs

Outils du site


ujusum:3-codage:2-sprints:4-sprint-4

Table des matières

Sprint 4 — Gestion des Propriétés

Objectif

Construire le domaine métier principal de la plateforme :

Property
PropertyType
PropertyAmenity
PropertyImage
PropertyAvailability
PropertyPricing
PropertyPolicy
PropertyReview

afin de permettre :

Catalogue de propriétés

Gestion des disponibilités

Gestion tarifaire

Avis clients

Moteur de réservation

Recherche avancée

Revenue Management

Channel Management Ready

Architecture cible

Property

├── PropertyType
├── PropertyAmenity
├── PropertyImage
├── PropertyAvailability
├── PropertyPricing
├── PropertyPolicy
└── PropertyReview

↓

Reservation Engine

↓

CRM

↓

Revenue Engine

Sous-domaines du Sprint 4

Sprint 4-A

Modèle Property Core

Property

PropertyType

PropertyAmenity

Relations

Multi-tenant

Sprint 4-B

Catalogue des Propriétés

PropertyModule

CRUD

Recherche

Pagination

Filtres

Sprint 4-C

Gestion des Équipements

Amenities

Catégories

Recherche

Attribution

Sprint 4-D

Gestion des Images

PropertyImage

Upload

Galerie

Ordonnancement

MinIO/S3

Sprint 4-E

Disponibilités

PropertyAvailability

Calendrier

Blocages

Inventaire

Sprint 4-F

Tarification

PropertyPricing

Tarifs saisonniers

Tarifs dynamiques

Revenue Ready

Sprint 4-G

Politiques

PropertyPolicy

Annulation

Check-in

Check-out

Règlement

Sprint 4-H

Avis Clients

PropertyReview

Notation

Modération

Réputation

Sprint 4-I

Recherche Avancée

Recherche géographique

Disponibilités

Prix

Filtres avancés

Sprint 4-J

Analytics & Intelligence

Performance propriétés

Occupation

Revenue

Recommandations

Architecture technique cible

src/modules

property
property-types
property-amenities
property-images
property-availability
property-pricing
property-policies
property-reviews

property-search
property-analytics

Modèles principaux à livrer

Property

PropertyType

PropertyAmenity

PropertyImage

PropertyAvailability

PropertyPricing

PropertyPolicy

PropertyReview

Capacités Enterprise attendues

✓ Multi-tenant

✓ AuditLog

✓ CRM Integration

✓ Reservation Ready

✓ Revenue Ready

✓ Analytics Ready

✓ Search Ready

✓ AI Ready

✓ Channel Manager Ready

Définition de terminé

Le Sprint 4 est terminé lorsque :

✓ Catalogue complet

✓ Disponibilités

✓ Tarification

✓ Politiques

✓ Avis

✓ Recherche

✓ Analytics

✓ Réservation Ready

Sprint 4-A.1 — Implémentation Prisma Property Core

Objectif

Créer les fondations du domaine métier Property.

À l'issue de cette étape :

✓ Property

✓ PropertyType

✓ PropertyAmenity

✓ Multi-tenant

✓ Catalogue Ready

✓ Reservation Ready

✓ CRM Ready

✓ Analytics Ready

Architecture cible

Property

├── PropertyType
├── PropertyAmenity
├── PropertyImage
├── PropertyAvailability
├── PropertyPricing
├── PropertyPolicy
└── PropertyReview

↓

Reservation Engine

↓

Revenue Engine

Sprint 4-A.1-A

PropertyType


Étape 1 — Création

Ajouter dans schema.prisma

model PropertyType {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  code                  String
 
  name                  String
 
  description           String?
 
  icon                  String?
 
  active                Boolean
                        @default(true)
 
  displayOrder          Int
                        @default(0)
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  properties            Property[]
 
  @@unique([
    tenantId,
    code
  ])
 
  @@index([tenantId])
 
  @@index([active])
}

Étape 2 — Types par défaut

Prévoir

HOTEL_ROOM

APARTMENT

HOUSE

VILLA

STUDIO

HOSTEL

RESORT

CHALET

CAMPING

OTHER

Sprint 4-A.1-B

PropertyAmenity


Étape 3 — Création

Ajouter

model PropertyAmenity {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  code                  String
 
  name                  String
 
  description           String?
 
  category              String?
 
  icon                  String?
 
  active                Boolean
                        @default(true)
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  properties            PropertyAmenityAssignment[]
 
  @@unique([
    tenantId,
    code
  ])
 
  @@index([tenantId])
 
  @@index([category])
 
  @@index([active])
}

Étape 4 — Relation M:N

Ajouter

model PropertyAmenityAssignment {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  amenityId             String
 
  createdAt             DateTime
                        @default(now())
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  amenity               PropertyAmenity
                        @relation(
                          fields:[amenityId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@unique([
    propertyId,
    amenityId
  ])
 
  @@index([propertyId])
 
  @@index([amenityId])
}

Étape 5 — Catégories standards

Prévoir

GENERAL

KITCHEN

BATHROOM

BEDROOM

CONNECTIVITY

SECURITY

ACCESSIBILITY

ENTERTAINMENT

OUTDOOR

PARKING

Sprint 4-A.1-C

Property


Étape 6 — Création

Ajouter

model Property {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyTypeId        String
 
  propertyNumber        String
 
  externalReference     String?
 
  name                  String
 
  slug                  String
 
  description           String?
 
  shortDescription      String?
 
  active                Boolean
                        @default(true)
 
  featured              Boolean
                        @default(false)
 
  published             Boolean
                        @default(false)
 
  maxGuests             Int
                        @default(1)
 
  bedrooms              Int
                        @default(0)
 
  bathrooms             Int
                        @default(0)
 
  beds                  Int
                        @default(1)
 
  floorArea             Decimal?
                        @db.Decimal(10,2)
 
  floorAreaUnit         String?
                        @default("m²")
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  deletedAt             DateTime?
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  propertyType          PropertyType
                        @relation(
                          fields:[propertyTypeId],
                          references:[id]
                        )
 
  amenities             PropertyAmenityAssignment[]
 
  @@unique([
    tenantId,
    propertyNumber
  ])
 
  @@unique([
    tenantId,
    slug
  ])
 
  @@index([tenantId])
 
  @@index([propertyTypeId])
 
  @@index([active])
 
  @@index([published])
 
  @@index([featured])
}

Étape 7 — Capacités réservation

Ajouter

minimumStay           Int?
                      @default(1)
 
maximumStay           Int?
 
advanceBookingDays    Int?
 
instantBooking        Boolean
                      @default(false)

Étape 8 — Capacités CRM

Ajouter

ownerName             String?
 
ownerEmail            String?
 
ownerPhone            String?

Étape 9 — Capacités Analytics

Ajouter

viewCount             Int
                      @default(0)
 
bookingCount          Int
                      @default(0)
 
averageRating         Float?

Sprint 4-A.1-D

Adresse Property


Étape 10 — Création

Ajouter

model PropertyAddress {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
                        @unique
 
  addressLine1          String
 
  addressLine2          String?
 
  postalCode            String?
 
  city                  String
 
  region                String?
 
  country               String
 
  latitude              Decimal?
                        @db.Decimal(10,7)
 
  longitude             Decimal?
                        @db.Decimal(10,7)
 
  timezone              String?
 
  geoValidated          Boolean
                        @default(false)
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@index([city])
 
  @@index([country])
 
  @@index([latitude])
 
  @@index([longitude])
}

Étape 11 — Relation

Ajouter dans Property

address PropertyAddress?

Sprint 4-A.1-E

SEO & Catalogue


Étape 12 — SEO

Ajouter dans Property

seoTitle             String?
 
seoDescription       String?
 
seoKeywords          String?

Étape 13 — Publication

Ajouter

publishedAt          DateTime?
 
publishedBy          String?

Étape 14 — Visibilité

Ajouter

visibility           PropertyVisibility
                      @default(PRIVATE)

Étape 15 — Enum

Ajouter

enum PropertyVisibility {
 
  PRIVATE
 
  INTERNAL
 
  PUBLIC
}

Sprint 4-A.1-F

Audit & Historisation


Étape 16 — Préparer

Compatible avec :

AuditLog

PropertyHistory

Reservation

ChannelManager

Étape 17 — Champs métier

Ajouter

metadata Json?

Sprint 4-A.1-G

Seed Initial


Étape 18 — Property Types

Créer

Dans le seed :

HOTEL_ROOM

APARTMENT

HOUSE

VILLA

STUDIO

Étape 19 — Amenities

Créer

WIFI

AIR_CONDITIONING

PARKING

POOL

TV

KITCHEN

WASHING_MACHINE

BREAKFAST

PET_FRIENDLY

Sprint 4-A.1-H

Migration


Étape 20 — Générer

npx prisma migrate dev \
--name property_core

Générer

npx prisma generate

Étape 21 — Vérification

Contrôler

Property

PropertyType

PropertyAmenity

PropertyAmenityAssignment

PropertyAddress

présents dans Prisma Client.


Définition de terminé

Le Sprint 4-A.1 est terminé lorsque :

✓ Property créé

✓ PropertyType créé

✓ PropertyAmenity créé

✓ PropertyAmenityAssignment créé

✓ PropertyAddress créé

✓ Multi-tenant prêt

✓ Catalogue prêt

✓ Réservation prête

✓ Analytics prêt

Livrables

Property

PropertyType

PropertyAmenity

PropertyAmenityAssignment

PropertyAddress

PropertyVisibility

Sprint 4-A.2 — Extension Enterprise du modèle Property

Objectif

Transformer le modèle Property en véritable référentiel immobilier Enterprise.

À l'issue de cette étape :

✓ PropertyStatus

✓ PropertyCategory

✓ PropertyOwner

✓ PropertyManager

✓ PropertyFeatures

✓ PropertyCompliance

✓ PropertyScore

✓ PropertyLifecycle

✓ Revenue Ready

✓ Enterprise Ready

Architecture cible

Property

├── PropertyType
├── PropertyCategory
├── PropertyOwner
├── PropertyManager
├── PropertyFeatures
├── PropertyCompliance
├── PropertyScore
└── PropertyLifecycle

↓

Reservation

↓

Revenue

↓

Analytics

↓

Compliance

Sprint 4-A.2-A

Property Status


Étape 1 — Enum PropertyStatus

Ajouter dans schema.prisma

enum PropertyStatus {
 
  DRAFT
 
  PENDING_REVIEW
 
  ACTIVE
 
  INACTIVE
 
  SUSPENDED
 
  ARCHIVED
}

Étape 2 — Ajouter dans Property

status PropertyStatus
       @default(DRAFT)

Étape 3 — Dates de cycle

Ajouter

activatedAt          DateTime?
 
deactivatedAt        DateTime?
 
archivedAt           DateTime?

Sprint 4-A.2-B

Property Category


Étape 4 — Création

Ajouter

model PropertyCategory {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  code                  String
 
  name                  String
 
  description           String?
 
  parentCategoryId      String?
 
  active                Boolean
                        @default(true)
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  parentCategory        PropertyCategory?
                        @relation(
                          "PropertyCategoryTree",
                          fields:[parentCategoryId],
                          references:[id]
                        )
 
  children              PropertyCategory[]
                        @relation(
                          "PropertyCategoryTree"
                        )
 
  properties            Property[]
 
  @@unique([
    tenantId,
    code
  ])
 
  @@index([tenantId])
 
  @@index([parentCategoryId])
}

Étape 5 — Relation

Ajouter dans Property

propertyCategoryId String?
 
propertyCategory PropertyCategory?
                 @relation(
                   fields:[propertyCategoryId],
                   references:[id]
                 )

Étape 6 — Catégories

Prévoir

LUXURY

BUSINESS

FAMILY

BUDGET

LONG_STAY

SHORT_STAY

PREMIUM

CORPORATE

Sprint 4-A.2-C

Property Owner


Étape 7 — Création

Ajouter

model PropertyOwner {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  code                  String
 
  companyName           String?
 
  firstName             String?
 
  lastName              String?
 
  email                 String?
 
  phone                 String?
 
  taxNumber             String?
 
  active                Boolean
                        @default(true)
 
  metadata              Json?
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  properties            Property[]
 
  @@unique([
    tenantId,
    code
  ])
 
  @@index([tenantId])
}

Étape 8 — Relation

Ajouter dans Property

propertyOwnerId String?
 
propertyOwner PropertyOwner?
              @relation(
                fields:[propertyOwnerId],
                references:[id]
              )

Sprint 4-A.2-D

Property Manager


Étape 9 — Création

Ajouter

model PropertyManager {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  userId                String?
 
  code                  String
 
  name                  String
 
  email                 String?
 
  phone                 String?
 
  active                Boolean
                        @default(true)
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  properties            Property[]
 
  @@unique([
    tenantId,
    code
  ])
 
  @@index([tenantId])
 
  @@index([userId])
}

Étape 10 — Relation

Ajouter dans Property

propertyManagerId String?
 
propertyManager PropertyManager?
                @relation(
                  fields:[propertyManagerId],
                  references:[id]
                )

Sprint 4-A.2-E

Property Features


Étape 11 — Création

Ajouter

model PropertyFeature {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  code                  String
 
  name                  String
 
  category              String?
 
  active                Boolean
                        @default(true)
 
  createdAt             DateTime
                        @default(now())
 
  properties            PropertyFeatureAssignment[]
 
  @@unique([
    tenantId,
    code
  ])
 
  @@index([tenantId])
}

Étape 12 — Affectation

Ajouter

model PropertyFeatureAssignment {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  featureId             String
 
  value                 String?
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  feature               PropertyFeature
                        @relation(
                          fields:[featureId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@unique([
    propertyId,
    featureId
  ])
}

Étape 13 — Exemples

SEA_VIEW

MOUNTAIN_VIEW

BALCONY

TERRACE

PRIVATE_POOL

JACUZZI

SMART_LOCK

EV_CHARGER

Sprint 4-A.2-F

Property Compliance


Étape 14 — Création

Ajouter

model PropertyCompliance {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
                        @unique
 
  licenseNumber         String?
 
  registrationNumber    String?
 
  insurancePolicy       String?
 
  insuranceExpiresAt    DateTime?
 
  fireSafetyValidated   Boolean
                        @default(false)
 
  accessibilityValidated Boolean
                         @default(false)
 
  complianceScore       Int
                        @default(0)
 
  lastAuditAt           DateTime?
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
}

Étape 15 — Relation

Ajouter dans Property

compliance PropertyCompliance?

Sprint 4-A.2-G

Property Score


Étape 16 — Création

Ajouter

model PropertyScore {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
                        @unique
 
  qualityScore          Int
                        @default(0)
 
  reviewScore           Int
                        @default(0)
 
  occupancyScore        Int
                        @default(0)
 
  revenueScore          Int
                        @default(0)
 
  complianceScore       Int
                        @default(0)
 
  globalScore           Int
                        @default(0)
 
  calculatedAt          DateTime
                        @default(now())
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
}

Étape 17 — Relation

Ajouter dans Property

score PropertyScore?

Sprint 4-A.2-H

Property Lifecycle


Étape 18 — Création

Ajouter

model PropertyLifecycle {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
                        @unique
 
  onboardingCompleted   Boolean
                        @default(false)
 
  contentCompleted      Boolean
                        @default(false)
 
  pricingCompleted      Boolean
                        @default(false)
 
  availabilityCompleted Boolean
                        @default(false)
 
  complianceCompleted   Boolean
                        @default(false)
 
  publishedCompleted    Boolean
                        @default(false)
 
  launchDate            DateTime?
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
}

Étape 19 — Relation

Ajouter dans Property

lifecycle PropertyLifecycle?

Sprint 4-A.2-I

Analytics & Revenue Ready


Étape 20 — KPI

Ajouter dans Property

occupancyRate         Float?
 
revenueYtd            Decimal?
                      @db.Decimal(14,2)
 
averageNightlyRate   Decimal?
                      @db.Decimal(12,2)
 
revPar                Decimal?
                      @db.Decimal(12,2)

Étape 21 — Revenue Metrics

Compatible avec :

ADR

RevPAR

Occupancy

Yield Management

Sprint 4-A.2-J

Migration & Seed


Étape 22 — Seed

Créer

Catégories :

LUXURY

BUSINESS

FAMILY

PREMIUM

LONG_STAY

Étape 23 — Migration

Générer

npx prisma migrate dev \
--name property_enterprise

Générer

npx prisma generate

Étape 24 — Audit Ready

Préparer

Compatible avec :

PropertyHistory

AuditLog

Reservation

ChannelManager

RevenueManagement

Définition de terminé

Le Sprint 4-A.2 est terminé lorsque :

✓ PropertyStatus

✓ PropertyCategory

✓ PropertyOwner

✓ PropertyManager

✓ PropertyFeature

✓ PropertyCompliance

✓ PropertyScore

✓ PropertyLifecycle

✓ Revenue KPI

✓ Analytics Ready

Livrables

PropertyCategory

PropertyOwner

PropertyManager

PropertyFeature

PropertyFeatureAssignment

PropertyCompliance

PropertyScore

PropertyLifecycle

PropertyStatus

Sprint 4-B.1 — Création du PropertyModule

Objectif

Implémenter le premier module métier complet du domaine Property.

À l'issue de cette étape :

✓ PropertyModule

✓ PropertyController

✓ PropertyService

✓ CRUD Property

✓ Recherche

✓ Pagination

✓ Multi-Tenant Security

✓ Swagger

Architecture cible

PropertyModule

├── PropertyController
├── PropertyService
├── PropertyRepository
├── DTOs
├── Validators
└── Policies

↓

Prisma

↓

Property

Sprint 4-B.1-A

Structure du module


Étape 1 — Création

src/modules/property

├── application
│
│   └── dto
│
│       ├── create-property.dto.ts
│
│       ├── update-property.dto.ts
│
│       ├── property-query.dto.ts
│
│       └── property-response.dto.ts
│
├── domain
│
│   └── services
│
│       └── property.service.ts
│
├── presentation
│
│   └── controllers
│
│       └── property.controller.ts
│
├── property.module.ts
│
└── property.constants.ts

Étape 2 — Déclaration Module

Créer

@Module({
 
  imports: [
    PrismaModule,
    AuthModule,
    AuditModule
  ],
 
  controllers: [
    PropertyController
  ],
 
  providers: [
    PropertyService
  ],
 
  exports: [
    PropertyService
  ]
})
export class PropertyModule {}

Sprint 4-B.1-B

DTOs


Étape 3 — CreatePropertyDto

Créer

create-property.dto.ts

Implémentation

export class CreatePropertyDto {
 
  propertyTypeId: string;
 
  propertyNumber: string;
 
  name: string;
 
  slug: string;
 
  description?: string;
 
  shortDescription?: string;
 
  maxGuests?: number;
 
  bedrooms?: number;
 
  bathrooms?: number;
 
  beds?: number;
 
  instantBooking?: boolean;
 
  ownerName?: string;
 
  ownerEmail?: string;
 
  ownerPhone?: string;
}

Étape 4 — UpdatePropertyDto

Créer

export class UpdatePropertyDto
  extends PartialType(
    CreatePropertyDto
  ) {}

Étape 5 — PropertyQueryDto

Créer

export class PropertyQueryDto {
 
  search?: string;
 
  propertyTypeId?: string;
 
  propertyCategoryId?: string;
 
  status?: string;
 
  published?: boolean;
 
  featured?: boolean;
 
  page?: number = 1;
 
  limit?: number = 25;
 
  sortBy?: string = 'createdAt';
 
  sortOrder?: 'asc' | 'desc'
    = 'desc';
}

Sprint 4-B.1-C

PropertyService


Étape 6 — Création

Créer

property.service.ts

Méthodes

findAll()
 
findById()
 
create()
 
update()
 
remove()

Étape 7 — Create

Exemple

async create(
  tenantId: string,
  dto: CreatePropertyDto,
  userId: string,
) {
 
  return this.prisma.property.create({
 
    data: {
 
      tenantId,
 
      ...dto
    }
  });
}

Étape 8 — Lecture

Vérifier

tenantId

sur toutes les requêtes.


Exemple

return this.prisma.property.findFirst({
 
  where: {
 
    id,
 
    tenantId
  }
});

Étape 9 — Mise à jour

Vérifier

Property

Tenant

Permissions

avant modification.


Étape 10 — Suppression

Soft Delete

deletedAt:
  new Date()
 
status:
  PropertyStatus.ARCHIVED

Sprint 4-B.1-D

Recherche


Étape 11 — Recherche texte

Champs

name

description

propertyNumber

slug

Prisma

OR: [
 
  {
    name: {
      contains: search,
      mode: 'insensitive'
    }
  },
 
  {
    propertyNumber: {
      contains: search,
      mode: 'insensitive'
    }
  }
]

Étape 12 — Filtres

Supporter

PropertyType

Category

Status

Published

Featured

Étape 13 — Relations

Charger

include: {
 
  propertyType: true,
 
  propertyCategory: true,
 
  address: true
}

Sprint 4-B.1-E

Pagination


Étape 14 — Pagination

Calcul

const skip =
  (page - 1) * limit;

Étape 15 — Retour

{
  "items": [],
  "meta": {
    "page": 1,
    "limit": 25,
    "total": 150
  }
}

Étape 16 — Tri

Supporter

name

createdAt

updatedAt

averageRating

bookingCount

Sprint 4-B.1-F

Contrôleur


Étape 17 — Création

Créer

property.controller.ts

Déclaration

@ApiTags('Properties')
 
@ApiBearerAuth()
 
@Controller('properties')
 
@UseGuards(
  JwtAuthGuard
)

Étape 18 — GET

Ajouter

GET /properties

Permissions

property.read

Étape 19 — GET BY ID

Ajouter

GET /properties/{id}

Étape 20 — POST

Ajouter

POST /properties

Permissions

property.create

Étape 21 — PUT

Ajouter

PUT /properties/{id}

Permissions

property.update

Étape 22 — DELETE

Ajouter

DELETE /properties/{id}

Permissions

property.delete

Sprint 4-B.1-G

Multi-Tenant Security


Étape 23 — Isolation

Obligatoire

Toutes les requêtes :

WHERE tenantId = currentTenant

Étape 24 — Validation

Refuser

Cross Tenant Access

avec :

ForbiddenException

Étape 25 — Audit

Journaliser

PROPERTY_CREATED

PROPERTY_UPDATED

PROPERTY_DELETED

PROPERTY_VIEWED

Sprint 4-B.1-H

Swagger


Étape 26 — Documentation

Ajouter

Properties

Create Property

Update Property

Delete Property

Search Properties

Étape 27 — Exemples

POST

{
  "propertyTypeId":"uuid",
  "propertyNumber":"APT-001",
  "name":"Appartement Centre Ville",
  "slug":"appartement-centre-ville",
  "maxGuests":4
}

Sprint 4-B.1-I

Permissions RBAC


Étape 28 — Ajouter

property.read

property.create

property.update

property.delete

property.publish

property.manage

Étape 29 — Rôles

SUPER_ADMIN

TENANT_ADMIN

PROPERTY_MANAGER

RECEPTIONIST

Sprint 4-B.1-J

Préparation Sprint 4-E


Étape 30 — Compatibilité

Préparer les relations futures :

PropertyAvailability

PropertyPricing

PropertyImage

PropertyReview

Reservation

Définition de terminé

Le Sprint 4-B.1 est terminé lorsque :

✓ PropertyModule créé

✓ PropertyController créé

✓ PropertyService créé

✓ CRUD complet

✓ Recherche

✓ Pagination

✓ Multi-tenant Security

✓ RBAC

✓ AuditLog

✓ Swagger

Livrables

PropertyModule

PropertyController

PropertyService

CreatePropertyDto

UpdatePropertyDto

PropertyQueryDto

PropertyResponseDto

Sprint 4-B.2 — Catalogue Enterprise & Recherche Avancée des Propriétés

Objectif

Transformer le catalogue Property en moteur de recherche immobilier Enterprise.

À l'issue de cette étape :

✓ Filtres multicritères

✓ Recherche géographique

✓ Recherche par capacité

✓ Recherche par équipements

✓ Recherche par score

✓ Recherches sauvegardées

✓ Catalogue intelligent

✓ Property Discovery Engine

Architecture cible

Property Catalog

↓

Search Engine

├── Geographic Search
├── Capacity Search
├── Amenity Search
├── Score Search
├── Availability Search
└── Smart Ranking

↓

Catalog Intelligence

↓

Reservation Engine

Sprint 4-B.2-A

Extension Prisma


Étape 1 — PropertySavedSearch

Ajouter dans schema.prisma

model PropertySavedSearch {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  userId                String
 
  name                  String
 
  query                 String?
 
  filters               Json
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  user                  User
                        @relation(
                          fields:[userId],
                          references:[id]
                        )
 
  @@index([tenantId])
 
  @@index([userId])
}

Étape 2 — PropertySearchHistory

Ajouter

model PropertySearchHistory {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  userId                String?
 
  searchTerm            String?
 
  filters               Json?
 
  resultsCount          Int
                        @default(0)
 
  createdAt             DateTime
                        @default(now())
 
  @@index([tenantId])
 
  @@index([createdAt])
}

Étape 3 — PropertySearchScore

Ajouter dans Property

searchScore           Float?

Étape 4 — Migration

Générer

npx prisma migrate dev \
--name property_catalog_search

Sprint 4-B.2-B

Recherche Avancée


Étape 5 — PropertySearchDto

Créer

property-search.dto.ts

Implémentation

export class PropertySearchDto {
 
  search?: string;
 
  propertyTypeId?: string;
 
  propertyCategoryId?: string;
 
  city?: string;
 
  country?: string;
 
  minGuests?: number;
 
  maxGuests?: number;
 
  minBedrooms?: number;
 
  maxBedrooms?: number;
 
  amenities?: string[];
 
  minScore?: number;
 
  maxScore?: number;
 
  featured?: boolean;
 
  page?: number = 1;
 
  limit?: number = 25;
}

Étape 6 — PropertyCatalogService

Créer

property-catalog.service.ts

Méthodes

search()
 
advancedSearch()
 
searchByLocation()
 
searchByAmenities()
 
searchByCapacity()

Sprint 4-B.2-C

Filtres Multicritères


Étape 7 — Recherche

Supporter

Type

Catégorie

Ville

Pays

Statut

Publication

Score

Capacité

Étape 8 — Exemple Prisma

where: {
 
  tenantId,
 
  active: true,
 
  city,
 
  maxGuests: {
 
    gte: minGuests
  }
}

Étape 9 — Combinaisons

Exemple

Appartement

+

Paris

+

4 personnes

+

Wifi

+

Score > 80

Sprint 4-B.2-D

Recherche Géographique


Étape 10 — Géolocalisation

Utiliser

PropertyAddress

Latitude

Longitude

Étape 11 — Recherche par rayon

Ajouter

GET /properties/search/radius

Paramètres

latitude

longitude

radiusKm

Étape 12 — Calcul

Implémenter

Formule :

Haversine

pour calculer la distance.


Étape 13 — Retour

Exemple

{
  "property":"Villa Prestige",
  "distanceKm":4.2
}

Sprint 4-B.2-E

Recherche par Capacité


Étape 14 — Critères

Supporter

Guests

Bedrooms

Bathrooms

Beds

Étape 15 — Exemple

8 voyageurs

4 chambres

3 salles de bain

Retour

Toutes les propriétés compatibles.


Sprint 4-B.2-F

Recherche par Équipements


Étape 16 — Recherche

Supporter

Wifi

Piscine

Parking

Cuisine

Climatisation

Jacuzzi

Étape 17 — Prisma

Exemple

amenities: {
 
  some: {
 
    amenity: {
 
      code: 'WIFI'
    }
  }
}

Étape 18 — Mode

Supporter

ANY

ALL

pour les équipements.


Sprint 4-B.2-G

Recherche par Score


Étape 19 — Utiliser

PropertyScore

Critères

GlobalScore

ReviewScore

RevenueScore

OccupancyScore

Étape 20 — Exemple

Score > 90

Retour

Propriétés Premium.


Sprint 4-B.2-H

Recherches Sauvegardées


Étape 21 — PropertySavedSearchService

Créer

property-saved-search.service.ts

Méthodes

saveSearch()
 
listSearches()
 
executeSearch()
 
deleteSearch()

Étape 22 — Endpoints

Ajouter

GET    /properties/search/saved
 
POST   /properties/search/saved
 
DELETE /properties/search/saved/{id}

Étape 23 — Exemple

Paris Premium

Wifi

Piscine

6 personnes

Sauvegarder

Mes Villas Premium

Sprint 4-B.2-I

Catalogue Intelligent


Étape 24 — Ranking

Créer

property-ranking.service.ts

Calcul

ReviewScore

Occupancy

Revenue

Featured

SearchPopularity

Étape 25 — Search Score

Exemple

40% Reviews

20% Revenue

20% Occupation

20% Popularité

Étape 26 — Recommandations

Ajouter

getRecommendedProperties()

Basé sur

Historique recherche

Réservations

Préférences utilisateur

Sprint 4-B.2-J

API Catalogue


Étape 27 — Endpoints

Ajouter

GET /properties/search
 
GET /properties/search/radius
 
GET /properties/search/facets
 
GET /properties/search/saved
 
POST /properties/search/saved
 
DELETE /properties/search/saved/{id}

Étape 28 — Facettes

Retour

{
  "cities": {
    "Paris": 142,
    "Lyon": 38
  },
  "types": {
    "APARTMENT": 97,
    "VILLA": 31
  }
}

Étape 29 — Audit

Journaliser

PROPERTY_SEARCH

PROPERTY_RADIUS_SEARCH

PROPERTY_SAVED_SEARCH

PROPERTY_SEARCH_EXECUTED

Étape 30 — Permissions

Ajouter

property.search

property.search.saved

property.search.analytics

Préparation Sprint 4-E

Compatible avec :

PropertyAvailability

Reservation

Calendar Engine

Inventory Engine

Préparation Sprint 4-F

Compatible avec :

PropertyPricing

Dynamic Pricing

Revenue Management

Préparation Sprint 20

Compatible avec :

Enterprise Catalog

Recommendation Engine

Search Intelligence

Booking Engine

Définition de terminé

Le Sprint 4-B.2 est terminé lorsque :

✓ Filtres multicritères

✓ Recherche géographique

✓ Recherche capacité

✓ Recherche équipements

✓ Recherche score

✓ Recherches sauvegardées

✓ Catalogue intelligent

✓ API Catalogue

✓ Audit intégré

Livrables

PropertyCatalogService

PropertySavedSearch

PropertySearchHistory

PropertyRankingService

PropertySearchDto

Enterprise Property Search API

Sprint 4-C.1 — Gestion des Équipements (Amenities)

Objectif

Implémenter la gestion complète des équipements des propriétés.

À l'issue de cette étape :

✓ PropertyAmenityModule

✓ PropertyAmenityController

✓ PropertyAmenityService

✓ CRUD Amenities

✓ Catégories

✓ Attribution aux propriétés

✓ Recherche équipements

✓ Catalogue enrichi

Architecture cible

PropertyAmenity

↓

PropertyAmenityAssignment

↓

Property

↓

Property Search

↓

Reservation Engine

Sprint 4-C.1-A

Module Amenities


Étape 1 — Création

src/modules/property-amenities

├── application
│
│   └── dto
│
│       ├── create-property-amenity.dto.ts
│
│       ├── update-property-amenity.dto.ts
│
│       ├── property-amenity-query.dto.ts
│
│       └── assign-property-amenity.dto.ts
│
├── domain
│
│   └── services
│
│       └── property-amenity.service.ts
│
├── presentation
│
│   └── controllers
│
│       └── property-amenity.controller.ts
│
└── property-amenity.module.ts

Étape 2 — Module

Créer

@Module({
 
  imports: [
    PrismaModule,
    AuthModule,
    AuditModule
  ],
 
  controllers: [
    PropertyAmenityController
  ],
 
  providers: [
    PropertyAmenityService
  ],
 
  exports: [
    PropertyAmenityService
  ]
})
export class PropertyAmenityModule {}

Sprint 4-C.1-B

DTOs


Étape 3 — CreatePropertyAmenityDto

Créer

export class CreatePropertyAmenityDto {
 
  code: string;
 
  name: string;
 
  description?: string;
 
  category?: string;
 
  icon?: string;
 
  active?: boolean;
}

Étape 4 — UpdatePropertyAmenityDto

Créer

export class UpdatePropertyAmenityDto
  extends PartialType(
    CreatePropertyAmenityDto
  ) {}

Étape 5 — AssignPropertyAmenityDto

Créer

export class AssignPropertyAmenityDto {
 
  amenityIds: string[];
}

Étape 6 — PropertyAmenityQueryDto

Créer

export class PropertyAmenityQueryDto {
 
  search?: string;
 
  category?: string;
 
  active?: boolean;
 
  page?: number = 1;
 
  limit?: number = 25;
}

Sprint 4-C.1-C

PropertyAmenityService


Étape 7 — Création

Créer

property-amenity.service.ts

Méthodes

findAll()
 
findById()
 
create()
 
update()
 
remove()
 
assignToProperty()
 
removeFromProperty()
 
listPropertyAmenities()

Étape 8 — Création

Exemple

async create(
  tenantId: string,
  dto: CreatePropertyAmenityDto,
) {
 
  return this.prisma.propertyAmenity.create({
 
    data: {
 
      tenantId,
 
      ...dto
    }
  });
}

Étape 9 — Mise à jour

Vérifier

Tenant

Code unique

Permissions

avant modification.


Étape 10 — Suppression

Soft Delete

active: false

afin de conserver l'historique.


Sprint 4-C.1-D

Gestion des Catégories


Étape 11 — Catégories Standards

Supporter

GENERAL

KITCHEN

BATHROOM

BEDROOM

CONNECTIVITY

SECURITY

ACCESSIBILITY

ENTERTAINMENT

OUTDOOR

PARKING

Étape 12 — Endpoint

Ajouter

GET /property-amenities/categories

Retour

[
  "GENERAL",
  "KITCHEN",
  "BATHROOM",
  "CONNECTIVITY"
]

Étape 13 — Compteurs

Ajouter

Nombre d'équipements par catégorie.


Sprint 4-C.1-E

Attribution aux propriétés


Étape 14 — Affectation

Utiliser

PropertyAmenityAssignment

Étape 15 — Service

Exemple

await prisma.propertyAmenityAssignment.create({
 
  data: {
 
    propertyId,
 
    amenityId
  }
});

Étape 16 — Affectation multiple

Supporter

Wifi

Parking

Piscine

Climatisation

en une seule requête.


Étape 17 — Synchronisation

Ajouter

syncPropertyAmenities()

pour remplacer totalement la liste.


Sprint 4-C.1-F

Recherche Équipements


Étape 18 — Recherche

Supporter

Code

Nom

Description

Catégorie

Étape 19 — Prisma

Exemple

OR: [
 
  {
    name: {
      contains: search,
      mode: 'insensitive'
    }
  },
 
  {
    code: {
      contains: search,
      mode: 'insensitive'
    }
  }
]

Étape 20 — Filtres

Ajouter

Catégorie

Actif

Utilisation

Sprint 4-C.1-G

Contrôleur


Étape 21 — Création

Créer

property-amenity.controller.ts

Déclaration

@ApiTags(
  'Property Amenities'
)
 
@ApiBearerAuth()
 
@Controller(
  'property-amenities'
)
 
@UseGuards(
  JwtAuthGuard
)

Étape 22 — CRUD

Ajouter

GET    /property-amenities
 
GET    /property-amenities/{id}
 
POST   /property-amenities
 
PUT    /property-amenities/{id}
 
DELETE /property-amenities/{id}

Étape 23 — Affectation

Ajouter

POST   /properties/{id}/amenities
 
GET    /properties/{id}/amenities
 
DELETE /properties/{id}/amenities/{amenityId}

Sprint 4-C.1-H

Pagination


Étape 24 — Retour

{
  "items": [],
  "meta": {
    "page": 1,
    "limit": 25,
    "total": 93
  }
}

Étape 25 — Tri

Supporter

name

category

createdAt

Sprint 4-C.1-I

Sécurité


Étape 26 — Multi-Tenant

Imposer

tenantId

sur toutes les opérations.


Étape 27 — Permissions

Ajouter

property.amenity.read

property.amenity.create

property.amenity.update

property.amenity.delete

property.amenity.assign

Étape 28 — Audit

Journaliser

PROPERTY_AMENITY_CREATED

PROPERTY_AMENITY_UPDATED

PROPERTY_AMENITY_DELETED

PROPERTY_AMENITY_ASSIGNED

PROPERTY_AMENITY_REMOVED

Sprint 4-C.1-J

Préparation Sprint 4-I


Étape 29 — Recherche

Compatible avec :

Property Search

Availability Search

Booking Search

Recommendation Engine

Étape 30 — Analytics

Préparer :

Most Used Amenities

Amenity Popularity

Amenity Conversion Rate

pour Sprint 4-J.


Définition de terminé

Le Sprint 4-C.1 est terminé lorsque :

✓ PropertyAmenityModule créé

✓ PropertyAmenityController créé

✓ PropertyAmenityService créé

✓ CRUD Amenities

✓ Catégories

✓ Attribution aux propriétés

✓ Recherche équipements

✓ Multi-tenant Security

✓ AuditLog intégré

Livrables

PropertyAmenityModule

PropertyAmenityController

PropertyAmenityService

CreatePropertyAmenityDto

AssignPropertyAmenityDto

PropertyAmenityAssignment API

Sprint 4-C.2 — Amenities Enterprise & Classification Intelligente

Objectif

Faire évoluer le catalogue des équipements vers un moteur intelligent capable d'alimenter :

Recherche avancée

Matching réservation

Scoring propriétés

Recommandations IA

Revenue Management

Analytics

À l'issue de cette étape :

✓ Hiérarchie équipements

✓ Tags équipements

✓ Popularité

✓ Scoring équipements

✓ Recommandations automatiques

✓ Classification IA

✓ Amenity Intelligence Engine

Architecture cible

PropertyAmenity

↓

Amenity Intelligence

├── Hierarchy
├── Tags
├── Popularity
├── Scoring
├── Recommendations
└── AI Classification

↓

Property Search

↓

Booking Engine

↓

Recommendation Engine

Sprint 4-C.2-A

Hiérarchie des Équipements


Étape 1 — Extension PropertyAmenity

Ajouter dans schema.prisma

parentAmenityId      String?

Étape 2 — Relations

Ajouter

parentAmenity PropertyAmenity?
              @relation(
                "AmenityHierarchy",
                fields:[parentAmenityId],
                references:[id]
              )
 
children PropertyAmenity[]
         @relation(
           "AmenityHierarchy"
         )

Étape 3 — Cas d'usage

Exemple

CONNECTIVITY

├── WIFI
├── FIBER
├── ETHERNET
└── WORKSPACE

Exemple

OUTDOOR

├── TERRACE
├── GARDEN
├── BBQ
└── PRIVATE_POOL

Étape 4 — Niveau

Ajouter

hierarchyLevel      Int
                    @default(0)

Sprint 4-C.2-B

Tags Équipements


Étape 5 — Création

Ajouter

model AmenityTag {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  code                  String
 
  name                  String
 
  createdAt             DateTime
                        @default(now())
 
  amenities             AmenityTagAssignment[]
 
  @@unique([
    tenantId,
    code
  ])
 
  @@index([tenantId])
}

Étape 6 — Affectation

Ajouter

model AmenityTagAssignment {
 
  id                    String
                        @id
                        @default(uuid())
 
  amenityId             String
 
  tagId                 String
 
  amenity               PropertyAmenity
                        @relation(
                          fields:[amenityId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  tag                   AmenityTag
                        @relation(
                          fields:[tagId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@unique([
    amenityId,
    tagId
  ])
}

Étape 7 — Tags standards

Prévoir

PREMIUM

LUXURY

BUSINESS

FAMILY

ACCESSIBLE

PET_FRIENDLY

REMOTE_WORK

ECO_FRIENDLY

Sprint 4-C.2-C

Popularité


Étape 8 — Popularité

Ajouter dans PropertyAmenity

usageCount           Int
                     @default(0)
 
searchCount          Int
                     @default(0)
 
bookingImpactScore   Float?

Étape 9 — Calcul

Alimenter via

Property Search

Bookings

Property Views

Recommendations

Étape 10 — Classement

Exemple

Wifi

Utilisé dans 94% des biens

Exemple

Piscine

Impact réservation +22%

Sprint 4-C.2-D

Scoring Équipements


Étape 11 — AmenityScore

Créer

model AmenityScore {
 
  id                    String
                        @id
                        @default(uuid())
 
  amenityId             String
                        @unique
 
  popularityScore       Float
                        @default(0)
 
  conversionScore       Float
                        @default(0)
 
  revenueScore          Float
                        @default(0)
 
  recommendationScore   Float
                        @default(0)
 
  globalScore           Float
                        @default(0)
 
  calculatedAt          DateTime
                        @default(now())
 
  amenity               PropertyAmenity
                        @relation(
                          fields:[amenityId],
                          references:[id],
                          onDelete:Cascade
                        )
}

Étape 12 — Calcul

Pondération

Popularity      30%

Conversion      30%

Revenue         20%

Recommendation  20%

Étape 13 — Classification

90-100 Elite

75-89 Premium

50-74 Standard

0-49 Basic

Sprint 4-C.2-E

Recommandations Automatiques


Étape 14 — AmenityRecommendation

Ajouter

model AmenityRecommendation {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  amenityId             String
 
  recommendationScore   Float
 
  reason                String?
 
  accepted              Boolean?
 
  createdAt             DateTime
                        @default(now())
 
  @@index([propertyId])
 
  @@index([amenityId])
}

Étape 15 — AmenityRecommendationService

Créer

amenity-recommendation.service.ts

Méthodes

generateRecommendations()
 
findMissingAmenities()
 
compareSimilarProperties()

Étape 16 — Exemples

Cas

Villa Premium

Sans Piscine

↓

Suggestion
PRIVATE_POOL

Cas

Appartement Business

Sans Wifi

↓

Suggestion
WIFI

Sprint 4-C.2-F

Classification IA


Étape 17 — AmenityClassificationService

Créer

amenity-classification.service.ts

Méthodes

classifyAmenity()
 
detectCategory()
 
generateTags()
 
detectPremiumLevel()

Étape 18 — Exemple

Entrée

Borne recharge Tesla

Résultat

Category:
PARKING

Tags:
PREMIUM
ECO_FRIENDLY

Score:
82

Étape 19 — Auto-tagging

Générer automatiquement

Luxury

Business

Family

Accessibility

Sprint 4-C.2-G

Analytics


Étape 20 — AmenityAnalyticsService

Créer

amenity-analytics.service.ts

Méthodes

getMostPopularAmenities()
 
getHighestRevenueAmenities()
 
getConversionImpact()

Étape 21 — KPI

Top Amenities

Revenue Impact

Booking Impact

Search Impact

Étape 22 — Endpoint

Ajouter

GET /property-amenities/analytics

Sprint 4-C.2-H

API Enterprise


Étape 23 — Endpoints

Ajouter

GET /property-amenities/hierarchy
 
GET /property-amenities/recommendations
 
GET /property-amenities/analytics
 
POST /property-amenities/classify

Étape 24 — Exemple

Retour

{
  "amenity":"WIFI",
  "globalScore":96,
  "classification":"ELITE"
}

Sprint 4-C.2-I

Audit & Sécurité


Étape 25 — AuditLog

Journaliser

AMENITY_CLASSIFIED

AMENITY_RECOMMENDED

AMENITY_SCORE_UPDATED

AMENITY_TAG_ASSIGNED

Étape 26 — Permissions

Ajouter

property.amenity.analytics

property.amenity.recommend

property.amenity.classify

Sprint 4-C.2-J

Préparation Future


Étape 27 — Compatible Sprint 4-I

Property Search

Recommendation Engine

Smart Filters

Étape 28 — Compatible Sprint 4-J

Property Analytics

Revenue Analytics

Property Intelligence

Étape 29 — Compatible Sprint 13

AI Recommendations

Knowledge Graph

Property Intelligence

Étape 30 — Migration

Générer

npx prisma migrate dev \
--name amenity_intelligence

Générer

npx prisma generate

Définition de terminé

Le Sprint 4-C.2 est terminé lorsque :

✓ Hiérarchie équipements

✓ Tags équipements

✓ Popularité

✓ Scoring équipements

✓ Recommandations automatiques

✓ Classification IA

✓ Analytics équipements

✓ API Enterprise

✓ Audit intégré

Livrables

AmenityTag

AmenityTagAssignment

AmenityScore

AmenityRecommendation

AmenityRecommendationService

AmenityClassificationService

AmenityAnalyticsService

Amenity Intelligence Engine

Sprint 4-D.1 — Gestion des Images des Propriétés

Objectif

Implémenter la gestion complète des médias immobiliers afin d'alimenter :

Catalogue

Moteur de réservation

Galerie Property

Marketing

SEO

Analytics

À l'issue de cette étape :

✓ PropertyImage

✓ PropertyImageModule

✓ PropertyImageController

✓ PropertyImageService

✓ Upload

✓ Galerie

✓ Ordonnancement

✓ Multi-Tenant Security

Architecture cible

Property

↓

PropertyImage

↓

Storage Layer

(MinIO / S3)

↓

Image Processing

↓

Gallery API

↓

Property Catalog

Sprint 4-D.1-A

Extension Prisma


Étape 1 — Création PropertyImage

Ajouter dans schema.prisma

model PropertyImage {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String
 
  fileName              String
 
  originalFileName      String
 
  mimeType              String
 
  fileSize              Int
 
  storagePath           String
 
  publicUrl             String?
 
  title                 String?
 
  altText               String?
 
  caption               String?
 
  displayOrder          Int
                        @default(0)
 
  isPrimary             Boolean
                        @default(false)
 
  width                 Int?
 
  height                Int?
 
  uploadedAt            DateTime
                        @default(now())
 
  deletedAt             DateTime?
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@index([tenantId])
 
  @@index([propertyId])
 
  @@index([displayOrder])
 
  @@index([isPrimary])
}

Étape 2 — Relation Property

Ajouter dans Property

images PropertyImage[]

Étape 3 — Migration

Générer

npx prisma migrate dev \
--name property_images

Générer

npx prisma generate

Sprint 4-D.1-B

Module


Étape 4 — Création

src/modules/property-images

├── application
│
│   └── dto
│
│       ├── upload-property-image.dto.ts
│
│       ├── reorder-property-images.dto.ts
│
│       └── property-image-response.dto.ts
│
├── domain
│
│   └── services
│
│       └── property-image.service.ts
│
├── presentation
│
│   └── controllers
│
│       └── property-image.controller.ts
│
└── property-image.module.ts

Étape 5 — Module

Créer

@Module({
 
  imports: [
    PrismaModule,
    StorageModule,
    AuthModule,
    AuditModule
  ],
 
  controllers: [
    PropertyImageController
  ],
 
  providers: [
    PropertyImageService
  ],
 
  exports: [
    PropertyImageService
  ]
})
export class PropertyImageModule {}

Sprint 4-D.1-C

DTOs


Étape 6 — Upload

Créer

export class UploadPropertyImageDto {
 
  title?: string;
 
  altText?: string;
 
  caption?: string;
 
  isPrimary?: boolean;
}

Étape 7 — Réorganisation

Créer

export class ReorderPropertyImagesDto {
 
  images: {
 
    id: string;
 
    order: number;
 
  }[];
}

Sprint 4-D.1-D

PropertyImageService


Étape 8 — Création

Créer

property-image.service.ts

Méthodes

findAll()
 
upload()
 
delete()
 
reorder()
 
setPrimary()

Étape 9 — Upload

Workflow

Upload

↓

Validation

↓

Storage

↓

Prisma

↓

Gallery

Étape 10 — Exemple

const image =
  await storage.upload(file);
 
await prisma.propertyImage.create({
 
  data: {
 
    tenantId,
 
    propertyId,
 
    storagePath:
      image.path,
 
    publicUrl:
      image.url
  }
});

Étape 11 — Validation

Autoriser

image/jpeg

image/png

image/webp

Taille maximale

10 MB

Sprint 4-D.1-E

Galerie


Étape 12 — Liste

Endpoint

GET /properties/{id}/images

Retour

[
  {
    "id":"uuid",
    "url":"...",
    "isPrimary":true
  }
]

Étape 13 — Image principale

Garantir

Une seule image :

isPrimary = true

par propriété.


Étape 14 — Tri

Utiliser

displayOrder ASC

Sprint 4-D.1-F

Ordonnancement


Étape 15 — Endpoint

Ajouter

PUT /properties/{id}/images/order

Étape 16 — Mise à jour

Exemple

{
  "images":[
    {
      "id":"1",
      "order":1
    },
    {
      "id":"2",
      "order":2
    }
  ]
}

Étape 17 — Transaction

Utiliser

prisma.$transaction()

pour garantir la cohérence.


Sprint 4-D.1-G

Suppression


Étape 18 — Endpoint

Ajouter

DELETE /properties/{id}/images/{imageId}

Étape 19 — Workflow

Prisma

↓

Storage

↓

Audit

Étape 20 — Protection

Refuser

Suppression de la dernière image principale.


Sprint 4-D.1-H

Contrôleur


Étape 21 — Création

Créer

property-image.controller.ts

Déclaration

@ApiTags(
  'Property Images'
)
 
@ApiBearerAuth()
 
@Controller(
  'properties/:id/images'
)
 
@UseGuards(
  JwtAuthGuard
)

Étape 22 — Endpoints

Ajouter

GET    /properties/{id}/images
 
POST   /properties/{id}/images
 
PUT    /properties/{id}/images/order
 
DELETE /properties/{id}/images/{imageId}

Étape 23 — Upload

Utiliser

@UseInterceptors(
  FileInterceptor('file')
)

Sprint 4-D.1-I

Sécurité


Étape 24 — Multi-Tenant

Vérifier

tenantId

propertyId

avant toute opération.


Étape 25 — Permissions

Ajouter

property.image.read

property.image.upload

property.image.update

property.image.delete

Étape 26 — Audit

Journaliser

PROPERTY_IMAGE_UPLOADED

PROPERTY_IMAGE_REORDERED

PROPERTY_IMAGE_DELETED

PROPERTY_PRIMARY_IMAGE_CHANGED

Sprint 4-D.1-J

Préparation Sprint 4-D.2


Étape 27 — Préparer

Compatible avec :

MinIO

AWS S3

CDN

Thumbnail Generation

Image Optimization

Étape 28 — Préparer

Compatible avec :

Property Gallery

SEO Images

Marketing Assets

Review Images

Définition de terminé

Le Sprint 4-D.1 est terminé lorsque :

✓ PropertyImage créé

✓ PropertyImageModule créé

✓ PropertyImageController créé

✓ PropertyImageService créé

✓ Upload opérationnel

✓ Galerie opérationnelle

✓ Ordonnancement opérationnel

✓ Multi-tenant Security

✓ AuditLog intégré

Livrables

PropertyImage

PropertyImageModule

PropertyImageController

PropertyImageService

UploadPropertyImageDto

ReorderPropertyImagesDto

Property Gallery API

Sprint 4-D.2 — Gestion Média Enterprise & Optimisation d'Images

Objectif

Transformer la gestion d'images Property en véritable plateforme média Enterprise.

À l'issue de cette étape :

✓ MinIO / S3

✓ CDN

✓ Thumbnails

✓ WebP

✓ Compression

✓ Watermark

✓ Vision IA

✓ Détection qualité

✓ Media Intelligence Platform

Architecture cible

PropertyImage

↓

Media Platform

├── Storage
├── CDN
├── Image Processing
├── AI Vision
├── Optimization
└── Analytics

↓

Property Catalog

↓

Reservation Platform

Sprint 4-D.2-A

Architecture de Stockage


Étape 1 — Extension PropertyImage

Ajouter dans schema.prisma

storageProvider       String?
 
cdnUrl                String?
 
thumbnailUrl          String?
 
mediumUrl             String?
 
largeUrl              String?
 
webpUrl               String?
 
checksum              String?
 
processingStatus      ImageProcessingStatus
                       @default(PENDING)

Étape 2 — Enum

Ajouter

enum ImageProcessingStatus {
 
  PENDING
 
  PROCESSING
 
  COMPLETED
 
  FAILED
}

Étape 3 — Migration

Générer

npx prisma migrate dev \
--name media_platform

Sprint 4-D.2-B

Storage Enterprise


Étape 4 — MediaModule

Créer

src/modules/media

├── storage
│
├── image-processing
│
├── ai-vision
│
├── cdn
│
└── analytics

Étape 5 — StorageService

Créer

storage.service.ts

Interface

upload()
 
delete()
 
copy()
 
move()
 
exists()
 
generateSignedUrl()

Étape 6 — Providers

Supporter

MinIO

AWS S3

Cloudflare R2

Azure Blob

Google Cloud Storage

Étape 7 — Configuration

Ajouter

STORAGE_PROVIDER=minio
 
MINIO_ENDPOINT=
 
MINIO_BUCKET=
 
MINIO_ACCESS_KEY=
 
MINIO_SECRET_KEY=

Sprint 4-D.2-C

CDN


Étape 8 — CDN Service

Créer

cdn.service.ts

Méthodes

buildUrl()
 
invalidate()
 
purgeCache()

Étape 9 — Fournisseurs

Préparer

Cloudflare

CloudFront

Fastly

Bunny CDN

Étape 10 — URLs

Générer

thumbnailUrl

mediumUrl

largeUrl

webpUrl

automatiquement.


Sprint 4-D.2-D

Génération des Variantes


Étape 11 — ImageProcessingService

Créer

image-processing.service.ts

Librairie

Sharp

Étape 12 — Générer

Formats

Thumbnail

Medium

Large

WebP

Étape 13 — Tailles

Thumbnail : 300px

Medium    : 1200px

Large     : 2400px

Étape 14 — Workflow

Upload

↓

Original

↓

Resize

↓

WebP

↓

CDN

↓

Gallery

Sprint 4-D.2-E

Compression


Étape 15 — Optimisation

Utiliser

Sharp

MozJPEG

WebP

Étape 16 — Objectifs

JPEG 80%

WebP 75%

PNG optimisé

Étape 17 — KPI

Calculer

Compression Ratio

Storage Saved

Bandwidth Saved

Sprint 4-D.2-F

Watermark


Étape 18 — WatermarkService

Créer

watermark.service.ts

Supporter

Logo

Texte

Dynamic Branding

Étape 19 — Configuration

Ajouter

Position

Opacity

Scale

Margins

Étape 20 — Cas d'usage

Marketplace

Partenaires

Protection contenu

Sprint 4-D.2-G

Vision IA


Étape 21 — ImageVisionAnalysis

Ajouter

model ImageVisionAnalysis {
 
  id                    String
                        @id
                        @default(uuid())
 
  imageId               String
                        @unique
 
  labels                Json?
 
  objects               Json?
 
  qualityScore          Float?
 
  blurScore             Float?
 
  brightnessScore       Float?
 
  adultContentDetected  Boolean
                        @default(false)
 
  duplicateDetected     Boolean
                        @default(false)
 
  analyzedAt            DateTime
                        @default(now())
 
  image                 PropertyImage
                        @relation(
                          fields:[imageId],
                          references:[id],
                          onDelete:Cascade
                        )
}

Étape 22 — VisionService

Créer

vision-analysis.service.ts

Fournisseurs

AWS Rekognition

Google Vision

Azure Vision

OpenAI Vision

Étape 23 — Détections

Bedroom

Bathroom

Kitchen

Pool

Garden

Sea View

Pets

Étape 24 — Auto-tagging

Exemple

Photo

↓

Pool

↓

Amenity:
PRIVATE_POOL

Sprint 4-D.2-H

Détection Qualité


Étape 25 — QualityScore

Calculer

Sharpness

Brightness

Contrast

Resolution

Composition

Étape 26 — Classification

90-100 Excellent

75-89 Good

50-74 Acceptable

0-49 Poor

Étape 27 — Recommandations

Exemple

Image sombre

↓

Augmenter luminosité

Image floue

↓

Remplacer photo

Sprint 4-D.2-I

Analytics Média


Étape 28 — MediaAnalyticsService

Créer

media-analytics.service.ts

KPI

Images Uploaded

Storage Used

Compression Ratio

AI Quality Score

Most Viewed Images

Étape 29 — Endpoint

Ajouter

GET /media/analytics

Sprint 4-D.2-J

API Enterprise


Étape 30 — Endpoints

Ajouter

POST /media/process
 
POST /media/watermark
 
POST /media/analyze
 
GET  /media/analytics
 
GET  /media/storage

Étape 31 — AuditLog

Journaliser

IMAGE_UPLOADED

IMAGE_PROCESSED

IMAGE_ANALYZED

IMAGE_WATERMARKED

IMAGE_OPTIMIZED

Étape 32 — Permissions

Ajouter

media.read

media.upload

media.process

media.analyze

media.admin

Préparation Sprint 4-H

Compatible avec :

Review Images

User Uploads

Moderation

Préparation Sprint 4-I

Compatible avec :

Property Search

AI Ranking

Visual Search

Préparation Sprint 13

Compatible avec :

Computer Vision

Property Intelligence

AI Classification

Knowledge Graph

Préparation Sprint 20

Compatible avec :

Enterprise Media Platform

Global CDN

AI Vision

Digital Asset Management

Définition de terminé

Le Sprint 4-D.2 est terminé lorsque :

✓ MinIO/S3 intégré

✓ CDN intégré

✓ Variantes d'images

✓ WebP

✓ Compression

✓ Watermark

✓ Vision IA

✓ Détection qualité

✓ Analytics média

✓ Audit intégré

Livrables

StorageService

ImageProcessingService

CDNService

WatermarkService

VisionAnalysisService

MediaAnalyticsService

ImageVisionAnalysis

Enterprise Media Platform

Sprint 4-E.1 — Gestion des Disponibilités

Objectif

Implémenter le moteur de disponibilités des propriétés.

Cette couche constitue la fondation du futur moteur de réservation.

À l'issue de cette étape :

✓ PropertyAvailability

✓ PropertyAvailabilityModule

✓ PropertyAvailabilityController

✓ PropertyAvailabilityService

✓ Calendrier

✓ Blocages

✓ Inventaire

✓ Reservation Ready

Architecture cible

Property

↓

PropertyAvailability

↓

Calendar Engine

↓

Inventory Engine

↓

Reservation Engine

Sprint 4-E.1-A

Extension Prisma


Étape 1 — Création PropertyAvailability

Ajouter dans schema.prisma

model PropertyAvailability {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String
 
  startDate             DateTime
 
  endDate               DateTime
 
  status                AvailabilityStatus
 
  inventory             Int
                        @default(1)
 
  availableUnits        Int
                        @default(1)
 
  reason                String?
 
  notes                 String?
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@index([tenantId])
 
  @@index([propertyId])
 
  @@index([startDate])
 
  @@index([endDate])
 
  @@index([status])
}

Étape 2 — Enum

Ajouter

enum AvailabilityStatus {
 
  AVAILABLE
 
  BLOCKED
 
  RESERVED
 
  MAINTENANCE
 
  CLOSED
}

Étape 3 — Relation

Ajouter dans Property

availabilities PropertyAvailability[]

Étape 4 — Migration

Générer

npx prisma migrate dev \
--name property_availability

Générer

npx prisma generate

Sprint 4-E.1-B

Module


Étape 5 — Création

src/modules/property-availability

├── application
│
│   └── dto
│
│       ├── create-property-availability.dto.ts
│
│       ├── update-property-availability.dto.ts
│
│       ├── availability-query.dto.ts
│
│       └── calendar-response.dto.ts
│
├── domain
│
│   └── services
│
│       └── property-availability.service.ts
│
├── presentation
│
│   └── controllers
│
│       └── property-availability.controller.ts
│
└── property-availability.module.ts

Étape 6 — Module

Créer

@Module({
 
  imports: [
    PrismaModule,
    AuthModule,
    AuditModule
  ],
 
  controllers: [
    PropertyAvailabilityController
  ],
 
  providers: [
    PropertyAvailabilityService
  ],
 
  exports: [
    PropertyAvailabilityService
  ]
})
export class PropertyAvailabilityModule {}

Sprint 4-E.1-C

DTOs


Étape 7 — CreatePropertyAvailabilityDto

Créer

export class CreatePropertyAvailabilityDto {
 
  startDate: Date;
 
  endDate: Date;
 
  status: AvailabilityStatus;
 
  inventory?: number;
 
  availableUnits?: number;
 
  reason?: string;
 
  notes?: string;
}

Étape 8 — UpdatePropertyAvailabilityDto

Créer

export class UpdatePropertyAvailabilityDto
  extends PartialType(
    CreatePropertyAvailabilityDto
  ) {}

Étape 9 — AvailabilityQueryDto

Créer

export class AvailabilityQueryDto {
 
  startDate?: Date;
 
  endDate?: Date;
 
  status?: AvailabilityStatus;
}

Sprint 4-E.1-D

PropertyAvailabilityService


Étape 10 — Création

Créer

property-availability.service.ts

Méthodes

findAll()
 
findCalendar()
 
create()
 
update()
 
remove()
 
checkAvailability()

Étape 11 — Création

Exemple

async create(
  tenantId: string,
  propertyId: string,
  dto: CreatePropertyAvailabilityDto,
) {
 
  return this.prisma.propertyAvailability.create({
 
    data: {
 
      tenantId,
 
      propertyId,
 
      ...dto
    }
  });
}

Étape 12 — Validation

Vérifier

startDate < endDate

et absence de conflits.


Étape 13 — Détection de chevauchement

Refuser

Périodes
superposées

pour les statuts incompatibles.


Prisma

where: {
 
  propertyId,
 
  startDate: {
    lte: dto.endDate
  },
 
  endDate: {
    gte: dto.startDate
  }
}

Sprint 4-E.1-E

Calendrier


Étape 14 — Endpoint

Ajouter

GET /properties/{id}/availability

Étape 15 — Vue calendrier

Retour

[
  {
    "startDate":"2026-07-01",
    "endDate":"2026-07-10",
    "status":"AVAILABLE"
  }
]

Étape 16 — Vue mensuelle

Ajouter

GET /properties/{id}/availability/calendar

Paramètres

month

year

Sprint 4-E.1-F

Blocages


Étape 17 — Supporter

Maintenance

Travaux

Usage privé

Fermeture saisonnière

Étape 18 — Exemple

{
  "status":"MAINTENANCE",
  "reason":"Pool renovation"
}

Étape 19 — Endpoint

Ajouter

POST /properties/{id}/availability/block

Sprint 4-E.1-G

Inventaire


Étape 20 — Support Multi-unités

Utiliser

inventory

availableUnits

Étape 21 — Exemple

Inventaire : 10

Disponibles : 7

Réservées : 3

Étape 22 — Vérification

Empêcher

availableUnits
>
inventory

Sprint 4-E.1-H

Contrôleur


Étape 23 — Création

Créer

property-availability.controller.ts

Déclaration

@ApiTags(
  'Property Availability'
)
 
@ApiBearerAuth()
 
@Controller(
  'properties/:id/availability'
)
 
@UseGuards(
  JwtAuthGuard
)

Étape 24 — Endpoints

Ajouter

GET    /properties/{id}/availability
 
GET    /properties/{id}/availability/calendar
 
POST   /properties/{id}/availability
 
PUT    /properties/{id}/availability/{availabilityId}
 
DELETE /properties/{id}/availability/{availabilityId}
 
POST   /properties/{id}/availability/block

Sprint 4-E.1-I

Sécurité


Étape 25 — Multi-Tenant

Vérifier

tenantId

propertyId

sur toutes les opérations.


Étape 26 — Permissions

Ajouter

property.availability.read

property.availability.create

property.availability.update

property.availability.delete

property.availability.manage

Étape 27 — Audit

Journaliser

PROPERTY_AVAILABILITY_CREATED

PROPERTY_AVAILABILITY_UPDATED

PROPERTY_AVAILABILITY_DELETED

PROPERTY_BLOCKED

PROPERTY_UNBLOCKED

Sprint 4-E.1-J

Préparation Sprint 4-E.2


Étape 28 — Compatibilité

Préparer :

Reservation

Booking Engine

Inventory Engine

Channel Manager

Étape 29 — Préparer

Compatible avec :

iCal

Airbnb

Booking.com

Expedia

Étape 30 — Préparer

Compatible avec :

Dynamic Pricing

Yield Management

Revenue Engine

Définition de terminé

Le Sprint 4-E.1 est terminé lorsque :

✓ PropertyAvailability créé

✓ PropertyAvailabilityModule créé

✓ PropertyAvailabilityController créé

✓ PropertyAvailabilityService créé

✓ Calendrier opérationnel

✓ Blocages opérationnels

✓ Inventaire opérationnel

✓ Multi-tenant Security

✓ AuditLog intégré

Livrables

PropertyAvailability

AvailabilityStatus

PropertyAvailabilityModule

PropertyAvailabilityController

PropertyAvailabilityService

Availability Calendar API

Sprint 4-E.2 — Disponibilités Enterprise & Synchronisation Multi-Canaux

Objectif

Transformer le moteur de disponibilités en véritable plateforme Channel Manager Enterprise.

À l'issue de cette étape :

✓ iCal

✓ Airbnb Sync

✓ Booking.com Sync

✓ Expedia Sync

✓ Channel Manager

✓ Availability Intelligence

✓ Conflict Resolution

✓ Multi-Channel Inventory

Architecture cible

Property Availability

↓

Channel Manager

├── iCal
├── Airbnb
├── Booking.com
├── Expedia
├── Direct Booking
└── Future OTA Connectors

↓

Availability Intelligence

↓

Reservation Engine

Sprint 4-E.2-A

Extension Prisma


Étape 1 — ChannelConnection

Ajouter dans schema.prisma

model ChannelConnection {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String
 
  channelType           ChannelType
 
  externalPropertyId    String?
 
  syncEnabled           Boolean
                        @default(true)
 
  lastSyncAt            DateTime?
 
  syncStatus            SyncStatus
                        @default(PENDING)
 
  configuration         Json?
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@index([tenantId])
 
  @@index([propertyId])
 
  @@index([channelType])
}

Étape 2 — AvailabilitySyncLog

Ajouter

model AvailabilitySyncLog {
 
  id                    String
                        @id
                        @default(uuid())
 
  channelConnectionId   String
 
  syncType              SyncType
 
  status                SyncStatus
 
  startedAt             DateTime
 
  completedAt           DateTime?
 
  recordsProcessed      Int
                        @default(0)
 
  errorMessage          String?
 
  payload               Json?
 
  @@index([status])
 
  @@index([startedAt])
}

Étape 3 — AvailabilityConflict

Ajouter

model AvailabilityConflict {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  channelType           ChannelType
 
  conflictType          ConflictType
 
  localData             Json
 
  externalData          Json
 
  resolved              Boolean
                        @default(false)
 
  resolvedAt            DateTime?
 
  resolvedBy            String?
 
  createdAt             DateTime
                        @default(now())
 
  @@index([propertyId])
 
  @@index([resolved])
}

Étape 4 — Enums

Ajouter

enum ChannelType {
 
  ICAL
 
  AIRBNB
 
  BOOKING
 
  EXPEDIA
 
  DIRECT
}
 
enum SyncStatus {
 
  PENDING
 
  RUNNING
 
  SUCCESS
 
  FAILED
 
  PARTIAL
}
 
enum SyncType {
 
  IMPORT
 
  EXPORT
 
  BIDIRECTIONAL
}
 
enum ConflictType {
 
  INVENTORY
 
  BOOKING
 
  AVAILABILITY
 
  PRICE
}

Étape 5 — Migration

Générer

npx prisma migrate dev \
--name channel_manager

Sprint 4-E.2-B

Channel Manager Module


Étape 6 — Création

src/modules/channel-manager

├── connectors
│
│   ├── ical
│
│   ├── airbnb
│
│   ├── booking
│
│   └── expedia
│
├── synchronization
│
├── conflict-resolution
│
├── intelligence
│
└── channel-manager.module.ts

Étape 7 — Services

Créer

ChannelManagerService

AvailabilitySyncService

ConflictResolutionService

AvailabilityIntelligenceService

Sprint 4-E.2-C

Synchronisation iCal


Étape 8 — IcalConnection

Ajouter

icalUrl              String?
icalExportUrl        String?

dans :

ChannelConnection

Étape 9 — IcalSyncService

Créer

ical-sync.service.ts

Méthodes

importCalendar()
 
exportCalendar()
 
syncCalendar()

Étape 10 — Endpoints

Ajouter

POST /channels/ical/connect
 
POST /channels/ical/sync
 
GET  /channels/ical/status

Sprint 4-E.2-D

Airbnb Connector


Étape 11 — AirbnbConnector

Créer

airbnb-connector.service.ts

Fonctions

syncAvailability()
 
syncInventory()
 
syncReservations()

Étape 12 — Mapping

Synchroniser

Property

Availability

Inventory

Reservations

Étape 13 — Endpoint

Ajouter

POST /channels/airbnb/connect
 
POST /channels/airbnb/sync

Sprint 4-E.2-E

Booking.com Connector


Étape 14 — BookingConnector

Créer

booking-connector.service.ts

Fonctions

syncAvailability()
 
syncInventory()
 
syncRates()

Étape 15 — Endpoint

Ajouter

POST /channels/booking/connect
 
POST /channels/booking/sync

Sprint 4-E.2-F

Expedia Connector


Étape 16 — ExpediaConnector

Créer

expedia-connector.service.ts

Fonctions

syncAvailability()
 
syncInventory()
 
syncRates()

Étape 17 — Endpoint

Ajouter

POST /channels/expedia/connect
 
POST /channels/expedia/sync

Sprint 4-E.2-G

Résolution de Conflits


Étape 18 — ConflictResolutionService

Créer

conflict-resolution.service.ts

Méthodes

detectConflicts()
 
resolveConflict()
 
autoResolve()

Étape 19 — Types

Détecter

Double réservation

Inventaire incohérent

Disponibilité divergente

Tarif divergent

Étape 20 — Politique

Priorité

Reservation Engine

↓

Direct Booking

↓

OTA

Sprint 4-E.2-H

Availability Intelligence


Étape 21 — AvailabilityIntelligenceService

Créer

availability-intelligence.service.ts

Méthodes

detectGaps()
 
forecastOccupancy()
 
recommendAvailabilityRules()

Étape 22 — Détections

Identifier

Dates non ouvertes

Blocages anormaux

Fenêtres d'opportunité

Périodes sous-occupées

Étape 23 — Exemple

Weekend libre

Taux occupation élevé

↓

Suggestion ouverture

Sprint 4-E.2-I

Dashboard Channel Manager


Étape 24 — Endpoint

Ajouter

GET /channels/dashboard

Retour

{
  "connectedChannels":4,
  "lastSync":"2026-07-01T10:00:00Z",
  "pendingConflicts":2,
  "occupancyForecast":84
}

Étape 25 — Monitoring

Afficher

Canaux actifs

Derniers syncs

Erreurs

Conflits

Performance OTA

Sprint 4-E.2-J

Sécurité & Gouvernance


Étape 26 — Permissions

Ajouter

channel.read

channel.manage

channel.sync

channel.resolve

channel.admin

Étape 27 — Audit

Journaliser

CHANNEL_CONNECTED

CHANNEL_SYNC_STARTED

CHANNEL_SYNC_COMPLETED

CHANNEL_CONFLICT_DETECTED

CHANNEL_CONFLICT_RESOLVED

Étape 28 — Jobs

Ajouter

Cron :

Toutes les 15 min

iCal Sync

OTA Sync

Conflict Detection

Étape 29 — Compatibilité Sprint 5

Préparer :

Reservation

Booking Engine

Inventory Locking

Overbooking Protection

Étape 30 — Compatibilité Sprint 20

Préparer :

Enterprise Channel Manager

Multi OTA

Revenue Management

Enterprise Inventory

Définition de terminé

Le Sprint 4-E.2 est terminé lorsque :

✓ iCal Sync

✓ Airbnb Connector

✓ Booking Connector

✓ Expedia Connector

✓ Channel Manager

✓ Conflict Resolution

✓ Availability Intelligence

✓ Dashboard

✓ Audit intégré

Livrables

ChannelConnection

AvailabilitySyncLog

AvailabilityConflict

ChannelManagerService

AvailabilitySyncService

ConflictResolutionService

AvailabilityIntelligenceService

Enterprise Channel Manager

Sprint 4-F.1 — Gestion de la Tarification

Objectif

Implémenter le moteur tarifaire des propriétés.

Cette couche constitue la fondation du futur Revenue Management System.

À l'issue de cette étape :

✓ PropertyPricing

✓ PropertyPricingModule

✓ PropertyPricingController

✓ PropertyPricingService

✓ Tarifs de base

✓ Tarifs saisonniers

✓ Tarifs par période

✓ Inventaire tarifaire

✓ Revenue Ready

Architecture cible

Property

↓

PropertyPricing

↓

Pricing Engine

↓

Reservation Engine

↓

Revenue Management

Sprint 4-F.1-A

Extension Prisma


Étape 1 — Création PropertyPricing

Ajouter dans schema.prisma

model PropertyPricing {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String
 
  pricingType           PricingType
 
  name                  String
 
  startDate             DateTime?
 
  endDate               DateTime?
 
  basePrice             Decimal
                        @db.Decimal(12,2)
 
  weekendPrice          Decimal?
                        @db.Decimal(12,2)
 
  extraGuestPrice       Decimal?
                        @db.Decimal(12,2)
 
  cleaningFee           Decimal?
                        @db.Decimal(12,2)
 
  serviceFee            Decimal?
                        @db.Decimal(12,2)
 
  securityDeposit       Decimal?
                        @db.Decimal(12,2)
 
  minimumStay           Int?
                        @default(1)
 
  maximumStay           Int?
 
  priority              Int
                        @default(0)
 
  active                Boolean
                        @default(true)
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@index([tenantId])
 
  @@index([propertyId])
 
  @@index([pricingType])
 
  @@index([startDate])
 
  @@index([endDate])
 
  @@index([active])
}

Étape 2 — Enum PricingType

Ajouter

enum PricingType {
 
  BASE
 
  SEASONAL
 
  SPECIAL_EVENT
 
  PROMOTIONAL
 
  LAST_MINUTE
 
  LONG_STAY
}

Étape 3 — Relation

Ajouter dans Property

pricingRules PropertyPricing[]

Étape 4 — Migration

Générer

npx prisma migrate dev \
--name property_pricing

Générer

npx prisma generate

Sprint 4-F.1-B

Module


Étape 5 — Création

src/modules/property-pricing

├── application
│
│   └── dto
│
│       ├── create-property-pricing.dto.ts
│
│       ├── update-property-pricing.dto.ts
│
│       ├── pricing-query.dto.ts
│
│       └── pricing-calculation.dto.ts
│
├── domain
│
│   └── services
│
│       ├── property-pricing.service.ts
│
│       └── pricing-calculation.service.ts
│
├── presentation
│
│   └── controllers
│
│       └── property-pricing.controller.ts
│
└── property-pricing.module.ts

Étape 6 — Module

Créer

@Module({
 
  imports: [
    PrismaModule,
    AuthModule,
    AuditModule
  ],
 
  controllers: [
    PropertyPricingController
  ],
 
  providers: [
    PropertyPricingService,
    PricingCalculationService
  ],
 
  exports: [
    PropertyPricingService,
    PricingCalculationService
  ]
})
export class PropertyPricingModule {}

Sprint 4-F.1-C

DTOs


Étape 7 — CreatePropertyPricingDto

Créer

export class CreatePropertyPricingDto {
 
  pricingType: PricingType;
 
  name: string;
 
  startDate?: Date;
 
  endDate?: Date;
 
  basePrice: number;
 
  weekendPrice?: number;
 
  extraGuestPrice?: number;
 
  cleaningFee?: number;
 
  serviceFee?: number;
 
  securityDeposit?: number;
 
  minimumStay?: number;
 
  maximumStay?: number;
 
  priority?: number;
}

Étape 8 — UpdatePropertyPricingDto

Créer

export class UpdatePropertyPricingDto
  extends PartialType(
    CreatePropertyPricingDto
  ) {}

Étape 9 — PricingQueryDto

Créer

export class PricingQueryDto {
 
  startDate?: Date;
 
  endDate?: Date;
 
  pricingType?: PricingType;
 
  active?: boolean;
}

Sprint 4-F.1-D

PropertyPricingService


Étape 10 — Création

Créer

property-pricing.service.ts

Méthodes

findAll()
 
findById()
 
create()
 
update()
 
remove()
 
findApplicablePricing()

Étape 11 — Validation

Vérifier

basePrice > 0

minimumStay >= 1

startDate <= endDate

Étape 12 — Gestion des conflits

Contrôler

Chevauchements de périodes.


Priorité

LAST_MINUTE

↓

PROMOTIONAL

↓

SPECIAL_EVENT

↓

SEASONAL

↓

BASE

Étape 13 — Tarification applicable

Sélection

Règle active :

plus haute priorité

pour une période donnée.


Sprint 4-F.1-E

Tarifs de Base


Étape 14 — Règle par défaut

Exiger

Une règle :

PricingType.BASE

par propriété.


Étape 15 — Exemple

{
  "pricingType":"BASE",
  "name":"Tarif Standard",
  "basePrice":120
}

Sprint 4-F.1-F

Tarifs Saisonniers


Étape 16 — Cas d'usage

Supporter

Haute saison

Basse saison

Vacances

Événements

Étape 17 — Exemple

{
  "pricingType":"SEASONAL",
  "name":"Été 2027",
  "startDate":"2027-06-01",
  "endDate":"2027-09-01",
  "basePrice":180
}

Étape 18 — Calendrier

Préparer

Compatible avec :

PropertyAvailability

Sprint 4-F.1-G

Calcul Tarifaire


Étape 19 — PricingCalculationService

Créer

pricing-calculation.service.ts

Méthodes

calculatePrice()
 
calculateStayPrice()
 
calculateFees()
 
calculateDeposit()

Étape 20 — Calcul

Exemple

3 nuits

Base : 120 €

↓

360 €

Étape 21 — Frais

Ajouter

Cleaning Fee

Service Fee

Security Deposit

Extra Guests

Étape 22 — Retour

Exemple

{
  "baseAmount":360,
  "cleaningFee":30,
  "serviceFee":15,
  "total":405
}

Sprint 4-F.1-H

Contrôleur


Étape 23 — Création

Créer

property-pricing.controller.ts

Déclaration

@ApiTags(
  'Property Pricing'
)
 
@ApiBearerAuth()
 
@Controller(
  'properties/:id/pricing'
)
 
@UseGuards(
  JwtAuthGuard
)

Étape 24 — Endpoints

Ajouter

GET    /properties/{id}/pricing
 
POST   /properties/{id}/pricing
 
PUT    /properties/{id}/pricing/{pricingId}
 
DELETE /properties/{id}/pricing/{pricingId}
 
POST   /properties/{id}/pricing/calculate

Étape 25 — Endpoint calcul

Exemple

{
  "checkIn":"2027-07-10",
  "checkOut":"2027-07-15",
  "guests":4
}

Sprint 4-F.1-I

Sécurité


Étape 26 — Multi-Tenant

Vérifier

tenantId

propertyId

sur toutes les opérations.


Étape 27 — Permissions

Ajouter

property.pricing.read

property.pricing.create

property.pricing.update

property.pricing.delete

property.pricing.calculate

Étape 28 — Audit

Journaliser

PROPERTY_PRICING_CREATED

PROPERTY_PRICING_UPDATED

PROPERTY_PRICING_DELETED

PROPERTY_PRICE_CALCULATED

Sprint 4-F.1-J

Préparation Sprint 4-F.2


Étape 29 — Compatible

Préparer :

Dynamic Pricing

Yield Management

Revenue Forecast

Competitor Rates

Étape 30 — Compatible

Préparer :

Reservation

Booking Engine

Channel Manager

Revenue Management

Définition de terminé

Le Sprint 4-F.1 est terminé lorsque :

✓ PropertyPricing créé

✓ PropertyPricingModule créé

✓ PropertyPricingController créé

✓ PropertyPricingService créé

✓ Tarifs de base

✓ Tarifs saisonniers

✓ Tarifs par période

✓ Calcul tarifaire

✓ Audit intégré

Livrables

PropertyPricing

PricingType

PropertyPricingModule

PropertyPricingController

PropertyPricingService

PricingCalculationService

Property Pricing API

Sprint 4-F.2 — Revenue Management & Tarification Dynamique

Objectif

Transformer le moteur tarifaire en véritable Revenue Management System Enterprise.

À l'issue de cette étape :

✓ Dynamic Pricing

✓ Yield Management

✓ Occupancy Pricing

✓ Competitor Pricing

✓ Demand Forecast

✓ Revenue Intelligence

✓ Revenue Optimization Engine

Architecture cible

Property Pricing

↓

Revenue Engine

├── Dynamic Pricing
├── Yield Management
├── Occupancy Analysis
├── Competitor Intelligence
├── Demand Forecast
└── Revenue Optimization

↓

Reservation Engine

↓

Channel Manager

Sprint 4-F.2-A

Extension Prisma


Étape 1 — DynamicPricingRule

Ajouter dans schema.prisma

model DynamicPricingRule {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String
 
  name                  String
 
  active                Boolean
                        @default(true)
 
  triggerType           DynamicPricingTrigger
 
  triggerValue          Float
 
  adjustmentType        PriceAdjustmentType
 
  adjustmentValue       Float
 
  priority              Int
                        @default(0)
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  @@index([tenantId])
 
  @@index([propertyId])
 
  @@index([active])
}

Étape 2 — RevenueSnapshot

Ajouter

model RevenueSnapshot {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  snapshotDate          DateTime
 
  occupancyRate         Float
 
  averageDailyRate      Decimal
                        @db.Decimal(12,2)
 
  revPar                Decimal
                        @db.Decimal(12,2)
 
  projectedRevenue      Decimal
                        @db.Decimal(14,2)
 
  createdAt             DateTime
                        @default(now())
 
  @@index([propertyId])
 
  @@index([snapshotDate])
}

Étape 3 — CompetitorRate

Ajouter

model CompetitorRate {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  competitorName        String
 
  competitorPropertyId  String?
 
  stayDate              DateTime
 
  nightlyRate           Decimal
                        @db.Decimal(12,2)
 
  source                String?
 
  collectedAt           DateTime
                        @default(now())
 
  @@index([propertyId])
 
  @@index([stayDate])
}

Étape 4 — Enums

Ajouter

enum DynamicPricingTrigger {
 
  OCCUPANCY
 
  DEMAND
 
  BOOKING_WINDOW
 
  COMPETITOR_RATE
 
  EVENT
 
  SEASON
}
 
enum PriceAdjustmentType {
 
  PERCENTAGE
 
  FIXED_AMOUNT
}

Étape 5 — Migration

Générer

npx prisma migrate dev \
--name revenue_management

Sprint 4-F.2-B

Revenue Management Module


Étape 6 — Création

src/modules/revenue-management

├── dynamic-pricing
│
├── yield-management
│
├── occupancy-pricing
│
├── competitor-pricing
│
├── demand-forecast
│
├── revenue-intelligence
│
└── revenue-management.module.ts

Étape 7 — Services

Créer

DynamicPricingService

YieldManagementService

OccupancyPricingService

CompetitorPricingService

DemandForecastService

RevenueIntelligenceService

Sprint 4-F.2-C

Dynamic Pricing


Étape 8 — DynamicPricingService

Créer

dynamic-pricing.service.ts

Méthodes

calculateDynamicPrice()
 
applyPricingRules()
 
simulatePricing()

Étape 9 — Exemple

Règle

Occupation > 85%

↓

+15%

Résultat

120 €

↓

138 €

Étape 10 — Endpoint

Ajouter

POST /revenue/dynamic-pricing/calculate

Sprint 4-F.2-D

Yield Management


Étape 11 — YieldManagementService

Créer

yield-management.service.ts

Méthodes

calculateOptimalRate()
 
calculateYield()
 
optimizeRevenue()

Étape 12 — Facteurs

Occupation

Historique réservations

Saisonnalité

Demande

Concurrence

Étape 13 — KPI

Calculer

ADR

RevPAR

Revenue per Stay

Yield Index

Sprint 4-F.2-E

Occupancy Pricing


Étape 14 — OccupancyPricingService

Créer

occupancy-pricing.service.ts

Méthodes

adjustByOccupancy()
 
predictOccupancyImpact()

Étape 15 — Exemple

Occupation

95%

↓

+20%

Occupation

30%

↓

-15%

Étape 16 — Paliers

0-30%

31-60%

61-85%

86-100%

Sprint 4-F.2-F

Competitor Pricing


Étape 17 — CompetitorPricingService

Créer

competitor-pricing.service.ts

Méthodes

collectCompetitorRates()
 
compareRates()
 
recommendAdjustment()

Étape 18 — Comparaison

Exemple

Votre prix

120 €

Concurrence

145 €

Recommandation

Augmenter à 132 €

Étape 19 — Endpoint

Ajouter

GET /revenue/competitors

Sprint 4-F.2-G

Demand Forecast


Étape 20 — DemandForecastService

Créer

demand-forecast.service.ts

Méthodes

forecastDemand()
 
forecastRevenue()
 
forecastOccupancy()

Étape 21 — Sources

Réservations

Historique

Événements

Saisonnalité

Recherche

Étape 22 — Exemple

Juillet

Demande

+24%

Action

Augmenter tarifs

Sprint 4-F.2-H

Revenue Intelligence


Étape 23 — RevenueIntelligenceService

Créer

revenue-intelligence.service.ts

Méthodes

generateInsights()
 
detectRevenueOpportunities()
 
recommendStrategies()

Étape 24 — Exemples

Insight

Week-end

Taux réservation

96%

Recommandation

+12% tarif

Insight

Sous-performance

Août

↓

Promotion ciblée

Étape 25 — Revenue Insight

Ajouter

model RevenueInsight {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  severity              String
 
  title                 String
 
  description           String
 
  recommendation        String?
 
  createdAt             DateTime
                        @default(now())
 
  resolved              Boolean
                        @default(false)
 
  @@index([propertyId])
 
  @@index([resolved])
}

Sprint 4-F.2-I

Dashboard Revenue


Étape 26 — Endpoint

Ajouter

GET /revenue/dashboard

KPI

Revenue

ADR

RevPAR

Occupation

Forecast

Opportunités

Étape 27 — Exemple

{
  "adr":142,
  "revPar":121,
  "occupancy":85,
  "forecastRevenue":42000
}

Étape 28 — Snapshot

Alimenter

RevenueSnapshot

quotidiennement.


Sprint 4-F.2-J

Gouvernance & Sécurité


Étape 29 — Permissions

Ajouter

revenue.read

revenue.manage

revenue.optimize

revenue.forecast

revenue.admin

Étape 30 — Audit

Journaliser

REVENUE_RULE_CREATED

DYNAMIC_PRICE_CALCULATED

REVENUE_FORECAST_GENERATED

REVENUE_INSIGHT_CREATED

REVENUE_OPTIMIZATION_APPLIED

Étape 31 — Jobs

Ajouter

Toutes les heures

Dynamic Pricing

Toutes les nuits

Revenue Forecast

Revenue Insights

Préparation Sprint 5

Compatible avec :

Reservation

Booking Engine

Upsell

Promotion Engine

Préparation Sprint 17

Compatible avec :

Financial Forecast

Profitability Analysis

Business Intelligence

Préparation Sprint 20

Compatible avec :

Enterprise Revenue Management

AI Pricing

Predictive Revenue

Revenue Intelligence

Définition de terminé

Le Sprint 4-F.2 est terminé lorsque :

✓ Dynamic Pricing

✓ Yield Management

✓ Occupancy Pricing

✓ Competitor Pricing

✓ Demand Forecast

✓ Revenue Intelligence

✓ Revenue Dashboard

✓ Audit intégré

Livrables

DynamicPricingRule

RevenueSnapshot

CompetitorRate

RevenueInsight

DynamicPricingService

YieldManagementService

DemandForecastService

RevenueIntelligenceService

Revenue Dashboard

Sprint 4-G.1 — Gestion des Politiques des Propriétés

Objectif

Implémenter le moteur de politiques métier des propriétés.

Cette couche constitue la fondation des règles de réservation, d'annulation et d'exploitation.

À l'issue de cette étape :

✓ PropertyPolicy

✓ PropertyPolicyModule

✓ PropertyPolicyController

✓ PropertyPolicyService

✓ Check-in

✓ Check-out

✓ Annulation

✓ Règlement intérieur

✓ Reservation Ready

Architecture cible

Property

↓

PropertyPolicy

├── Check-in
├── Check-out
├── Cancellation
├── House Rules
├── Guest Rules
└── Booking Restrictions

↓

Reservation Engine

↓

Revenue Engine

Sprint 4-G.1-A

Extension Prisma


Étape 1 — Création PropertyPolicy

Ajouter dans schema.prisma

model PropertyPolicy {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String
                        @unique
 
  cancellationPolicy    CancellationPolicyType
 
  checkInFrom           String?
 
  checkInTo             String?
 
  checkOutFrom          String?
 
  checkOutTo            String?
 
  minimumGuestAge       Int?
 
  petsAllowed           Boolean
                        @default(false)
 
  smokingAllowed        Boolean
                        @default(false)
 
  partiesAllowed        Boolean
                        @default(false)
 
  childrenAllowed       Boolean
                        @default(true)
 
  eventsAllowed         Boolean
                        @default(false)
 
  quietHoursStart       String?
 
  quietHoursEnd         String?
 
  houseRules            String?
 
  guestInstructions     String?
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@index([tenantId])
 
  @@index([cancellationPolicy])
}

Étape 2 — Enum

Ajouter

enum CancellationPolicyType {
 
  FLEXIBLE
 
  MODERATE
 
  STRICT
 
  NON_REFUNDABLE
 
  CUSTOM
}

Étape 3 — Relation

Ajouter dans Property

policy PropertyPolicy?

Étape 4 — Migration

Générer

npx prisma migrate dev \
--name property_policy

Générer

npx prisma generate

Sprint 4-G.1-B

Politiques d'Annulation


Étape 5 — Règles Standards

FLEXIBLE

Annulation gratuite

jusqu'à 24h avant arrivée

MODERATE

Annulation gratuite

jusqu'à 5 jours avant arrivée

STRICT

Remboursement partiel

selon conditions

NON_REFUNDABLE

Aucun remboursement

Étape 6 — Politique personnalisée

Ajouter

customCancellationPolicy String?

pour :

CancellationPolicyType.CUSTOM

Sprint 4-G.1-C

Check-in & Check-out


Étape 7 — Gestion horaires

Supporter

Check-in From

Check-in To

Check-out From

Check-out To

Étape 8 — Exemples

Check-in

15:00 → 22:00

Check-out

08:00 → 11:00

Étape 9 — Validation

Vérifier

Format :

HH:mm

sur tous les horaires.


Sprint 4-G.1-D

Règlement Intérieur


Étape 10 — Gestion

Supporter

Animaux

Fumeurs

Fêtes

Enfants

Événements

Étape 11 — Exemple

{
  "petsAllowed":true,
  "smokingAllowed":false,
  "partiesAllowed":false
}

Étape 12 — Texte libre

Utiliser

houseRules

guestInstructions

pour les consignes détaillées.


Sprint 4-G.1-E

Module


Étape 13 — Création

src/modules/property-policy

├── application
│
│   └── dto
│
│       ├── update-property-policy.dto.ts
│
│       └── property-policy-response.dto.ts
│
├── domain
│
│   └── services
│
│       └── property-policy.service.ts
│
├── presentation
│
│   └── controllers
│
│       └── property-policy.controller.ts
│
└── property-policy.module.ts

Étape 14 — Module

Créer

@Module({
 
  imports: [
    PrismaModule,
    AuthModule,
    AuditModule
  ],
 
  controllers: [
    PropertyPolicyController
  ],
 
  providers: [
    PropertyPolicyService
  ],
 
  exports: [
    PropertyPolicyService
  ]
})
export class PropertyPolicyModule {}

Sprint 4-G.1-F

DTOs


Étape 15 — UpdatePropertyPolicyDto

Créer

export class UpdatePropertyPolicyDto {
 
  cancellationPolicy:
    CancellationPolicyType;
 
  customCancellationPolicy?: string;
 
  checkInFrom?: string;
 
  checkInTo?: string;
 
  checkOutFrom?: string;
 
  checkOutTo?: string;
 
  minimumGuestAge?: number;
 
  petsAllowed?: boolean;
 
  smokingAllowed?: boolean;
 
  partiesAllowed?: boolean;
 
  childrenAllowed?: boolean;
 
  eventsAllowed?: boolean;
 
  quietHoursStart?: string;
 
  quietHoursEnd?: string;
 
  houseRules?: string;
 
  guestInstructions?: string;
}

Sprint 4-G.1-G

PropertyPolicyService


Étape 16 — Création

Créer

property-policy.service.ts

Méthodes

getPolicy()
 
updatePolicy()
 
validatePolicy()
 
initializePolicy()

Étape 17 — Initialisation

Créer automatiquement

lors de la création d'une propriété :

MODERATE

15:00-22:00

08:00-11:00

comme valeurs par défaut.


Étape 18 — Validation

Contrôler

Check-in

Check-out

Âge minimum

Règles cohérentes

avant sauvegarde.


Sprint 4-G.1-H

Contrôleur


Étape 19 — Création

Créer

property-policy.controller.ts

Déclaration

@ApiTags(
  'Property Policies'
)
 
@ApiBearerAuth()
 
@Controller(
  'properties/:id/policies'
)
 
@UseGuards(
  JwtAuthGuard
)

Étape 20 — Endpoints

Ajouter

GET /properties/{id}/policies
 
PUT /properties/{id}/policies

Étape 21 — Exemple

Retour

{
  "cancellationPolicy":"MODERATE",
  "checkInFrom":"15:00",
  "checkInTo":"22:00",
  "petsAllowed":true
}

Sprint 4-G.1-I

Sécurité


Étape 22 — Multi-Tenant

Vérifier

tenantId

propertyId

sur toutes les opérations.


Étape 23 — Permissions

Ajouter

property.policy.read

property.policy.update

property.policy.manage

Étape 24 — Audit

Journaliser

PROPERTY_POLICY_VIEWED

PROPERTY_POLICY_UPDATED

PROPERTY_CANCELLATION_UPDATED

PROPERTY_RULES_UPDATED

Sprint 4-G.1-J

Préparation Sprint 5


Étape 25 — Compatible

Préparer :

Reservation

Booking Workflow

Refund Engine

Guest Management

Étape 26 — Compatible

Préparer :

Revenue Management

Legal Compliance

Terms & Conditions

Insurance Rules

Étape 27 — Préparer

Compatible avec :

Airbnb

Booking.com

Expedia

OTA Mapping

Définition de terminé

Le Sprint 4-G.1 est terminé lorsque :

✓ PropertyPolicy créé

✓ PropertyPolicyModule créé

✓ PropertyPolicyController créé

✓ PropertyPolicyService créé

✓ Check-in géré

✓ Check-out géré

✓ Annulation gérée

✓ Règlement intérieur géré

✓ Audit intégré

Livrables

PropertyPolicy

CancellationPolicyType

PropertyPolicyModule

PropertyPolicyController

PropertyPolicyService

Property Policy API

Sprint 4-G.2 — Politiques Enterprise & Conformité Juridique

Objectif

Transformer le moteur de politiques en véritable couche de gouvernance juridique Enterprise.

À l'issue de cette étape :

✓ Conditions contractuelles

✓ Dépôts de garantie

✓ Conformité locale

✓ RGPD

✓ Documents légaux

✓ Signature électronique

✓ Gestion des exceptions

✓ Legal Compliance Engine

Architecture cible

Property Policy

↓

Legal Engine

├── Contracts
├── Deposits
├── Compliance
├── GDPR
├── Legal Documents
├── E-Signature
└── Exceptions

↓

Reservation Engine

↓

Governance Layer

Sprint 4-G.2-A

Extension Prisma


Étape 1 — PropertyLegalPolicy

Ajouter dans schema.prisma

model PropertyLegalPolicy {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String
                        @unique
 
  termsAndConditions    String?
 
  privacyPolicy         String?
 
  liabilityWaiver       String?
 
  cancellationTerms     String?
 
  localComplianceNotes  String?
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@index([tenantId])
}

Étape 2 — SecurityDepositPolicy

Ajouter

model SecurityDepositPolicy {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
                        @unique
 
  depositRequired       Boolean
                        @default(false)
 
  depositAmount         Decimal?
                        @db.Decimal(12,2)
 
  depositCurrency       String?
                        @default("EUR")
 
  refundDelayDays       Int?
                        @default(7)
 
  refundConditions      String?
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  @@index([propertyId])
}

Étape 3 — LegalDocument

Ajouter

model LegalDocument {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String?
 
  documentType          LegalDocumentType
 
  version               String
 
  title                 String
 
  storagePath           String
 
  published             Boolean
                        @default(false)
 
  effectiveDate         DateTime
 
  createdAt             DateTime
                        @default(now())
 
  @@index([tenantId])
 
  @@index([documentType])
 
  @@index([effectiveDate])
}

Étape 4 — Enums

Ajouter

enum LegalDocumentType {
 
  TERMS
 
  PRIVACY_POLICY
 
  HOUSE_RULES
 
  RENTAL_CONTRACT
 
  LIABILITY_WAIVER
 
  GDPR_NOTICE
}

Étape 5 — Migration

Générer

npx prisma migrate dev \
--name legal_compliance

Sprint 4-G.2-B

Gestion Contractuelle


Étape 6 — ContractModule

Créer

src/modules/legal

├── contracts
│
├── compliance
│
├── gdpr
│
├── signatures
│
└── documents

Étape 7 — ContractService

Créer

contract.service.ts

Méthodes

generateContract()
 
validateContract()
 
publishContract()
 
archiveContract()

Étape 8 — Contrat réservation

Générer automatiquement

à partir de :

Property

Reservation

Policies

Guest

Sprint 4-G.2-C

Dépôts de Garantie


Étape 9 — SecurityDepositService

Créer

security-deposit.service.ts

Méthodes

calculateDeposit()
 
reserveDeposit()
 
releaseDeposit()
 
claimDeposit()

Étape 10 — Types

Supporter

Montant fixe

Pourcentage réservation

Selon catégorie

Étape 11 — Exemple

Réservation

1 000 €

Dépôt

20 %

↓

200 €

Sprint 4-G.2-D

Conformité Locale


Étape 12 — LocalComplianceRule

Ajouter

model LocalComplianceRule {
 
  id                    String
                        @id
                        @default(uuid())
 
  countryCode           String
 
  regionCode            String?
 
  ruleType              String
 
  title                 String
 
  description           String
 
  active                Boolean
                        @default(true)
 
  createdAt             DateTime
                        @default(now())
 
  @@index([countryCode])
 
  @@index([ruleType])
}

Étape 13 — ComplianceService

Créer

compliance.service.ts

Méthodes

validatePropertyCompliance()
 
getApplicableRules()
 
generateComplianceReport()

Étape 14 — Contrôles

Vérifier

Taxe séjour

Déclaration hébergement

Assurance

Capacité légale

Sécurité incendie

Sprint 4-G.2-E

RGPD


Étape 15 — GDPRConsent

Ajouter

model GDPRConsent {
 
  id                    String
                        @id
                        @default(uuid())
 
  userId                String
 
  consentType           String
 
  accepted              Boolean
 
  acceptedAt            DateTime?
 
  revokedAt             DateTime?
 
  ipAddress             String?
 
  createdAt             DateTime
                        @default(now())
 
  @@index([userId])
 
  @@index([consentType])
}

Étape 16 — GDPRService

Créer

gdpr.service.ts

Méthodes

recordConsent()
 
revokeConsent()
 
exportUserData()
 
anonymizeUserData()

Étape 17 — Supporter

Consentement

Portabilité

Rectification

Droit à l'oubli

Sprint 4-G.2-F

Signature Électronique


Étape 18 — ElectronicSignature

Ajouter

model ElectronicSignature {
 
  id                    String
                        @id
                        @default(uuid())
 
  documentId            String
 
  signerId              String
 
  signedAt              DateTime?
 
  ipAddress             String?
 
  status                SignatureStatus
 
  signatureHash         String?
 
  @@index([documentId])
 
  @@index([signerId])
}

Étape 19 — Enum

Ajouter

enum SignatureStatus {
 
  PENDING
 
  SIGNED
 
  REJECTED
 
  EXPIRED
}

Étape 20 — SignatureService

Créer

signature.service.ts

Méthodes

requestSignature()
 
signDocument()
 
verifySignature()

Sprint 4-G.2-G

Gestion des Exceptions


Étape 21 — PolicyException

Ajouter

model PolicyException {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  exceptionType         String
 
  reason                String
 
  approvedBy            String?
 
  validFrom             DateTime?
 
  validUntil            DateTime?
 
  active                Boolean
                        @default(true)
 
  createdAt             DateTime
                        @default(now())
 
  @@index([propertyId])
 
  @@index([active])
}

Étape 22 — Cas d'usage

Supporter

Animal exceptionnel

Check-in tardif

Annulation exceptionnelle

Remise exceptionnelle

Étape 23 — Validation

Exiger

Approbation selon RBAC.


Sprint 4-G.2-H

API Enterprise


Étape 24 — Endpoints

Ajouter

GET  /properties/{id}/legal
 
PUT  /properties/{id}/legal
 
GET  /properties/{id}/compliance
 
POST /properties/{id}/compliance/validate
 
POST /contracts/generate
 
POST /contracts/sign
 
GET  /gdpr/export
 
POST /gdpr/delete-request

Étape 25 — Documents

Ajouter

GET    /legal-documents
 
POST   /legal-documents
 
PUT    /legal-documents/{id}
 
DELETE /legal-documents/{id}

Sprint 4-G.2-I

Gouvernance


Étape 26 — Permissions

Ajouter

legal.read

legal.manage

legal.contracts

legal.compliance

legal.gdpr

legal.signatures

Étape 27 — Audit

Journaliser

LEGAL_DOCUMENT_CREATED

CONTRACT_GENERATED

CONTRACT_SIGNED

GDPR_EXPORT_REQUESTED

GDPR_DELETE_REQUESTED

COMPLIANCE_VALIDATED

POLICY_EXCEPTION_CREATED

Étape 28 — Reporting

Générer

Compliance Score

GDPR Status

Pending Signatures

Legal Risks

Sprint 4-G.2-J

Préparation Future


Étape 29 — Compatible Sprint 5

Préparer :

Reservation Contract

Guest Agreements

Refund Workflow

Étape 30 — Compatible Sprint 19

Préparer :

Governance

Risk Management

Audit Framework

Compliance Dashboard

Étape 31 — Compatible Sprint 20

Préparer :

Enterprise Compliance

Legal Automation

Contract Intelligence

Global Regulations

Définition de terminé

Le Sprint 4-G.2 est terminé lorsque :

✓ Contrats gérés

✓ Dépôts de garantie gérés

✓ Conformité locale gérée

✓ RGPD géré

✓ Documents légaux gérés

✓ Signature électronique gérée

✓ Exceptions gérées

✓ Audit intégré

Livrables

PropertyLegalPolicy

SecurityDepositPolicy

LegalDocument

ElectronicSignature

GDPRConsent

PolicyException

ComplianceService

GDPRService

SignatureService

Enterprise Legal Engine

Sprint 4-H.1 — Gestion des Avis Clients

Objectif

Implémenter le système d'avis clients des propriétés.

Cette couche constitue la fondation de la réputation, de la confiance et du classement des biens.

À l'issue de cette étape :

✓ PropertyReview

✓ PropertyReviewModule

✓ PropertyReviewController

✓ PropertyReviewService

✓ Avis

✓ Notes

✓ Commentaires

✓ Réponses propriétaires

✓ Reputation Ready

Architecture cible

Reservation

↓

Review Eligibility

↓

PropertyReview

├── Rating
├── Comment
├── Owner Response
├── Moderation
└── Analytics

↓

Property Score

↓

Search Ranking

Sprint 4-H.1-A

Extension Prisma


Étape 1 — Création PropertyReview

Ajouter dans schema.prisma

model PropertyReview {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String
 
  customerId            String
 
  reservationId         String?
 
  overallRating         Int
 
  cleanlinessRating     Int?
 
  communicationRating   Int?
 
  locationRating        Int?
 
  valueRating           Int?
 
  checkInRating         Int?
 
  title                 String?
 
  comment               String?
 
  verifiedStay          Boolean
                        @default(false)
 
  published             Boolean
                        @default(true)
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  deletedAt             DateTime?
 
  tenant                Tenant
                        @relation(
                          fields:[tenantId],
                          references:[id]
                        )
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  customer              Customer
                        @relation(
                          fields:[customerId],
                          references:[id]
                        )
 
  responses             PropertyReviewResponse[]
 
  @@index([tenantId])
 
  @@index([propertyId])
 
  @@index([customerId])
 
  @@index([overallRating])
 
  @@index([published])
}

Étape 2 — Réponse propriétaire

Ajouter

model PropertyReviewResponse {
 
  id                    String
                        @id
                        @default(uuid())
 
  reviewId              String
 
  userId                String
 
  response              String
 
  createdAt             DateTime
                        @default(now())
 
  updatedAt             DateTime
                        @updatedAt
 
  review                PropertyReview
                        @relation(
                          fields:[reviewId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@index([reviewId])
}

Étape 3 — Relation Property

Ajouter dans Property

reviews PropertyReview[]

Étape 4 — Migration

Générer

npx prisma migrate dev \
--name property_reviews

Générer

npx prisma generate

Sprint 4-H.1-B

Module


Étape 5 — Création

src/modules/property-reviews

├── application
│
│   └── dto
│
│       ├── create-review.dto.ts
│
│       ├── update-review.dto.ts
│
│       ├── review-response.dto.ts
│
│       └── review-query.dto.ts
│
├── domain
│
│   └── services
│
│       └── property-review.service.ts
│
├── presentation
│
│   └── controllers
│
│       └── property-review.controller.ts
│
└── property-review.module.ts

Étape 6 — Module

Créer

@Module({
 
  imports: [
    PrismaModule,
    AuthModule,
    AuditModule
  ],
 
  controllers: [
    PropertyReviewController
  ],
 
  providers: [
    PropertyReviewService
  ],
 
  exports: [
    PropertyReviewService
  ]
})
export class PropertyReviewModule {}

Sprint 4-H.1-C

DTOs


Étape 7 — CreateReviewDto

Créer

export class CreateReviewDto {
 
  reservationId?: string;
 
  overallRating: number;
 
  cleanlinessRating?: number;
 
  communicationRating?: number;
 
  locationRating?: number;
 
  valueRating?: number;
 
  checkInRating?: number;
 
  title?: string;
 
  comment?: string;
}

Étape 8 — Validation

Contraindre

1 <= Rating <= 5

sur toutes les notes.


Étape 9 — ReviewResponseDto

Créer

export class ReviewResponseDto {
 
  response: string;
}

Sprint 4-H.1-D

PropertyReviewService


Étape 10 — Création

Créer

property-review.service.ts

Méthodes

findAll()
 
findById()
 
create()
 
update()
 
remove()
 
respond()
 
calculatePropertyRating()

Étape 11 — Vérification séjour

Contrôler

Le client doit :

Posséder réservation

ET

Réservation terminée

pour déposer un avis.


Étape 12 — Verified Stay

Activer

verifiedStay = true

si réservation validée.


Étape 13 — Un avis par réservation

Refuser

plusieurs avis :

reservationId

identique.


Sprint 4-H.1-E

Notes & Commentaires


Étape 14 — Notes supportées

Global

Propreté

Communication

Emplacement

Rapport qualité/prix

Check-in

Étape 15 — Calcul

Note moyenne

AVG(overallRating)

par propriété.


Étape 16 — Mise à jour

Alimenter

PropertyScore.reviewScore

automatiquement.


Sprint 4-H.1-F

Réponses Propriétaires


Étape 17 — Endpoint

Ajouter

POST /reviews/{id}/response

Étape 18 — Autoriser

Property Manager

Tenant Admin

Owner

uniquement.


Étape 19 — Exemple

{
  "response":"Merci pour votre séjour."
}

Sprint 4-H.1-G

Contrôleur


Étape 20 — Création

Créer

property-review.controller.ts

Déclaration

@ApiTags(
  'Property Reviews'
)
 
@ApiBearerAuth()

Étape 21 — Endpoints

Ajouter

GET    /properties/{id}/reviews
 
POST   /properties/{id}/reviews
 
PUT    /reviews/{id}
 
DELETE /reviews/{id}
 
POST   /reviews/{id}/response

Étape 22 — Recherche

Supporter

Rating

Verified

Date

Published

Sprint 4-H.1-H

Modération


Étape 23 — ReviewModeration

Ajouter

model ReviewModeration {
 
  id                    String
                        @id
                        @default(uuid())
 
  reviewId              String
                        @unique
 
  flagged               Boolean
                        @default(false)
 
  reason                String?
 
  reviewedBy            String?
 
  reviewedAt            DateTime?
 
  createdAt             DateTime
                        @default(now())
}

Étape 24 — Contrôles

Détecter

Spam

Abus

Langage interdit

Fraude

Étape 25 — Actions

Publish

Hide

Delete

Escalate

Sprint 4-H.1-I

Sécurité


Étape 26 — Multi-Tenant

Vérifier

tenantId

propertyId

sur toutes les opérations.


Étape 27 — Permissions

Ajouter

property.review.read

property.review.create

property.review.update

property.review.delete

property.review.respond

property.review.moderate

Étape 28 — Audit

Journaliser

PROPERTY_REVIEW_CREATED

PROPERTY_REVIEW_UPDATED

PROPERTY_REVIEW_DELETED

PROPERTY_REVIEW_RESPONDED

PROPERTY_REVIEW_MODERATED

Sprint 4-H.1-J

Préparation Sprint 4-H.2


Étape 29 — Compatible

Préparer :

Review Images

Review Sentiment

AI Moderation

Review Analytics

Étape 30 — Compatible

Préparer :

Search Ranking

Property Score

Recommendation Engine

Trust Score

Définition de terminé

Le Sprint 4-H.1 est terminé lorsque :

✓ PropertyReview créé

✓ PropertyReviewModule créé

✓ PropertyReviewController créé

✓ PropertyReviewService créé

✓ Avis opérationnels

✓ Notes opérationnelles

✓ Commentaires opérationnels

✓ Réponses propriétaires opérationnelles

✓ Modération intégrée

Livrables

PropertyReview

PropertyReviewResponse

ReviewModeration

PropertyReviewModule

PropertyReviewController

PropertyReviewService

Property Reviews API

Sprint 4-H.2 — Review Intelligence & Réputation Enterprise

Objectif

Transformer le système d'avis en plateforme de réputation intelligente Enterprise.

À l'issue de cette étape :

✓ Analyse de sentiment

✓ IA de modération

✓ Review Images

✓ Détection fraude

✓ Trust Score

✓ Réputation globale

✓ Insights clients

✓ Reputation Intelligence Platform

Architecture cible

Property Reviews

↓

Review Intelligence Engine

├── Sentiment Analysis
├── AI Moderation
├── Review Images
├── Fraud Detection
├── Trust Scoring
├── Reputation Analytics
└── Customer Insights

↓

Property Score

↓

Search Ranking

↓

Recommendation Engine

Sprint 4-H.2-A

Extension Prisma


Étape 1 — ReviewSentiment

Ajouter dans schema.prisma

model ReviewSentiment {
 
  id                    String
                        @id
                        @default(uuid())
 
  reviewId              String
                        @unique
 
  sentiment             SentimentType
 
  score                 Float
 
  positiveKeywords      Json?
 
  negativeKeywords      Json?
 
  emotions              Json?
 
  analyzedAt            DateTime
                        @default(now())
 
  review                PropertyReview
                        @relation(
                          fields:[reviewId],
                          references:[id],
                          onDelete:Cascade
                        )
}

Étape 2 — ReviewTrustScore

Ajouter

model ReviewTrustScore {
 
  id                    String
                        @id
                        @default(uuid())
 
  reviewId              String
                        @unique
 
  trustScore            Float
 
  fraudRisk             Float
 
  authenticityScore     Float
 
  behaviorScore         Float
 
  calculatedAt          DateTime
                        @default(now())
 
  review                PropertyReview
                        @relation(
                          fields:[reviewId],
                          references:[id],
                          onDelete:Cascade
                        )
}

Étape 3 — ReviewImage

Ajouter

model ReviewImage {
 
  id                    String
                        @id
                        @default(uuid())
 
  reviewId              String
 
  imageUrl              String
 
  thumbnailUrl          String?
 
  moderationStatus      ModerationStatus
                        @default(PENDING)
 
  uploadedAt            DateTime
                        @default(now())
 
  review                PropertyReview
                        @relation(
                          fields:[reviewId],
                          references:[id],
                          onDelete:Cascade
                        )
 
  @@index([reviewId])
}

Étape 4 — Enums

Ajouter

enum SentimentType {
 
  VERY_POSITIVE
 
  POSITIVE
 
  NEUTRAL
 
  NEGATIVE
 
  VERY_NEGATIVE
}
 
enum ModerationStatus {
 
  PENDING
 
  APPROVED
 
  REJECTED
 
  FLAGGED
}

Étape 5 — Migration

Générer

npx prisma migrate dev \
--name review_intelligence

Sprint 4-H.2-B

Analyse de Sentiment


Étape 6 — ReviewSentimentService

Créer

review-sentiment.service.ts

Méthodes

analyzeSentiment()
 
extractKeywords()
 
detectEmotions()
 
generateSummary()

Étape 7 — Classification

Très positif

Positif

Neutre

Négatif

Très négatif

Étape 8 — Exemple

Avis

Appartement magnifique,
très propre,
hôte exceptionnel

Résultat

Sentiment:
VERY_POSITIVE

Score:
94

Sprint 4-H.2-C

IA de Modération


Étape 9 — ReviewModerationAIService

Créer

review-moderation-ai.service.ts

Méthodes

detectSpam()
 
detectAbuse()
 
detectToxicity()
 
detectFakeReview()

Étape 10 — Contrôles

Détecter

Spam

Insultes

Contenu haineux

Fraude

Bots

Étape 11 — Actions

Approve

Flag

Reject

Escalate

Sprint 4-H.2-D

Gestion des Images d'Avis


Étape 12 — Upload

Ajouter

POST /reviews/{id}/images

Étape 13 — Validation

Vérifier

Format

Poids

Qualité

Contenu interdit

Étape 14 — Analyse IA

Détecter

Chambre

Salle de bain

Piscine

Cuisine

Animaux

Personnes

Étape 15 — Auto-tagging

Associer

aux équipements détectés.


Sprint 4-H.2-E

Détection de Fraude


Étape 16 — FraudDetectionService

Créer

review-fraud-detection.service.ts

Méthodes

detectFraud()
 
calculateRisk()
 
detectReviewFarm()
 
detectDuplicatePatterns()

Étape 17 — Signaux

Analyser

IP

Device

Timing

Texte

Historique

Étape 18 — Alertes

Déclencher

Suspicious Review

Fake Review

Mass Review Activity

Sprint 4-H.2-F

Trust Score


Étape 19 — TrustScoreService

Créer

review-trust-score.service.ts

Calcul

Verified Stay

Historique client

Fraud Risk

Sentiment Consistency

Review Completeness

Étape 20 — Classification

90-100 Trusted

75-89 Reliable

50-74 Medium

0-49 Suspicious

Étape 21 — Exemple

Trust Score

96

Trusted

Sprint 4-H.2-G

Réputation Globale


Étape 22 — ReputationService

Créer

reputation.service.ts

Méthodes

calculatePropertyReputation()
 
calculateTenantReputation()
 
calculateBrandReputation()

Étape 23 — KPI

Calculer

Average Rating

Review Volume

Trust Score

Response Rate

Response Time

Étape 24 — Reputation Index

Exemple

Property Reputation

92

Excellent

Sprint 4-H.2-H

Customer Insights


Étape 25 — ReviewInsight

Ajouter

model ReviewInsight {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  category              String
 
  title                 String
 
  description           String
 
  severity              String?
 
  createdAt             DateTime
                        @default(now())
 
  resolved              Boolean
                        @default(false)
 
  @@index([propertyId])
}

Étape 26 — Génération

Identifier

Forces

Faiblesses

Opportunités

Problèmes récurrents

Étape 27 — Exemple

32% des avis

mentionnent

Wifi lent

Action

Améliorer réseau

Sprint 4-H.2-I

Dashboard Réputation


Étape 28 — Endpoint

Ajouter

GET /reviews/reputation/dashboard

Retour

{
  "averageRating":4.7,
  "trustScore":91,
  "responseRate":96,
  "sentiment":"POSITIVE"
}

Étape 29 — Analytics

Afficher

Sentiment Trends

Review Trends

Trust Trends

Customer Insights

Sprint 4-H.2-J

Gouvernance & Sécurité


Étape 30 — Permissions

Ajouter

property.review.analytics

property.review.moderate

property.review.trust

property.review.reputation

Étape 31 — Audit

Journaliser

REVIEW_ANALYZED

REVIEW_FLAGGED

REVIEW_FRAUD_DETECTED

REPUTATION_UPDATED

TRUST_SCORE_UPDATED

Étape 32 — Jobs

Ajouter

Toutes les heures

Sentiment Analysis

Fraud Detection

Toutes les nuits

Reputation Calculation

Insights Generation

Préparation Sprint 4-I

Compatible avec :

Search Ranking

Property Score

Recommendation Engine

Préparation Sprint 13

Compatible avec :

LLM Analytics

AI Insights

Customer Intelligence

Knowledge Graph

Préparation Sprint 20

Compatible avec :

Enterprise Reputation Platform

AI Moderation

Fraud Prevention

Brand Intelligence

Définition de terminé

Le Sprint 4-H.2 est terminé lorsque :

✓ Analyse de sentiment

✓ IA de modération

✓ Review Images

✓ Détection fraude

✓ Trust Score

✓ Réputation globale

✓ Insights clients

✓ Dashboard réputation

✓ Audit intégré

Livrables

ReviewSentiment

ReviewTrustScore

ReviewImage

ReviewInsight

ReviewSentimentService

ReviewModerationAIService

FraudDetectionService

ReputationService

Enterprise Reputation Platform

Sprint 4-I.1 — Moteur de Recherche Immobilier

Objectif

Construire le moteur de recherche central de la plateforme.

Cette couche unifie :

Property

Amenities

Availability

Pricing

Reviews

Scores

Analytics

dans une expérience de recherche Enterprise unique.

À l'issue de cette étape :

✓ PropertySearchEngine

✓ Faceted Search

✓ Geo Search

✓ Availability Search

✓ Ranking Engine

✓ Search Analytics

✓ Search API Enterprise

Architecture cible

Property Search Engine

├── Catalog Search
├── Availability Search
├── Geo Search
├── Pricing Search
├── Review Search
├── Faceted Search
├── Ranking Engine
└── Search Analytics

↓

Booking Engine

↓

Recommendation Engine

Sprint 4-I.1-A

Extension Prisma


Étape 1 — SearchQueryLog

Ajouter dans schema.prisma

model SearchQueryLog {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String?
 
  userId                String?
 
  query                 String?
 
  filters               Json?
 
  resultCount           Int
                        @default(0)
 
  executionTimeMs       Int?
 
  createdAt             DateTime
                        @default(now())
 
  @@index([tenantId])
 
  @@index([userId])
 
  @@index([createdAt])
}

Étape 2 — PropertySearchIndex

Ajouter

model PropertySearchIndex {
 
  propertyId            String
                        @id
 
  searchableText        String
 
  amenities             Json?
 
  city                  String?
 
  country               String?
 
  averageRating         Float?
 
  reviewCount           Int?
 
  minPrice              Decimal?
                        @db.Decimal(12,2)
 
  maxGuests             Int?
 
  searchScore           Float?
                        @default(0)
 
  updatedAt             DateTime
                        @updatedAt
 
  @@index([city])
 
  @@index([country])
 
  @@index([searchScore])
}

Étape 3 — SavedSearch

Ajouter

model SavedPropertySearch {
 
  id                    String
                        @id
                        @default(uuid())
 
  userId                String
 
  tenantId              String
 
  name                  String
 
  filters               Json
 
  createdAt             DateTime
                        @default(now())
 
  @@index([userId])
 
  @@index([tenantId])
}

Étape 4 — Migration

Générer

npx prisma migrate dev \
--name property_search_engine

Sprint 4-I.1-B

Search Engine Module


Étape 5 — Création

src/modules/property-search

├── search
│
├── ranking
│
├── analytics
│
├── facets
│
├── geo
│
└── property-search.module.ts

Étape 6 — Services

Créer

PropertySearchEngineService

FacetedSearchService

GeoSearchService

AvailabilitySearchService

RankingEngineService

SearchAnalyticsService

Sprint 4-I.1-C

Recherche Unifiée


Étape 7 — PropertySearchDto

Créer

export class PropertySearchDto {
 
  query?: string;
 
  city?: string;
 
  country?: string;
 
  latitude?: number;
 
  longitude?: number;
 
  radiusKm?: number;
 
  checkIn?: Date;
 
  checkOut?: Date;
 
  guests?: number;
 
  minPrice?: number;
 
  maxPrice?: number;
 
  minRating?: number;
 
  amenities?: string[];
 
  propertyTypeId?: string;
 
  page?: number = 1;
 
  limit?: number = 25;
}

Étape 8 — Search Engine

Méthode

search()

Agrège

Property

Availability

Pricing

Reviews

Amenities

dans une requête unique.


Étape 9 — Recherche texte

Champs

Name

Description

Location

Amenities

Reviews

Sprint 4-I.1-D


Étape 10 — FacetedSearchService

Créer

faceted-search.service.ts

Générer

Cities

Countries

Amenities

Ratings

Price Ranges

Property Types

Étape 11 — Endpoint

Ajouter

GET /search/facets

Étape 12 — Exemple

{
  "cities": {
    "Paris": 132
  },
  "amenities": {
    "Wifi": 218
  }
}

Sprint 4-I.1-E

Recherche Géographique


Étape 13 — GeoSearchService

Créer

geo-search.service.ts

Méthodes

searchByRadius()
 
calculateDistance()
 
sortByDistance()

Étape 14 — Utiliser

Latitude

Longitude

Haversine

Étape 15 — Exemple

Rayon

10 km

autour de Paris

Sprint 4-I.1-F

Recherche de Disponibilités


Étape 16 — AvailabilitySearchService

Créer

availability-search.service.ts

Vérifier

Check-In

Check-Out

Inventory

Blocks

Étape 17 — Endpoint

Ajouter

GET /search/availability

Étape 18 — Retour

Uniquement les biens :

Disponibles

sur la période demandée.


Sprint 4-I.1-G

Ranking Engine


Étape 19 — RankingEngineService

Créer

ranking-engine.service.ts

Facteurs

Review Score

Trust Score

Price Score

Availability Score

Popularity

Revenue Score

Étape 20 — Pondération

Reviews       30%

Popularity    20%

Availability  20%

Price         15%

Revenue       15%

Étape 21 — Search Score

Alimenter

PropertySearchIndex.searchScore

automatiquement.


Sprint 4-I.1-H

Search Analytics


Étape 22 — SearchAnalyticsService

Créer

search-analytics.service.ts

Méthodes

trackSearch()
 
getPopularSearches()
 
getZeroResultsQueries()
 
getConversionRate()

Étape 23 — KPI

Mesurer

Search Volume

CTR

Bookings

Search Conversion

Top Filters

Étape 24 — Endpoint

Ajouter

GET /search/analytics

Sprint 4-I.1-I

API Enterprise


Étape 25 — Endpoints

Ajouter

GET /search
 
GET /search/facets
 
GET /search/availability
 
GET /search/analytics
 
POST /search/saved
 
GET /search/saved
 
DELETE /search/saved/{id}

Étape 26 — Exemple

Requête

Paris

4 personnes

Wifi

Piscine

14-20 juillet

Retour

{
  "items": [],
  "facets": {},
  "meta": {}
}

Étape 27 — Pagination

Supporter

Offset

Cursor

Infinite Scroll

Sprint 4-I.1-J

Gouvernance


Étape 28 — Permissions

Ajouter

property.search

property.search.saved

property.search.analytics

property.search.admin

Étape 29 — Audit

Journaliser

PROPERTY_SEARCH_EXECUTED

PROPERTY_SEARCH_SAVED

PROPERTY_SEARCH_ANALYTICS_VIEWED

Étape 30 — Jobs

Ajouter

Toutes les heures

Search Index Refresh

Toutes les nuits

Ranking Rebuild

Analytics Aggregation

Préparation Sprint 4-I.2

Compatible avec :

Semantic Search

AI Search

Recommendations

Personalization

Préparation Sprint 13

Compatible avec :

Vector Search

LLM Search

Knowledge Graph

RAG

Préparation Sprint 20

Compatible avec :

Enterprise Search Platform

Global Catalog

AI Discovery

Unified Search

Définition de terminé

Le Sprint 4-I.1 est terminé lorsque :

✓ PropertySearchEngine

✓ Faceted Search

✓ Geo Search

✓ Availability Search

✓ Ranking Engine

✓ Search Analytics

✓ Search API Enterprise

✓ Audit intégré

Livrables

PropertySearchEngineService

FacetedSearchService

GeoSearchService

AvailabilitySearchService

RankingEngineService

SearchAnalyticsService

PropertySearchIndex

Enterprise Search Platform

Sprint 4-I.2 — Recherche IA & Discovery Platform

Objectif

Transformer le moteur de recherche immobilier en plateforme de découverte intelligente alimentée par l'IA.

À l'issue de cette étape :

✓ Recherche sémantique

✓ Vector Search

✓ Recommandations

✓ Personnalisation

✓ Intent Detection

✓ AI Discovery

✓ Property Intelligence Graph

Architecture cible

User Query

↓

AI Discovery Platform

├── Intent Detection
├── Semantic Search
├── Vector Search
├── Recommendation Engine
├── Personalization Engine
├── Property Intelligence Graph
└── Ranking AI

↓

Search Engine

↓

Booking Engine

Sprint 4-I.2-A

Extension Prisma


Étape 1 — PropertyEmbedding

Ajouter dans schema.prisma

model PropertyEmbedding {
 
  propertyId            String
                        @id
 
  embeddingModel        String
 
  embeddingVersion      String
 
  vectorId              String
 
  generatedAt           DateTime
                        @default(now())
 
  property              Property
                        @relation(
                          fields:[propertyId],
                          references:[id],
                          onDelete:Cascade
                        )
}

Étape 2 — SearchIntent

Ajouter

model SearchIntent {
 
  id                    String
                        @id
                        @default(uuid())
 
  query                 String
 
  detectedIntent        String
 
  confidence            Float
 
  entities              Json?
 
  createdAt             DateTime
                        @default(now())
 
  @@index([detectedIntent])
}

Étape 3 — RecommendationProfile

Ajouter

model RecommendationProfile {
 
  id                    String
                        @id
                        @default(uuid())
 
  userId                String
                        @unique
 
  preferences           Json?
 
  interests             Json?
 
  travelPatterns        Json?
 
  preferredAmenities    Json?
 
  preferredLocations    Json?
 
  updatedAt             DateTime
                        @updatedAt
 
  @@index([userId])
}

Étape 4 — PropertyRecommendation

Ajouter

model PropertyRecommendation {
 
  id                    String
                        @id
                        @default(uuid())
 
  userId                String
 
  propertyId            String
 
  recommendationScore   Float
 
  reason                String?
 
  generatedAt           DateTime
                        @default(now())
 
  clicked               Boolean
                        @default(false)
 
  booked                Boolean
                        @default(false)
 
  @@index([userId])
 
  @@index([propertyId])
}

Étape 5 — Migration

Générer

npx prisma migrate dev \
--name ai_discovery_platform

Sprint 4-I.2-B

AI Discovery Module


Étape 6 — Création

src/modules/ai-discovery

├── semantic-search
│
├── vector-search
│
├── recommendations
│
├── personalization
│
├── intent-detection
│
├── intelligence-graph
│
└── ai-discovery.module.ts

Étape 7 — Services

Créer

SemanticSearchService

VectorSearchService

RecommendationEngineService

PersonalizationService

IntentDetectionService

PropertyIntelligenceGraphService

Sprint 4-I.2-C

Recherche Sémantique


Étape 8 — SemanticSearchService

Créer

semantic-search.service.ts

Méthodes

semanticSearch()
 
expandQuery()
 
extractConcepts()
 
rankSemanticResults()

Étape 9 — Exemples

Requête

Appartement calme pour télétravail
près de la mer

Compréhension

Remote Work

Wifi

Workspace

Sea View

Quiet Area

Étape 10 — Sources

Indexer

Property

Amenities

Reviews

Descriptions

Policies

Sprint 4-I.2-D


Étape 11 — VectorSearchService

Créer

vector-search.service.ts

Méthodes

generateEmbedding()
 
searchSimilarProperties()
 
findNearestNeighbors()

Étape 12 — Infrastructure

Préparer

pgvector

Qdrant

Weaviate

Pinecone

Étape 13 — Embeddings

Générer pour

Properties

Reviews

Amenities

Policies

Locations

Étape 14 — Similarité

Exemple

Villa luxe avec piscine

↓

Biens similaires

Sprint 4-I.2-E

Recommandations


Étape 15 — RecommendationEngineService

Créer

recommendation-engine.service.ts

Méthodes

recommendForUser()
 
recommendSimilarProperties()
 
recommendTrending()

Étape 16 — Facteurs

Historique recherches

Réservations

Favoris

Reviews

Préférences

Étape 17 — Types

Supporter

Similar

Trending

Recently Viewed

Personalized

Popular

Sprint 4-I.2-F

Personnalisation


Étape 18 — PersonalizationService

Créer

personalization.service.ts

Méthodes

buildUserProfile()
 
updatePreferences()
 
personalizeRanking()

Étape 19 — Profil

Utiliser

Search History

Bookings

Preferences

Behavior

Étape 20 — Exemple

Utilisateur

Voyage famille

↓

Prioriser

Family Friendly

Sprint 4-I.2-G

Intent Detection


Étape 21 — IntentDetectionService

Créer

intent-detection.service.ts

Détecter

Business Travel

Family Vacation

Luxury Stay

Remote Work

Romantic Getaway

Étape 22 — Extraction

Identifier

Budget

Guests

Location

Amenities

Dates

Étape 23 — Exemple

Requête

Je cherche un logement calme
pour travailler à distance

Résultat

Intent:
REMOTE_WORK

Confidence:
94%

Sprint 4-I.2-H

Property Intelligence Graph


Étape 24 — PropertyIntelligenceGraphService

Créer

property-intelligence-graph.service.ts

Connecter

Properties

Amenities

Reviews

Locations

Customers

Étape 25 — Relations

Exemple

Property

↓

Wifi

↓

Remote Work

↓

Business Traveler

Étape 26 — Utilisation

Alimenter

Recommendations

Semantic Search

Discovery

Sprint 4-I.2-I

API Discovery


Étape 27 — Endpoints

Ajouter

POST /discovery/search
 
GET  /discovery/recommendations
 
GET  /discovery/trending
 
GET  /discovery/similar/{propertyId}
 
POST /discovery/intent

Étape 28 — Exemple

Requête

{
  "query":"Villa avec piscine pour famille"
}

Réponse

{
  "intent":"FAMILY_VACATION",
  "results":[],
  "recommendations":[]
}

Étape 29 — Analytics IA

Mesurer

Recommendation CTR

Search Satisfaction

Discovery Conversion

Intent Accuracy

Sprint 4-I.2-J

Gouvernance


Étape 30 — Permissions

Ajouter

discovery.search

discovery.recommend

discovery.personalization

discovery.analytics

discovery.admin

Étape 31 — Audit

Journaliser

SEMANTIC_SEARCH_EXECUTED

VECTOR_SEARCH_EXECUTED

RECOMMENDATION_GENERATED

INTENT_DETECTED

DISCOVERY_RESULT_CLICKED

Étape 32 — Jobs

Ajouter

Toutes les heures

Recommendation Refresh

Toutes les nuits

Embedding Generation

Intent Training

Ranking Rebuild

Préparation Sprint 5

Compatible avec :

Reservation Suggestions

Upsell Engine

Cross Sell Engine

Préparation Sprint 13

Compatible avec :

LLM Assistant

RAG

Knowledge Graph

Agentic Search

Préparation Sprint 20

Compatible avec :

Enterprise AI Discovery

Predictive Booking

Hyper Personalization

Property Intelligence Platform

Définition de terminé

Le Sprint 4-I.2 est terminé lorsque :

✓ Recherche sémantique

✓ Vector Search

✓ Recommandations

✓ Personnalisation

✓ Intent Detection

✓ AI Discovery

✓ Analytics IA

✓ Audit intégré

Livrables

PropertyEmbedding

SearchIntent

RecommendationProfile

PropertyRecommendation

SemanticSearchService

VectorSearchService

RecommendationEngineService

PersonalizationService

IntentDetectionService

PropertyIntelligenceGraphService

AI Discovery Platform

Sprint 4-J.1 — Property Analytics & Dashboard

Objectif

Construire le cockpit opérationnel central des propriétés.

Cette couche fournit une vision temps réel de :

Occupation

Revenus

Avis

Disponibilités

Performance

Réservations

afin de permettre le pilotage métier des propriétés.

À l'issue de cette étape :

✓ Property Dashboard

✓ Occupancy Analytics

✓ Revenue Analytics

✓ Review Analytics

✓ Availability Analytics

✓ Performance KPIs

✓ Executive Dashboard

Architecture cible

Property Analytics Platform

├── Occupancy Analytics
├── Revenue Analytics
├── Review Analytics
├── Availability Analytics
├── Search Analytics
├── Booking Analytics
└── KPI Dashboard

↓

Property Intelligence

↓

Revenue Management

Sprint 4-J.1-A

Extension Prisma


Étape 1 — PropertyAnalyticsSnapshot

Ajouter dans schema.prisma

model PropertyAnalyticsSnapshot {
 
  id                    String
                        @id
                        @default(uuid())
 
  tenantId              String
 
  propertyId            String
 
  snapshotDate          DateTime
 
  occupancyRate         Float?
 
  averageDailyRate      Decimal?
                        @db.Decimal(12,2)
 
  revenue               Decimal?
                        @db.Decimal(14,2)
 
  reviewScore           Float?
 
  reviewCount           Int?
 
  availabilityRate      Float?
 
  searchViews           Int?
                        @default(0)
 
  bookings              Int?
                        @default(0)
 
  createdAt             DateTime
                        @default(now())
 
  @@unique([
    propertyId,
    snapshotDate
  ])
 
  @@index([tenantId])
 
  @@index([propertyId])
 
  @@index([snapshotDate])
}

Étape 2 — PropertyKPI

Ajouter

model PropertyKPI {
 
  propertyId            String
                        @id
 
  occupancyRate         Float?
 
  averageDailyRate      Float?
 
  revPar                Float?
 
  revenue               Float?
 
  reviewScore           Float?
 
  conversionRate        Float?
 
  searchRanking         Float?
 
  reputationScore       Float?
 
  updatedAt             DateTime
                        @updatedAt
}

Étape 3 — Migration

Générer

npx prisma migrate dev \
--name property_analytics

Sprint 4-J.1-B

Analytics Module


Étape 4 — Création

src/modules/property-analytics

├── dashboard
│
├── occupancy
│
├── revenue
│
├── reviews
│
├── availability
│
├── kpi
│
└── property-analytics.module.ts

Étape 5 — Services

Créer

PropertyDashboardService

OccupancyAnalyticsService

RevenueAnalyticsService

ReviewAnalyticsService

AvailabilityAnalyticsService

PropertyKPIService

Sprint 4-J.1-C

Occupancy Analytics


Étape 6 — OccupancyAnalyticsService

Créer

occupancy-analytics.service.ts

Méthodes

calculateOccupancyRate()
 
calculateOccupancyTrend()
 
forecastOccupancy()

Étape 7 — KPI

Calculer

Occupied Nights

Available Nights

Occupancy %

Average Stay

Étape 8 — Exemple

Occupancy

82%

↑ +6%

Sprint 4-J.1-D

Revenue Analytics


Étape 9 — RevenueAnalyticsService

Créer

revenue-analytics.service.ts

Méthodes

calculateRevenue()
 
calculateADR()
 
calculateRevPAR()
 
calculateRevenueTrend()

Étape 10 — KPI

Mesurer

Revenue

ADR

RevPAR

Revenue Growth

Étape 11 — Exemple

Revenue

45 000 €

↑ 12%

Sprint 4-J.1-E

Review Analytics


Étape 12 — ReviewAnalyticsService

Créer

review-analytics.service.ts

Méthodes

calculateAverageRating()
 
analyzeSentimentTrend()
 
calculateResponseRate()

Étape 13 — KPI

Mesurer

Average Rating

Review Count

Trust Score

Sentiment Trend

Étape 14 — Exemple

Rating

4.8 / 5

↑ 0.2

Sprint 4-J.1-F

Availability Analytics


Étape 15 — AvailabilityAnalyticsService

Créer

availability-analytics.service.ts

Méthodes

calculateAvailabilityRate()
 
detectAvailabilityGaps()
 
analyzeBlockedDates()

Étape 16 — KPI

Mesurer

Available Days

Blocked Days

Maintenance Days

Availability %

Étape 17 — Exemple

Availability

74%

Blocked

12 jours

Sprint 4-J.1-G

Dashboard Principal


Étape 18 — PropertyDashboardService

Créer

property-dashboard.service.ts

Agréger

Occupancy

Revenue

Reviews

Availability

Search

Bookings

Étape 19 — Endpoint

Ajouter

GET /properties/{id}/dashboard

Étape 20 — Exemple

Retour

{
  "occupancy":82,
  "revenue":45000,
  "rating":4.8,
  "availability":74,
  "bookings":34
}

Sprint 4-J.1-H

KPI Engine


Étape 21 — PropertyKPIService

Créer

property-kpi.service.ts

Calculer

Occupancy Score

Revenue Score

Review Score

Availability Score

Search Score

Global Score

Étape 22 — Global Score

Pondération

Revenue      30%

Occupancy    25%

Reviews      20%

Availability 15%

Search       10%

Étape 23 — Classement

Supporter

Top Properties

Most Profitable

Best Rated

Highest Occupancy

Sprint 4-J.1-I

API Analytics


Étape 24 — Endpoints

Ajouter

GET /properties/{id}/dashboard
 
GET /properties/{id}/analytics/occupancy
 
GET /properties/{id}/analytics/revenue
 
GET /properties/{id}/analytics/reviews
 
GET /properties/{id}/analytics/availability
 
GET /properties/{id}/analytics/kpis

Étape 25 — Périodes

Supporter

Today

7 Days

30 Days

90 Days

12 Months

Custom Range

Étape 26 — Export

Ajouter

GET /properties/{id}/analytics/export

Formats :

CSV

Excel

PDF

Sprint 4-J.1-J

Gouvernance


Étape 27 — Permissions

Ajouter

property.analytics.read

property.analytics.export

property.analytics.kpi

property.analytics.admin

Étape 28 — Audit

Journaliser

PROPERTY_DASHBOARD_VIEWED

PROPERTY_ANALYTICS_VIEWED

PROPERTY_KPI_CALCULATED

PROPERTY_ANALYTICS_EXPORTED

Étape 29 — Jobs

Ajouter

Toutes les heures

KPI Refresh

Toutes les nuits

Analytics Snapshot

Score Rebuild

Étape 30 — Compatibilité

Préparer :

Revenue Management

Booking Engine

Business Intelligence

Executive Reporting

Définition de terminé

Le Sprint 4-J.1 est terminé lorsque :

✓ Dashboard propriété

✓ Occupancy Analytics

✓ Revenue Analytics

✓ Review Analytics

✓ Availability Analytics

✓ KPI Engine

✓ Export Analytics

✓ Audit intégré

Livrables

PropertyAnalyticsSnapshot

PropertyKPI

PropertyDashboardService

OccupancyAnalyticsService

RevenueAnalyticsService

ReviewAnalyticsService

AvailabilityAnalyticsService

PropertyKPIService

Property Analytics Dashboard

Sprint 4-J.2 — Property Intelligence & Analytics Prédictifs

Objectif

Transformer le cockpit analytique en plateforme Property Intelligence Enterprise.

À l'issue de cette étape :

✓ Prévision occupation

✓ Prévision revenus

✓ Prévision demande

✓ Détection anomalies

✓ Insights IA

✓ Property Health Score

✓ Property Intelligence Platform

Architecture cible

Property Analytics

↓

Property Intelligence Engine

├── Occupancy Forecast
├── Revenue Forecast
├── Demand Forecast
├── Anomaly Detection
├── AI Insights
├── Health Scoring
└── Optimization Recommendations

↓

Revenue Management

↓

Executive Intelligence

Sprint 4-J.2-A

Extension Prisma


Étape 1 — PropertyForecast

Ajouter dans schema.prisma

model PropertyForecast {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  forecastType          ForecastType
 
  forecastDate          DateTime
 
  predictedValue        Float
 
  confidenceScore       Float?
 
  generatedAt           DateTime
                        @default(now())
 
  @@index([propertyId])
 
  @@index([forecastType])
 
  @@index([forecastDate])
}

Étape 2 — PropertyInsight

Ajouter

model PropertyInsight {
 
  id                    String
                        @id
                        @default(uuid())
 
  propertyId            String
 
  severity              InsightSeverity
 
  category              InsightCategory
 
  title                 String
 
  description           String
 
  recommendation        String?
 
  impactScore           Float?
 
  resolved              Boolean
                        @default(false)
 
  createdAt             DateTime
                        @default(now())
 
  @@index([propertyId])
 
  @@index([resolved])
 
  @@index([category])
}

Étape 3 — PropertyHealthScore

Ajouter

model PropertyHealthScore {
 
  propertyId            String
                        @id
 
  overallScore          Float
 
  occupancyScore        Float
 
  revenueScore          Float
 
  reviewScore           Float
 
  availabilityScore     Float
 
  complianceScore       Float
 
  reputationScore       Float
 
  calculatedAt          DateTime
                        @updatedAt
}

Étape 4 — Enums

Ajouter

enum ForecastType {
 
  OCCUPANCY
 
  REVENUE
 
  DEMAND
 
  BOOKINGS
}
 
enum InsightSeverity {
 
  LOW
 
  MEDIUM
 
  HIGH
 
  CRITICAL
}
 
enum InsightCategory {
 
  OCCUPANCY
 
  REVENUE
 
  REVIEWS
 
  DEMAND
 
  AVAILABILITY
 
  COMPLIANCE
}

Étape 5 — Migration

Générer

npx prisma migrate dev \
--name property_intelligence

Sprint 4-J.2-B

Intelligence Module


Étape 6 — Création

src/modules/property-intelligence

├── forecasts
│
├── anomalies
│
├── insights
│
├── health-score
│
├── optimization
│
└── property-intelligence.module.ts

Étape 7 — Services

Créer

OccupancyForecastService

RevenueForecastService

DemandForecastService

AnomalyDetectionService

PropertyInsightService

PropertyHealthScoreService

Sprint 4-J.2-C

Prévision d'Occupation


Étape 8 — OccupancyForecastService

Créer

occupancy-forecast.service.ts

Méthodes

forecastOccupancy()
 
forecastSeasonality()
 
forecastBookingWindow()

Étape 9 — Sources

Utiliser

Availability

Reservations

Seasonality

Events

Historical Occupancy

Étape 10 — Exemple

Août

Occupation prévue

91%

Confiance

88%

Sprint 4-J.2-D

Prévision de Revenus


Étape 11 — RevenueForecastService

Créer

revenue-forecast.service.ts

Méthodes

forecastRevenue()
 
forecastADR()
 
forecastRevPAR()

Étape 12 — Sources

Revenue History

Pricing

Occupancy Forecast

Demand Forecast

Étape 13 — Exemple

Revenu prévisionnel

52 000 €

+14%

Sprint 4-J.2-E

Prévision de Demande


Étape 14 — DemandForecastService

Créer

demand-forecast.service.ts

Détecter

Haute saison

Vacances

Événements

Tendances marché

Étape 15 — Méthodes

forecastDemand()
 
detectDemandPeaks()
 
recommendPricingActions()

Étape 16 — Exemple

Demande

+27%

↓

Augmentation tarifaire
recommandée

Sprint 4-J.2-F

Détection d'Anomalies


Étape 17 — AnomalyDetectionService

Créer

anomaly-detection.service.ts

Méthodes

detectOccupancyAnomalies()
 
detectRevenueAnomalies()
 
detectReviewAnomalies()
 
detectAvailabilityAnomalies()

Étape 18 — Détecter

Baisse brutale occupation

Chute revenus

Explosion annulations

Avis négatifs anormaux

Blocages excessifs

Étape 19 — Exemple

Occupation

-32%

↓

Alerte HIGH

Sprint 4-J.2-G

Insights IA


Étape 20 — PropertyInsightService

Créer

property-insight.service.ts

Générer

Opportunités

Risques

Optimisations

Recommandations

Étape 21 — Exemple

Les week-ends sont
réservés à 96%

↓

Augmenter tarifs
de 10%

Étape 22 — Exemple

Faible taux
de réservation
en novembre

↓

Lancer campagne
promotionnelle

Sprint 4-J.2-H

Property Health Score


Étape 23 — PropertyHealthScoreService

Créer

property-health-score.service.ts

Calcul

Occupation      25%

Revenus         25%

Avis            20%

Réputation      10%

Disponibilité   10%

Conformité      10%

Étape 24 — Classification

90-100 Excellent

75-89 Healthy

50-74 At Risk

0-49 Critical

Étape 25 — Exemple

Property Health

93

Excellent

Sprint 4-J.2-I

Dashboard Intelligence


Étape 26 — Endpoint

Ajouter

GET /properties/{id}/intelligence

Retour

{
  "healthScore":93,
  "occupancyForecast":91,
  "revenueForecast":52000,
  "insights":[]
}

Étape 27 — Endpoints

Ajouter

GET /properties/{id}/forecasts
 
GET /properties/{id}/insights
 
GET /properties/{id}/health-score
 
GET /properties/{id}/anomalies

Étape 28 — Analytics IA

Mesurer

Forecast Accuracy

Insight Adoption

Health Score Trends

Anomaly Resolution Rate

Sprint 4-J.2-J

Gouvernance


Étape 29 — Permissions

Ajouter

property.intelligence.read

property.intelligence.forecast

property.intelligence.insights

property.intelligence.health

property.intelligence.admin

Étape 30 — Audit

Journaliser

FORECAST_GENERATED

ANOMALY_DETECTED

PROPERTY_INSIGHT_CREATED

HEALTH_SCORE_UPDATED

INTELLIGENCE_DASHBOARD_VIEWED

Étape 31 — Jobs

Ajouter

Toutes les heures

Anomaly Detection

Toutes les nuits

Forecast Generation

Health Score Refresh

Insight Generation

Clôture Sprint 4

À la fin du Sprint 4, la plateforme dispose désormais de :

✓ Catalogue Propriétés

✓ Amenities

✓ Images Enterprise

✓ Disponibilités

✓ Channel Manager

✓ Tarification

✓ Revenue Management

✓ Policies

✓ Legal Compliance

✓ Reviews

✓ Reputation Intelligence

✓ Search Engine

✓ AI Discovery

✓ Analytics

✓ Property Intelligence

Préparation Sprint 5

Compatible avec :

Reservations

Booking Workflow

Payments

Check-In

Guest Journey

Préparation Sprint 13

Compatible avec :

AI Platform

Knowledge Graph

LLM Agents

Predictive Intelligence

Préparation Sprint 20

Compatible avec :

Enterprise Property Platform

AI Revenue Management

Predictive Operations

Global Hospitality OS

Définition de terminé

Le Sprint 4-J.2 est terminé lorsque :

✓ Prévision occupation

✓ Prévision revenus

✓ Prévision demande

✓ Détection anomalies

✓ Insights IA

✓ Property Health Score

✓ Dashboard Intelligence

✓ Audit intégré

Livrables

PropertyForecast

PropertyInsight

PropertyHealthScore

OccupancyForecastService

RevenueForecastService

DemandForecastService

AnomalyDetectionService

PropertyInsightService

PropertyHealthScoreService

Property Intelligence Platform
ujusum/3-codage/2-sprints/4-sprint-4.txt · Dernière modification : 2026/06/10 16:43 de 83.202.252.200

DokuWiki Appliance - Powered by TurnKey Linux