Add multi_value technical fields and FA category AI forms.
Support duplicatable free-text lists, always append سایر ویژگیها on AI category forms, and fill leftover product specs into that field. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
ac04e51c8b
commit
00d0284454
@@ -10,6 +10,10 @@ import { PermissionsService } from '../auth/permissions.service';
|
||||
import { CategoryTechnicalFormService } from '../categories/category-technical-form.service';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { ReplaceProductTechnicalInfoDto } from './dto/product-technical-info.dto';
|
||||
import {
|
||||
decodeMultiValueText,
|
||||
encodeMultiValueText,
|
||||
} from '../common/technical-multi-value.util';
|
||||
|
||||
type FormField = {
|
||||
id: string;
|
||||
@@ -159,6 +163,22 @@ export class ProductTechnicalInfoService {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field.type === 'multi_value') {
|
||||
const items = Array.isArray(entry.value)
|
||||
? entry.value.map((item) => String(item).trim()).filter(Boolean)
|
||||
: [];
|
||||
if (!items.length) continue;
|
||||
await tx.productTechnicalFieldValue.create({
|
||||
data: {
|
||||
businessId,
|
||||
productId: product.id,
|
||||
fieldId,
|
||||
textValue: encodeMultiValueText(items),
|
||||
},
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field.type === 'text' || field.type === 'textarea') {
|
||||
await tx.productTechnicalFieldValue.create({
|
||||
data: {
|
||||
@@ -185,6 +205,9 @@ export class ProductTechnicalInfoService {
|
||||
}
|
||||
|
||||
const selectedValues = entry.value as string[];
|
||||
if (!Array.isArray(selectedValues) || !selectedValues.length) {
|
||||
continue;
|
||||
}
|
||||
const fieldValue = await tx.productTechnicalFieldValue.create({
|
||||
data: {
|
||||
businessId,
|
||||
@@ -230,6 +253,24 @@ export class ProductTechnicalInfoService {
|
||||
return;
|
||||
}
|
||||
|
||||
if (field.type === 'multi_value') {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new BadRequestException(
|
||||
`Field "${field.label}" expects an array of text values`,
|
||||
);
|
||||
}
|
||||
const items = value.map((item) => String(item).trim()).filter(Boolean);
|
||||
if (!items.length) {
|
||||
if (field.isRequired) {
|
||||
throw new BadRequestException(
|
||||
`Required field "${field.label}" cannot be empty`,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (field.type === 'select') {
|
||||
if (typeof value !== 'string') {
|
||||
throw new BadRequestException(
|
||||
@@ -303,7 +344,17 @@ export class ProductTechnicalInfoService {
|
||||
fieldKey: field.key,
|
||||
fieldLabel: field.label,
|
||||
type: field.type,
|
||||
value: field.type === 'multi_select' ? [] : null,
|
||||
value:
|
||||
field.type === 'multi_select' || field.type === 'multi_value' ? [] : null,
|
||||
};
|
||||
}
|
||||
|
||||
if (field.type === 'multi_value') {
|
||||
return {
|
||||
fieldKey: field.key,
|
||||
fieldLabel: field.label,
|
||||
type: field.type,
|
||||
value: decodeMultiValueText(record.textValue),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user