package database import ( "context" "errors" "log/slog" slogGorm "github.com/orandin/slog-gorm" "gorm.io/driver/postgres" "gorm.io/driver/sqlite" "gorm.io/gorm" "payouts/internal/service/database/config" "payouts/internal/service/database/orm" ) type dbService struct { dbType string db *gorm.DB ctx context.Context } func NewDatabaseService(conf config.Database) (Service, error) { var dialector gorm.Dialector switch conf.Type { case "sqlite": dialector = sqlite.Open(conf.Connection) case "postgres": dialector = postgres.Open(conf.Connection) default: return nil, errors.New("unknown dbType") } level := slog.LevelInfo level.UnmarshalText([]byte(conf.LogLevel)) slogGormOpts := []slogGorm.Option{ slogGorm.SetLogLevel(slogGorm.DefaultLogType, level), } if conf.TraceRequests { slogGormOpts = append(slogGormOpts, slogGorm.WithTraceAll()) } slogGorm := slogGorm.New(slogGormOpts...) db, err := gorm.Open(dialector, &gorm.Config{ Logger: slogGorm, }) if err == nil { db.DB() db.AutoMigrate(&orm.User{}, &orm.Payout{}) } result := &dbService{ ctx: context.Background(), } result.dbType = conf.Type result.db = db return result, err } func (d *dbService) getParams(options ...Optional) *params { params := ¶ms{ ctx: d.ctx, } for _, opt := range options { opt(params) } return params } // AddUser implements [Service]. func (d *dbService) CreateUser(userModel *orm.User, opts ...Optional) error { p := d.getParams(opts...) return gorm.G[orm.User](d.db).Create(p.ctx, userModel) } // GetUser implements [Service]. func (d *dbService) GetUser(userModel *orm.User, opts ...Optional) (orm.User, error) { p := d.getParams(opts...) return gorm.G[orm.User](d.db).Where(userModel).First(p.ctx) } // GetPayout implements [Service]. func (d *dbService) GetPayout(payoutModel *orm.Payout, opts ...Optional) (orm.Payout, error) { p := d.getParams(opts...) return gorm.G[orm.Payout](d.db).Where(payoutModel).First(p.ctx) } // CreatePayout implements [Service]. func (d *dbService) CreatePayout(payoutModel *orm.Payout, opts ...Optional) error { p := d.getParams(opts...) return gorm.G[orm.Payout](d.db).Create(p.ctx, payoutModel) } // UpdatePayoutById implements [Service]. func (d *dbService) UpdatePayoutById(id uint, updateModel orm.Payout, opts ...Optional) (int, error) { p := d.getParams(opts...) return gorm.G[orm.Payout](d.db).Where("id = ?", id).Updates(p.ctx, updateModel) } // UpdatePayoutByPayoutID implements [Service]. func (d *dbService) UpdatePayoutByPayoutID(payoutId string, updateModel orm.Payout, opts ...Optional) (int, error) { p := d.getParams(opts...) return gorm.G[orm.Payout](d.db).Where("payout_id = ?", payoutId).Updates(p.ctx, updateModel) } // HealthCheck implements [Service]. func (d *dbService) HealthCheck() error { if d.db == nil { return errors.New("database connection is nil") } db, err := d.db.DB() if err != nil { return err } return db.Ping() }