# Produits

Créez et gérez des produits dans votre catalogue.

## Lister les produits

Récupère les produits du catalogue, paginés et filtrables.

## GET /v2/catalog

> List products with pagination

```json
{"openapi":"3.0.0","info":{"title":"Abby API","version":"1.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"CatalogOrderBy":{"type":"string","enum":["createdAt","designation"]},"OrderDirection":{"type":"string","enum":["ASC","DESC"]},"ReadCatalogCollectionDto":{"type":"object","properties":{"countWithoutFilters":{"type":"number"},"totalDocs":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"},"hasNextPage":{"type":"boolean"},"hasPrevPage":{"type":"boolean"},"nextPage":{"type":"number"},"page":{"type":"number"},"prevPage":{"type":"number"},"docs":{"type":"array","items":{"$ref":"#/components/schemas/ReadProductListItemDto"}}},"required":["countWithoutFilters","totalDocs","limit","totalPages","hasNextPage","hasPrevPage","nextPage","page","prevPage","docs"]},"ReadProductListItemDto":{"type":"object","properties":{"id":{"type":"string"},"type":{"allOf":[{"$ref":"#/components/schemas/ProductType"}]},"unit":{"allOf":[{"$ref":"#/components/schemas/ProductUnit"}]},"designation":{"type":"string"},"description":{"type":"string","nullable":true},"reference":{"type":"string","nullable":true},"vatCode":{"allOf":[{"$ref":"#/components/schemas/VatCode"}]},"personalServiceActivity":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/PersonalServiceActivity"}]},"isDeliveryOfGood":{"type":"boolean"},"taxesIncluded":{"type":"boolean"},"purchasePrice":{"type":"number","description":"Purchase price per unit without taxes"},"productMargin":{"type":"number","description":"Product margin"},"unitPrice":{"type":"number","description":"Price per unit without taxes"},"priceWithoutTaxes":{"type":"number","description":"Total price without taxes"},"vatAmount":{"type":"number","description":"VAT amount"},"priceWithTaxes":{"type":"number","description":"Total price including taxes"},"stock":{"type":"number","description":"Stock"}},"required":["id","type","unit","designation","vatCode","isDeliveryOfGood","taxesIncluded","unitPrice","priceWithoutTaxes","vatAmount","priceWithTaxes","stock"]},"ProductType":{"type":"number","enum":[1,2,3,4,5]},"ProductUnit":{"type":"number","enum":[14,1,2,3,22,23,24,25,26,21,20,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,27,28]},"VatCode":{"type":"string","enum":["FR_210","FR_550","FR_850","FR_1000","FR_2000","FR_00HT","FR_00UE","FR_0HUE"]},"PersonalServiceActivity":{"type":"string","enum":["GARDE_ENFANT_HANDICAPE","ACCOMPAGNEMENT_ENFANT_HANDICAPE","AIDE_HUMAINE","CONDUITE_VEHICULE_PERSONNEL","AIDE_AU_DEPLACEMENT","ENTRETIEN_DE_LA_MAISON","JARDINAGE","BRICOLAGE","GARDE_ENFANT_PLUS_DE_6_ANS","SOUTIEN_SCOLAIRE_COURS_A_DOMICILE","SOIN_ESTHETIQUE_A_DOMICILE","PREPARATION_REPAS_A_DOMICILE","LIVRAISON_REPAS_A_DOMICILE","COLLECTE_ET_LIVRAISON_DE_LINGE_REPASSE","LIVRAISON_COURSES_A_DOMICILE","ASSISTANCE_INFORMATIQUE","SOINS_ET_PROMENADES_ANIMAUX_DE_COMPAGNIE_POUR_PERSONNES_DEPENDANTES","MAINTENANCE_ENTRETIEN_ET_VIGILANCE_DE_LA_RESIDENCE_PRINCIPALE","ASSISTANCE_ADMINISTRATIVE","ACCOMPAGNEMENT_ENFANT_PLUS_DE_6_ANS","TELEASSISTANCE","INTERPRETE_LANGUE_DES_SIGNES","CONDUITE_VEHICULE_PERSONNEL_EN_CAS_INVALIDITE_TEMPORAIRE","ACCOMPAGNEMENT_DEPLACEMENTS_EN_DEHORS_DU_DOMICILE","ASSISTANCE_PERSONNES_TEMPORAIREMENT_DEPENDANTES_A_DOMICILE","COORDINATION_ET_GESTION","DIVERS_NON_ELIGIBLE"]}}},"paths":{"/v2/catalog":{"get":{"operationId":"CatalogController_paginate_v2","parameters":[{"name":"page","required":true,"in":"query","description":"The page number to retrieve","schema":{"minimum":1,"type":"number"}},{"name":"limit","required":true,"in":"query","description":"The number of items per page","schema":{"minimum":1,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Optional search term to filter the catalog","schema":{"type":"string"}},{"name":"orderBy","required":false,"in":"query","description":"Optional order by to filter the catalog","schema":{"$ref":"#/components/schemas/CatalogOrderBy"}},{"name":"orderDirection","required":false,"in":"query","description":"Optional order direction to filter the catalog","schema":{"$ref":"#/components/schemas/OrderDirection"}},{"name":"sapCompatible","required":false,"in":"query","description":"Optional sap compatible to filter the catalog","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadCatalogCollectionDto"}}}}},"summary":"List products with pagination","tags":["catalog"]}}}}
```

