Franchise Partner Added
A person became a partner of a franchise unit, with their roles. One message per partner. Consumed by cna-nexus itself to invalidate the economic group statistics cache.
Overview
Fact: a Franchise PartnerFranchise PartnerEntityv1.0.0The link between a franchise unit and a person behind it, with one or more roles - FRANCHISEE (leads the unit) or OPERAT...Ownercna-platformView docs row was added. The payload carries the unit, the partner’s roles and a snapshot of the person. Since 1.1.0 person.birthDate is a calendar day, YYYY-MM-DD, with no time zone: the column is a date, and a consumer that built a Date from the former midnight-UTC timestamp and stored it in a negative offset landed on the day before.
When it is published. CNA NexusCNA NexusServicev1.0.0Franchise network back-office (franchises, economic groups, partners, contracts and amendments, document storage, AI doc...PublishesInviteUser, ContractActivationRequested +13SubscribesContractActivationRequested, AmendmentApplyRequested +4Ownercna-platformMapRepoView docs, in addPartners, which runs inside replaceFranchisePartners whenever a franchise is created from a contract, its legal information is edited, or a contract is applied onto it. Registered with manager.afterCommit(), one message per added partner, batched in a single send. The same commit may also carry Franchise Partner RemovedFranchise Partner RemovedEventv1.1.0A person stopped being a partner of a franchise unit. One message per partner. Consumed by cna-nexus itself to invalidat...Ownercna-platformSchemaMapView docs and Franchise Partner UpdatedFranchise Partner UpdatedEventv1.1.0The roles of a franchise partner changed - roles are the only mutable field. Carries the roles before and after. Consume...Ownercna-platformSchemaMapView docs messages. A later change to the person’s own data does not republish this event; it travels as Partner UpdatedPartner UpdatedEventv1.0.0The personal data of a franchise partner changed in CNA Nexus - name, legal name, e-mail, phone or birth date. Snapshot ...Ownercna-platformSchemaMapView docs on Partner (Kafka topic)Partner (Kafka topic)Channelv1.0.0Kafka topic for the Partner aggregate - a person in their capacity as partner of one or more franchise units. Carries Pa...Ownercna-platformView docs (target contract).
What the consumer does. cna-nexus (touchEconomicGroupOnFranchisePartnerChange, group economic-group-partner-touch): loads the franchise; if it has an economic group, bumps the group’s updatedAt. That timestamp versions the Redis cache of the economic group statistics (units, franchisees, active groups), so the next read recomputes them. Franchises without a group are ignored. CNA OneCNA OneServicev1.0.0Franchise operating system (franchises and employees, pricing, products and learning books, school operations). Publishe...PublishesGrantApplicationAccess, EmployeeCreated +6SubscribesInviteUser, FranchiseCreated +9Ownercna-platformMapRepoView docs has no class for this event and drops it.
Kafka
Topic (aggregateRoot) | Franchise |
Message key (routingKey) | payload.franchiseId |
| Contract owner | NEXUS |
metadata.event | FranchisePartnerAdded |
| Consumer group | economic-group-partner-touch |
Payload schema
Source of truth
export type FranchisePartnerEventPerson = { id: string; document: string; documentType: PersonsDocumentType; name: string; email?: string | null; phone?: string | null; birthDate?: string | null; legalName?: string | null; isFranchisee: boolean;};
export type FranchisePartnerEventPayload = { franchiseId: string; roles: FranchisePartnerRole[]; person: FranchisePartnerEventPerson;};
export class FranchisePartnerAdded extends Event<FranchisePartnerEventPayload> { static readonly owner = 'NEXUS'; static readonly aggregateRoot = 'Franchise'; static readonly routingKey = 'franchiseId'; static readonly version = '1.0.0'; // wire format is 1.1.0, bump pending (Known drift)}Known drift
Observed 2026-09-24.
- cna-nexus
api/app/events/nexus/franchise/FranchisePartnerAdded.tsonstaging(cna-br/cna-nexus#562) sendsperson.birthDateasYYYY-MM-DD, the 1.1.0 contract, but still declaresstatic readonly version = '1.0.0', sometadata.versionwill read1.0.0. Production (v0.13.0) runs the 1.0.0 contract, with the ISO timestamp, until the next release. No pin: cna-nexus is the producer and the only consumer, and its handler reads onlyfranchiseId. The badge and this note go when the class declares1.1.0in production. - cna-one has no class for this event on
mainand drops it. Branchjl/feature/CWH-49388-consume-franchise-partner-events(not merged) typesbirthDateasYYYY-MM-DDtext, has nostatic version, and does not carryrolesorisFranchisee. person.isFranchiseeis true when the person holdsFRANCHISEEin any franchise, not only infranchiseId.
Custom properties
| Property | Value |
|---|---|
| Contract Ownerx-contract-owner | NEXUS |
| Kafka Topicx-kafka-topic | Franchise |
| Message Keyx-message-key | franchiseId |
| Sourcex-source | cna-nexus api/app/events/nexus/franchise/FranchisePartnerAdded.ts |
| Driftx-drift | cna-nexus publishes birthDate as YYYY-MM-DD (cna-br/cna-nexus#562, staging) but its class still declares version 1.0.0, and production sends the ISO timestamp until the next release; isFranchisee is global across franchises, not scoped to franchiseId. |
Franchise id (UUID). Kafka message key.
Roles of the partner in this unit (FranchisePartnerRole). Never empty.
Snapshot of the person (common.persons).