feat: skip QSOs with unchanged confirmation data

When syncing from LoTW/DCL, only update QSOs if confirmation data
has changed. This avoids unnecessary database updates and makes it
clear which QSOs actually changed.

- LoTW: Checks if lotwQslRstatus or lotwQslRdate changed
- DCL: Checks if dclQslRstatus, dclQslRdate, DOK, or grid changed
- Frontend: Shows skipped count in sync summary

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-17 19:49:56 +01:00
parent 3592dbb4fb
commit e09ab94e63
3 changed files with 74 additions and 38 deletions

View File

@@ -222,6 +222,7 @@ export async function syncQSOs(userId, lotwUsername, lotwPassword, sinceDate = n
let addedCount = 0;
let updatedCount = 0;
let skippedCount = 0;
const errors = [];
const addedQSOs = [];
const updatedQSOs = [];
@@ -247,22 +248,34 @@ export async function syncQSOs(userId, lotwUsername, lotwPassword, sinceDate = n
.limit(1);
if (existing.length > 0) {
await db
.update(qsos)
.set({
lotwQslRdate: dbQSO.lotwQslRdate,
lotwQslRstatus: dbQSO.lotwQslRstatus,
lotwSyncedAt: dbQSO.lotwSyncedAt,
})
.where(eq(qsos.id, existing[0].id));
updatedCount++;
// Track updated QSO (CALL and DATE)
updatedQSOs.push({
callsign: dbQSO.callsign,
date: dbQSO.qsoDate,
band: dbQSO.band,
mode: dbQSO.mode,
});
const existingQSO = existing[0];
// Check if LoTW confirmation data has changed
const confirmationChanged =
existingQSO.lotwQslRstatus !== dbQSO.lotwQslRstatus ||
existingQSO.lotwQslRdate !== dbQSO.lotwQslRdate;
if (confirmationChanged) {
await db
.update(qsos)
.set({
lotwQslRdate: dbQSO.lotwQslRdate,
lotwQslRstatus: dbQSO.lotwQslRstatus,
lotwSyncedAt: dbQSO.lotwSyncedAt,
})
.where(eq(qsos.id, existingQSO.id));
updatedCount++;
// Track updated QSO (CALL and DATE)
updatedQSOs.push({
callsign: dbQSO.callsign,
date: dbQSO.qsoDate,
band: dbQSO.band,
mode: dbQSO.mode,
});
} else {
// Skip - same data
skippedCount++;
}
} else {
await db.insert(qsos).values(dbQSO);
addedCount++;
@@ -288,13 +301,14 @@ export async function syncQSOs(userId, lotwUsername, lotwPassword, sinceDate = n
}
}
logger.info('LoTW sync completed', { total: adifQSOs.length, added: addedCount, updated: updatedCount, jobId });
logger.info('LoTW sync completed', { total: adifQSOs.length, added: addedCount, updated: updatedCount, skipped: skippedCount, jobId });
return {
success: true,
total: adifQSOs.length,
added: addedCount,
updated: updatedCount,
skipped: skippedCount,
addedQSOs,
updatedQSOs,
errors: errors.length > 0 ? errors : undefined,