package repository import ( "context" "encoding/json" "fmt" "github.com/jackc/pgx/v5/pgxpool" "github.com/yourorg/go-dw-platform/services/omnix-broadcast/entity" ) type Repository struct { pool *pgxpool.Pool } func New(pool *pgxpool.Pool) *Repository { return &Repository{pool: pool} } func (r *Repository) FindPending(ctx context.Context, limit int) ([]*entity.BroadcastStaging, error) { query := ` SELECT id, sopiga_collar_id, sopiga_template_id, message_payload, status, error_message, error_count, sopiga_recipient_detail_id, created_at, updated_at FROM collection_broadcasts.broadcast_staging WHERE status = 'pending' ORDER BY created_at ASC LIMIT $1 ` rows, err := r.pool.Query(ctx, query, limit) if err != nil { return nil, fmt.Errorf("find pending: %w", err) } defer rows.Close() var records []*entity.BroadcastStaging for rows.Next() { var e entity.BroadcastStaging if err := rows.Scan( &e.ID, &e.SopigaCollarID, &e.SopigaTemplateID, &e.MessagePayload, &e.Status, &e.ErrorMessage, &e.ErrorCount, &e.SopigaRecipientDetailID, &e.CreatedAt, &e.UpdatedAt, ); err != nil { return nil, fmt.Errorf("scan: %w", err) } records = append(records, &e) } return records, rows.Err() } func (r *Repository) FindTemplateVariables(ctx context.Context, templateID int) ([]*entity.TemplateVariableMapping, error) { query := ` SELECT variable_order, sopiga_variable_name, variable_type, db_field_source, is_required FROM collection_broadcasts.template_variable_mapping WHERE sopiga_template_id = $1 ORDER BY variable_order ASC ` rows, err := r.pool.Query(ctx, query, templateID) if err != nil { return nil, fmt.Errorf("find template variables: %w", err) } defer rows.Close() var variables []*entity.TemplateVariableMapping for rows.Next() { var v entity.TemplateVariableMapping if err := rows.Scan(&v.VariableOrder, &v.SopigaVariableName, &v.VariableType, &v.DBFieldSource, &v.IsRequired); err != nil { return nil, fmt.Errorf("scan: %w", err) } variables = append(variables, &v) } return variables, rows.Err() } func (r *Repository) FindByRecipientDetailID(ctx context.Context, recipientDetailID int64) (*entity.BroadcastStaging, error) { query := ` SELECT id, sopiga_collar_id, sopiga_template_id, message_payload, status, error_message, error_count, sopiga_recipient_detail_id, created_at, updated_at FROM collection_broadcasts.broadcast_staging WHERE sopiga_recipient_detail_id = $1 ` var e entity.BroadcastStaging err := r.pool.QueryRow(ctx, query, recipientDetailID).Scan( &e.ID, &e.SopigaCollarID, &e.SopigaTemplateID, &e.MessagePayload, &e.Status, &e.ErrorMessage, &e.ErrorCount, &e.SopigaRecipientDetailID, &e.CreatedAt, &e.UpdatedAt, ) if err != nil { return nil, fmt.Errorf("find by recipient_detail_id %d: %w", recipientDetailID, err) } return &e, nil } func (r *Repository) UpdateStatus(ctx context.Context, id int64, status, errMsg string, sopigaResponse any) error { var respJSON []byte if sopigaResponse != nil { var err error respJSON, err = json.Marshal(sopigaResponse) if err != nil { return fmt.Errorf("marshal sopiga response: %w", err) } } query := `SELECT collection_broadcasts.update_broadcast_status($1, $2, $3, $4)` _, err := r.pool.Exec(ctx, query, id, status, errMsg, respJSON) if err != nil { return fmt.Errorf("update status: %w", err) } return nil } func (r *Repository) FindDispatched(ctx context.Context, limit int) ([]*entity.BroadcastStaging, error) { query := ` SELECT id, sopiga_collar_id, sopiga_template_id, message_payload, status, error_message, error_count, sopiga_recipient_detail_id, created_at, updated_at FROM collection_broadcasts.broadcast_staging WHERE status = 'dispatched' AND sopiga_recipient_detail_id IS NOT NULL ORDER BY dispatched_at ASC LIMIT $1 ` rows, err := r.pool.Query(ctx, query, limit) if err != nil { return nil, fmt.Errorf("find dispatched: %w", err) } defer rows.Close() var records []*entity.BroadcastStaging for rows.Next() { var e entity.BroadcastStaging if err := rows.Scan( &e.ID, &e.SopigaCollarID, &e.SopigaTemplateID, &e.MessagePayload, &e.Status, &e.ErrorMessage, &e.ErrorCount, &e.SopigaRecipientDetailID, &e.CreatedAt, &e.UpdatedAt, ); err != nil { return nil, fmt.Errorf("scan: %w", err) } records = append(records, &e) } return records, rows.Err() } func (r *Repository) UpdateDispatched(ctx context.Context, id int64, recipientDetailID int64) error { query := ` UPDATE collection_broadcasts.broadcast_staging SET status = 'dispatched', sopiga_recipient_detail_id = $1, dispatched_at = NOW(), updated_at = NOW() WHERE id = $2 ` _, err := r.pool.Exec(ctx, query, recipientDetailID, id) if err != nil { return fmt.Errorf("update dispatched: %w", err) } return nil }