merge issue-89-metadata-lock → main (Create-string model, #89/#90)
Drop the metadata_locked column + "Save and lock" UI end-to-end. The review endpoint now builds the deterministic title/short_description on every call; the owner's Create title / Create short desc buttons fire the build and write the result (force-overwrite contract). commitReview auto-fills only empty fields (no owner-clobber) and folds the deterministic copy into its single PUT (kills the client_rev 409 cascade). Taken wholesale from the branch: photo strip, wood primary/secondary, server-side thickness band (hidden from UI, passed to Woo on publish), and fixes #80/#82/#83/#84. - backend: remove metadata_locked from schema.sql, db sentinels, slabs.py client fields/exposure, review.py lock action; review always computes title/short_desc - frontend: slabs.ts + Review.svelte drop the lock model, add Create-string workflow + wood primary + photo strip - e2e: m3-create + review-photo-strip rewritten for the Create-string contract; thickness-band test asserts absence (per #90) - deploy: recreate LAN binds (override-m3.yml was absent); verify metadata_locked gone, review builds title, PUT persists Gates: backend 117/117, unit 88/88, tsc clean, e2e 6/6 (m3-create + photo-strip). Live UAT verified at 192.168.1.202:10881.
This commit is contained in:
@@ -43,7 +43,7 @@ function baseSlab(): Record<string, unknown> {
|
||||
species_id: null, wood_category_ids: [], edge_type_term_id: null, figure_term_ids: [], grade_term_id: null,
|
||||
thickness_term_id: null, moisture_term_id: null, fig_tag_ids: [], feat_tag_ids: [],
|
||||
title: null, short_description: null, description: null, content_source: 'manual',
|
||||
metadata_locked: false, species_confidence: null, figure_confidence: null, grade_confidence: null,
|
||||
species_confidence: null, figure_confidence: null, grade_confidence: null,
|
||||
inference_status: null, calibration_photo_id: null, woo_product_id: null, server_rev: 0,
|
||||
created_at: '2026-01-01T00:00:00Z', updated_at: '2026-01-01T00:00:00Z',
|
||||
};
|
||||
@@ -66,7 +66,7 @@ async function mockApi(page: Page) {
|
||||
|
||||
const merge = (payload: Record<string, unknown>) => {
|
||||
if (typeof payload.client_rev === 'number' && payload.client_rev !== slab.server_rev) return false;
|
||||
for (const k of ['sku', 'species_id', 'wood_category_ids', 'title', 'short_description', 'price', 'metadata_locked', 'edge_type_term_id']) {
|
||||
for (const k of ['sku', 'species_id', 'wood_category_ids', 'title', 'short_description', 'price', 'edge_type_term_id']) {
|
||||
if (k in payload) (slab as Record<string, unknown>)[k] = payload[k];
|
||||
}
|
||||
if (typeof payload.client_rev === 'number') slab.server_rev = payload.client_rev + 1;
|
||||
@@ -91,7 +91,7 @@ async function mockApi(page: Page) {
|
||||
title: (slab.title as string) ?? null,
|
||||
short_description: (slab.short_description as string) ?? null,
|
||||
price: (slab.price as number) ?? null, price_suggestion: 120,
|
||||
primary_wood_category_id: null, locked: slab.metadata_locked === true,
|
||||
primary_wood_category_id: null,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -181,8 +181,8 @@ async function completeForReady(page: Page) {
|
||||
await page.getByTestId('wood-cat-done').click();
|
||||
await page.getByTestId('edge-type').selectOption('31');
|
||||
await page.getByTestId('price').fill('120');
|
||||
await expect(page.getByTestId('lock-metadata')).toBeEnabled();
|
||||
await page.getByTestId('lock-metadata').click();
|
||||
await expect(page.getByTestId('create-title')).toBeEnabled();
|
||||
await page.getByTestId('create-title').click();
|
||||
await expect(page.getByTestId('title')).not.toHaveValue('');
|
||||
await page.getByTestId('sku').fill('SLAB-0001');
|
||||
await page.getByTestId('sku').press('Tab');
|
||||
|
||||
Reference in New Issue
Block a user