diff --git a/src/services/statcastAggregateService.js b/src/services/statcastAggregateService.js index afa98d3..9b84727 100644 --- a/src/services/statcastAggregateService.js +++ b/src/services/statcastAggregateService.js @@ -272,14 +272,13 @@ async function refreshSeason(opts = {}) { const asOf = (opts.asOfDate || started).slice(0, 10); let retained = 0; for (let i = 0; i < rows.length; i += chunk) { - const batch = rows.slice(i, i + chunk).map((r) => { - const row = toDbRow(r); - delete row.updated_at; delete row.source; - delete row.position; delete row.role_detail; - delete row.games_started; delete row.games_pitched; - delete row.saves; delete row.holds; - return { ...row, as_of_date: asOf }; - }); + // The history table MIRRORS statcast_aggregates (created via LIKE), so the + // row goes in whole. The first prod attempt hand-stripped columns against a + // hand-enumerated schema and failed on the first one that had drifted + // ('swing_pct'); passing the same shape through removes the drift surface + // entirely. `updated_at` rides along as the refresh timestamp; `as_of_date` + // is the day the snapshot describes and is what point-in-time queries use. + const batch = rows.slice(i, i + chunk).map((r) => ({ ...toDbRow(r), as_of_date: asOf })); const { error } = await sb.from('statcast_history') .upsert(batch, { onConflict: 'as_of_date,sport,season,source_id,role' }); if (error) { summary.history_error = error.message; break; }