### Paramètres de requête

Champs requis :

* `page` : numéro de page (à partir de `1`)
* `limit` : nombre d'éléments par page

Champs optionnels :

* `search` : terme de recherche (filtre sur la désignation, la référence, etc.)
* `orderBy` : champ de tri (voir valeurs ci-dessous)
* `orderDirection` : sens du tri (`ASC` ou `DESC`)
* `sapCompatible` : `true` pour ne lister que les produits compatibles avec une comptabilité SAP

#### `orderBy` (CatalogOrderBy)

* `createdAt` (défaut)
* `designation`

#### `orderDirection` (OrderDirection)

* `ASC`
* `DESC`

#### Exemple

```http
GET /v2/catalog?page=1&limit=20&search=widget&orderBy=designation&orderDirection=ASC
```

### Réponse (`ReadCatalogCollectionDto`)

Réponse paginée contenant un tableau `docs` de produits, ainsi que les métadonnées de pagination (`total`, `page`, `limit`, `pages`, etc.).

## Récupérer un produit

Renvoie le détail complet d'un produit à partir de son identifiant.

## GET /v2/catalog/product/{productId}

> Retrieve a product by id

```json
{"openapi":"3.0.0","info":{"title":"Abby API","version":"1.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"ReadProductDto":{"type":"object","properties":{"id":{"type":"string"},"type":{"description":"Type of the product","allOf":[{"$ref":"#/components/schemas/ProductType"}]},"unit":{"description":"Unit of measurement for the product","allOf":[{"$ref":"#/components/schemas/ProductUnit"}]},"designation":{"type":"string","description":"Name or title of the product"},"description":{"type":"string","nullable":true,"description":"Detailed description of the product"},"reference":{"type":"string","nullable":true,"description":"Product reference code"},"vatCode":{"description":"VAT code applicable to this product","allOf":[{"$ref":"#/components/schemas/VatCode"}]},"personalServiceActivity":{"nullable":true,"description":"Personal service activity classification, if applicable","allOf":[{"$ref":"#/components/schemas/PersonalServiceActivity"}]},"isDeliveryOfGood":{"type":"boolean","description":"Indicates if the product involves delivery of physical goods"},"taxesIncluded":{"type":"boolean","description":"Indicates if the prices include taxes"},"purchasePrice":{"type":"number","description":"Purchase price per unit without taxes"},"productMargin":{"type":"number","description":"Product margin"},"lockUnitPrice":{"type":"boolean","description":"Indicates if the unit price is locked"},"unitPrice":{"type":"number","description":"Price per unit without taxes"},"priceWithoutTaxes":{"type":"number","description":"Total price without taxes"},"vatAmount":{"type":"number","description":"VAT amount"},"priceWithTaxes":{"type":"number","description":"Total price including taxes"},"stock":{"type":"number","description":"Stock"}},"required":["id","type","unit","designation","vatCode","isDeliveryOfGood","taxesIncluded","unitPrice","priceWithoutTaxes","vatAmount","priceWithTaxes","stock"]},"ProductType":{"type":"number","enum":[1,2,3,4,5]},"ProductUnit":{"type":"number","enum":[14,1,2,3,22,23,24,25,26,21,20,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,27,28]},"VatCode":{"type":"string","enum":["FR_210","FR_550","FR_850","FR_1000","FR_2000","FR_00HT","FR_00UE","FR_0HUE"]},"PersonalServiceActivity":{"type":"string","enum":["GARDE_ENFANT_HANDICAPE","ACCOMPAGNEMENT_ENFANT_HANDICAPE","AIDE_HUMAINE","CONDUITE_VEHICULE_PERSONNEL","AIDE_AU_DEPLACEMENT","ENTRETIEN_DE_LA_MAISON","JARDINAGE","BRICOLAGE","GARDE_ENFANT_PLUS_DE_6_ANS","SOUTIEN_SCOLAIRE_COURS_A_DOMICILE","SOIN_ESTHETIQUE_A_DOMICILE","PREPARATION_REPAS_A_DOMICILE","LIVRAISON_REPAS_A_DOMICILE","COLLECTE_ET_LIVRAISON_DE_LINGE_REPASSE","LIVRAISON_COURSES_A_DOMICILE","ASSISTANCE_INFORMATIQUE","SOINS_ET_PROMENADES_ANIMAUX_DE_COMPAGNIE_POUR_PERSONNES_DEPENDANTES","MAINTENANCE_ENTRETIEN_ET_VIGILANCE_DE_LA_RESIDENCE_PRINCIPALE","ASSISTANCE_ADMINISTRATIVE","ACCOMPAGNEMENT_ENFANT_PLUS_DE_6_ANS","TELEASSISTANCE","INTERPRETE_LANGUE_DES_SIGNES","CONDUITE_VEHICULE_PERSONNEL_EN_CAS_INVALIDITE_TEMPORAIRE","ACCOMPAGNEMENT_DEPLACEMENTS_EN_DEHORS_DU_DOMICILE","ASSISTANCE_PERSONNES_TEMPORAIREMENT_DEPENDANTES_A_DOMICILE","COORDINATION_ET_GESTION","DIVERS_NON_ELIGIBLE"]}}},"paths":{"/v2/catalog/product/{productId}":{"get":{"operationId":"CatalogController_retrieve_v2","parameters":[{"name":"productId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadProductDto"}}}}},"summary":"Retrieve a product by id","tags":["catalog"]}}}}
```

