fixed projects snapshot issue
This commit is contained in:
parent
3d06d927cf
commit
b6cf7a702a
@ -239,12 +239,26 @@ class Project_element_defaultsDBApi extends GenericDBApi {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Dedupe by element_type (keep first occurrence)
|
||||
// Prevents unique constraint violations if global defaults have duplicates
|
||||
const seenTypes = new Set();
|
||||
const dedupedDefaults = globalDefaults.rows.filter((row) => {
|
||||
if (seenTypes.has(row.element_type)) {
|
||||
console.warn(
|
||||
`Duplicate element_type in global defaults: ${row.element_type} (skipping)`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
seenTypes.add(row.element_type);
|
||||
return true;
|
||||
});
|
||||
|
||||
const now = new Date();
|
||||
const currentUserId = options.currentUser?.id || null;
|
||||
|
||||
// Create project defaults from global defaults
|
||||
const projectDefaults = await this.MODEL.bulkCreate(
|
||||
globalDefaults.rows.map((globalDefault) => ({
|
||||
dedupedDefaults.map((globalDefault) => ({
|
||||
projectId,
|
||||
element_type: globalDefault.element_type,
|
||||
name: globalDefault.name,
|
||||
|
||||
@ -116,19 +116,12 @@ class ProjectsDBApi extends GenericDBApi {
|
||||
const project = await super.create(data, options);
|
||||
|
||||
// Auto-snapshot global element defaults to the new project
|
||||
try {
|
||||
const Project_element_defaultsDBApi = require('./project_element_defaults');
|
||||
await Project_element_defaultsDBApi.snapshotGlobalDefaults(project.id, {
|
||||
...options,
|
||||
transaction,
|
||||
});
|
||||
} catch (error) {
|
||||
// Log but don't fail project creation if snapshot fails
|
||||
console.error(
|
||||
'Failed to snapshot global element defaults to project:',
|
||||
error,
|
||||
);
|
||||
}
|
||||
// Errors propagate to service layer → transaction rollback → proper error to client
|
||||
const Project_element_defaultsDBApi = require('./project_element_defaults');
|
||||
await Project_element_defaultsDBApi.snapshotGlobalDefaults(project.id, {
|
||||
...options,
|
||||
transaction,
|
||||
});
|
||||
|
||||
return project;
|
||||
}
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Remove duplicate element_type_defaults rows.
|
||||
* Keeps the oldest entry (by createdAt) for each element_type.
|
||||
* This fixes the unique constraint violation during project creation.
|
||||
*/
|
||||
module.exports = {
|
||||
async up(queryInterface, Sequelize) {
|
||||
// Find duplicate element_types
|
||||
const duplicates = await queryInterface.sequelize.query(
|
||||
`SELECT element_type, COUNT(*) as count
|
||||
FROM element_type_defaults
|
||||
WHERE "deletedAt" IS NULL
|
||||
GROUP BY element_type
|
||||
HAVING COUNT(*) > 1`,
|
||||
{ type: Sequelize.QueryTypes.SELECT },
|
||||
);
|
||||
|
||||
if (duplicates.length === 0) {
|
||||
console.log('No duplicate element_type_defaults found.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Found ${duplicates.length} element_types with duplicates:`,
|
||||
duplicates.map((d) => d.element_type).join(', '),
|
||||
);
|
||||
|
||||
// For each duplicate element_type, keep oldest and delete others
|
||||
for (const dup of duplicates) {
|
||||
// Get all rows for this element_type, ordered by createdAt
|
||||
const rows = await queryInterface.sequelize.query(
|
||||
`SELECT id, "createdAt"
|
||||
FROM element_type_defaults
|
||||
WHERE element_type = :element_type AND "deletedAt" IS NULL
|
||||
ORDER BY "createdAt" ASC`,
|
||||
{
|
||||
replacements: { element_type: dup.element_type },
|
||||
type: Sequelize.QueryTypes.SELECT,
|
||||
},
|
||||
);
|
||||
|
||||
// Keep the first (oldest), delete the rest
|
||||
const idsToDelete = rows.slice(1).map((r) => r.id);
|
||||
|
||||
if (idsToDelete.length > 0) {
|
||||
await queryInterface.sequelize.query(
|
||||
`DELETE FROM element_type_defaults WHERE id IN (:ids)`,
|
||||
{ replacements: { ids: idsToDelete } },
|
||||
);
|
||||
console.log(
|
||||
`Deleted ${idsToDelete.length} duplicate(s) for element_type: ${dup.element_type}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Duplicate removal complete.');
|
||||
},
|
||||
|
||||
async down(_queryInterface, _Sequelize) {
|
||||
// Cannot restore deleted duplicates
|
||||
console.log('Down migration not applicable - duplicates cannot be restored.');
|
||||
},
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user