Table des matières
Sprint 3 — Gestion des Clients
Objectif
Implémenter le premier domaine métier CRM complet de la plateforme.
Le domaine :
Customer
deviendra le pivot central de :
Réservations Facturation CRM Marketing Communication Programme de fidélité Revenue Management
Périmètre du Sprint 3
Entités
Customer CustomerAddress CustomerDocument CustomerTag CustomerNote CustomerCommunication CustomerPreference
Fonctionnalités
CRUD Clients Profil Client Adresses Documents Tags CRM Notes internes Historique communications Préférences client Segmentation Fidélisation
Architecture cible
Customer ├── Addresses ├── Documents ├── Tags ├── Notes ├── Communications ├── Preferences ├── Reservations ├── Invoices └── CRM Activities
Découpage du Sprint
Sprint 3-A
Modèle CRM Prisma
Customer CustomerAddress CustomerPreference
Sprint 3-B
CRUD Clients
CustomerModule CustomerController CustomerService
Sprint 3-C
Adresses Client
CustomerAddressModule
Sprint 3-D
Documents Client
CustomerDocument Upload Stockage
Sprint 3-E
Tags CRM
CustomerTag Segmentation
Sprint 3-F
Notes CRM
CustomerNote
Sprint 3-G
Communications
CustomerCommunication
Sprint 3-H
Préférences Client
CustomerPreference
Sprint 3-I
Recherche CRM Avancée
Filtres Segmentation Recherche globale
Sprint 3-J
Vue CRM Enterprise
Dashboard Client Vue 360° Historique complet
Sprint 3-A.1 — Implémentation Prisma CRM Core
Objectif
Créer le socle CRM principal de la plateforme.
Ces modèles deviendront les fondations de :
Reservations CRM Marketing Facturation Communication Fidélisation Revenue Management
Architecture CRM
Customer ├── CustomerAddress ├── CustomerPreference ├── Reservations ├── Invoices ├── Notes ├── Tags ├── Documents └── Communications
Étape 1 — Création Customer
Ajouter dans schema.prisma
model Customer {
id String
@id
@default(uuid())
tenantId String
customerNumber String?
externalReference String?
type String
@default("INDIVIDUAL")
status String
@default("ACTIVE")
firstName String
lastName String
companyName String?
email String?
phone String?
mobilePhone String?
dateOfBirth DateTime?
nationality String?
language String?
source String?
acquisitionChannel String?
notes String?
vip Boolean
@default(false)
blacklisted Boolean
@default(false)
marketingConsent Boolean
@default(false)
emailVerified Boolean
@default(false)
phoneVerified Boolean
@default(false)
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
deletedAt DateTime?
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
addresses CustomerAddress[]
preferences CustomerPreference?
@@index([tenantId])
@@index([status])
@@index([email])
@@index([phone])
@@index([vip])
@@index([createdAt])
@@unique([
tenantId,
customerNumber
])
}
Étape 2 — Création CustomerAddress
Ajouter
model CustomerAddress {
id String
@id
@default(uuid())
customerId String
label String
addressLine1 String
addressLine2 String?
postalCode String
city String
state String?
country String
latitude Decimal?
@db.Decimal(10,7)
longitude Decimal?
@db.Decimal(10,7)
formattedAddress String?
placeId String?
isDefault Boolean
@default(false)
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
@@index([customerId])
@@index([country])
@@index([city])
@@index([isDefault])
}
Étape 3 — Création CustomerPreference
Ajouter
model CustomerPreference {
id String
@id
@default(uuid())
customerId String
@unique
preferredLanguage String?
preferredCurrency String?
preferredChannel String?
prefersEmail Boolean
@default(true)
prefersSms Boolean
@default(false)
prefersPhone Boolean
@default(false)
acceptsMarketing Boolean
@default(false)
acceptsNewsletter Boolean
@default(false)
acceptsPromotions Boolean
@default(false)
acceptsSurveys Boolean
@default(false)
loyaltyEligible Boolean
@default(true)
vipProgramEligible Boolean
@default(false)
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
@@index([preferredLanguage])
@@index([preferredCurrency])
@@index([acceptsMarketing])
}
Étape 4 — Relation Tenant
Ajouter dans Tenant
customers Customer[]
Étape 5 — Préparation Reservations
Ajouter dans Customer
reservations Reservation[]
Ajouter dans Reservation
customerId String?
customer Customer?
@relation(
fields:[customerId],
references:[id]
)
Étape 6 — Préparation CRM
Ajouter dans Customer
Relations futures :
notes CustomerNote[] documents CustomerDocument[] communications CustomerCommunication[] tags CustomerTag[]
Ne pas créer encore
Ces modèles arriveront dans :
Sprint 3-D Sprint 3-E Sprint 3-F Sprint 3-G
Étape 7 — Préparation Marketing
Champs CRM
Déjà présents :
source acquisitionChannel marketingConsent
Exemples
Website Booking Airbnb Google Ads Facebook Referral Direct
Étape 8 — Préparation Fidélité
Champs
vip loyaltyEligible vipProgramEligible
Utilisation future
Loyalty Program Reward Engine Customer Segmentation
Étape 9 — Migration
Générer
npx prisma migrate dev \
--name crm_customer_core
Générer
npx prisma generate
Étape 10 — Validation
Exécuter
npx prisma validate
Résultat attendu
The schema at prisma/schema.prisma is valid
Étape 11 — Vérification SQL
PostgreSQL
\d "Customer" \d "CustomerAddress" \d "CustomerPreference"
Modèle CRM obtenu
Customer │ ├── Profil CRM │ ├── Préférences │ ├── Adresses │ ├── Réservations │ ├── Marketing │ └── Fidélité
Définition de terminé
Le Sprint 3-A.1 est terminé lorsque :
✓ Customer créé ✓ CustomerAddress créée ✓ CustomerPreference créée ✓ Tenant relation ajoutée ✓ Reservation relation préparée ✓ Migration exécutée ✓ Prisma Client généré ✓ Validation Prisma verte
Livrables
Customer CustomerAddress CustomerPreference Migration crm_customer_core Prisma Client mis à jour
Sprint 3-A.2 — Amélioration Enterprise du modèle Customer
Objectif
Faire évoluer le modèle CRM Core vers un modèle Enterprise capable de supporter :
CRM avancé Segmentation Marketing Automation Fidélisation Analyse comportementale Revenue Management RGPD Conformité
Architecture cible
Customer ├── Profile ├── Preferences ├── Addresses ├── Segmentation ├── Scoring ├── Risk ├── Lifetime Value ├── GDPR ├── Communications ├── Reservations └── CRM History
Sprint 3-A.2-A
CustomerStatus
Étape 1 — Création Enum
Ajouter
enum CustomerStatus {
LEAD
ACTIVE
VIP
INACTIVE
BLOCKED
BLACKLISTED
}
Étape 2 — Utilisation
Remplacer
Dans :
model Customer
Ancien
status String
Nouveau
status CustomerStatus
@default(ACTIVE)
Sprint 3-A.2-B
CustomerSource
Étape 3 — Enum Source
Ajouter
enum CustomerSource {
WEBSITE
DIRECT
AIRBNB
BOOKING
EXPEDIA
VRBO
GOOGLE
FACEBOOK
INSTAGRAM
REFERRAL
PARTNER
IMPORT
OTHER
}
Étape 4 — Utilisation
Remplacer
source String?
Par
source CustomerSource?
Sprint 3-A.2-C
Customer Score
Étape 5 — Ajouter
Dans :
model Customer
Champs
customerScore Int
@default(0)
engagementScore Int
@default(0)
satisfactionScore Int
@default(0)
loyaltyScore Int
@default(0)
Utilisation
Segmentation CRM Marketing Fidélisation
Sprint 3-A.2-D
Customer Lifetime Value
Étape 6 — Ajouter
lifetimeValue Decimal?
@db.Decimal(14,2)
totalReservations Int
@default(0)
totalRevenue Decimal?
@db.Decimal(14,2)
averageBasket Decimal?
@db.Decimal(14,2)
lastReservationAt DateTime?
Préparation
Pour :
Revenue Management Business Intelligence Customer Analytics
Sprint 3-A.2-E
Customer Risk
Étape 7 — Enum
enum CustomerRiskLevel {
LOW
MEDIUM
HIGH
CRITICAL
}
Étape 8 — Ajouter
Dans Customer :
riskLevel CustomerRiskLevel
@default(LOW)
riskScore Int
@default(0)
fraudFlag Boolean
@default(false)
Utilisation
Fraude Paiements Réservations Sécurité
Sprint 3-A.2-F
Segmentation
Étape 9 — Enum
enum CustomerSegment {
STANDARD
FREQUENT
VIP
CORPORATE
OWNER
PARTNER
BLACKLISTED
}
Étape 10 — Ajouter
segment CustomerSegment
@default(STANDARD)
Utilisation
Campagnes CRM Automatisation Fidélisation
Sprint 3-A.2-G
RGPD
Étape 11 — Ajouter
Dans Customer :
gdprConsentGiven Boolean
@default(false)
gdprConsentAt DateTime?
marketingConsentAt DateTime?
privacyPolicyAccepted Boolean
@default(false)
privacyPolicyAcceptedAt DateTime?
dataRetentionUntil DateTime?
Préparation
Pour :
Consent ComplianceAudit RetentionPolicy
Sprint 3-A.2-H
Historisation CRM
Étape 12 — Création CustomerHistory
Ajouter
model CustomerHistory {
id String
@id
@default(uuid())
customerId String
changedField String
oldValue String?
newValue String?
changedBy String?
changedAt DateTime
@default(now())
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
@@index([customerId])
@@index([changedAt])
}
Étape 13 — Relation
Ajouter
Dans :
model Customer
history CustomerHistory[]
Sprint 3-A.2-I
Scoring Automatique
Étape 14 — Préparer
Ajouter dans Customer :
firstReservationAt DateTime? lastCommunicationAt DateTime? lastActivityAt DateTime?
Calcul futur
Customer Score Engagement Score Loyalty Score Risk Score
seront alimentés par :
Reservations Invoices CRM Activities Communications
Sprint 3-A.2-J
Préparation Marketing
Étape 15 — Ajouter
preferredPropertyType String? preferredStayDuration Int? preferredDestination String? preferredTravelSeason String?
Utilisation
Marketing IA Recommandations Segmentation Campagnes
Étape 16 — Index CRM
Ajouter
Dans Customer :
@@index([segment]) @@index([customerScore]) @@index([riskLevel]) @@index([source]) @@index([lifetimeValue]) @@index([lastReservationAt]) @@index([gdprConsentGiven])
Étape 17 — Migration
Générer
npx prisma migrate dev \
--name customer_enterprise
Générer
npx prisma generate
Étape 18 — Validation
Exécuter
npx prisma validate
Résultat attendu
The schema at prisma/schema.prisma is valid
Modèle CRM Enterprise obtenu
Customer ├── Profil ├── Adresses ├── Préférences ├── Segmentation ├── Score ├── Lifetime Value ├── Risque ├── RGPD ├── Historique ├── Marketing └── Fidélisation
Définition de terminé
Le Sprint 3-A.2 est terminé lorsque :
✓ CustomerStatus ✓ CustomerSource ✓ CustomerScore ✓ CustomerLifetimeValue ✓ CustomerRisk ✓ CustomerSegment ✓ RGPD ✓ CustomerHistory ✓ Index CRM ✓ Migration exécutée
Livrables
Customer Enterprise CustomerHistory CustomerStatus CustomerSource CustomerSegment CustomerRiskLevel Migration customer_enterprise
Sprint 3-B.1 — Création du CustomerModule
Objectif
Implémenter le premier module CRM métier complet basé sur :
Customer
avec :
CRUD Clients Recherche CRM Pagination Tri Filtres Multi-Tenant Security Swagger
Architecture
Créer
src/modules/customers
Structure
customers ├── application │ │ └── dto │ │ ├── create-customer.dto.ts │ ├── update-customer.dto.ts │ ├── customer-query.dto.ts │ └── customer-response.dto.ts │ ├── domain │ │ └── services │ │ └── customer.service.ts │ ├── presentation │ │ └── controllers │ │ └── customer.controller.ts │ └── customer.module.ts
Sprint 3-B.1-A
DTOs
Étape 1 — CreateCustomerDto
Créer
create-customer.dto.ts
Implémentation
export class CreateCustomerDto {
firstName: string;
lastName: string;
email?: string;
phone?: string;
mobilePhone?: string;
companyName?: string;
language?: string;
source?: string;
marketingConsent?: boolean;
}
Étape 2 — UpdateCustomerDto
Créer
update-customer.dto.ts
Implémentation
export class UpdateCustomerDto
extends PartialType(
CreateCustomerDto
) {}
Étape 3 — CustomerQueryDto
Créer
customer-query.dto.ts
Ajouter
export class CustomerQueryDto {
page?: number = 1;
limit?: number = 25;
search?: string;
status?: string;
segment?: string;
source?: string;
vip?: boolean;
sortBy?: string =
'createdAt';
sortOrder?: 'asc' | 'desc' =
'desc';
}
Étape 4 — CustomerResponseDto
Créer
customer-response.dto.ts
Ajouter
export class CustomerResponseDto {
id: string;
firstName: string;
lastName: string;
email?: string;
phone?: string;
status: string;
segment: string;
customerScore: number;
lifetimeValue?: number;
vip: boolean;
createdAt: Date;
}
Sprint 3-B.1-B
CustomerService
Étape 5 — Création
Créer
customer.service.ts
Injection
@Injectable()
export class CustomerService {
constructor(
private readonly prisma:
PrismaService
) {}
}
Étape 6 — Méthodes
Ajouter
findAll() findOne() create() update() remove()
Étape 7 — Multi-Tenant Security
Principe
Aucune requête CRM ne doit sortir du tenant.
Exemple
where: {
tenantId:
currentTenantId
}
Obligatoire
Dans :
Toutes les requêtes
Étape 8 — Recherche CRM
Recherche globale
OR: [
{
firstName: {
contains: search,
mode: 'insensitive'
}
},
{
lastName: {
contains: search,
mode: 'insensitive'
}
},
{
email: {
contains: search,
mode: 'insensitive'
}
},
{
companyName: {
contains: search,
mode: 'insensitive'
}
}
]
Étape 9 — Filtres
Ajouter
status segment source vip
Exemple
if (query.vip !== undefined) {
where.vip =
query.vip;
}
Étape 10 — Pagination
Calcul
const skip = (page - 1) * limit;
Prisma
skip, take: limit
Étape 11 — Tri
Ajouter
orderBy: {
[query.sortBy]:
query.sortOrder
}
Étape 12 — findAll
Implémentation
async findAll(
tenantId: string,
query:
CustomerQueryDto
)
Retour
return {
data:
customers,
meta: {
page,
limit,
total
}
};
Étape 13 — findOne
Implémentation
async findOne( tenantId: string, id: string )
Sécurité
where: {
id,
tenantId
}
Sinon
throw new NotFoundException( 'Customer not found' );
Étape 14 — create
Génération CRM
customerNumber =
`CUS-${Date.now()}`
Création
await prisma.customer.create({
data: {
tenantId,
customerNumber,
...dto
}
});
Étape 15 — CustomerPreference
Création automatique
await prisma.customerPreference.create({
data: {
customerId:
customer.id
}
});
Étape 16 — update
Vérifier
Customer existe + Même tenant
Mise à jour
await prisma.customer.update(...)
Étape 17 — remove
Soft Delete
Ne jamais supprimer réellement.
Ajouter
deletedAt: new Date()
Mise à jour
await prisma.customer.update({
where: {
id
},
data: {
deletedAt:
new Date(),
status:
'INACTIVE'
}
});
Sprint 3-B.1-C
CustomerController
Étape 18 — Création
Créer
customer.controller.ts
Déclaration
@ApiTags('Customers')
@Controller('customers')
@UseGuards(
JwtAuthGuard
)
@ApiBearerAuth()
Étape 19 — GET /customers
Route
@Get()
Paramètres
Recherche Pagination Filtres
Étape 20 — GET /customers/{id}
Route
@Get(':id')
Étape 21 — POST /customers
Route
@Post()
Étape 22 — PUT /customers/{id}
Route
@Put(':id')
Étape 23 — DELETE /customers/{id}
Route
@Delete(':id')
Sprint 3-B.1-D
CustomerModule
Étape 24 — Création
Créer
customer.module.ts
Implémentation
@Module({
imports: [
PrismaModule,
AuthModule
],
controllers: [
CustomerController
],
providers: [
CustomerService
],
exports: [
CustomerService
]
})
export class CustomerModule {}
Étape 25 — AppModule
Ajouter
imports: [ ... CustomerModule ]
Sprint 3-B.1-E
Swagger
Étape 26 — Vérification
Endpoints
GET /customers
GET /customers/{id}
POST /customers
PUT /customers/{id}
DELETE /customers/{id}
Étape 27 — Exemple GET
Requête
GET /customers?page=1&limit=25
Réponse
{
"data": [
{
"id": "xxx",
"firstName": "Jean",
"lastName": "Dupont",
"segment": "VIP"
}
],
"meta": {
"page": 1,
"limit": 25,
"total": 132
}
}
Étape 28 — Exemple POST
Body
{
"firstName": "Jean",
"lastName": "Dupont",
"email": "jean@demo.fr",
"marketingConsent": true
}
Résultat
Customer créé CustomerPreference créée Numéro CRM généré
Préparation Sprint 3-C
Ce module servira directement à :
CustomerAddress CustomerDocument CustomerTag CustomerNote CustomerCommunication
Définition de terminé
Le Sprint 3-B.1 est terminé lorsque :
✓ CustomerModule créé ✓ CustomerController créé ✓ CustomerService créé ✓ CRUD Clients opérationnel ✓ Recherche CRM ✓ Pagination ✓ Filtres ✓ Multi-Tenant Security ✓ Swagger documenté ✓ Soft Delete
Livrables
CustomerModule CustomerController CustomerService CreateCustomerDto UpdateCustomerDto CustomerQueryDto CustomerResponseDto
Sprint 3-B.2 — CRM Enterprise Search & Segmentation
Objectif
Transformer le CRUD Clients en véritable CRM Enterprise.
À l'issue de cette étape :
✓ Recherche avancée ✓ Segmentation dynamique ✓ Smart Segments ✓ Scores CRM ✓ Filtres combinés ✓ Export CSV ✓ Vues enregistrées ✓ CRM Analytics Ready
Architecture cible
Customer ↓ CRM Search Engine ↓ Dynamic Filters ↓ Segmentation Engine ↓ Smart Segments ↓ Export / Campaigns / Analytics
Sprint 3-B.2-A
Segments CRM
Étape 1 — Création SavedCustomerView
Ajouter dans schema.prisma
model SavedCustomerView {
id String
@id
@default(uuid())
tenantId String
userId String
name String
description String?
filters Json
isDefault Boolean
@default(false)
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 — Création CustomerSegmentRule
Ajouter
model CustomerSegmentRule {
id String
@id
@default(uuid())
tenantId String
name String
code String
@unique
description String?
conditions Json
active Boolean
@default(true)
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
@@index([tenantId])
@@index([active])
}
Étape 3 — Migration
Générer
npx prisma migrate dev \
--name crm_segmentation
Générer
npx prisma generate
Sprint 3-B.2-B
Recherche CRM Avancée
Étape 4 — Extension CustomerQueryDto
Ajouter
customerScoreMin?: number; customerScoreMax?: number; lifetimeValueMin?: number; lifetimeValueMax?: number; riskLevel?: string; country?: string; language?: string; createdFrom?: Date; createdTo?: Date; lastReservationFrom?: Date; lastReservationTo?: Date; marketingConsent?: boolean; segment?: string; vip?: boolean;
Étape 5 — Recherche multi-critères
Exemple
AND: [ status, segment, vip, marketingConsent, riskLevel ]
Recherche texte
OR: [ firstName, lastName, email, companyName, customerNumber ]
Étape 6 — Recherche CRM complète
Exemple
VIP ET Score > 80 ET LifetimeValue > 5000€ ET MarketingConsent = true
Résultat
Liste filtrée
Sprint 3-B.2-C
CRM Score Engine
Étape 7 — Création
crm-score.service.ts
Méthodes
calculateCustomerScore() calculateEngagementScore() calculateLoyaltyScore()
Étape 8 — Exemple Score
Réservations +30 Paiements +20 Avis positifs +15 Ancienneté +20 Marketing +15
Total
100
Étape 9 — Classification
0-25 LOW
26-50 NORMAL
51-75 GOOD
76-100 EXCELLENT
Sprint 3-B.2-D
Smart Segments
Étape 10 — Segments automatiques
Créer
crm-segmentation.service.ts
Segments
VIP Frequent Travelers Corporate High Revenue Inactive High Risk Marketing Qualified
Étape 11 — Segment VIP
Règle
LifetimeValue > 10000 ET Score > 80
Étape 12 — Segment Inactif
Règle
Dernière réservation > 365 jours
Étape 13 — Segment Corporate
Règle
CompanyName != null
Sprint 3-B.2-E
Vues enregistrées
Étape 14 — DTO
Créer
create-saved-view.dto.ts
Structure
export class CreateSavedViewDto {
name: string;
description?: string;
filters: Record<
string,
unknown
>;
}
Étape 15 — API
Ajouter
GET /customers/views
POST /customers/views
DELETE /customers/views/{id}
Exemple
Mes VIP Clients inactifs Corporate France Top Revenue
Sprint 3-B.2-F
Export CSV
Étape 16 — Service
Créer
crm-export.service.ts
Méthodes
exportCsv() exportExcel()
Étape 17 — Colonnes
CustomerNumber FirstName LastName Email Segment Score LifetimeValue Status
Étape 18 — Endpoint
Ajouter
GET /customers/export
Paramètres
Même filtres CRM
Sprint 3-B.2-G
API CRM Enterprise
Étape 19 — Nouveaux endpoints
GET /customers/search
GET /customers/export
GET /customers/views
POST /customers/views
DELETE /customers/views/{id}
GET /customers/segments
POST /customers/segments/recalculate
Étape 20 — Exemple recherche
Requête
GET /customers/search
Paramètres
segment=VIP scoreMin=80 marketingConsent=true country=FR
Résultat
Liste CRM filtrée
Sprint 3-B.2-H
Multi-Tenant Security
Étape 21 — Obligatoire
Toutes les requêtes :
tenantId
doivent être injectées automatiquement.
Vérification
SavedCustomerView CustomerSegmentRule Customer Export
Étape 22 — Audit
Journaliser
CRM_SEARCH CRM_EXPORT CRM_SEGMENT_UPDATE CRM_VIEW_CREATE
dans :
AuditLog
Sprint 3-B.2-I
Préparation Marketing
Compatible
Campaign CampaignRecipient MarketingSegment AutomationRule Recommendation
Préparation IA
Compatible avec :
Customer Scoring Recommendations Lead Scoring Predictive Segmentation
Définition de terminé
Le Sprint 3-B.2 est terminé lorsque :
✓ Recherche avancée ✓ Segmentation dynamique ✓ Smart Segments ✓ CRM Score Engine ✓ Export CSV ✓ Vues enregistrées ✓ Audit CRM ✓ Swagger documenté
Livrables
SavedCustomerView CustomerSegmentRule CrmScoreService CrmSegmentationService CrmExportService CRM Search API CRM Segments API CRM Views API
Sprint 3-C.1 — Gestion des Adresses Client
Objectif
Implémenter la gestion complète des adresses CRM client basée sur :
CustomerAddress
avec :
CRUD Adresses Adresse principale Géolocalisation Validation avancée Multi-Tenant Security Historisation CRM
Architecture
Créer
src/modules/customer-addresses
Structure
customer-addresses ├── application │ │ └── dto │ │ ├── create-customer-address.dto.ts │ ├── update-customer-address.dto.ts │ └── customer-address-response.dto.ts │ ├── domain │ │ └── services │ │ └── customer-address.service.ts │ ├── presentation │ │ └── controllers │ │ └── customer-address.controller.ts │ └── customer-address.module.ts
Sprint 3-C.1-A
DTOs
Étape 1 — CreateCustomerAddressDto
Créer
create-customer-address.dto.ts
Implémentation
export class CreateCustomerAddressDto {
label: string;
addressLine1: string;
addressLine2?: string;
postalCode: string;
city: string;
state?: string;
country: string;
isDefault?: boolean;
}
Étape 2 — UpdateCustomerAddressDto
Créer
update-customer-address.dto.ts
Implémentation
export class UpdateCustomerAddressDto
extends PartialType(
CreateCustomerAddressDto
) {}
Étape 3 — CustomerAddressResponseDto
Créer
customer-address-response.dto.ts
Ajouter
export class CustomerAddressResponseDto {
id: string;
label: string;
addressLine1: string;
postalCode: string;
city: string;
country: string;
latitude?: number;
longitude?: number;
formattedAddress?: string;
isDefault: boolean;
createdAt: Date;
}
Sprint 3-C.1-B
CustomerAddressService
Étape 4 — Création
Créer
customer-address.service.ts
Injection
@Injectable()
export class CustomerAddressService {
constructor(
private readonly prisma:
PrismaService,
private readonly geocodingService:
GeocodingService
) {}
}
Étape 5 — Méthodes
Ajouter
findAll() create() update() remove() setDefault()
Étape 6 — Vérification CRM
Vérifier
Le client appartient au tenant.
Requête
const customer =
await prisma.customer.findFirst({
where: {
id: customerId,
tenantId
}
});
Sinon
throw new NotFoundException( 'Customer not found' );
Étape 7 — Recherche adresses
Implémentation
async findAll( tenantId: string, customerId: string )
Requête
return prisma.customerAddress.findMany({
where: {
customerId
},
orderBy: [
{
isDefault:
'desc'
},
{
createdAt:
'desc'
}
]
});
Sprint 3-C.1-C
Adresse principale
Étape 8 — Reset adresse principale
Ajouter
private async resetDefaultAddress( customerId: string )
Implémentation
await prisma.customerAddress.updateMany({
where: {
customerId
},
data: {
isDefault: false
}
});
Étape 9 — Création
Si
dto.isDefault === true
Exécuter
await resetDefaultAddress( customerId );
Étape 10 — Première adresse
Si aucune adresse
count === 0
Alors
isDefault = true
Sprint 3-C.1-D
Géolocalisation
Étape 11 — Construction adresse
Ajouter
const fullAddress =
`${dto.addressLine1}
${dto.postalCode}
${dto.city}
${dto.country}`;
Étape 12 — Géocoder
Utiliser
await geocodingService.geocode( fullAddress );
Retour
latitude longitude formattedAddress placeId
Étape 13 — Gestion erreur
Fallback
Si :
OpenStreetMap indisponible
Alors
Créer quand même l'adresse.
Valeurs
latitude = null longitude = null
Sprint 3-C.1-E
Validation avancée
Étape 14 — Validation pays
Réutiliser
SUPPORTED_COUNTRIES
Étape 15 — Validation code postal
Réutiliser
PostalCodeValidator
Étape 16 — Validation géographique
Vérifier
Ville Code postal Pays
sont cohérents avec :
GeocodingResult
Sinon
throw new BadRequestException( 'Address validation failed' );
Sprint 3-C.1-F
Historisation CRM
Étape 17 — CustomerHistory
Ajouter
Lors de :
CREATE UPDATE DELETE
Exemple
await prisma.customerHistory.create({
data: {
customerId,
changedField:
'address',
oldValue:
oldAddress,
newValue:
newAddress
}
});
Étape 18 — AuditLog
Journaliser
CUSTOMER_ADDRESS_CREATED CUSTOMER_ADDRESS_UPDATED CUSTOMER_ADDRESS_DELETED CUSTOMER_ADDRESS_DEFAULT_CHANGED
Sprint 3-C.1-G
Update
Étape 19 — Contrôle tenant
Vérifier
Customer Adresse Tenant
avant toute modification.
Étape 20 — Mise à jour
Si
dto.isDefault = true
Alors
resetDefaultAddress()
Puis
update()
Étape 21 — Delete
Soft Delete recommandé
Ajouter dans Prisma :
deletedAt DateTime?
à :
CustomerAddress
Suppression
deletedAt: new Date()
Sprint 3-C.1-H
CustomerAddressController
Étape 22 — Création
Créer
customer-address.controller.ts
Déclaration
@ApiTags('Customer Addresses')
@Controller(
'customers/:id/addresses'
)
@UseGuards(
JwtAuthGuard
)
@ApiBearerAuth()
Étape 23 — GET
Route
GET /customers/{id}/addresses
Étape 24 — POST
Route
POST /customers/{id}/addresses
Étape 25 — PUT
Route
PUT /customers/{id}/addresses/{addressId}
Étape 26 — DELETE
Route
DELETE /customers/{id}/addresses/{addressId}
Sprint 3-C.1-I
CustomerAddressModule
Étape 27 — Création
Créer
customer-address.module.ts
Implémentation
@Module({
imports: [
PrismaModule,
AuthModule,
GeocodingModule
],
controllers: [
CustomerAddressController
],
providers: [
CustomerAddressService
],
exports: [
CustomerAddressService
]
})
export class CustomerAddressModule {}
Étape 28 — Swagger
Vérifier
GET /customers/{id}/addresses
POST /customers/{id}/addresses
PUT /customers/{id}/addresses/{addressId}
DELETE /customers/{id}/addresses/{addressId}
Étape 29 — Exemple POST
Body
{
"label": "Residence",
"addressLine1": "10 Rue Victor Hugo",
"postalCode": "75001",
"city": "Paris",
"country": "FR",
"isDefault": true
}
Résultat
Adresse créée Adresse principale définie Coordonnées GPS calculées Historique CRM enregistré
Préparation Sprint 3-D
Les adresses client seront utilisées par :
Reservations Invoices Documents Marketing CRM Analytics
Définition de terminé
Le Sprint 3-C.1 est terminé lorsque :
✓ CustomerAddressModule créé ✓ CustomerAddressController créé ✓ CustomerAddressService créé ✓ CRUD adresses opérationnel ✓ Adresse principale opérationnelle ✓ Géolocalisation opérationnelle ✓ Validation avancée ✓ Historisation CRM ✓ AuditLog intégré ✓ Swagger documenté
Livrables
CustomerAddressModule CustomerAddressController CustomerAddressService CreateCustomerAddressDto UpdateCustomerAddressDto CustomerAddressResponseDto
Sprint 3-C.2 — Adresses Enterprise & Cartographie CRM
Objectif
Transformer le système d'adresses CRM en moteur géospatial Enterprise.
À l'issue de cette étape :
✓ Multi-adresses ✓ Zones géographiques ✓ Distance client ✓ Recherche par rayon ✓ Clustering géographique ✓ Cartographie CRM ✓ Heatmaps ✓ Géo-segmentation
Architecture cible
Customer ↓ CustomerAddress ↓ Geo Engine ↓ Spatial Queries ↓ Maps ↓ CRM Analytics
Sprint 3-C.2-A
Extension Prisma
Étape 1 — Création GeoZone
Ajouter
model GeoZone {
id String
@id
@default(uuid())
tenantId String
code String
name String
description String?
zoneType GeoZoneType
country String?
region String?
city String?
polygon Json?
centerLatitude Decimal?
@db.Decimal(10,7)
centerLongitude Decimal?
@db.Decimal(10,7)
radiusKm Decimal?
@db.Decimal(10,2)
active Boolean
@default(true)
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
@@index([tenantId])
@@index([zoneType])
@@index([active])
}
Étape 2 — Enum GeoZoneType
Ajouter
enum GeoZoneType {
COUNTRY
REGION
CITY
CUSTOM
SALES
MARKETING
DELIVERY
}
Étape 3 — Extension CustomerAddress
Ajouter
geoHash String?
geoValidated Boolean
@default(false)
geoValidatedAt DateTime?
timezone String?
district String?
Étape 4 — Migration
Générer
npx prisma migrate dev \
--name crm_geospatial
Générer
npx prisma generate
Sprint 3-C.2-B
GeoSpatial Module
Étape 5 — Création
src/modules/geospatial
Structure
geospatial ├── domain │ │ └── services │ │ ├── geo-distance.service.ts │ │ ├── geo-search.service.ts │ │ ├── geo-clustering.service.ts │ │ └── geo-zone.service.ts │ └── geospatial.module.ts
Étape 6 — Dépendances
Installer
npm install geolib npm install ngeohash
Sprint 3-C.2-C
Distance Client
Étape 7 — GeoDistanceService
Créer
geo-distance.service.ts
Méthodes
calculateDistance() calculateTravelRadius() findNearestCustomers()
Étape 8 — Calcul
Exemple
getDistance(
{
latitude: lat1,
longitude: lng1
},
{
latitude: lat2,
longitude: lng2
}
)
Retour
Distance en kilomètres
Étape 9 — Cas d'usage
Client ↔ Propriété Client ↔ Agence Client ↔ Région Client ↔ Zone commerciale
Sprint 3-C.2-D
Recherche par rayon
Étape 10 — Endpoint
Ajouter
GET /customers/search/radius
Paramètres
latitude longitude radiusKm
Étape 11 — Service
Ajouter
findCustomersInRadius( tenantId, lat, lng, radiusKm )
Retour
Tous les clients dans le rayon demandé
Étape 12 — Exemple
Recherche
Paris 50 km
Retour
Clients Paris Clients Versailles Clients Saint-Denis
Sprint 3-C.2-E
Clustering CRM
Étape 13 — GeoClusteringService
Créer
geo-clustering.service.ts
Méthodes
clusterCustomers() clusterByCity() clusterByRegion()
Étape 14 — Types
Ville Région Pays Distance Segment CRM
Étape 15 — Exemple
Résultat
{
"cluster":"Paris",
"customers":421
}
Sprint 3-C.2-F
Cartographie CRM
Étape 16 — DTO
Créer
customer-map-point.dto.ts
Structure
export class CustomerMapPointDto {
customerId: string;
customerNumber: string;
latitude: number;
longitude: number;
city: string;
segment: string;
customerScore: number;
}
Étape 17 — Endpoint
Ajouter
GET /customers/map
Retour
Points cartographiques CRM
Étape 18 — Préparation Front
Compatible :
Leaflet Mapbox Google Maps OpenLayers
Sprint 3-C.2-G
Heatmaps CRM
Étape 19 — Endpoint
Ajouter
GET /customers/heatmap
Retour
Densité clients par zone géographique
Étape 20 — Agrégation
Calcul
Nombre clients par géohash ou par ville
Exemple
[
{
"city":"Paris",
"count":421
},
{
"city":"Lyon",
"count":187
}
]
Sprint 3-C.2-H
Zones Marketing
Étape 21 — Gestion GeoZone
Endpoints
GET /geo-zones
POST /geo-zones
PUT /geo-zones/{id}
DELETE /geo-zones/{id}
Étape 22 — Segmentation
Exemple
Zone Paris ↓ Clients VIP ↓ Campagne Marketing
Étape 23 — Attribution automatique
Workflow
Adresse Client ↓ GeoZone Matching ↓ Segment Géographique ↓ Marketing
Sprint 3-C.2-I
CRM Analytics
Étape 24 — Dashboard
Ajouter
GET /customers/geographic-statistics
Retour
{
"countries":12,
"regions":38,
"cities":142,
"topCity":"Paris"
}
Étape 25 — Métriques
Top villes Top régions Répartition pays Répartition segments Lifetime Value géographique
Sprint 3-C.2-J
Audit & Sécurité
Étape 26 — Journaliser
Dans :
AuditLog
Événements
CRM_GEO_SEARCH CRM_MAP_VIEW CRM_HEATMAP_VIEW CRM_ZONE_CREATED CRM_ZONE_UPDATED
Étape 27 — Multi-Tenant
Obligatoire
Toutes les requêtes :
tenantId
doivent filtrer :
GeoZone Customer CustomerAddress
Préparation Sprint 9
Compatible avec :
Campaign MarketingSegment CampaignRecipient
Préparation Sprint 13
Compatible avec :
Recommendation AutomationScenario AI Segmentation
Définition de terminé
Le Sprint 3-C.2 est terminé lorsque :
✓ GeoZone créée ✓ Distance Client ✓ Recherche par rayon ✓ Clustering CRM ✓ Cartographie CRM ✓ Heatmaps ✓ Dashboard géographique ✓ Multi-Tenant Security ✓ Swagger documenté
Livrables
GeoZone GeoDistanceService GeoSearchService GeoClusteringService GeoZoneService CRM Map API CRM Heatmap API CRM Geographic Analytics
Sprint 3-D.1 — Gestion des Documents Client
Objectif
Implémenter la gestion documentaire CRM complète basée sur :
CustomerDocument
avec :
Upload Stockage MinIO/S3 Catégorisation Validation documentaire Historisation Audit RGPD
Architecture cible
Customer ↓ CustomerDocument ↓ StorageService ↓ MinIO / S3 ↓ CRM / Reservations / Compliance
Sprint 3-D.1-A
Modèle Prisma
Étape 1 — Création CustomerDocument
Ajouter dans schema.prisma
model CustomerDocument {
id String
@id
@default(uuid())
tenantId String
customerId String
documentType CustomerDocumentType
category String?
name String
originalFilename String
storagePath String
mimeType String
fileSize Int
checksum String?
version Int
@default(1)
status DocumentStatus
@default(PENDING)
expiresAt DateTime?
verifiedAt DateTime?
verifiedBy String?
uploadedBy String?
metadata Json?
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
deletedAt DateTime?
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
@@index([tenantId])
@@index([customerId])
@@index([documentType])
@@index([status])
@@index([expiresAt])
}
Étape 2 — Enum DocumentType
Ajouter
enum CustomerDocumentType {
IDENTITY_CARD
PASSPORT
DRIVING_LICENSE
VISA
RESIDENCE_PERMIT
CONTRACT
INVOICE
PROOF_OF_ADDRESS
INSURANCE
TAX_DOCUMENT
OTHER
}
Étape 3 — Enum DocumentStatus
Ajouter
enum DocumentStatus {
PENDING
VERIFIED
REJECTED
EXPIRED
ARCHIVED
}
Étape 4 — Relation Customer
Ajouter
Dans :
model Customer
documents CustomerDocument[]
Étape 5 — Migration
Générer
npx prisma migrate dev \
--name customer_documents
Générer
npx prisma generate
Sprint 3-D.1-B
Module
Étape 6 — Création
src/modules/customer-documents ├── application │ │ └── dto │ │ ├── upload-customer-document.dto.ts │ └── customer-document-response.dto.ts │ ├── domain │ │ └── services │ │ └── customer-document.service.ts │ ├── presentation │ │ └── controllers │ │ └── customer-document.controller.ts │ └── customer-document.module.ts
Sprint 3-D.1-C
DTOs
Étape 7 — Upload DTO
Créer
upload-customer-document.dto.ts
Ajouter
export class UploadCustomerDocumentDto {
documentType:
CustomerDocumentType;
category?: string;
expiresAt?: Date;
}
Étape 8 — Response DTO
Créer
customer-document-response.dto.ts
Ajouter
export class CustomerDocumentResponseDto {
id: string;
name: string;
documentType: string;
status: string;
mimeType: string;
fileSize: number;
createdAt: Date;
}
Sprint 3-D.1-D
Validation documentaire
Étape 9 — Types autorisés
Créer
shared/constants document-mime-types.ts
Ajouter
export const ALLOWED_DOCUMENT_TYPES = [ 'application/pdf', 'image/jpeg', 'image/png', 'image/webp' ];
Étape 10 — Taille maximale
Ajouter
export const MAX_DOCUMENT_SIZE = 20 * 1024 * 1024;
Étape 11 — Validation
Vérifier
mimetype size
Rejeter
EXE ZIP JS BAT SH
Sprint 3-D.1-E
CustomerDocumentService
Étape 12 — Création
Créer
customer-document.service.ts
Injection
@Injectable()
export class CustomerDocumentService {
constructor(
private readonly prisma:
PrismaService,
private readonly storageService:
StorageService
) {}
}
Étape 13 — Méthodes
Ajouter
findAll() upload() remove() verify() generateDownloadUrl()
Étape 14 — Upload
Chemin
customers/
{customerId}/
documents/
{uuid}
Upload MinIO
const storagePath =
await storageService
.uploadDocument(
file,
customerId
);
Étape 15 — Enregistrement
Créer
await prisma.customerDocument.create({
data: {
tenantId,
customerId,
documentType,
storagePath,
mimeType:
file.mimetype,
fileSize:
file.size,
status:
'PENDING'
}
});
Étape 16 — URL sécurisée
Générer
generateDownloadUrl()
Utiliser
Presigned URL Expiration 1h
Sprint 3-D.1-F
Historisation CRM
Étape 17 — CustomerHistory
Ajouter
DOCUMENT_UPLOADED DOCUMENT_VERIFIED DOCUMENT_DELETED
Exemple
changedField: 'document'
Étape 18 — Audit
Ajouter
Dans :
AuditLog
Événements
CUSTOMER_DOCUMENT_UPLOAD CUSTOMER_DOCUMENT_VERIFY CUSTOMER_DOCUMENT_DELETE
Sprint 3-D.1-G
Contrôleur
Étape 19 — Création
Créer
customer-document.controller.ts
Déclaration
@ApiTags( 'Customer Documents' ) @Controller( 'customers/:id/documents' ) @UseGuards( JwtAuthGuard ) @ApiBearerAuth()
Étape 20 — GET
Route
GET /customers/{id}/documents
Étape 21 — POST
Route
POST /customers/{id}/documents
Upload
@UseInterceptors(
FileInterceptor(
'file'
)
)
Étape 22 — DELETE
Route
DELETE /customers/{id}/documents/{documentId}
Étape 23 — Download
Ajouter
GET /customers/{id}/documents/{documentId}/download
Sprint 3-D.1-H
Vérification documentaire
Étape 24 — Endpoint
Ajouter
PUT /customers/{id}/documents/{documentId}/verify
Action
Status ↓ VERIFIED
Métadonnées
verifiedAt verifiedBy
Étape 25 — Expiration
Vérifier
Passport Visa Insurance
Automatisation future
Créer alertes :
30 jours avant expiration
Sprint 3-D.1-I
Module
Étape 26 — Création
Créer
customer-document.module.ts
Implémentation
@Module({
imports: [
PrismaModule,
AuthModule,
StorageModule
],
controllers: [
CustomerDocumentController
],
providers: [
CustomerDocumentService
],
exports: [
CustomerDocumentService
]
})
export class CustomerDocumentModule {}
Étape 27 — Swagger
Vérifier
GET /customers/{id}/documents
POST /customers/{id}/documents
DELETE /customers/{id}/documents/{documentId}
GET /customers/{id}/documents/{documentId}/download
PUT /customers/{id}/documents/{documentId}/verify
Étape 28 — Exemple
Upload
Passeport.pdf
Résultat
Document stocké MinIO Status=PENDING Historique CRM créé Audit créé
Préparation Sprint 19
Compatible avec :
Consent ComplianceAudit RetentionPolicy DataClassification
Préparation Sprint 13
Compatible avec :
OCR Document AI Extraction automatique Classification automatique
Définition de terminé
Le Sprint 3-D.1 est terminé lorsque :
✓ CustomerDocument créé ✓ Upload opérationnel ✓ MinIO/S3 intégré ✓ Validation documentaire ✓ Vérification documentaire ✓ AuditLog intégré ✓ Historisation CRM ✓ URLs sécurisées ✓ Swagger documenté
Livrables
CustomerDocument CustomerDocumentModule CustomerDocumentController CustomerDocumentService Document Validation MinIO Integration Secure Download URLs
Sprint 3-D.2 — Gestion Documentaire Enterprise
Objectif
Faire évoluer le système documentaire CRM vers une GED Enterprise complète.
À l'issue de cette étape :
✓ Versioning ✓ OCR ✓ Classification automatique ✓ Extraction de données ✓ Expiration automatique ✓ Workflow de validation ✓ Signature électronique ✓ Conformité RGPD ✓ Préparation ISO27001
Architecture cible
Document Upload ↓ OCR Engine ↓ Classification Engine ↓ Extraction Engine ↓ Validation Workflow ↓ Storage ↓ Compliance
Sprint 3-D.2-A
Extension Prisma
Étape 1 — Versioning documentaire
Ajouter dans CustomerDocument
parentDocumentId String?
documentVersion Int
@default(1)
isLatestVersion Boolean
@default(true)
supersededAt DateTime?
Étape 2 — Relation Version
Ajouter
parentDocument CustomerDocument?
@relation(
"DocumentVersions",
fields:[parentDocumentId],
references:[id]
)
versions CustomerDocument[]
@relation(
"DocumentVersions"
)
Étape 3 — OCR
Ajouter
ocrStatus OcrStatus
@default(PENDING)
ocrText String?
ocrExecutedAt DateTime?
Étape 4 — Classification
Ajouter
classificationScore Float? classificationSource String? detectedDocumentType String?
Étape 5 — Extraction
Ajouter
extractedData Json? extractionStatus String?
Étape 6 — Signature
Ajouter
signatureRequired Boolean
@default(false)
signedAt DateTime?
signatureProvider String?
signatureReference String?
Étape 7 — Enum OCR
Ajouter
enum OcrStatus {
PENDING
PROCESSING
COMPLETED
FAILED
}
Étape 8 — Migration
Générer
npx prisma migrate dev \
--name customer_documents_enterprise
Générer
npx prisma generate
Sprint 3-D.2-B
GED Workflow
Étape 9 — Création DocumentWorkflow
Ajouter
model DocumentWorkflow {
id String
@id
@default(uuid())
tenantId String
name String
documentType String
active Boolean
@default(true)
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
steps DocumentWorkflowStep[]
}
Étape 10 — Workflow Steps
Ajouter
model DocumentWorkflowStep {
id String
@id
@default(uuid())
workflowId String
name String
stepOrder Int
validatorRole String?
required Boolean
@default(true)
workflow DocumentWorkflow
@relation(
fields:[workflowId],
references:[id],
onDelete:Cascade
)
@@index([workflowId])
@@index([stepOrder])
}
Étape 11 — Workflow Instance
Ajouter
model CustomerDocumentWorkflow {
id String
@id
@default(uuid())
documentId String
currentStep Int
@default(1)
status WorkflowStatus
@default(PENDING)
startedAt DateTime
@default(now())
completedAt DateTime?
document CustomerDocument
@relation(
fields:[documentId],
references:[id]
)
}
Étape 12 — Enum Workflow
Ajouter
enum WorkflowStatus {
PENDING
IN_PROGRESS
APPROVED
REJECTED
CANCELLED
}
Sprint 3-D.2-C
OCR Module
Étape 13 — Création
src/modules/document-ai
Structure
document-ai ├── domain │ │ └── services │ │ ├── ocr.service.ts │ │ ├── document-classifier.service.ts │ │ ├── extraction.service.ts │ │ └── expiration-monitor.service.ts │ └── document-ai.module.ts
Étape 14 — OCR Service
Méthodes
processDocument() extractText() detectLanguage()
Prévoir
Connecteurs futurs :
Tesseract AWS Textract Google Vision Azure Form Recognizer
Étape 15 — OCR Workflow
Upload ↓ OCR ↓ Classification ↓ Extraction ↓ Validation ↓ Archive
Sprint 3-D.2-D
Classification Automatique
Étape 16 — DocumentClassifier
Méthodes
classify() detectPassport() detectInvoice() detectContract()
Étape 17 — Classification
Exemple
Passeport ↓ IDENTITY_DOCUMENT
Résultat
classificationScore: 0.98
Étape 18 — Mise à jour
Ajouter
detectedDocumentType classificationScore classificationSource
Sprint 3-D.2-E
Extraction de données
Étape 19 — ExtractionService
Méthodes
extractIdentityData() extractInvoiceData() extractContractData()
Étape 20 — Exemple
Passeport
Nom Prénom Nationalité Date expiration Numéro
Sauvegarder
extractedData Json
Étape 21 — Exemple
Facture
Numéro facture Montant Date TVA
Sprint 3-D.2-F
Expiration Automatique
Étape 22 — ExpirationMonitor
Méthodes
checkExpiringDocuments() markExpiredDocuments()
Étape 23 — Workflow
Tous les jours ↓ Expiration < 30 jours ↓ Notification ↓ Alert
Étape 24 — Statut
Mise à jour
EXPIRED
automatiquement.
Sprint 3-D.2-G
Signature Électronique
Étape 25 — Préparation
Ajouter
SignatureProvider
Fournisseurs
DocuSign Yousign Adobe Sign
Étape 26 — Workflow
Document ↓ Signature Request ↓ Signed ↓ Archive
Étape 27 — Endpoints
Ajouter
POST /customers/{id}/documents/{documentId}/sign
GET /customers/{id}/documents/{documentId}/signature
Sprint 3-D.2-H
API GED
Étape 28 — Endpoints
Ajouter
POST /documents/{id}/ocr
POST /documents/{id}/classify
POST /documents/{id}/extract
GET /documents/{id}/workflow
PUT /documents/{id}/approve
PUT /documents/{id}/reject
Étape 29 — Permissions
RBAC
documents.read documents.write documents.verify documents.approve documents.sign
Sprint 3-D.2-I
Audit & Conformité
Étape 30 — AuditLog
Journaliser
DOCUMENT_OCR DOCUMENT_CLASSIFIED DOCUMENT_EXTRACTED DOCUMENT_APPROVED DOCUMENT_REJECTED DOCUMENT_SIGNED DOCUMENT_EXPIRED
Étape 31 — DataClassification
Préparer
Compatible avec :
PII IDENTITY FINANCIAL LEGAL CONFIDENTIAL
Étape 32 — Retention
Préparer
Compatible avec :
RetentionPolicy ComplianceAudit GDPR
Sprint 3-D.2-J
Dashboard GED
Étape 33 — Statistiques
Ajouter
GET /documents/statistics
Retour
{
"totalDocuments": 5234,
"verifiedDocuments": 4987,
"expiredDocuments": 74,
"pendingValidation": 32,
"pendingSignatures": 11
}
Étape 34 — Recherche GED
Ajouter
GET /documents/search
Filtres
Type Statut Date expiration Client OCR Workflow
Préparation Sprint 13
Compatible avec :
KnowledgeDocument Recommendation AI Assistant Document AI
Préparation Sprint 19
Compatible avec :
ComplianceAudit DataClassification RetentionPolicy SecurityIncident
Définition de terminé
Le Sprint 3-D.2 est terminé lorsque :
✓ Versioning ✓ OCR ✓ Classification automatique ✓ Extraction de données ✓ Expiration automatique ✓ Workflow validation ✓ Signature électronique ✓ Audit GED ✓ Conformité préparée
Livrables
DocumentWorkflow DocumentWorkflowStep CustomerDocumentWorkflow OcrService DocumentClassifierService ExtractionService ExpirationMonitorService Enterprise GED API
Sprint 3-E.1 — Gestion des Tags CRM
Objectif
Implémenter un moteur de tags CRM permettant :
Segmentation Classification Automatisation Marketing CRM Analytics Personnalisation
basé sur :
CustomerTag CustomerTagAssignment
Architecture cible
Customer ↓ CustomerTagAssignment ↓ CustomerTag ↓ CRM Segmentation ↓ Campaigns ↓ Automation
Sprint 3-E.1-A
Modèle Prisma
Étape 1 — Création CustomerTag
Ajouter dans schema.prisma
model CustomerTag {
id String
@id
@default(uuid())
tenantId String
name String
code String
description String?
color String?
icon String?
category String?
tagType CustomerTagType
@default(MANUAL)
active Boolean
@default(true)
usageCount Int
@default(0)
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
assignments CustomerTagAssignment[]
@@unique([
tenantId,
code
])
@@index([tenantId])
@@index([tagType])
@@index([active])
}
Étape 2 — Création CustomerTagAssignment
Ajouter
model CustomerTagAssignment {
id String
@id
@default(uuid())
customerId String
tagId String
assignedBy String?
assignedAt DateTime
@default(now())
source String?
@default("MANUAL")
expiresAt DateTime?
metadata Json?
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
tag CustomerTag
@relation(
fields:[tagId],
references:[id],
onDelete:Cascade
)
@@unique([
customerId,
tagId
])
@@index([customerId])
@@index([tagId])
@@index([assignedAt])
}
Étape 3 — Enum TagType
Ajouter
enum CustomerTagType {
MANUAL
DYNAMIC
SYSTEM
MARKETING
LOYALTY
RISK
}
Étape 4 — Relations
Ajouter dans Customer
tags CustomerTagAssignment[]
Étape 5 — Migration
Générer
npx prisma migrate dev \
--name customer_tags
Générer
npx prisma generate
Sprint 3-E.1-B
Module
Étape 6 — Création
src/modules/customer-tags ├── application │ │ └── dto │ │ ├── create-customer-tag.dto.ts │ │ ├── assign-customer-tag.dto.ts │ │ └── customer-tag-response.dto.ts │ ├── domain │ │ └── services │ │ └── customer-tag.service.ts │ ├── presentation │ │ └── controllers │ │ └── customer-tag.controller.ts │ └── customer-tag.module.ts
Sprint 3-E.1-C
DTOs
Étape 7 — CreateCustomerTagDto
Créer
create-customer-tag.dto.ts
Implémentation
export class CreateCustomerTagDto {
name: string;
code: string;
description?: string;
color?: string;
icon?: string;
category?: string;
tagType?: string;
}
Étape 8 — AssignCustomerTagDto
Créer
assign-customer-tag.dto.ts
Implémentation
export class AssignCustomerTagDto {
tagId: string;
expiresAt?: Date;
}
Sprint 3-E.1-D
CustomerTagService
Étape 9 — Méthodes
Ajouter
findTags() createTag() assignTag() removeTag() getCustomerTags() recalculateUsage()
Étape 10 — Création Tag
Vérifier
Code unique par tenant
Création
await prisma.customerTag.create({
data: {
tenantId,
...dto
}
});
Étape 11 — Affectation
Vérifier
Customer Tag Même tenant
Affecter
await prisma.customerTagAssignment.create({
data: {
customerId,
tagId,
assignedBy:
userId
}
});
Étape 12 — Usage Count
Mettre à jour
await prisma.customerTag.update({
where: {
id: tagId
},
data: {
usageCount: {
increment: 1
}
}
});
Étape 13 — Suppression
Supprimer
CustomerTagAssignment
Décrémenter
usageCount
Sprint 3-E.1-E
Tags Dynamiques
Étape 14 — Extension CustomerTag
Ajouter
dynamicRule Json?
Étape 15 — Exemple
VIP
{
"customerScore": {
"gte": 80
}
}
High Revenue
{
"lifetimeValue": {
"gte": 10000
}
}
Étape 16 — Recalcul
Méthode
evaluateDynamicTags()
Déclencheurs
Customer Updated Reservation Created Score Updated
Sprint 3-E.1-F
Tags Système
Étape 17 — Tags par défaut
Seed
VIP FREQUENT CORPORATE HIGH_VALUE INACTIVE BLACKLISTED HIGH_RISK NEWSLETTER LOYALTY
Étape 18 — Attribution automatique
Exemple
Segment = VIP ↓ Tag VIP
Exemple
Risk = HIGH ↓ Tag HIGH_RISK
Sprint 3-E.1-G
Contrôleur
Étape 19 — Création
Créer
customer-tag.controller.ts
Déclaration
@ApiTags('Customer Tags')
@Controller('customers')
Étape 20 — Liste tags
Route
GET /customers/tags
Étape 21 — Création tag
Route
POST /customers/tags
Étape 22 — Affectation
Route
POST /customers/{id}/tags
Étape 23 — Suppression
Route
DELETE /customers/{id}/tags/{tagId}
Étape 24 — Consultation
Ajouter
GET /customers/{id}/tags
Sprint 3-E.1-H
Recherche CRM
Étape 25 — Filtre Tags
Ajouter dans
CustomerQueryDto
Champ
tags?: string[];
Étape 26 — Recherche
Exemple
VIP + NEWSLETTER
Résultat
Clients correspondants
Étape 27 — Segmentation
Exemple
GET /customers/search
tag=VIP
Utilisation
Marketing Campagnes Automatisation
Sprint 3-E.1-I
Audit & Historisation
Étape 28 — CustomerHistory
Journaliser
TAG_ASSIGNED TAG_REMOVED
Étape 29 — AuditLog
Ajouter
CUSTOMER_TAG_CREATED CUSTOMER_TAG_ASSIGNED CUSTOMER_TAG_REMOVED CUSTOMER_DYNAMIC_TAG_UPDATED
Sprint 3-E.1-J
Préparation Sprint 9
Compatible
Campaign CampaignRecipient MarketingSegment MarketingEvent
Préparation Sprint 13
Compatible avec :
AutomationRule Recommendation AiConversation AutomationScenario
Préparation Sprint 20
Compatible avec :
Customer Analytics Predictive Segmentation Lead Scoring AI Recommendations
Définition de terminé
Le Sprint 3-E.1 est terminé lorsque :
✓ CustomerTag créé ✓ CustomerTagAssignment créé ✓ Tags manuels ✓ Tags dynamiques ✓ Segmentation CRM ✓ Recherche par tags ✓ AuditLog intégré ✓ Historisation CRM ✓ Swagger documenté
Livrables
CustomerTag CustomerTagAssignment CustomerTagModule CustomerTagController CustomerTagService Dynamic Tag Engine
Sprint 3-E.2 — Segmentation CRM Avancée & Smart Tags
Objectif
Transformer le moteur de tags CRM en moteur intelligent de segmentation Enterprise.
À l'issue de cette étape :
✓ Tag Rules Engine ✓ Smart Tags IA ✓ Segmentation comportementale ✓ Scoring automatique ✓ Segments prédictifs ✓ Marketing Intelligence ✓ CRM Intelligence Engine
Architecture cible
Customer Data ↓ Behavior Analysis ↓ Scoring Engine ↓ Tag Rules Engine ↓ Smart Segments ↓ Marketing Intelligence ↓ Automation
Sprint 3-E.2-A
Extension Prisma
Étape 1 — Création SmartSegment
Ajouter dans schema.prisma
model SmartSegment {
id String
@id
@default(uuid())
tenantId String
name String
code String
description String?
segmentType SmartSegmentType
active Boolean
@default(true)
ruleDefinition Json
estimatedCustomers Int
@default(0)
lastCalculatedAt DateTime?
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
@@unique([
tenantId,
code
])
@@index([tenantId])
@@index([segmentType])
@@index([active])
}
Étape 2 — Création CustomerScore
Ajouter
model CustomerScore {
id String
@id
@default(uuid())
customerId String
@unique
engagementScore Int
@default(0)
loyaltyScore Int
@default(0)
revenueScore Int
@default(0)
marketingScore Int
@default(0)
riskScore Int
@default(0)
predictiveScore Int
@default(0)
overallScore Int
@default(0)
calculatedAt DateTime
@default(now())
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
}
Étape 3 — Enum SegmentType
Ajouter
enum SmartSegmentType {
BEHAVIORAL
REVENUE
LOYALTY
MARKETING
PREDICTIVE
RISK
AI_GENERATED
}
Étape 4 — Relations
Ajouter dans Customer
score CustomerScore?
Étape 5 — Migration
Générer
npx prisma migrate dev \
--name crm_smart_segments
Générer
npx prisma generate
Sprint 3-E.2-B
Tag Rules Engine
Étape 6 — Création
crm-tag-rules.service.ts
Méthodes
evaluateRules() executeRule() assignTags() removeTags()
Étape 7 — Structure Rule
Exemple
{
"conditions": [
{
"field": "lifetimeValue",
"operator": "gte",
"value": 10000
}
],
"action": {
"tag": "HIGH_VALUE"
}
}
Étape 8 — Opérateurs
eq neq gt gte lt lte contains in notIn
Sprint 3-E.2-C
Scoring Automatique
Étape 9 — Création
customer-scoring.service.ts
Méthodes
calculateOverallScore() calculateEngagement() calculateLoyalty() calculateRevenue() calculateRisk()
Étape 10 — Engagement
Critères
Communications Ouvertures emails Réponses Activité CRM
Score
0 → 100
Étape 11 — Loyalty
Critères
Ancienneté Réservations Lifetime Value VIP
Étape 12 — Revenue
Critères
Total Revenue Average Basket Frequency
Sprint 3-E.2-D
Smart Tags IA
Étape 13 — Création
smart-tag.service.ts
Méthodes
generateSmartTags() predictCustomerCategory() recommendTags()
Étape 14 — Smart Tags
Exemples
HIGH_VALUE FUTURE_VIP AT_RISK LOYAL_CUSTOMER UPSELL_TARGET CHURN_RISK
Étape 15 — Attribution
Exemple
Lifetime Value élevé + Croissance forte ↓ FUTURE_VIP
Sprint 3-E.2-E
Segmentation Comportementale
Étape 16 — BehaviorSegmentService
Créer
behavior-segmentation.service.ts
Segments
Frequent Traveler Weekend Traveler Luxury Traveler Business Traveler Seasonal Traveler Family Traveler
Étape 17 — Analyse
Sources
Reservations Invoices Communications Preferences
Étape 18 — Exemple
80% réservations Vendredi → Dimanche ↓ Weekend Traveler
Sprint 3-E.2-F
Segments Prédictifs
Étape 19 — PredictiveSegmentation
Créer
predictive-segmentation.service.ts
Segments
Future VIP Future Churn Future Corporate Future High Revenue Future Ambassador
Étape 20 — Prévision
Critères
Croissance dépenses Fréquence réservations Engagement Satisfaction
Étape 21 — Exemple
Croissance 30% ↓ Future VIP
Sprint 3-E.2-G
Marketing Intelligence
Étape 22 — Création
marketing-intelligence.service.ts
Méthodes
findCampaignTargets() findUpsellTargets() findRetentionTargets() findReferralCandidates()
Étape 23 — Exemples
Upsell
VIP + Revenue > 5000 ↓ Campagne Premium
Rétention
CHURN_RISK ↓ Campagne Réactivation
Sprint 3-E.2-H
API CRM Intelligence
Étape 24 — Endpoints
Ajouter
GET /customers/segments/smart GET /customers/tags/smart GET /customers/scoring POST /customers/scoring/recalculate POST /customers/segments/recalculate
Étape 25 — Exemple
Réponse
{
"customerId":"123",
"overallScore":87,
"smartTags":[
"VIP",
"LOYAL_CUSTOMER",
"UPSELL_TARGET"
]
}
Sprint 3-E.2-I
Dashboard CRM Intelligence
Étape 26 — KPI
Ajouter
GET /customers/intelligence/dashboard
Retour
{
"futureVip":54,
"churnRisk":23,
"upsellTargets":118,
"loyalCustomers":401
}
Étape 27 — Visualisation
Répartition
Segments Scores Tags Prévisions
Sprint 3-E.2-J
Audit & Automatisation
Étape 28 — AuditLog
Journaliser
SMART_TAG_ASSIGNED SEGMENT_RECALCULATED CUSTOMER_SCORE_UPDATED PREDICTIVE_SEGMENT_ASSIGNED
Étape 29 — Automatisation
Déclencheurs
Reservation Created Invoice Paid Customer Updated Campaign Opened
Actions
Recalculate Scores Recalculate Tags Recalculate Segments
Préparation Sprint 9
Compatible avec :
Campaign CampaignRecipient MarketingSegment MarketingEvent
Préparation Sprint 13
Compatible avec :
Recommendation AutomationRule AutomationScenario AiConversation
Préparation Sprint 20
Compatible avec :
Enterprise Analytics Customer Intelligence Predictive CRM AI Recommendations
Définition de terminé
Le Sprint 3-E.2 est terminé lorsque :
✓ SmartSegment créé ✓ CustomerScore créé ✓ Tag Rules Engine ✓ Smart Tags ✓ Segmentation comportementale ✓ Segments prédictifs ✓ Marketing Intelligence ✓ Dashboard CRM Intelligence ✓ Audit intégré
Livrables
SmartSegment CustomerScore CustomerScoringService SmartTagService BehaviorSegmentationService PredictiveSegmentationService MarketingIntelligenceService CRM Intelligence API
Sprint 3-F.1 — Gestion des Notes CRM
Objectif
Implémenter le système de notes CRM permettant aux équipes :
Commerciales Support Réservations Finance Marketing Administration
de collaborer autour d'un client.
À l'issue de cette étape :
✓ Notes privées ✓ Notes publiques ✓ Historique CRM ✓ Mentions utilisateurs ✓ Audit ✓ Recherche ✓ Timeline CRM
Architecture cible
Customer ↓ CustomerNote ↓ Mentions ↓ Timeline CRM ↓ Audit ↓ Collaboration
Sprint 3-F.1-A
Modèle Prisma
Étape 1 — Création CustomerNote
Ajouter dans schema.prisma
model CustomerNote {
id String
@id
@default(uuid())
tenantId String
customerId String
authorId String
title String?
content String
visibility NoteVisibility
@default(PRIVATE)
noteType CustomerNoteType
@default(GENERAL)
pinned Boolean
@default(false)
edited Boolean
@default(false)
editedAt DateTime?
metadata Json?
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
deletedAt DateTime?
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
author User
@relation(
fields:[authorId],
references:[id]
)
mentions CustomerNoteMention[]
@@index([tenantId])
@@index([customerId])
@@index([authorId])
@@index([visibility])
@@index([createdAt])
}
Étape 2 — Création CustomerNoteMention
Ajouter
model CustomerNoteMention {
id String
@id
@default(uuid())
noteId String
userId String
readAt DateTime?
createdAt DateTime
@default(now())
note CustomerNote
@relation(
fields:[noteId],
references:[id],
onDelete:Cascade
)
user User
@relation(
fields:[userId],
references:[id]
)
@@unique([
noteId,
userId
])
@@index([userId])
@@index([noteId])
}
Étape 3 — Enum Visibility
Ajouter
enum NoteVisibility {
PRIVATE
INTERNAL
PUBLIC
}
Étape 4 — Enum Type
Ajouter
enum CustomerNoteType {
GENERAL
SALES
SUPPORT
FINANCE
MARKETING
RESERVATION
VIP
RISK
}
Étape 5 — Relation Customer
Ajouter
Dans :
model Customer
notes CustomerNote[]
Étape 6 — Migration
Générer
npx prisma migrate dev \
--name customer_notes
Générer
npx prisma generate
Sprint 3-F.1-B
Module
Étape 7 — Création
src/modules/customer-notes ├── application │ │ └── dto │ │ ├── create-customer-note.dto.ts │ │ ├── update-customer-note.dto.ts │ │ └── customer-note-response.dto.ts │ ├── domain │ │ └── services │ │ └── customer-note.service.ts │ ├── presentation │ │ └── controllers │ │ └── customer-note.controller.ts │ └── customer-note.module.ts
Sprint 3-F.1-C
DTOs
Étape 8 — CreateCustomerNoteDto
Créer
create-customer-note.dto.ts
Implémentation
export class CreateCustomerNoteDto {
title?: string;
content: string;
visibility?: string;
noteType?: string;
pinned?: boolean;
mentions?: string[];
}
Étape 9 — UpdateCustomerNoteDto
Créer
update-customer-note.dto.ts
Implémentation
export class UpdateCustomerNoteDto
extends PartialType(
CreateCustomerNoteDto
) {}
Sprint 3-F.1-D
CustomerNoteService
Étape 10 — Méthodes
Ajouter
findAll() findOne() create() update() remove() createMentions()
Étape 11 — Liste
Trier
Pinned ↓ Date création DESC
Prisma
orderBy: [
{
pinned: 'desc'
},
{
createdAt: 'desc'
}
]
Étape 12 — Création
Vérifier
Customer Tenant
Créer
const note =
await prisma.customerNote.create({
data: {
tenantId,
customerId,
authorId,
...dto
}
});
Étape 13 — Mentions
Exemple
@john @support @manager
Créer
await prisma.customerNoteMention.createMany({
data: [...]
});
Étape 14 — Notifications
Déclencher
IN_APP EMAIL
pour les utilisateurs mentionnés.
Sprint 3-F.1-E
Notes privées
Étape 15 — Visibilité
PRIVATE
Auteur uniquement
INTERNAL
Employés du tenant
PUBLIC
Visible dans CRM global
Étape 16 — Filtrage
Vérifier
Avant lecture :
Visibility Tenant Permissions
Sprint 3-F.1-F
Modification
Étape 17 — Update
Ajouter
edited = true editedAt = new Date()
Étape 18 — Historique
Journaliser
Dans :
CustomerHistory
Événements
NOTE_CREATED NOTE_UPDATED NOTE_DELETED
Étape 19 — Soft Delete
Supprimer
deletedAt: new Date()
Sprint 3-F.1-G
Recherche CRM
Étape 20 — Recherche
Ajouter
GET /customers/{id}/notes
Paramètres
noteType visibility author search
Étape 21 — Recherche texte
Champs
title content
Prisma
contains: search
Sprint 3-F.1-H
Contrôleur
Étape 22 — Création
Créer
customer-note.controller.ts
Déclaration
@ApiTags( 'Customer Notes' ) @Controller( 'customers/:id/notes' ) @UseGuards( JwtAuthGuard ) @ApiBearerAuth()
Étape 23 — Endpoints
Ajouter
GET /customers/{id}/notes
POST /customers/{id}/notes
PUT /customers/{id}/notes/{noteId}
DELETE /customers/{id}/notes/{noteId}
Étape 24 — Mentions
Ajouter
GET /notes/mentions
Retour
Mes mentions
Sprint 3-F.1-I
Timeline CRM
Étape 25 — Préparation
Les notes alimentent :
Customer Timeline
future.
Événements
Notes Documents Tags Communications Réservations
Étape 26 — Notes épinglées
Utilisation
VIP Risques Informations critiques
Sprint 3-F.1-J
Audit & Sécurité
Étape 27 — AuditLog
Journaliser
CUSTOMER_NOTE_CREATED CUSTOMER_NOTE_UPDATED CUSTOMER_NOTE_DELETED CUSTOMER_NOTE_PINNED CUSTOMER_MENTION_CREATED
Étape 28 — Permissions
Ajouter
customer.notes.read customer.notes.write customer.notes.delete customer.notes.manage
Préparation Sprint 9
Compatible avec :
CustomerCommunication Campaign MarketingEvent
Préparation Sprint 13
Compatible avec :
AiConversation Recommendation KnowledgeDocument
Définition de terminé
Le Sprint 3-F.1 est terminé lorsque :
✓ CustomerNote créé ✓ CustomerNoteMention créé ✓ Notes privées ✓ Notes publiques ✓ Mentions utilisateurs ✓ Historisation CRM ✓ AuditLog intégré ✓ Recherche notes ✓ Swagger documenté
Livrables
CustomerNote CustomerNoteMention CustomerNoteModule CustomerNoteController CustomerNoteService CRM Notes API
Sprint 3-F.2 — Collaboration CRM Enterprise
Objectif
Transformer le système de notes CRM en véritable plateforme collaborative Enterprise.
À l'issue de cette étape :
✓ Threads ✓ Réponses aux notes ✓ Réactions ✓ Tâches liées ✓ Assignation ✓ Notifications temps réel ✓ Timeline CRM unifiée ✓ Collaboration multi-équipes
Architecture cible
Customer ↓ CRM Timeline ↓ Notes ↓ Threads ↓ Tasks ↓ Mentions ↓ Notifications ↓ Collaboration Hub
Sprint 3-F.2-A
Extension Prisma
Étape 1 — Support des Threads
Ajouter dans CustomerNote
parentNoteId String?
threadRootId String?
replyCount Int
@default(0)
Étape 2 — Relations
Ajouter
parentNote CustomerNote?
@relation(
"CustomerNoteThread",
fields:[parentNoteId],
references:[id]
)
replies CustomerNote[]
@relation(
"CustomerNoteThread"
)
Étape 3 — Réactions
Créer
model CustomerNoteReaction {
id String
@id
@default(uuid())
noteId String
userId String
reaction String
createdAt DateTime
@default(now())
note CustomerNote
@relation(
fields:[noteId],
references:[id],
onDelete:Cascade
)
user User
@relation(
fields:[userId],
references:[id]
)
@@unique([
noteId,
userId,
reaction
])
@@index([noteId])
@@index([userId])
}
Étape 4 — Tâches CRM
Créer
model CustomerTask {
id String
@id
@default(uuid())
tenantId String
customerId String
noteId String?
assignedToId String?
createdById String
title String
description String?
priority TaskPriority
status TaskStatus
dueDate DateTime?
completedAt DateTime?
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
customer Customer
@relation(
fields:[customerId],
references:[id]
)
@@index([tenantId])
@@index([customerId])
@@index([assignedToId])
@@index([status])
}
Étape 5 — Enums
Ajouter
enum TaskPriority {
LOW
MEDIUM
HIGH
CRITICAL
}
enum TaskStatus {
OPEN
IN_PROGRESS
COMPLETED
CANCELLED
}
Étape 6 — Migration
Générer
npx prisma migrate dev \
--name crm_collaboration
Générer
npx prisma generate
Sprint 3-F.2-B
Threads CRM
Étape 7 — Réponses
Ajouter
Dans :
CustomerNoteService
Méthode
replyToNote()
Workflow
Note ↓ Réponse ↓ Thread ↓ Timeline
Étape 8 — Exemple
Client VIP ↓ Note commerciale ↓ Réponse finance ↓ Réponse support
Résultat
Conversation CRM unifiée
Étape 9 — Lecture Thread
Endpoint
GET /customers/{id}/notes/{noteId}/thread
Retour
Arborescence complète
Sprint 3-F.2-C
Réactions
Étape 10 — Réactions supportées
LIKE IMPORTANT FOLLOW_UP DONE WARNING
Étape 11 — Service
Ajouter
addReaction() removeReaction() listReactions()
Étape 12 — Endpoint
Ajouter
POST /notes/{noteId}/reactions
DELETE /notes/{noteId}/reactions
Sprint 3-F.2-D
Assignation CRM
Étape 13 — Assignation
Ajouter dans CustomerNote
assignedToId String?
Relation
assignedTo User?
Étape 14 — Endpoint
Ajouter
PUT /notes/{noteId}/assign
Exemple
Client réclame facture ↓ Assigné Finance
Étape 15 — Notification
Déclencher
Notification Email In-App
Sprint 3-F.2-E
Tâches CRM
Étape 16 — CustomerTaskService
Créer
customer-task.service.ts
Méthodes
createTask() assignTask() completeTask() cancelTask()
Étape 17 — Endpoints
Ajouter
GET /customers/{id}/tasks
POST /customers/{id}/tasks
PUT /customers/{id}/tasks/{taskId}
DELETE /customers/{id}/tasks/{taskId}
Étape 18 — Exemple
Rappeler client ↓ Assigner commercial ↓ Date limite
Sprint 3-F.2-F
Notifications Temps Réel
Étape 19 — WebSocket
Réutiliser
Infrastructure :
Notification Gateway
prévue en Sprint 9.
Étape 20 — Événements
NOTE_CREATED NOTE_REPLY NOTE_MENTION NOTE_ASSIGNED TASK_CREATED TASK_COMPLETED
Étape 21 — Canal
tenant:{tenantId}
crm:{customerId}
Sprint 3-F.2-G
Timeline CRM Unifiée
Étape 22 — Création
crm-timeline.service.ts
Sources
CustomerNote CustomerDocument CustomerTag CustomerTask Reservation Invoice Communication
Étape 23 — Timeline
Endpoint
GET /customers/{id}/timeline
Exemple
[
{
"type":"NOTE",
"date":"2026-01-01"
},
{
"type":"TASK",
"date":"2026-01-03"
},
{
"type":"DOCUMENT",
"date":"2026-01-05"
}
]
Étape 24 — Filtres
Notes Documents Tâches Tags Réservations Factures
Sprint 3-F.2-H
Collaboration Dashboard
Étape 25 — Endpoint
Ajouter
GET /crm/collaboration/dashboard
KPI
Notes ouvertes Tâches ouvertes Mentions non lues Assignations Threads actifs
Étape 26 — Exemple
{
"openTasks":42,
"activeThreads":17,
"unreadMentions":9
}
Sprint 3-F.2-I
Audit & Historisation
Étape 27 — CustomerHistory
Journaliser
NOTE_REPLIED NOTE_ASSIGNED TASK_CREATED TASK_COMPLETED
Étape 28 — AuditLog
Ajouter
CRM_THREAD_CREATED CRM_NOTE_REACTION CRM_TASK_CREATED CRM_TASK_ASSIGNED CRM_TASK_COMPLETED
Sprint 3-F.2-J
Préparation Sprint 9
Compatible
Campaign MarketingEvent NotificationCenter Realtime Communication
Préparation Sprint 13
Compatible avec :
AiConversation Recommendation AutomationScenario KnowledgeDocument
Préparation Sprint 20
Compatible avec :
Enterprise CRM Collaboration Analytics Customer Intelligence Unified Timeline
Définition de terminé
Le Sprint 3-F.2 est terminé lorsque :
✓ Threads CRM ✓ Réponses aux notes ✓ Réactions ✓ Assignation ✓ Tâches CRM ✓ Notifications temps réel ✓ Timeline unifiée ✓ Dashboard collaboration ✓ Audit intégré
Livrables
CustomerNoteReaction CustomerTask CustomerTaskService CrmTimelineService CRM Collaboration API Unified CRM Timeline Realtime CRM Events
Sprint 3-G.1 — Gestion des Communications Client
Objectif
Implémenter la couche CRM Communication centralisée permettant de tracer toutes les interactions client.
À l'issue de cette étape :
✓ Emails ✓ SMS ✓ Appels ✓ Historique communications ✓ Timeline CRM ✓ Audit ✓ Statistiques ✓ Préparation Marketing
Architecture cible
Customer ↓ CustomerCommunication ↓ Email SMS Calls ↓ Timeline CRM ↓ Analytics ↓ Marketing
Sprint 3-G.1-A
Modèle Prisma
Étape 1 — Création CustomerCommunication
Ajouter dans schema.prisma
model CustomerCommunication {
id String
@id
@default(uuid())
tenantId String
customerId String
userId String?
communicationType CommunicationType
direction CommunicationDirection
status CommunicationStatus
subject String?
content String?
externalReference String?
provider String?
sender String?
recipient String?
durationSeconds Int?
scheduledAt DateTime?
sentAt DateTime?
deliveredAt DateTime?
openedAt DateTime?
repliedAt DateTime?
metadata Json?
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
deletedAt DateTime?
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
user User?
@relation(
fields:[userId],
references:[id]
)
@@index([tenantId])
@@index([customerId])
@@index([communicationType])
@@index([status])
@@index([createdAt])
}
Étape 2 — CommunicationType
Ajouter
enum CommunicationType {
EMAIL
SMS
PHONE_CALL
WHATSAPP
PUSH_NOTIFICATION
LETTER
INTERNAL_NOTE
}
Étape 3 — Direction
Ajouter
enum CommunicationDirection {
INBOUND
OUTBOUND
}
Étape 4 — Status
Ajouter
enum CommunicationStatus {
DRAFT
SCHEDULED
SENT
DELIVERED
OPENED
REPLIED
FAILED
CANCELLED
}
Étape 5 — Relation Customer
Ajouter
Dans :
model Customer
communications CustomerCommunication[]
Étape 6 — Migration
Générer
npx prisma migrate dev \
--name customer_communications
Générer
npx prisma generate
Sprint 3-G.1-B
Module
Étape 7 — Création
src/modules/customer-communications ├── application │ │ └── dto │ │ ├── create-customer-communication.dto.ts │ │ ├── communication-query.dto.ts │ │ └── communication-response.dto.ts │ ├── domain │ │ └── services │ │ └── customer-communication.service.ts │ ├── presentation │ │ └── controllers │ │ └── customer-communication.controller.ts │ └── customer-communication.module.ts
Sprint 3-G.1-C
DTOs
Étape 8 — Create DTO
Créer
create-customer-communication.dto.ts
Implémentation
export class CreateCustomerCommunicationDto {
communicationType: string;
direction: string;
subject?: string;
content?: string;
recipient?: string;
sender?: string;
scheduledAt?: Date;
}
Étape 9 — Query DTO
Ajouter
export class CommunicationQueryDto {
communicationType?: string;
status?: string;
direction?: string;
page?: number = 1;
limit?: number = 25;
}
Sprint 3-G.1-D
CustomerCommunicationService
Étape 10 — Création
Créer
customer-communication.service.ts
Méthodes
findAll() findTimeline() create() markDelivered() markOpened() markReplied()
Étape 11 — Création
Exemple
await prisma.customerCommunication.create({
data: {
tenantId,
customerId,
userId,
...dto
}
});
Étape 12 — Historisation
Ajouter
Dans :
CustomerHistory
Événements
COMMUNICATION_CREATED EMAIL_SENT SMS_SENT CALL_LOGGED
Sprint 3-G.1-E
Emails
Étape 13 — Intégration
Préparer
EmailService
Fournisseurs
SMTP SendGrid Mailgun AWS SES
Étape 14 — Workflow
CRM ↓ Email ↓ Send ↓ Tracking ↓ Timeline
Étape 15 — Tracking
Stocker
sentAt deliveredAt openedAt repliedAt
Sprint 3-G.1-F
SMS
Étape 16 — Intégration
Préparer
SmsService
Fournisseurs
Twilio OVH SMS MessageBird
Étape 17 — Tracking
Stocker
Sent Delivered Failed
Sprint 3-G.1-G
Appels
Étape 18 — Journalisation
Ajouter
PHONE_CALL
Métadonnées
Duration Agent Outcome Recording
Étape 19 — Exemple
{
"communicationType":"PHONE_CALL",
"durationSeconds":420
}
Sprint 3-G.1-H
Timeline CRM
Étape 20 — Endpoint
Ajouter
GET /customers/{id}/communications/timeline
Retour
Communications + Notes + Documents + Tags
Étape 21 — Vue unifiée
Exemple
[
{
"type":"EMAIL",
"date":"2026-01-01"
},
{
"type":"SMS",
"date":"2026-01-02"
},
{
"type":"CALL",
"date":"2026-01-03"
}
]
Sprint 3-G.1-I
Contrôleur
Étape 22 — Création
Créer
customer-communication.controller.ts
Déclaration
@ApiTags( 'Customer Communications' ) @Controller( 'customers/:id/communications' ) @UseGuards( JwtAuthGuard )
Étape 23 — Endpoints
Ajouter
GET /customers/{id}/communications
POST /customers/{id}/communications
GET /customers/{id}/communications/timeline
Étape 24 — Recherche
Ajouter
Filtres :
Type Statut Direction Période
Sprint 3-G.1-J
Audit & Analytics
Étape 25 — AuditLog
Journaliser
COMMUNICATION_CREATED EMAIL_DELIVERED EMAIL_OPENED SMS_DELIVERED CALL_CREATED
Étape 26 — KPI
Endpoint
GET /customers/{id}/communications/statistics
Retour
{
"emails":124,
"sms":31,
"calls":14,
"openRate":67,
"replyRate":19
}
Étape 27 — Permissions
Ajouter
communications.read communications.write communications.send communications.manage
Préparation Sprint 9
Compatible avec :
Campaign EmailCampaign SmsCampaign NotificationCenter RealtimeMessaging
Préparation Sprint 13
Compatible avec :
AiConversation Recommendation AutomationScenario KnowledgeBase
Préparation Sprint 20
Compatible avec :
Customer Intelligence Communication Analytics Engagement Scoring Predictive CRM
Définition de terminé
Le Sprint 3-G.1 est terminé lorsque :
✓ CustomerCommunication créé ✓ Emails tracés ✓ SMS tracés ✓ Appels tracés ✓ Historique complet ✓ Timeline CRM ✓ AuditLog intégré ✓ Statistiques CRM ✓ Swagger documenté
Livrables
CustomerCommunication CustomerCommunicationModule CustomerCommunicationController CustomerCommunicationService Communication Timeline Communication Analytics
Étape suivante
Sprint 3-G.2 — Communication Intelligence & Omnicanal
Objectif
Faire évoluer le module CRM Communication vers une plateforme omnicanale Enterprise.
À l'issue de cette étape :
✓ WhatsApp ✓ Messagerie instantanée ✓ Templates ✓ Campagnes ✓ Analyse de sentiment ✓ IA conversationnelle ✓ Centre omnicanal ✓ Communication Intelligence
Architecture cible
Customer ↓ Omnichannel Hub ├── Email ├── SMS ├── WhatsApp ├── Chat ├── Push ├── Voice │ ↓ AI Intelligence ↓ Campaigns ↓ Analytics
Sprint 3-G.2-A
Extension Prisma
Étape 1 — CommunicationTemplate
Ajouter dans schema.prisma
model CommunicationTemplate {
id String
@id
@default(uuid())
tenantId String
name String
code String
channel CommunicationChannel
subject String?
content String
variables Json?
active Boolean
@default(true)
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
@@unique([
tenantId,
code
])
@@index([tenantId])
@@index([channel])
}
Étape 2 — OmnichannelConversation
Ajouter
model OmnichannelConversation {
id String
@id
@default(uuid())
tenantId String
customerId String
channel CommunicationChannel
status ConversationStatus
subject String?
startedAt DateTime
@default(now())
lastMessageAt DateTime?
closedAt DateTime?
assignedToId String?
sentimentScore Float?
aiSummary String?
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
customer Customer
@relation(
fields:[customerId],
references:[id]
)
@@index([tenantId])
@@index([customerId])
@@index([channel])
@@index([status])
}
Étape 3 — ConversationMessage
Ajouter
model ConversationMessage {
id String
@id
@default(uuid())
conversationId String
direction CommunicationDirection
messageType String
content String?
externalReference String?
sentAt DateTime
@default(now())
metadata Json?
conversation OmnichannelConversation
@relation(
fields:[conversationId],
references:[id],
onDelete:Cascade
)
@@index([conversationId])
@@index([sentAt])
}
Étape 4 — Enums
Ajouter
enum CommunicationChannel {
EMAIL
SMS
WHATSAPP
CHAT
PUSH
VOICE
}
enum ConversationStatus {
OPEN
ASSIGNED
WAITING_CUSTOMER
CLOSED
}
Étape 5 — Migration
Générer
npx prisma migrate dev \
--name omnichannel_communications
Sprint 3-G.2-B
Omnichannel Module
Étape 6 — Création
src/modules/omnichannel
Structure
omnichannel ├── templates │ ├── conversations │ ├── whatsapp │ ├── chat │ ├── ai │ └── analytics
Sprint 3-G.2-C
WhatsApp Business
Étape 7 — WhatsApp Service
Créer
whatsapp.service.ts
Méthodes
sendMessage() sendTemplate() receiveWebhook() markDelivered()
Étape 8 — Modèles WhatsApp
Exemples
Booking Confirmation Payment Reminder Welcome Message Review Request Check-In Reminder
Étape 9 — Endpoints
Ajouter
POST /communications/whatsapp/send POST /communications/whatsapp/template POST /communications/whatsapp/webhook
Sprint 3-G.2-D
Messagerie Instantanée
Étape 10 — Chat Service
Créer
chat.service.ts
Méthodes
startConversation() sendMessage() closeConversation() assignConversation()
Étape 11 — Temps réel
Utiliser
WebSocket Gateway
Événements
CHAT_MESSAGE CHAT_TYPING CHAT_ASSIGNED CHAT_CLOSED
Étape 12 — Endpoints
GET /conversations
GET /conversations/{id}
POST /conversations/{id}/messages
PUT /conversations/{id}/assign
Sprint 3-G.2-E
Templates Enterprise
Étape 13 — Template Service
Créer
communication-template.service.ts
Variables
{{customerName}}
{{reservationNumber}}
{{propertyName}}
{{checkInDate}}
{{amount}}
Étape 14 — Rendu
Méthode
renderTemplate()
Étape 15 — Endpoints
GET /communication-templates
POST /communication-templates
PUT /communication-templates/{id}
DELETE /communication-templates/{id}
Sprint 3-G.2-F
Campagnes CRM
Étape 16 — CampaignCommunication
Ajouter
model CampaignCommunication {
id String
@id
@default(uuid())
tenantId String
name String
channel CommunicationChannel
templateId String?
targetSegment String?
status String
scheduledAt DateTime?
sentAt DateTime?
recipientsCount Int
@default(0)
createdAt DateTime
@default(now())
@@index([tenantId])
@@index([status])
}
Étape 17 — Campagnes
Types
Newsletter Promotion Loyalty Upsell Cross-sell Retention
Étape 18 — Endpoints
GET /campaigns
POST /campaigns
POST /campaigns/{id}/send
Sprint 3-G.2-G
Analyse de Sentiment
Étape 19 — Extension Conversation
Utiliser
sentimentScore Float? aiSummary String?
Étape 20 — Sentiment
Service
sentiment-analysis.service.ts
Résultat
NEGATIVE NEUTRAL POSITIVE
Étape 21 — Exemple
"Très satisfait" ↓ POSITIVE ↓ 0.92
Sprint 3-G.2-H
IA Conversationnelle
Étape 22 — AI Conversation Service
Créer
conversation-ai.service.ts
Capacités
Résumé automatique Détection intention Suggestions réponses Priorisation
Étape 23 — Suggestions
Exemple
Client demande remboursement ↓ Intent: REFUND_REQUEST ↓ Réponse suggérée
Étape 24 — Résumé
Générer
aiSummary
à la fermeture d'une conversation.
Sprint 3-G.2-I
Centre Omnicanal
Étape 25 — Dashboard
Endpoint
GET /omnichannel/dashboard
KPI
Conversations ouvertes Temps réponse moyen Messages aujourd'hui Sentiment moyen Campagnes actives
Étape 26 — Vue Agent
Endpoint
GET /omnichannel/inbox
Regroupe
Email SMS WhatsApp Chat
Sprint 3-G.2-J
Audit & Intelligence
Étape 27 — AuditLog
Ajouter
WHATSAPP_SENT CHAT_STARTED CHAT_ASSIGNED CAMPAIGN_CREATED CAMPAIGN_SENT SENTIMENT_ANALYZED AI_RESPONSE_GENERATED
Étape 28 — Permissions
Ajouter
communications.campaigns communications.templates communications.omnichannel communications.ai
Préparation Sprint 9
Compatible avec :
NotificationCenter RealtimeMessaging CampaignEngine CommunicationHub
Préparation Sprint 13
Compatible avec :
AiConversation AiMessage Recommendation AutomationScenario
Préparation Sprint 20
Compatible avec :
Enterprise Analytics Communication Intelligence Customer Intelligence Revenue Intelligence
Définition de terminé
Le Sprint 3-G.2 est terminé lorsque :
✓ WhatsApp intégré ✓ Messagerie instantanée ✓ Templates ✓ Campagnes CRM ✓ Analyse de sentiment ✓ IA conversationnelle ✓ Centre omnicanal ✓ Dashboard omnicanal ✓ Audit intégré
Livrables
CommunicationTemplate OmnichannelConversation ConversationMessage WhatsAppService ChatService ConversationAIService SentimentAnalysisService Omnichannel Dashboard
Sprint 3-H.1 — Gestion des Préférences Client
Objectif
Implémenter la gestion centralisée des préférences client permettant :
Personnalisation Marketing Communication Fidélisation Consentements Expérience client
À l'issue de cette étape :
✓ Préférences marketing ✓ Canaux préférés ✓ Consentements ✓ Préférences linguistiques ✓ Préférences monétaires ✓ Personnalisation CRM ✓ Conformité RGPD
Architecture cible
Customer ↓ CustomerPreference ├── Marketing ├── Communication ├── Language ├── Currency ├── Timezone ├── Loyalty └── GDPR ↓ CRM ↓ Marketing Automation
Sprint 3-H.1-A
Extension Prisma
Étape 1 — Enrichissement CustomerPreference
Ajouter
model CustomerPreference {
id String
@id
@default(uuid())
customerId String
@unique
preferredLanguage String?
preferredCurrency String?
preferredTimezone String?
preferredChannel PreferredChannel?
preferredContactTime String?
prefersEmail Boolean
@default(true)
prefersSms Boolean
@default(false)
prefersPhone Boolean
@default(false)
prefersWhatsApp Boolean
@default(false)
acceptsMarketing Boolean
@default(false)
acceptsNewsletter Boolean
@default(false)
acceptsPromotions Boolean
@default(false)
acceptsSurveys Boolean
@default(false)
acceptsRecommendations Boolean
@default(false)
loyaltyEligible Boolean
@default(true)
vipProgramEligible Boolean
@default(false)
communicationFrequency CommunicationFrequency?
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
}
Étape 2 — PreferredChannel
Ajouter
enum PreferredChannel {
EMAIL
SMS
PHONE
WHATSAPP
PUSH
}
Étape 3 — CommunicationFrequency
Ajouter
enum CommunicationFrequency {
IMMEDIATE
DAILY
WEEKLY
MONTHLY
NEVER
}
Étape 4 — Consentement RGPD
Ajouter
marketingConsentAt DateTime? newsletterConsentAt DateTime? privacyAcceptedAt DateTime? consentVersion String? consentIpAddress String?
Étape 5 — Migration
Générer
npx prisma migrate dev \
--name customer_preferences_enterprise
Générer
npx prisma generate
Sprint 3-H.1-B
Module
Étape 6 — Création
src/modules/customer-preferences ├── application │ │ └── dto │ │ ├── update-customer-preference.dto.ts │ │ └── customer-preference-response.dto.ts │ ├── domain │ │ └── services │ │ └── customer-preference.service.ts │ ├── presentation │ │ └── controllers │ │ └── customer-preference.controller.ts │ └── customer-preference.module.ts
Sprint 3-H.1-C
DTOs
Étape 7 — Update DTO
Créer
update-customer-preference.dto.ts
Implémentation
export class UpdateCustomerPreferenceDto {
preferredLanguage?: string;
preferredCurrency?: string;
preferredTimezone?: string;
preferredChannel?: string;
preferredContactTime?: string;
prefersEmail?: boolean;
prefersSms?: boolean;
prefersPhone?: boolean;
prefersWhatsApp?: boolean;
acceptsMarketing?: boolean;
acceptsNewsletter?: boolean;
acceptsPromotions?: boolean;
acceptsSurveys?: boolean;
acceptsRecommendations?: boolean;
communicationFrequency?: string;
}
Étape 8 — Response DTO
Créer
customer-preference-response.dto.ts
Ajouter
export class CustomerPreferenceResponseDto {
preferredLanguage: string;
preferredCurrency: string;
preferredChannel: string;
acceptsMarketing: boolean;
acceptsNewsletter: boolean;
communicationFrequency: string;
}
Sprint 3-H.1-D
CustomerPreferenceService
Étape 9 — Création
Créer
customer-preference.service.ts
Méthodes
findPreferences() updatePreferences() validatePreferences() recordConsent()
Étape 10 — Lecture
Vérifier
Customer Tenant
avant toute lecture.
Retour
CustomerPreference
Étape 11 — Mise à jour
Exemple
await prisma.customerPreference.update({
where: {
customerId
},
data: {
...dto
}
});
Étape 12 — Consentements
Si
acceptsMarketing=true
Ajouter
marketingConsentAt: new Date()
Si
acceptsNewsletter=true
Ajouter
newsletterConsentAt: new Date()
Sprint 3-H.1-E
Validation
Étape 13 — Langues
Vérifier
Contre :
SupportedLanguages
Étape 14 — Devises
Vérifier
Contre :
SupportedCurrencies
Étape 15 — Fuseaux horaires
Vérifier
Contre :
IANA Timezones
Étape 16 — Cohérence
Exemple
PreferredChannel=SMS ↓ Téléphone requis
Sinon
throw new BadRequestException()
Sprint 3-H.1-F
Personnalisation CRM
Étape 17 — Utilisation
Les préférences alimentent :
Marketing Communication Campagnes Recommandations Automatisation
Étape 18 — Exemples
Langue = FR ↓ Templates FR
Canal = WhatsApp ↓ Communication WhatsApp
Fréquence = Weekly ↓ Digest hebdomadaire
Sprint 3-H.1-G
Contrôleur
Étape 19 — Création
Créer
customer-preference.controller.ts
Déclaration
@ApiTags( 'Customer Preferences' ) @Controller( 'customers/:id/preferences' ) @UseGuards( JwtAuthGuard ) @ApiBearerAuth()
Étape 20 — GET
Route
GET /customers/{id}/preferences
Étape 21 — PUT
Route
PUT /customers/{id}/preferences
Sprint 3-H.1-H
Historisation CRM
Étape 22 — CustomerHistory
Journaliser
PREFERENCES_UPDATED MARKETING_CONSENT_UPDATED COMMUNICATION_CHANNEL_CHANGED
Étape 23 — AuditLog
Ajouter
CUSTOMER_PREFERENCES_UPDATED CUSTOMER_CONSENT_GRANTED CUSTOMER_CONSENT_REVOKED
Sprint 3-H.1-I
Analytics
Étape 24 — Statistiques
Endpoint
GET /customers/preferences/statistics
Retour
{
"email":523,
"sms":121,
"whatsapp":84,
"marketingOptIn":432
}
Étape 25 — Segmentation
Exemple
acceptsMarketing=true AND preferredChannel=EMAIL
Utilisation
Campagnes CRM Marketing Automation
Sprint 3-H.1-J
Sécurité & RGPD
Étape 26 — Export
Préparer
Compatible avec :
GDPR Export Data Portability
Étape 27 — Révocation
Supporter
Retrait consentement Opt-out Désinscription
Étape 28 — Permissions
Ajouter
customer.preferences.read customer.preferences.write customer.consent.manage
Préparation Sprint 9
Compatible avec :
Campaign MarketingSegment NotificationCenter CommunicationHub
Préparation Sprint 13
Compatible avec :
Recommendation AiConversation AutomationScenario Customer Intelligence
Préparation Sprint 19
Compatible avec :
Consent ComplianceAudit RetentionPolicy DataClassification
Définition de terminé
Le Sprint 3-H.1 est terminé lorsque :
✓ CustomerPreference enrichi ✓ CustomerPreferenceModule créé ✓ CustomerPreferenceController créé ✓ CustomerPreferenceService créé ✓ Consentements RGPD ✓ Personnalisation CRM ✓ Historisation ✓ AuditLog intégré ✓ Swagger documenté
Livrables
CustomerPreference Enterprise CustomerPreferenceModule CustomerPreferenceController CustomerPreferenceService Consent Management Preference Analytics
Sprint 3-H.2 — Centre de Préférences Enterprise & Consent Management
Objectif
Finaliser la couche CRM Enterprise de conformité et de gestion des consentements.
À l'issue de cette étape :
✓ Consentements RGPD avancés ✓ Historique complet ✓ Double Opt-In ✓ Centre omnicanal ✓ Gestion abonnements ✓ Portabilité des données ✓ Droit à l'oubli ✓ Audit de conformité
Architecture cible
Customer ↓ Consent Center ├── Marketing ├── Newsletter ├── SMS ├── WhatsApp ├── Push ├── Profilage ├── Analytics └── Partage données ↓ Compliance ↓ GDPR
Sprint 3-H.2-A
Modèle RGPD
Étape 1 — Création Consent
Ajouter dans schema.prisma
model Consent {
id String
@id
@default(uuid())
tenantId String
customerId String
consentType ConsentType
status ConsentStatus
source ConsentSource
version String
grantedAt DateTime?
revokedAt DateTime?
expiresAt DateTime?
ipAddress String?
userAgent String?
proofReference String?
metadata Json?
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
history ConsentHistory[]
@@index([tenantId])
@@index([customerId])
@@index([consentType])
@@index([status])
}
Étape 2 — Historique
Ajouter
model ConsentHistory {
id String
@id
@default(uuid())
consentId String
oldStatus ConsentStatus?
newStatus ConsentStatus
changedAt DateTime
@default(now())
changedBy String?
reason String?
metadata Json?
consent Consent
@relation(
fields:[consentId],
references:[id],
onDelete:Cascade
)
@@index([consentId])
@@index([changedAt])
}
Étape 3 — Types
Ajouter
enum ConsentType {
MARKETING
NEWSLETTER
SMS
WHATSAPP
EMAIL
PROFILING
ANALYTICS
THIRD_PARTY_SHARING
PERSONALIZATION
}
Étape 4 — Status
Ajouter
enum ConsentStatus {
PENDING
GRANTED
REVOKED
EXPIRED
}
Étape 5 — Source
Ajouter
enum ConsentSource {
WEBSITE
CRM
API
IMPORT
MOBILE_APP
CUSTOMER_PORTAL
}
Étape 6 — Relation Customer
Ajouter
consents Consent[]
dans :
model Customer
Étape 7 — Migration
Générer
npx prisma migrate dev \
--name consent_management
Sprint 3-H.2-B
Double Opt-In
Étape 8 — Extension Consent
Ajouter
doubleOptInRequired Boolean
@default(false)
doubleOptInToken String?
doubleOptInSentAt DateTime?
doubleOptInConfirmedAt DateTime?
Étape 9 — Workflow
Inscription ↓ Consentement ↓ Email confirmation ↓ Lien sécurisé ↓ Consentement actif
Étape 10 — Service
Créer
double-optin.service.ts
Méthodes
generateToken() sendConfirmation() confirmConsent()
Sprint 3-H.2-C
Centre Omnicanal
Étape 11 — Subscription
Ajouter
model CustomerSubscription {
id String
@id
@default(uuid())
customerId String
code String
name String
channel PreferredChannel
subscribed Boolean
@default(true)
subscribedAt DateTime?
unsubscribedAt DateTime?
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
@@index([customerId])
@@index([channel])
}
Étape 12 — Types
Exemples
Newsletter Promotions Loyalty Product Updates Reservation Alerts Security Alerts
Étape 13 — Endpoint
Ajouter
GET /customers/{id}/subscriptions
PUT /customers/{id}/subscriptions
Sprint 3-H.2-D
Consent Management Service
Étape 14 — Création
consent-management.service.ts
Méthodes
grantConsent() revokeConsent() expireConsent() recordProof() getConsentHistory()
Étape 15 — Historisation
Obligatoire
Toute modification crée :
ConsentHistory
Étape 16 — Vérification
Avant envoi
Email SMS WhatsApp Campagne
Vérifier
Consent actif
Sprint 3-H.2-E
Portabilité des données
Étape 17 — Export GDPR
Créer
gdpr-export.service.ts
Agréger
Customer Preferences Consents Communications Documents Notes Tags Reservations
Étape 18 — Endpoint
Ajouter
POST /customers/{id}/gdpr/export
Formats
JSON ZIP PDF
Sprint 3-H.2-F
Droit à l'oubli
Étape 19 — GDPR Erasure
Créer
gdpr-erasure.service.ts
Méthodes
anonymizeCustomer() deletePersonalData() generateErasureReport()
Étape 20 — Workflow
Demande ↓ Validation ↓ Anonymisation ↓ Rapport ↓ Audit
Étape 21 — Endpoint
Ajouter
POST /customers/{id}/gdpr/erase
Anonymisation
Email Téléphone Adresse Documents Métadonnées personnelles
Sprint 3-H.2-G
Centre de Préférences
Étape 22 — Endpoint public
Ajouter
GET /preferences-center/{token}
PUT /preferences-center/{token}
Permet
Modifier préférences Modifier abonnements Retirer consentements Télécharger données
Étape 23 — Token sécurisé
Ajouter
JWT signé Expiration configurable
Sprint 3-H.2-H
Compliance Dashboard
Étape 24 — Endpoint
Ajouter
GET /compliance/consents/dashboard
KPI
Total Consents Active Consents Revoked Consents Double Opt-In Pending Export Requests Erasure Requests
Étape 25 — Exemple
{
"activeConsents":8421,
"revokedConsents":213,
"pendingDoubleOptIn":54
}
Sprint 3-H.2-I
Audit & Conformité
Étape 26 — AuditLog
Ajouter
CONSENT_GRANTED CONSENT_REVOKED DOUBLE_OPTIN_CONFIRMED GDPR_EXPORT_REQUESTED GDPR_ERASURE_REQUESTED GDPR_ERASURE_COMPLETED
Étape 27 — ComplianceAudit
Préparer
Compatible avec :
Sprint 19 ISO27001 SOC2 GDPR Audit
Étape 28 — RetentionPolicy
Préparer
Compatible avec :
RetentionPolicy DataClassification SecurityIncident
Sprint 3-H.2-J
Permissions
Étape 29 — Ajouter
consents.read consents.write consents.manage gdpr.export gdpr.erase
Préparation Sprint 9
Compatible avec :
Campaign NotificationCenter CommunicationHub Marketing Automation
Préparation Sprint 19
Compatible avec :
Consent ComplianceAudit RetentionPolicy DataClassification SecurityPolicy
Préparation Sprint 20
Compatible avec :
Enterprise Governance Enterprise Compliance Privacy Center Customer Trust Dashboard
Définition de terminé
Le Sprint 3-H.2 est terminé lorsque :
✓ Consent créé ✓ ConsentHistory créé ✓ Double Opt-In ✓ Centre omnicanal ✓ Gestion abonnements ✓ Portabilité données ✓ Droit à l'oubli ✓ Dashboard conformité ✓ Audit intégré
Livrables
Consent ConsentHistory CustomerSubscription ConsentManagementService DoubleOptInService GdprExportService GdprErasureService Compliance Dashboard
Sprint 3-I.1 — Recherche CRM Avancée
Objectif
Mettre en place un moteur de recherche CRM Enterprise capable de rechercher instantanément dans l'ensemble du domaine Client.
À l'issue de cette étape :
✓ Recherche globale ✓ Recherche plein texte ✓ Recherche multicritères ✓ Filtres avancés ✓ Facettes ✓ Recherches sauvegardées ✓ CRM Search Engine
Architecture cible
CRM Search API ↓ Search Engine ├── Customers ├── Notes ├── Documents ├── Communications ├── Tags ├── Preferences └── Reservations ↓ Filters Engine ↓ Facets Engine ↓ Saved Searches
Sprint 3-I.1-A
Extension Prisma
Étape 1 — SavedSearch
Ajouter dans schema.prisma
model SavedSearch {
id String
@id
@default(uuid())
tenantId String
userId String
name String
description String?
entityType SearchEntityType
query String?
filters Json
isDefault Boolean
@default(false)
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 — Search History
Ajouter
model SearchHistory {
id String
@id
@default(uuid())
tenantId String
userId String
query String
entityType SearchEntityType?
resultCount Int
@default(0)
executedAt DateTime
@default(now())
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
user User
@relation(
fields:[userId],
references:[id]
)
@@index([tenantId])
@@index([userId])
@@index([executedAt])
}
Étape 3 — Enum
Ajouter
enum SearchEntityType {
CUSTOMER
NOTE
DOCUMENT
COMMUNICATION
TAG
RESERVATION
GLOBAL
}
Étape 4 — Migration
Générer
npx prisma migrate dev \
--name crm_search_engine
Sprint 3-I.1-B
CRM Search Module
Étape 5 — Création
src/modules/crm-search ├── application │ │ └── dto │ │ ├── crm-search.dto.ts │ │ ├── facet-filter.dto.ts │ │ └── saved-search.dto.ts │ ├── domain │ │ └── services │ │ ├── crm-search.service.ts │ │ ├── crm-facet.service.ts │ │ └── saved-search.service.ts │ ├── presentation │ │ └── controllers │ │ └── crm-search.controller.ts │ └── crm-search.module.ts
Sprint 3-I.1-C
DTOs
Étape 6 — Recherche
Créer
crm-search.dto.ts
Ajouter
export class CrmSearchDto {
q?: string;
entityType?: string;
page?: number = 1;
limit?: number = 25;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
filters?: Record<
string,
unknown
>;
}
Étape 7 — Filtres avancés
Supporter
Status Segment Tags Score Revenue Risk Country Language Consent Date
Sprint 3-I.1-D
Recherche Globale
Étape 8 — CrmSearchService
Créer
crm-search.service.ts
Méthodes
globalSearch() searchCustomers() searchNotes() searchDocuments() searchCommunications()
Étape 9 — Recherche Clients
Champs
CustomerNumber FirstName LastName Email Phone CompanyName
Prisma
OR: [
{
firstName: {
contains: q,
mode: 'insensitive'
}
},
{
lastName: {
contains: q,
mode: 'insensitive'
}
},
{
email: {
contains: q,
mode: 'insensitive'
}
}
]
Étape 10 — Recherche Globale
Agréger
Customers Notes Documents Communications
Retour
{
"customers": [],
"notes": [],
"documents": [],
"communications": []
}
Sprint 3-I.1-E
Recherche Plein Texte
Étape 11 — PostgreSQL
Ajouter
Colonnes :
title content subject
Utiliser
tsvector tsquery
Étape 12 — Index
Exemple
CREATE INDEX idx_note_search ON "CustomerNote" USING GIN( to_tsvector( 'simple', content ) );
Étape 13 — Recherche
Exemple
VIP facture
Retour
Notes
Documents
Emails concernés.
Sprint 3-I.1-F
Recherche Multicritères
Étape 14 — Filtres combinés
Exemple
VIP + France + Revenue > 5000 + Marketing = true
Prisma
AND: [ ... ]
Étape 15 — Support
Equals Contains In Range Date Boolean
Sprint 3-I.1-G
Facettes CRM
Étape 16 — CrmFacetService
Créer
crm-facet.service.ts
Méthodes
buildFacets() countSegments() countTags() countCountries()
Étape 17 — Facettes
Exemple
{
"segments": {
"VIP": 41,
"STANDARD": 381
},
"countries": {
"FR": 250,
"ES": 71
}
}
Étape 18 — Endpoint
Ajouter
GET /crm-search/facets
Sprint 3-I.1-H
Recherches Sauvegardées
Étape 19 — SavedSearchService
Créer
saved-search.service.ts
Méthodes
createSearch() listSearches() deleteSearch() executeSavedSearch()
Étape 20 — Exemple
Recherche
VIP France
Sauvegarder
Mes VIP France
Étape 21 — Endpoints
GET /crm-search/saved
POST /crm-search/saved
DELETE /crm-search/saved/{id}
Sprint 3-I.1-I
API Search
Étape 22 — Contrôleur
Créer
crm-search.controller.ts
Étape 23 — Endpoints
Ajouter
GET /crm-search
GET /crm-search/global
GET /crm-search/facets
GET /crm-search/saved
POST /crm-search/saved
DELETE /crm-search/saved/{id}
Étape 24 — Exemple
Requête
GET /crm-search/global?q=dupont
Retour
{
"customers": 3,
"notes": 5,
"communications": 2
}
Sprint 3-I.1-J
Audit & Analytics
Étape 25 — Historique
Créer
SearchHistory
automatiquement.
Étape 26 — AuditLog
Journaliser
CRM_SEARCH CRM_GLOBAL_SEARCH CRM_SAVED_SEARCH CRM_SEARCH_EXPORT
Étape 27 — KPI
Endpoint
GET /crm-search/statistics
Retour
{
"searchesToday":421,
"savedSearches":82,
"mostUsedFilter":"VIP"
}
Préparation Sprint 13
Compatible avec :
Recommendation KnowledgeDocument AiConversation AutomationScenario
Préparation Sprint 17
Compatible avec :
RevenueForecast CustomerAnalytics Predictive Segmentation
Préparation Sprint 20
Compatible avec :
Enterprise Search Global Search Data Intelligence Enterprise Analytics
Définition de terminé
Le Sprint 3-I.1 est terminé lorsque :
✓ Recherche globale ✓ Recherche plein texte ✓ Recherche multicritères ✓ Facettes CRM ✓ Recherches sauvegardées ✓ Historique recherches ✓ Audit intégré ✓ Swagger documenté
Livrables
SavedSearch SearchHistory CrmSearchService CrmFacetService SavedSearchService CRM Search API Enterprise Search Engine
Sprint 3-I.2 — CRM Search Intelligence & Recommandations
Objectif
Faire évoluer le moteur CRM Search vers une plateforme de recherche intelligente assistée par IA.
À l'issue de cette étape :
✓ Recherche sémantique ✓ Suggestions intelligentes ✓ Recherche IA ✓ Résultats personnalisés ✓ Recherche prédictive ✓ Recommandations CRM ✓ Search Intelligence Engine
Architecture cible
User Query ↓ Search Intelligence Layer ├── Full Text Search ├── Semantic Search ├── Predictive Search ├── Personalized Ranking └── AI Recommendations ↓ CRM Knowledge Graph ↓ Results Engine ↓ Recommendations
Sprint 3-I.2-A
Extension Prisma
Étape 1 — SearchSuggestion
Ajouter dans schema.prisma
model SearchSuggestion {
id String
@id
@default(uuid())
tenantId String
query String
frequency Int
@default(1)
lastUsedAt DateTime
@default(now())
createdAt DateTime
@default(now())
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
@@unique([
tenantId,
query
])
@@index([tenantId])
@@index([frequency])
@@index([lastUsedAt])
}
Étape 2 — SearchRecommendation
Ajouter
model SearchRecommendation {
id String
@id
@default(uuid())
tenantId String
userId String
recommendationType RecommendationType
entityType SearchEntityType
entityId String
score Float
reason String?
createdAt DateTime
@default(now())
expiresAt DateTime?
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
user User
@relation(
fields:[userId],
references:[id]
)
@@index([tenantId])
@@index([userId])
@@index([score])
}
Étape 3 — RecommendationType
Ajouter
enum RecommendationType {
RECENT
FREQUENT
RELATED
PREDICTIVE
AI_GENERATED
BEHAVIOR_BASED
}
Étape 4 — Migration
Générer
npx prisma migrate dev \
--name crm_search_ai
Sprint 3-I.2-B
Search Intelligence Module
Étape 5 — Création
src/modules/search-intelligence ├── semantic-search │ ├── suggestions │ ├── recommendations │ ├── predictive-search │ ├── ranking │ └── ai-search
Sprint 3-I.2-C
Recherche Sémantique
Étape 6 — SemanticSearchService
Créer
semantic-search.service.ts
Méthodes
semanticSearch() findRelatedTerms() expandQuery()
Étape 7 — Synonymes CRM
Exemples
VIP = Premium Client = Customer Facture = Invoice Réservation = Booking
Étape 8 — Expansion
Exemple
Recherche : "client premium"
Recherche réelle
VIP Premium High Value Loyal Customer
Sprint 3-I.2-D
Suggestions Intelligentes
Étape 9 — SearchSuggestionService
Créer
search-suggestion.service.ts
Méthodes
generateSuggestions() recordSearch() getPopularQueries()
Étape 10 — Suggestions
Sources
Historique utilisateur Historique tenant Popularité Fréquence
Étape 11 — Endpoint
Ajouter
GET /crm-search/suggestions
Exemple
vip vip france vip paris vip corporate
Sprint 3-I.2-E
Résultats Personnalisés
Étape 12 — PersonalizedRankingService
Créer
personalized-ranking.service.ts
Méthodes
rankResults() applyUserPreferences() boostFrequentlyUsedEntities()
Étape 13 — Critères
Historique utilisateur Segments favoris Clients récents Résultats utilisés
Étape 14 — Exemple
Commercial
VIP Leads Réservations
plus visibles.
Finance
Factures Paiements Contrats
plus visibles.
Sprint 3-I.2-F
Recherche Prédictive
Étape 15 — PredictiveSearchService
Créer
predictive-search.service.ts
Méthodes
predictNextQueries() predictCustomerInterest() predictRelatedSearches()
Étape 16 — Exemples
Recherche
VIP France
Suggestions
VIP Paris VIP Revenue > 10000 VIP Loyalty
Étape 17 — Analyse
Basée sur
SearchHistory SavedSearch CustomerActivity
Sprint 3-I.2-G
Recommandations CRM
Étape 18 — SearchRecommendationService
Créer
search-recommendation.service.ts
Méthodes
generateRecommendations() recommendCustomers() recommendSegments() recommendActions()
Étape 19 — Exemples
Recommandation
23 clients à risque non contactés
Recommandation
12 VIP sans campagne active
Étape 20 — Endpoint
Ajouter
GET /crm-search/recommendations
Sprint 3-I.2-H
Recherche IA
Étape 21 — AI Search Service
Créer
ai-search.service.ts
Méthodes
naturalLanguageSearch() explainResults() generateInsights()
Étape 22 — Exemples
Requête
Montre-moi les clients VIP qui n'ont pas été contactés depuis 90 jours.
Traduction
Segment=VIP AND LastCommunication < 90 jours
Étape 23 — Endpoint
Ajouter
POST /crm-search/ai
Sprint 3-I.2-I
Dashboard Search Intelligence
Étape 24 — Endpoint
Ajouter
GET /crm-search/intelligence/dashboard
KPI
Top recherches Suggestions utilisées Recherche IA Taux de clic Recommandations générées
Étape 25 — Exemple
{
"topSearch":"VIP",
"aiSearches":128,
"recommendations":342
}
Sprint 3-I.2-J
Audit & Gouvernance
Étape 26 — AuditLog
Journaliser
SEMANTIC_SEARCH AI_SEARCH SEARCH_RECOMMENDATION SEARCH_SUGGESTION_SELECTED PREDICTIVE_SEARCH
Étape 27 — Permissions
Ajouter
crm.search.ai crm.search.recommendations crm.search.analytics
Préparation Sprint 13
Compatible avec :
AiConversation KnowledgeGraph RecommendationEngine AutomationScenario
Préparation Sprint 17
Compatible avec :
RevenueForecast CustomerAnalytics PredictiveCRM BusinessIntelligence
Préparation Sprint 20
Compatible avec :
Enterprise AI Search Intelligence Enterprise Knowledge Decision Support System
Définition de terminé
Le Sprint 3-I.2 est terminé lorsque :
✓ Recherche sémantique ✓ Suggestions intelligentes ✓ Recherche IA ✓ Résultats personnalisés ✓ Recherche prédictive ✓ Recommandations CRM ✓ Dashboard Search Intelligence ✓ Audit intégré
Livrables
SearchSuggestion SearchRecommendation SemanticSearchService PredictiveSearchService AISearchService SearchRecommendationService Search Intelligence Dashboard
Sprint 3-J.1 — CRM Analytics & Tableau de Bord
Objectif
Construire le premier cockpit CRM Enterprise centralisant l'ensemble des indicateurs stratégiques.
À l'issue de cette étape :
✓ KPI CRM ✓ Customer Dashboard ✓ Segmentation Analytics ✓ Communication Analytics ✓ Conversion Analytics ✓ Revenue Analytics ✓ Executive Dashboard
Architecture cible
CRM Analytics ↓ Analytics Engine ├── Customers ├── Segments ├── Communications ├── Revenue ├── Conversion └── Loyalty ↓ Dashboard API ↓ Frontend Cockpit
Sprint 3-J.1-A
Extension Prisma
Étape 1 — Dashboard Snapshot
Ajouter dans schema.prisma
model DashboardSnapshot {
id String
@id
@default(uuid())
tenantId String
snapshotDate DateTime
metrics Json
createdAt DateTime
@default(now())
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
@@unique([
tenantId,
snapshotDate
])
@@index([tenantId])
@@index([snapshotDate])
}
Étape 2 — KPI Definition
Ajouter
model KpiDefinition {
id String
@id
@default(uuid())
tenantId String
code String
name String
description String?
category String
active Boolean
@default(true)
createdAt DateTime
@default(now())
updatedAt DateTime
@updatedAt
@@unique([
tenantId,
code
])
@@index([tenantId])
}
Étape 3 — Migration
Générer
npx prisma migrate dev \
--name crm_analytics_dashboard
Générer
npx prisma generate
Sprint 3-J.1-B
CRM Analytics Module
Étape 4 — Création
src/modules/crm-analytics ├── application │ │ └── dto │ ├── domain │ │ └── services │ │ ├── crm-dashboard.service.ts │ │ ├── customer-analytics.service.ts │ │ ├── communication-analytics.service.ts │ │ ├── segmentation-analytics.service.ts │ │ ├── conversion-analytics.service.ts │ │ └── revenue-analytics.service.ts │ ├── presentation │ │ └── controllers │ │ └── crm-analytics.controller.ts │ └── crm-analytics.module.ts
Sprint 3-J.1-C
KPI CRM
Étape 5 — KPI Principaux
Calculer
Nombre clients Clients actifs Clients inactifs VIP Nouveaux clients Clients à risque
Étape 6 — Customer KPI
Exemple
{
"totalCustomers": 12584,
"activeCustomers": 10874,
"inactiveCustomers": 1710,
"vipCustomers": 524
}
Étape 7 — Service
Créer
customer-analytics.service.ts
Méthodes
getCustomerKpis() getGrowthRate() getCustomerHealth()
Sprint 3-J.1-D
Customer Dashboard
Étape 8 — Endpoint
Ajouter
GET /crm-analytics/dashboard
Retour
{
"customers": {},
"communications": {},
"revenue": {},
"segments": {}
}
Étape 9 — Widgets
Ajouter
Top clients Derniers clients Clients à risque Clients VIP Croissance
Étape 10 — Exemple
{
"topCustomers": [],
"vipCustomers": [],
"riskCustomers": []
}
Sprint 3-J.1-E
Segmentation Analytics
Étape 11 — Service
Créer
segmentation-analytics.service.ts
Méthodes
getSegmentDistribution() getSegmentGrowth() getSegmentRevenue()
Étape 12 — KPI
Répartition
VIP Corporate Loyal High Value Standard At Risk
Étape 13 — Endpoint
Ajouter
GET /crm-analytics/segments
Retour
{
"VIP": 412,
"LOYAL": 1832,
"CORPORATE": 94
}
Sprint 3-J.1-F
Communication Analytics
Étape 14 — Service
Créer
communication-analytics.service.ts
Méthodes
getCommunicationStats() getOpenRate() getReplyRate() getChannelPerformance()
Étape 15 — KPI
Calculer
Emails envoyés Emails ouverts SMS envoyés SMS délivrés WhatsApp envoyés Réponses
Étape 16 — Endpoint
Ajouter
GET /crm-analytics/communications
Retour
{
"emailOpenRate": 68.4,
"replyRate": 17.2,
"smsDeliveryRate": 95.8
}
Sprint 3-J.1-G
Conversion Analytics
Étape 17 — Service
Créer
conversion-analytics.service.ts
Méthodes
getConversionRate() getLeadConversion() getCampaignConversion()
Étape 18 — KPI
Exemple
Client créé ↓ Premier achat ↓ Client fidèle
Étape 19 — Endpoint
Ajouter
GET /crm-analytics/conversions
Retour
{
"leadConversion": 22.3,
"repeatCustomerRate": 38.1
}
Sprint 3-J.1-H
Revenue Analytics
Étape 20 — Service
Créer
revenue-analytics.service.ts
Méthodes
getRevenueMetrics() getLifetimeValue() getAverageBasket() getRevenueBySegment()
Étape 21 — KPI
Calculer
Revenue total MRR CRM Lifetime Value Average Basket Revenue Segment
Étape 22 — Endpoint
Ajouter
GET /crm-analytics/revenue
Retour
{
"revenue": 1542870,
"averageBasket": 382,
"averageLtv": 4120
}
Sprint 3-J.1-I
Dashboard Exécutif
Étape 23 — Endpoint
Ajouter
GET /crm-analytics/executive
KPI Stratégiques
Croissance clients Croissance revenu VIP Attrition Satisfaction Engagement
Étape 24 — Snapshot
Générer
Tous les jours :
DashboardSnapshot
Utilisation
Historique Tendances Comparaisons
Étape 25 — Comparaison
Exemple
{
"customersGrowth": 12.4,
"revenueGrowth": 18.7
}
Sprint 3-J.1-J
Audit & Gouvernance
Étape 26 — AuditLog
Journaliser
CRM_DASHBOARD_VIEW CRM_ANALYTICS_VIEW CRM_REVENUE_ANALYTICS CRM_SEGMENT_ANALYTICS CRM_EXPORT_ANALYTICS
Étape 27 — Permissions
Ajouter
crm.analytics.read crm.analytics.export crm.analytics.executive
Étape 28 — Export
Ajouter
GET /crm-analytics/export
Formats
CSV XLSX PDF
Préparation Sprint 13
Compatible avec :
RecommendationEngine AiInsights Forecasting Business Intelligence
Préparation Sprint 17
Compatible avec :
Revenue Forecast Customer Forecast Predictive Analytics Financial Analytics
Préparation Sprint 20
Compatible avec :
Executive Cockpit Enterprise BI Enterprise Analytics Data Warehouse
Définition de terminé
Le Sprint 3-J.1 est terminé lorsque :
✓ KPI CRM ✓ Customer Dashboard ✓ Segmentation Analytics ✓ Communication Analytics ✓ Conversion Analytics ✓ Revenue Analytics ✓ Dashboard exécutif ✓ Export Analytics ✓ Audit intégré
Livrables
DashboardSnapshot KpiDefinition CrmDashboardService CustomerAnalyticsService CommunicationAnalyticsService ConversionAnalyticsService RevenueAnalyticsService Executive Dashboard
Sprint 3-J.2 — CRM Intelligence & Analytics Prédictifs
Objectif
Finaliser le CRM Enterprise en ajoutant une couche complète d'intelligence prédictive.
À l'issue de cette étape :
✓ Prévision revenus ✓ Prévision churn ✓ Prévision LTV ✓ Détection opportunités ✓ Détection anomalies ✓ Insights IA ✓ Score santé client ✓ CRM Intelligence Platform
Architecture cible
CRM Data ↓ Analytics Engine ↓ Prediction Engine ├── Revenue Forecast ├── Churn Prediction ├── LTV Prediction ├── Opportunity Detection ├── Anomaly Detection └── Customer Health ↓ AI Insights ↓ Executive Dashboard
Sprint 3-J.2-A
Extension Prisma
Étape 1 — CustomerHealth
Ajouter dans schema.prisma
model CustomerHealth {
id String
@id
@default(uuid())
customerId String
@unique
overallScore Int
@default(0)
engagementScore Int
@default(0)
loyaltyScore Int
@default(0)
satisfactionScore Int
@default(0)
communicationScore Int
@default(0)
revenueScore Int
@default(0)
churnRiskScore Int
@default(0)
lastCalculatedAt DateTime
@default(now())
customer Customer
@relation(
fields:[customerId],
references:[id],
onDelete:Cascade
)
}
Étape 2 — PredictionSnapshot
Ajouter
model PredictionSnapshot {
id String
@id
@default(uuid())
tenantId String
predictionType PredictionType
snapshotDate DateTime
result Json
createdAt DateTime
@default(now())
tenant Tenant
@relation(
fields:[tenantId],
references:[id]
)
@@index([tenantId])
@@index([predictionType])
@@index([snapshotDate])
}
Étape 3 — AI Insight
Ajouter
model AiInsight {
id String
@id
@default(uuid())
tenantId String
category InsightCategory
severity InsightSeverity
title String
description String
recommendation String?
entityType String?
entityId String?
active Boolean
@default(true)
createdAt DateTime
@default(now())
expiresAt DateTime?
@@index([tenantId])
@@index([category])
@@index([severity])
@@index([active])
}
Étape 4 — Enums
Ajouter
enum PredictionType {
REVENUE
CHURN
LTV
OPPORTUNITY
CUSTOMER_HEALTH
}
enum InsightCategory {
REVENUE
CHURN
CUSTOMER
SEGMENT
COMMUNICATION
MARKETING
}
enum InsightSeverity {
LOW
MEDIUM
HIGH
CRITICAL
}
Étape 5 — Migration
Générer
npx prisma migrate dev \
--name crm_predictive_intelligence
Sprint 3-J.2-B
CRM Intelligence Module
Étape 6 — Création
src/modules/crm-intelligence ├── revenue-forecast │ ├── churn-prediction │ ├── ltv-prediction │ ├── opportunity-detection │ ├── anomaly-detection │ ├── ai-insights │ ├── customer-health │ └── dashboard
Sprint 3-J.2-C
Prévision Revenus
Étape 7 — RevenueForecastService
Créer
revenue-forecast.service.ts
Méthodes
forecastRevenue() forecastSegmentRevenue() forecastCustomerRevenue()
Étape 8 — Sources
Invoices Reservations Customer LTV Customer Score Segments
Étape 9 — Endpoint
Ajouter
GET /crm-intelligence/revenue-forecast
Retour
{
"nextMonth": 152000,
"nextQuarter": 487000,
"confidence": 0.84
}
Sprint 3-J.2-D
Prévision Churn
Étape 10 — ChurnPredictionService
Créer
churn-prediction.service.ts
Méthodes
calculateChurnRisk() predictChurn() detectInactiveCustomers()
Étape 11 — Critères
Dernière activité Dernière communication Baisse dépenses Baisse engagement Réclamations
Étape 12 — Classification
LOW MEDIUM HIGH CRITICAL
Étape 13 — Endpoint
Ajouter
GET /crm-intelligence/churn
Exemple
{
"highRiskCustomers": 42,
"criticalCustomers": 8
}
Sprint 3-J.2-E
Prévision LTV
Étape 14 — LtvPredictionService
Créer
ltv-prediction.service.ts
Méthodes
predictLifetimeValue() predictVipCustomers() estimateFutureRevenue()
Étape 15 — Facteurs
Historique achats Segments Fidélité Engagement Communication
Étape 16 — Endpoint
Ajouter
GET /crm-intelligence/ltv
Retour
{
"averagePredictedLtv": 5420,
"futureVipCustomers": 73
}
Sprint 3-J.2-F
Détection Opportunités
Étape 17 — OpportunityDetectionService
Créer
opportunity-detection.service.ts
Méthodes
findUpsellOpportunities() findCrossSellOpportunities() findRetentionActions()
Étape 18 — Exemples
VIP sans offre premium ↓ Upsell
Corporate sans programme fidélité ↓ Cross-sell
Étape 19 — Endpoint
Ajouter
GET /crm-intelligence/opportunities
Sprint 3-J.2-G
Détection d'Anomalies
Étape 20 — AnomalyDetectionService
Créer
anomaly-detection.service.ts
Méthodes
detectRevenueAnomalies() detectBehaviorAnomalies() detectCommunicationAnomalies()
Étape 21 — Exemples
Baisse revenu -45% ↓ Anomalie
Ouvertures emails 0% ↓ Alerte
Étape 22 — Endpoint
Ajouter
GET /crm-intelligence/anomalies
Sprint 3-J.2-H
Score Santé Client
Étape 23 — CustomerHealthService
Créer
customer-health.service.ts
Méthodes
calculateHealthScore() updateHealthScores() getHealthDistribution()
Étape 24 — Calcul
Pondérations
Engagement 20% Communication 15% Loyalty 20% Revenue 20% Satisfaction 15% Churn Risk 10%
Étape 25 — Classification
90-100 Excellent 75-89 Healthy 50-74 Attention 0-49 Critical
Étape 26 — Endpoint
Ajouter
GET /crm-intelligence/health
Sprint 3-J.2-I
AI Insights
Étape 27 — AiInsightService
Créer
ai-insight.service.ts
Méthodes
generateInsights() generateRecommendations() prioritizeActions()
Étape 28 — Exemples
Insight
23 VIP sans contact depuis 60 jours
Recommandation
Créer campagne VIP
Insight
Segment Corporate +18% revenu ce mois-ci
Étape 29 — Endpoint
Ajouter
GET /crm-intelligence/insights
Sprint 3-J.2-J
Cockpit CRM Intelligence
Étape 30 — Endpoint
Ajouter
GET /crm-intelligence/dashboard
Agrège
Forecast Revenue Churn LTV Health Opportunities Insights
Étape 31 — Exemple
{
"forecastRevenue": 487000,
"highRiskCustomers": 42,
"futureVipCustomers": 73,
"opportunities": 118,
"insights": 14
}
Étape 32 — AuditLog
Journaliser
CRM_FORECAST_GENERATED CRM_CHURN_ANALYSIS CRM_LTV_PREDICTION CRM_ANOMALY_DETECTED CRM_AI_INSIGHT_GENERATED
Étape 33 — Permissions
Ajouter
crm.intelligence.read crm.intelligence.forecast crm.intelligence.insights crm.intelligence.executive
Préparation Sprint 17
Compatible avec :
Forecast Engine Revenue Planning Financial Intelligence Business Intelligence
Préparation Sprint 20
Compatible avec :
Enterprise AI Executive Intelligence Decision Support Predictive Analytics Enterprise BI
Définition de terminé
Le Sprint 3-J.2 est terminé lorsque :
✓ Revenue Forecast ✓ Churn Prediction ✓ LTV Prediction ✓ Opportunity Detection ✓ Anomaly Detection ✓ Customer Health Score ✓ AI Insights ✓ CRM Intelligence Dashboard ✓ Audit intégré
Livrables
CustomerHealth PredictionSnapshot AiInsight RevenueForecastService ChurnPredictionService LtvPredictionService OpportunityDetectionService AnomalyDetectionService CustomerHealthService AiInsightService CRM Intelligence Dashboard
Sprint 3 — Gestion des Clients TERMINÉ
Domaines CRM Livrés
✓ Customer ✓ CustomerAddress ✓ CustomerDocument ✓ CustomerTag ✓ CustomerNote ✓ CustomerCommunication ✓ CustomerPreference ✓ Consent Management ✓ CRM Search ✓ CRM Analytics ✓ CRM Intelligence