### Paramètres de chemin

* `productId` : identifiant du produit

### Réponse (`ReadProductDto`)

Renvoie l'objet produit complet avec ses prix, sa TVA, son stock, sa description, etc.

## Créer un produit

## POST /v2/catalog/product

> Create a new product

```json
{"openapi":"3.0.0","info":{"title":"Abby API","version":"1.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"CreateProductDto":{"type":"object","properties":{"type":{"description":"The type of the product","allOf":[{"$ref":"#/components/schemas/ProductType"}]},"unit":{"description":"The unit of measurement for the product","allOf":[{"$ref":"#/components/schemas/ProductUnit"}]},"designation":{"type":"string","description":"The name or title of the product"},"amountInCents":{"type":"number","description":"The price of the product in cents"},"purchasePrice":{"type":"number","description":"The purchase price of the product in cents"},"productMargin":{"type":"number","description":"The margin of the product in percentage"},"lockUnitPrice":{"type":"boolean","description":"Whether the unit price is locked or not calculating from purchase price and product margin","default":false},"taxesIncluded":{"type":"boolean","description":"Whether the amount includes taxes"},"vatCode":{"description":"The VAT code applicable to the product","default":"FR_00HT","allOf":[{"$ref":"#/components/schemas/VatCode"}]},"isDeliveryOfGood":{"type":"boolean","description":"Whether the product involves delivery of a physical good"},"description":{"type":"string","description":"Detailed description of the product"},"reference":{"type":"string","description":"Product reference or SKU"},"stock":{"type":"number","description":"The stock quantity"}},"required":["type","unit","designation"]},"ProductType":{"type":"number","enum":[1,2,3,4,5]},"ProductUnit":{"type":"number","enum":[14,1,2,3,22,23,24,25,26,21,20,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,27,28]},"VatCode":{"type":"string","enum":["FR_210","FR_550","FR_850","FR_1000","FR_2000","FR_00HT","FR_00UE","FR_0HUE"]},"ReadProductDto":{"type":"object","properties":{"id":{"type":"string"},"type":{"description":"Type of the product","allOf":[{"$ref":"#/components/schemas/ProductType"}]},"unit":{"description":"Unit of measurement for the product","allOf":[{"$ref":"#/components/schemas/ProductUnit"}]},"designation":{"type":"string","description":"Name or title of the product"},"description":{"type":"string","nullable":true,"description":"Detailed description of the product"},"reference":{"type":"string","nullable":true,"description":"Product reference code"},"vatCode":{"description":"VAT code applicable to this product","allOf":[{"$ref":"#/components/schemas/VatCode"}]},"personalServiceActivity":{"nullable":true,"description":"Personal service activity classification, if applicable","allOf":[{"$ref":"#/components/schemas/PersonalServiceActivity"}]},"isDeliveryOfGood":{"type":"boolean","description":"Indicates if the product involves delivery of physical goods"},"taxesIncluded":{"type":"boolean","description":"Indicates if the prices include taxes"},"purchasePrice":{"type":"number","description":"Purchase price per unit without taxes"},"productMargin":{"type":"number","description":"Product margin"},"lockUnitPrice":{"type":"boolean","description":"Indicates if the unit price is locked"},"unitPrice":{"type":"number","description":"Price per unit without taxes"},"priceWithoutTaxes":{"type":"number","description":"Total price without taxes"},"vatAmount":{"type":"number","description":"VAT amount"},"priceWithTaxes":{"type":"number","description":"Total price including taxes"},"stock":{"type":"number","description":"Stock"}},"required":["id","type","unit","designation","vatCode","isDeliveryOfGood","taxesIncluded","unitPrice","priceWithoutTaxes","vatAmount","priceWithTaxes","stock"]},"PersonalServiceActivity":{"type":"string","enum":["GARDE_ENFANT_HANDICAPE","ACCOMPAGNEMENT_ENFANT_HANDICAPE","AIDE_HUMAINE","CONDUITE_VEHICULE_PERSONNEL","AIDE_AU_DEPLACEMENT","ENTRETIEN_DE_LA_MAISON","JARDINAGE","BRICOLAGE","GARDE_ENFANT_PLUS_DE_6_ANS","SOUTIEN_SCOLAIRE_COURS_A_DOMICILE","SOIN_ESTHETIQUE_A_DOMICILE","PREPARATION_REPAS_A_DOMICILE","LIVRAISON_REPAS_A_DOMICILE","COLLECTE_ET_LIVRAISON_DE_LINGE_REPASSE","LIVRAISON_COURSES_A_DOMICILE","ASSISTANCE_INFORMATIQUE","SOINS_ET_PROMENADES_ANIMAUX_DE_COMPAGNIE_POUR_PERSONNES_DEPENDANTES","MAINTENANCE_ENTRETIEN_ET_VIGILANCE_DE_LA_RESIDENCE_PRINCIPALE","ASSISTANCE_ADMINISTRATIVE","ACCOMPAGNEMENT_ENFANT_PLUS_DE_6_ANS","TELEASSISTANCE","INTERPRETE_LANGUE_DES_SIGNES","CONDUITE_VEHICULE_PERSONNEL_EN_CAS_INVALIDITE_TEMPORAIRE","ACCOMPAGNEMENT_DEPLACEMENTS_EN_DEHORS_DU_DOMICILE","ASSISTANCE_PERSONNES_TEMPORAIREMENT_DEPENDANTES_A_DOMICILE","COORDINATION_ET_GESTION","DIVERS_NON_ELIGIBLE"]}}},"paths":{"/v2/catalog/product":{"post":{"operationId":"CatalogController_create_v2","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProductDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadProductDto"}}}}},"summary":"Create a new product","tags":["catalog"]}}}}
```

