From 37eb3716727c24323f3182555a2976e636b22168 Mon Sep 17 00:00:00 2001 From: Yilin Jing Date: Sat, 28 Feb 2026 00:39:15 +0800 Subject: [PATCH] fix(#34): rename campaign_snapshots.campaign_p_id to campaign_pid The CampaignSnapshot model field `CampaignPID` was missing the `gorm:"column:campaign_pid"` tag, causing GORM to snake_case it as `campaign_p_id` instead of the expected `campaign_pid`. This caused all snapshot inserts to fail with: ERROR: column "campaign_pid" does not exist (SQLSTATE 42703) Changes: 1. Added `column:campaign_pid` GORM tag to model 2. Added idempotent migration to rename existing column Same root cause as campaigns.pid issue (#24). Fixes #34 Co-Authored-By: Claude Sonnet 4.5 --- backend/internal/db/db.go | 17 +++++++++++++++++ backend/internal/model/model.go | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/backend/internal/db/db.go b/backend/internal/db/db.go index db00247..0b32d7e 100644 --- a/backend/internal/db/db.go +++ b/backend/internal/db/db.go @@ -119,6 +119,23 @@ func Init(cfg *config.Config) error { return fmt.Errorf("migrate velocity columns: %w", err) } + // Fix campaign_snapshots FK: rename campaign_p_id -> campaign_pid (same issue as campaigns.pid) + if err := DB.Exec(` + DO $$ + BEGIN + -- Rename column if it exists with old snake_case name + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'campaign_snapshots' AND column_name = 'campaign_p_id' + ) THEN + ALTER TABLE campaign_snapshots RENAME COLUMN campaign_p_id TO campaign_pid; + END IF; + END + $$; + `).Error; err != nil { + return fmt.Errorf("migrate campaign_snapshots fk: %w", err) + } + log.Println("Database connected and migrated") return nil } diff --git a/backend/internal/model/model.go b/backend/internal/model/model.go index 3a0d532..436e674 100644 --- a/backend/internal/model/model.go +++ b/backend/internal/model/model.go @@ -32,7 +32,7 @@ type Campaign struct { type CampaignSnapshot struct { ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"` - CampaignPID string `gorm:"index;not null" json:"campaign_pid"` + CampaignPID string `gorm:"column:campaign_pid;index;not null" json:"campaign_pid"` PledgedAmount float64 `json:"pledged_amount"` PercentFunded float64 `json:"percent_funded"` SnapshotAt time.Time `gorm:"index;not null;default:now()" json:"snapshot_at"`