package postgresql import ( "context" "fmt" "gitea.computernetthings.ru/yash/crypto_alert_bot/internal/entities" "github.com/shopspring/decimal" ) const saveAlertQuery = ` insert into alert(user_id, instrument_id, price, condition) values ($1, $2, $3, $4) returning id` func (p *Postgresql) SaveAlert(ctx context.Context, alert *entities.Alert) (entities.AlertID, error) { var id entities.AlertID err := p.db.QueryRow(ctx, saveAlertQuery, alert.UserID, alert.Instrument.ID, alert.Price.String(), alert.Condition).Scan(&id) if err != nil { return "", fmt.Errorf("failed to exec saveAlertQuery: %w", err) } return id, nil } const allActiveAlertsQuery = ` select a.id, a.user_id, a.price, a.condition, i.id, c_base.symbol, c_quote.symbol from alert a join instrument i on i.id = a.instrument_id join currency c_base on c_base.id = i.base_currency_id join currency c_quote on c_quote.id = i.quoted_currency_id where a.active = true order by a.id` func (p *Postgresql) AllActiveAlerts(ctx context.Context) ([]entities.Alert, error) { rows, err := p.db.Query(ctx, allActiveAlertsQuery) if err != nil { return nil, fmt.Errorf("failed to exec allActiveAlertsQuery: %w", err) } defer rows.Close() var alerts []entities.Alert for rows.Next() { var alert entities.Alert var priceStr string if err := rows.Scan( &alert.ID, &alert.UserID, &priceStr, &alert.Condition, &alert.Instrument.ID, &alert.Instrument.BaseCurrency, &alert.Instrument.QuoteCurrency, ); err != nil { return nil, fmt.Errorf("failed to scan alert row: %w", err) } alert.Price, err = decimal.NewFromString(priceStr) if err != nil { return nil, fmt.Errorf("failed to parse alert price: %w", err) } alerts = append(alerts, alert) } return alerts, nil } const alertByIDQuery = ` select a.id, a.user_id, a.price, a.condition, i.id, c_base.symbol, c_quote.symbol from alert a join instrument i on i.id = a.instrument_id join currency c_base on c_base.id = i.base_currency_id join currency c_quote on c_quote.id = i.quoted_currency_id where a.id = $1 and a.active = true` func (p *Postgresql) AlertByID(ctx context.Context, id entities.AlertID) (*entities.Alert, error) { var alert entities.Alert var priceStr string err := p.db.QueryRow(ctx, alertByIDQuery, id).Scan( &alert.ID, &alert.UserID, &priceStr, &alert.Condition, &alert.Instrument.ID, &alert.Instrument.BaseCurrency, &alert.Instrument.QuoteCurrency, ) if err != nil { return nil, fmt.Errorf("failed to exec alertByIDQuery: %w", err) } alert.Price, err = decimal.NewFromString(priceStr) if err != nil { return nil, fmt.Errorf("failed to parse alert price: %w", err) } return &alert, nil } const alertsByUserIDQuery = ` select a.id, a.user_id, a.price, a.condition, i.id, c_base.symbol, c_quote.symbol from alert a join instrument i on i.id = a.instrument_id join currency c_base on c_base.id = i.base_currency_id join currency c_quote on c_quote.id = i.quoted_currency_id where a.user_id = $1 and a.active = true order by a.id offset $2 limit $3` func (p *Postgresql) AlertsByUserID(ctx context.Context, userID entities.UserID, offset, limit int) ([]entities.Alert, error) { rows, err := p.db.Query(ctx, alertsByUserIDQuery, userID, offset, limit) if err != nil { return nil, fmt.Errorf("failed to exec alertsByUserIDQuery: %w", err) } defer rows.Close() var alerts []entities.Alert for rows.Next() { var alert entities.Alert var priceStr string if err := rows.Scan( &alert.ID, &alert.UserID, &priceStr, &alert.Condition, &alert.Instrument.ID, &alert.Instrument.BaseCurrency, &alert.Instrument.QuoteCurrency, ); err != nil { return nil, fmt.Errorf("failed to scan alert row: %w", err) } alert.Price, err = decimal.NewFromString(priceStr) if err != nil { return nil, fmt.Errorf("failed to parse alert price: %w", err) } alerts = append(alerts, alert) } return alerts, nil } const deleteAlertQuery = "update alert set active = false where id = $1" func (p *Postgresql) DeleteAlert(ctx context.Context, id entities.AlertID) error { _, err := p.db.Exec(ctx, deleteAlertQuery, id) if err != nil { return fmt.Errorf("failed to exec deleteAlertQuery: %w", err) } return nil } const disableAlertQuery = "update alert set active = false where id = $1" func (p *Postgresql) DisableAlert(ctx context.Context, id entities.AlertID) error { _, err := p.db.Exec(ctx, disableAlertQuery, id) if err != nil { return fmt.Errorf("failed to exec disableAlertQuery: %w", err) } return nil } const updateAlertPriceQuery = "update alert set price = $2 where id = $1" func (p *Postgresql) UpdateAlertPrice(ctx context.Context, id entities.AlertID, price decimal.Decimal) error { _, err := p.db.Exec(ctx, updateAlertPriceQuery, id, price.String()) if err != nil { return fmt.Errorf("failed to exec updateAlertPriceQuery: %w", err) } return nil }