### Corps de requête (`CreateProductDto`)

Champs requis :

* `type` : type de produit (ex: `service_delivery`)
* `unit` : unité de mesure (ex: `unit`)
* `designation` : libellé du produit

Champs optionnels :

* `amountInCents` : prix de vente en centimes
* `purchasePrice` : prix d'achat en centimes
* `productMargin` : marge en pourcentage
* `lockUnitPrice` : bloque le prix unitaire
* `taxesIncluded` : prix TTC si `true`
* `vatCode` : code TVA (défaut `FR_00HT`)
* `isDeliveryOfGood` : livraison d'un bien physique
* `description` : description détaillée (HTML nettoyé)
* `reference` : référence / SKU
* `stock` : stock disponible

### Valeurs possibles

Les champs `type` et `unit` attendent des **chaînes** (`string`) en `snake_case`.

#### `type` (ProductType)

* `sale_of_goods`
* `service_delivery`
* `commercial_or_craft_services`
* `sale_of_manufactured_goods`
* `disbursement`

#### `unit` (ProductUnit)

<details>

<summary>Voir toutes les valeurs</summary>

```
unit
gram
hour
day
week
fixed_rate
year
character
line
license
article
month
kilogram
kilometer
liter
batch
meter
square_meter
cubic_meter
linear_meter
person
ton
word
page
leaflet
paragraph
minute
overnight_stay
```

