Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af91dba268 |
@@ -673,6 +673,111 @@ app.get('/api/health', async (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
// ─── MIGRATIONS ─────────────────────────────────────────────────
|
||||
|
||||
// One-time migration: convert Translations with post_id → Artefacts (copy type)
|
||||
// Safe to run multiple times — skips posts that already have copy Artefacts.
|
||||
app.post('/api/admin/migrate-translations-to-artefacts', requireAuth, async (req, res) => {
|
||||
if (req.session.userRole !== 'superadmin') return res.status(403).json({ error: 'Superadmin only' });
|
||||
const dryRun = req.body.dry_run !== false; // default true for safety
|
||||
const report = { dry_run: dryRun, skipped: [], migrated: [], errors: [] };
|
||||
|
||||
try {
|
||||
// All translations linked to a post (caption or body copy)
|
||||
const translations = await nocodb.list('Translations', {
|
||||
where: `(post_id,gt,0)`, limit: 2000,
|
||||
});
|
||||
|
||||
for (const t of translations) {
|
||||
if (!t.post_id) continue;
|
||||
const copyType = t.copy_type || 'body';
|
||||
|
||||
// Skip if an Artefact for this post+copy_type already exists
|
||||
const existing = await nocodb.list('Artefacts', {
|
||||
where: `(post_id,eq,${t.post_id})~and(type,eq,copy)~and(copy_type,eq,${copyType})`,
|
||||
limit: 1,
|
||||
});
|
||||
if (existing.length > 0) {
|
||||
report.skipped.push({ translation_id: t.Id, post_id: t.post_id, copy_type: copyType, reason: 'artefact already exists' });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dryRun) {
|
||||
report.migrated.push({ translation_id: t.Id, post_id: t.post_id, copy_type: copyType, title: t.title, dry_run: true });
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. Create Artefact
|
||||
const artefact = await nocodb.create('Artefacts', {
|
||||
title: t.title || (copyType === 'caption' ? 'Caption' : 'Body Copy'),
|
||||
type: 'copy',
|
||||
copy_type: copyType,
|
||||
status: t.status || 'draft',
|
||||
post_id: t.post_id,
|
||||
brand_id: t.brand_id || null,
|
||||
approver_ids: t.approver_ids || null,
|
||||
approval_token: t.approval_token || null,
|
||||
approved_by_name: t.approved_by_name || null,
|
||||
approved_at: t.approved_at || null,
|
||||
feedback: t.feedback || null,
|
||||
created_by_user_id: t.created_by_user_id || null,
|
||||
});
|
||||
|
||||
// 2. Create first ArtefactVersion
|
||||
const version = await nocodb.create('ArtefactVersions', {
|
||||
artefact_id: artefact.Id,
|
||||
version_number: 1,
|
||||
status: t.status || 'draft',
|
||||
created_by_user_id: t.created_by_user_id || null,
|
||||
});
|
||||
|
||||
// 3. Migrate source content as a version text entry
|
||||
const textsToCreate = [];
|
||||
if (t.source_content && t.source_language) {
|
||||
textsToCreate.push({
|
||||
version_id: version.Id,
|
||||
language_code: t.source_language,
|
||||
language_label: t.source_language,
|
||||
content: t.source_content,
|
||||
status: 'draft',
|
||||
});
|
||||
}
|
||||
|
||||
// 4. Migrate TranslationTexts as additional language entries
|
||||
const translationTexts = await nocodb.list('TranslationTexts', {
|
||||
where: `(translation_id,eq,${t.Id})`, limit: 50,
|
||||
});
|
||||
for (const tt of translationTexts) {
|
||||
if (tt.language_code === t.source_language) continue; // already added above
|
||||
textsToCreate.push({
|
||||
version_id: version.Id,
|
||||
language_code: tt.language_code,
|
||||
language_label: tt.language_label || tt.language_code,
|
||||
content: tt.content || '',
|
||||
status: tt.status || 'draft',
|
||||
});
|
||||
}
|
||||
|
||||
if (textsToCreate.length > 0) {
|
||||
await nocodb.bulkCreate('ArtefactVersionTexts', textsToCreate);
|
||||
}
|
||||
|
||||
// 5. Set current_version on Artefact
|
||||
await nocodb.update('Artefacts', artefact.Id, { current_version: 1 });
|
||||
|
||||
report.migrated.push({ translation_id: t.Id, artefact_id: artefact.Id, post_id: t.post_id, copy_type: copyType, title: artefact.title, texts: textsToCreate.length });
|
||||
} catch (err) {
|
||||
report.errors.push({ translation_id: t.Id, post_id: t.post_id, error: err.message });
|
||||
}
|
||||
}
|
||||
|
||||
res.json({ ...report, summary: { total: translations.length, migrated: report.migrated.length, skipped: report.skipped.length, errors: report.errors.length } });
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// ─── EMAIL TEST ─────────────────────────────────────────────────
|
||||
|
||||
app.post('/api/admin/test-email', requireAuth, async (req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user