feat: added settings routes
This commit is contained in:
parent
696b713699
commit
5615c93fbb
|
|
@ -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 (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
first_name VARCHAR(255) NOT NULL,
|
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
|
-- Views
|
||||||
CREATE VIEW companies_details AS
|
CREATE VIEW companies_details AS
|
||||||
SELECT companies.*,
|
SELECT companies.*,
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,11 @@
|
||||||
-- Settings Initial Data
|
-- Settings Initial Data
|
||||||
INSERT INTO settings (key, value)
|
INSERT INTO settings (key, value)
|
||||||
VALUES ('sms_provider', '30'),
|
VALUES ('sms_provider', '30'),
|
||||||
<<<<<<< HEAD
|
|
||||||
('max_number_of_outcomes', '30'),
|
|
||||||
('bet_amount_limit', '100000'),
|
|
||||||
=======
|
|
||||||
('max_number_of_outcomes', '30'),
|
('max_number_of_outcomes', '30'),
|
||||||
('bet_amount_limit', '10000000'),
|
('bet_amount_limit', '10000000'),
|
||||||
>>>>>>> 7d8d824a94381bd82c40398654c3bd78218c5950
|
|
||||||
('daily_ticket_limit', '50'),
|
('daily_ticket_limit', '50'),
|
||||||
('total_winnings_limit', '1000000'),
|
('total_winnings_limit', '1000000'),
|
||||||
('amount_for_bet_referral', '1000000'),
|
('amount_for_bet_referral', '1000000'),
|
||||||
('cashback_amount_cap', '1000') ON CONFLICT (key) DO
|
('cashback_amount_cap', '1000') ON CONFLICT (key) DO
|
||||||
UPDATE
|
UPDATE
|
||||||
<<<<<<< HEAD
|
SET value = EXCLUDED.value;
|
||||||
SET value = EXCLUDED.value;
|
|
||||||
=======
|
|
||||||
SET value = EXCLUDED.value;
|
|
||||||
>>>>>>> 7d8d824a94381bd82c40398654c3bd78218c5950
|
|
||||||
|
|
@ -5,9 +5,8 @@ FROM settings;
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM settings
|
FROM settings
|
||||||
WHERE key = $1;
|
WHERE key = $1;
|
||||||
-- name: SaveSetting :one
|
-- name: UpdateSetting :exec
|
||||||
INSERT INTO settings (key, value, updated_at)
|
UPDATE settings
|
||||||
VALUES ($1, $2, CURRENT_TIMESTAMP) ON CONFLICT (key) DO
|
SET value = $2,
|
||||||
UPDATE
|
updated_at = CURRENT_TIMESTAMP
|
||||||
SET value = EXCLUDED.value
|
WHERE key = $1;
|
||||||
RETURNING *;
|
|
||||||
|
|
@ -57,27 +57,19 @@ func (q *Queries) GetSettings(ctx context.Context) ([]Setting, error) {
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const SaveSetting = `-- name: SaveSetting :one
|
const UpdateSetting = `-- name: UpdateSetting :exec
|
||||||
INSERT INTO settings (key, value, updated_at)
|
UPDATE settings
|
||||||
VALUES ($1, $2, CURRENT_TIMESTAMP) ON CONFLICT (key) DO
|
SET value = $2,
|
||||||
UPDATE
|
updated_at = CURRENT_TIMESTAMP
|
||||||
SET value = EXCLUDED.value
|
WHERE key = $1
|
||||||
RETURNING key, value, created_at, updated_at
|
|
||||||
`
|
`
|
||||||
|
|
||||||
type SaveSettingParams struct {
|
type UpdateSettingParams struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) SaveSetting(ctx context.Context, arg SaveSettingParams) (Setting, error) {
|
func (q *Queries) UpdateSetting(ctx context.Context, arg UpdateSettingParams) error {
|
||||||
row := q.db.QueryRow(ctx, SaveSetting, arg.Key, arg.Value)
|
_, err := q.db.Exec(ctx, UpdateSetting, arg.Key, arg.Value)
|
||||||
var i Setting
|
return err
|
||||||
err := row.Scan(
|
|
||||||
&i.Key,
|
|
||||||
&i.Value,
|
|
||||||
&i.CreatedAt,
|
|
||||||
&i.UpdatedAt,
|
|
||||||
)
|
|
||||||
return i, err
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
type Currency int64
|
||||||
|
|
||||||
// ToCurrency converts a float32 to Currency
|
// ToCurrency converts a float32 to Currency
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package domain
|
package domain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -11,9 +12,19 @@ type Setting struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SettingRes struct {
|
type SettingRes struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
UpdatedAt string `json:"updated_at"`
|
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 {
|
type SettingList struct {
|
||||||
|
|
@ -26,7 +37,17 @@ type SettingList struct {
|
||||||
CashbackAmountCap Currency `json:"cashback_amount_cap"`
|
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
|
SMSProvider ValidString
|
||||||
MaxNumberOfOutcomes ValidInt64
|
MaxNumberOfOutcomes ValidInt64
|
||||||
BetAmountLimit ValidInt64
|
BetAmountLimit ValidInt64
|
||||||
|
|
@ -36,7 +57,7 @@ type DBSettingList struct {
|
||||||
CashbackAmountCap ValidInt64
|
CashbackAmountCap ValidInt64
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertInt64SettingsMap(dbSettingList *DBSettingList) map[string]*ValidInt64 {
|
func ConvertInt64SettingsMap(dbSettingList *ValidSettingList) map[string]*ValidInt64 {
|
||||||
return map[string]*ValidInt64{
|
return map[string]*ValidInt64{
|
||||||
"max_number_of_outcomes": &dbSettingList.MaxNumberOfOutcomes,
|
"max_number_of_outcomes": &dbSettingList.MaxNumberOfOutcomes,
|
||||||
"bet_amount_limit": &dbSettingList.BetAmountLimit,
|
"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{
|
return map[string]*ValidString{
|
||||||
"sms_provider": &dbSettingList.SMSProvider,
|
"sms_provider": &dbSettingList.SMSProvider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertBoolSettingsMap(dbSettingList *DBSettingList) map[string]*ValidBool {
|
func ConvertBoolSettingsMap(dbSettingList *ValidSettingList) map[string]*ValidBool {
|
||||||
return 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{}
|
return map[string]*ValidFloat32{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertTimeSettingsMap(dbSettingList *DBSettingList) map[string]*ValidTime {
|
func ConvertTimeSettingsMap(dbSettingList *ValidSettingList) map[string]*ValidTime {
|
||||||
return map[string]*ValidTime{}
|
return map[string]*ValidTime{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertDBSetting(dbSettingList DBSettingList) SettingList {
|
func ValidateSettingList(dbSettingList ValidSettingList) SettingList {
|
||||||
|
// TODO: Add validation here
|
||||||
return SettingList{
|
return SettingList{
|
||||||
SMSProvider: SMSProvider(dbSettingList.SMSProvider.Value),
|
SMSProvider: SMSProvider(dbSettingList.SMSProvider.Value),
|
||||||
MaxNumberOfOutcomes: dbSettingList.MaxNumberOfOutcomes.Value,
|
MaxNumberOfOutcomes: dbSettingList.MaxNumberOfOutcomes.Value,
|
||||||
|
|
@ -76,3 +98,96 @@ func ConvertDBSetting(dbSettingList DBSettingList) SettingList {
|
||||||
CashbackAmountCap: Currency(dbSettingList.CashbackAmountCap.Value),
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||||
var dbSettingList domain.DBSettingList
|
var dbSettingList domain.ValidSettingList
|
||||||
|
|
||||||
var int64SettingsMap = domain.ConvertInt64SettingsMap(&dbSettingList)
|
var int64SettingsMap = domain.ConvertInt64SettingsMap(&dbSettingList)
|
||||||
var stringSettingsMap = domain.ConvertStringSettingsMap(&dbSettingList)
|
var stringSettingsMap = domain.ConvertStringSettingsMap(&dbSettingList)
|
||||||
|
|
@ -21,7 +21,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||||
var timeSettingsMap = domain.ConvertTimeSettingsMap(&dbSettingList)
|
var timeSettingsMap = domain.ConvertTimeSettingsMap(&dbSettingList)
|
||||||
|
|
||||||
for _, setting := range settings {
|
for _, setting := range settings {
|
||||||
is_setting_unknown := true
|
isSettingUnknown := true
|
||||||
for key, dbSetting := range int64SettingsMap {
|
for key, dbSetting := range int64SettingsMap {
|
||||||
if setting.Key == key {
|
if setting.Key == key {
|
||||||
value, err := strconv.ParseInt(setting.Value, 10, 64)
|
value, err := strconv.ParseInt(setting.Value, 10, 64)
|
||||||
|
|
@ -32,7 +32,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||||
Value: value,
|
Value: value,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
}
|
}
|
||||||
is_setting_unknown = false
|
isSettingUnknown = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,7 +42,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||||
Value: setting.Value,
|
Value: setting.Value,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
}
|
}
|
||||||
is_setting_unknown = false
|
isSettingUnknown = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||||
Value: value,
|
Value: value,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
}
|
}
|
||||||
is_setting_unknown = false
|
isSettingUnknown = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,7 +70,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||||
Value: float32(value),
|
Value: float32(value),
|
||||||
Valid: true,
|
Valid: true,
|
||||||
}
|
}
|
||||||
is_setting_unknown = false
|
isSettingUnknown = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for key, dbSetting := range timeSettingsMap {
|
for key, dbSetting := range timeSettingsMap {
|
||||||
|
|
@ -83,11 +83,11 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||||
Value: value,
|
Value: value,
|
||||||
Valid: true,
|
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))
|
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) {
|
func (s *Store) GetSettingList(ctx context.Context) (domain.SettingList, error) {
|
||||||
settings, err := s.queries.GetSettings(ctx)
|
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
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) SaveSetting(ctx context.Context, key, value string) (domain.Setting, error) {
|
func (s *Store) UpdateSetting(ctx context.Context, key, value string) error {
|
||||||
dbSetting, err := s.queries.SaveSetting(ctx, dbgen.SaveSettingParams{
|
err := s.queries.UpdateSetting(ctx, dbgen.UpdateSettingParams{
|
||||||
Key: key,
|
Key: key,
|
||||||
Value: value,
|
Value: value,
|
||||||
})
|
})
|
||||||
|
|
@ -154,14 +154,22 @@ func (s *Store) SaveSetting(ctx context.Context, key, value string) (domain.Sett
|
||||||
if err != nil {
|
if err != nil {
|
||||||
domain.MongoDBLogger.Error("failed to update setting", zap.String("key", key), zap.String("value", value), zap.Error(err))
|
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{
|
return err
|
||||||
Key: dbSetting.Key,
|
|
||||||
Value: dbSetting.Value,
|
|
||||||
}
|
|
||||||
|
|
||||||
return setting, 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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,5 +10,6 @@ type SettingStore interface {
|
||||||
GetSettingList(ctx context.Context) (domain.SettingList, error)
|
GetSettingList(ctx context.Context) (domain.SettingList, error)
|
||||||
GetSettings(ctx context.Context) ([]domain.Setting, error)
|
GetSettings(ctx context.Context) ([]domain.Setting, error)
|
||||||
GetSetting(ctx context.Context, key string) (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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
func (s *Service) GetSetting(ctx context.Context, key string) (domain.Setting, error) {
|
||||||
return s.settingStore.GetSetting(ctx, key)
|
return s.settingStore.GetSetting(ctx, key)
|
||||||
}
|
}
|
||||||
func (s *Service) SaveSetting(ctx context.Context, key, value string) (domain.Setting, error) {
|
func (s *Service) UpdateSetting(ctx context.Context, key, value string) error {
|
||||||
return s.settingStore.SaveSetting(ctx, key, value)
|
return s.settingStore.UpdateSetting(ctx, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) UpdateSettingList(ctx context.Context, settingList domain.ValidSettingList) error {
|
||||||
|
return s.settingStore.UpdateSettingList(ctx, settingList)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -863,7 +863,7 @@ func (h *Handler) UpdateBranch(c *fiber.Ctx) error {
|
||||||
var req domain.UpdateBranchReq
|
var req domain.UpdateBranchReq
|
||||||
|
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
zap.Time("timestamp", time.Now()),
|
||||||
|
|
@ -879,7 +879,6 @@ func (h *Handler) UpdateBranch(c *fiber.Ctx) error {
|
||||||
h.mongoLoggerSvc.Info("Failed to validate UpdateBranchReq",
|
h.mongoLoggerSvc.Info("Failed to validate UpdateBranchReq",
|
||||||
zap.String("branchID", branchID),
|
zap.String("branchID", branchID),
|
||||||
zap.Int("status_code", fiber.StatusBadRequest),
|
zap.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
|
||||||
zap.String("errMsg", errMsg),
|
zap.String("errMsg", errMsg),
|
||||||
zap.Time("timestamp", time.Now()),
|
zap.Time("timestamp", time.Now()),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
105
internal/web_server/handlers/settings_handler.go
Normal file
105
internal/web_server/handlers/settings_handler.go
Normal file
|
|
@ -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)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -336,4 +336,10 @@ func (a *App) initAppRoutes() {
|
||||||
groupV1.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues)
|
groupV1.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues)
|
||||||
groupV1.Patch("/issues/:issue_id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus)
|
groupV1.Patch("/issues/:issue_id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus)
|
||||||
groupV1.Delete("/issues/:issue_id", a.authMiddleware, a.OnlyAdminAndAbove, h.DeleteIssue)
|
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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
96
new.env
Executable file
96
new.env
Executable file
|
|
@ -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
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user