feat(custom-fields): allow creating values without predefined field ID

This commit is contained in:
Matthieu
2025-09-30 15:34:06 +02:00
parent 55c57362c5
commit bd058cd533
4 changed files with 176 additions and 50 deletions

View File

@@ -8,6 +8,7 @@ import {
CreateCustomFieldValueDto,
UpdateCustomFieldValueDto,
CustomFieldEntityType,
UpsertCustomFieldValueDto,
} from '../shared/dto/custom-field.dto';
@Injectable()
@@ -170,37 +171,87 @@ export class CustomFieldsService {
// Créer ou mettre à jour une valeur de champ personnalisé
async upsertCustomFieldValue(
customFieldId: string,
entityType: CustomFieldEntityType,
entityId: string,
value: string,
dto: UpsertCustomFieldValueDto,
) {
const {
customFieldId: rawCustomFieldId,
customFieldName,
customFieldType,
customFieldOptions,
customFieldRequired,
entityType,
entityId,
value,
} = dto;
const { typeId, customFieldTypeField, valueKey } =
await this.resolveEntityContext(entityType, entityId);
const allowedCustomField = await this.prisma.customField.findFirst({
where: {
id: customFieldId,
[customFieldTypeField]: typeId,
},
});
let targetCustomFieldId = rawCustomFieldId?.trim() || null;
if (!allowedCustomField) {
if (!targetCustomFieldId) {
const normalizedName = customFieldName?.trim();
if (!normalizedName) {
throw new BadRequestException(
'customFieldId ou customFieldName est requis pour sauvegarder une valeur.',
);
}
const normalizedOptions = Array.isArray(customFieldOptions)
? customFieldOptions.map((option) => String(option))
: [];
const existingField = await this.prisma.customField.findFirst({
where: {
name: normalizedName,
[customFieldTypeField]: typeId,
},
});
if (existingField) {
targetCustomFieldId = existingField.id;
} else {
const createdField = await this.prisma.customField.create({
data: {
name: normalizedName,
type: (customFieldType || 'text').trim() || 'text',
required: !!customFieldRequired,
options: normalizedOptions,
[customFieldTypeField]: typeId,
},
});
targetCustomFieldId = createdField.id;
}
} else {
const allowedCustomField = await this.prisma.customField.findFirst({
where: {
id: targetCustomFieldId,
[customFieldTypeField]: typeId,
},
});
if (!allowedCustomField) {
throw new BadRequestException(
"Le champ personnalisé n'est pas autorisé pour cette entité.",
);
}
}
if (!targetCustomFieldId) {
throw new BadRequestException(
"Le champ personnalisé n'est pas autorisé pour cette entité.",
'Impossible de déterminer le champ personnalisé ciblé.',
);
}
// D'abord, essayer de trouver une valeur existante
const existingValue = await this.prisma.customFieldValue.findFirst({
where: {
customFieldId,
customFieldId: targetCustomFieldId,
[valueKey]: entityId,
},
});
if (existingValue) {
// Mettre à jour la valeur existante
return this.prisma.customFieldValue.update({
where: { id: existingValue.id },
data: { value },
@@ -208,18 +259,17 @@ export class CustomFieldsService {
customField: true,
},
});
} else {
// Créer une nouvelle valeur
return this.prisma.customFieldValue.create({
data: {
customFieldId,
value,
[valueKey]: entityId,
},
include: {
customField: true,
},
});
}
return this.prisma.customFieldValue.create({
data: {
customFieldId: targetCustomFieldId,
value,
[valueKey]: entityId,
},
include: {
customField: true,
},
});
}
}