Aller au contenu

retours-d-execution

Événement (AsyncAPI) — version 0.2.0. Producteur : carnet-ordres. Consommateurs déclarés : operations.

CE QUE LE CARNET RENVOIE À OPÉRATIONS. « Opérations publie ce qui doit être exécuté ; le carnet d’ordres dit ce qu’il en advient. » CES FAITS NE SONT PAS COMPTABILISABLES : ils disent l’AVANCEMENT, pas le fait définitif. La comptabilisation passe par le canal carnet-ordres.compte-rendu-execution, sous une règle de finalité versionnée — les mêler ouvrirait la porte à une comptabilisation prématurée. TOUTE ANNONCE PRISE EN CHARGE OBTIENT UNE ISSUE EXPLICITE : exécutée, rejetée, reportée, annulée — jamais d’abandon silencieux.

asyncapi: 3.0.0
info:
title: carnet-ordres — les retours d'exécution
version: 0.2.0
x-ruptures:
- version: 0.2.0
rupture: "propriété retirée : tenant"
motif: >-
Isolation forte par tenant — aucun identifiant de tenant n'est transporté ;
l'appartenance est celle de l'installation (précédent instruments 0.4.0).
description: >-
CE QUE LE CARNET RENVOIE À OPÉRATIONS. « Opérations publie ce qui doit être exécuté ; le
carnet d'ordres dit ce qu'il en advient. » CES FAITS NE SONT PAS COMPTABILISABLES : ils
disent l'AVANCEMENT, pas le fait définitif. La comptabilisation passe par le canal
carnet-ordres.compte-rendu-execution, sous une règle de finalité versionnée — les mêler
ouvrirait la porte à une comptabilisation prématurée. TOUTE ANNONCE PRISE EN CHARGE
OBTIENT UNE ISSUE EXPLICITE : exécutée, rejetée, reportée, annulée — jamais d'abandon
silencieux.
x-producteurs:
- carnet-ordres
x-consommateurs:
- operations
defaultContentType: application/json
channels:
retoursDExecution:
address: carnet-ordres.retour-execution
description: >-
Les retours vers Opérations. UN CANAL, UN CONSOMMATEUR : les obligations de règlement
vers la banque et les comptes rendus vers la tenue de compte ont les leurs.
messages:
ordrePrisEnCharge: { $ref: '#/components/messages/ordrePrisEnCharge' }
ordreRejete: { $ref: '#/components/messages/ordreRejete' }
ordreExecute: { $ref: '#/components/messages/ordreExecute' }
reliquatReporte: { $ref: '#/components/messages/reliquatReporte' }
annulationTraitee: { $ref: '#/components/messages/annulationTraitee' }
ordreSuspendu: { $ref: '#/components/messages/ordreSuspendu' }
operations:
publierLesRetoursDExecution:
action: send
channel: { $ref: '#/channels/retoursDExecution' }
summary: >-
Faire avancer les jambes d'Opérations sans jamais rien comptabiliser. Le carnet NE
MODIFIE JAMAIS l'opération pour la rendre exécutable : il retourne de quoi décider.
messages:
- $ref: '#/channels/retoursDExecution/messages/ordrePrisEnCharge'
- $ref: '#/channels/retoursDExecution/messages/ordreRejete'
- $ref: '#/channels/retoursDExecution/messages/ordreExecute'
- $ref: '#/channels/retoursDExecution/messages/reliquatReporte'
- $ref: '#/channels/retoursDExecution/messages/annulationTraitee'
- $ref: '#/channels/retoursDExecution/messages/ordreSuspendu'
components:
messages:
ordrePrisEnCharge:
name: ordre-pris-en-charge
title: Ordre pris en charge
summary: >-
Le carnet s'est saisi de l'annonce et lui a calculé une échéance. CELA NE GARANTIT
NI LA RÉCEPTION EXTERNE NI L'EXÉCUTION.
contentType: application/json
payload: { $ref: '#/components/schemas/ordrePrisEnCharge' }
ordreRejete:
name: ordre-rejete
title: Ordre rejeté
summary: >-
L'annonce est inexécutable dans le contexte évalué. Le carnet PEUT REJETER une
annonce qu'Opérations avait jugée recevable, si le contexte d'exécution a changé ;
il ne rouvre jamais la recevabilité métier.
contentType: application/json
payload: { $ref: '#/components/schemas/ordreRejete' }
ordreExecute:
name: ordre-execute
title: Ordre exécuté
summary: >-
Une tranche est exécutée, VENTILÉE PAR INSTRUCTION D'ORIGINE. Une exécution
PARTIELLE ne vaut JAMAIS exécution totale.
contentType: application/json
payload: { $ref: '#/components/schemas/ordreExecute' }
reliquatReporte:
name: reliquat-reporte
title: Reliquat reporté
summary: >-
La part non servie est affectée à une échéance ultérieure. UN RELIQUAT NÉ D'UN ORDRE
EN MONTANT RESTE EN MONTANT : il s'exécutera à un autre prix.
contentType: application/json
payload: { $ref: '#/components/schemas/reliquatReporte' }
annulationTraitee:
name: annulation-traitee
title: Annulation traitée
summary: >-
La suite donnée à une demande d'annulation. AVANT REMISE elle est appliquée ; APRÈS
REMISE elle devient une demande adressée à la place ; APRÈS EXÉCUTION elle est
refusée — seule la compensation reste possible, et elle appartient à Opérations.
contentType: application/json
payload: { $ref: '#/components/schemas/annulationTraitee' }
ordreSuspendu:
name: ordre-suspendu
title: Ordre suspendu ou repris
summary: >-
Le traitement est bloqué ou reprend. LE MOTIF D'UNE SUSPENSION DE CONFORMITÉ NE
REMONTE JAMAIS : la suspension se voit, elle ne s'explique pas.
contentType: application/json
payload: { $ref: '#/components/schemas/ordreSuspendu' }
schemas:
enveloppe:
type: object
required: [evenementId, typeEvenement, versionContrat, dateEvenement, producteur,
ordreRef, operationRef, instructionRef, cleIdempotence]
properties:
evenementId:
type: string
description: >-
Identifiant unique — LA CLÉ D'IDEMPOTENCE DES CONSOMMATEURS. La livraison est au
moins une fois : le rejeu ne doit produire qu'un effet.
typeEvenement: { type: string }
versionContrat: { type: string }
dateEvenement: { type: string, format: date-time }
producteur: { type: string, const: carnet-ordres }
sequenceEntite:
type: integer
description: Numéro de séquence PAR ORDRE INDIVIDUEL et par producteur.
ordreRef: { type: string, description: 'Identifiant publié de l''ordre chez le carnet.' }
annonceRef: { type: string }
operationRef: { type: string }
instructionRef:
type: string
description: >-
L'INSTRUCTION D'ORIGINE. C'est elle qui rend le dépouillement exact : Opérations
n'a jamais à redescendre d'un agrégat.
cleIdempotence: { type: string }
ordrePrisEnCharge:
allOf:
- $ref: '#/components/schemas/enveloppe'
- type: object
required: [dateCentralisation, heureLimite, fuseauHeureLimite]
properties:
centralisationRef: { type: string }
dateCentralisation: { type: string, format: date }
dateVlAttendue: { type: string, format: date }
dateReglementPrevue: { type: string, format: date }
heureLimite: { type: string, format: date-time }
fuseauHeureLimite:
type: string
description: >-
Fuseau IANA. Un ordre reçu à 12 h 01 heure de Paris n'est pas le même fait
qu'un ordre reçu à 12 h 01 heure de Luxembourg.
reservationAccordee: { type: boolean }
ordreRejete:
allOf:
- $ref: '#/components/schemas/enveloppe'
- type: object
required: [motif, explication]
properties:
motif:
type: string
enum: [DOUBLON_CONFLICTUEL, SUPPORT_NON_ORDONNABLE, OFFRE_NON_ACTIVE,
POSITION_INSUFFISANTE, POSITION_GELEE, RESERVATION_IMPOSSIBLE,
HEURE_LIMITE_DEPASSEE, ECHEANCE_INTROUVABLE, CHAINE_INDISPONIBLE,
SERVICE_NON_ACTIVE, VL_INDISPONIBLE, REJETE_EXTERNE]
description: 'Code STABLE, séparé du libellé utilisateur.'
explication:
type: string
description: 'En français métier — ce qui rend le rejet explicable des années plus tard.'
versionsUtilisees:
type: object
description: >-
Les versions consommées par la décision — support, offre, position. C'est ce qui
la rend REJOUABLE À L'IDENTIQUE. Jamais le dispositif : il ne parvient pas au
carnet.
additionalProperties: { type: string }
ordreExecute:
allOf:
- $ref: '#/components/schemas/enveloppe'
- type: object
required: [nature, quantiteExecuteeUpm, montantExecuteCt, dateExecution,
montantDemandeInitialCt]
properties:
nature:
type: string
enum: [PARTIELLE, TOTALE]
description: >-
UNE EXÉCUTION PARTIELLE NE VAUT JAMAIS EXÉCUTION TOTALE, et la clôture ne se
déduit jamais du premier retour.
quantiteExecuteeUpm: { type: integer, format: int64, description: 'En MILLIONIÈMES de part.' }
montantExecuteCt: { type: integer, format: int64, description: 'En CENTIMES, brut.' }
montantDemandeInitialCt:
type: integer
format: int64
description: >-
LA DEMANDE INITIALE RAPPELÉE dans le message. C'est ce qui rend la
conservation — exécutions + rejets + reliquats = demande — vérifiable DEPUIS
LE FLUX SEUL, sans consultation.
quantiteDemandeeInitialeUpm: { type: integer, format: int64 }
vlUe6:
type: integer
format: int64
description: 'Valeur liquidative appliquée, en MICRO-EUROS. Fil rouge : 24381200.'
dateVl: { type: string, format: date }
prixMoyenUe6: { type: integer, format: int64, description: 'Chaîne titres.' }
dateExecution: { type: string, format: date }
motifReduction:
type: string
enum: [PLAFONNEMENT_RACHATS, EXECUTION_PARTIELLE_MARCHE, SUSPENSION_SUPPORT]
description: 'Présent seulement quand la tranche est réduite.'
frais:
type: array
description: 'Les frais par nature, EN LIGNES — jamais en colonnes.'
items:
type: object
required: [nature, montantCt]
properties:
nature:
type: string
enum: [DROITS_ENTREE, DROITS_SORTIE, FRAIS_BOURSE, COMMISSION,
TAXE_TRANSACTION]
montantCt: { type: integer, format: int64 }
reliquatReporte:
allOf:
- $ref: '#/components/schemas/enveloppe'
- type: object
required: [revocable]
properties:
montantRestantCt:
type: integer
format: int64
description: >-
UN RELIQUAT NÉ D'UN ORDRE EN MONTANT RESTE EN MONTANT : il s'exécutera à un
AUTRE PRIX, et figer une quantité serait faux.
quantiteRestanteUpm: { type: integer, format: int64 }
prochaineDateVlAttendue: { type: string, format: date }
prochaineCentralisationRef: { type: string }
revocable:
type: boolean
description: >-
Un reliquat NON RÉVOCABLE ne s'annule pas par une action locale : la demande
d'annulation est rejetée avec la source de la règle.
representationNo: { type: integer }
maxRepresentations: { type: integer }
motif:
type: string
enum: [PLAFONNEMENT_RACHATS, EXECUTION_PARTIELLE_MARCHE]
annulationTraitee:
allOf:
- $ref: '#/components/schemas/enveloppe'
- type: object
required: [demandeVisee, suite]
properties:
demandeVisee: { type: string }
suite:
type: string
enum: [APPLIQUEE, TRANSMISE_A_LA_PLACE, CONFIRMEE_PAR_LA_PLACE,
REFUSEE_PAR_LA_PLACE, IMPOSSIBLE_APRES_EXECUTION,
IMPOSSIBLE_RELIQUAT_NON_REVOCABLE]
description: >-
UNE ANNULATION REÇOIT UNE SUITE, JAMAIS UN SILENCE. Après exécution, seule
la compensation reste possible — et elle appartient à Opérations.
motif: { type: string }
reservationLiberee: { type: boolean }
ordreSuspendu:
allOf:
- $ref: '#/components/schemas/enveloppe'
- type: object
required: [sens, origine]
properties:
sens:
type: string
enum: [SUSPENDU, REPRIS]
origine:
type: string
enum: [CONFORMITE, DONNEE, TECHNIQUE, EXTERNE]
motif:
type: string
description: >-
ABSENT ET INTERDIT quand l'origine est CONFORMITE : le cloisonnement du
domaine Conformité vaut jusque dans ce contrat. Présent sinon.