</details>

#### `vatCode` (VatCode)

Le champ `vatCode` attend une chaîne (`string`).

Valeurs disponibles :

* `FR_210`
* `FR_550`
* `FR_850`
* `FR_1000`
* `FR_2000`
* `FR_00HT` (défaut)
* `FR_00UE`
* `FR_0HUE`

#### Exemple

```json
{
  "type": "service_delivery",
  "unit": "unit",
  "designation": "Premium Widget",
  "amountInCents": 1999,
  "taxesIncluded": true,
  "vatCode": "FR_00HT",
  "isDeliveryOfGood": true,
  "description": "High-quality widget for various applications",
  "reference": "WIDGET-001",
  "stock": 20
}
```

## Mettre à jour un produit

> Le verbe HTTP est `PUT`. **Tous** les champs requis de `UpdateProductDto` doivent être envoyés à chaque appel (pas uniquement les champs modifiés), sinon ils seront écrasés ou refusés en validation.

## PUT /v2/catalog/product/{productId}

> Update a product

```json
{"openapi":"3.0.0","info":{"title":"Abby API","version":"1.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"UpdateProductDto":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/ProductType"}]},"unit":{"allOf":[{"$ref":"#/components/schemas/ProductUnit"}]},"designation":{"type":"string"},"amountInCents":{"type":"number","description":"The price of the product in cents"},"purchasePrice":{"type":"number","description":"The purchase price of the product in cents"},"productMargin":{"type":"number","description":"The margin of the product in percentage"},"lockUnitPrice":{"type":"boolean","description":"Whether the unit price is locked or not calculating from purchase price and product margin","default":false},"taxesIncluded":{"type":"boolean"},"vatCode":{"allOf":[{"$ref":"#/components/schemas/VatCode"}]},"isDeliveryOfGood":{"type":"boolean"},"description":{"type":"string"},"reference":{"type":"string"},"stock":{"type":"number"}},"required":["type","unit","designation","vatCode"]},"ProductType":{"type":"number","enum":[1,2,3,4,5]},"ProductUnit":{"type":"number","enum":[14,1,2,3,22,23,24,25,26,21,20,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,27,28]},"VatCode":{"type":"string","enum":["FR_210","FR_550","FR_850","FR_1000","FR_2000","FR_00HT","FR_00UE","FR_0HUE"]},"ReadProductDto":{"type":"object","properties":{"id":{"type":"string"},"type":{"description":"Type of the product","allOf":[{"$ref":"#/components/schemas/ProductType"}]},"unit":{"description":"Unit of measurement for the product","allOf":[{"$ref":"#/components/schemas/ProductUnit"}]},"designation":{"type":"string","description":"Name or title of the product"},"description":{"type":"string","nullable":true,"description":"Detailed description of the product"},"reference":{"type":"string","nullable":true,"description":"Product reference code"},"vatCode":{"description":"VAT code applicable to this product","allOf":[{"$ref":"#/components/schemas/VatCode"}]},"personalServiceActivity":{"nullable":true,"description":"Personal service activity classification, if applicable","allOf":[{"$ref":"#/components/schemas/PersonalServiceActivity"}]},"isDeliveryOfGood":{"type":"boolean","description":"Indicates if the product involves delivery of physical goods"},"taxesIncluded":{"type":"boolean","description":"Indicates if the prices include taxes"},"purchasePrice":{"type":"number","description":"Purchase price per unit without taxes"},"productMargin":{"type":"number","description":"Product margin"},"lockUnitPrice":{"type":"boolean","description":"Indicates if the unit price is locked"},"unitPrice":{"type":"number","description":"Price per unit without taxes"},"priceWithoutTaxes":{"type":"number","description":"Total price without taxes"},"vatAmount":{"type":"number","description":"VAT amount"},"priceWithTaxes":{"type":"number","description":"Total price including taxes"},"stock":{"type":"number","description":"Stock"}},"required":["id","type","unit","designation","vatCode","isDeliveryOfGood","taxesIncluded","unitPrice","priceWithoutTaxes","vatAmount","priceWithTaxes","stock"]},"PersonalServiceActivity":{"type":"string","enum":["GARDE_ENFANT_HANDICAPE","ACCOMPAGNEMENT_ENFANT_HANDICAPE","AIDE_HUMAINE","CONDUITE_VEHICULE_PERSONNEL","AIDE_AU_DEPLACEMENT","ENTRETIEN_DE_LA_MAISON","JARDINAGE","BRICOLAGE","GARDE_ENFANT_PLUS_DE_6_ANS","SOUTIEN_SCOLAIRE_COURS_A_DOMICILE","SOIN_ESTHETIQUE_A_DOMICILE","PREPARATION_REPAS_A_DOMICILE","LIVRAISON_REPAS_A_DOMICILE","COLLECTE_ET_LIVRAISON_DE_LINGE_REPASSE","LIVRAISON_COURSES_A_DOMICILE","ASSISTANCE_INFORMATIQUE","SOINS_ET_PROMENADES_ANIMAUX_DE_COMPAGNIE_POUR_PERSONNES_DEPENDANTES","MAINTENANCE_ENTRETIEN_ET_VIGILANCE_DE_LA_RESIDENCE_PRINCIPALE","ASSISTANCE_ADMINISTRATIVE","ACCOMPAGNEMENT_ENFANT_PLUS_DE_6_ANS","TELEASSISTANCE","INTERPRETE_LANGUE_DES_SIGNES","CONDUITE_VEHICULE_PERSONNEL_EN_CAS_INVALIDITE_TEMPORAIRE","ACCOMPAGNEMENT_DEPLACEMENTS_EN_DEHORS_DU_DOMICILE","ASSISTANCE_PERSONNES_TEMPORAIREMENT_DEPENDANTES_A_DOMICILE","COORDINATION_ET_GESTION","DIVERS_NON_ELIGIBLE"]}}},"paths":{"/v2/catalog/product/{productId}":{"put":{"operationId":"CatalogController_update_v2","parameters":[{"name":"productId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProductDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadProductDto"}}}}},"summary":"Update a product","tags":["catalog"]}}}}
```

