96 lines
2.3 KiB
Go
96 lines
2.3 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"git.threesix.ai/jordan/slack5-1770544098/services/preferences-api/internal/domain"
|
|
)
|
|
|
|
// PreferencesRepository implements port.PreferencesRepository using PostgreSQL.
|
|
type PreferencesRepository struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
// NewPreferencesRepository creates a new PostgreSQL-backed preferences repository.
|
|
func NewPreferencesRepository(db *sql.DB) *PreferencesRepository {
|
|
return &PreferencesRepository{db: db}
|
|
}
|
|
|
|
// Get returns preferences for a user by ID.
|
|
// Returns nil when no preferences exist for the user.
|
|
func (r *PreferencesRepository) Get(ctx context.Context, userID string) (*domain.UserPreferences, error) {
|
|
var (
|
|
prefsJSON []byte
|
|
createdAt time.Time
|
|
updatedAt time.Time
|
|
)
|
|
|
|
err := r.db.QueryRowContext(ctx,
|
|
`SELECT preferences, created_at, updated_at FROM user_preferences WHERE user_id = $1`,
|
|
userID,
|
|
).Scan(&prefsJSON, &createdAt, &updatedAt)
|
|
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var prefs map[string]any
|
|
if err := json.Unmarshal(prefsJSON, &prefs); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &domain.UserPreferences{
|
|
UserID: userID,
|
|
Preferences: prefs,
|
|
CreatedAt: createdAt,
|
|
UpdatedAt: updatedAt,
|
|
}, nil
|
|
}
|
|
|
|
// Upsert creates or updates preferences for a user using JSONB merge.
|
|
// Returns the full merged preferences after upsert.
|
|
func (r *PreferencesRepository) Upsert(ctx context.Context, userID string, prefs map[string]any) (*domain.UserPreferences, error) {
|
|
prefsJSON, err := json.Marshal(prefs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var (
|
|
resultJSON []byte
|
|
createdAt time.Time
|
|
updatedAt time.Time
|
|
)
|
|
|
|
err = r.db.QueryRowContext(ctx, `
|
|
INSERT INTO user_preferences (user_id, preferences, created_at, updated_at)
|
|
VALUES ($1, $2, NOW(), NOW())
|
|
ON CONFLICT (user_id) DO UPDATE
|
|
SET preferences = user_preferences.preferences || $2,
|
|
updated_at = NOW()
|
|
RETURNING preferences, created_at, updated_at`,
|
|
userID, prefsJSON,
|
|
).Scan(&resultJSON, &createdAt, &updatedAt)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var merged map[string]any
|
|
if err := json.Unmarshal(resultJSON, &merged); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &domain.UserPreferences{
|
|
UserID: userID,
|
|
Preferences: merged,
|
|
CreatedAt: createdAt,
|
|
UpdatedAt: updatedAt,
|
|
}, nil
|
|
}
|