c25e3f4927
Call 2 seed now requires benefit-first short + four-part long HTML, returned as JSON. POST parses and persists both fields; Create-desc gate no longer requires short (Call 2 writes it). Brand voice/geo stay Settings-injected.
60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
/**
|
|
* Create-desc gate (Call 2): disable Create desc unless these are present.
|
|
* Does NOT require short_description, description, or price — Call 2 writes
|
|
* short + long; price stays publish-only.
|
|
*/
|
|
|
|
export type CreateDescInput = {
|
|
contentLlmEnabled: boolean;
|
|
title: string;
|
|
speciesId: number | null | undefined;
|
|
woodCategoryIds: number[];
|
|
primaryCatId: number | '' | null | undefined;
|
|
edgeTermId: number | string | '' | null | undefined;
|
|
figureTermIds: number[];
|
|
gradeTermId: number | string | '' | null | undefined;
|
|
moistureTermId: number | string | '' | null | undefined;
|
|
};
|
|
|
|
/** Human labels shown under Create desc when the gate fails. */
|
|
export const CREATE_DESC_LABELS: Record<string, string> = {
|
|
content_llm: 'content LLM on',
|
|
title: 'title',
|
|
species: 'species',
|
|
wood_categories: '≥1 wood category',
|
|
primary: 'primary wood category',
|
|
edge: 'edge type',
|
|
figure: '≥1 figure',
|
|
grade: 'grade',
|
|
moisture: 'moisture',
|
|
};
|
|
|
|
function presentId(v: number | string | '' | null | undefined): boolean {
|
|
if (v === null || v === undefined || v === '') return false;
|
|
if (typeof v === 'number') return Number.isFinite(v);
|
|
return String(v).trim() !== '';
|
|
}
|
|
|
|
/** Return missing field keys (stable order). Empty ⇒ Create desc enabled. */
|
|
export function missingCreateDesc(input: CreateDescInput): string[] {
|
|
const missing: string[] = [];
|
|
if (!input.contentLlmEnabled) missing.push('content_llm');
|
|
if (!String(input.title ?? '').trim()) missing.push('title');
|
|
if (input.speciesId == null || !Number.isFinite(Number(input.speciesId))) missing.push('species');
|
|
if (!input.woodCategoryIds?.length) missing.push('wood_categories');
|
|
if (!presentId(input.primaryCatId)) missing.push('primary');
|
|
if (!presentId(input.edgeTermId)) missing.push('edge');
|
|
if (!input.figureTermIds?.length) missing.push('figure');
|
|
if (!presentId(input.gradeTermId)) missing.push('grade');
|
|
if (!presentId(input.moistureTermId)) missing.push('moisture');
|
|
return missing;
|
|
}
|
|
|
|
export function canCreateDesc(input: CreateDescInput): boolean {
|
|
return missingCreateDesc(input).length === 0;
|
|
}
|
|
|
|
export function missingCreateDescLabels(input: CreateDescInput): string[] {
|
|
return missingCreateDesc(input).map((k) => CREATE_DESC_LABELS[k] ?? k);
|
|
}
|