ProductTypesPage: openEdit() should fetch full ProductTypeDetail before populating form #39

Closed
opened 2026-04-19 15:20:18 +00:00 by dmolinari · 1 comment
Owner

Problem

When an admin clicks "Edit" on an existing ProductType row with multimedia limits (e.g., AllowImages: true, MaxImages: 5), the form opens with all multimedia fields empty (null stubs). If the admin submits without modifying them, the update command sends maxImages: null → the handler overwrites the database with null multimedia limits, silently wiping the previous config.

Minimal Reproduction

  1. Create a ProductType with AllowImages: true, MaxImages: 5, MaxImageSizeMB: 10, ...
  2. In ProductTypesPage, click Edit on that row
  3. ProductTypeFormDialog opens with edit mode
  4. Observe: all multimedia fields are empty (null stubs from line ~X in openEdit stub mapping)
  5. Click Save without touching multimedia fields
  6. ProductType now has MaxImages: null, MaxImageSizeMB: null, ... — previous config lost

Root Cause

ProductTypesPage.tsx, openEdit() function maps from ProductTypeListItem (list DTO) to a ProductTypeDetail stub with hardcoded null multimedia fields:

const openEdit = (item: ProductTypeListItem) => {
  const detail: ProductTypeDetail = {
    ...item,
    maxImages: null,  // STUB
    maxImageSizeMB: null,  // STUB
    // ... etc
  };
  setEditingProductType(detail);
  setIsEditDialogOpen(true);
};

The form renders these null values, and when submitted, they overwrite the database.

Solution

Before opening the edit dialog, fetch the full ProductTypeDetail from the API:

const openEdit = async (item: ProductTypeListItem) => {
  try {
    const detail = await productTypesApi.getProductTypeById(item.id);  // Fetch from backend
    setEditingProductType(detail);
    setIsEditDialogOpen(true);
  } catch (err) {
    // Handle error
  }
};

Alternatively, wire the existing useProductType(id) hook that was added but never used.

Impact

  • Severity: WARNING (practical risk LOW pre-PRD-008, since no real ProductTypes have multimedia limits configured yet; all 12 legacy types have AllowImages: false)
  • Affects: Edit flow for ProductTypes with multimedia config
  • Blocks: Not critical for PRD-002, but should be resolved in PRD-008 polish or dedicated cleanup

Acceptance Criteria

  • openEdit() fetches full ProductTypeDetail via API (or hook) before opening dialog
  • Edit form pre-populates with correct multimedia values from database
  • Submitting form without changes preserves all multimedia limits (no silent wipe)
  • No regression in create flow (create dialog still works, starts with null multimedia)
  • Test added: Edit ProductType with multimedia, submit without changes, verify DB unchanged
  • PRD-001 archive report (obs #sdd/prd-001-product-type-flags-multimedia/archive-report)
  • W_OPENEDIT warning (re-verify report, obs #461)
  • CAT-001 / CAT-002 patterns (precedent for dialog-based CRUD)
## Problem When an admin clicks "Edit" on an existing ProductType row with multimedia limits (e.g., `AllowImages: true, MaxImages: 5`), the form opens with all multimedia fields empty (null stubs). If the admin submits without modifying them, the update command sends `maxImages: null` → the handler overwrites the database with null multimedia limits, **silently wiping the previous config**. ### Minimal Reproduction 1. Create a ProductType with `AllowImages: true, MaxImages: 5, MaxImageSizeMB: 10, ...` 2. In ProductTypesPage, click Edit on that row 3. ProductTypeFormDialog opens with edit mode 4. Observe: all multimedia fields are empty (null stubs from line ~X in openEdit stub mapping) 5. Click Save without touching multimedia fields 6. ProductType now has `MaxImages: null, MaxImageSizeMB: null, ...` — previous config lost ### Root Cause `ProductTypesPage.tsx`, `openEdit()` function maps from `ProductTypeListItem` (list DTO) to a `ProductTypeDetail` stub with hardcoded null multimedia fields: ```typescript const openEdit = (item: ProductTypeListItem) => { const detail: ProductTypeDetail = { ...item, maxImages: null, // STUB maxImageSizeMB: null, // STUB // ... etc }; setEditingProductType(detail); setIsEditDialogOpen(true); }; ``` The form renders these null values, and when submitted, they overwrite the database. ## Solution Before opening the edit dialog, fetch the full `ProductTypeDetail` from the API: ```typescript const openEdit = async (item: ProductTypeListItem) => { try { const detail = await productTypesApi.getProductTypeById(item.id); // Fetch from backend setEditingProductType(detail); setIsEditDialogOpen(true); } catch (err) { // Handle error } }; ``` Alternatively, wire the existing `useProductType(id)` hook that was added but never used. ## Impact - **Severity**: WARNING (practical risk LOW pre-PRD-008, since no real ProductTypes have multimedia limits configured yet; all 12 legacy types have `AllowImages: false`) - **Affects**: Edit flow for ProductTypes with multimedia config - **Blocks**: Not critical for PRD-002, but should be resolved in PRD-008 polish or dedicated cleanup ## Acceptance Criteria - [ ] `openEdit()` fetches full `ProductTypeDetail` via API (or hook) before opening dialog - [ ] Edit form pre-populates with correct multimedia values from database - [ ] Submitting form without changes preserves all multimedia limits (no silent wipe) - [ ] No regression in create flow (create dialog still works, starts with null multimedia) - [ ] Test added: Edit ProductType with multimedia, submit without changes, verify DB unchanged ## Related - PRD-001 archive report (obs #sdd/prd-001-product-type-flags-multimedia/archive-report) - W_OPENEDIT warning (re-verify report, obs #461) - CAT-001 / CAT-002 patterns (precedent for dialog-based CRUD)
dmolinari added the followup label 2026-04-19 15:20:23 +00:00
Author
Owner

Duplicate of #37 — cerrando. Seguir el tracking en #37 que tiene el contexto completo, 3 opciones de fix con recomendación, y criterios de aceptación.

Duplicate of #37 — cerrando. Seguir el tracking en #37 que tiene el contexto completo, 3 opciones de fix con recomendación, y criterios de aceptación.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dmolinari/SIG-CM2.0#39