fix: Implement folio prefix system with database migration

- Fix generateFolio() to use configured prefix (e.g. "AP-k8hcg" instead of "AP--k8hcg")
- Add migration endpoint /api/migrate-folios to update existing folios with prefix
- Add automatic migration prompt when folio prefix changes in settings
- Ensure all new folios use the configured prefix format
- Maintain backward compatibility with existing folios

Migration process:
- Detects folios without prefix and adds the configured prefix
- Only updates folios that don't already have the prefix
- Provides user feedback on migration results
- Automatically refreshes ticket list after successful migration

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Marco Gallegos
2025-09-14 09:02:27 -06:00
parent 9559652f40
commit bcab7573c3
2 changed files with 109 additions and 1 deletions

50
app.js
View File

@@ -844,12 +844,13 @@ async function loadDashboardData() {
}
function generateFolio() {
const prefix = settings.folioPrefix || 'AP-';
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < 5; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
return `${prefix}${result}`;
}
async function addMovement(mov) {
@@ -1188,6 +1189,22 @@ async function handleSaveSettings(e) {
});
if (response.ok) {
alert('Configuración guardada.');
// Check if folio prefix changed and needs migration
const oldPrefix = window.settings?.folioPrefix;
const newPrefix = settings.folioPrefix;
if (oldPrefix && newPrefix && oldPrefix !== newPrefix) {
const shouldMigrate = confirm(
`El prefijo de folio cambió de "${oldPrefix}" a "${newPrefix}".\n\n` +
'¿Deseas actualizar todos los folios existentes con el nuevo prefijo?\n\n' +
'Esto agregará el prefijo a todos los folios que no lo tengan.'
);
if (shouldMigrate) {
await migrateFolios(settings);
}
}
} else {
throw new Error('Failed to save settings');
}
@@ -1197,6 +1214,37 @@ async function handleSaveSettings(e) {
}
}
// Function to migrate existing folios
async function migrateFolios(settings) {
try {
console.log('Starting folio migration...');
const response = await fetch('/api/migrate-folios', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ settings })
});
const result = await response.json();
if (result.success) {
if (result.updated > 0) {
alert(`✅ Migración completada!\n\n${result.updated} folios actualizados con el nuevo prefijo.`);
// Refresh the tickets table if visible
if (document.querySelector('.tab-content').style.display !== 'none') {
loadMovements();
}
} else {
alert(' No hay folios que necesiten migración.');
}
} else {
throw new Error(result.message || 'Migration failed');
}
} catch (error) {
console.error('Error during migration:', error);
alert('❌ Error durante la migración de folios: ' + error.message);
}
}
async function handleSaveCredentials(e) {
e.preventDefault();
const name = document.getElementById('s-name').value;

View File

@@ -789,6 +789,66 @@ function startServer() {
});
});
// Migration endpoint to update existing folios with prefix
apiRouter.post('/migrate-folios', (req, res) => {
const settings = req.body.settings;
const prefix = settings?.folioPrefix || 'AP-';
console.log(`Starting folio migration with prefix: ${prefix}`);
// Get all movements that don't already have the prefix
db.all(`SELECT id, folio FROM movements WHERE folio NOT LIKE '${prefix}%'`, [], (err, rows) => {
if (err) {
console.error('Error fetching movements for migration:', err);
return res.status(500).json({ error: err.message });
}
if (rows.length === 0) {
console.log('No folios need migration');
return res.json({
success: true,
message: 'No folios need migration',
updated: 0
});
}
let updatedCount = 0;
let errorCount = 0;
// Update each folio
const updatePromises = rows.map(row => {
return new Promise((resolve) => {
const newFolio = `${prefix}${row.folio}`;
db.run(`UPDATE movements SET folio = ? WHERE id = ?`,
[newFolio, row.id],
function(updateErr) {
if (updateErr) {
console.error(`Error updating folio ${row.folio}:`, updateErr);
errorCount++;
} else {
console.log(`Updated folio: ${row.folio}${newFolio}`);
updatedCount++;
}
resolve();
}
);
});
});
// Wait for all updates to complete
Promise.all(updatePromises).then(() => {
console.log(`Migration completed: ${updatedCount} updated, ${errorCount} errors`);
res.json({
success: true,
message: `Migration completed: ${updatedCount} folios updated, ${errorCount} errors`,
updated: updatedCount,
errors: errorCount
});
});
});
});
app.use('/api', apiRouter);
app.listen(port, () => {