diff --git a/db/migrations/000001_fortune.up.sql b/db/migrations/000001_fortune.up.sql index e388a5e..ddf5d79 100644 --- a/db/migrations/000001_fortune.up.sql +++ b/db/migrations/000001_fortune.up.sql @@ -1,21 +1,3 @@ -CREATE TABLE direct_deposits ( - id BIGSERIAL PRIMARY KEY, - customer_id BIGINT NOT NULL REFERENCES users(id), - wallet_id BIGINT NOT NULL REFERENCES wallets(id), - amount NUMERIC(15, 2) NOT NULL, - bank_reference TEXT NOT NULL, - sender_account TEXT NOT NULL, - status TEXT NOT NULL CHECK (status IN ('pending', 'completed', 'rejected')), - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - verified_by BIGINT REFERENCES users(id), - verification_notes TEXT, - verified_at TIMESTAMP -); - -CREATE INDEX idx_direct_deposits_status ON direct_deposits(status); -CREATE INDEX idx_direct_deposits_customer ON direct_deposits(customer_id); -CREATE INDEX idx_direct_deposits_reference ON direct_deposits(bank_reference); - CREATE TABLE IF NOT EXISTS users ( id BIGSERIAL PRIMARY KEY, first_name VARCHAR(255) NOT NULL, @@ -398,6 +380,22 @@ CREATE TABLE flags ( ) ) ); +CREATE TABLE direct_deposits ( + id BIGSERIAL PRIMARY KEY, + customer_id BIGINT NOT NULL REFERENCES users(id), + wallet_id BIGINT NOT NULL REFERENCES wallets(id), + amount NUMERIC(15, 2) NOT NULL, + bank_reference TEXT NOT NULL, + sender_account TEXT NOT NULL, + status TEXT NOT NULL CHECK (status IN ('pending', 'completed', 'rejected')), + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + verified_by BIGINT REFERENCES users(id), + verification_notes TEXT, + verified_at TIMESTAMP +); +CREATE INDEX idx_direct_deposits_status ON direct_deposits(status); +CREATE INDEX idx_direct_deposits_customer ON direct_deposits(customer_id); +CREATE INDEX idx_direct_deposits_reference ON direct_deposits(bank_reference); -- Views CREATE VIEW companies_details AS SELECT companies.*, diff --git a/db/migrations/000007_setting_data.up.sql b/db/migrations/000007_setting_data.up.sql index 458da81..e98967b 100644 --- a/db/migrations/000007_setting_data.up.sql +++ b/db/migrations/000007_setting_data.up.sql @@ -1,20 +1,11 @@ -- Settings Initial Data INSERT INTO settings (key, value) VALUES ('sms_provider', '30'), -<<<<<<< HEAD -('max_number_of_outcomes', '30'), - ('bet_amount_limit', '100000'), -======= ('max_number_of_outcomes', '30'), ('bet_amount_limit', '10000000'), ->>>>>>> 7d8d824a94381bd82c40398654c3bd78218c5950 ('daily_ticket_limit', '50'), ('total_winnings_limit', '1000000'), ('amount_for_bet_referral', '1000000'), ('cashback_amount_cap', '1000') ON CONFLICT (key) DO UPDATE -<<<<<<< HEAD -SET value = EXCLUDED.value; -======= -SET value = EXCLUDED.value; ->>>>>>> 7d8d824a94381bd82c40398654c3bd78218c5950 +SET value = EXCLUDED.value; \ No newline at end of file diff --git a/db/query/settings.sql b/db/query/settings.sql index d0f4482..6a06aae 100644 --- a/db/query/settings.sql +++ b/db/query/settings.sql @@ -5,9 +5,8 @@ FROM settings; SELECT * FROM settings WHERE key = $1; --- name: SaveSetting :one -INSERT INTO settings (key, value, updated_at) -VALUES ($1, $2, CURRENT_TIMESTAMP) ON CONFLICT (key) DO -UPDATE -SET value = EXCLUDED.value -RETURNING *; \ No newline at end of file +-- name: UpdateSetting :exec +UPDATE settings +SET value = $2, + updated_at = CURRENT_TIMESTAMP +WHERE key = $1; \ No newline at end of file diff --git a/gen/db/settings.sql.go b/gen/db/settings.sql.go index d842661..8a9281b 100644 --- a/gen/db/settings.sql.go +++ b/gen/db/settings.sql.go @@ -57,27 +57,19 @@ func (q *Queries) GetSettings(ctx context.Context) ([]Setting, error) { return items, nil } -const SaveSetting = `-- name: SaveSetting :one -INSERT INTO settings (key, value, updated_at) -VALUES ($1, $2, CURRENT_TIMESTAMP) ON CONFLICT (key) DO -UPDATE -SET value = EXCLUDED.value -RETURNING key, value, created_at, updated_at +const UpdateSetting = `-- name: UpdateSetting :exec +UPDATE settings +SET value = $2, + updated_at = CURRENT_TIMESTAMP +WHERE key = $1 ` -type SaveSettingParams struct { +type UpdateSettingParams struct { Key string `json:"key"` Value string `json:"value"` } -func (q *Queries) SaveSetting(ctx context.Context, arg SaveSettingParams) (Setting, error) { - row := q.db.QueryRow(ctx, SaveSetting, arg.Key, arg.Value) - var i Setting - err := row.Scan( - &i.Key, - &i.Value, - &i.CreatedAt, - &i.UpdatedAt, - ) - return i, err +func (q *Queries) UpdateSetting(ctx context.Context, arg UpdateSettingParams) error { + _, err := q.db.Exec(ctx, UpdateSetting, arg.Key, arg.Value) + return err } diff --git a/internal/domain/common.go b/internal/domain/common.go index 88c5852..93db311 100644 --- a/internal/domain/common.go +++ b/internal/domain/common.go @@ -99,6 +99,69 @@ func (v ValidBool) ToPG() pgtype.Bool { } } +func ConvertInt64Ptr(value *int64) ValidInt64 { + if value == nil { + return ValidInt64{} + } + return ValidInt64{ + Value: *value, + Valid: true, + } +} + +func ConvertInt32Ptr(value *int32) ValidInt32 { + if value == nil { + return ValidInt32{} + } + return ValidInt32{ + Value: *value, + Valid: true, + } +} + +func ConvertStringPtr(value *string) ValidString { + if value == nil { + return ValidString{} + } + return ValidString{ + Value: *value, + Valid: true, + } +} + +func ConvertFloat32Ptr(value *float32) ValidFloat32 { + if value == nil { + return ValidFloat32{} + } + return ValidFloat32{ + Value: *value, + Valid: true, + } +} + +func ConvertCurrencyFloatPtr(value *float32) ValidInt64 { + if value == nil { + return ValidInt64{} + } + + convertedCurrency := ToCurrency(*value) + + return ValidInt64{ + Value: int64(convertedCurrency), + Valid: true, + } +} + +func ConvertBoolPtr(value *bool) ValidBool { + if value == nil { + return ValidBool{} + } + return ValidBool{ + Value: *value, + Valid: true, + } +} + type Currency int64 // ToCurrency converts a float32 to Currency diff --git a/internal/domain/settings.go b/internal/domain/settings.go index 3b49c5c..eaa6256 100644 --- a/internal/domain/settings.go +++ b/internal/domain/settings.go @@ -1,6 +1,7 @@ package domain import ( + "strconv" "time" ) @@ -11,9 +12,19 @@ type Setting struct { } type SettingRes struct { - Key string `json:"key"` - Value string `json:"value"` - UpdatedAt string `json:"updated_at"` + Key string `json:"key"` + Value string `json:"value"` + UpdatedAt time.Time `json:"updated_at"` +} + +type UpdateSettingListReq struct { + SMSProvider *string `json:"sms_provider,omitempty"` + MaxNumberOfOutcomes *int64 `json:"max_number_of_outcomes,omitempty"` + BetAmountLimit *float32 `json:"bet_amount_limit,omitempty"` + DailyTicketPerIP *int64 `json:"daily_ticket_limit,omitempty"` + TotalWinningLimit *float32 `json:"total_winning_limit,omitempty"` + AmountForBetReferral *float32 `json:"amount_for_bet_referral,omitempty"` + CashbackAmountCap *float32 `json:"cashback_amount_cap,omitempty"` } type SettingList struct { @@ -26,7 +37,17 @@ type SettingList struct { CashbackAmountCap Currency `json:"cashback_amount_cap"` } -type DBSettingList struct { +type SettingListRes struct { + SMSProvider SMSProvider `json:"sms_provider"` + MaxNumberOfOutcomes int64 `json:"max_number_of_outcomes"` + BetAmountLimit float32 `json:"bet_amount_limit"` + DailyTicketPerIP int64 `json:"daily_ticket_limit"` + TotalWinningLimit float32 `json:"total_winning_limit"` + AmountForBetReferral float32 `json:"amount_for_bet_referral"` + CashbackAmountCap float32 `json:"cashback_amount_cap"` +} + +type ValidSettingList struct { SMSProvider ValidString MaxNumberOfOutcomes ValidInt64 BetAmountLimit ValidInt64 @@ -36,7 +57,7 @@ type DBSettingList struct { CashbackAmountCap ValidInt64 } -func ConvertInt64SettingsMap(dbSettingList *DBSettingList) map[string]*ValidInt64 { +func ConvertInt64SettingsMap(dbSettingList *ValidSettingList) map[string]*ValidInt64 { return map[string]*ValidInt64{ "max_number_of_outcomes": &dbSettingList.MaxNumberOfOutcomes, "bet_amount_limit": &dbSettingList.BetAmountLimit, @@ -47,25 +68,26 @@ func ConvertInt64SettingsMap(dbSettingList *DBSettingList) map[string]*ValidInt6 } } -func ConvertStringSettingsMap(dbSettingList *DBSettingList) map[string]*ValidString { +func ConvertStringSettingsMap(dbSettingList *ValidSettingList) map[string]*ValidString { return map[string]*ValidString{ "sms_provider": &dbSettingList.SMSProvider, } } -func ConvertBoolSettingsMap(dbSettingList *DBSettingList) map[string]*ValidBool { +func ConvertBoolSettingsMap(dbSettingList *ValidSettingList) map[string]*ValidBool { return map[string]*ValidBool{} } -func ConvertFloat32SettingsMap(dbSettingList *DBSettingList) map[string]*ValidFloat32 { +func ConvertFloat32SettingsMap(dbSettingList *ValidSettingList) map[string]*ValidFloat32 { return map[string]*ValidFloat32{} } -func ConvertTimeSettingsMap(dbSettingList *DBSettingList) map[string]*ValidTime { +func ConvertTimeSettingsMap(dbSettingList *ValidSettingList) map[string]*ValidTime { return map[string]*ValidTime{} } -func ConvertDBSetting(dbSettingList DBSettingList) SettingList { +func ValidateSettingList(dbSettingList ValidSettingList) SettingList { + // TODO: Add validation here return SettingList{ SMSProvider: SMSProvider(dbSettingList.SMSProvider.Value), MaxNumberOfOutcomes: dbSettingList.MaxNumberOfOutcomes.Value, @@ -76,3 +98,96 @@ func ConvertDBSetting(dbSettingList DBSettingList) SettingList { CashbackAmountCap: Currency(dbSettingList.CashbackAmountCap.Value), } } + +func ConvertValidSettingList(settingList ValidSettingList) []Setting { + var convertedSettings []Setting + // if settingList.AmountForBetReferral.Valid { + // newValue := strconv.FormatInt(settingList.AmountForBetReferral.Value, 10) + // settings = append(settings, Setting{ + // Key: "amount_for_bet_referral", + // Value: newValue, + // }) + // } + + int64SettingsMap := ConvertInt64SettingsMap(&settingList) + stringSettingsMap := ConvertStringSettingsMap(&settingList) + boolSettingsMap := ConvertBoolSettingsMap(&settingList) + float32SettingsMap := ConvertFloat32SettingsMap(&settingList) + timeSettingsMap := ConvertTimeSettingsMap(&settingList) + + for key, settingPtr := range int64SettingsMap { + setting := *settingPtr + if setting.Valid { + stringVal := strconv.FormatInt(setting.Value, 10) + convertedSettings = append(convertedSettings, Setting{ + Key: key, + Value: stringVal, + }) + } + } + + for key, settingPtr := range stringSettingsMap { + setting := *settingPtr + if setting.Valid { + convertedSettings = append(convertedSettings, Setting{ + Key: key, + Value: setting.Value, + }) + } + } + + for key, settingPtr := range boolSettingsMap { + setting := *settingPtr + if setting.Valid { + stringVal := strconv.FormatBool(setting.Value) + convertedSettings = append(convertedSettings, Setting{ + Key: key, + Value: stringVal, + }) + } + } + + for key, settingPtr := range float32SettingsMap { + setting := *settingPtr + if setting.Valid { + stringVal := strconv.FormatFloat(float64(setting.Value), 'E', -1, 64) + convertedSettings = append(convertedSettings, Setting{ + Key: key, + Value: stringVal, + }) + } + } + + for key, settingPtr := range timeSettingsMap { + setting := *settingPtr + if setting.Valid { + var stringVal string = setting.Value.Format("2006-01-02 15:04:05") + convertedSettings = append(convertedSettings, Setting{ + Key: key, + Value: stringVal, + }) + } + } + + return convertedSettings +} + +func ConvertSetting(setting Setting) SettingRes { + return SettingRes{ + Key: setting.Key, + Value: setting.Value, + UpdatedAt: setting.UpdatedAt, + } +} + +func ConvertUpdateSettingListReq(settings UpdateSettingListReq) ValidSettingList { + return ValidSettingList{ + SMSProvider: ConvertStringPtr(settings.SMSProvider), + MaxNumberOfOutcomes: ConvertInt64Ptr(settings.MaxNumberOfOutcomes), + BetAmountLimit: ConvertCurrencyFloatPtr(settings.BetAmountLimit), + DailyTicketPerIP: ConvertInt64Ptr(settings.DailyTicketPerIP), + TotalWinningLimit: ConvertCurrencyFloatPtr(settings.TotalWinningLimit), + AmountForBetReferral: ConvertCurrencyFloatPtr(settings.AmountForBetReferral), + CashbackAmountCap: ConvertCurrencyFloatPtr(settings.CashbackAmountCap), + } +} diff --git a/internal/repository/settings.go b/internal/repository/settings.go index 8f06372..cb2c2b2 100644 --- a/internal/repository/settings.go +++ b/internal/repository/settings.go @@ -12,7 +12,7 @@ import ( ) func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) { - var dbSettingList domain.DBSettingList + var dbSettingList domain.ValidSettingList var int64SettingsMap = domain.ConvertInt64SettingsMap(&dbSettingList) var stringSettingsMap = domain.ConvertStringSettingsMap(&dbSettingList) @@ -21,7 +21,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) { var timeSettingsMap = domain.ConvertTimeSettingsMap(&dbSettingList) for _, setting := range settings { - is_setting_unknown := true + isSettingUnknown := true for key, dbSetting := range int64SettingsMap { if setting.Key == key { value, err := strconv.ParseInt(setting.Value, 10, 64) @@ -32,7 +32,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) { Value: value, Valid: true, } - is_setting_unknown = false + isSettingUnknown = false } } @@ -42,7 +42,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) { Value: setting.Value, Valid: true, } - is_setting_unknown = false + isSettingUnknown = false } } @@ -56,7 +56,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) { Value: value, Valid: true, } - is_setting_unknown = false + isSettingUnknown = false } } @@ -70,7 +70,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) { Value: float32(value), Valid: true, } - is_setting_unknown = false + isSettingUnknown = false } } for key, dbSetting := range timeSettingsMap { @@ -83,11 +83,11 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) { Value: value, Valid: true, } - is_setting_unknown = false + isSettingUnknown = false } } - if is_setting_unknown { + if isSettingUnknown { domain.MongoDBLogger.Warn("unknown setting found on database", zap.String("setting", setting.Key)) } } @@ -99,7 +99,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) { } } - return domain.ConvertDBSetting(dbSettingList), nil + return domain.ValidateSettingList(dbSettingList), nil } func (s *Store) GetSettingList(ctx context.Context) (domain.SettingList, error) { settings, err := s.queries.GetSettings(ctx) @@ -145,8 +145,8 @@ func (s *Store) GetSetting(ctx context.Context, key string) (domain.Setting, err return result, nil } -func (s *Store) SaveSetting(ctx context.Context, key, value string) (domain.Setting, error) { - dbSetting, err := s.queries.SaveSetting(ctx, dbgen.SaveSettingParams{ +func (s *Store) UpdateSetting(ctx context.Context, key, value string) error { + err := s.queries.UpdateSetting(ctx, dbgen.UpdateSettingParams{ Key: key, Value: value, }) @@ -154,14 +154,22 @@ func (s *Store) SaveSetting(ctx context.Context, key, value string) (domain.Sett if err != nil { domain.MongoDBLogger.Error("failed to update setting", zap.String("key", key), zap.String("value", value), zap.Error(err)) - return domain.Setting{}, err + return err } - setting := domain.Setting{ - Key: dbSetting.Key, - Value: dbSetting.Value, - } - - return setting, err + return err } + +func (s *Store) UpdateSettingList(ctx context.Context, settingList domain.ValidSettingList) error { + convertedSettings := domain.ConvertValidSettingList(settingList) + + for _, setting := range convertedSettings { + err := s.UpdateSetting(ctx, setting.Key, setting.Value) + if err != nil { + domain.MongoDBLogger.Warn("failed to update setting list", zap.String("key", setting.Key), zap.Error(err)) + return err + } + } + return nil +} diff --git a/internal/services/settings/port.go b/internal/services/settings/port.go index ce86f06..9f83ab2 100644 --- a/internal/services/settings/port.go +++ b/internal/services/settings/port.go @@ -10,5 +10,6 @@ type SettingStore interface { GetSettingList(ctx context.Context) (domain.SettingList, error) GetSettings(ctx context.Context) ([]domain.Setting, error) GetSetting(ctx context.Context, key string) (domain.Setting, error) - SaveSetting(ctx context.Context, key, value string) (domain.Setting, error) + UpdateSetting(ctx context.Context, key, value string) error + UpdateSettingList(ctx context.Context, settingList domain.ValidSettingList) error } diff --git a/internal/services/settings/service.go b/internal/services/settings/service.go index 66591a1..8180e94 100644 --- a/internal/services/settings/service.go +++ b/internal/services/settings/service.go @@ -27,6 +27,10 @@ func (s *Service) GetSettings(ctx context.Context) ([]domain.Setting, error) { func (s *Service) GetSetting(ctx context.Context, key string) (domain.Setting, error) { return s.settingStore.GetSetting(ctx, key) } -func (s *Service) SaveSetting(ctx context.Context, key, value string) (domain.Setting, error) { - return s.settingStore.SaveSetting(ctx, key, value) +func (s *Service) UpdateSetting(ctx context.Context, key, value string) error { + return s.settingStore.UpdateSetting(ctx, key, value) +} + +func (s *Service) UpdateSettingList(ctx context.Context, settingList domain.ValidSettingList) error { + return s.settingStore.UpdateSettingList(ctx, settingList) } diff --git a/internal/web_server/handlers/branch_handler.go b/internal/web_server/handlers/branch_handler.go index f73c20d..f65a7f8 100644 --- a/internal/web_server/handlers/branch_handler.go +++ b/internal/web_server/handlers/branch_handler.go @@ -863,7 +863,7 @@ func (h *Handler) UpdateBranch(c *fiber.Ctx) error { var req domain.UpdateBranchReq if err := c.BodyParser(&req); err != nil { - h.mongoLoggerSvc.Info("Failed to parse CreateBranchReq", + h.mongoLoggerSvc.Info("Failed to parse UpdateBranchReq", zap.Int("status_code", fiber.StatusBadRequest), zap.Error(err), zap.Time("timestamp", time.Now()), @@ -879,7 +879,6 @@ func (h *Handler) UpdateBranch(c *fiber.Ctx) error { h.mongoLoggerSvc.Info("Failed to validate UpdateBranchReq", zap.String("branchID", branchID), zap.Int("status_code", fiber.StatusBadRequest), - zap.Error(err), zap.String("errMsg", errMsg), zap.Time("timestamp", time.Now()), ) diff --git a/internal/web_server/handlers/settings_handler.go b/internal/web_server/handlers/settings_handler.go new file mode 100644 index 0000000..016b80b --- /dev/null +++ b/internal/web_server/handlers/settings_handler.go @@ -0,0 +1,105 @@ +package handlers + +import ( + "fmt" + "time" + + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" + "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" + "github.com/gofiber/fiber/v2" + "go.uber.org/zap" +) + +func (h *Handler) GetSettingList(c *fiber.Ctx) error { + settingsList, err := h.settingSvc.GetSettingList(c.Context()) + + if err != nil { + h.mongoLoggerSvc.Error("Failed to fetch settings", + zap.Int("status_code", fiber.StatusInternalServerError), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusInternalServerError, "Failed to get setting list:"+err.Error()) + } + + return response.WriteJSON(c, fiber.StatusOK, "All Settings retrieved successfully", settingsList, nil) +} + +func (h *Handler) GetSettingByKey(c *fiber.Ctx) error { + settingKey := c.Params("key") + if settingKey == "" { + h.mongoLoggerSvc.Info("empty setting key", + zap.Int("status_code", fiber.StatusBadRequest), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "setting key must be passed") + } + + setting, err := h.settingSvc.GetSetting(c.Context(), settingKey) + + if err != nil { + h.mongoLoggerSvc.Info("invalid setting key", + zap.String("setting_key", settingKey), + zap.Int("status_code", fiber.StatusBadRequest), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "setting key is invalid") + } + + res := domain.ConvertSetting(setting) + + return response.WriteJSON(c, fiber.StatusOK, "setting retrieved successfully", res, nil) + +} + +func (h *Handler) UpdateSettingList(c *fiber.Ctx) error { + + var req domain.UpdateSettingListReq + + if err := c.BodyParser(&req); err != nil { + h.mongoLoggerSvc.Info("Failed to parse UpdateSettingListReq", + zap.Int("status_code", fiber.StatusBadRequest), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, "Invalid request") + } + valErrs, ok := h.validator.Validate(c, req) + if !ok { + var errMsg string + for field, msg := range valErrs { + errMsg += fmt.Sprintf("%s: %s; ", field, msg) + } + h.mongoLoggerSvc.Info("Failed to validate UpdateSettingListReq", + zap.Int("status_code", fiber.StatusBadRequest), + zap.String("errMsg", errMsg), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusBadRequest, errMsg) + } + settingList := domain.ConvertUpdateSettingListReq(req) + err := h.settingSvc.UpdateSettingList(c.Context(), settingList) + + if err != nil { + h.mongoLoggerSvc.Info("failed to update setting", + zap.Any("setting_list", settingList), + zap.Int("status_code", fiber.StatusInternalServerError), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusInternalServerError, "failed to update setting") + } + + settingsList, err := h.settingSvc.GetSettingList(c.Context()) + + if err != nil { + h.mongoLoggerSvc.Error("Failed to fetch settings", + zap.Int("status_code", fiber.StatusInternalServerError), + zap.Error(err), + zap.Time("timestamp", time.Now()), + ) + return fiber.NewError(fiber.StatusInternalServerError, "Failed to get setting list:"+err.Error()) + } + + return response.WriteJSON(c, fiber.StatusOK, "setting updated", settingsList, nil) + +} diff --git a/internal/web_server/routes.go b/internal/web_server/routes.go index 8311bb5..941f076 100644 --- a/internal/web_server/routes.go +++ b/internal/web_server/routes.go @@ -336,4 +336,10 @@ func (a *App) initAppRoutes() { groupV1.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues) groupV1.Patch("/issues/:issue_id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus) groupV1.Delete("/issues/:issue_id", a.authMiddleware, a.OnlyAdminAndAbove, h.DeleteIssue) + + // Settings + groupV1.Get("/settings", a.authMiddleware, h.GetSettingList) + groupV1.Get("/settings/:key", a.authMiddleware, h.GetSettingByKey) + groupV1.Put("/settings", a.authMiddleware, h.UpdateSettingList) + } diff --git a/new.env b/new.env new file mode 100755 index 0000000..1d2ac4c --- /dev/null +++ b/new.env @@ -0,0 +1,96 @@ +# REPORT_EXPORT_PATH="C:\\ProgramData\\FortuneBet\\exported_reports" #prod env +# REPORT_EXPORT_PATH ="./exported_reports" #dev env + + +# Telebirr +TELEBIRR_BASE_URL="https://developerportal.ethiotelebirr.et:38443/payment/web/paygate?" +TELEBIRR_APP_SECRET=your_telebirr_app_secret +TELEBIRR_FABRIC_APP_ID=your_telebirr_fabric_app_id +TELEBIRR_MERCHANT_CODE=your_telebirr_merchant_code +TELEBIRR_CALLBACK_URL=https://api.fortunebets.net/api/v1/telebirr/callback + +RESEND_SENDER_EMAIL=email +RESEND_API_KEY=123 + +ENV=development +PORT=8080 +DB_URL=postgresql://root:secret@localhost:5422/gh?sslmode=disable +REFRESH_EXPIRY=2592000 +JWT_KEY=mysecretkey +ACCESS_EXPIRY=600 +LOG_LEVEL=debug +AFRO_SMS_API_KEY=1 +AFRO_SMS_SENDER_NAME= + +AFRO_SMS_RECEIVER_PHONE_NUMBER= +BET365_TOKEN=158046-hesJDP2Cay2M5G +POPOK_CLIENT_ID=1 +POPOK_PLATFORM=111 +POPOK_SECRET_KEY=XwFQ76Y59zBxGryh +# POPOK_BASE_URL=https://api.pokgaming.com/game/launch #Production +# POPOK_BASE_URL=https://games.pokgaming.com/launch #Production +# POPOK_BASE_URL=https://sandbox.pokgaming.com/game/launch #Staging +# POPOK_BASE_URL=https://test-api.pokgaming.com/launch #Staging +POPOK_BASE_URL=https://st.pokgaming.com/ #Staging +POPOK_CALLBACK_URL=https://api.fortunebets.net + +#Muli-currency Support +FIXER_API_KEY=3b0f1eb30d-63c875026d-sxy9pl +BASE_CURRENCY=ETB +FIXER_BASE_URL=https://api.apilayer.com/fixer + +# Chapa API Configuration +CHAPA_TRANSFER_TYPE=Payout +CHAPA_PAYMENT_TYPE=API +CHAPA_BASE_URL=https://api.chapa.co/v1 +CHAPA_ENCRYPTION_KEY=zLdYrjnBCknMvFikmP5jBfen +CHAPA_PUBLIC_KEY=CHAPUBK_TEST-HJR0qhQRPLTkauNy9Q8UrmskPTOR31aC +CHAPA_SECRET_KEY=CHASECK_TEST-q3jypwmFK6XJGYOK3aX4z9Kogd9KaHhF +CHAPA_CALLBACK_URL=https://api.fortunebets.net/api/v1/payments/webhook/verify +CHAPA_RETURN_URL=https://fortunebets.net/dashboard + +#Alea Play +ALEA_ENABLED=true +ALEA_BASE_URL=https://api.aleaplay.com +ALEA_OPERATOR_ID=operator_id +ALEA_SECRET_KEY=hmac_secret +ALEA_GAME_LIST_URL=https://api.aleaplay.com/games/list # Optional +ALEA_DEFAULT_CURRENCY=USD # Optional (default: USD) +ALEA_SESSION_TIMEOUT=24 # Optional (hours, default: 24) +ALEA_GAME_ID_AVIATOR=aviator_prod + + +# Veli Games +VELI_ENABLED=true +VELI_BASE_URL=https://stage-api.velitech.games +VELI_REGIONAL_URL=https://stage-api.velitech.games +VELI_WEBHOOK_URL=https://api.fortunebets.net/ +VELI_SECRET_KEY=qPfg7PyhyOI9d2_bcx3ovKqzMqtjaVen +VELI_OPERATOR_KEY=111 +VELI_OPERATOR_ID=fortune_bets +VELI_BRAND_ID=fortune_bets +VELI_DEFAULT_CURRENCY=ETB + +# Arifpay +ARIFPAY_API_KEY=OV7MLkA39tgWiEApLLSg6aNf4F1RDobV +ARIFPAY_CANCEL_URL=https://api.fortunebets.net/api/v1/payments/arifpay/cancel +ARIFPAY_ERROR_URL=https://api.fortunebets.net/api/v1/payments/arifpay/error +ARIFPAY_NOTIFY_URL=https://api.fortunebets.net/api/v1/payments/arifpay/notify +ARIFPAY_SUCCESS_URL=https://api.fortunebets.net/api/v1/payments/arifpay/success + +# Santimpay +SANTIMPAY_SECRET_KEY=your_santim_pay_secret_key +SANTIMPAY_MERCHANT_ID=your_santim_pay_merchant_id +SANTIMPAY_Base_URL=https://services.santimpay.com/api/v1/gateway + +#MongoDB +MONGODB_URL=mongodb://root:secret@mongo:27017/?authSource=admin + +# Twilio SMS +TWILIO_ACCOUNT_SID=123 +TWILIO_AUTH_TOKEN=2334eadf +TWILIO_SENDER_PHONE_NUMBER=0912345678 + +# Redis +REDIS_ADDR=redis:6379 +