update_quote
Modifier un devis
Rôle#
Recompose un devis BROUILLON (cible, cycles, lignes, sections, billingPlan, contacts, objet, remise) : la composition envoyée REMPLACE l'actuelle. expectedUpdatedAt = updatedAt lu par get_quote (refus si le devis a bougé entre-temps). Le commercial du devis ne change pas. Conserver sections et billingPlan lus par get_quote, convertir chaque sectionId en index dans sections ; les omettre les retire.
Accès#
Scope principal : quotes:write. Le scope ne remplace pas les gardes de visibilité, d'organisation, de module ni les scopes complémentaires des gestes composés.
Catalogue complet · Approbations
Paramètres#
Le schéma ci-dessous est produit par la fonction qui enregistre les outils, y compris idempotency_key lorsqu'elle s'applique. Consultez les objets imbriqués dans le schéma complet.
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
id | string | Oui | |
options | array | Non | |
targetType | string | Oui | Valeurs : company, contact |
targetId | string | Oui | |
cycleIds | array | Oui | Cycles couverts - vide seulement avec serviceOn (devis ponctuel, T-1412) |
serviceOn | union | Non | Date de prestation d'un devis PONCTUEL (T-1412) ; null ou absent : devis par cycle |
currency | string | Non | Devise du devis (T-1404, ADR-184) : EUR, ou une devise activée par l'organisation ; absent : EUR à la création, inchangée à l'édition Valeurs : EUR, USD, GBP, CHF |
fxRate | number | Non | Taux saisi à la main, « 1 EUR = fxRate devise » ; absent : taux BCE du jour figé à la création |
subject | union | Non | |
discount | union | Non | |
indexPercent | number | Non | #968 : indexation de N % par cycle appliquée aux montants, tracée dans le fil du devis |
lines | array | Oui | #747 : vide permis - le brouillon est « Non chiffré » (priced = false) et ne s'envoie ni ne se signe tant qu'aucune ligne chiffrée n'existe |
sections | array | Non | |
billingPlan | union | Non | Plan de facturation par cycle : pourcentages totalisant 100, décalage en jours depuis la signature ou le début du cycle. Aucune facture créée avant signature. |
contacts | array | Non | |
expectedUpdatedAt | union | Oui | updatedAt lu au GET - jeton de concurrence |
idempotency_key | string | Non | Clé d'idempotence (recommandée) : rejouer la MÊME mutation avec la même clé renvoie la réponse originale sans ré-exécuter - TTL 24 h |
Schéma JSON complet des paramètres
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"options": {
"maxItems": 100,
"type": "array",
"items": {
"type": "object",
"properties": {
"productId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"productPriceId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"businessUnitId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"unitPrice": {
"type": "number",
"exclusiveMinimum": 0
},
"quantity": {
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"label": {
"type": "string",
"minLength": 1
},
"discountPercent": {
"type": "number",
"minimum": 0,
"maximum": 100
},
"amountsByCycle": {
"type": "object",
"propertyNames": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"additionalProperties": {
"type": "number",
"minimum": 0
}
},
"cycleIds": {
"minItems": 1,
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
},
"required": [
"productId",
"businessUnitId",
"unitPrice",
"quantity"
],
"additionalProperties": false
}
},
"targetType": {
"type": "string",
"enum": [
"company",
"contact"
]
},
"targetId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"cycleIds": {
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"description": "Cycles couverts - vide seulement avec serviceOn (devis ponctuel, T-1412)"
},
"serviceOn": {
"description": "Date de prestation d'un devis PONCTUEL (T-1412) ; null ou absent : devis par cycle",
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "null"
}
]
},
"currency": {
"description": "Devise du devis (T-1404, ADR-184) : EUR, ou une devise activée par l'organisation ; absent : EUR à la création, inchangée à l'édition",
"type": "string",
"enum": [
"EUR",
"USD",
"GBP",
"CHF"
]
},
"fxRate": {
"description": "Taux saisi à la main, « 1 EUR = fxRate devise » ; absent : taux BCE du jour figé à la création",
"type": "number",
"exclusiveMinimum": 0,
"maximum": 999999
},
"subject": {
"anyOf": [
{
"type": "null"
},
{
"type": "string",
"maxLength": 300
}
]
},
"discount": {
"anyOf": [
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"percent",
"amount"
]
},
"value": {
"type": "number",
"minimum": 0
}
},
"required": [
"type",
"value"
]
},
{
"type": "null"
}
]
},
"indexPercent": {
"description": "#968 : indexation de N % par cycle appliquée aux montants, tracée dans le fil du devis",
"type": "number",
"minimum": 0,
"maximum": 100
},
"lines": {
"type": "array",
"items": {
"type": "object",
"properties": {
"productId": {
"description": "null/absent = ligne libre (label requis)",
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"productPriceId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"sectionIndex": {
"description": "Index de la section dans sections (à partir de 0) ; absent : ligne à plat",
"anyOf": [
{
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"businessUnitId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"unitPrice": {
"type": "number",
"minimum": 0
},
"quantity": {
"type": "number",
"exclusiveMinimum": 0
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 2000
},
"discountPercent": {
"type": "number",
"minimum": 0,
"maximum": 100
},
"isText": {
"description": "Ligne de texte (#973) : libellé seul, sans produit ; prix 0, quantité 1, aucun cycle, hors de tout total",
"type": "boolean"
},
"amountsByCycle": {
"description": "#968 : montant HT de la ligne par cycle couvert, AVANT remise de ligne ({ cycleId: montant }) ; absent : PU × quantité à chaque cycle",
"type": "object",
"propertyNames": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"additionalProperties": {
"type": "number",
"minimum": 0
}
}
},
"required": [
"businessUnitId",
"unitPrice",
"quantity"
],
"additionalProperties": false
},
"description": "#747 : vide permis - le brouillon est « Non chiffré » (priced = false) et ne s'envoie ni ne se signe tant qu'aucune ligne chiffrée n'existe"
},
"sections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"minLength": 1
},
"isBundle": {
"type": "boolean"
}
},
"required": [
"label"
],
"additionalProperties": false
}
},
"billingPlan": {
"description": "Plan de facturation par cycle : pourcentages totalisant 100, décalage en jours depuis la signature ou le début du cycle. Aucune facture créée avant signature.",
"anyOf": [
{
"minItems": 1,
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"minLength": 1
},
"percentage": {
"type": "number",
"exclusiveMinimum": 0,
"maximum": 100
},
"offsetDays": {
"type": "integer",
"minimum": -3650,
"maximum": 3650
},
"anchor": {
"type": "string",
"enum": [
"signature",
"cycle_start"
]
}
},
"required": [
"label",
"percentage",
"offsetDays"
]
}
},
{
"type": "null"
}
]
},
"contacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"contactId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"role": {
"type": "string",
"enum": [
"principal",
"operational",
"billing",
"other"
]
}
},
"required": [
"contactId",
"role"
],
"additionalProperties": false
}
},
"expectedUpdatedAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
},
{
"type": "string",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
}
],
"description": "updatedAt lu au GET - jeton de concurrence"
},
"idempotency_key": {
"description": "Clé d'idempotence (recommandée) : rejouer la MÊME mutation avec la même clé renvoie la réponse originale sans ré-exécuter - TTL 24 h",
"type": "string",
"minLength": 1,
"maxLength": 200
}
},
"required": [
"id",
"targetType",
"targetId",
"cycleIds",
"lines",
"expectedUpdatedAt"
],
"additionalProperties": false
}