package postgres import ( "context" "errors" "fmt" "github.com/jackc/pgx/v5" ) type Tenant struct { ID string TenantCode string Name string Status string } type AdminEventRecord struct { ID string PublicID string TenantID *string TenantCode *string TenantName *string Slug string DisplayName string Summary *string Status string CurrentReleaseID *string CurrentReleasePubID *string ConfigLabel *string ManifestURL *string ManifestChecksum *string RouteCode *string } type CreateAdminEventParams struct { PublicID string TenantID *string Slug string DisplayName string Summary *string Status string } type UpdateAdminEventParams struct { EventID string TenantID *string Slug string DisplayName string Summary *string Status string ClearTenant bool } func (s *Store) GetTenantByCode(ctx context.Context, tenantCode string) (*Tenant, error) { row := s.pool.QueryRow(ctx, ` SELECT id, tenant_code, name, status FROM tenants WHERE tenant_code = $1 LIMIT 1 `, tenantCode) var item Tenant err := row.Scan(&item.ID, &item.TenantCode, &item.Name, &item.Status) if errors.Is(err, pgx.ErrNoRows) { return nil, nil } if err != nil { return nil, fmt.Errorf("get tenant by code: %w", err) } return &item, nil } func (s *Store) ListAdminEvents(ctx context.Context, limit int) ([]AdminEventRecord, error) { if limit <= 0 || limit > 200 { limit = 50 } rows, err := s.pool.Query(ctx, ` SELECT e.id, e.event_public_id, e.tenant_id, t.tenant_code, t.name, e.slug, e.display_name, e.summary, e.status, e.current_release_id, er.release_public_id, er.config_label, er.manifest_url, er.manifest_checksum_sha256, er.route_code FROM events e LEFT JOIN tenants t ON t.id = e.tenant_id LEFT JOIN event_releases er ON er.id = e.current_release_id ORDER BY e.created_at DESC LIMIT $1 `, limit) if err != nil { return nil, fmt.Errorf("list admin events: %w", err) } defer rows.Close() items := []AdminEventRecord{} for rows.Next() { item, err := scanAdminEventFromRows(rows) if err != nil { return nil, err } items = append(items, *item) } if err := rows.Err(); err != nil { return nil, fmt.Errorf("iterate admin events: %w", err) } return items, nil } func (s *Store) GetAdminEventByPublicID(ctx context.Context, eventPublicID string) (*AdminEventRecord, error) { row := s.pool.QueryRow(ctx, ` SELECT e.id, e.event_public_id, e.tenant_id, t.tenant_code, t.name, e.slug, e.display_name, e.summary, e.status, e.current_release_id, er.release_public_id, er.config_label, er.manifest_url, er.manifest_checksum_sha256, er.route_code FROM events e LEFT JOIN tenants t ON t.id = e.tenant_id LEFT JOIN event_releases er ON er.id = e.current_release_id WHERE e.event_public_id = $1 LIMIT 1 `, eventPublicID) return scanAdminEvent(row) } func (s *Store) CreateAdminEvent(ctx context.Context, tx Tx, params CreateAdminEventParams) (*AdminEventRecord, error) { row := tx.QueryRow(ctx, ` INSERT INTO events (tenant_id, event_public_id, slug, display_name, summary, status) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id, event_public_id, tenant_id, slug, display_name, summary, status, current_release_id `, params.TenantID, params.PublicID, params.Slug, params.DisplayName, params.Summary, params.Status) var item AdminEventRecord if err := row.Scan( &item.ID, &item.PublicID, &item.TenantID, &item.Slug, &item.DisplayName, &item.Summary, &item.Status, &item.CurrentReleaseID, ); err != nil { return nil, fmt.Errorf("create admin event: %w", err) } return &item, nil } func (s *Store) UpdateAdminEvent(ctx context.Context, tx Tx, params UpdateAdminEventParams) (*AdminEventRecord, error) { row := tx.QueryRow(ctx, ` UPDATE events SET tenant_id = CASE WHEN $7 THEN NULL ELSE $2 END, slug = $3, display_name = $4, summary = $5, status = $6 WHERE id = $1 RETURNING id, event_public_id, tenant_id, slug, display_name, summary, status, current_release_id `, params.EventID, params.TenantID, params.Slug, params.DisplayName, params.Summary, params.Status, params.ClearTenant) var item AdminEventRecord if err := row.Scan( &item.ID, &item.PublicID, &item.TenantID, &item.Slug, &item.DisplayName, &item.Summary, &item.Status, &item.CurrentReleaseID, ); err != nil { return nil, fmt.Errorf("update admin event: %w", err) } return &item, nil } func scanAdminEvent(row pgx.Row) (*AdminEventRecord, error) { var item AdminEventRecord err := row.Scan( &item.ID, &item.PublicID, &item.TenantID, &item.TenantCode, &item.TenantName, &item.Slug, &item.DisplayName, &item.Summary, &item.Status, &item.CurrentReleaseID, &item.CurrentReleasePubID, &item.ConfigLabel, &item.ManifestURL, &item.ManifestChecksum, &item.RouteCode, ) if errors.Is(err, pgx.ErrNoRows) { return nil, nil } if err != nil { return nil, fmt.Errorf("scan admin event: %w", err) } return &item, nil } func scanAdminEventFromRows(rows pgx.Rows) (*AdminEventRecord, error) { var item AdminEventRecord err := rows.Scan( &item.ID, &item.PublicID, &item.TenantID, &item.TenantCode, &item.TenantName, &item.Slug, &item.DisplayName, &item.Summary, &item.Status, &item.CurrentReleaseID, &item.CurrentReleasePubID, &item.ConfigLabel, &item.ManifestURL, &item.ManifestChecksum, &item.RouteCode, ) if err != nil { return nil, fmt.Errorf("scan admin event row: %w", err) } return &item, nil }