# Product Discount Form - Read-Only Product Field Update

## Changes Made

The Product Discount form has been updated to use a **read-only product display field** instead of a selectable dropdown.

---

## Previous Implementation (Dropdown)
```json
{
  "label": "Product",
  "field_name": "product_id",
  "data_column": "product_id",
  "type_id": 13,
  "options_table": "products",
  "options_label_column": "name",
  "options_value_column": "product_id",
  "order_index": 1,
  "required": true
}
```

**Issue**: User could select any product, even though the discount button was clicked from a specific product row.

---

## New Implementation (Read-Only + Hidden)

### Field 1: Product Name (Display - Read-Only)
```json
{
  "label": "Product",
  "field_name": "product_name",
  "type_id": 1,
  "order_index": 1,
  "readonly": true,
  "default": ""
}
```

**Purpose**: Displays the selected product name in a read-only text field.

### Field 2: Product ID (Hidden)
```json
{
  "field_name": "product_id",
  "data_column": "product_id",
  "type_id": 1,
  "order_index": 0,
  "hidden": true,
  "required": true
}
```

**Purpose**: Stores the product_id foreign key for the database relationship.

---

## How It Works

### 1. User clicks "Discount" button on a product row
   - The button is configured with `formId: 134` in the Products module
   - ModalBuilder detects this is a row action

### 2. Form loads with pre-filled data
   - ModalBuilder/FormRenderer automatically passes row data to the form
   - The `product_name` field receives the product's name (read-only display)
   - The `product_id` field receives the product's ID (hidden, required for DB)

### 3. User fills remaining fields
   - **Product**: Shows product name, cannot be changed (read-only)
   - **Discount Amount**: User enters discount value
   - **Start Date**: User selects start date
   - **End Date**: User selects end date

### 4. Form submits
   - `product_id` (hidden field) is sent to the database
   - Maps to `product_discounts.product_id` column
   - Creates the foreign key relationship

---

## Benefits

✅ **User Experience**: Clear which product the discount applies to  
✅ **Data Integrity**: Prevents accidental selection of wrong product  
✅ **Simpler UI**: No dropdown search needed  
✅ **Context Aware**: Discount tied to the specific product row clicked  
✅ **Form Validation**: product_id is required but hidden from view  

---

## Technical Details

### Form Fields Structure
| Order | Field Name   | Type | Visibility | Purpose              |
|-------|-------------|------|------------|----------------------|
| 0     | product_id  | 1    | Hidden     | Store FK to products |
| 1     | product_name| 1    | Read-only  | Display product name |
| 2     | discount_amount | 2 | Editable  | User input          |
| 3     | start_date  | 3    | Editable   | Date picker         |
| 4     | end_date    | 3    | Editable   | Date picker         |

### Field Type IDs
- **Type 1**: Text input (can be readonly or hidden)
- **Type 2**: Numeric input
- **Type 3**: Date picker
- **Type 13**: Select-search dropdown (previously used, now removed)

---

## Row Action Configuration

In `sql/modules.sql`, the Products table has:

```json
"rowActions": [
  {
    "label": "Discount",
    "formId": 134,
    "icon": "fa-tags",
    "class": "btn-sm btn-info"
  }
]
```

When this button is clicked:
1. ModalBuilder reads the row data
2. Opens form ID 134 (Product Discount)
3. Passes row data to pre-fill fields
4. The `product_id` and `product_name` from the row populate the form

---

## Database Schema

The `product_discounts` table:

```sql
CREATE TABLE product_discounts (
  discount_id       uuid PRIMARY KEY,
  product_id        uuid REFERENCES products(product_id),  ← FK from hidden field
  discount_amount   NUMERIC(10,2),
  start_date        date,
  end_date          date,
  org_id            uuid,
  isDeleted         BOOLEAN,
  updatedAt         timestamptz
);
```

---

## Files Modified

1. ✅ `/var/www/html/TAF/sql/defaults.sql` - Updated form definition (line ~3110)
2. ✅ `/var/www/html/TAF/docs/ProductDiscounts.md` - Updated documentation
3. ✅ `/var/www/html/TAF/docs/ProductDiscountsDiagram.md` - Updated diagrams

---

## Testing

To test the readonly product field:

1. **Open Products module** from dashboard
2. **Click Discount button** on any product row
3. **Verify**:
   - Product name appears in a grayed-out/readonly text field
   - Product name matches the row clicked
   - Field cannot be edited or changed
   - Discount amount, start date, and end date are editable
4. **Fill form** and save
5. **Check database**:
   ```sql
   SELECT * FROM product_discounts;
   ```
   - Verify `product_id` matches the product clicked
   - Verify discount_amount and dates are correct

---

## Implementation Notes

### Why Two Fields?

**product_name (readonly, visible)**:
- For user interface display
- Shows which product the discount applies to
- Cannot be edited by user
- Not mapped to database column (display only)

**product_id (hidden, required)**:
- For database relationship
- Stores the actual foreign key
- Required for form submission
- Maps to `product_discounts.product_id` column

### FormRenderer Behavior

When ModalBuilder opens a form from a row action:
- It automatically passes the row object to FormRenderer
- Fields with `data_column` matching row properties get pre-filled
- Fields with `readonly: true` render with `readonly` HTML attribute
- Fields with `hidden: true` render as `<input type="hidden">`

### Alternative Approaches Considered

❌ **Dropdown with disabled state**: Could still be confusing  
❌ **No product field at all**: User wouldn't see which product  
✅ **Readonly display + hidden ID**: Best UX and data integrity  

---

## Summary

The Product Discount form now provides a **clearer, more contextual user experience** by displaying the selected product as read-only text while storing the product_id in a hidden field. This prevents confusion and errors while maintaining proper database relationships.