### Paramètres de chemin

* `productId` : identifiant du produit à mettre à jour

### Corps de requête (`UpdateProductDto`)

Champs requis :

* `type` : type de produit (voir [valeurs](#type-producttype))
* `unit` : unité de mesure (voir [valeurs](#unit-productunit))
* `designation` : libellé du produit
* `vatCode` : code TVA (voir [valeurs](#vatcode-vatcode))

Champs optionnels :

* `amountInCents` : prix de vente en centimes
* `purchasePrice` : prix d'achat en centimes
* `productMargin` : marge en pourcentage
* `lockUnitPrice` : bloque le prix unitaire (défaut `false`)
* `taxesIncluded` : prix TTC si `true`
* `isDeliveryOfGood` : livraison d'un bien physique
* `description` : description détaillée (HTML nettoyé)
* `reference` : référence / SKU
* `stock` : stock disponible

#### Exemple

```json
{
  "type": "service_delivery",
  "unit": "unit",
  "designation": "Premium Widget",
  "amountInCents": 2499,
  "vatCode": "FR_00HT",
  "taxesIncluded": true,
  "isDeliveryOfGood": true,
  "description": "Updated description",
  "reference": "WIDGET-001",
  "stock": 15
}
```

### Réponse

Renvoie le produit mis à jour (`ReadProductDto`).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.abby.fr/api/produits.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
