Refactor sync service to handle conflicted category and note IDs during synchronization
Despliegue Automático / desplegar (push) Successful in 1m25s

This commit is contained in:
2026-08-18 09:23:18 +02:00
parent ded4c8fc03
commit 80f1b7ad28
+17 -10
View File
@@ -41,7 +41,6 @@ const buildStoredNoteData = (incomingNote, existingNote = null) => {
: (incomingNote.position ?? existingNote?.position ?? 0);
return {
// categoryId eliminado de aquí
title: permanentDelete ? '' : incomingNote.title,
body: permanentDelete ? '' : incomingNote.body,
position,
@@ -73,6 +72,10 @@ class SyncService {
const incomingCategories = Array.isArray(changes.categories) ? changes.categories : [];
const incomingNotes = Array.isArray(changes.notes) ? changes.notes : [];
// ARRAYS PARA IDs DESFASADOS
const conflictedCategoryIds = [];
const conflictedNoteIds = [];
await sequelize.transaction(async (transaction) => {
// --- SINCRONIZACIÓN DE CATEGORÍAS ---
for (const incomingCategory of incomingCategories) {
@@ -109,6 +112,8 @@ class SyncService {
delete: Boolean(incomingCategory.delete),
serverVersion: serverVersion + 1
}, { transaction });
} else if (serverVersion > incomingBaseVersion) {
conflictedCategoryIds.push(existingCategory.id);
}
}
@@ -116,7 +121,6 @@ class SyncService {
for (const incomingNote of incomingNotes) {
const permanentDelete = Boolean(incomingNote.permanentDelete);
// Se verifica que sea 'string' para aceptar strings vacíos
if (!incomingNote.id || typeof incomingNote.title !== 'string' || typeof incomingNote.body !== 'string') {
throw new Error("Cada nota debe incluir id, title y body");
}
@@ -138,7 +142,6 @@ class SyncService {
serverVersion: 1
}, { transaction });
// 👇 Actualizar la relación de muchos a muchos al crear
if (Array.isArray(incomingNote.categoryIds)) {
await newNote.setCategories(incomingNote.categoryIds, { transaction });
}
@@ -155,12 +158,11 @@ class SyncService {
serverVersion: serverVersion + 1
}, { transaction });
// 👇 Actualizar la relación de muchos a muchos al editar
if (Array.isArray(incomingNote.categoryIds)) {
await existingNote.setCategories(incomingNote.categoryIds, { transaction });
}
} else if (serverVersion > incomingBaseVersion) {
// Conflicto de versiones... (implementación de duplicados omitida por ahora)
conflictedNoteIds.push(existingNote.id);
} else {
throw new Error(`serverVersion inválida en la nota ${incomingNote.id}`);
}
@@ -172,20 +174,25 @@ class SyncService {
Category.findAll({
where: {
userId,
updatedAt: { [Op.gt]: lastSyncAt }
[Op.or]: [
{ updatedAt: { [Op.gt]: lastSyncAt } },
{ id: { [Op.in]: conflictedCategoryIds } }
]
},
order: [['updatedAt', 'ASC']]
}),
Note.findAll({
where: {
userId,
updatedAt: { [Op.gt]: lastSyncAt }
[Op.or]: [
{ updatedAt: { [Op.gt]: lastSyncAt } },
{ id: { [Op.in]: conflictedNoteIds } }
]
},
// 👇 Le decimos a Sequelize que incluya la tabla Category para poder sacar los IDs
include: [{
model: Category,
attributes: ['id'], // Solo necesitamos el ID para el array de Flutter
through: { attributes: [] } // Omite los datos de la tabla intermedia en el JSON final
attributes: ['id'],
through: { attributes: [] }
}],
order: [['updatedAt', 'ASC']]
})