# product-expiry-tracking Specification

## Purpose

Capturing each product's expiry date and promotion note, and surfacing that information where it matters: two-tier expiry highlighting and an expiry filter on the product list, plus promotion and near-expiry warnings at the POS.

## Requirements

### Requirement: Product expiry date and promotion note capture
The system SHALL allow an optional expiry date and an optional promotion note to be recorded for each product, on both the product creation and product edit forms.

#### Scenario: Admin sets expiry date and promotion note when creating a product
- **WHEN** an admin fills the product creation form with an expiry date and a promotion note and submits it
- **THEN** the new product is persisted with the given `expiry_date` and `promotion_note` values

#### Scenario: Admin updates expiry date and promotion note on an existing product
- **WHEN** an admin edits a product's expiry date and/or promotion note and saves
- **THEN** the product's `expiry_date` and `promotion_note` are updated accordingly

#### Scenario: Expiry date and promotion note are optional
- **WHEN** an admin creates or updates a product without providing an expiry date or a promotion note
- **THEN** the product is saved successfully with `expiry_date` and/or `promotion_note` left empty

### Requirement: Product list shows expiry date with two-tier highlighting
The product list SHALL display each product's expiry date and SHALL visually distinguish already-expired products from near-expiry products, regardless of whether an expiry filter is active.

#### Scenario: Product within the near-expiry threshold is highlighted as a warning
- **WHEN** the product list is rendered and a product's `expiry_date` is between today (inclusive) and today plus the configured near-expiry threshold (inclusive)
- **THEN** that product's expiry date cell is displayed with a warning (orange) highlight

#### Scenario: Already-expired product is highlighted as danger
- **WHEN** the product list is rendered and a product's `expiry_date` is earlier than today
- **THEN** that product's expiry date cell is displayed with a danger (red) highlight

#### Scenario: Product without an expiry date shows no highlight
- **WHEN** the product list is rendered and a product has no `expiry_date`
- **THEN** the expiry date cell is shown empty and without any highlight

#### Scenario: Product further than the near-expiry threshold shows no highlight
- **WHEN** a product's `expiry_date` is further in the future than the configured near-expiry threshold
- **THEN** the expiry date cell is displayed without a highlight

### Requirement: Expiry filter on product list
The product list SHALL provide a filter control with three modes — all products, near-expiry only, and expired only — so an admin can list either "expiring soon, still sellable" stock or "already expired" stock without recomputing the threshold client-side. When a non-default mode is active, results SHALL be sorted by `expiry_date`.

#### Scenario: Near-expiry mode shows only non-expired, within-threshold products sorted ascending
- **WHEN** an admin selects the "Gần hết hạn" filter option on the product list
- **THEN** only products with a non-null `expiry_date` between today and today plus the configured near-expiry threshold are shown, ordered by `expiry_date` ascending

#### Scenario: Expired mode shows only already-expired products
- **WHEN** an admin selects the "Đã hết hạn" filter option on the product list
- **THEN** only products with a non-null `expiry_date` earlier than today are shown, ordered by `expiry_date` descending

#### Scenario: Default mode is unfiltered
- **WHEN** an admin opens the product list with the filter left at "Tất cả" (the default)
- **THEN** all products are shown in the existing default order, unaffected by expiry date

### Requirement: POS surfaces promotion note and expiry warning
The POS "Bán hàng" screen SHALL show a product's `promotion_note`, when present, and SHALL warn the cashier when a product is already expired, in both the product search dropdown and the cart line — without requiring extra clicks or a separate lookup.

#### Scenario: Promotion note is shown in the search dropdown
- **WHEN** a cashier searches for a product that has a non-empty `promotion_note`
- **THEN** the matching entry in the search-suggestion dropdown shows the promotion note, marked with a gift icon

#### Scenario: Promotion note is shown in the cart line
- **WHEN** a product with a non-empty `promotion_note` is added to the cart
- **THEN** its cart line shows the promotion note, marked with a gift icon

#### Scenario: Expired product is flagged in the search dropdown
- **WHEN** a cashier searches for a product whose `expiry_date` is earlier than today
- **THEN** the matching entry in the search-suggestion dropdown shows a red warning icon next to the product name, with no additional text

#### Scenario: Expired product is flagged in the cart line
- **WHEN** an already-expired product is added to the cart
- **THEN** its cart line shows the same red warning icon next to the product name

#### Scenario: Non-expired product without a promotion note shows neither indicator
- **WHEN** a product has no `promotion_note` and is not expired
- **THEN** neither the gift icon/note nor the expiry warning icon is shown for it
