feat(fields): мягкое удаление полей формы — архив удалённых с восстановлением и блок «Удалённые поля» в задаче
This commit is contained in:
@@ -121,25 +121,8 @@ export function registerFormStructureRoutes(router: ReturnType<typeof import("ex
|
||||
const incomingIds = fields.filter((f: Record<string, unknown>) => f.id).map((f: Record<string, unknown>) => f.id as number);
|
||||
const fieldsToDelete = existingFields.filter(existing => !incomingIds.includes(existing.id));
|
||||
|
||||
if (fieldsToDelete.length > 0) {
|
||||
const tasks = await storage.getTasksByForm(formId, req.organizationId!);
|
||||
const usedFieldIds = new Set();
|
||||
for (const task of tasks) {
|
||||
const fieldValues = await storage.getTaskFieldValues(task.id, req.organizationId!);
|
||||
for (const value of fieldValues) {
|
||||
usedFieldIds.add(value.fieldId);
|
||||
}
|
||||
}
|
||||
for (const field of fieldsToDelete) {
|
||||
if (usedFieldIds.has(field.id)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: `Невозможно удалить поле "${field.name}" - оно используется в существующих задачах. Сначала удалите значения этого поля во всех задачах.`
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Мягкое удаление: значения в задачах сохраняются (поле уходит в архив),
|
||||
// поэтому раньше существовавшая блокировка «поле используется в задачах» снята.
|
||||
const fieldIdsToDelete = fieldsToDelete.map(f => f.id);
|
||||
const normalizedFields = fields.map((f: Record<string, unknown>) => ({
|
||||
...f,
|
||||
@@ -171,4 +154,42 @@ export function registerFormStructureRoutes(router: ReturnType<typeof import("ex
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Архив удалённых (мягко) полей формы
|
||||
router.get('/api/forms/:id/fields/deleted',
|
||||
requireFormAdminOrPermission('forms.manage'),
|
||||
async (req: AuthenticatedRequest, res) => {
|
||||
try {
|
||||
const formId = parseInt(req.params.id);
|
||||
if (isNaN(formId)) {
|
||||
return res.status(400).json({ success: false, error: 'Неверный ID формы' });
|
||||
}
|
||||
const fields = await storage.getDeletedFormFields(formId, req.organizationId!);
|
||||
res.json({ success: true, fields });
|
||||
} catch (error) {
|
||||
console.error('Get deleted fields error:', error);
|
||||
res.status(500).json({ success: false, error: 'Ошибка при загрузке удалённых полей' });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Восстановление удалённого поля (значения в задачах сохранились и вернутся сами)
|
||||
router.post('/api/forms/:id/fields/:fieldId/restore',
|
||||
requireFormAdminOrPermission('forms.manage'),
|
||||
async (req: AuthenticatedRequest, res) => {
|
||||
try {
|
||||
const formId = parseInt(req.params.id);
|
||||
const fieldId = parseInt(req.params.fieldId);
|
||||
if (isNaN(formId) || isNaN(fieldId)) {
|
||||
return res.status(400).json({ success: false, error: 'Неверный ID формы или поля' });
|
||||
}
|
||||
const restored = await storage.restoreFormField(fieldId, formId, req.organizationId!);
|
||||
formsCache.invalidatePrefix(`forms:${req.organizationId}`);
|
||||
res.json({ success: true, field: restored });
|
||||
} catch (error) {
|
||||
console.error('Restore field error:', error);
|
||||
res.status(400).json({ success: false, error: error instanceof Error ? error.message : 'Ошибка при восстановлении поля' });
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user