## ADDED Requirements

### Requirement: Custom item matching by normalized name
When creating a lunch menu, the system SHALL match each `custom_items` entry to an existing, non-deleted lunch item by comparing `lower(trim(name))`. A matched entry SHALL attach the existing item to the menu; an unmatched entry SHALL create a new lunch item and attach it.

#### Scenario: Name matches an existing item ignoring case and surrounding spaces
- **WHEN** an existing item "Cơm gà" exists and the admin creates a menu with `custom_items: [{name: "  cơm GÀ "}]`
- **THEN** the menu is attached to the existing "Cơm gà" item and no new item is created

#### Scenario: Name matches only a soft-deleted item
- **WHEN** the only item named "Cơm gà" is soft-deleted and the admin creates a menu with `custom_items: [{name: "Cơm gà", price: 40000}]`
- **THEN** a new lunch item "Cơm gà" with price 40000 is created and attached to the menu

### Requirement: Existing item price is updated from custom items
When a `custom_items` entry matches an existing lunch item and its `price` is not null, the system SHALL update that lunch item's `price` to the given value before the menu is created.

#### Scenario: New price sent for an existing item
- **WHEN** item "Cơm gà" has price 35000 and the admin creates a menu with `custom_items: [{name: "Cơm gà", price: 40000}]`
- **THEN** item "Cơm gà" has price 40000 and the created menu lists it with price 40000

#### Scenario: Employee orders after the price change
- **WHEN** the menu above is available and an employee orders "Cơm gà"
- **THEN** the order's recorded `price` is 40000

#### Scenario: Existing orders keep their price
- **WHEN** an order for "Cơm gà" was placed at 35000 before the price was updated to 40000
- **THEN** that order's recorded `price` remains 35000

#### Scenario: Same item also sent via items by id
- **WHEN** item "Cơm gà" (id 5) has price 35000 and the admin creates a menu with `items: [{id: 5}]` and `custom_items: [{name: "Cơm gà", price: 40000}]`
- **THEN** item 5 has price 40000 and is attached to the menu exactly once

### Requirement: Missing price keeps the existing item price
When a `custom_items` entry matches an existing lunch item and its `price` is omitted or null, the system SHALL keep that item's current price and SHALL NOT apply `default_item_price`.

#### Scenario: Price omitted for an existing item
- **WHEN** item "Cơm gà" has price 35000 and the admin creates a menu with `custom_items: [{name: "Cơm gà"}]`
- **THEN** item "Cơm gà" still has price 35000

#### Scenario: Price omitted for a new item
- **WHEN** no item named "Bún bò" exists and the admin creates a menu with `custom_items: [{name: "Bún bò"}]`
- **THEN** a new item "Bún bò" is created with price equal to the `default_item_price` setting

### Requirement: Conflicting duplicate custom items are rejected
The system SHALL reject a create-menu request with a 422 validation error when two or more `custom_items` entries share the same `lower(trim(name))` but have different prices, where an omitted price counts as null and numeric values are compared by value. In that case the system SHALL NOT create the menu, create any item, or change any item price.

#### Scenario: Same name with different prices
- **WHEN** the admin creates a menu with `custom_items: [{name: "Cơm gà", price: 35000}, {name: " cơm gà", price: 40000}]`
- **THEN** the request fails with HTTP 422 and an error on the conflicting `custom_items` entry, and no menu or item is created or changed

#### Scenario: Same name, one entry without price
- **WHEN** the admin creates a menu with `custom_items: [{name: "Cơm gà", price: 40000}, {name: "Cơm gà"}]`
- **THEN** the request fails with HTTP 422

#### Scenario: Same name with the same price
- **WHEN** the admin creates a menu with `custom_items: [{name: "Cơm gà", price: 40000}, {name: "CƠM GÀ", price: 40000}]`
- **THEN** the request succeeds and "Cơm gà" is attached to the menu once with price 40000

### Requirement: Menu creation is atomic with item changes
The system SHALL create new items, update existing item prices, and create the menu with its item and account links in a single database transaction, so that if any step fails no item is created or repriced.

#### Scenario: Menu creation fails after item price update
- **WHEN** a create-menu request updates "Cơm gà" to 40000 and a later step in the same request throws an error
- **THEN** item "Cơm gà" keeps its previous price and no menu is created
