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:
@@ -192,6 +192,7 @@ export async function syncQSOs(userId, dclApiKey, sinceDate = null, jobId = null
|
|||||||
|
|
||||||
let addedCount = 0;
|
let addedCount = 0;
|
||||||
let updatedCount = 0;
|
let updatedCount = 0;
|
||||||
|
let skippedCount = 0;
|
||||||
const errors = [];
|
const errors = [];
|
||||||
const addedQSOs = [];
|
const addedQSOs = [];
|
||||||
const updatedQSOs = [];
|
const updatedQSOs = [];
|
||||||
@@ -219,26 +220,41 @@ export async function syncQSOs(userId, dclApiKey, sinceDate = null, jobId = null
|
|||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
if (existing.length > 0) {
|
if (existing.length > 0) {
|
||||||
// Update existing QSO with DCL confirmation and DOK data
|
const existingQSO = existing[0];
|
||||||
await db
|
|
||||||
.update(qsos)
|
// Check if DCL confirmation or DOK data has changed
|
||||||
.set({
|
const dataChanged =
|
||||||
dclQslRdate: dbQSO.dclQslRdate,
|
existingQSO.dclQslRstatus !== dbQSO.dclQslRstatus ||
|
||||||
dclQslRstatus: dbQSO.dclQslRstatus,
|
existingQSO.dclQslRdate !== dbQSO.dclQslRdate ||
|
||||||
darcDok: dbQSO.darcDok || existing[0].darcDok,
|
existingQSO.darcDok !== (dbQSO.darcDok || existingQSO.darcDok) ||
|
||||||
myDarcDok: dbQSO.myDarcDok || existing[0].myDarcDok,
|
existingQSO.myDarcDok !== (dbQSO.myDarcDok || existingQSO.myDarcDok) ||
|
||||||
grid: dbQSO.grid || existing[0].grid,
|
existingQSO.grid !== (dbQSO.grid || existingQSO.grid);
|
||||||
gridSource: dbQSO.gridSource || existing[0].gridSource,
|
|
||||||
})
|
if (dataChanged) {
|
||||||
.where(eq(qsos.id, existing[0].id));
|
// Update existing QSO with changed DCL confirmation and DOK data
|
||||||
updatedCount++;
|
await db
|
||||||
// Track updated QSO (CALL and DATE)
|
.update(qsos)
|
||||||
updatedQSOs.push({
|
.set({
|
||||||
callsign: dbQSO.callsign,
|
dclQslRdate: dbQSO.dclQslRdate,
|
||||||
date: dbQSO.qsoDate,
|
dclQslRstatus: dbQSO.dclQslRstatus,
|
||||||
band: dbQSO.band,
|
darcDok: dbQSO.darcDok || existingQSO.darcDok,
|
||||||
mode: dbQSO.mode,
|
myDarcDok: dbQSO.myDarcDok || existingQSO.myDarcDok,
|
||||||
});
|
grid: dbQSO.grid || existingQSO.grid,
|
||||||
|
gridSource: dbQSO.gridSource || existingQSO.gridSource,
|
||||||
|
})
|
||||||
|
.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 {
|
} else {
|
||||||
// Insert new QSO
|
// Insert new QSO
|
||||||
await db.insert(qsos).values(dbQSO);
|
await db.insert(qsos).values(dbQSO);
|
||||||
@@ -274,6 +290,7 @@ export async function syncQSOs(userId, dclApiKey, sinceDate = null, jobId = null
|
|||||||
total: adifQSOs.length,
|
total: adifQSOs.length,
|
||||||
added: addedCount,
|
added: addedCount,
|
||||||
updated: updatedCount,
|
updated: updatedCount,
|
||||||
|
skipped: skippedCount,
|
||||||
addedQSOs,
|
addedQSOs,
|
||||||
updatedQSOs,
|
updatedQSOs,
|
||||||
confirmed: adifQSOs.filter(q => q.dcl_qsl_rcvd === 'Y').length,
|
confirmed: adifQSOs.filter(q => q.dcl_qsl_rcvd === 'Y').length,
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ export async function syncQSOs(userId, lotwUsername, lotwPassword, sinceDate = n
|
|||||||
|
|
||||||
let addedCount = 0;
|
let addedCount = 0;
|
||||||
let updatedCount = 0;
|
let updatedCount = 0;
|
||||||
|
let skippedCount = 0;
|
||||||
const errors = [];
|
const errors = [];
|
||||||
const addedQSOs = [];
|
const addedQSOs = [];
|
||||||
const updatedQSOs = [];
|
const updatedQSOs = [];
|
||||||
@@ -247,22 +248,34 @@ export async function syncQSOs(userId, lotwUsername, lotwPassword, sinceDate = n
|
|||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
if (existing.length > 0) {
|
if (existing.length > 0) {
|
||||||
await db
|
const existingQSO = existing[0];
|
||||||
.update(qsos)
|
|
||||||
.set({
|
// Check if LoTW confirmation data has changed
|
||||||
lotwQslRdate: dbQSO.lotwQslRdate,
|
const confirmationChanged =
|
||||||
lotwQslRstatus: dbQSO.lotwQslRstatus,
|
existingQSO.lotwQslRstatus !== dbQSO.lotwQslRstatus ||
|
||||||
lotwSyncedAt: dbQSO.lotwSyncedAt,
|
existingQSO.lotwQslRdate !== dbQSO.lotwQslRdate;
|
||||||
})
|
|
||||||
.where(eq(qsos.id, existing[0].id));
|
if (confirmationChanged) {
|
||||||
updatedCount++;
|
await db
|
||||||
// Track updated QSO (CALL and DATE)
|
.update(qsos)
|
||||||
updatedQSOs.push({
|
.set({
|
||||||
callsign: dbQSO.callsign,
|
lotwQslRdate: dbQSO.lotwQslRdate,
|
||||||
date: dbQSO.qsoDate,
|
lotwQslRstatus: dbQSO.lotwQslRstatus,
|
||||||
band: dbQSO.band,
|
lotwSyncedAt: dbQSO.lotwSyncedAt,
|
||||||
mode: dbQSO.mode,
|
})
|
||||||
});
|
.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 {
|
} else {
|
||||||
await db.insert(qsos).values(dbQSO);
|
await db.insert(qsos).values(dbQSO);
|
||||||
addedCount++;
|
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 {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
total: adifQSOs.length,
|
total: adifQSOs.length,
|
||||||
added: addedCount,
|
added: addedCount,
|
||||||
updated: updatedCount,
|
updated: updatedCount,
|
||||||
|
skipped: skippedCount,
|
||||||
addedQSOs,
|
addedQSOs,
|
||||||
updatedQSOs,
|
updatedQSOs,
|
||||||
errors: errors.length > 0 ? errors : undefined,
|
errors: errors.length > 0 ? errors : undefined,
|
||||||
|
|||||||
@@ -296,7 +296,12 @@
|
|||||||
<div class="alert {syncResult.success ? 'alert-success' : 'alert-error'}">
|
<div class="alert {syncResult.success ? 'alert-success' : 'alert-error'}">
|
||||||
{#if syncResult.success}
|
{#if syncResult.success}
|
||||||
<h3>Sync Complete!</h3>
|
<h3>Sync Complete!</h3>
|
||||||
<p>Total: {syncResult.total}, Added: {syncResult.added}, Updated: {syncResult.updated}</p>
|
<p>
|
||||||
|
Total: {syncResult.total},
|
||||||
|
Added: {syncResult.added},
|
||||||
|
Updated: {syncResult.updated || 0},
|
||||||
|
Skipped: {syncResult.skipped || 0}
|
||||||
|
</p>
|
||||||
{#if syncResult.errors && syncResult.errors.length > 0}
|
{#if syncResult.errors && syncResult.errors.length > 0}
|
||||||
<p class="text-small">Some QSOs had errors</p>
|
<p class="text-small">Some QSOs had errors</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user