diff --git a/product-variant-assign-topping-description.md b/product-variant-assign-topping-description.md new file mode 100644 index 0000000..3ac408c --- /dev/null +++ b/product-variant-assign-topping-description.md @@ -0,0 +1,93 @@ +# Assign Topping To Product Variant API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to assign a topping to a specific product variant. + +The Assign Topping To Product Variant API assigns one topping to one product variant identified by product id and variant SKU. The API validates variant and topping existence, persists the assignment transactionally, appends an outbox event (`product.variant.topping.assigned`), and returns assignment details. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/products/{productId}/variants/{sku}/topping/{toppingId}/assign` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/products/{productId:long}/variants")]` +- **Action route:** `[HttpPost("{sku}/topping/{toppingId:long}/assign")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/products/{productId}/variants/{sku}/topping/{toppingId}/assign` +- **Path parameters:** `vendorId` (long), `productId` (long), `sku` (string), `toppingId` (long). +- **Request body:** none. + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier used for topping lookup. | +| `productId` | number | Yes | Product identifier used with SKU to find variant. | +| `sku` | string | Yes | Product variant SKU. | +| `toppingId` | number | Yes | Topping identifier to assign. | + +**Business rules:** +- Product variant must exist for `(productId, sku)`; otherwise request fails with not found. +- Topping must exist for `(vendorId, toppingId)`; otherwise request fails with not found. +- Assignment is saved transactionally and outbox event `product.variant.topping.assigned` is emitted. + +--- + +## Sample Request + +```http +POST /vendors/100/products/501/variants/VAR-901/topping/12345/assign +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/products/501/variants/VAR-901/topping/12345/assign" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "sku": "VAR-901", + "toppingId": 12345, + "assignedAt": "2026-03-18T12:15:00Z" +} +``` + +### Error - 404 / 400 / 409 / 500 + +- **404:** Product variant or topping not found. +- **400:** Validation error (for example invalid route parameter binding). +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while assigning topping to product variant. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping assigned to product variant successfully. | +| **404** | Product variant or topping not found. | +| **400** | Validation failure. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-activate-description.md b/topping-activate-description.md new file mode 100644 index 0000000..af6f52b --- /dev/null +++ b/topping-activate-description.md @@ -0,0 +1,109 @@ +# Activate Topping API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to activate a topping for a vendor. + +The Activate Topping API activates a topping by vendor and topping id. If the topping is already active, the API returns the current topping response without applying changes. If activation is needed, it updates the record, appends an outbox event (`topping.activated`), and returns the updated topping payload. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/toppings/{id}/activate` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpPost("{id:long}/activate")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/{id}/activate` +- **Path parameters:** `vendorId` (long), `id` (long). +- **Note:** `vendorId` and `id` from route are applied as source of truth and override request body values. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | number | Yes | Topping id in payload. Route `id` is applied as source of truth. | +| `vendorId` | number | Yes | Vendor id in payload. Route `vendorId` is applied as source of truth. | + +**Business rules:** +- Topping must exist for `(id, vendorId)`; otherwise request fails with not found. +- If `isActive` is already true, current topping response is returned immediately. +- If inactive, topping is activated and saved transactionally. +- Outbox event `topping.activated` is emitted when activation is applied. + +--- + +## Sample Request + +```http +POST /vendors/100/toppings/12345/activate +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "vendorId": 100 +} +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/toppings/12345/activate" \ + -H "Content-Type: application/json" \ + -d '{"id":12345,"vendorId":100}' +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "name": "Extra Cheese Premium", + "vendorId": 100, + "signature": "TOP-100-0012345", + "price": 30000, + "stock": 90, + "status": "Active", + "approvedBy": 7001, + "approvedAt": "2026-03-18T11:30:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": true +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** Topping id not found for vendor. +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while activating topping. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping activated successfully (or already active). | +| **400** | Validation failure. | +| **404** | Topping not found. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-approve-chef-description.md b/topping-approve-chef-description.md new file mode 100644 index 0000000..fa645b1 --- /dev/null +++ b/topping-approve-chef-description.md @@ -0,0 +1,112 @@ +# Approve Topping API (Chef Users) - Description + +This document is for **chef users** integrating with the Menu Management API to approve a pending (LQA) topping for a vendor. + +The Approve Topping API approves the pending topping version for the given topping id and vendor. If an active base version exists, it is deleted and replaced by the approved pending version. The API appends an outbox event (`topping.approved`) and returns the approved topping payload. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/toppings/{id}/approve` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpPost("{id:long}/approve")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/{id}/approve` +- **Path parameters:** `vendorId` (long), `id` (long). +- **Note:** `vendorId` and `id` from route are applied as source of truth and override request body values. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | number | Yes | Topping id in payload. Route `id` is applied as source of truth. | +| `vendorId` | number | Yes | Vendor id in payload. Route `vendorId` is applied as source of truth. | +| `agentUserId` | number | Yes | Chef/backoffice user id performing approval. | + +**Business rules:** +- System loads LQA records by `(vendorId, id)`. +- At least one record must exist; otherwise request fails with not found. +- A **Pending** LQA topping must exist for approval. +- If an **Active** base topping exists, it is deleted during the same transaction. +- Approved pending topping is updated and outbox event `topping.approved` is emitted. + +--- + +## Sample Request + +```http +POST /vendors/100/toppings/12345/approve +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "vendorId": 100, + "agentUserId": 7001 +} +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/toppings/12345/approve" \ + -H "Content-Type: application/json" \ + -d '{"id":12345,"vendorId":100,"agentUserId":7001}' +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "name": "Extra Cheese Premium", + "vendorId": 100, + "signature": "TOP-100-0012345", + "price": 30000, + "stock": 90, + "status": "Active", + "approvedBy": 7001, + "approvedAt": "2026-03-18T11:30:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": true +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** Topping id not found for vendor, or pending LQA topping not found. +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while approving topping. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping approved successfully. | +| **400** | Validation failure. | +| **404** | Topping or pending LQA record not found. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-assign-product-variants-description.md b/topping-assign-product-variants-description.md new file mode 100644 index 0000000..7376796 --- /dev/null +++ b/topping-assign-product-variants-description.md @@ -0,0 +1,115 @@ +# Assign Topping To Product Variants API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to assign a topping to product variants. + +The Assign Topping To Product Variants API updates the variant assignments for a topping. Existing assignments are removed first, then new assignments are applied based on request mode (`allProductVariants`, explicit `productVariants`, or `productId`). The API appends an outbox event (`topping.assigned`) and returns assigned variant data. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/toppings/{id}/assign` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpPost("{id:long}/assign")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/{id}/assign` +- **Path parameters:** `vendorId` (long), `id` (long). +- **Note:** `vendorId` and `id` from route are applied as source of truth and override request body values. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | number | Yes | Topping id in payload. Route `id` is applied as source of truth. | +| `vendorId` | number | Yes | Vendor id in payload. Route `vendorId` is applied as source of truth. | +| `productVariants` | array | No | Explicit product variant ids to assign when `allProductVariants` is false. | +| `allProductVariants` | boolean | Yes | If true, assign topping to all variants of the vendor. | +| `productId` | number | No | Assign topping to variants under this product when `allProductVariants` is false and `productVariants` is empty. | + +**Assignment mode priority (from handler):** +1. If `allProductVariants = true`: use all vendor variants. +2. Else if `productVariants` has values: use those variant ids. +3. Else if `productId` has value: use variants under that product. +4. Else: assign no variants (existing assignments are still removed). + +**Business rules:** +- Topping must exist for `(vendorId, id)`; otherwise request fails with not found. +- Existing topping-variant mappings are cleared before new assignment is applied. +- Outbox event `topping.assigned` is emitted with assigned variant SKU payload. + +--- + +## Sample Request + +```http +POST /vendors/100/toppings/12345/assign +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "vendorId": 100, + "productVariants": [901, 902, 903], + "allProductVariants": false, + "productId": null +} +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/toppings/12345/assign" \ + -H "Content-Type: application/json" \ + -d '{"id":12345,"vendorId":100,"productVariants":[901,902,903],"allProductVariants":false,"productId":null}' +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "name": "Extra Cheese Premium", + "vendorId": 100, + "productVariants": [ + "VAR-901", + "VAR-902", + "VAR-903" + ] +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** Topping id not found for vendor. +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while assigning topping to product variants. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping assignment applied successfully. | +| **400** | Validation failure. | +| **404** | Topping not found. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-categories-get-approved-description.md b/topping-categories-get-approved-description.md new file mode 100644 index 0000000..aa1169f --- /dev/null +++ b/topping-categories-get-approved-description.md @@ -0,0 +1,101 @@ +# Get Approved Topping Categories API - Description + +This document is for **backoffice developers** integrating with the Menu Management API to fetch approved topping categories for a vendor. + +The Get Approved Topping Categories API returns only topping categories that are already approved for the given vendor. It also supports an optional name filter. On success it returns **200 OK** with an array of `ApprovedToppingCategoryResponse` objects. If no approved records exist, the API returns an empty array. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/topping-categories/approved` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Path parameter:** `vendorId` (number) identifies the vendor whose approved topping categories are requested. +- **Query parameter:** `name` (optional string) filters approved categories by name. + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | + +### Query parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `name` | string | No | Optional text filter passed to repository query. | + +--- + +## Sample Request + +```http +GET /vendors/100/topping-categories/approved?name=sauce +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/topping-categories/approved?name=sauce" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +[ + { + "id": 98766, + "name": "Sauces", + "vendorId": 100, + "isRequired": true, + "maxSelect": 1, + "status": "Approved", + "approvedBy": 3001, + "approvedAt": "2026-03-18T07:45:00Z" + }, + { + "id": 98767, + "name": "Cheese Add-ons", + "vendorId": 100, + "isRequired": false, + "maxSelect": 2, + "status": "Approved", + "approvedBy": 3002, + "approvedAt": "2026-03-18T08:00:00Z" + } +] +``` + +### Error - 400 / 500 + +- **400:** Validation error (for example invalid route/query parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Approved topping categories fetched successfully (possibly empty list). | +| **400** | Validation failure. | +| **500** | Server error. | diff --git a/topping-categories-get-description.md b/topping-categories-get-description.md new file mode 100644 index 0000000..e4fba6f --- /dev/null +++ b/topping-categories-get-description.md @@ -0,0 +1,102 @@ +# Get Topping Categories API - Description + +This document is for **backoffice developers** integrating with the Menu Management API to fetch topping categories for a vendor. + +The Get Topping Categories API returns the list of topping categories for a given vendor. On success it returns **200 OK** with an array of `ToppingCategoryResponse` objects. If no records exist, the API returns an empty array. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/topping-categories` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Path parameter:** `vendorId` (number) identifies the vendor whose topping categories are requested. + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | + +--- + +## Sample Request + +```http +GET /vendors/100/topping-categories +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/topping-categories" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +[ + { + "id": 98765, + "signature": "TCAT-100-00098765", + "name": "Pizza Toppings", + "vendorId": 100, + "isRequired": false, + "maxSelect": 3, + "status": "Pending", + "approvedBy": null, + "approvedAt": null, + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null + }, + { + "id": 98766, + "signature": "TCAT-100-00098766", + "name": "Sauces", + "vendorId": 100, + "isRequired": true, + "maxSelect": 1, + "status": "Approved", + "approvedBy": 3001, + "approvedAt": "2026-03-18T07:45:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null + } +] +``` + +### Error - 400 / 500 + +- **400:** Validation error (for example invalid route parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping categories fetched successfully (possibly empty list). | +| **400** | Validation failure. | +| **500** | Server error. | diff --git a/topping-categories-get-pending-description.md b/topping-categories-get-pending-description.md new file mode 100644 index 0000000..0c4dd30 --- /dev/null +++ b/topping-categories-get-pending-description.md @@ -0,0 +1,99 @@ +# Get Pending Topping Categories API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to fetch pending topping categories for a vendor. + +The Get Pending Topping Categories API returns only pending topping categories for the given vendor. It also supports an optional name filter. On success it returns **200 OK** with an array of `ToppingCategoryResponse` objects. If no records match, the API returns an empty array. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/topping-categories/pending` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/topping-categories")]` +- **Action route:** `[HttpGet("pending")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/topping-categories/pending` +- **Path parameter:** `vendorId` (long). +- **Query parameter:** `name` (optional string) for filtering pending topping categories by name. + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | + +### Query parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `name` | string | No | Optional text filter passed to repository query. | + +--- + +## Sample Request + +```http +GET /vendors/100/topping-categories/pending?name=sauce +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/topping-categories/pending?name=sauce" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +[ + { + "id": 98765, + "signature": "TCAT-100-00098765", + "name": "Pizza Toppings", + "vendorId": 100, + "isRequired": false, + "maxSelect": 3, + "status": "Pending", + "approvedBy": null, + "approvedAt": null, + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": true + } +] +``` + +### Error - 400 / 500 + +- **400:** Validation error (for example invalid route/query parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Pending topping categories fetched successfully (possibly empty list). | +| **400** | Validation failure. | +| **500** | Server error. | diff --git a/topping-category-activate-description.md b/topping-category-activate-description.md new file mode 100644 index 0000000..e02eabe --- /dev/null +++ b/topping-category-activate-description.md @@ -0,0 +1,109 @@ +# Activate Topping Category API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to activate a topping category for a vendor. + +The Activate Topping Category API activates a topping category by vendor and category id. If the topping category is already active, the API returns the current category response without applying changes. If activation is needed, it updates the record, appends an outbox event (`topping.category.activated`), and returns the updated topping category payload. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/topping-categories/{id}/activate` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/topping-categories")]` +- **Action route:** `[HttpPost("{id:long}/activate")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/topping-categories/{id}/activate` +- **Path parameters:** `vendorId` (long), `id` (long). +- **Note:** `vendorId` and `id` from route are applied as source of truth and override request body values. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor id in payload. Route `vendorId` is applied as source of truth. | +| `id` | number | Yes | Topping category id in payload. Route `id` is applied as source of truth. | + +**Business rules:** +- Topping category must exist for `(vendorId, id)`; otherwise request fails with not found. +- If `isActive` is already true, current topping category response is returned immediately. +- If inactive, category is activated and saved transactionally. +- Outbox event `topping.category.activated` is emitted when activation is applied. + +--- + +## Sample Request + +```http +POST /vendors/100/topping-categories/98765/activate +Content-Type: application/json +``` + +```json +{ + "vendorId": 100, + "id": 98765 +} +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/topping-categories/98765/activate" \ + -H "Content-Type: application/json" \ + -d '{"vendorId":100,"id":98765}' +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 98765, + "signature": "TCAT-100-00098765", + "name": "Pizza Toppings", + "vendorId": 100, + "isRequired": false, + "maxSelect": 3, + "status": "Approved", + "approvedBy": 7001, + "approvedAt": "2026-03-18T11:30:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": true +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** Topping category id not found for vendor. +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while activating topping category. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping category activated successfully (or already active). | +| **400** | Validation failure. | +| **404** | Topping category not found. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-category-deactivate-description.md b/topping-category-deactivate-description.md new file mode 100644 index 0000000..eb4df6d --- /dev/null +++ b/topping-category-deactivate-description.md @@ -0,0 +1,109 @@ +# Deactivate Topping Category API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to deactivate a topping category for a vendor. + +The Deactivate Topping Category API deactivates a topping category by vendor and category id. If the topping category is already inactive, the API returns the current category response without applying changes. If deactivation is needed, it updates the record, appends an outbox event (`topping.category.deactivated`), and returns the updated topping category payload. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/topping-categories/{id}/deactivate` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/topping-categories")]` +- **Action route:** `[HttpPost("{id:long}/deactivate")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/topping-categories/{id}/deactivate` +- **Path parameters:** `vendorId` (long), `id` (long). +- **Note:** `vendorId` and `id` from route are applied as source of truth and override request body values. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor id in payload. Route `vendorId` is applied as source of truth. | +| `id` | number | Yes | Topping category id in payload. Route `id` is applied as source of truth. | + +**Business rules:** +- Topping category must exist for `(vendorId, id)`; otherwise request fails with not found. +- If `isActive` is already false, current topping category response is returned immediately. +- If active, category is deactivated and saved transactionally. +- Outbox event `topping.category.deactivated` is emitted when deactivation is applied. + +--- + +## Sample Request + +```http +POST /vendors/100/topping-categories/98765/deactivate +Content-Type: application/json +``` + +```json +{ + "vendorId": 100, + "id": 98765 +} +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/topping-categories/98765/deactivate" \ + -H "Content-Type: application/json" \ + -d '{"vendorId":100,"id":98765}' +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 98765, + "signature": "TCAT-100-00098765", + "name": "Pizza Toppings", + "vendorId": 100, + "isRequired": false, + "maxSelect": 3, + "status": "Approved", + "approvedBy": 7001, + "approvedAt": "2026-03-18T11:30:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": false +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** Topping category id not found for vendor. +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while deactivating topping category. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping category deactivated successfully (or already inactive). | +| **400** | Validation failure. | +| **404** | Topping category not found. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-category-get-by-id-description.md b/topping-category-get-by-id-description.md new file mode 100644 index 0000000..c7a3fd4 --- /dev/null +++ b/topping-category-get-by-id-description.md @@ -0,0 +1,96 @@ +# Get Topping Category By Id API - Description + +This document is for **backoffice developers** integrating with the Menu Management API to fetch a single topping category by id for a vendor. + +The Get Topping Category By Id API returns one topping category record scoped by vendor and category id. It can also accept an optional `name` query filter. On success it returns **200 OK** with a `ToppingCategoryResponse` payload. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/topping-categories/{id}` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Path parameters:** `vendorId` (number) and `id` (number) identify the requested topping category. +- **Query parameter:** `name` (optional string) filter. + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | +| `id` | number | Yes | Topping category identifier. | + +### Query parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `name` | string | No | Optional name filter. | + +--- + +## Sample Request + +```http +GET /vendors/100/topping-categories/98765?name=Sauces +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/topping-categories/98765?name=Sauces" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 98765, + "signature": "TCAT-100-00098765", + "name": "Pizza Toppings", + "vendorId": 100, + "isRequired": false, + "maxSelect": 3, + "status": "Approved", + "approvedBy": 3001, + "approvedAt": "2026-03-18T07:45:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null +} +``` + +### Error - 404 / 400 / 500 + +- **404:** Topping category not found for the provided id/vendor scope. +- **400:** Validation error (for example invalid route/query parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping category fetched successfully. | +| **404** | Topping category not found. | +| **400** | Validation failure. | +| **500** | Server error. | diff --git a/topping-category-reject-description.md b/topping-category-reject-description.md new file mode 100644 index 0000000..6eb0f44 --- /dev/null +++ b/topping-category-reject-description.md @@ -0,0 +1,108 @@ +# Reject Topping Category API - Description + +This document is for **backoffice developers** integrating with the Menu Management API to reject a pending topping category record for a vendor. + +The Reject Topping Category API marks a pending topping category as **Rejected**, stores the rejection metadata (agent and reason), and publishes an outbox event (`topping.category.rejected`). On success it returns **200 OK** with the updated topping category payload. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/topping-categories/{id}/reject` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Path parameter:** `vendorId` (number) is used as the effective vendor identifier. +- **Note:** `vendorId` from route is used by the handler and overrides `vendorId` sent in request body. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `signature` | string | Yes | Topping category signature used to locate the LQA record. | +| `vendorId` | number | Yes | Vendor identifier in payload. Route `vendorId` is applied as source of truth. | +| `agentUserId` | number | Yes | Backoffice agent user id performing the rejection. | +| `rejectReason` | string | Yes | Human-readable reason for rejection. | + +**Business rules:** +- The system searches by `(vendorId from route, signature)`. +- A matching topping category record must exist; otherwise the request fails. +- The record must be in **Pending** status to be rejected. + +--- + +## Sample Request + +```http +POST /vendors/100/topping-categories/98765/reject +Content-Type: application/json +``` + +```json +{ + "signature": "TCAT-100-00098765", + "vendorId": 100, + "agentUserId": 5012, + "rejectReason": "Category name conflicts with vendor taxonomy" +} +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/topping-categories/98765/reject" \ + -H "Content-Type: application/json" \ + -d '{"signature":"TCAT-100-00098765","vendorId":100,"agentUserId":5012,"rejectReason":"Category name conflicts with vendor taxonomy"}' +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 98765, + "signature": "TCAT-100-00098765", + "name": "Pizza Toppings", + "vendorId": 100, + "isRequired": false, + "maxSelect": 3, + "status": "Rejected", + "approvedBy": null, + "approvedAt": null, + "rejectedBy": 5012, + "rejectedAt": "2026-03-18T10:20:30Z", + "rejectionReason": "Category name conflicts with vendor taxonomy" +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** No matching topping category found for `(vendorId, signature)`. +- **409:** Concurrency conflict during transactional update. +- **500:** Unexpected server error while rejecting topping category. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping category rejected successfully. | +| **400** | Validation failure. | +| **404** | Topping category signature not found for vendor. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-create-description.md b/topping-create-description.md new file mode 100644 index 0000000..d1ce342 --- /dev/null +++ b/topping-create-description.md @@ -0,0 +1,122 @@ +# Create Topping API - Description + +This document is for **backoffice developers** integrating with the Menu Management API to create a topping record for a vendor. + +The Create Topping API submits a new topping and returns the created entity details. The API validates vendor existence, validates topping category existence, persists the topping in a transaction, and appends an outbox event (`topping.created`). On success it returns **201 Created** with the topping payload and a `Location` header pointing to GetOne. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/toppings` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Controller route:** `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpPost]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings` +- **Path parameter:** `vendorId` (long) is used as the effective vendor identifier. +- **Note:** `vendorId` from route is used by the handler and overrides `vendorId` sent in request body. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier in payload. Route `vendorId` is applied as source of truth. | +| `sku` | number | Yes | SKU identifier for the topping. | +| `name` | string | Yes | Topping name. | +| `toppingCategoryId` | number | Yes | Target topping category id. Must exist. | +| `price` | number | Yes | Topping price amount (Toman). | +| `taxIncluded` | boolean | Yes | Whether the price is tax-inclusive. | +| `stock` | number | Yes | Current stock amount. | +| `tax` | decimal | Yes | Tax value for the topping. | + +**Business rules:** +- Vendor must exist; otherwise request fails with not found. +- Topping category must exist; otherwise request fails with not found. +- Record is created transactionally and an outbox event (`topping.created`) is emitted. + +--- + +## Sample Request + +```http +POST /vendors/100/toppings +Content-Type: application/json +``` + +```json +{ + "vendorId": 100, + "sku": 200001, + "name": "Extra Cheese", + "toppingCategoryId": 98766, + "price": 25000, + "taxIncluded": true, + "stock": 120, + "tax": 0.09 +} +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/toppings" \ + -H "Content-Type: application/json" \ + -d '{"vendorId":100,"sku":200001,"name":"Extra Cheese","toppingCategoryId":98766,"price":25000,"taxIncluded":true,"stock":120,"tax":0.09}' +``` + +--- + +## Responses + +### Success - 201 Created + +```http +HTTP/1.1 201 Created +Location: /vendors/100/toppings/12345 +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "name": "Extra Cheese", + "vendorId": 100, + "signature": "TOP-100-0012345", + "price": 25000, + "tax": 0.09, + "stock": 120, + "status": "Pending", + "approvedBy": null, + "approvedAt": null, + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** Vendor or topping category not found. +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while creating topping. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **201** | Topping created successfully. | +| **400** | Validation failure. | +| **404** | Vendor or topping category not found. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-deactive-description.md b/topping-deactive-description.md new file mode 100644 index 0000000..2c9fe46 --- /dev/null +++ b/topping-deactive-description.md @@ -0,0 +1,109 @@ +# DeActive Topping API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to deactivate a topping for a vendor. + +The DeActive Topping API deactivates a topping by vendor and topping id. If the topping is already inactive, the API returns the current topping response without applying changes. If deactivation is needed, it updates the record, appends an outbox event (`topping.deactivated`), and returns the updated topping payload. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/toppings/{id}/deActive` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpPost("{id:long}/deActive")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/{id}/deActive` +- **Path parameters:** `vendorId` (long), `id` (long). +- **Note:** `vendorId` and `id` from route are applied as source of truth and override request body values. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | number | Yes | Topping id in payload. Route `id` is applied as source of truth. | +| `vendorId` | number | Yes | Vendor id in payload. Route `vendorId` is applied as source of truth. | + +**Business rules:** +- Topping must exist for `(id, vendorId)`; otherwise request fails with not found. +- If `isActive` is already false, current topping response is returned immediately. +- If active, topping is deactivated and saved transactionally. +- Outbox event `topping.deactivated` is emitted when deactivation is applied. + +--- + +## Sample Request + +```http +POST /vendors/100/toppings/12345/deActive +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "vendorId": 100 +} +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/toppings/12345/deActive" \ + -H "Content-Type: application/json" \ + -d '{"id":12345,"vendorId":100}' +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "name": "Extra Cheese Premium", + "vendorId": 100, + "signature": "TOP-100-0012345", + "price": 30000, + "stock": 90, + "status": "Active", + "approvedBy": 7001, + "approvedAt": "2026-03-18T11:30:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": false +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** Topping id not found for vendor. +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while deactivating topping. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping deactivated successfully (or already inactive). | +| **400** | Validation failure. | +| **404** | Topping not found. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-delete-description.md b/topping-delete-description.md new file mode 100644 index 0000000..fb43cee --- /dev/null +++ b/topping-delete-description.md @@ -0,0 +1,86 @@ +# Delete Topping API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to delete a topping for a vendor. + +The Delete Topping API performs a logical delete on the topping record for the given vendor and id, appends an outbox event (`topping.deleted`), and commits the change transactionally. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `DELETE` | `/vendors/{vendorId}/toppings/{id}` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpDelete("{id:long}")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/{id}` +- **Path parameters:** `vendorId` (long), `id` (long). + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | +| `id` | number | Yes | Topping identifier. | + +**Business rules:** +- Topping must exist for `(id, vendorId)`; otherwise request fails with not found. +- Delete operation is logical (`topping.Delete()`), then persisted. +- Outbox event `topping.deleted` is emitted in the same transaction. + +--- + +## Sample Request + +```http +DELETE /vendors/100/toppings/12345 +``` + +### cURL example + +```bash +curl -X DELETE "{baseUrl}/vendors/100/toppings/12345" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{} +``` + +### Error - 404 / 400 / 409 / 500 + +- **404:** Topping id not found for vendor. +- **400:** Validation error (for example invalid route parameter binding). +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while deleting topping. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping deleted successfully. | +| **404** | Topping not found. | +| **400** | Validation failure. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-get-approved-description.md b/topping-get-approved-description.md new file mode 100644 index 0000000..52c2c86 --- /dev/null +++ b/topping-get-approved-description.md @@ -0,0 +1,105 @@ +# Get Approved Toppings API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to fetch approved toppings for a vendor. + +The Get Approved Toppings API returns only approved toppings for the given vendor. It also supports an optional name filter. On success it returns **200 OK** with an array of `ToppingResponse` objects. If no records match, the API returns an empty array. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/toppings/approved` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpGet("approved")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/approved` +- **Path parameter:** `vendorId` (long). +- **Query parameter:** `name` (optional string) for filtering approved toppings by name. + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | + +### Query parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `name` | string | No | Optional text filter passed to repository query. | + +--- + +## Sample Request + +```http +GET /vendors/100/toppings/approved?name=cheese +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/toppings/approved?name=cheese" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +[ + { + "id": 12345, + "name": "Extra Cheese Premium", + "vendorId": 100, + "signature": "TCAT-100-00098766", + "price": 30000, + "stock": 90, + "status": "Approved", + "approvedBy": 7001, + "approvedAt": "2026-03-18T11:30:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": true + } +] +``` + +### Error - 400 / 500 + +- **400:** Validation error (for example invalid route/query parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Approved toppings fetched successfully (possibly empty list). | +| **400** | Validation failure. | +| **500** | Server error. | + +--- + +## Implementation note + +- Current handler maps `ToppingResponse.signature` from `topping.ToppingCategorySignature.Value` in `PrepareResponse`. diff --git a/topping-get-by-category-description.md b/topping-get-by-category-description.md new file mode 100644 index 0000000..48abcd5 --- /dev/null +++ b/topping-get-by-category-description.md @@ -0,0 +1,106 @@ +# Get Toppings By Category API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to fetch toppings by category for a vendor. + +The Get Toppings By Category API returns toppings for the given vendor and category signature. It also supports an optional name filter. On success it returns **200 OK** with an array of `ToppingResponse` objects. If no records match, the API returns an empty array. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/toppings/category/{signature}` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpGet("category/{signature}")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/category/{signature}` +- **Path parameters:** `vendorId` (long), `signature` (string). +- **Query parameter:** `name` (optional string) for filtering toppings by name. + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | +| `signature` | string | Yes | Topping category signature used to filter toppings. | + +### Query parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `name` | string | No | Optional text filter passed to repository query. | + +--- + +## Sample Request + +```http +GET /vendors/100/toppings/category/TCAT-100-00098766?name=cheese +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/toppings/category/TCAT-100-00098766?name=cheese" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +[ + { + "id": 12345, + "name": "Extra Cheese Premium", + "vendorId": 100, + "signature": "TCAT-100-00098766", + "price": 30000, + "stock": 90, + "status": "Approved", + "approvedBy": 7001, + "approvedAt": "2026-03-18T11:30:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": true + } +] +``` + +### Error - 400 / 500 + +- **400:** Validation error (for example invalid route/query parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Toppings fetched successfully (possibly empty list). | +| **400** | Validation failure. | +| **500** | Server error. | + +--- + +## Implementation note + +- Current handler maps `ToppingResponse.signature` from `topping.ToppingCategorySignature.Value` in `PrepareResponse`. diff --git a/topping-get-description.md b/topping-get-description.md new file mode 100644 index 0000000..bd0b5ae --- /dev/null +++ b/topping-get-description.md @@ -0,0 +1,99 @@ +# Get Topping API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to fetch a single topping by vendor and topping id. + +The Get Topping API returns one topping record scoped by vendor and topping id. On success it returns **200 OK** with a `ToppingResponse` payload. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/toppings/{id}` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpGet("{id:long}")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/{id}` +- **Path parameters:** `vendorId` (long), `id` (long). + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | +| `id` | number | Yes | Topping identifier. | + +--- + +## Sample Request + +```http +GET /vendors/100/toppings/12345 +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/toppings/12345" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "name": "Extra Cheese Premium", + "vendorId": 100, + "signature": "TCAT-100-00098766", + "price": 30000, + "tax": 0.09, + "stock": 90, + "status": "Active", + "approvedBy": 7001, + "approvedAt": "2026-03-18T11:30:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null +} +``` + +### Error - 404 / 400 / 500 + +- **404:** Topping not found for the provided `(id, vendorId)`. +- **400:** Validation error (for example invalid route parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping fetched successfully. | +| **404** | Topping not found. | +| **400** | Validation failure. | +| **500** | Server error. | + +--- + +## Implementation note + +- Current handler maps `ToppingResponse.signature` from `topping.ToppingCategorySignature.Value` in `PrepareResponse`. diff --git a/topping-get-pending-description.md b/topping-get-pending-description.md new file mode 100644 index 0000000..8296cfd --- /dev/null +++ b/topping-get-pending-description.md @@ -0,0 +1,105 @@ +# Get Pending Toppings API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to fetch pending toppings for a vendor. + +The Get Pending Toppings API returns only pending toppings for the given vendor. It also supports an optional name filter. On success it returns **200 OK** with an array of `ToppingResponse` objects. If no records match, the API returns an empty array. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/toppings/pending` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpGet("pending")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/pending` +- **Path parameter:** `vendorId` (long). +- **Query parameter:** `name` (optional string) for filtering pending toppings by name. + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | + +### Query parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `name` | string | No | Optional text filter passed to repository query. | + +--- + +## Sample Request + +```http +GET /vendors/100/toppings/pending?name=cheese +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/toppings/pending?name=cheese" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +[ + { + "id": 12346, + "name": "Spicy Sauce", + "vendorId": 100, + "signature": "TCAT-100-00098767", + "price": 15000, + "stock": 70, + "status": "Pending", + "approvedBy": null, + "approvedAt": null, + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": true + } +] +``` + +### Error - 400 / 500 + +- **400:** Validation error (for example invalid route/query parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Pending toppings fetched successfully (possibly empty list). | +| **400** | Validation failure. | +| **500** | Server error. | + +--- + +## Implementation note + +- Current handler maps `ToppingResponse.signature` from `topping.ToppingCategorySignature.Value` in `PrepareResponse`. diff --git a/topping-get-variants-description.md b/topping-get-variants-description.md new file mode 100644 index 0000000..3e93760 --- /dev/null +++ b/topping-get-variants-description.md @@ -0,0 +1,92 @@ +# Get Topping Variants API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to fetch product variants assigned to a topping. + +The Get Topping Variants API retrieves a topping by vendor and id, then returns the list of assigned product variants for that topping signature. On success it returns **200 OK** with an array of `ToppingVariantResponse` objects. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/toppings/{id}/variants` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpGet("{id:long}/variants")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/{id}/variants` +- **Path parameters:** `vendorId` (long), `id` (long). + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | +| `id` | number | Yes | Topping identifier. | + +**Business rules:** +- Topping must exist for `(vendorId, id)`; otherwise request fails with not found. +- Variants are loaded by topping signature from the resolved topping record. + +--- + +## Sample Request + +```http +GET /vendors/100/toppings/12345/variants +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/toppings/12345/variants" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +[ + { + "sku": "VAR-901", + "name": "Large Pizza" + }, + { + "sku": "VAR-902", + "name": "Medium Pizza" + } +] +``` + +### Error - 404 / 400 / 500 + +- **404:** Topping id not found for vendor. +- **400:** Validation error (for example invalid route parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping variants fetched successfully (possibly empty list). | +| **404** | Topping not found. | +| **400** | Validation failure. | +| **500** | Server error. | diff --git a/topping-get-vendor-product-description.md b/topping-get-vendor-product-description.md new file mode 100644 index 0000000..64e0ecf --- /dev/null +++ b/topping-get-vendor-product-description.md @@ -0,0 +1,107 @@ +# Get Vendor Product Toppings API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to fetch all toppings for a vendor. + +The Get Vendor Product Toppings API returns the topping list for a given vendor. On success it returns **200 OK** with an array of `ToppingResponse` objects. If no toppings exist, the API returns an empty array. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `GET` | `/vendors/{vendorId}/toppings` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpGet]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings` +- **Path parameter:** `vendorId` (long). + +--- + +## Request + +This endpoint does not require a request body. + +### Path parameter reference + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier. | + +--- + +## Sample Request + +```http +GET /vendors/100/toppings +``` + +### cURL example + +```bash +curl -X GET "{baseUrl}/vendors/100/toppings" \ + -H "Accept: application/json" +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +[ + { + "id": 12345, + "name": "Extra Cheese Premium", + "vendorId": 100, + "signature": "TOP-100-0012345", + "price": 30000, + "tax": 0.09, + "stock": 90, + "status": "Active", + "approvedBy": 7001, + "approvedAt": "2026-03-18T11:30:00Z", + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null + }, + { + "id": 12346, + "name": "Spicy Sauce", + "vendorId": 100, + "signature": "TOP-100-0012346", + "price": 15000, + "tax": 0.09, + "stock": 70, + "status": "Pending", + "approvedBy": null, + "approvedAt": null, + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null + } +] +``` + +### Error - 400 / 500 + +- **400:** Validation error (for example invalid route parameter binding). +- **500:** Unexpected server error. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping list fetched successfully (possibly empty list). | +| **400** | Validation failure. | +| **500** | Server error. | diff --git a/topping-reject-description.md b/topping-reject-description.md new file mode 100644 index 0000000..0019306 --- /dev/null +++ b/topping-reject-description.md @@ -0,0 +1,113 @@ +# Reject Topping API - Description + +This document is for **backoffice and chef users** integrating with the Menu Management API to reject a pending (LQA) topping for a vendor. + +The Reject Topping API rejects the pending topping version for the given topping id and vendor, stores rejection metadata (agent and reason), appends an outbox event (`topping.rejected`), and returns the updated topping payload. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `POST` | `/vendors/{vendorId}/toppings/{id}/reject` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpPost("{id:long}/reject")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/{id}/reject` +- **Path parameters:** `vendorId` (long), `id` (long). +- **Important mapping note:** current action method maps `vendorId` from route but does **not** map route `id` into method parameters; request processing uses `body.id`. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | number | Yes | Topping id used in command payload. | +| `vendorId` | number | Yes | Vendor id in payload. Route `vendorId` is applied as source of truth. | +| `agentUserId` | number | Yes | User id performing rejection. | +| `rejectReason` | string | Yes | Human-readable rejection reason. | + +**Business rules:** +- System loads LQA records by `(vendorId, id)`. +- At least one record must exist; otherwise request fails with not found. +- A **Pending** LQA topping record is selected and rejected. +- Rejected record is saved transactionally and outbox event `topping.rejected` is emitted. + +--- + +## Sample Request + +```http +POST /vendors/100/toppings/12345/reject +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "vendorId": 100, + "agentUserId": 7002, + "rejectReason": "Price policy mismatch" +} +``` + +### cURL example + +```bash +curl -X POST "{baseUrl}/vendors/100/toppings/12345/reject" \ + -H "Content-Type: application/json" \ + -d '{"id":12345,"vendorId":100,"agentUserId":7002,"rejectReason":"Price policy mismatch"}' +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 12345, + "name": "Extra Cheese Premium", + "vendorId": 100, + "signature": "TOP-100-0012345", + "price": 30000, + "tax": 0.09, + "stock": 90, + "status": "Rejected", + "approvedBy": null, + "approvedAt": null, + "rejectedBy": 7002, + "rejectedAt": "2026-03-18T11:55:00Z", + "rejectionReason": "Price policy mismatch" +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** Topping id not found for vendor. +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while rejecting topping. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping rejected successfully. | +| **400** | Validation failure. | +| **404** | Topping not found. | +| **409** | Concurrency conflict. | +| **500** | Server error. | diff --git a/topping-update-description.md b/topping-update-description.md new file mode 100644 index 0000000..851bb7c --- /dev/null +++ b/topping-update-description.md @@ -0,0 +1,114 @@ +# Update Topping API - Description + +This document is for **backoffice developers** integrating with the Menu Management API to update a topping record for a vendor. + +The Update Topping API receives an existing topping id and creates an updated LQA version of that topping using the provided fields. The handler resolves the topping category from the existing topping category signature to obtain tax percent, appends an outbox event (`topping.lqa.added`), and returns the updated topping payload. On success it returns **200 OK**. + +--- + +## Endpoint + +| Method | Path | Content-Type | +|--------|------|--------------| +| `PUT` | `/vendors/{vendorId}/toppings/{id}` | `application/json` | + +- **Base URL:** Use your environment base URL. +- **Controller attributes:** `[ApiController]` and `[Route("vendors/{vendorId:long}/toppings")]` +- **Action route:** `[HttpPut("{id:long}")]` +- **Resolved endpoint path:** `/vendors/{vendorId}/toppings/{id}` +- **Path parameters:** `vendorId` (long), `id` (long). +- **Note:** `vendorId` from route is used by the handler and overrides `vendorId` sent in request body. + +--- + +## Request Body + +### Field reference + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `vendorId` | number | Yes | Vendor identifier in payload. Route `vendorId` is applied as source of truth. | +| `name` | string | Yes | Topping name. | +| `price` | number | Yes | Topping price amount (Toman). | +| `stock` | number | Yes | Current stock amount. | + +**Business rules:** +- The base topping must exist for `(id, vendorId)`; otherwise request fails with not found. +- The topping category for the current topping signature must exist; otherwise request fails with not found. +- Update flow creates a new LQA topping version from existing signature/sku/vendor and request fields. +- Tax percent is derived from topping category (`TaxPercent`) during creation of the new LQA topping. +- Outbox event `topping.lqa.added` is emitted transactionally. + +--- + +## Sample Request + +```http +PUT /vendors/100/toppings/12345 +Content-Type: application/json +``` + +```json +{ + "vendorId": 100, + "name": "Extra Cheese Premium", + "price": 30000, + "stock": 90 +} +``` + +### cURL example + +```bash +curl -X PUT "{baseUrl}/vendors/100/toppings/12345" \ + -H "Content-Type: application/json" \ + -d '{"vendorId":100,"name":"Extra Cheese Premium","price":30000,"stock":90}' +``` + +--- + +## Responses + +### Success - 200 OK + +```http +HTTP/1.1 200 OK +Content-Type: application/json +``` + +```json +{ + "id": 12401, + "name": "Extra Cheese Premium", + "vendorId": 100, + "signature": "TOP-100-0012345", + "price": 30000, + "stock": 90, + "status": "Pending", + "approvedBy": null, + "approvedAt": null, + "rejectedBy": null, + "rejectedAt": null, + "rejectionReason": null, + "isActive": false +} +``` + +### Error - 400 / 404 / 409 / 500 + +- **400:** Validation error (invalid payload). +- **404:** Topping not found for provided `id` and `vendorId`, or related topping category not found. +- **409:** Concurrency conflict during transactional save. +- **500:** Unexpected server error while updating topping. + +--- + +## Status codes summary + +| Code | Meaning | +|------|---------| +| **200** | Topping update accepted and returned. | +| **400** | Validation failure. | +| **404** | Topping not found. | +| **409** | Concurrency conflict. | +| **500** | Server error. |