fix: Refactored and moved store ports into separate folder

- Added stats service
This commit is contained in:
Samuel Tariku 2025-10-29 01:33:50 +03:00
parent 0ffba57ec5
commit e5fdd33a52
114 changed files with 2063 additions and 1692 deletions

View File

@ -17,5 +17,7 @@
"**/internal/services/**/*.go": "${filename}.${dirname}.service", "**/internal/services/**/*.go": "${filename}.${dirname}.service",
"**/internal/domain/**/*.go": "${filename}.${dirname}", "**/internal/domain/**/*.go": "${filename}.${dirname}",
"**/internal/repository/**/*.go": "${filename}.repo", "**/internal/repository/**/*.go": "${filename}.repo",
"**/internal/ports/**/*.go": "${filename}.ports",
"**/internal/web_server/handlers/**/*.go": "${filename}.handlers",
}, },
} }

View File

@ -52,6 +52,7 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/santimpay" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/santimpay"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/stats"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/telebirr" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/telebirr"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
@ -109,86 +110,170 @@ func main() {
v := customvalidator.NewCustomValidator(validator.New()) v := customvalidator.NewCustomValidator(validator.New())
// Initialize services // Initialize services
settingSvc := settings.NewService(store) settingSvc := settings.NewService(repository.NewSettingStore(store))
messengerSvc := messenger.NewService(settingSvc, cfg) messengerSvc := messenger.NewService(settingSvc, cfg)
statSvc := stats.NewService(
repository.NewCompanyStatStore(store),
repository.NewEventStatStore(store),
)
authSvc := authentication.NewService(store, store, cfg.RefreshExpiry) authSvc := authentication.NewService(
userSvc := user.NewService(store, store, messengerSvc, cfg) repository.NewUserStore(store),
eventSvc := event.New(cfg.Bet365Token, store, settingSvc, domain.MongoDBLogger, cfg) repository.NewTokenStore(store),
oddsSvc := odds.New(store, cfg, eventSvc, logger, domain.MongoDBLogger) cfg.RefreshExpiry,
notificationRepo := repository.NewNotificationRepository(store) )
virtuaGamesRepo := repository.NewVirtualGameRepository(store) userSvc := user.NewService(
// var userStore user.UserStore repository.NewUserStore(store),
repository.NewOTPStore(store),
messengerSvc,
cfg,
)
leagueSvc := league.New(repository.NewLeagueStore(store))
eventSvc := event.New(
cfg.Bet365Token,
repository.NewEventStore(store),
repository.NewEventHistoryStore(store),
*leagueSvc,
settingSvc,
domain.MongoDBLogger,
cfg,
)
oddsSvc := odds.New(
repository.NewOddStore(store),
cfg,
eventSvc,
logger,
domain.MongoDBLogger,
)
// virtuaGamesRepo := repository.NewVirtualGameRepository(store)
// Initialize producer // Initialize producer
// topic := "wallet-balance-topic" // topic := "wallet-balance-topic"
// producer := kafka.NewProducer(cfg.KafkaBrokers, topic) // producer := kafka.NewProducer(cfg.KafkaBrokers, topic)
notificationSvc := notificationservice.New(notificationRepo, domain.MongoDBLogger, logger, cfg, messengerSvc, userSvc) notificationSvc := notificationservice.New(
repository.NewNotificationStore(store),
domain.MongoDBLogger,
logger,
cfg,
messengerSvc,
userSvc,
)
walletSvc := wallet.NewService( walletSvc := wallet.NewService(
wallet.WalletStore(store), repository.NewWalletStore(store),
wallet.TransferStore(store), repository.NewTransferStore(store),
wallet.DirectDepositStore(store), repository.NewDirectDepositStore(store),
notificationSvc, notificationSvc,
userSvc, userSvc,
domain.MongoDBLogger, domain.MongoDBLogger,
logger, logger,
) )
branchSvc := branch.NewService(store) branchSvc := branch.NewService(repository.NewBranchStore(store))
companySvc := company.NewService(store) companySvc := company.NewService(repository.NewCompanyStore(store))
leagueSvc := league.New(store)
ticketSvc := ticket.NewService(store, eventSvc, *oddsSvc, domain.MongoDBLogger, settingSvc, notificationSvc) ticketSvc := ticket.NewService(
betSvc := bet.NewService(store, eventSvc, *oddsSvc, *walletSvc, *branchSvc, *companySvc, *settingSvc, *userSvc, notificationSvc, logger, domain.MongoDBLogger) repository.NewTicketStore(store),
resultSvc := result.NewService(store, cfg, logger, domain.MongoDBLogger, *betSvc, *oddsSvc, eventSvc, leagueSvc, notificationSvc, messengerSvc, *userSvc) eventSvc,
bonusSvc := bonus.NewService(store, walletSvc, settingSvc, notificationSvc, domain.MongoDBLogger) *oddsSvc,
referalRepo := repository.NewReferralRepository(store) domain.MongoDBLogger,
settingSvc,
)
betSvc := bet.NewService(
repository.NewBetStore(store),
eventSvc,
*oddsSvc,
*walletSvc,
*branchSvc,
*companySvc,
*settingSvc,
*userSvc,
notificationSvc,
logger,
domain.MongoDBLogger,
)
resultSvc := result.NewService(
repository.NewResultLogStore(store),
cfg,
logger,
domain.MongoDBLogger,
*betSvc,
*oddsSvc,
eventSvc,
leagueSvc,
notificationSvc,
messengerSvc,
*userSvc,
)
bonusSvc := bonus.NewService(
repository.NewBonusStore(store),
walletSvc,
settingSvc,
notificationSvc,
domain.MongoDBLogger,
)
vitualGameRepo := repository.NewVirtualGameRepository(store) vitualGameRepo := repository.NewVirtualGameRepository(store)
recommendationRepo := repository.NewRecommendationRepository(store) recommendationRepo := repository.NewRecommendationRepository(store)
referalSvc := referralservice.New(referalRepo, *walletSvc, *settingSvc, cfg, logger, domain.MongoDBLogger) referalSvc := referralservice.New(
raffleSvc := raffle.NewService(store) repository.NewReferralStore(store),
*walletSvc,
*settingSvc,
cfg,
logger,
domain.MongoDBLogger,
)
raffleSvc := raffle.NewService(
repository.NewRaffleStore(store),
)
virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger) virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger)
aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger) aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger)
veliCLient := veli.NewClient(cfg, walletSvc) veliCLient := veli.NewClient(cfg, walletSvc)
veliVirtualGameService := veli.New(virtualGameSvc, vitualGameRepo, veliCLient, walletSvc, wallet.TransferStore(store), domain.MongoDBLogger, cfg) veliVirtualGameService := veli.New(virtualGameSvc, vitualGameRepo, veliCLient, walletSvc, repository.NewTransferStore(store), domain.MongoDBLogger, cfg)
atlasClient := atlas.NewClient(cfg, walletSvc) atlasClient := atlas.NewClient(cfg, walletSvc)
atlasVirtualGameService := atlas.New(virtualGameSvc, vitualGameRepo, atlasClient, walletSvc, wallet.TransferStore(store), cfg) atlasVirtualGameService := atlas.New(virtualGameSvc, vitualGameRepo, atlasClient, walletSvc, repository.NewTransferStore(store), cfg)
recommendationSvc := recommendation.NewService(recommendationRepo) recommendationSvc := recommendation.NewService(recommendationRepo)
chapaClient := chapa.NewClient(cfg.CHAPA_BASE_URL, cfg.CHAPA_SECRET_KEY) chapaClient := chapa.NewClient(cfg.CHAPA_BASE_URL, cfg.CHAPA_SECRET_KEY)
chapaSvc := chapa.NewService( chapaSvc := chapa.NewService(
wallet.TransferStore(store), repository.NewTransferStore(store),
*walletSvc, *walletSvc,
user.UserStore(store), repository.NewUserStore(store),
cfg, cfg,
chapaClient, chapaClient,
) )
reportRepo := repository.NewReportRepo(store)
currRepo := repository.NewCurrencyPostgresRepository(store) currRepo := repository.NewCurrencyPostgresRepository(store)
fixerFertcherSvc := currency.NewFixerFetcher( fixerFertcherSvc := currency.NewFixerFetcher(
cfg.FIXER_API_KEY, cfg.FIXER_API_KEY,
cfg.FIXER_BASE_URL, cfg.FIXER_BASE_URL,
) )
transactionSvc := transaction.NewService(store, *branchSvc, *betSvc, *walletSvc, *userSvc) transactionSvc := transaction.NewService(
repository.NewTransactionStore(store),
*branchSvc,
*betSvc,
*walletSvc,
*userSvc,
)
reportSvc := report.NewService( reportSvc := report.NewService(
store, repository.NewReportStore(store),
bet.BetStore(store), repository.NewBetStore(store),
wallet.WalletStore(store), repository.NewWalletStore(store),
transaction.TransactionStore(store), repository.NewTransactionStore(store),
branch.BranchStore(store), repository.NewBranchStore(store),
user.UserStore(store), repository.NewUserStore(store),
reportRepo, repository.NewOldRepositoryStore(store),
company.CompanyStore(store), repository.NewCompanyStore(store),
virtuaGamesRepo, repository.NewVirtualGameRepository(store),
notificationRepo, repository.NewNotificationStore(store),
notificationSvc, notificationSvc,
eventSvc, statSvc,
companySvc,
logger, logger,
domain.MongoDBLogger, domain.MongoDBLogger,
cfg, cfg,
@ -242,16 +327,16 @@ func main() {
defer exchangeWorker.Stop() defer exchangeWorker.Stop()
go walletMonitorSvc.Start() go walletMonitorSvc.Start()
httpserver.StartDataFetchingCrons(eventSvc, *oddsSvc, resultSvc, domain.MongoDBLogger) httpserver.StartBetAPIDataFetchingCrons(eventSvc, *oddsSvc, resultSvc, domain.MongoDBLogger)
httpserver.StartCleanupCrons(*ticketSvc, notificationSvc, domain.MongoDBLogger) httpserver.StartCleanupCrons(*ticketSvc, notificationSvc, domain.MongoDBLogger)
httpserver.StartStatCrons(*companySvc, eventSvc, domain.MongoDBLogger) httpserver.StartStatCrons(statSvc, domain.MongoDBLogger)
httpserver.StartReportCrons(reportSvc, domain.MongoDBLogger) httpserver.StartReportCrons(reportSvc, domain.MongoDBLogger)
issueReportingRepo := repository.NewReportedIssueRepository(store) issueReportingRepo := repository.NewReportedIssueRepository(store)
issueReportingSvc := issuereporting.New(issueReportingRepo) issueReportingSvc := issuereporting.New(issueReportingRepo)
transferStore := wallet.TransferStore(store) transferStore := repository.NewTransferStore(store)
// walletStore := wallet.WalletStore(store) // walletStore := wallet.WalletStore(store)
arifpaySvc := arifpay.NewArifpayService(cfg, transferStore, walletSvc, &http.Client{ arifpaySvc := arifpay.NewArifpayService(cfg, transferStore, walletSvc, &http.Client{
@ -303,6 +388,7 @@ func main() {
// veliService, // veliService,
recommendationSvc, recommendationSvc,
resultSvc, resultSvc,
statSvc,
cfg, cfg,
domain.MongoDBLogger, domain.MongoDBLogger,
) )

View File

@ -393,14 +393,6 @@ CREATE TABLE odd_history (
odd_value DOUBLE PRECISION NOT NULL, odd_value DOUBLE PRECISION NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
); );
CREATE TABLE disabled_odd (
id BIGSERIAL PRIMARY KEY,
company_id BIGINT NOT NULL,
odds_market_id BIGINT NOT NULL,
raw_odd_id BIGINT NOT NULL,
event_id BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE company_odd_settings ( CREATE TABLE company_odd_settings (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
company_id BIGINT NOT NULL, company_id BIGINT NOT NULL,

View File

@ -1,26 +0,0 @@
-- name: InsertDisabledOdds :one
INSERT INTO disabled_odd (
odds_market_id,
company_id,
event_id,
raw_odd_id
)
VALUES ($1, $2, $3, $4)
RETURNING *;
-- name: GetAllDisabledOdds :many
SELECT *
FROM disabled_odd;
-- name: GetDisabledOddByRawOddID :one
SELECT *
FROM disabled_odd
WHERE raw_odd_id = $1;
-- name: GetDisabledOddByID :one
SELECT *
FROM disabled_odd
WHERE raw_odd_id = $1;
-- name: DeleteDisabledOddsByID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1;
-- name: DeleteDisabledOddsByRawOddID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1;

View File

@ -1,139 +0,0 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: disabled_odds.sql
package dbgen
import (
"context"
)
const DeleteDisabledOddsByID = `-- name: DeleteDisabledOddsByID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) DeleteDisabledOddsByID(ctx context.Context, rawOddID int64) error {
_, err := q.db.Exec(ctx, DeleteDisabledOddsByID, rawOddID)
return err
}
const DeleteDisabledOddsByRawOddID = `-- name: DeleteDisabledOddsByRawOddID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) DeleteDisabledOddsByRawOddID(ctx context.Context, rawOddID int64) error {
_, err := q.db.Exec(ctx, DeleteDisabledOddsByRawOddID, rawOddID)
return err
}
const GetAllDisabledOdds = `-- name: GetAllDisabledOdds :many
SELECT id, company_id, odds_market_id, raw_odd_id, event_id, created_at
FROM disabled_odd
`
func (q *Queries) GetAllDisabledOdds(ctx context.Context) ([]DisabledOdd, error) {
rows, err := q.db.Query(ctx, GetAllDisabledOdds)
if err != nil {
return nil, err
}
defer rows.Close()
var items []DisabledOdd
for rows.Next() {
var i DisabledOdd
if err := rows.Scan(
&i.ID,
&i.CompanyID,
&i.OddsMarketID,
&i.RawOddID,
&i.EventID,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const GetDisabledOddByID = `-- name: GetDisabledOddByID :one
SELECT id, company_id, odds_market_id, raw_odd_id, event_id, created_at
FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) GetDisabledOddByID(ctx context.Context, rawOddID int64) (DisabledOdd, error) {
row := q.db.QueryRow(ctx, GetDisabledOddByID, rawOddID)
var i DisabledOdd
err := row.Scan(
&i.ID,
&i.CompanyID,
&i.OddsMarketID,
&i.RawOddID,
&i.EventID,
&i.CreatedAt,
)
return i, err
}
const GetDisabledOddByRawOddID = `-- name: GetDisabledOddByRawOddID :one
SELECT id, company_id, odds_market_id, raw_odd_id, event_id, created_at
FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) GetDisabledOddByRawOddID(ctx context.Context, rawOddID int64) (DisabledOdd, error) {
row := q.db.QueryRow(ctx, GetDisabledOddByRawOddID, rawOddID)
var i DisabledOdd
err := row.Scan(
&i.ID,
&i.CompanyID,
&i.OddsMarketID,
&i.RawOddID,
&i.EventID,
&i.CreatedAt,
)
return i, err
}
const InsertDisabledOdds = `-- name: InsertDisabledOdds :one
INSERT INTO disabled_odd (
odds_market_id,
company_id,
event_id,
raw_odd_id
)
VALUES ($1, $2, $3, $4)
RETURNING id, company_id, odds_market_id, raw_odd_id, event_id, created_at
`
type InsertDisabledOddsParams struct {
OddsMarketID int64 `json:"odds_market_id"`
CompanyID int64 `json:"company_id"`
EventID int64 `json:"event_id"`
RawOddID int64 `json:"raw_odd_id"`
}
func (q *Queries) InsertDisabledOdds(ctx context.Context, arg InsertDisabledOddsParams) (DisabledOdd, error) {
row := q.db.QueryRow(ctx, InsertDisabledOdds,
arg.OddsMarketID,
arg.CompanyID,
arg.EventID,
arg.RawOddID,
)
var i DisabledOdd
err := row.Scan(
&i.ID,
&i.CompanyID,
&i.OddsMarketID,
&i.RawOddID,
&i.EventID,
&i.CreatedAt,
)
return i, err
}

View File

@ -279,15 +279,6 @@ type DirectDeposit struct {
VerifiedAt pgtype.Timestamp `json:"verified_at"` VerifiedAt pgtype.Timestamp `json:"verified_at"`
} }
type DisabledOdd struct {
ID int64 `json:"id"`
CompanyID int64 `json:"company_id"`
OddsMarketID int64 `json:"odds_market_id"`
RawOddID int64 `json:"raw_odd_id"`
EventID int64 `json:"event_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}
type EnetpulseSport struct { type EnetpulseSport struct {
ID int64 `json:"id"` ID int64 `json:"id"`
SportID string `json:"sport_id"` SportID string `json:"sport_id"`

View File

@ -0,0 +1,113 @@
package domain
import (
"time"
"math/big"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/jackc/pgx/v5/pgtype"
)
type DirectDepositStatus string
const (
DepositStatusPending DirectDepositStatus = "pending"
DepositStatusCompleted DirectDepositStatus = "completed"
DepositStatusRejected DirectDepositStatus = "rejected"
)
type DirectDeposit struct {
ID int64 `json:"id"`
CustomerID int64 `json:"customer_id"`
WalletID int64 `json:"wallet_id"`
Wallet Wallet `json:"wallet"`
Amount Currency `json:"amount"`
BankReference string `json:"bank_reference"`
SenderAccount string `json:"sender_account"`
Status DirectDepositStatus `json:"status"`
CreatedAt time.Time `json:"created_at"`
VerifiedBy *int64 `json:"verified_by"`
VerificationNotes string `json:"verification_notes"`
VerifiedAt *time.Time `json:"verified_at"`
}
type CreateDirectDeposit struct {
CustomerID int64
WalletID int64
Amount Currency
BankReference string
SenderAccount string
Status DirectDepositStatus
}
type UpdateDirectDeposit struct {
ID int64
Status DirectDepositStatus
VerifiedBy int64
VerificationNotes string
VerifiedAt time.Time
}
type DirectDepositRequest struct {
CustomerID int64 `json:"customer_id" binding:"required"`
Amount Currency `json:"amount" binding:"required,gt=0"`
BankReference string `json:"bank_reference" binding:"required"`
SenderAccount string `json:"sender_account" binding:"required"`
}
type VerifyDirectDepositRequest struct {
DepositID int64 `json:"deposit_id" binding:"required"`
IsVerified bool `json:"is_verified" binding:"required"`
Notes string `json:"notes"`
}
func ConvertDBDirectDeposit(deposit dbgen.DirectDeposit) DirectDeposit {
return DirectDeposit{
ID: deposit.ID,
CustomerID: deposit.CustomerID,
WalletID: deposit.WalletID,
Amount: Currency(deposit.Amount.Int.Int64()),
BankReference: deposit.BankReference,
SenderAccount: deposit.SenderAccount,
Status: DirectDepositStatus(deposit.Status),
CreatedAt: deposit.CreatedAt.Time,
VerifiedBy: convertPgInt64ToPtr(deposit.VerifiedBy),
VerificationNotes: deposit.VerificationNotes.String,
VerifiedAt: convertPgTimeToPtr(deposit.VerifiedAt),
}
}
func ConvertCreateDirectDeposit(deposit CreateDirectDeposit) dbgen.CreateDirectDepositParams {
return dbgen.CreateDirectDepositParams{
CustomerID: deposit.CustomerID,
WalletID: deposit.WalletID,
Amount: pgtype.Numeric{Int: big.NewInt(int64(deposit.Amount)), Valid: true},
BankReference: deposit.BankReference,
SenderAccount: deposit.SenderAccount,
Status: string(deposit.Status),
}
}
func ConvertUpdateDirectDeposit(deposit UpdateDirectDeposit) dbgen.UpdateDirectDepositParams {
return dbgen.UpdateDirectDepositParams{
ID: deposit.ID,
Status: string(deposit.Status),
VerifiedBy: pgtype.Int8{Int64: deposit.VerifiedBy, Valid: true},
VerificationNotes: pgtype.Text{String: deposit.VerificationNotes, Valid: deposit.VerificationNotes != ""},
VerifiedAt: pgtype.Timestamp{Time: deposit.VerifiedAt, Valid: true},
}
}
func convertPgInt64ToPtr(i pgtype.Int8) *int64 {
if i.Valid {
return &i.Int64
}
return nil
}
func convertPgTimeToPtr(t pgtype.Timestamp) *time.Time {
if t.Valid {
return &t.Time
}
return nil
}

View File

@ -1,51 +0,0 @@
package domain
import (
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
)
type DisabledOdd struct {
ID int64
OddMarketID int64
RawOddID int64
EventID int64
CompanyID int64
CreatedAt time.Time
}
type CreateDisabledOdd struct {
OddMarketID int64
RawOddID int64
EventID int64
CompanyID int64
}
func ConvertCreateDisabledOdd(odd CreateDisabledOdd) dbgen.InsertDisabledOddsParams {
return dbgen.InsertDisabledOddsParams{
OddsMarketID: odd.OddMarketID,
EventID: odd.EventID,
CompanyID: odd.CompanyID,
RawOddID: odd.RawOddID,
}
}
func ConvertDBDisabledOdd(dbDisabledOdd dbgen.DisabledOdd) DisabledOdd {
return DisabledOdd{
ID: dbDisabledOdd.ID,
OddMarketID: dbDisabledOdd.OddsMarketID,
RawOddID: dbDisabledOdd.RawOddID,
EventID: dbDisabledOdd.EventID,
CompanyID: dbDisabledOdd.CompanyID,
CreatedAt: dbDisabledOdd.CreatedAt.Time,
}
}
func ConvertDisabledOdds(list []dbgen.DisabledOdd) []DisabledOdd {
result := make([]DisabledOdd, 0, len(list))
for _, item := range list {
result = append(result, ConvertDBDisabledOdd(item))
}
return result
}

View File

@ -1,6 +1,11 @@
package domain package domain
import "time" import (
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/jackc/pgx/v5/pgtype"
)
type Raffle struct { type Raffle struct {
ID int32 ID int32
@ -83,3 +88,62 @@ type UpdateRaffleParams struct {
Name string `json:"name" validate:"required_without_all=ExpiresAt"` Name string `json:"name" validate:"required_without_all=ExpiresAt"`
ExpiresAt *time.Time `json:"expires_at" validate:"required_without_all=Name"` ExpiresAt *time.Time `json:"expires_at" validate:"required_without_all=Name"`
} }
func ConvertRaffleOutcome(raffle dbgen.Raffle) Raffle {
return Raffle{
ID: raffle.ID,
CompanyID: raffle.CompanyID,
Name: raffle.Name,
CreatedAt: raffle.CreatedAt.Time,
ExpiresAt: raffle.ExpiresAt.Time,
TicketLimit: raffle.TicketLimit,
Type: raffle.Type,
Status: raffle.Status,
}
}
func ConvertRaffleTicketOutcome(raffle dbgen.RaffleTicket) RaffleTicket {
return RaffleTicket{
ID: raffle.ID,
RaffleID: raffle.RaffleID,
UserID: raffle.UserID,
IsActive: raffle.IsActive.Bool,
}
}
func ConvertJoinedRaffleTicketOutcome(raffle dbgen.GetUserRaffleTicketsRow) RaffleTicketRes {
return RaffleTicketRes{
TicketID: raffle.TicketID,
UserID: raffle.UserID,
Name: raffle.Name,
Type: raffle.Type,
ExpiresAt: raffle.ExpiresAt.Time,
Status: raffle.Status,
}
}
func ConvertCreateRaffle(raffle CreateRaffle) dbgen.CreateRaffleParams {
return dbgen.CreateRaffleParams{
CompanyID: raffle.CompanyID,
Name: raffle.Name,
ExpiresAt: pgtype.Timestamp{
Time: *raffle.ExpiresAt,
Valid: true,
},
TicketLimit: raffle.TicketLimit,
Type: raffle.Type,
}
}
func ConvertRaffleStanding(raffleStanding dbgen.GetRaffleStandingRow) RaffleStanding {
return RaffleStanding{
UserID: raffleStanding.UserID,
RaffleID: raffleStanding.RaffleID,
FirstName: raffleStanding.FirstName,
LastName: raffleStanding.LastName,
PhoneNumber: raffleStanding.PhoneNumber.String,
Email: raffleStanding.Email.String,
TicketCount: raffleStanding.TicketCount,
}
}

View File

@ -1,6 +1,10 @@
package domain package domain
import "time" import (
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
)
type ShopTransactionType int type ShopTransactionType int
@ -191,3 +195,121 @@ func ConvertShopTransactionDetail(transaction ShopTransactionDetail) ShopTransac
type UpdateTransactionVerifiedReq struct { type UpdateTransactionVerifiedReq struct {
Verified bool `json:"verified" example:"true"` Verified bool `json:"verified" example:"true"`
} }
func ConvertDBShopTransaction(transaction dbgen.ShopTransaction) ShopTransaction {
return ShopTransaction{
ID: transaction.ID,
Amount: Currency(transaction.Amount),
BranchID: transaction.BranchID,
UserID: transaction.UserID,
Type: ShopTransactionType(transaction.Type),
PaymentOption: PaymentOption(transaction.PaymentOption),
FullName: transaction.FullName,
PhoneNumber: transaction.PhoneNumber,
BankCode: ValidString{
Value: transaction.BankCode.String,
Valid: transaction.BankCode.Valid,
},
BeneficiaryName: ValidString{
Value: transaction.BeneficiaryName.String,
Valid: transaction.BeneficiaryName.Valid,
},
AccountName: ValidString{
Value: transaction.AccountName.String,
Valid: transaction.AccountName.Valid,
},
AccountNumber: ValidString{
Value: transaction.AccountName.String,
Valid: transaction.AccountNumber.Valid,
},
ReferenceNumber: ValidString{
Value: transaction.ReferenceNumber.String,
Valid: transaction.ReferenceNumber.Valid,
},
ApprovedBy: ValidInt64{
Value: transaction.ApprovedBy.Int64,
Valid: transaction.ApprovedBy.Valid,
},
CreatedAt: transaction.CreatedAt.Time,
UpdatedAt: transaction.UpdatedAt.Time,
Verified: transaction.Verified,
CompanyID: transaction.CompanyID,
}
}
func ConvertDBShopTransactionDetail(transaction dbgen.ShopTransactionDetail) ShopTransactionDetail {
return ShopTransactionDetail{
ID: transaction.ID,
Amount: Currency(transaction.Amount),
BranchID: transaction.BranchID,
UserID: transaction.UserID,
CreatorFirstName: transaction.CreatorFirstName.String,
CreatorLastName: transaction.CreatorLastName.String,
CreatorPhoneNumber: transaction.CreatorPhoneNumber.String,
Type: ShopTransactionType(transaction.Type),
PaymentOption: PaymentOption(transaction.PaymentOption),
FullName: transaction.FullName,
PhoneNumber: transaction.PhoneNumber,
BankCode: ValidString{
Value: transaction.BankCode.String,
Valid: transaction.BankCode.Valid,
},
BeneficiaryName: ValidString{
Value: transaction.BeneficiaryName.String,
Valid: transaction.BeneficiaryName.Valid,
},
AccountName: ValidString{
Value: transaction.AccountName.String,
Valid: transaction.AccountName.Valid,
},
AccountNumber: ValidString{
Value: transaction.AccountName.String,
Valid: transaction.AccountNumber.Valid,
},
ReferenceNumber: ValidString{
Value: transaction.ReferenceNumber.String,
Valid: transaction.ReferenceNumber.Valid,
},
ApprovedBy: ValidInt64{
Value: transaction.ApprovedBy.Int64,
Valid: transaction.ApprovedBy.Valid,
},
ApproverFirstName: ValidString{
Value: transaction.ApproverFirstName.String,
Valid: transaction.ApproverFirstName.Valid,
},
ApproverLastName: ValidString{
Value: transaction.ApproverLastName.String,
Valid: transaction.ApproverLastName.Valid,
},
ApproverPhoneNumber: ValidString{
Value: transaction.ApproverPhoneNumber.String,
Valid: transaction.ApproverPhoneNumber.Valid,
},
CreatedAt: transaction.CreatedAt.Time,
UpdatedAt: transaction.UpdatedAt.Time,
Verified: transaction.Verified,
CompanyID: transaction.CompanyID,
BranchName: transaction.BranchName.String,
BranchLocation: transaction.BranchLocation.String,
}
}
func ConvertCreateShopTransaction(transaction CreateShopTransaction) dbgen.CreateShopTransactionParams {
return dbgen.CreateShopTransactionParams{
Amount: int64(transaction.Amount),
BranchID: transaction.BranchID,
UserID: transaction.UserID,
Type: int64(transaction.Type),
PaymentOption: int64(transaction.PaymentOption),
FullName: transaction.FullName,
PhoneNumber: transaction.PhoneNumber,
CompanyID: transaction.CompanyID,
BankCode: transaction.BankCode.ToPG(),
BeneficiaryName: transaction.BeneficiaryName.ToPG(),
AccountName: transaction.AccountName.ToPG(),
AccountNumber: transaction.AccountNumber.ToPG(),
ReferenceNumber: transaction.ReferenceNumber.ToPG(),
}
}

View File

@ -1,6 +1,11 @@
package domain package domain
import "time" import (
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/jackc/pgx/v5/pgtype"
)
type TicketOutcome struct { type TicketOutcome struct {
ID int64 `json:"id" example:"1"` ID int64 `json:"id" example:"1"`
@ -89,3 +94,72 @@ type TicketRes struct {
type TicketFilter struct { type TicketFilter struct {
CompanyID ValidInt64 CompanyID ValidInt64
} }
func ConvertDBTicket(ticket dbgen.Ticket) Ticket {
return Ticket{
ID: ticket.ID,
Amount: Currency(ticket.Amount),
TotalOdds: ticket.TotalOdds,
CompanyID: ticket.CompanyID,
}
}
func ConvertDBTicketOutcomes(ticket dbgen.TicketWithOutcome) GetTicket {
var outcomes []TicketOutcome = make([]TicketOutcome, 0, len(ticket.Outcomes))
for _, outcome := range ticket.Outcomes {
outcomes = append(outcomes, TicketOutcome{
ID: outcome.ID,
TicketID: outcome.TicketID,
EventID: outcome.EventID,
OddID: outcome.OddID,
HomeTeamName: outcome.HomeTeamName,
AwayTeamName: outcome.AwayTeamName,
MarketID: outcome.MarketID,
MarketName: outcome.MarketName,
Odd: outcome.Odd,
OddName: outcome.OddName,
OddHeader: outcome.OddHeader,
OddHandicap: outcome.OddHandicap,
Status: OutcomeStatus(outcome.Status),
Expires: outcome.Expires.Time,
})
}
return GetTicket{
ID: ticket.ID,
CompanyID: ticket.CompanyID,
Amount: Currency(ticket.Amount),
TotalOdds: ticket.TotalOdds,
Outcomes: outcomes,
}
}
func ConvertDBCreateTicketOutcome(ticketOutcome CreateTicketOutcome) dbgen.CreateTicketOutcomeParams {
return dbgen.CreateTicketOutcomeParams{
TicketID: ticketOutcome.TicketID,
EventID: ticketOutcome.EventID,
OddID: ticketOutcome.OddID,
HomeTeamName: ticketOutcome.HomeTeamName,
AwayTeamName: ticketOutcome.AwayTeamName,
MarketID: ticketOutcome.MarketID,
MarketName: ticketOutcome.MarketName,
Odd: ticketOutcome.Odd,
OddName: ticketOutcome.OddName,
OddHeader: ticketOutcome.OddHeader,
OddHandicap: ticketOutcome.OddHandicap,
Expires: pgtype.Timestamp{
Time: ticketOutcome.Expires,
Valid: true,
},
}
}
func ConvertCreateTicket(ticket CreateTicket) dbgen.CreateTicketParams {
return dbgen.CreateTicketParams{
Amount: int64(ticket.Amount),
TotalOdds: ticket.TotalOdds,
Ip: ticket.IP,
CompanyID: ticket.CompanyID,
}
}

View File

@ -1,6 +1,11 @@
package domain package domain
import "time" import (
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/jackc/pgx/v5/pgtype"
)
type TransferType string type TransferType string
@ -112,3 +117,82 @@ type TransferStats struct {
TotalWithdraws int64 TotalWithdraws int64
TotalWalletToWallet int64 TotalWalletToWallet int64
} }
func ConvertDBTransferDetail(transfer dbgen.WalletTransferDetail) TransferDetail {
return TransferDetail{
ID: transfer.ID,
Amount: Currency(transfer.Amount.Int64),
Type: TransferType(transfer.Type.String),
Verified: transfer.Verified.Bool,
Message: transfer.Message,
ReceiverWalletID: ValidInt64{
Value: transfer.ReceiverWalletID.Int64,
Valid: transfer.ReceiverWalletID.Valid,
},
SenderWalletID: ValidInt64{
Value: transfer.SenderWalletID.Int64,
Valid: transfer.SenderWalletID.Valid,
},
DepositorID: ValidInt64{
Value: transfer.CashierID.Int64,
Valid: transfer.CashierID.Valid,
},
DepositorFirstName: transfer.FirstName.String,
DepositorLastName: transfer.LastName.String,
DepositorPhoneNumber: transfer.PhoneNumber.String,
PaymentMethod: PaymentMethod(transfer.PaymentMethod.String),
ReferenceNumber: transfer.ReferenceNumber,
SessionID: transfer.SessionID.String,
Status: transfer.Status.String,
CreatedAt: transfer.CreatedAt.Time,
UpdatedAt: transfer.UpdatedAt.Time,
}
}
func ConvertDBTransfer(transfer dbgen.WalletTransfer) Transfer {
return Transfer{
ID: transfer.ID,
Amount: Currency(transfer.Amount.Int64),
Type: TransferType(transfer.Type.String),
Verified: transfer.Verified.Bool,
Message: transfer.Message,
ReceiverWalletID: ValidInt64{
Value: transfer.ReceiverWalletID.Int64,
Valid: transfer.ReceiverWalletID.Valid,
},
SenderWalletID: ValidInt64{
Value: transfer.SenderWalletID.Int64,
Valid: transfer.SenderWalletID.Valid,
},
DepositorID: ValidInt64{
Value: transfer.CashierID.Int64,
Valid: transfer.CashierID.Valid,
},
PaymentMethod: PaymentMethod(transfer.PaymentMethod.String),
ReferenceNumber: transfer.ReferenceNumber,
SessionID: transfer.SessionID.String,
Status: transfer.Status.String,
CreatedAt: transfer.CreatedAt.Time,
UpdatedAt: transfer.UpdatedAt.Time,
}
}
func ConvertCreateTransfer(transfer CreateTransfer) dbgen.CreateTransferParams {
return dbgen.CreateTransferParams{
Message: transfer.Message,
Amount: pgtype.Int8{Int64: int64(transfer.Amount), Valid: true},
Type: pgtype.Text{String: string(transfer.Type), Valid: true},
ReceiverWalletID: transfer.ReceiverWalletID.ToPG(),
SenderWalletID: transfer.SenderWalletID.ToPG(),
CashierID: transfer.CashierID.ToPG(),
ReferenceNumber: string(transfer.ReferenceNumber),
SessionID: pgtype.Text{
String: transfer.SessionID,
Valid: true,
},
PaymentMethod: pgtype.Text{String: string(transfer.PaymentMethod), Valid: true},
Verified: pgtype.Bool{
Bool: transfer.Verified,
Valid: true,
},
}
}

View File

@ -3,6 +3,8 @@ package domain
import ( import (
"errors" "errors"
"time" "time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
) )
var ( var (
@ -89,57 +91,64 @@ const (
CompanyWalletType WalletType = "company_wallet" CompanyWalletType WalletType = "company_wallet"
) )
// domain/wallet.go func ConvertDBWallet(wallet dbgen.Wallet) Wallet {
return Wallet{
type DirectDepositStatus string ID: wallet.ID,
Balance: Currency(wallet.Balance),
const ( IsWithdraw: wallet.IsWithdraw,
DepositStatusPending DirectDepositStatus = "pending" IsBettable: wallet.IsBettable,
DepositStatusCompleted DirectDepositStatus = "completed" IsTransferable: wallet.IsTransferable,
DepositStatusRejected DirectDepositStatus = "rejected" IsActive: wallet.IsActive,
) UserID: wallet.UserID,
Type: WalletType(wallet.Type),
type DirectDeposit struct { UpdatedAt: wallet.UpdatedAt.Time,
ID int64 `json:"id"` CreatedAt: wallet.CreatedAt.Time,
CustomerID int64 `json:"customer_id"` }
WalletID int64 `json:"wallet_id"`
Wallet Wallet `json:"wallet"`
Amount Currency `json:"amount"`
BankReference string `json:"bank_reference"`
SenderAccount string `json:"sender_account"`
Status DirectDepositStatus `json:"status"`
CreatedAt time.Time `json:"created_at"`
VerifiedBy *int64 `json:"verified_by"`
VerificationNotes string `json:"verification_notes"`
VerifiedAt *time.Time `json:"verified_at"`
} }
type CreateDirectDeposit struct { func ConvertCreateWallet(wallet CreateWallet) dbgen.CreateWalletParams {
CustomerID int64 return dbgen.CreateWalletParams{
WalletID int64 IsWithdraw: wallet.IsWithdraw,
Amount Currency IsBettable: wallet.IsBettable,
BankReference string IsTransferable: wallet.IsTransferable,
SenderAccount string UserID: wallet.UserID,
Status DirectDepositStatus Type: string(wallet.Type),
}
} }
type UpdateDirectDeposit struct { func ConvertDBCustomerWallet(customerWallet dbgen.CustomerWallet) CustomerWallet {
ID int64 return CustomerWallet{
Status DirectDepositStatus ID: customerWallet.ID,
VerifiedBy int64 RegularID: customerWallet.RegularWalletID,
VerificationNotes string StaticID: customerWallet.StaticWalletID,
VerifiedAt time.Time CustomerID: customerWallet.CustomerID,
}
}
func ConvertCreateCustomerWallet(customerWallet CreateCustomerWallet) dbgen.CreateCustomerWalletParams {
return dbgen.CreateCustomerWalletParams{
CustomerID: customerWallet.CustomerID,
RegularWalletID: customerWallet.RegularWalletID,
StaticWalletID: customerWallet.StaticWalletID,
}
} }
type DirectDepositRequest struct { func ConvertDBGetCustomerWallet(customerWallet dbgen.CustomerWalletDetail) GetCustomerWallet {
CustomerID int64 `json:"customer_id" binding:"required"` return GetCustomerWallet{
Amount Currency `json:"amount" binding:"required,gt=0"` ID: customerWallet.ID,
BankReference string `json:"bank_reference" binding:"required"` RegularID: customerWallet.RegularID,
SenderAccount string `json:"sender_account" binding:"required"` RegularBalance: Currency(customerWallet.RegularBalance),
StaticID: customerWallet.StaticID,
StaticBalance: Currency(customerWallet.StaticBalance),
CustomerID: customerWallet.CustomerID,
RegularIsActive: customerWallet.RegularIsActive,
StaticIsActive: customerWallet.StaticIsActive,
RegularUpdatedAt: customerWallet.RegularUpdatedAt.Time,
StaticUpdatedAt: customerWallet.StaticUpdatedAt.Time,
CreatedAt: customerWallet.CreatedAt.Time,
FirstName: customerWallet.FirstName,
LastName: customerWallet.LastName,
PhoneNumber: customerWallet.PhoneNumber.String,
}
} }
type VerifyDirectDepositRequest struct {
DepositID int64 `json:"deposit_id" binding:"required"`
IsVerified bool `json:"is_verified" binding:"required"`
Notes string `json:"notes"`
}

View File

@ -1,4 +1,4 @@
package authentication package ports
import ( import (
"context" "context"
@ -6,9 +6,6 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
) )
type UserStore interface {
GetUserByEmailPhone(ctx context.Context, email, phone string, companyID domain.ValidInt64) (domain.User, error)
}
type TokenStore interface { type TokenStore interface {
CreateRefreshToken(ctx context.Context, rt domain.RefreshToken) error CreateRefreshToken(ctx context.Context, rt domain.RefreshToken) error
GetRefreshToken(ctx context.Context, token string) (domain.RefreshToken, error) GetRefreshToken(ctx context.Context, token string) (domain.RefreshToken, error)

View File

@ -1,9 +1,7 @@
package bet package ports
import ( import (
"context" "context"
"time" "time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
) )
@ -51,3 +49,5 @@ type BetStore interface {
GetBetsForCashback(ctx context.Context) ([]domain.GetBet, error) GetBetsForCashback(ctx context.Context) ([]domain.GetBet, error)
UpdateBetWithCashback(ctx context.Context, betID int64, cashbackStatus bool) error UpdateBetWithCashback(ctx context.Context, betID int64, cashbackStatus bool) error
} }

View File

@ -1,4 +1,5 @@
package bonus package ports
import ( import (
"context" "context"

View File

@ -1,4 +1,4 @@
package branch package ports
import ( import (
"context" "context"

View File

@ -1,4 +1,4 @@
package company package ports
import ( import (
"context" "context"
@ -16,7 +16,11 @@ type CompanyStore interface {
DeleteCompany(ctx context.Context, id int64) error DeleteCompany(ctx context.Context, id int64) error
GetCompanyCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) GetCompanyCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
}
type CompanyStatStore interface {
UpdateCompanyStats(ctx context.Context) error UpdateCompanyStats(ctx context.Context) error
GetCompanyStatByID(ctx context.Context, companyID int64) ([]domain.CompanyStat, error) GetCompanyStatByID(ctx context.Context, companyID int64) ([]domain.CompanyStat, error)
GetCompanyStatsByInterval(ctx context.Context, filter domain.CompanyStatFilter) ([]domain.CompanyStat, error) GetCompanyStatsByInterval(ctx context.Context, filter domain.CompanyStatFilter) ([]domain.CompanyStat, error)
} }

View File

@ -1,4 +1,4 @@
package event package ports
import ( import (
"context" "context"
@ -7,24 +7,33 @@ import (
) )
type EventStore interface { type EventStore interface {
// FetchLiveEvents(ctx context.Context) error SaveEvent(ctx context.Context, e domain.CreateEvent) error
FetchUpcomingEvents(ctx context.Context) error
GetAllEvents(ctx context.Context, filter domain.EventFilter) ([]domain.BaseEvent, int64, error) GetAllEvents(ctx context.Context, filter domain.EventFilter) ([]domain.BaseEvent, int64, error)
GetEventByID(ctx context.Context, ID int64) (domain.BaseEvent, error) GetEventByID(ctx context.Context, ID int64) (domain.BaseEvent, error)
// GetAndStoreMatchResult(ctx context.Context, eventID int64) error
UpdateFinalScore(ctx context.Context, eventID int64, fullScore string, status domain.EventStatus) error UpdateFinalScore(ctx context.Context, eventID int64, fullScore string, status domain.EventStatus) error
UpdateEventStatus(ctx context.Context, eventID int64, status domain.EventStatus) error UpdateEventStatus(ctx context.Context, eventID int64, status domain.EventStatus) error
IsEventMonitored(ctx context.Context, eventID int64) (bool, error) IsEventMonitored(ctx context.Context, eventID int64) (bool, error)
UpdateEventMonitored(ctx context.Context, eventID int64, IsMonitored bool) error UpdateEventMonitored(ctx context.Context, eventID int64, IsMonitored bool) error
GetSportAndLeagueIDs(ctx context.Context, eventID int64) ([]int64, error) GetSportAndLeagueIDs(ctx context.Context, eventID int64) ([]int64, error)
GetLiveEventIDs(ctx context.Context) ([]int64, error)
GetEventBySourceID(ctx context.Context, id string, source domain.EventSource) (domain.BaseEvent, error)
DeleteEvent(ctx context.Context, eventID int64) error
// Event Settings Views // Event Settings Views
GetEventsWithSettings(ctx context.Context, companyID int64, filter domain.EventFilter) ([]domain.EventWithSettings, int64, error) GetEventsWithSettings(ctx context.Context, companyID int64, filter domain.EventFilter) ([]domain.EventWithSettings, int64, error)
GetEventWithSettingByID(ctx context.Context, ID int64, companyID int64) (domain.EventWithSettings, error) GetEventWithSettingByID(ctx context.Context, ID int64, companyID int64) (domain.EventWithSettings, error)
UpdateTenantEventSettings(ctx context.Context, event domain.UpdateTenantEventSettings) error UpdateTenantEventSettings(ctx context.Context, event domain.UpdateTenantEventSettings) error
UpdateGlobalEventSettings(ctx context.Context, event domain.UpdateGlobalEventSettings) error UpdateGlobalEventSettings(ctx context.Context, event domain.UpdateGlobalEventSettings) error
}
// Stats type EventHistoryStore interface {
InsertEventHistory(ctx context.Context, eventHistory domain.CreateEventHistory) (domain.EventHistory, error)
GetAllEventHistory(ctx context.Context, filter domain.EventHistoryFilter) ([]domain.EventHistory, error)
GetInitialEventPerDay(ctx context.Context, filter domain.EventHistoryFilter) ([]domain.EventHistory, error)
}
type EventStatStore interface {
GetTotalEventStats(ctx context.Context, filter domain.EventStatsFilter) (domain.EventStats, error) GetTotalEventStats(ctx context.Context, filter domain.EventStatsFilter) (domain.EventStats, error)
GetTotalEventStatsByInterval(ctx context.Context, filter domain.EventStatsByIntervalFilter) ([]domain.EventStatsByInterval, error) GetTotalEventStatsByInterval(ctx context.Context, filter domain.EventStatsByIntervalFilter) ([]domain.EventStatsByInterval, error)
UpdateEventBetStats(ctx context.Context) error UpdateEventBetStats(ctx context.Context) error

View File

@ -1,4 +1,4 @@
package league package ports
import ( import (
"context" "context"

View File

@ -1,23 +1,20 @@
package notificationservice package ports
import ( import (
"context" "context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/gorilla/websocket"
) )
type NotificationStore interface { type NotificationStore interface {
SendNotification(ctx context.Context, notification *domain.Notification) error
MarkAsRead(ctx context.Context, notificationID string, recipientID int64) error
GetUserNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, int64, error) GetUserNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, int64, error)
ConnectWebSocket(ctx context.Context, recipientID int64, c *websocket.Conn) error
DisconnectWebSocket(recipientID int64)
SendSMS(ctx context.Context, recipientID int64, message string) error
SendEmail(ctx context.Context, recipientID int64, subject, message string) error
ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error) // New method ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error) // New method
CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error) CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error)
GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error)
GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error) GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error)
CreateNotification(ctx context.Context, notification *domain.Notification) (*domain.Notification, error)
UpdateNotificationStatus(ctx context.Context, id, status string, isRead bool, metadata []byte) (*domain.Notification, error)
ListFailedNotifications(ctx context.Context, limit int) ([]domain.Notification, error)
DeleteOldNotifications(ctx context.Context) error
} }

31
internal/ports/odds.go Normal file
View File

@ -0,0 +1,31 @@
package ports
import (
"context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
type OddStore interface {
SaveOddMarket(ctx context.Context, m domain.CreateOddMarket) error
GetAllOdds(ctx context.Context, filter domain.OddMarketFilter) ([]domain.OddMarket, error)
GetAllOddsWithSettings(ctx context.Context, companyID int64, filter domain.OddMarketFilter) ([]domain.OddMarketWithSettings, error)
GetOddByID(ctx context.Context, id int64) (domain.OddMarket, error)
GetOddsByMarketID(ctx context.Context, marketID int64, eventID int64) (domain.OddMarket, error)
GetOddsWithSettingsByMarketID(ctx context.Context, marketID int64, eventID int64, companyID int64) (domain.OddMarketWithSettings, error)
GetOddsByEventID(ctx context.Context, eventID int64, filter domain.OddMarketWithEventFilter) ([]domain.OddMarket, error)
GetOddsWithSettingsByEventID(ctx context.Context, eventID int64, companyID int64, filter domain.OddMarketFilter) ([]domain.OddMarketWithSettings, error)
DeleteOddsForEvent(ctx context.Context, eventID int64) error
// Settings
SaveOddsSetting(ctx context.Context, odd domain.CreateOddMarketSettings) error
UpdateGlobalOddsSetting(ctx context.Context, odd domain.UpdateGlobalOddMarketSettings) error
GetOddsWithSettingsByID(ctx context.Context, ID int64, companyID int64) (domain.OddMarketWithSettings, error)
DeleteAllCompanyOddsSetting(ctx context.Context, companyID int64) error
DeleteCompanyOddsSettingByOddMarketID(ctx context.Context, companyID int64, oddMarketID int64) error
// Odd History
InsertOddHistory(ctx context.Context, odd domain.CreateOddHistory) (domain.OddHistory, error)
GetAllOddHistory(ctx context.Context, filter domain.OddHistoryFilter) ([]domain.OddHistory, error)
GetInitialOddPerDay(ctx context.Context, filter domain.OddHistoryFilter) ([]domain.OddHistory, error)
}

View File

@ -1,4 +1,4 @@
package raffle package ports
import ( import (
"context" "context"

View File

@ -0,0 +1,19 @@
package ports
import (
"context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
type ReferralStore interface {
CreateReferralCode(ctx context.Context, referralCode domain.CreateReferralCode) (domain.ReferralCode, error)
CreateUserReferral(ctx context.Context, referral domain.CreateUserReferrals) (domain.UserReferral, error)
GetReferralCodesByUser(ctx context.Context, userID int64) ([]domain.ReferralCode, error)
GetReferralCode(ctx context.Context, code string) (domain.ReferralCode, error)
UpdateReferralCode(ctx context.Context, referral domain.UpdateReferralCode) error
GetReferralStats(ctx context.Context, userID int64, companyID int64) (domain.ReferralStats, error)
GetUserReferral(ctx context.Context, referredID int64) (domain.UserReferral, error)
GetUserReferralsByCode(ctx context.Context, code string) ([]domain.UserReferral, error)
GetUserReferralCount(ctx context.Context, referrerID int64) (int64, error)
}

44
internal/ports/report.go Normal file
View File

@ -0,0 +1,44 @@
package ports
import (
"context"
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
type ReportStore interface {
// GetDashboardSummary(ctx context.Context, filter domain.ReportFilter) (domain.DashboardSummary, error)
// GetBetAnalysis(ctx context.Context, filter domain.ReportFilter) ([]domain.BetAnalysis, error)
// GetCustomerActivity(ctx context.Context, filter domain.ReportFilter) ([]domain.CustomerActivity, error)
// GetBranchPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.BranchPerformance, error)
// GetSportPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.SportPerformance, error)
// GetNotificationReport(ctx context.Context, filter domain.ReportFilter) (domain.NotificationReport, error)
// GetCashierPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.CashierPerformance, error)
// GetCompanyPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.CompanyPerformance, error)
CreateReportRequest(ctx context.Context, report domain.CreateReportRequest) (domain.ReportRequest, error)
GetAllReportRequests(ctx context.Context, filter domain.ReportRequestFilter) ([]domain.ReportRequestDetail, int64, error)
GetReportRequestByRequestedByID(ctx context.Context, requestedBy int64, filter domain.ReportRequestFilter) ([]domain.ReportRequestDetail, error)
GetReportRequestByID(ctx context.Context, ID int64) (domain.ReportRequestDetail, error)
UpdateReportRequest(ctx context.Context, report domain.UpdateRequestRequest) error
}
// TODO: Move the code to new Report Store using report requests
// Auto-generated reports should also use a report request (but with no requested_by param)
type OldReportRepository interface {
GenerateReport(timeFrame domain.ReportTimeFrame, start, end time.Time) (*domain.Report, error)
SaveReport(report *domain.Report) error
FindReportsByTimeFrame(timeFrame domain.ReportTimeFrame, limit int) ([]*domain.Report, error)
GetTotalCashOutInRange(ctx context.Context, from, to time.Time) (float64, error)
GetTotalCashMadeInRange(ctx context.Context, from, to time.Time) (float64, error)
GetTotalCashBacksInRange(ctx context.Context, from, to time.Time) (float64, error)
GetTotalBetsMadeInRange(ctx context.Context, from, to time.Time) (int64, error)
GetVirtualGameSummaryInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetVirtualGameSummaryInRangeRow, error)
GetAllTicketsInRange(ctx context.Context, from, to time.Time) (dbgen.GetAllTicketsInRangeRow, error)
GetWalletTransactionsInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetWalletTransactionsInRangeRow, error)
// GetCompanyWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetCompanyWiseReportRow, error)
// GetBranchWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetBranchWiseReportRow, error)
}

View File

@ -1,4 +1,4 @@
package result package ports
import ( import (
"context" "context"
@ -6,11 +6,6 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
) )
type ResultService interface {
FetchAndProcessResults(ctx context.Context) error
FetchAndStoreResult(ctx context.Context, eventID string) error
}
type ResultLogStore interface { type ResultLogStore interface {
CreateResultLog(ctx context.Context, result domain.CreateResultLog) (domain.ResultLog, error) CreateResultLog(ctx context.Context, result domain.CreateResultLog) (domain.ResultLog, error)
GetAllResultLog(ctx context.Context, filter domain.ResultLogFilter) ([]domain.ResultLog, error) GetAllResultLog(ctx context.Context, filter domain.ResultLogFilter) ([]domain.ResultLog, error)

View File

@ -1,4 +1,4 @@
package settings package ports
import ( import (
"context" "context"

View File

@ -1,4 +1,4 @@
package ticket package ports
import ( import (
"context" "context"

View File

@ -1,8 +1,7 @@
package transaction package ports
import ( import (
"context" "context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
) )

View File

@ -1,4 +1,4 @@
package user package ports
import ( import (
"context" "context"
@ -24,6 +24,7 @@ type UserStore interface {
GetUserByPhone(ctx context.Context, phoneNum string, companyID domain.ValidInt64) (domain.User, error) GetUserByPhone(ctx context.Context, phoneNum string, companyID domain.ValidInt64) (domain.User, error)
SearchUserByNameOrPhone(ctx context.Context, searchString string, role *domain.Role, companyID domain.ValidInt64) ([]domain.User, error) SearchUserByNameOrPhone(ctx context.Context, searchString string, role *domain.Role, companyID domain.ValidInt64) ([]domain.User, error)
UpdatePassword(ctx context.Context, identifier string, password []byte, usedOtpId int64, companyId int64) error UpdatePassword(ctx context.Context, identifier string, password []byte, usedOtpId int64, companyId int64) error
GetUserByEmailPhone(ctx context.Context, email, phone string, companyID domain.ValidInt64) (domain.User, error)
GetCustomerCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) GetCustomerCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
GetCustomerDetails(ctx context.Context, filter domain.ReportFilter) (map[int64]domain.CustomerDetail, error) GetCustomerDetails(ctx context.Context, filter domain.ReportFilter) (map[int64]domain.CustomerDetail, error)

View File

@ -1,4 +1,4 @@
package wallet package ports
import ( import (
"context" "context"

View File

@ -7,49 +7,13 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
func (s *Store) GetUserByEmailPhone(ctx context.Context, email, phone string, companyID domain.ValidInt64) (domain.User, error) { // Interface for creating new token store
user, err := s.queries.GetUserByEmailPhone(ctx, dbgen.GetUserByEmailPhoneParams{ func NewTokenStore(s *Store) ports.TokenStore { return s }
Email: pgtype.Text{
String: email,
Valid: true,
},
PhoneNumber: pgtype.Text{
String: phone,
Valid: true,
},
CompanyID: companyID.ToPG(),
})
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return domain.User{}, authentication.ErrUserNotFound
}
return domain.User{}, err
}
return domain.User{
ID: user.ID,
FirstName: user.FirstName,
LastName: user.LastName,
Email: user.Email.String,
PhoneNumber: user.PhoneNumber.String,
Password: user.Password,
Role: domain.Role(user.Role),
EmailVerified: user.EmailVerified,
PhoneVerified: user.PhoneVerified,
CreatedAt: user.CreatedAt.Time,
UpdatedAt: user.UpdatedAt.Time,
SuspendedAt: user.SuspendedAt.Time,
Suspended: user.Suspended,
CompanyID: domain.ValidInt64{
Value: user.CompanyID.Int64,
Valid: user.CompanyID.Valid,
},
}, nil
}
func (s *Store) CreateRefreshToken(ctx context.Context, rt domain.RefreshToken) error { func (s *Store) CreateRefreshToken(ctx context.Context, rt domain.RefreshToken) error {
return s.queries.CreateRefreshToken(ctx, dbgen.CreateRefreshTokenParams{ return s.queries.CreateRefreshToken(ctx, dbgen.CreateRefreshTokenParams{

View File

@ -3,28 +3,22 @@ package repository
import ( import (
"context" "context"
"fmt" "fmt"
"log/slog"
"time" "time"
// "fmt"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
"go.uber.org/zap" "go.uber.org/zap"
) )
var ( // Interface for creating new bet store
logger *slog.Logger func NewBetStore(s *Store) ports.BetStore { return s }
mongoLogger *zap.Logger
)
func (s *Store) CreateBet(ctx context.Context, bet domain.CreateBet) (domain.Bet, error) { func (s *Store) CreateBet(ctx context.Context, bet domain.CreateBet) (domain.Bet, error) {
newBet, err := s.queries.CreateBet(ctx, domain.ConvertCreateBet(bet)) newBet, err := s.queries.CreateBet(ctx, domain.ConvertCreateBet(bet))
if err != nil { if err != nil {
fmt.Println("We are here")
logger.Error("Failed to create bet", slog.String("error", err.Error()), slog.Any("bet", bet))
return domain.Bet{}, err return domain.Bet{}, err
} }
return domain.ConvertDBBet(newBet), err return domain.ConvertDBBet(newBet), err
@ -432,7 +426,7 @@ func (s *Store) UpdateBetOutcomeStatusForOddId(ctx context.Context, oddID int64,
return result, nil return result, nil
} }
func (s *Store) BulkUpdateBetOutcomeStatusForOddIds(ctx context.Context, oddID []int64, status domain.OutcomeStatus) (error) { func (s *Store) BulkUpdateBetOutcomeStatusForOddIds(ctx context.Context, oddID []int64, status domain.OutcomeStatus) error {
err := s.queries.BulkUpdateBetOutcomeStatusByOddIDs(ctx, dbgen.BulkUpdateBetOutcomeStatusByOddIDsParams{ err := s.queries.BulkUpdateBetOutcomeStatusByOddIDs(ctx, dbgen.BulkUpdateBetOutcomeStatusByOddIDsParams{
Status: int32(status), Status: int32(status),
OddIds: oddID, OddIds: oddID,

View File

@ -5,8 +5,12 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
// Interface for creating new bonus store
func NewBonusStore(s *Store) ports.BonusStore { return s }
func (s *Store) CreateUserBonus(ctx context.Context, bonus domain.CreateBonus) (domain.UserBonus, error) { func (s *Store) CreateUserBonus(ctx context.Context, bonus domain.CreateBonus) (domain.UserBonus, error) {
newBonus, err := s.queries.CreateUserBonus(ctx, domain.ConvertCreateBonus(bonus)) newBonus, err := s.queries.CreateUserBonus(ctx, domain.ConvertCreateBonus(bonus))

View File

@ -6,9 +6,13 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
// Interface for creating new branch store
func NewBranchStore(s *Store) ports.BranchStore { return s }
func (s *Store) CreateBranch(ctx context.Context, branch domain.CreateBranch) (domain.Branch, error) { func (s *Store) CreateBranch(ctx context.Context, branch domain.CreateBranch) (domain.Branch, error) {
dbBranch, err := s.queries.CreateBranch(ctx, domain.ConvertCreateBranch(branch)) dbBranch, err := s.queries.CreateBranch(ctx, domain.ConvertCreateBranch(branch))

View File

@ -5,9 +5,13 @@ import (
"fmt" "fmt"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
// Interface for creating new company store
func NewCompanyStore(s *Store) ports.CompanyStore { return s }
func (s *Store) CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error) { func (s *Store) CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error) {
dbCompany, err := s.queries.CreateCompany(ctx, domain.ConvertCreateCompany(company)) dbCompany, err := s.queries.CreateCompany(ctx, domain.ConvertCreateCompany(company))
@ -81,8 +85,6 @@ func (s *Store) DeleteCompany(ctx context.Context, id int64) error {
return s.queries.DeleteCompany(ctx, id) return s.queries.DeleteCompany(ctx, id)
} }
func (s *Store) GetCompanyCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) { func (s *Store) GetCompanyCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) {
query := `SELECT query := `SELECT
COUNT(*) as total, COUNT(*) as total,

View File

@ -5,8 +5,12 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
// Interface for creating new company stats store
func NewCompanyStatStore(s *Store) ports.CompanyStatStore { return s }
func (s *Store) UpdateCompanyStats(ctx context.Context) error { func (s *Store) UpdateCompanyStats(ctx context.Context) error {
return s.queries.UpdateCompanyStats(ctx) return s.queries.UpdateCompanyStats(ctx)
} }

View File

@ -2,71 +2,21 @@ package repository
import ( import (
"context" "context"
"math/big"
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/jackc/pgx/v5/pgtype" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
func convertDBDirectDeposit(deposit dbgen.DirectDeposit) domain.DirectDeposit { // Interface for creating new wallet store
return domain.DirectDeposit{ func NewDirectDepositStore(s *Store) ports.DirectDepositStore { return s }
ID: deposit.ID,
CustomerID: deposit.CustomerID,
WalletID: deposit.WalletID,
Amount: domain.Currency(deposit.Amount.Int.Int64()),
BankReference: deposit.BankReference,
SenderAccount: deposit.SenderAccount,
Status: domain.DirectDepositStatus(deposit.Status),
CreatedAt: deposit.CreatedAt.Time,
VerifiedBy: convertPgInt64ToPtr(deposit.VerifiedBy),
VerificationNotes: deposit.VerificationNotes.String,
VerifiedAt: convertPgTimeToPtr(deposit.VerifiedAt),
}
}
func convertCreateDirectDeposit(deposit domain.CreateDirectDeposit) dbgen.CreateDirectDepositParams {
return dbgen.CreateDirectDepositParams{
CustomerID: deposit.CustomerID,
WalletID: deposit.WalletID,
Amount: pgtype.Numeric{Int: big.NewInt(int64(deposit.Amount)), Valid: true},
BankReference: deposit.BankReference,
SenderAccount: deposit.SenderAccount,
Status: string(deposit.Status),
}
}
func convertUpdateDirectDeposit(deposit domain.UpdateDirectDeposit) dbgen.UpdateDirectDepositParams {
return dbgen.UpdateDirectDepositParams{
ID: deposit.ID,
Status: string(deposit.Status),
VerifiedBy: pgtype.Int8{Int64: deposit.VerifiedBy, Valid: true},
VerificationNotes: pgtype.Text{String: deposit.VerificationNotes, Valid: deposit.VerificationNotes != ""},
VerifiedAt: pgtype.Timestamp{Time: deposit.VerifiedAt, Valid: true},
}
}
func convertPgInt64ToPtr(i pgtype.Int8) *int64 {
if i.Valid {
return &i.Int64
}
return nil
}
func convertPgTimeToPtr(t pgtype.Timestamp) *time.Time {
if t.Valid {
return &t.Time
}
return nil
}
func (s *Store) CreateDirectDeposit(ctx context.Context, deposit domain.CreateDirectDeposit) (domain.DirectDeposit, error) { func (s *Store) CreateDirectDeposit(ctx context.Context, deposit domain.CreateDirectDeposit) (domain.DirectDeposit, error) {
newDeposit, err := s.queries.CreateDirectDeposit(ctx, convertCreateDirectDeposit(deposit)) newDeposit, err := s.queries.CreateDirectDeposit(ctx, domain.ConvertCreateDirectDeposit(deposit))
if err != nil { if err != nil {
return domain.DirectDeposit{}, err return domain.DirectDeposit{}, err
} }
return convertDBDirectDeposit(newDeposit), nil return domain.ConvertDBDirectDeposit(newDeposit), nil
} }
func (s *Store) GetDirectDeposit(ctx context.Context, id int64) (domain.DirectDeposit, error) { func (s *Store) GetDirectDeposit(ctx context.Context, id int64) (domain.DirectDeposit, error) {
@ -74,15 +24,15 @@ func (s *Store) GetDirectDeposit(ctx context.Context, id int64) (domain.DirectDe
if err != nil { if err != nil {
return domain.DirectDeposit{}, err return domain.DirectDeposit{}, err
} }
return convertDBDirectDeposit(deposit), nil return domain.ConvertDBDirectDeposit(deposit), nil
} }
func (s *Store) UpdateDirectDeposit(ctx context.Context, deposit domain.UpdateDirectDeposit) (domain.DirectDeposit, error) { func (s *Store) UpdateDirectDeposit(ctx context.Context, deposit domain.UpdateDirectDeposit) (domain.DirectDeposit, error) {
updatedDeposit, err := s.queries.UpdateDirectDeposit(ctx, convertUpdateDirectDeposit(deposit)) updatedDeposit, err := s.queries.UpdateDirectDeposit(ctx, domain.ConvertUpdateDirectDeposit(deposit))
if err != nil { if err != nil {
return domain.DirectDeposit{}, err return domain.DirectDeposit{}, err
} }
return convertDBDirectDeposit(updatedDeposit), nil return domain.ConvertDBDirectDeposit(updatedDeposit), nil
} }
func (s *Store) GetDirectDepositsByStatus(ctx context.Context, status domain.DirectDepositStatus) ([]domain.DirectDeposit, error) { func (s *Store) GetDirectDepositsByStatus(ctx context.Context, status domain.DirectDepositStatus) ([]domain.DirectDeposit, error) {
@ -93,7 +43,7 @@ func (s *Store) GetDirectDepositsByStatus(ctx context.Context, status domain.Dir
result := make([]domain.DirectDeposit, 0, len(deposits)) result := make([]domain.DirectDeposit, 0, len(deposits))
for _, deposit := range deposits { for _, deposit := range deposits {
result = append(result, convertDBDirectDeposit(deposit)) result = append(result, domain.ConvertDBDirectDeposit(deposit))
} }
return result, nil return result, nil
} }
@ -106,7 +56,7 @@ func (s *Store) GetCustomerDirectDeposits(ctx context.Context, customerID int64)
result := make([]domain.DirectDeposit, 0, len(deposits)) result := make([]domain.DirectDeposit, 0, len(deposits))
for _, deposit := range deposits { for _, deposit := range deposits {
result = append(result, convertDBDirectDeposit(deposit)) result = append(result, domain.ConvertDBDirectDeposit(deposit))
} }
return result, nil return result, nil
} }

View File

@ -1,68 +0,0 @@
package repository
import (
"context"
"fmt"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
func (s *Store) InsertDisabledOdd(ctx context.Context, odd domain.CreateDisabledOdd) (domain.DisabledOdd, error) {
dbDisabledOdd, err := s.queries.InsertDisabledOdds(ctx, domain.ConvertCreateDisabledOdd(odd))
if err != nil {
return domain.DisabledOdd{}, fmt.Errorf("InsertDisabledOdd failed: %w", err)
}
return domain.ConvertDBDisabledOdd(dbDisabledOdd), nil
}
func (s *Store) GetAllDisabledOdds(ctx context.Context) ([]domain.DisabledOdd, error) {
dbDisabledOdds, err := s.queries.GetAllDisabledOdds(ctx)
if err != nil {
return nil, fmt.Errorf("GetAllDisabledOdds failed: %w", err)
}
return domain.ConvertDisabledOdds(dbDisabledOdds), nil
}
func (s *Store) GetDisabledOddByRawOddID(ctx context.Context, rawOddID int64) (domain.DisabledOdd, error) {
dbDisabledOdd, err := s.queries.GetDisabledOddByRawOddID(ctx, rawOddID)
if err != nil {
return domain.DisabledOdd{}, fmt.Errorf("GetDisabledOddByRawOddID failed: %w", err)
}
return domain.ConvertDBDisabledOdd(dbDisabledOdd), nil
}
func (s *Store) GetDisabledOddByID(ctx context.Context, id int64) (domain.DisabledOdd, error) {
dbDisabledOdd, err := s.queries.GetDisabledOddByID(ctx, id)
if err != nil {
return domain.DisabledOdd{}, fmt.Errorf("GetDisabledOddByID failed: %w", err)
}
return domain.ConvertDBDisabledOdd(dbDisabledOdd), nil
}
func (s *Store) DeleteDisabledOddsByID(ctx context.Context, id int64) error {
err := s.queries.DeleteDisabledOddsByID(ctx, id)
if err != nil {
return fmt.Errorf("DeleteDisabledOddsByID failed: %w", err)
}
return nil
}
func (s *Store) DeleteDisabledOddsByRawOddID(ctx context.Context, id int64) error {
err := s.queries.DeleteDisabledOddsByRawOddID(ctx, id)
if err != nil {
return fmt.Errorf("DeleteDisabledOddsByRawOddID failed: %w", err)
}
return nil
}

View File

@ -6,11 +6,15 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" // "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
// Interface for creating new event store
func NewEventStore(s *Store) ports.EventStore { return s }
func (s *Store) SaveEvent(ctx context.Context, e domain.CreateEvent) error { func (s *Store) SaveEvent(ctx context.Context, e domain.CreateEvent) error {
return s.queries.InsertEvent(ctx, domain.ConvertCreateEvent(e)) return s.queries.InsertEvent(ctx, domain.ConvertCreateEvent(e))
} }

View File

@ -6,8 +6,12 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
// Interface for creating new event history store
func NewEventHistoryStore(s *Store) ports.EventHistoryStore { return s }
func (s *Store) InsertEventHistory(ctx context.Context, eventHistory domain.CreateEventHistory) (domain.EventHistory, error) { func (s *Store) InsertEventHistory(ctx context.Context, eventHistory domain.CreateEventHistory) (domain.EventHistory, error) {
dbEventHistory, err := s.queries.InsertEventHistory(ctx, domain.ConvertCreateEventHistory(eventHistory)) dbEventHistory, err := s.queries.InsertEventHistory(ctx, domain.ConvertCreateEventHistory(eventHistory))

View File

@ -5,8 +5,12 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
// Interface for creating new event stats store
func NewEventStatStore(s *Store) ports.EventStatStore { return s }
func (s *Store) GetTotalEventStats(ctx context.Context, filter domain.EventStatsFilter) (domain.EventStats, error) { func (s *Store) GetTotalEventStats(ctx context.Context, filter domain.EventStatsFilter) (domain.EventStats, error) {
stats, err := s.queries.GetTotalEventStats(ctx, dbgen.GetTotalEventStatsParams{ stats, err := s.queries.GetTotalEventStats(ctx, dbgen.GetTotalEventStatsParams{
LeagueID: filter.LeagueID.ToPG(), LeagueID: filter.LeagueID.ToPG(),

View File

@ -5,9 +5,13 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
// Interface for creating new league store
func NewLeagueStore(s *Store) ports.LeagueStore { return s }
func (s *Store) SaveLeague(ctx context.Context, league domain.CreateLeague) error { func (s *Store) SaveLeague(ctx context.Context, league domain.CreateLeague) error {
return s.queries.InsertLeague(ctx, domain.ConvertCreateLeague(league)) return s.queries.InsertLeague(ctx, domain.ConvertCreateLeague(league))
} }

View File

@ -7,38 +7,13 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/gorilla/websocket" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
type NotificationRepository interface { func NewNotificationStore(s *Store) ports.NotificationStore { return s }
CreateNotification(ctx context.Context, notification *domain.Notification) (*domain.Notification, error)
UpdateNotificationStatus(ctx context.Context, id, status string, isRead bool, metadata []byte) (*domain.Notification, error)
GetUserNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, int64, error)
ListFailedNotifications(ctx context.Context, limit int) ([]domain.Notification, error)
ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error)
CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error)
GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error)
GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error)
DeleteOldNotifications(ctx context.Context) error
}
type Repository struct { func (r *Store) CreateNotification(ctx context.Context, notification *domain.Notification) (*domain.Notification, error) {
store *Store
}
func NewNotificationRepository(store *Store) NotificationRepository {
return &Repository{store: store}
}
func (s *Store) ConnectWebSocket(ctx context.Context, recipientID int64, c *websocket.Conn) error {
return nil
}
func (s *Store) DisconnectWebSocket(recipientID int64) {
}
func (r *Repository) CreateNotification(ctx context.Context, notification *domain.Notification) (*domain.Notification, error) {
var errorSeverity pgtype.Text var errorSeverity pgtype.Text
if notification.ErrorSeverity != "" { if notification.ErrorSeverity != "" {
errorSeverity.String = string(notification.ErrorSeverity) errorSeverity.String = string(notification.ErrorSeverity)
@ -75,7 +50,7 @@ func (r *Repository) CreateNotification(ctx context.Context, notification *domai
Metadata: notification.Metadata, Metadata: notification.Metadata,
} }
dbNotification, err := r.store.queries.CreateNotification(ctx, params) dbNotification, err := r.queries.CreateNotification(ctx, params)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -83,7 +58,7 @@ func (r *Repository) CreateNotification(ctx context.Context, notification *domai
return r.mapDBToDomain(&dbNotification), nil return r.mapDBToDomain(&dbNotification), nil
} }
func (r *Repository) UpdateNotificationStatus(ctx context.Context, id, status string, isRead bool, metadata []byte) (*domain.Notification, error) { func (r *Store) UpdateNotificationStatus(ctx context.Context, id, status string, isRead bool, metadata []byte) (*domain.Notification, error) {
params := dbgen.UpdateNotificationStatusParams{ params := dbgen.UpdateNotificationStatusParams{
ID: id, ID: id,
DeliveryStatus: status, DeliveryStatus: status,
@ -91,7 +66,7 @@ func (r *Repository) UpdateNotificationStatus(ctx context.Context, id, status st
Metadata: metadata, Metadata: metadata,
} }
dbNotification, err := r.store.queries.UpdateNotificationStatus(ctx, params) dbNotification, err := r.queries.UpdateNotificationStatus(ctx, params)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -99,19 +74,19 @@ func (r *Repository) UpdateNotificationStatus(ctx context.Context, id, status st
return r.mapDBToDomain(&dbNotification), nil return r.mapDBToDomain(&dbNotification), nil
} }
func (r *Repository) GetUserNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, int64, error) { func (r *Store) GetUserNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, int64, error) {
params := dbgen.GetUserNotificationsParams{ params := dbgen.GetUserNotificationsParams{
RecipientID: recipientID, RecipientID: recipientID,
Limit: int32(limit), Limit: int32(limit),
Offset: int32(offset), Offset: int32(offset),
} }
dbNotifications, err := r.store.queries.GetUserNotifications(ctx, params) dbNotifications, err := r.queries.GetUserNotifications(ctx, params)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
total, err := r.store.queries.GetUserNotificationCount(ctx, recipientID) total, err := r.queries.GetUserNotificationCount(ctx, recipientID)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
@ -126,9 +101,9 @@ func (r *Repository) GetUserNotifications(ctx context.Context, recipientID int64
return result, total, nil return result, total, nil
} }
func (r *Repository) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) { func (r *Store) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) {
dbNotifications, err := r.store.queries.GetAllNotifications(ctx, dbgen.GetAllNotificationsParams{ dbNotifications, err := r.queries.GetAllNotifications(ctx, dbgen.GetAllNotificationsParams{
Limit: int32(limit), Limit: int32(limit),
Offset: int32(offset), Offset: int32(offset),
}) })
@ -144,8 +119,8 @@ func (r *Repository) GetAllNotifications(ctx context.Context, limit, offset int)
return result, nil return result, nil
} }
func (r *Repository) ListFailedNotifications(ctx context.Context, limit int) ([]domain.Notification, error) { func (r *Store) ListFailedNotifications(ctx context.Context, limit int) ([]domain.Notification, error) {
dbNotifications, err := r.store.queries.ListFailedNotifications(ctx, int32(limit)) dbNotifications, err := r.queries.ListFailedNotifications(ctx, int32(limit))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -159,15 +134,15 @@ func (r *Repository) ListFailedNotifications(ctx context.Context, limit int) ([]
return result, nil return result, nil
} }
func (r *Repository) ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error) { func (r *Store) ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error) {
return r.store.queries.ListRecipientIDsByReceiver(ctx, string(receiver)) return r.queries.ListRecipientIDsByReceiver(ctx, string(receiver))
} }
func (s *Repository) DeleteOldNotifications(ctx context.Context) error { func (s *Store) DeleteOldNotifications(ctx context.Context) error {
return s.store.queries.DeleteOldNotifications(ctx) return s.queries.DeleteOldNotifications(ctx)
} }
func (r *Repository) mapDBToDomain(dbNotif *dbgen.Notification) *domain.Notification { func (r *Store) mapDBToDomain(dbNotif *dbgen.Notification) *domain.Notification {
var errorSeverity domain.NotificationErrorSeverity var errorSeverity domain.NotificationErrorSeverity
if dbNotif.ErrorSeverity.Valid { if dbNotif.ErrorSeverity.Valid {
errorSeverity = domain.NotificationErrorSeverity(dbNotif.ErrorSeverity.String) errorSeverity = domain.NotificationErrorSeverity(dbNotif.ErrorSeverity.String)
@ -225,12 +200,12 @@ func unmarshalPayload(data []byte) (domain.NotificationPayload, error) {
return payload, nil return payload, nil
} }
func (r *Repository) CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error) { func (r *Store) CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error) {
return r.store.queries.CountUnreadNotifications(ctx, recipient_id) return r.queries.CountUnreadNotifications(ctx, recipient_id)
} }
func (r *Repository) GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error) { func (r *Store) GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error) {
rows, err := r.store.queries.GetNotificationCounts(ctx) rows, err := r.queries.GetNotificationCounts(ctx)
if err != nil { if err != nil {
return 0, 0, 0, fmt.Errorf("failed to get notification counts: %w", err) return 0, 0, 0, fmt.Errorf("failed to get notification counts: %w", err)
} }
@ -326,14 +301,6 @@ func (s *Store) GetNotificationCountsByType(ctx context.Context, filter domain.R
return counts, nil return counts, nil
} }
func (s *Store) CountUnreadNotifications(ctx context.Context, userID int64) (int64, error) {
count, err := s.queries.CountUnreadNotifications(ctx, userID)
if err != nil {
return 0, err
}
return count, nil
}
// func (s *Store) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) { // func (s *Store) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) {
// dbNotifications, err := s.queries.GetAllNotifications(ctx, dbgen.GetAllNotificationsParams{ // dbNotifications, err := s.queries.GetAllNotifications(ctx, dbgen.GetAllNotificationsParams{
// Limit: int32(limit), // Limit: int32(limit),

View File

@ -9,9 +9,13 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
// Interface for creating new event store
func NewOddStore(s *Store) ports.OddStore { return s }
func (s *Store) SaveOddMarket(ctx context.Context, m domain.CreateOddMarket) error { func (s *Store) SaveOddMarket(ctx context.Context, m domain.CreateOddMarket) error {
if len(m.Odds) == 0 { if len(m.Odds) == 0 {
return nil return nil

View File

@ -1,16 +1,22 @@
package repository package repository
import ( import (
// "context" "context"
// "fmt" "fmt"
// "time" "time"
// dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// "github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
type ReportRepository interface {
// Interface for creating new old repository repo interface
// We need to have an external definition of the repository or else we can't reuse the interface
func NewOldRepositoryStore(s *Store) ports.OldReportRepository { return s }
// type ReportRepository interface {
// GenerateReport(timeFrame domain.ReportTimeFrame, start, end time.Time) (*domain.Report, error) // GenerateReport(timeFrame domain.ReportTimeFrame, start, end time.Time) (*domain.Report, error)
// SaveReport(report *domain.Report) error // SaveReport(report *domain.Report) error
// FindReportsByTimeFrame(timeFrame domain.ReportTimeFrame, limit int) ([]*domain.Report, error) // FindReportsByTimeFrame(timeFrame domain.ReportTimeFrame, limit int) ([]*domain.Report, error)
@ -24,211 +30,211 @@ type ReportRepository interface {
// GetWalletTransactionsInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetWalletTransactionsInRangeRow, error) // GetWalletTransactionsInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetWalletTransactionsInRangeRow, error)
// GetCompanyWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetCompanyWiseReportRow, error) // GetCompanyWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetCompanyWiseReportRow, error)
// GetBranchWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetBranchWiseReportRow, error) // GetBranchWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetBranchWiseReportRow, error)
// }
// type ReportRepo struct {
// store *Store
// }
// func NewReportRepo(store *Store) ReportRepository {
// return &ReportRepo{store: store}
// }
func (s *Store) GenerateReport(timeFrame domain.ReportTimeFrame, start, end time.Time) (*domain.Report, error) {
// Implement SQL queries to calculate metrics
var report domain.Report
// Total Bets
err := s.conn.QueryRow(
context.Background(),
`SELECT COUNT(*) FROM bets
WHERE created_at BETWEEN $1 AND $2`, start, end).Scan(&report.TotalBets)
if err != nil {
return nil, err
} }
type ReportRepo struct { // Total Cash In
store *Store err = s.conn.QueryRow(
context.Background(),
`SELECT COALESCE(SUM(amount), 0) FROM transactions
WHERE type = 'stake' AND created_at BETWEEN $1 AND $2`, start, end).Scan(&report.TotalCashIn)
if err != nil {
return nil, err
} }
func NewReportRepo(store *Store) ReportRepository { // Similar queries for Cash Out and Cash Back...
return &ReportRepo{store: store}
report.TimeFrame = timeFrame
report.PeriodStart = start
report.PeriodEnd = end
report.GeneratedAt = time.Now()
return &report, nil
} }
// func (r *ReportRepo) GenerateReport(timeFrame domain.ReportTimeFrame, start, end time.Time) (*domain.Report, error) { func (s *Store) SaveReport(report *domain.Report) error {
// // Implement SQL queries to calculate metrics _, err := s.conn.Exec(
// var report domain.Report context.Background(),
`INSERT INTO reports
(id, time_frame, period_start, period_end, total_bets, total_cash_in, total_cash_out, total_cash_back, generated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
report.ID, report.TimeFrame, report.PeriodStart, report.PeriodEnd,
report.TotalBets, report.TotalCashIn, report.TotalCashOut, report.TotalCashBack, report.GeneratedAt)
return err
}
// // Total Bets func (s *Store) FindReportsByTimeFrame(timeFrame domain.ReportTimeFrame, limit int) ([]*domain.Report, error) {
// err := r.store.conn.QueryRow( rows, err := s.conn.Query(
// context.Background(), context.Background(),
// `SELECT COUNT(*) FROM bets `SELECT id, time_frame, period_start, period_end, total_bets,
// WHERE created_at BETWEEN $1 AND $2`, start, end).Scan(&report.TotalBets) total_cash_in, total_cash_out, total_cash_back, generated_at
// if err != nil { FROM reports
// return nil, err WHERE time_frame = $1
// } ORDER BY generated_at DESC
LIMIT $2`,
timeFrame, limit)
if err != nil {
return nil, err
}
defer rows.Close()
// // Total Cash In var reports []*domain.Report
// err = r.store.conn.QueryRow( for rows.Next() {
// context.Background(), var report domain.Report
// `SELECT COALESCE(SUM(amount), 0) FROM transactions err := rows.Scan(
// WHERE type = 'stake' AND created_at BETWEEN $1 AND $2`, start, end).Scan(&report.TotalCashIn) &report.ID,
// if err != nil { &report.TimeFrame,
// return nil, err &report.PeriodStart,
// } &report.PeriodEnd,
&report.TotalBets,
&report.TotalCashIn,
&report.TotalCashOut,
&report.TotalCashBack,
&report.GeneratedAt,
)
if err != nil {
return nil, err
}
reports = append(reports, &report)
}
// // Similar queries for Cash Out and Cash Back... if err := rows.Err(); err != nil {
return nil, err
}
// report.TimeFrame = timeFrame return reports, nil
// report.PeriodStart = start }
// report.PeriodEnd = end
// report.GeneratedAt = time.Now()
// return &report, nil func (s *Store) GetTotalBetsMadeInRange(ctx context.Context, from, to time.Time) (int64, error) {
// } params := dbgen.GetTotalBetsMadeInRangeParams{
From: ToPgTimestamp(from),
To: ToPgTimestamp(to),
}
return s.queries.GetTotalBetsMadeInRange(ctx, params)
}
// func (r *ReportRepo) SaveReport(report *domain.Report) error { func (s *Store) GetTotalCashBacksInRange(ctx context.Context, from, to time.Time) (float64, error) {
// _, err := r.store.conn.Exec( params := dbgen.GetTotalCashBacksInRangeParams{
// context.Background(), From: ToPgTimestamp(from),
// `INSERT INTO reports To: ToPgTimestamp(to),
// (id, time_frame, period_start, period_end, total_bets, total_cash_in, total_cash_out, total_cash_back, generated_at) }
// VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`, value, err := s.queries.GetTotalCashBacksInRange(ctx, params)
// report.ID, report.TimeFrame, report.PeriodStart, report.PeriodEnd, if err != nil {
// report.TotalBets, report.TotalCashIn, report.TotalCashOut, report.TotalCashBack, report.GeneratedAt) return 0, err
// return err }
// } return parseFloat(value)
}
// func (r *ReportRepo) FindReportsByTimeFrame(timeFrame domain.ReportTimeFrame, limit int) ([]*domain.Report, error) { func (s *Store) GetTotalCashMadeInRange(ctx context.Context, from, to time.Time) (float64, error) {
// rows, err := r.store.conn.Query( params := dbgen.GetTotalCashMadeInRangeParams{
// context.Background(), From: ToPgTimestamp(from),
// `SELECT id, time_frame, period_start, period_end, total_bets, To: ToPgTimestamp(to),
// total_cash_in, total_cash_out, total_cash_back, generated_at }
// FROM reports value, err := s.queries.GetTotalCashMadeInRange(ctx, params)
// WHERE time_frame = $1 if err != nil {
// ORDER BY generated_at DESC return 0, err
// LIMIT $2`, }
// timeFrame, limit) return parseFloat(value)
// if err != nil { }
// return nil, err
// }
// defer rows.Close()
// var reports []*domain.Report func (s *Store) GetTotalCashOutInRange(ctx context.Context, from, to time.Time) (float64, error) {
// for rows.Next() { params := dbgen.GetTotalCashOutInRangeParams{
// var report domain.Report From: ToPgTimestamp(from),
// err := rows.Scan( To: ToPgTimestamp(to),
// &report.ID, }
// &report.TimeFrame, value, err := s.queries.GetTotalCashOutInRange(ctx, params)
// &report.PeriodStart, if err != nil {
// &report.PeriodEnd, return 0, err
// &report.TotalBets, }
// &report.TotalCashIn, return parseFloat(value)
// &report.TotalCashOut, }
// &report.TotalCashBack,
// &report.GeneratedAt,
// )
// if err != nil {
// return nil, err
// }
// reports = append(reports, &report)
// }
// if err := rows.Err(); err != nil { func (s *Store) GetWalletTransactionsInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetWalletTransactionsInRangeRow, error) {
// return nil, err params := dbgen.GetWalletTransactionsInRangeParams{
// } CreatedAt: ToPgTimestamp(from),
CreatedAt_2: ToPgTimestamp(to),
}
return s.queries.GetWalletTransactionsInRange(ctx, params)
}
// return reports, nil func (s *Store) GetAllTicketsInRange(ctx context.Context, from, to time.Time) (dbgen.GetAllTicketsInRangeRow, error) {
// } params := dbgen.GetAllTicketsInRangeParams{
CreatedAt: ToPgTimestamp(from),
CreatedAt_2: ToPgTimestamp(to),
}
return s.queries.GetAllTicketsInRange(ctx, params)
}
// func (r *ReportRepo) GetTotalBetsMadeInRange(ctx context.Context, from, to time.Time) (int64, error) { func (s *Store) GetVirtualGameSummaryInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetVirtualGameSummaryInRangeRow, error) {
// params := dbgen.GetTotalBetsMadeInRangeParams{ params := dbgen.GetVirtualGameSummaryInRangeParams{
// From: ToPgTimestamp(from), CreatedAt: ToPgTimestamptz(from),
// To: ToPgTimestamp(to), CreatedAt_2: ToPgTimestamptz(to),
// } }
// return r.store.queries.GetTotalBetsMadeInRange(ctx, params) return s.queries.GetVirtualGameSummaryInRange(ctx, params)
// } }
// func (r *ReportRepo) GetTotalCashBacksInRange(ctx context.Context, from, to time.Time) (float64, error) { func ToPgTimestamp(t time.Time) pgtype.Timestamp {
// params := dbgen.GetTotalCashBacksInRangeParams{ return pgtype.Timestamp{Time: t, Valid: true}
// From: ToPgTimestamp(from), }
// To: ToPgTimestamp(to),
// }
// value, err := r.store.queries.GetTotalCashBacksInRange(ctx, params)
// if err != nil {
// return 0, err
// }
// return parseFloat(value)
// }
// func (r *ReportRepo) GetTotalCashMadeInRange(ctx context.Context, from, to time.Time) (float64, error) { func ToPgTimestamptz(t time.Time) pgtype.Timestamptz {
// params := dbgen.GetTotalCashMadeInRangeParams{ return pgtype.Timestamptz{Time: t, Valid: true}
// From: ToPgTimestamp(from), }
// To: ToPgTimestamp(to),
// }
// value, err := r.store.queries.GetTotalCashMadeInRange(ctx, params)
// if err != nil {
// return 0, err
// }
// return parseFloat(value)
// }
// func (r *ReportRepo) GetTotalCashOutInRange(ctx context.Context, from, to time.Time) (float64, error) { func parseFloat(value interface{}) (float64, error) {
// params := dbgen.GetTotalCashOutInRangeParams{ switch v := value.(type) {
// From: ToPgTimestamp(from), case float64:
// To: ToPgTimestamp(to), return v, nil
// } case int64:
// value, err := r.store.queries.GetTotalCashOutInRange(ctx, params) return float64(v), nil
// if err != nil { case pgtype.Numeric:
// return 0, err if !v.Valid {
// } return 0, nil
// return parseFloat(value) }
// } f, err := v.Float64Value()
if err != nil {
return 0, fmt.Errorf("failed to convert pgtype.Numeric to float64: %w", err)
}
return f.Float64, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unexpected type %T for value: %+v", v, v)
}
}
// func (r *ReportRepo) GetWalletTransactionsInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetWalletTransactionsInRangeRow, error) { // func (s *Store) GetCompanyWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetCompanyWiseReportRow, error) {
// params := dbgen.GetWalletTransactionsInRangeParams{
// CreatedAt: ToPgTimestamp(from),
// CreatedAt_2: ToPgTimestamp(to),
// }
// return r.store.queries.GetWalletTransactionsInRange(ctx, params)
// }
// func (r *ReportRepo) GetAllTicketsInRange(ctx context.Context, from, to time.Time) (dbgen.GetAllTicketsInRangeRow, error) {
// params := dbgen.GetAllTicketsInRangeParams{
// CreatedAt: ToPgTimestamp(from),
// CreatedAt_2: ToPgTimestamp(to),
// }
// return r.store.queries.GetAllTicketsInRange(ctx, params)
// }
// func (r *ReportRepo) GetVirtualGameSummaryInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetVirtualGameSummaryInRangeRow, error) {
// params := dbgen.GetVirtualGameSummaryInRangeParams{
// CreatedAt: ToPgTimestamptz(from),
// CreatedAt_2: ToPgTimestamptz(to),
// }
// return r.store.queries.GetVirtualGameSummaryInRange(ctx, params)
// }
// func ToPgTimestamp(t time.Time) pgtype.Timestamp {
// return pgtype.Timestamp{Time: t, Valid: true}
// }
// func ToPgTimestamptz(t time.Time) pgtype.Timestamptz {
// return pgtype.Timestamptz{Time: t, Valid: true}
// }
// func parseFloat(value interface{}) (float64, error) {
// switch v := value.(type) {
// case float64:
// return v, nil
// case int64:
// return float64(v), nil
// case pgtype.Numeric:
// if !v.Valid {
// return 0, nil
// }
// f, err := v.Float64Value()
// if err != nil {
// return 0, fmt.Errorf("failed to convert pgtype.Numeric to float64: %w", err)
// }
// return f.Float64, nil
// case nil:
// return 0, nil
// default:
// return 0, fmt.Errorf("unexpected type %T for value: %+v", v, v)
// }
// }
// func (r *ReportRepo) GetCompanyWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetCompanyWiseReportRow, error) {
// params := dbgen.GetCompanyWiseReportParams{ // params := dbgen.GetCompanyWiseReportParams{
// From: ToPgTimestamp(from), // From: ToPgTimestamp(from),
// To: ToPgTimestamp(to), // To: ToPgTimestamp(to),
// } // }
// return r.store.queries.GetCompanyWiseReport(ctx, params) // return s.queries.GetCompanyWiseReport(ctx, params)
// } // }
// func (r *ReportRepo) GetBranchWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetBranchWiseReportRow, error) { // func (s *Store) GetBranchWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetBranchWiseReportRow, error) {
// params := dbgen.GetBranchWiseReportParams{ // params := dbgen.GetBranchWiseReportParams{
// From: ToPgTimestamp(from), // From: ToPgTimestamp(from),
// To: ToPgTimestamp(to), // To: ToPgTimestamp(to),
// } // }
// return r.store.queries.GetBranchWiseReport(ctx, params) // return s.queries.GetBranchWiseReport(ctx, params)
// } // }

View File

@ -7,9 +7,13 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
// Interface for creating new otp store
func NewOTPStore(s *Store) ports.OtpStore { return s }
func (s *Store) CreateOtp(ctx context.Context, otp domain.Otp) error { func (s *Store) CreateOtp(ctx context.Context, otp domain.Otp) error {
return s.queries.CreateOtp(ctx, dbgen.CreateOtpParams{ return s.queries.CreateOtp(ctx, dbgen.CreateOtpParams{
SentTo: otp.SentTo, SentTo: otp.SentTo,

View File

@ -5,74 +5,20 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
func convertRaffleOutcome(raffle dbgen.Raffle) domain.Raffle { // Interface for creating new raffle store
return domain.Raffle{ func NewRaffleStore(s *Store) ports.RaffleStore { return s }
ID: raffle.ID,
CompanyID: raffle.CompanyID,
Name: raffle.Name,
CreatedAt: raffle.CreatedAt.Time,
ExpiresAt: raffle.ExpiresAt.Time,
TicketLimit: raffle.TicketLimit,
Type: raffle.Type,
Status: raffle.Status,
}
}
func convertRaffleTicketOutcome(raffle dbgen.RaffleTicket) domain.RaffleTicket {
return domain.RaffleTicket{
ID: raffle.ID,
RaffleID: raffle.RaffleID,
UserID: raffle.UserID,
IsActive: raffle.IsActive.Bool,
}
}
func convertJoinedRaffleTicketOutcome(raffle dbgen.GetUserRaffleTicketsRow) domain.RaffleTicketRes {
return domain.RaffleTicketRes{
TicketID: raffle.TicketID,
UserID: raffle.UserID,
Name: raffle.Name,
Type: raffle.Type,
ExpiresAt: raffle.ExpiresAt.Time,
Status: raffle.Status,
}
}
func convertCreateRaffle(raffle domain.CreateRaffle) dbgen.CreateRaffleParams {
return dbgen.CreateRaffleParams{
CompanyID: raffle.CompanyID,
Name: raffle.Name,
ExpiresAt: pgtype.Timestamp{
Time: *raffle.ExpiresAt,
Valid: true,
},
TicketLimit: raffle.TicketLimit,
Type: raffle.Type,
}
}
func convertRaffleStanding(raffleStanding dbgen.GetRaffleStandingRow) domain.RaffleStanding {
return domain.RaffleStanding{
UserID: raffleStanding.UserID,
RaffleID: raffleStanding.RaffleID,
FirstName: raffleStanding.FirstName,
LastName: raffleStanding.LastName,
PhoneNumber: raffleStanding.PhoneNumber.String,
Email: raffleStanding.Email.String,
TicketCount: raffleStanding.TicketCount,
}
}
func (s *Store) CreateRaffle(ctx context.Context, raffle domain.CreateRaffle) (domain.Raffle, error) { func (s *Store) CreateRaffle(ctx context.Context, raffle domain.CreateRaffle) (domain.Raffle, error) {
raffleRes, err := s.queries.CreateRaffle(ctx, convertCreateRaffle(raffle)) raffleRes, err := s.queries.CreateRaffle(ctx, domain.ConvertCreateRaffle(raffle))
if err != nil { if err != nil {
return domain.Raffle{}, err return domain.Raffle{}, err
} }
return convertRaffleOutcome(raffleRes), nil return domain.ConvertRaffleOutcome(raffleRes), nil
} }
func (s *Store) DeleteRaffle(ctx context.Context, raffleID int32) (domain.Raffle, error) { func (s *Store) DeleteRaffle(ctx context.Context, raffleID int32) (domain.Raffle, error) {
@ -81,7 +27,7 @@ func (s *Store) DeleteRaffle(ctx context.Context, raffleID int32) (domain.Raffle
return domain.Raffle{}, err return domain.Raffle{}, err
} }
return convertRaffleOutcome(raffleRes), nil return domain.ConvertRaffleOutcome(raffleRes), nil
} }
func (s *Store) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbgen.Raffle, error) { func (s *Store) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbgen.Raffle, error) {
@ -102,7 +48,7 @@ func (s *Store) CreateRaffleTicket(ctx context.Context, raffleTicketParams domai
return domain.RaffleTicket{}, err return domain.RaffleTicket{}, err
} }
return convertRaffleTicketOutcome(raffleTicket), nil return domain.ConvertRaffleTicketOutcome(raffleTicket), nil
} }
func (s *Store) GetUserRaffleTickets(ctx context.Context, userID int32) ([]domain.RaffleTicketRes, error) { func (s *Store) GetUserRaffleTickets(ctx context.Context, userID int32) ([]domain.RaffleTicketRes, error) {
@ -113,7 +59,7 @@ func (s *Store) GetUserRaffleTickets(ctx context.Context, userID int32) ([]domai
res := []domain.RaffleTicketRes{} res := []domain.RaffleTicketRes{}
for _, raffle := range raffleTickets { for _, raffle := range raffleTickets {
res = append(res, convertJoinedRaffleTicketOutcome(raffle)) res = append(res, domain.ConvertJoinedRaffleTicketOutcome(raffle))
} }
return res, nil return res, nil
@ -152,7 +98,7 @@ func (s *Store) GetRaffleStanding(ctx context.Context, raffleID, limit int32) ([
res := []domain.RaffleStanding{} res := []domain.RaffleStanding{}
for _, standing := range raffleStanding { for _, standing := range raffleStanding {
res = append(res, convertRaffleStanding(standing)) res = append(res, domain.ConvertRaffleStanding(standing))
} }
return res, nil return res, nil

View File

@ -5,30 +5,14 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
type ReferralRepository interface { // Interface for creating new referral store
CreateReferralCode(ctx context.Context, referralCode domain.CreateReferralCode) (domain.ReferralCode, error) func NewReferralStore(s *Store) ports.ReferralStore { return s }
CreateUserReferral(ctx context.Context, referral domain.CreateUserReferrals) (domain.UserReferral, error)
GetReferralCodesByUser(ctx context.Context, userID int64) ([]domain.ReferralCode, error)
GetReferralCode(ctx context.Context, code string) (domain.ReferralCode, error)
UpdateReferralCode(ctx context.Context, referral domain.UpdateReferralCode) error
GetReferralStats(ctx context.Context, userID int64, companyID int64) (domain.ReferralStats, error)
GetUserReferral(ctx context.Context, referredID int64) (domain.UserReferral, error)
GetUserReferralsByCode(ctx context.Context, code string) ([]domain.UserReferral, error)
GetUserReferralCount(ctx context.Context, referrerID int64) (int64, error)
}
type ReferralRepo struct { func (s *Store) CreateReferralCode(ctx context.Context, referralCode domain.CreateReferralCode) (domain.ReferralCode, error) {
store *Store newReferralCode, err := s.queries.CreateReferralCode(ctx, domain.ConvertCreateReferralCode(referralCode))
}
func NewReferralRepository(store *Store) ReferralRepository {
return &ReferralRepo{store: store}
}
func (r *ReferralRepo) CreateReferralCode(ctx context.Context, referralCode domain.CreateReferralCode) (domain.ReferralCode, error) {
newReferralCode, err := r.store.queries.CreateReferralCode(ctx, domain.ConvertCreateReferralCode(referralCode))
if err != nil { if err != nil {
return domain.ReferralCode{}, err return domain.ReferralCode{}, err
@ -36,8 +20,8 @@ func (r *ReferralRepo) CreateReferralCode(ctx context.Context, referralCode doma
return domain.ConvertDBReferralCode(newReferralCode), nil return domain.ConvertDBReferralCode(newReferralCode), nil
} }
func (r *ReferralRepo) CreateUserReferral(ctx context.Context, referral domain.CreateUserReferrals) (domain.UserReferral, error) { func (s *Store) CreateUserReferral(ctx context.Context, referral domain.CreateUserReferrals) (domain.UserReferral, error) {
newReferral, err := r.store.queries.CreateUserReferral(ctx, domain.ConvertCreateUserReferral(referral)) newReferral, err := s.queries.CreateUserReferral(ctx, domain.ConvertCreateUserReferral(referral))
if err != nil { if err != nil {
return domain.UserReferral{}, err return domain.UserReferral{}, err
@ -46,8 +30,8 @@ func (r *ReferralRepo) CreateUserReferral(ctx context.Context, referral domain.C
return domain.ConvertDBUserReferral(newReferral), nil return domain.ConvertDBUserReferral(newReferral), nil
} }
func (r *ReferralRepo) GetReferralCodesByUser(ctx context.Context, userID int64) ([]domain.ReferralCode, error) { func (s *Store) GetReferralCodesByUser(ctx context.Context, userID int64) ([]domain.ReferralCode, error) {
codes, err := r.store.queries.GetReferralCodeByUser(ctx, userID) codes, err := s.queries.GetReferralCodeByUser(ctx, userID)
if err != nil { if err != nil {
return nil, err return nil, err
@ -56,8 +40,8 @@ func (r *ReferralRepo) GetReferralCodesByUser(ctx context.Context, userID int64)
return domain.ConvertDBReferralCodes(codes), nil return domain.ConvertDBReferralCodes(codes), nil
} }
func (r *ReferralRepo) GetReferralCode(ctx context.Context, code string) (domain.ReferralCode, error) { func (s *Store) GetReferralCode(ctx context.Context, code string) (domain.ReferralCode, error) {
referralCode, err := r.store.queries.GetReferralCode(ctx, code) referralCode, err := s.queries.GetReferralCode(ctx, code)
if err != nil { if err != nil {
return domain.ReferralCode{}, err return domain.ReferralCode{}, err
@ -66,8 +50,8 @@ func (r *ReferralRepo) GetReferralCode(ctx context.Context, code string) (domain
return domain.ConvertDBReferralCode(referralCode), nil return domain.ConvertDBReferralCode(referralCode), nil
} }
func (r *ReferralRepo) UpdateReferralCode(ctx context.Context, referral domain.UpdateReferralCode) error { func (s *Store) UpdateReferralCode(ctx context.Context, referral domain.UpdateReferralCode) error {
err := r.store.queries.UpdateReferralCode(ctx, domain.ConvertUpdateReferralCode(referral)) err := s.queries.UpdateReferralCode(ctx, domain.ConvertUpdateReferralCode(referral))
if err != nil { if err != nil {
return err return err
@ -76,8 +60,8 @@ func (r *ReferralRepo) UpdateReferralCode(ctx context.Context, referral domain.U
return nil return nil
} }
func (r *ReferralRepo) GetReferralStats(ctx context.Context, userID int64, companyID int64) (domain.ReferralStats, error) { func (s *Store) GetReferralStats(ctx context.Context, userID int64, companyID int64) (domain.ReferralStats, error) {
stats, err := r.store.queries.GetReferralStats(ctx, dbgen.GetReferralStatsParams{ stats, err := s.queries.GetReferralStats(ctx, dbgen.GetReferralStatsParams{
ReferrerID: userID, ReferrerID: userID,
CompanyID: companyID, CompanyID: companyID,
}) })
@ -88,16 +72,16 @@ func (r *ReferralRepo) GetReferralStats(ctx context.Context, userID int64, compa
return domain.ConvertDBReferralStats(stats), nil return domain.ConvertDBReferralStats(stats), nil
} }
func (r *ReferralRepo) GetUserReferral(ctx context.Context, referredID int64) (domain.UserReferral, error) { func (s *Store) GetUserReferral(ctx context.Context, referredID int64) (domain.UserReferral, error) {
dbReferral, err := r.store.queries.GetUserReferral(ctx, referredID) dbReferral, err := s.queries.GetUserReferral(ctx, referredID)
if err != nil { if err != nil {
return domain.UserReferral{}, err return domain.UserReferral{}, err
} }
return domain.ConvertDBUserReferral(dbReferral), nil return domain.ConvertDBUserReferral(dbReferral), nil
} }
func (r *ReferralRepo) GetUserReferralsByCode(ctx context.Context, code string) ([]domain.UserReferral, error) { func (s *Store) GetUserReferralsByCode(ctx context.Context, code string) ([]domain.UserReferral, error) {
dbReferrals, err := r.store.queries.GetUserReferralsByCode(ctx, code) dbReferrals, err := s.queries.GetUserReferralsByCode(ctx, code)
if err != nil { if err != nil {
return nil, err return nil, err
@ -106,80 +90,10 @@ func (r *ReferralRepo) GetUserReferralsByCode(ctx context.Context, code string)
return domain.ConvertDBUserReferrals(dbReferrals), nil return domain.ConvertDBUserReferrals(dbReferrals), nil
} }
func (r *ReferralRepo) GetUserReferralCount(ctx context.Context, referrerID int64) (int64, error) { func (s *Store) GetUserReferralCount(ctx context.Context, referrerID int64) (int64, error) {
count, err := r.store.queries.GetUserReferralsCount(ctx, referrerID) count, err := s.queries.GetUserReferralsCount(ctx, referrerID)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return count, nil return count, nil
} }
// func (r *ReferralRepo) mapToDomainReferral(dbRef *dbgen.Referral) *domain.Referral {
// var referredID *int64
// if dbRef.ReferredID.Valid {
// referredID = &dbRef.ReferredID.Int64
// }
// rewardAmount := 0.0
// if dbRef.RewardAmount.Valid {
// if f8, err := dbRef.RewardAmount.Float64Value(); err == nil {
// rewardAmount = f8.Float64
// }
// }
// cashbackAmount := 0.0
// if dbRef.CashbackAmount.Valid {
// if f8, err := dbRef.CashbackAmount.Float64Value(); err == nil {
// cashbackAmount = f8.Float64
// }
// }
// return &domain.Referral{
// ID: dbRef.ID,
// ReferralCode: dbRef.ReferralCode,
// ReferrerID: dbRef.ReferrerID,
// ReferredID: referredID,
// Status: domain.ReferralStatus(dbRef.Status),
// RewardAmount: rewardAmount,
// CashbackAmount: cashbackAmount,
// CreatedAt: dbRef.CreatedAt.Time,
// UpdatedAt: dbRef.UpdatedAt.Time,
// ExpiresAt: dbRef.ExpiresAt.Time,
// }
// }
// func (r *ReferralRepo) mapToDomainSettings(dbSettings *dbgen.ReferralSetting) *domain.ReferralSettings {
// rewardAmount := 0.0
// if dbSettings.ReferralRewardAmount.Valid {
// if f8, err := dbSettings.ReferralRewardAmount.Float64Value(); err == nil {
// rewardAmount = f8.Float64
// }
// }
// cashbackPercentage := 0.0
// if dbSettings.CashbackPercentage.Valid {
// if f8, err := dbSettings.CashbackPercentage.Float64Value(); err == nil {
// cashbackPercentage = f8.Float64
// }
// }
// betReferralBonusPercentage := 0.0
// if dbSettings.BetReferralBonusPercentage.Valid {
// if f8, err := dbSettings.BetReferralBonusPercentage.Float64Value(); err == nil {
// betReferralBonusPercentage = f8.Float64
// }
// }
// return &domain.ReferralSettings{
// ID: dbSettings.ID,
// ReferralRewardAmount: rewardAmount,
// CashbackPercentage: cashbackPercentage,
// BetReferralBonusPercentage: betReferralBonusPercentage, // New field
// MaxReferrals: dbSettings.MaxReferrals,
// ExpiresAfterDays: dbSettings.ExpiresAfterDays,
// UpdatedBy: dbSettings.UpdatedBy,
// CreatedAt: dbSettings.CreatedAt.Time,
// UpdatedAt: dbSettings.UpdatedAt.Time,
// Version: dbSettings.Version,
// }
// }

View File

@ -6,11 +6,14 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
func (s *Store) CreateReportRequest(ctx context.Context, report domain.CreateReportRequest) (domain.ReportRequest, error) { // Interface for ReportStore
func NewReportStore(s *Store) ports.ReportStore { return s }
func (s *Store) CreateReportRequest(ctx context.Context, report domain.CreateReportRequest) (domain.ReportRequest, error) {
reportMetadata, err := report.Metadata.ToPG() reportMetadata, err := report.Metadata.ToPG()
if err != nil { if err != nil {
return domain.ReportRequest{}, err return domain.ReportRequest{}, err

View File

@ -5,9 +5,14 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
// Interface for creating new result log store
func NewResultLogStore(s *Store) ports.ResultLogStore { return s }
func (s *Store) CreateResultLog(ctx context.Context, result domain.CreateResultLog) (domain.ResultLog, error) { func (s *Store) CreateResultLog(ctx context.Context, result domain.CreateResultLog) (domain.ResultLog, error) {
dbResult, err := s.queries.CreateResultLog(ctx, domain.ConvertCreateResultLog(result)) dbResult, err := s.queries.CreateResultLog(ctx, domain.ConvertCreateResultLog(result))
if err != nil { if err != nil {

View File

@ -5,9 +5,13 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"go.uber.org/zap" "go.uber.org/zap"
) )
// Interface for creating new setting store
func NewSettingStore(s *Store) ports.SettingStore { return s }
func (s *Store) GetGlobalSettingList(ctx context.Context) (domain.SettingList, error) { func (s *Store) GetGlobalSettingList(ctx context.Context) (domain.SettingList, error) {
settings, err := s.queries.GetGlobalSettings(ctx) settings, err := s.queries.GetGlobalSettings(ctx)
if err != nil { if err != nil {

View File

@ -6,133 +6,20 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
func convertDBShopTransaction(transaction dbgen.ShopTransaction) domain.ShopTransaction { // Interface for creating new shop transaction store
return domain.ShopTransaction{ func NewTransactionStore(s *Store) ports.TransactionStore { return s }
ID: transaction.ID,
Amount: domain.Currency(transaction.Amount),
BranchID: transaction.BranchID,
UserID: transaction.UserID,
Type: domain.ShopTransactionType(transaction.Type),
PaymentOption: domain.PaymentOption(transaction.PaymentOption),
FullName: transaction.FullName,
PhoneNumber: transaction.PhoneNumber,
BankCode: domain.ValidString{
Value: transaction.BankCode.String,
Valid: transaction.BankCode.Valid,
},
BeneficiaryName: domain.ValidString{
Value: transaction.BeneficiaryName.String,
Valid: transaction.BeneficiaryName.Valid,
},
AccountName: domain.ValidString{
Value: transaction.AccountName.String,
Valid: transaction.AccountName.Valid,
},
AccountNumber: domain.ValidString{
Value: transaction.AccountName.String,
Valid: transaction.AccountNumber.Valid,
},
ReferenceNumber: domain.ValidString{
Value: transaction.ReferenceNumber.String,
Valid: transaction.ReferenceNumber.Valid,
},
ApprovedBy: domain.ValidInt64{
Value: transaction.ApprovedBy.Int64,
Valid: transaction.ApprovedBy.Valid,
},
CreatedAt: transaction.CreatedAt.Time,
UpdatedAt: transaction.UpdatedAt.Time,
Verified: transaction.Verified,
CompanyID: transaction.CompanyID,
}
}
func convertDBShopTransactionDetail(transaction dbgen.ShopTransactionDetail) domain.ShopTransactionDetail {
return domain.ShopTransactionDetail{
ID: transaction.ID,
Amount: domain.Currency(transaction.Amount),
BranchID: transaction.BranchID,
UserID: transaction.UserID,
CreatorFirstName: transaction.CreatorFirstName.String,
CreatorLastName: transaction.CreatorLastName.String,
CreatorPhoneNumber: transaction.CreatorPhoneNumber.String,
Type: domain.ShopTransactionType(transaction.Type),
PaymentOption: domain.PaymentOption(transaction.PaymentOption),
FullName: transaction.FullName,
PhoneNumber: transaction.PhoneNumber,
BankCode: domain.ValidString{
Value: transaction.BankCode.String,
Valid: transaction.BankCode.Valid,
},
BeneficiaryName: domain.ValidString{
Value: transaction.BeneficiaryName.String,
Valid: transaction.BeneficiaryName.Valid,
},
AccountName: domain.ValidString{
Value: transaction.AccountName.String,
Valid: transaction.AccountName.Valid,
},
AccountNumber: domain.ValidString{
Value: transaction.AccountName.String,
Valid: transaction.AccountNumber.Valid,
},
ReferenceNumber: domain.ValidString{
Value: transaction.ReferenceNumber.String,
Valid: transaction.ReferenceNumber.Valid,
},
ApprovedBy: domain.ValidInt64{
Value: transaction.ApprovedBy.Int64,
Valid: transaction.ApprovedBy.Valid,
},
ApproverFirstName: domain.ValidString{
Value: transaction.ApproverFirstName.String,
Valid: transaction.ApproverFirstName.Valid,
},
ApproverLastName: domain.ValidString{
Value: transaction.ApproverLastName.String,
Valid: transaction.ApproverLastName.Valid,
},
ApproverPhoneNumber: domain.ValidString{
Value: transaction.ApproverPhoneNumber.String,
Valid: transaction.ApproverPhoneNumber.Valid,
},
CreatedAt: transaction.CreatedAt.Time,
UpdatedAt: transaction.UpdatedAt.Time,
Verified: transaction.Verified,
CompanyID: transaction.CompanyID,
BranchName: transaction.BranchName.String,
BranchLocation: transaction.BranchLocation.String,
}
}
func convertCreateShopTransaction(transaction domain.CreateShopTransaction) dbgen.CreateShopTransactionParams {
return dbgen.CreateShopTransactionParams{
Amount: int64(transaction.Amount),
BranchID: transaction.BranchID,
UserID: transaction.UserID,
Type: int64(transaction.Type),
PaymentOption: int64(transaction.PaymentOption),
FullName: transaction.FullName,
PhoneNumber: transaction.PhoneNumber,
CompanyID: transaction.CompanyID,
BankCode: pgtype.Text{String: transaction.BankCode.Value, Valid: transaction.BankCode.Valid},
BeneficiaryName: pgtype.Text{String: transaction.BeneficiaryName.Value, Valid: transaction.BeneficiaryName.Valid},
AccountName: pgtype.Text{String: transaction.AccountName.Value, Valid: transaction.AccountName.Valid},
AccountNumber: pgtype.Text{String: transaction.AccountNumber.Value, Valid: transaction.AccountNumber.Valid},
ReferenceNumber: pgtype.Text{String: transaction.ReferenceNumber.Value, Valid: transaction.ReferenceNumber.Valid},
}
}
func (s *Store) CreateShopTransaction(ctx context.Context, transaction domain.CreateShopTransaction) (domain.ShopTransaction, error) { func (s *Store) CreateShopTransaction(ctx context.Context, transaction domain.CreateShopTransaction) (domain.ShopTransaction, error) {
newTransaction, err := s.queries.CreateShopTransaction(ctx, convertCreateShopTransaction(transaction)) newTransaction, err := s.queries.CreateShopTransaction(ctx, domain.ConvertCreateShopTransaction(transaction))
if err != nil { if err != nil {
return domain.ShopTransaction{}, err return domain.ShopTransaction{}, err
} }
return convertDBShopTransaction(newTransaction), err return domain.ConvertDBShopTransaction(newTransaction), err
} }
func (s *Store) GetShopTransactionByID(ctx context.Context, id int64) (domain.ShopTransactionDetail, error) { func (s *Store) GetShopTransactionByID(ctx context.Context, id int64) (domain.ShopTransactionDetail, error) {
@ -141,35 +28,17 @@ func (s *Store) GetShopTransactionByID(ctx context.Context, id int64) (domain.Sh
return domain.ShopTransactionDetail{}, err return domain.ShopTransactionDetail{}, err
} }
return convertDBShopTransactionDetail(transaction), nil return domain.ConvertDBShopTransactionDetail(transaction), nil
} }
func (s *Store) GetAllShopTransactions(ctx context.Context, filter domain.ShopTransactionFilter) ([]domain.ShopTransactionDetail, error) { func (s *Store) GetAllShopTransactions(ctx context.Context, filter domain.ShopTransactionFilter) ([]domain.ShopTransactionDetail, error) {
transaction, err := s.queries.GetAllShopTransactions(ctx, dbgen.GetAllShopTransactionsParams{ transaction, err := s.queries.GetAllShopTransactions(ctx, dbgen.GetAllShopTransactionsParams{
BranchID: pgtype.Int8{ BranchID: filter.BranchID.ToPG(),
Int64: filter.BranchID.Value, CompanyID: filter.CompanyID.ToPG(),
Valid: filter.BranchID.Valid, UserID: filter.UserID.ToPG(),
}, Query: filter.Query.ToPG(),
CompanyID: pgtype.Int8{ CreatedBefore: filter.CreatedBefore.ToPG(),
Int64: filter.CompanyID.Value, CreatedAfter: filter.CreatedAfter.ToPG(),
Valid: filter.CompanyID.Valid,
},
UserID: pgtype.Int8{
Int64: filter.UserID.Value,
Valid: filter.UserID.Valid,
},
Query: pgtype.Text{
String: filter.Query.Value,
Valid: filter.Query.Valid,
},
CreatedBefore: pgtype.Timestamp{
Time: filter.CreatedBefore.Value,
Valid: filter.CreatedBefore.Valid,
},
CreatedAfter: pgtype.Timestamp{
Time: filter.CreatedAfter.Value,
Valid: filter.CreatedAfter.Valid,
},
}) })
if err != nil { if err != nil {
@ -178,7 +47,7 @@ func (s *Store) GetAllShopTransactions(ctx context.Context, filter domain.ShopTr
var result []domain.ShopTransactionDetail = make([]domain.ShopTransactionDetail, 0, len(transaction)) var result []domain.ShopTransactionDetail = make([]domain.ShopTransactionDetail, 0, len(transaction))
for _, tAction := range transaction { for _, tAction := range transaction {
result = append(result, convertDBShopTransactionDetail(tAction)) result = append(result, domain.ConvertDBShopTransactionDetail(tAction))
} }
return result, nil return result, nil
} }
@ -191,7 +60,7 @@ func (s *Store) GetShopTransactionByBranch(ctx context.Context, id int64) ([]dom
var result []domain.ShopTransactionDetail = make([]domain.ShopTransactionDetail, 0, len(transaction)) var result []domain.ShopTransactionDetail = make([]domain.ShopTransactionDetail, 0, len(transaction))
for _, ticket := range transaction { for _, ticket := range transaction {
result = append(result, convertDBShopTransactionDetail(ticket)) result = append(result, domain.ConvertDBShopTransactionDetail(ticket))
} }
return result, nil return result, nil
} }
@ -208,7 +77,6 @@ func (s *Store) UpdateShopTransactionVerified(ctx context.Context, id int64, ver
return err return err
} }
// GetTransactionTotals returns total deposits and withdrawals // GetTransactionTotals returns total deposits and withdrawals
func (s *Store) GetTransactionTotals(ctx context.Context, filter domain.ReportFilter) (deposits, withdrawals domain.Currency, err error) { func (s *Store) GetTransactionTotals(ctx context.Context, filter domain.ReportFilter) (deposits, withdrawals domain.Currency, err error) {
query := `SELECT query := `SELECT

View File

@ -5,85 +5,19 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/jackc/pgx/v5/pgtype" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
func convertDBTicket(ticket dbgen.Ticket) domain.Ticket { // Interface for creating new user store
return domain.Ticket{ func NewTicketStore(s *Store) ports.TicketStore { return s }
ID: ticket.ID,
Amount: domain.Currency(ticket.Amount),
TotalOdds: ticket.TotalOdds,
CompanyID: ticket.CompanyID,
}
}
func convertDBTicketOutcomes(ticket dbgen.TicketWithOutcome) domain.GetTicket {
var outcomes []domain.TicketOutcome = make([]domain.TicketOutcome, 0, len(ticket.Outcomes))
for _, outcome := range ticket.Outcomes {
outcomes = append(outcomes, domain.TicketOutcome{
ID: outcome.ID,
TicketID: outcome.TicketID,
EventID: outcome.EventID,
OddID: outcome.OddID,
HomeTeamName: outcome.HomeTeamName,
AwayTeamName: outcome.AwayTeamName,
MarketID: outcome.MarketID,
MarketName: outcome.MarketName,
Odd: outcome.Odd,
OddName: outcome.OddName,
OddHeader: outcome.OddHeader,
OddHandicap: outcome.OddHandicap,
Status: domain.OutcomeStatus(outcome.Status),
Expires: outcome.Expires.Time,
})
}
return domain.GetTicket{
ID: ticket.ID,
CompanyID: ticket.CompanyID,
Amount: domain.Currency(ticket.Amount),
TotalOdds: ticket.TotalOdds,
Outcomes: outcomes,
}
}
func convertDBCreateTicketOutcome(ticketOutcome domain.CreateTicketOutcome) dbgen.CreateTicketOutcomeParams {
return dbgen.CreateTicketOutcomeParams{
TicketID: ticketOutcome.TicketID,
EventID: ticketOutcome.EventID,
OddID: ticketOutcome.OddID,
HomeTeamName: ticketOutcome.HomeTeamName,
AwayTeamName: ticketOutcome.AwayTeamName,
MarketID: ticketOutcome.MarketID,
MarketName: ticketOutcome.MarketName,
Odd: ticketOutcome.Odd,
OddName: ticketOutcome.OddName,
OddHeader: ticketOutcome.OddHeader,
OddHandicap: ticketOutcome.OddHandicap,
Expires: pgtype.Timestamp{
Time: ticketOutcome.Expires,
Valid: true,
},
}
}
func convertCreateTicket(ticket domain.CreateTicket) dbgen.CreateTicketParams {
return dbgen.CreateTicketParams{
Amount: int64(ticket.Amount),
TotalOdds: ticket.TotalOdds,
Ip: ticket.IP,
CompanyID: ticket.CompanyID,
}
}
func (s *Store) CreateTicket(ctx context.Context, ticket domain.CreateTicket) (domain.Ticket, error) { func (s *Store) CreateTicket(ctx context.Context, ticket domain.CreateTicket) (domain.Ticket, error) {
newTicket, err := s.queries.CreateTicket(ctx, convertCreateTicket(ticket)) newTicket, err := s.queries.CreateTicket(ctx, domain.ConvertCreateTicket(ticket))
if err != nil { if err != nil {
return domain.Ticket{}, err return domain.Ticket{}, err
} }
return convertDBTicket(newTicket), err return domain.ConvertDBTicket(newTicket), err
} }
@ -91,7 +25,7 @@ func (s *Store) CreateTicketOutcome(ctx context.Context, outcomes []domain.Creat
var dbParams []dbgen.CreateTicketOutcomeParams = make([]dbgen.CreateTicketOutcomeParams, 0, len(outcomes)) var dbParams []dbgen.CreateTicketOutcomeParams = make([]dbgen.CreateTicketOutcomeParams, 0, len(outcomes))
for _, outcome := range outcomes { for _, outcome := range outcomes {
dbParams = append(dbParams, convertDBCreateTicketOutcome(outcome)) dbParams = append(dbParams, domain.ConvertDBCreateTicketOutcome(outcome))
} }
rows, err := s.queries.CreateTicketOutcome(ctx, dbParams) rows, err := s.queries.CreateTicketOutcome(ctx, dbParams)
@ -110,7 +44,7 @@ func (s *Store) GetTicketByID(ctx context.Context, id int64) (domain.GetTicket,
return domain.GetTicket{}, err return domain.GetTicket{}, err
} }
return convertDBTicketOutcomes(ticket), nil return domain.ConvertDBTicketOutcomes(ticket), nil
} }
func (s *Store) GetAllTickets(ctx context.Context, filter domain.TicketFilter) ([]domain.GetTicket, error) { func (s *Store) GetAllTickets(ctx context.Context, filter domain.TicketFilter) ([]domain.GetTicket, error) {
@ -121,7 +55,7 @@ func (s *Store) GetAllTickets(ctx context.Context, filter domain.TicketFilter) (
var result []domain.GetTicket = make([]domain.GetTicket, 0, len(tickets)) var result []domain.GetTicket = make([]domain.GetTicket, 0, len(tickets))
for _, ticket := range tickets { for _, ticket := range tickets {
result = append(result, convertDBTicketOutcomes(ticket)) result = append(result, domain.ConvertDBTicketOutcomes(ticket))
} }
return result, nil return result, nil

View File

@ -5,104 +5,19 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
func convertDBTransferDetail(transfer dbgen.WalletTransferDetail) domain.TransferDetail { // Interface for creating new transfer store
return domain.TransferDetail{ func NewTransferStore(s *Store) ports.TransferStore { return s }
ID: transfer.ID,
Amount: domain.Currency(transfer.Amount.Int64),
Type: domain.TransferType(transfer.Type.String),
Verified: transfer.Verified.Bool,
Message: transfer.Message,
ReceiverWalletID: domain.ValidInt64{
Value: transfer.ReceiverWalletID.Int64,
Valid: transfer.ReceiverWalletID.Valid,
},
SenderWalletID: domain.ValidInt64{
Value: transfer.SenderWalletID.Int64,
Valid: transfer.SenderWalletID.Valid,
},
DepositorID: domain.ValidInt64{
Value: transfer.CashierID.Int64,
Valid: transfer.CashierID.Valid,
},
DepositorFirstName: transfer.FirstName.String,
DepositorLastName: transfer.LastName.String,
DepositorPhoneNumber: transfer.PhoneNumber.String,
PaymentMethod: domain.PaymentMethod(transfer.PaymentMethod.String),
ReferenceNumber: transfer.ReferenceNumber,
SessionID: transfer.SessionID.String,
Status: transfer.Status.String,
CreatedAt: transfer.CreatedAt.Time,
UpdatedAt: transfer.UpdatedAt.Time,
}
}
func convertDBTransfer(transfer dbgen.WalletTransfer) domain.Transfer {
return domain.Transfer{
ID: transfer.ID,
Amount: domain.Currency(transfer.Amount.Int64),
Type: domain.TransferType(transfer.Type.String),
Verified: transfer.Verified.Bool,
Message: transfer.Message,
ReceiverWalletID: domain.ValidInt64{
Value: transfer.ReceiverWalletID.Int64,
Valid: transfer.ReceiverWalletID.Valid,
},
SenderWalletID: domain.ValidInt64{
Value: transfer.SenderWalletID.Int64,
Valid: transfer.SenderWalletID.Valid,
},
DepositorID: domain.ValidInt64{
Value: transfer.CashierID.Int64,
Valid: transfer.CashierID.Valid,
},
PaymentMethod: domain.PaymentMethod(transfer.PaymentMethod.String),
ReferenceNumber: transfer.ReferenceNumber,
SessionID: transfer.SessionID.String,
Status: transfer.Status.String,
CreatedAt: transfer.CreatedAt.Time,
UpdatedAt: transfer.UpdatedAt.Time,
}
}
func convertCreateTransfer(transfer domain.CreateTransfer) dbgen.CreateTransferParams {
return dbgen.CreateTransferParams{
Message: transfer.Message,
Amount: pgtype.Int8{Int64: int64(transfer.Amount), Valid: true},
Type: pgtype.Text{String: string(transfer.Type), Valid: true},
ReceiverWalletID: pgtype.Int8{
Int64: transfer.ReceiverWalletID.Value,
Valid: transfer.ReceiverWalletID.Valid,
},
SenderWalletID: pgtype.Int8{
Int64: transfer.SenderWalletID.Value,
Valid: transfer.SenderWalletID.Valid,
},
CashierID: pgtype.Int8{
Int64: transfer.CashierID.Value,
Valid: transfer.CashierID.Valid,
},
ReferenceNumber: string(transfer.ReferenceNumber),
SessionID: pgtype.Text{
String: transfer.SessionID,
Valid: true,
},
PaymentMethod: pgtype.Text{String: string(transfer.PaymentMethod), Valid: true},
Verified: pgtype.Bool{
Bool: transfer.Verified,
Valid: true,
},
}
}
func (s *Store) CreateTransfer(ctx context.Context, transfer domain.CreateTransfer) (domain.Transfer, error) { func (s *Store) CreateTransfer(ctx context.Context, transfer domain.CreateTransfer) (domain.Transfer, error) {
newTransfer, err := s.queries.CreateTransfer(ctx, convertCreateTransfer(transfer)) newTransfer, err := s.queries.CreateTransfer(ctx, domain.ConvertCreateTransfer(transfer))
if err != nil { if err != nil {
return domain.Transfer{}, err return domain.Transfer{}, err
} }
return convertDBTransfer(newTransfer), nil return domain.ConvertDBTransfer(newTransfer), nil
} }
func (s *Store) GetAllTransfers(ctx context.Context) ([]domain.TransferDetail, error) { func (s *Store) GetAllTransfers(ctx context.Context) ([]domain.TransferDetail, error) {
@ -113,7 +28,7 @@ func (s *Store) GetAllTransfers(ctx context.Context) ([]domain.TransferDetail, e
var result []domain.TransferDetail = make([]domain.TransferDetail, 0, len(transfers)) var result []domain.TransferDetail = make([]domain.TransferDetail, 0, len(transfers))
for _, transfer := range transfers { for _, transfer := range transfers {
result = append(result, convertDBTransferDetail(transfer)) result = append(result, domain.ConvertDBTransferDetail(transfer))
} }
return result, nil return result, nil
} }
@ -127,7 +42,7 @@ func (s *Store) GetTransfersByWallet(ctx context.Context, walletID int64) ([]dom
var result []domain.TransferDetail = make([]domain.TransferDetail, 0, len(transfers)) var result []domain.TransferDetail = make([]domain.TransferDetail, 0, len(transfers))
for _, transfer := range transfers { for _, transfer := range transfers {
result = append(result, convertDBTransferDetail(transfer)) result = append(result, domain.ConvertDBTransferDetail(transfer))
} }
return result, nil return result, nil
} }
@ -137,7 +52,7 @@ func (s *Store) GetTransferByReference(ctx context.Context, reference string) (d
if err != nil { if err != nil {
return domain.TransferDetail{}, nil return domain.TransferDetail{}, nil
} }
return convertDBTransferDetail(transfer), nil return domain.ConvertDBTransferDetail(transfer), nil
} }
func (s *Store) GetTransferByID(ctx context.Context, id int64) (domain.TransferDetail, error) { func (s *Store) GetTransferByID(ctx context.Context, id int64) (domain.TransferDetail, error) {
@ -145,7 +60,7 @@ func (s *Store) GetTransferByID(ctx context.Context, id int64) (domain.TransferD
if err != nil { if err != nil {
return domain.TransferDetail{}, nil return domain.TransferDetail{}, nil
} }
return convertDBTransferDetail(transfer), nil return domain.ConvertDBTransferDetail(transfer), nil
} }
func (s *Store) GetTransferStats(ctx context.Context, walletID int64) (domain.TransferStats, error) { func (s *Store) GetTransferStats(ctx context.Context, walletID int64) (domain.TransferStats, error) {

View File

@ -9,10 +9,15 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
// Interface for creating new user store
func NewUserStore(s *Store) ports.UserStore { return s }
func (s *Store) CreateUser(ctx context.Context, user domain.User, usedOtpId int64, is_company bool) (domain.User, error) { func (s *Store) CreateUser(ctx context.Context, user domain.User, usedOtpId int64, is_company bool) (domain.User, error) {
err := s.queries.MarkOtpAsUsed(ctx, dbgen.MarkOtpAsUsedParams{ err := s.queries.MarkOtpAsUsed(ctx, dbgen.MarkOtpAsUsedParams{
ID: usedOtpId, ID: usedOtpId,
@ -529,6 +534,46 @@ func (s *Store) GetAdminByCompanyID(ctx context.Context, companyID int64) (domai
}, nil }, nil
} }
func (s *Store) GetUserByEmailPhone(ctx context.Context, email, phone string, companyID domain.ValidInt64) (domain.User, error) {
user, err := s.queries.GetUserByEmailPhone(ctx, dbgen.GetUserByEmailPhoneParams{
Email: pgtype.Text{
String: email,
Valid: true,
},
PhoneNumber: pgtype.Text{
String: phone,
Valid: true,
},
CompanyID: companyID.ToPG(),
})
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return domain.User{}, authentication.ErrUserNotFound
}
return domain.User{}, err
}
return domain.User{
ID: user.ID,
FirstName: user.FirstName,
LastName: user.LastName,
Email: user.Email.String,
PhoneNumber: user.PhoneNumber.String,
Password: user.Password,
Role: domain.Role(user.Role),
EmailVerified: user.EmailVerified,
PhoneVerified: user.PhoneVerified,
CreatedAt: user.CreatedAt.Time,
UpdatedAt: user.UpdatedAt.Time,
SuspendedAt: user.SuspendedAt.Time,
Suspended: user.Suspended,
CompanyID: domain.ValidInt64{
Value: user.CompanyID.Int64,
Valid: user.CompanyID.Valid,
},
}, nil
}
// GetCustomerCounts returns total and active customer counts // GetCustomerCounts returns total and active customer counts
func (s *Store) GetCustomerCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) { func (s *Store) GetCustomerCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) {
query := `SELECT query := `SELECT

View File

@ -6,86 +6,31 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
func convertDBWallet(wallet dbgen.Wallet) domain.Wallet { // Interface for creating new wallet store
return domain.Wallet{ func NewWalletStore(s *Store) ports.WalletStore { return s }
ID: wallet.ID,
Balance: domain.Currency(wallet.Balance),
IsWithdraw: wallet.IsWithdraw,
IsBettable: wallet.IsBettable,
IsTransferable: wallet.IsTransferable,
IsActive: wallet.IsActive,
UserID: wallet.UserID,
Type: domain.WalletType(wallet.Type),
UpdatedAt: wallet.UpdatedAt.Time,
CreatedAt: wallet.CreatedAt.Time,
}
}
func convertCreateWallet(wallet domain.CreateWallet) dbgen.CreateWalletParams {
return dbgen.CreateWalletParams{
IsWithdraw: wallet.IsWithdraw,
IsBettable: wallet.IsBettable,
IsTransferable: wallet.IsTransferable,
UserID: wallet.UserID,
Type: string(wallet.Type),
}
}
func convertDBCustomerWallet(customerWallet dbgen.CustomerWallet) domain.CustomerWallet {
return domain.CustomerWallet{
ID: customerWallet.ID,
RegularID: customerWallet.RegularWalletID,
StaticID: customerWallet.StaticWalletID,
CustomerID: customerWallet.CustomerID,
}
}
func convertCreateCustomerWallet(customerWallet domain.CreateCustomerWallet) dbgen.CreateCustomerWalletParams {
return dbgen.CreateCustomerWalletParams{
CustomerID: customerWallet.CustomerID,
RegularWalletID: customerWallet.RegularWalletID,
StaticWalletID: customerWallet.StaticWalletID,
}
}
func convertDBGetCustomerWallet(customerWallet dbgen.CustomerWalletDetail) domain.GetCustomerWallet {
return domain.GetCustomerWallet{
ID: customerWallet.ID,
RegularID: customerWallet.RegularID,
RegularBalance: domain.Currency(customerWallet.RegularBalance),
StaticID: customerWallet.StaticID,
StaticBalance: domain.Currency(customerWallet.StaticBalance),
CustomerID: customerWallet.CustomerID,
RegularIsActive: customerWallet.RegularIsActive,
StaticIsActive: customerWallet.StaticIsActive,
RegularUpdatedAt: customerWallet.RegularUpdatedAt.Time,
StaticUpdatedAt: customerWallet.StaticUpdatedAt.Time,
CreatedAt: customerWallet.CreatedAt.Time,
FirstName: customerWallet.FirstName,
LastName: customerWallet.LastName,
PhoneNumber: customerWallet.PhoneNumber.String,
}
}
func (s *Store) CreateWallet(ctx context.Context, wallet domain.CreateWallet) (domain.Wallet, error) { func (s *Store) CreateWallet(ctx context.Context, wallet domain.CreateWallet) (domain.Wallet, error) {
newWallet, err := s.queries.CreateWallet(ctx, convertCreateWallet(wallet)) newWallet, err := s.queries.CreateWallet(ctx, domain.ConvertCreateWallet(wallet))
if err != nil { if err != nil {
if IsUniqueViolation(err) { if IsUniqueViolation(err) {
return domain.Wallet{}, domain.ErrWalletIDDuplicate return domain.Wallet{}, domain.ErrWalletIDDuplicate
} }
return domain.Wallet{}, err return domain.Wallet{}, err
} }
return convertDBWallet(newWallet), nil return domain.ConvertDBWallet(newWallet), nil
} }
func (s *Store) CreateCustomerWallet(ctx context.Context, customerWallet domain.CreateCustomerWallet) (domain.CustomerWallet, error) { func (s *Store) CreateCustomerWallet(ctx context.Context, customerWallet domain.CreateCustomerWallet) (domain.CustomerWallet, error) {
newCustomerWallet, err := s.queries.CreateCustomerWallet(ctx, convertCreateCustomerWallet(customerWallet)) newCustomerWallet, err := s.queries.CreateCustomerWallet(ctx, domain.ConvertCreateCustomerWallet(customerWallet))
if err != nil { if err != nil {
return domain.CustomerWallet{}, err return domain.CustomerWallet{}, err
} }
return convertDBCustomerWallet(newCustomerWallet), nil return domain.ConvertDBCustomerWallet(newCustomerWallet), nil
} }
func (s *Store) GetWalletByID(ctx context.Context, id int64) (domain.Wallet, error) { func (s *Store) GetWalletByID(ctx context.Context, id int64) (domain.Wallet, error) {
@ -94,7 +39,7 @@ func (s *Store) GetWalletByID(ctx context.Context, id int64) (domain.Wallet, err
if err != nil { if err != nil {
return domain.Wallet{}, err return domain.Wallet{}, err
} }
return convertDBWallet(wallet), nil return domain.ConvertDBWallet(wallet), nil
} }
func (s *Store) GetAllWallets(ctx context.Context) ([]domain.Wallet, error) { func (s *Store) GetAllWallets(ctx context.Context) ([]domain.Wallet, error) {
@ -106,7 +51,7 @@ func (s *Store) GetAllWallets(ctx context.Context) ([]domain.Wallet, error) {
var result []domain.Wallet = make([]domain.Wallet, 0, len(wallets)) var result []domain.Wallet = make([]domain.Wallet, 0, len(wallets))
for _, wallet := range wallets { for _, wallet := range wallets {
result = append(result, convertDBWallet(wallet)) result = append(result, domain.ConvertDBWallet(wallet))
} }
return result, nil return result, nil
} }
@ -120,7 +65,7 @@ func (s *Store) GetWalletsByUser(ctx context.Context, userID int64) ([]domain.Wa
var result []domain.Wallet = make([]domain.Wallet, 0, len(wallets)) var result []domain.Wallet = make([]domain.Wallet, 0, len(wallets))
for _, wallet := range wallets { for _, wallet := range wallets {
result = append(result, convertDBWallet(wallet)) result = append(result, domain.ConvertDBWallet(wallet))
} }
return result, nil return result, nil
} }
@ -133,7 +78,7 @@ func (s *Store) GetAllCustomerWallets(ctx context.Context) ([]domain.GetCustomer
var result []domain.GetCustomerWallet = make([]domain.GetCustomerWallet, 0, len(customerWallets)) var result []domain.GetCustomerWallet = make([]domain.GetCustomerWallet, 0, len(customerWallets))
for _, wallet := range customerWallets { for _, wallet := range customerWallets {
result = append(result, convertDBGetCustomerWallet(wallet)) result = append(result, domain.ConvertDBGetCustomerWallet(wallet))
} }
return result, nil return result, nil
} }
@ -144,7 +89,7 @@ func (s *Store) GetCustomerWallet(ctx context.Context, customerID int64) (domain
if err != nil { if err != nil {
return domain.GetCustomerWallet{}, err return domain.GetCustomerWallet{}, err
} }
return convertDBGetCustomerWallet(customerWallet), nil return domain.ConvertDBGetCustomerWallet(customerWallet), nil
} }
func (s *Store) GetAllBranchWallets(ctx context.Context) ([]domain.BranchWallet, error) { func (s *Store) GetAllBranchWallets(ctx context.Context) ([]domain.BranchWallet, error) {

View File

@ -11,18 +11,19 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"github.com/google/uuid" "github.com/google/uuid"
) )
type ArifpayService struct { type ArifpayService struct {
cfg *config.Config cfg *config.Config
transferStore wallet.TransferStore transferStore ports.TransferStore
walletSvc *wallet.Service walletSvc *wallet.Service
httpClient *http.Client httpClient *http.Client
} }
func NewArifpayService(cfg *config.Config, transferStore wallet.TransferStore, walletSvc *wallet.Service, httpClient *http.Client) *ArifpayService { func NewArifpayService(cfg *config.Config, transferStore ports.TransferStore, walletSvc *wallet.Service, httpClient *http.Client) *ArifpayService {
return &ArifpayService{ return &ArifpayService{
cfg: cfg, cfg: cfg,
transferStore: transferStore, transferStore: transferStore,

View File

@ -0,0 +1,17 @@
package authentication
// import (
// "context"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type UserStore interface {
// GetUserByEmailPhone(ctx context.Context, email, phone string, companyID domain.ValidInt64) (domain.User, error)
// }
// type TokenStore interface {
// CreateRefreshToken(ctx context.Context, rt domain.RefreshToken) error
// GetRefreshToken(ctx context.Context, token string) (domain.RefreshToken, error)
// GetRefreshTokenByUserID(ctx context.Context, id int64) (domain.RefreshToken, error)
// RevokeRefreshToken(ctx context.Context, token string) error
// }

View File

@ -1,5 +1,7 @@
package authentication package authentication
import "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
// type EmailPhone struct { // type EmailPhone struct {
// Email ValidString // Email ValidString
// PhoneNumber ValidString // PhoneNumber ValidString
@ -14,12 +16,12 @@ type Tokens struct {
RefreshToken string RefreshToken string
} }
type Service struct { type Service struct {
userStore UserStore userStore ports.UserStore
tokenStore TokenStore tokenStore ports.TokenStore
RefreshExpiry int RefreshExpiry int
} }
func NewService(userStore UserStore, tokenStore TokenStore, RefreshExpiry int) *Service { func NewService(userStore ports.UserStore, tokenStore ports.TokenStore, RefreshExpiry int) *Service {
return &Service{ return &Service{
userStore: userStore, userStore: userStore,
tokenStore: tokenStore, tokenStore: tokenStore,

View File

@ -0,0 +1,53 @@
package bet
// import (
// "context"
// "time"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type BetStore interface {
// CreateBet(ctx context.Context, bet domain.CreateBet) (domain.Bet, error)
// CreateBetOutcome(ctx context.Context, outcomes []domain.CreateBetOutcome) (int64, error)
// CreateFlag(ctx context.Context, flag domain.CreateFlagReq) (domain.Flag, error)
// GetBetByID(ctx context.Context, id int64) (domain.GetBet, error)
// GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, int64, error)
// GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error)
// GetBetByFastCode(ctx context.Context, fastcode string) (domain.GetBet, error)
// GetBetOutcomeViewByEventID(ctx context.Context, eventID int64, filter domain.BetOutcomeViewFilter) ([]domain.BetOutcomeViewRes, int64, error)
// GetBetOutcomeByEventID(ctx context.Context, eventID int64, is_filtered bool) ([]domain.BetOutcome, error)
// GetBetOutcomeByBetID(ctx context.Context, betID int64) ([]domain.BetOutcome, error)
// GetBetOutcomeCountByOddID(ctx context.Context, oddID int64) (int64, error)
// GetBetCountByUserID(ctx context.Context, userID int64, outcomesHash string) (int64, error)
// GetBetCountByOutcomesHash(ctx context.Context, outcomesHash string) (int64, error)
// UpdateCashOut(ctx context.Context, id int64, cashedOut bool) error
// UpdateStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error
// UpdateBetOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) (domain.BetOutcome, error)
// UpdateBetOutcomeStatusByBetID(ctx context.Context, id int64, status domain.OutcomeStatus) (domain.BetOutcome, error)
// UpdateBetOutcomeStatusForEvent(ctx context.Context, eventID int64, status domain.OutcomeStatus) ([]domain.BetOutcome, error)
// UpdateBetOutcomeStatusForOddId(ctx context.Context, oddID int64, status domain.OutcomeStatus) ([]domain.BetOutcome, error)
// BulkUpdateBetOutcomeStatusForOddIds(ctx context.Context, oddID []int64, status domain.OutcomeStatus) error
// GetBetSummary(ctx context.Context, filter domain.ReportFilter) (
// totalStakes domain.Currency,
// totalBets int64,
// activeBets int64,
// totalWins int64,
// totalLosses int64,
// winBalance domain.Currency,
// err error,
// )
// GetBetStats(ctx context.Context, filter domain.ReportFilter) ([]domain.BetStat, error)
// GetSportPopularity(ctx context.Context, filter domain.ReportFilter) (map[time.Time]string, error)
// GetMarketPopularity(ctx context.Context, filter domain.ReportFilter) (map[time.Time]string, error)
// GetExtremeValues(ctx context.Context, filter domain.ReportFilter) (map[time.Time]domain.ExtremeValues, error)
// GetCustomerBetActivity(ctx context.Context, filter domain.ReportFilter) ([]domain.CustomerBetActivity, error)
// GetCustomerPreferences(ctx context.Context, filter domain.ReportFilter) (map[int64]domain.CustomerPreferences, error)
// GetBranchBetActivity(ctx context.Context, filter domain.ReportFilter) ([]domain.BranchBetActivity, error)
// GetSportBetActivity(ctx context.Context, filter domain.ReportFilter) ([]domain.SportBetActivity, error)
// GetSportDetails(ctx context.Context, filter domain.ReportFilter) (map[string]string, error)
// GetSportMarketPopularity(ctx context.Context, filter domain.ReportFilter) (map[string]string, error)
// GetBetsForCashback(ctx context.Context) ([]domain.GetBet, error)
// UpdateBetWithCashback(ctx context.Context, betID int64, cashbackStatus bool) error
// }

View File

@ -19,6 +19,7 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers" "github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
@ -53,7 +54,7 @@ var (
) )
type Service struct { type Service struct {
betStore BetStore betStore ports.BetStore
eventSvc *event.Service eventSvc *event.Service
prematchSvc odds.ServiceImpl prematchSvc odds.ServiceImpl
walletSvc wallet.Service walletSvc wallet.Service
@ -67,7 +68,7 @@ type Service struct {
} }
func NewService( func NewService(
betStore BetStore, betStore ports.BetStore,
eventSvc *event.Service, eventSvc *event.Service,
prematchSvc odds.ServiceImpl, prematchSvc odds.ServiceImpl,
walletSvc wallet.Service, walletSvc wallet.Service,

View File

@ -0,0 +1,17 @@
package bonus
// import (
// "context"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type BonusStore interface {
// CreateUserBonus(ctx context.Context, bonus domain.CreateBonus) (domain.UserBonus, error)
// GetAllUserBonuses(ctx context.Context, filter domain.BonusFilter) ([]domain.UserBonus, error)
// GetBonusCount(ctx context.Context, filter domain.BonusFilter) (int64, error)
// GetBonusByID(ctx context.Context, bonusID int64) (domain.UserBonus, error)
// GetBonusStats(ctx context.Context, filter domain.BonusFilter) (domain.BonusStats, error)
// UpdateUserBonus(ctx context.Context, bonusID int64, IsClaimed bool) error
// DeleteUserBonus(ctx context.Context, bonusID int64) error
// }

View File

@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification" notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
@ -15,14 +16,20 @@ import (
) )
type Service struct { type Service struct {
bonusStore BonusStore bonusStore ports.BonusStore
walletSvc *wallet.Service walletSvc *wallet.Service
settingSvc *settings.Service settingSvc *settings.Service
notificationSvc *notificationservice.Service notificationSvc *notificationservice.Service
mongoLogger *zap.Logger mongoLogger *zap.Logger
} }
func NewService(bonusStore BonusStore, walletSvc *wallet.Service, settingSvc *settings.Service, notificationSvc *notificationservice.Service, mongoLogger *zap.Logger) *Service { func NewService(
bonusStore ports.BonusStore,
walletSvc *wallet.Service,
settingSvc *settings.Service,
notificationSvc *notificationservice.Service,
mongoLogger *zap.Logger,
) *Service {
return &Service{ return &Service{
bonusStore: bonusStore, bonusStore: bonusStore,
walletSvc: walletSvc, walletSvc: walletSvc,

View File

@ -0,0 +1,34 @@
package branch
// import (
// "context"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type BranchStore interface {
// CreateBranch(ctx context.Context, branch domain.CreateBranch) (domain.Branch, error)
// GetBranchByID(ctx context.Context, id int64) (domain.BranchDetail, error)
// GetBranchByManagerID(ctx context.Context, branchManagerID int64) ([]domain.BranchDetail, error)
// GetBranchByCompanyID(ctx context.Context, companyID int64) ([]domain.BranchDetail, error)
// GetAllBranches(ctx context.Context, filter domain.BranchFilter) ([]domain.BranchDetail, error)
// SearchBranchByName(ctx context.Context, name string, companyID domain.ValidInt64) ([]domain.BranchDetail, error)
// UpdateBranch(ctx context.Context, branch domain.UpdateBranch) (domain.Branch, error)
// DeleteBranch(ctx context.Context, id int64) error
// CreateBranchOperation(ctx context.Context, branchOperation domain.CreateBranchOperation) error
// CreateSupportedOperation(ctx context.Context, supportedOperation domain.CreateSupportedOperation) (domain.SupportedOperation, error)
// GetAllSupportedOperations(ctx context.Context) ([]domain.SupportedOperation, error)
// GetBranchOperations(ctx context.Context, branchID int64) ([]domain.BranchOperation, error)
// DeleteBranchOperation(ctx context.Context, branchID int64, operationID int64) error
// CreateBranchCashier(ctx context.Context, branchID int64, userID int64) error
// GetBranchByCashier(ctx context.Context, userID int64) (domain.Branch, error)
// DeleteBranchCashier(ctx context.Context, userID int64) error
// GetBranchCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
// GetBranchDetails(ctx context.Context, filter domain.ReportFilter) (map[int64]domain.BranchDetail, error)
// GetAllCompaniesBranch(ctx context.Context) ([]domain.Company, error)
// GetBranchesByCompany(ctx context.Context, companyID int64) ([]domain.Branch, error)
// GetAllBranchLocations(ctx context.Context, query domain.ValidString) ([]domain.BranchLocation, error)
// }

View File

@ -4,13 +4,14 @@ import (
"context" "context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
type Service struct { type Service struct {
branchStore BranchStore branchStore ports.BranchStore
} }
func NewService(branchStore BranchStore) *Service { func NewService(branchStore ports.BranchStore) *Service {
return &Service{ return &Service{
branchStore: branchStore, branchStore: branchStore,
} }
@ -78,4 +79,3 @@ func (s *Service) GetAllCompaniesBranch(ctx context.Context) ([]domain.Company,
func (s *Service) GetBranchesByCompany(ctx context.Context, companyID int64) ([]domain.Branch, error) { func (s *Service) GetBranchesByCompany(ctx context.Context, companyID int64) ([]domain.Branch, error) {
return s.branchStore.GetBranchesByCompany(ctx, companyID) return s.branchStore.GetBranchesByCompany(ctx, companyID)
} }

View File

@ -9,23 +9,24 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"github.com/google/uuid" "github.com/google/uuid"
) )
type Service struct { type Service struct {
transferStore wallet.TransferStore transferStore ports.TransferStore
walletStore wallet.Service walletStore wallet.Service
userStore user.UserStore userStore ports.UserStore
cfg *config.Config cfg *config.Config
chapaClient *Client chapaClient *Client
} }
func NewService( func NewService(
transferStore wallet.TransferStore, transferStore ports.TransferStore,
walletStore wallet.Service, walletStore wallet.Service,
userStore user.UserStore, userStore ports.UserStore,
cfg *config.Config, cfg *config.Config,
chapaClient *Client, chapaClient *Client,

View File

@ -0,0 +1,23 @@
package company
// import (
// "context"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type CompanyStore interface {
// CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error)
// GetAllCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.GetCompany, error)
// SearchCompanyByName(ctx context.Context, name string) ([]domain.GetCompany, error)
// GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany, error)
// GetCompanyBySlug(ctx context.Context, slug string) (domain.Company, error)
// UpdateCompany(ctx context.Context, company domain.UpdateCompany) error
// DeleteCompany(ctx context.Context, id int64) error
// GetCompanyCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
// UpdateCompanyStats(ctx context.Context) error
// GetCompanyStatByID(ctx context.Context, companyID int64) ([]domain.CompanyStat, error)
// GetCompanyStatsByInterval(ctx context.Context, filter domain.CompanyStatFilter) ([]domain.CompanyStat, error)
// }

View File

@ -4,13 +4,14 @@ import (
"context" "context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
type Service struct { type Service struct {
companyStore CompanyStore companyStore ports.CompanyStore
} }
func NewService(companyStore CompanyStore) *Service { func NewService(companyStore ports.CompanyStore) *Service {
return &Service{ return &Service{
companyStore: companyStore, companyStore: companyStore,
} }

View File

@ -0,0 +1,29 @@
package event
// import (
// "context"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type EventStore interface {
// FetchUpcomingEvents(ctx context.Context) error
// GetAllEvents(ctx context.Context, filter domain.EventFilter) ([]domain.BaseEvent, int64, error)
// GetEventByID(ctx context.Context, ID int64) (domain.BaseEvent, error)
// UpdateFinalScore(ctx context.Context, eventID int64, fullScore string, status domain.EventStatus) error
// UpdateEventStatus(ctx context.Context, eventID int64, status domain.EventStatus) error
// IsEventMonitored(ctx context.Context, eventID int64) (bool, error)
// UpdateEventMonitored(ctx context.Context, eventID int64, IsMonitored bool) error
// GetSportAndLeagueIDs(ctx context.Context, eventID int64) ([]int64, error)
// // Event Settings Views
// GetEventsWithSettings(ctx context.Context, companyID int64, filter domain.EventFilter) ([]domain.EventWithSettings, int64, error)
// GetEventWithSettingByID(ctx context.Context, ID int64, companyID int64) (domain.EventWithSettings, error)
// UpdateTenantEventSettings(ctx context.Context, event domain.UpdateTenantEventSettings) error
// UpdateGlobalEventSettings(ctx context.Context, event domain.UpdateGlobalEventSettings) error
// // Stats
// GetTotalEventStats(ctx context.Context, filter domain.EventStatsFilter) (domain.EventStats, error)
// GetTotalEventStatsByInterval(ctx context.Context, filter domain.EventStatsByIntervalFilter) ([]domain.EventStatsByInterval, error)
// UpdateEventBetStats(ctx context.Context) error
// }

View File

@ -14,7 +14,9 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/league"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
"go.uber.org/zap" "go.uber.org/zap"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" // "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
@ -22,16 +24,28 @@ import (
type Service struct { type Service struct {
token string token string
store *repository.Store eventStore ports.EventStore
eventHistoryStore ports.EventHistoryStore
leagueSvc league.Service
settingSvc *settings.Service settingSvc *settings.Service
mongoLogger *zap.Logger mongoLogger *zap.Logger
cfg *config.Config cfg *config.Config
} }
func New(token string, store *repository.Store, settingSvc *settings.Service, mongoLogger *zap.Logger, cfg *config.Config) *Service { func New(
token string,
eventStore ports.EventStore,
eventHistoryStore ports.EventHistoryStore,
leagueSvc league.Service,
settingSvc *settings.Service,
mongoLogger *zap.Logger,
cfg *config.Config,
) *Service {
return &Service{ return &Service{
token: token, token: token,
store: store, eventStore: eventStore,
eventHistoryStore: eventHistoryStore,
leagueSvc: leagueSvc,
settingSvc: settingSvc, settingSvc: settingSvc,
mongoLogger: mongoLogger, mongoLogger: mongoLogger,
cfg: cfg, cfg: cfg,
@ -93,7 +107,7 @@ func New(token string, store *repository.Store, settingSvc *settings.Service, mo
// } // }
// for _, event := range events { // for _, event := range events {
// if err := s.store.SaveEvent(ctx, event); err != nil { // if err := s.eventStore.SaveEvent(ctx, event); err != nil {
// fmt.Printf("Could not store live event [id=%s]: %v\n", event.ID, err) // fmt.Printf("Could not store live event [id=%s]: %v\n", event.ID, err)
// } // }
// } // }
@ -299,7 +313,7 @@ func (s *Service) fetchUpcomingEventsFromProvider(ctx context.Context, source_ur
// no this its fine to keep it here // no this its fine to keep it here
// but change the league id to bet365 id later // but change the league id to bet365 id later
//Automatically feature the league if its in the list //Automatically feature the league if its in the list
err = s.store.SaveLeague(ctx, domain.CreateLeague{ err = s.leagueSvc.SaveLeague(ctx, domain.CreateLeague{
ID: leagueID, ID: leagueID,
Name: ev.League.Name, Name: ev.League.Name,
DefaultIsActive: true, DefaultIsActive: true,
@ -313,7 +327,7 @@ func (s *Service) fetchUpcomingEventsFromProvider(ctx context.Context, source_ur
} }
// Since the system is multi-vendor now, no events are going to be skipped // Since the system is multi-vendor now, no events are going to be skipped
// if supported, err := s.store.CheckLeagueSupport(ctx, leagueID); !supported || err != nil { // if supported, err := s.eventStore.CheckLeagueSupport(ctx, leagueID); !supported || err != nil {
// dataLogger.Warn( // dataLogger.Warn(
// "Skipping league", // "Skipping league",
// zap.Bool("is_supported", supported), // zap.Bool("is_supported", supported),
@ -356,7 +370,7 @@ func (s *Service) fetchUpcomingEventsFromProvider(ctx context.Context, source_ur
dataLogger.Info("event history has been recorded") dataLogger.Info("event history has been recorded")
} }
err = s.store.SaveEvent(ctx, event) err = s.eventStore.SaveEvent(ctx, event)
if err != nil { if err != nil {
dataLogger.Error("failed to save upcoming event", zap.Error(err)) dataLogger.Error("failed to save upcoming event", zap.Error(err))
} }
@ -401,7 +415,7 @@ func (s *Service) CheckAndInsertEventHistory(ctx context.Context, newEvent domai
zap.Int32("sport_id", newEvent.SportID), zap.Int32("sport_id", newEvent.SportID),
) )
oldEvent, err := s.store.GetEventBySourceID(ctx, newEvent.SourceEventID, newEvent.Source) oldEvent, err := s.eventStore.GetEventBySourceID(ctx, newEvent.SourceEventID, newEvent.Source)
if err != nil { if err != nil {
return false, err return false, err
@ -412,7 +426,7 @@ func (s *Service) CheckAndInsertEventHistory(ctx context.Context, newEvent domai
} }
if oldEvent.Status != newEvent.Status { if oldEvent.Status != newEvent.Status {
_, err := s.store.InsertEventHistory(ctx, domain.CreateEventHistory{ _, err := s.eventHistoryStore.InsertEventHistory(ctx, domain.CreateEventHistory{
EventID: oldEvent.ID, EventID: oldEvent.ID,
Status: string(newEvent.Status), Status: string(newEvent.Status),
}) })
@ -462,27 +476,35 @@ func convertInt64(num string) int64 {
return 0 return 0
} }
func (s *Service) GetAllEvents(ctx context.Context, filter domain.EventFilter) ([]domain.BaseEvent, int64, error) { func (s *Service) GetAllEvents(ctx context.Context, filter domain.EventFilter) ([]domain.BaseEvent, int64, error) {
return s.store.GetAllEvents(ctx, filter) return s.eventStore.GetAllEvents(ctx, filter)
} }
func (s *Service) GetEventByID(ctx context.Context, ID int64) (domain.BaseEvent, error) { func (s *Service) GetEventByID(ctx context.Context, ID int64) (domain.BaseEvent, error) {
return s.store.GetEventByID(ctx, ID) return s.eventStore.GetEventByID(ctx, ID)
} }
func (s *Service) UpdateFinalScore(ctx context.Context, eventID int64, fullScore string, status domain.EventStatus) error { func (s *Service) UpdateFinalScore(ctx context.Context, eventID int64, fullScore string, status domain.EventStatus) error {
return s.store.UpdateFinalScore(ctx, eventID, fullScore, status) return s.eventStore.UpdateFinalScore(ctx, eventID, fullScore, status)
} }
func (s *Service) UpdateEventStatus(ctx context.Context, eventID int64, status domain.EventStatus) error { func (s *Service) UpdateEventStatus(ctx context.Context, eventID int64, status domain.EventStatus) error {
return s.store.UpdateEventStatus(ctx, eventID, status) return s.eventStore.UpdateEventStatus(ctx, eventID, status)
} }
func (s *Service) IsEventMonitored(ctx context.Context, eventID int64) (bool, error) { func (s *Service) IsEventMonitored(ctx context.Context, eventID int64) (bool, error) {
return s.store.IsEventMonitored(ctx, eventID) return s.eventStore.IsEventMonitored(ctx, eventID)
} }
func (s *Service) UpdateEventMonitored(ctx context.Context, eventID int64, IsMonitored bool) error { func (s *Service) UpdateEventMonitored(ctx context.Context, eventID int64, IsMonitored bool) error {
return s.store.UpdateEventMonitored(ctx, eventID, IsMonitored) return s.eventStore.UpdateEventMonitored(ctx, eventID, IsMonitored)
} }
func (s *Service) GetSportAndLeagueIDs(ctx context.Context, eventID int64) ([]int64, error) { func (s *Service) GetSportAndLeagueIDs(ctx context.Context, eventID int64) ([]int64, error) {
return s.store.GetSportAndLeagueIDs(ctx, eventID) return s.eventStore.GetSportAndLeagueIDs(ctx, eventID)
}
func (s *Service) DeleteEvent(ctx context.Context, eventID int64) error {
return s.eventStore.DeleteEvent(ctx, eventID)
}
func (s *Service) GetEventBySourceID(ctx context.Context, id string, source domain.EventSource) (domain.BaseEvent, error) {
return s.eventStore.GetEventBySourceID(ctx, id, source)
} }

View File

@ -7,16 +7,16 @@ import (
) )
func (s *Service) GetEventsWithSettings(ctx context.Context, companyID int64, filter domain.EventFilter) ([]domain.EventWithSettings, int64, error) { func (s *Service) GetEventsWithSettings(ctx context.Context, companyID int64, filter domain.EventFilter) ([]domain.EventWithSettings, int64, error) {
return s.store.GetEventsWithSettings(ctx, companyID, filter) return s.eventStore.GetEventsWithSettings(ctx, companyID, filter)
} }
func (s *Service) GetEventWithSettingByID(ctx context.Context, ID int64, companyID int64) (domain.EventWithSettings, error) { func (s *Service) GetEventWithSettingByID(ctx context.Context, ID int64, companyID int64) (domain.EventWithSettings, error) {
return s.store.GetEventWithSettingByID(ctx, ID, companyID) return s.eventStore.GetEventWithSettingByID(ctx, ID, companyID)
} }
func (s *Service) UpdateTenantEventSettings(ctx context.Context, event domain.UpdateTenantEventSettings) error { func (s *Service) UpdateTenantEventSettings(ctx context.Context, event domain.UpdateTenantEventSettings) error {
return s.store.UpdateTenantEventSettings(ctx, event) return s.eventStore.UpdateTenantEventSettings(ctx, event)
} }
func (s *Service) UpdateGlobalEventSettings(ctx context.Context, event domain.UpdateGlobalEventSettings) error { func (s *Service) UpdateGlobalEventSettings(ctx context.Context, event domain.UpdateGlobalEventSettings) error {
return s.store.UpdateGlobalEventSettings(ctx, event) return s.eventStore.UpdateGlobalEventSettings(ctx, event)
} }

View File

@ -0,0 +1,17 @@
package league
// import (
// "context"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type LeagueStore interface {
// SaveLeague(ctx context.Context, league domain.CreateLeague) error
// SaveLeagueSettings(ctx context.Context, leagueSettings domain.CreateLeagueSettings) error
// GetAllLeagues(ctx context.Context, filter domain.LeagueFilter) ([]domain.BaseLeague, int64, error)
// GetAllLeaguesByCompany(ctx context.Context, companyID int64, filter domain.LeagueFilter) ([]domain.LeagueWithSettings, int64, error)
// CheckLeagueSupport(ctx context.Context, leagueID int64, companyID int64) (bool, error)
// UpdateLeague(ctx context.Context, league domain.UpdateLeague) error
// UpdateGlobalLeagueSettings(ctx context.Context, league domain.UpdateGlobalLeagueSettings) error
// }

View File

@ -4,14 +4,15 @@ import (
"context" "context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
type Service struct { type Service struct {
store *repository.Store store ports.LeagueStore
} }
func New(store *repository.Store) *Service { func New(store ports.LeagueStore) *Service {
return &Service{ return &Service{
store: store, store: store,
} }

View File

@ -0,0 +1,23 @@
package notificationservice
// import (
// "context"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// "github.com/gorilla/websocket"
// )
// type NotificationStore interface {
// SendNotification(ctx context.Context, notification *domain.Notification) error
// MarkAsRead(ctx context.Context, notificationID string, recipientID int64) error
// GetUserNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, int64, error)
// ConnectWebSocket(ctx context.Context, recipientID int64, c *websocket.Conn) error
// DisconnectWebSocket(recipientID int64)
// SendSMS(ctx context.Context, recipientID int64, message string) error
// SendEmail(ctx context.Context, recipientID int64, subject, message string) error
// ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error) // New method
// CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error)
// GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error)
// GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error)
// }

View File

@ -11,9 +11,9 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers" "github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/messenger" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/messenger"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
// "github.com/segmentio/kafka-go" // "github.com/segmentio/kafka-go"
@ -27,9 +27,8 @@ import (
) )
type Service struct { type Service struct {
repo repository.NotificationRepository store ports.NotificationStore
Hub *ws.NotificationHub Hub *ws.NotificationHub
notificationStore NotificationStore
connections sync.Map connections sync.Map
notificationCh chan *domain.Notification notificationCh chan *domain.Notification
stopCh chan struct{} stopCh chan struct{}
@ -40,7 +39,8 @@ type Service struct {
logger *slog.Logger logger *slog.Logger
} }
func New(repo repository.NotificationRepository, func New(
store ports.NotificationStore,
mongoLogger *zap.Logger, mongoLogger *zap.Logger,
logger *slog.Logger, logger *slog.Logger,
cfg *config.Config, cfg *config.Config,
@ -50,7 +50,7 @@ func New(repo repository.NotificationRepository,
hub := ws.NewNotificationHub() hub := ws.NewNotificationHub()
svc := &Service{ svc := &Service{
repo: repo, store: store,
Hub: hub, Hub: hub,
mongoLogger: mongoLogger, mongoLogger: mongoLogger,
logger: logger, logger: logger,
@ -95,7 +95,7 @@ func (s *Service) SendNotification(ctx context.Context, notification *domain.Not
notification.Timestamp = time.Now() notification.Timestamp = time.Now()
notification.DeliveryStatus = domain.DeliveryStatusPending notification.DeliveryStatus = domain.DeliveryStatusPending
created, err := s.repo.CreateNotification(ctx, notification) created, err := s.store.CreateNotification(ctx, notification)
if err != nil { if err != nil {
s.mongoLogger.Error("[NotificationSvc.SendNotification] Failed to create notification", s.mongoLogger.Error("[NotificationSvc.SendNotification] Failed to create notification",
zap.String("id", notification.ID), zap.String("id", notification.ID),
@ -129,7 +129,7 @@ func (s *Service) SendNotification(ctx context.Context, notification *domain.Not
func (s *Service) MarkAsRead(ctx context.Context, notificationIDs []string, recipientID int64) error { func (s *Service) MarkAsRead(ctx context.Context, notificationIDs []string, recipientID int64) error {
for _, notificationID := range notificationIDs { for _, notificationID := range notificationIDs {
_, err := s.repo.UpdateNotificationStatus(ctx, notificationID, string(domain.DeliveryStatusSent), true, nil) _, err := s.store.UpdateNotificationStatus(ctx, notificationID, string(domain.DeliveryStatusSent), true, nil)
if err != nil { if err != nil {
s.mongoLogger.Error("[NotificationSvc.MarkAsRead] Failed to mark notification as read", s.mongoLogger.Error("[NotificationSvc.MarkAsRead] Failed to mark notification as read",
zap.String("notificationID", notificationID), zap.String("notificationID", notificationID),
@ -140,7 +140,7 @@ func (s *Service) MarkAsRead(ctx context.Context, notificationIDs []string, reci
return err return err
} }
// count, err := s.repo.CountUnreadNotifications(ctx, recipientID) // count, err := s.store.CountUnreadNotifications(ctx, recipientID)
// if err != nil { // if err != nil {
// s.logger.Error("[NotificationSvc.MarkAsRead] Failed to count unread notifications", "recipientID", recipientID, "error", err) // s.logger.Error("[NotificationSvc.MarkAsRead] Failed to count unread notifications", "recipientID", recipientID, "error", err)
// return err // return err
@ -165,7 +165,7 @@ func (s *Service) MarkAsRead(ctx context.Context, notificationIDs []string, reci
} }
func (s *Service) GetUserNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, int64, error) { func (s *Service) GetUserNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, int64, error) {
notifications, total, err := s.repo.GetUserNotifications(ctx, recipientID, limit, offset) notifications, total, err := s.store.GetUserNotifications(ctx, recipientID, limit, offset)
if err != nil { if err != nil {
s.mongoLogger.Error("[NotificationSvc.GetUserNotifications] Failed to list notifications", s.mongoLogger.Error("[NotificationSvc.GetUserNotifications] Failed to list notifications",
zap.Int64("recipientID", recipientID), zap.Int64("recipientID", recipientID),
@ -186,7 +186,7 @@ func (s *Service) GetUserNotifications(ctx context.Context, recipientID int64, l
} }
func (s *Service) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) { func (s *Service) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) {
notifications, err := s.repo.GetAllNotifications(ctx, limit, offset) notifications, err := s.store.GetAllNotifications(ctx, limit, offset)
if err != nil { if err != nil {
s.mongoLogger.Error("[NotificationSvc.ListNotifications] Failed to get all notifications", s.mongoLogger.Error("[NotificationSvc.ListNotifications] Failed to get all notifications",
zap.Int("limit", limit), zap.Int("limit", limit),
@ -282,7 +282,7 @@ func (s *Service) startWorker() {
} }
func (s *Service) ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error) { func (s *Service) ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error) {
return s.repo.ListRecipientIDs(ctx, receiver) return s.store.ListRecipientIDs(ctx, receiver)
} }
func (s *Service) handleNotification(notification *domain.Notification) { func (s *Service) handleNotification(notification *domain.Notification) {
@ -314,7 +314,7 @@ func (s *Service) handleNotification(notification *domain.Notification) {
} }
} }
if _, err := s.repo.UpdateNotificationStatus(ctx, notification.ID, string(notification.DeliveryStatus), notification.IsRead, notification.Metadata); err != nil { if _, err := s.store.UpdateNotificationStatus(ctx, notification.ID, string(notification.DeliveryStatus), notification.IsRead, notification.Metadata); err != nil {
s.mongoLogger.Error("[NotificationSvc.HandleNotification] Failed to update notification status", s.mongoLogger.Error("[NotificationSvc.HandleNotification] Failed to update notification status",
zap.String("id", notification.ID), zap.String("id", notification.ID),
zap.Error(err), zap.Error(err),
@ -404,7 +404,7 @@ func (s *Service) startRetryWorker() {
func (s *Service) retryFailedNotifications() { func (s *Service) retryFailedNotifications() {
ctx := context.Background() ctx := context.Background()
failedNotifications, err := s.repo.ListFailedNotifications(ctx, 100) failedNotifications, err := s.store.ListFailedNotifications(ctx, 100)
if err != nil { if err != nil {
s.mongoLogger.Error("[NotificationSvc.RetryFailedNotifications] Failed to list failed notifications", s.mongoLogger.Error("[NotificationSvc.RetryFailedNotifications] Failed to list failed notifications",
zap.Error(err), zap.Error(err),
@ -422,7 +422,7 @@ func (s *Service) retryFailedNotifications() {
case domain.DeliveryChannelSMS: case domain.DeliveryChannelSMS:
if err := s.SendNotificationSMS(ctx, notification.RecipientID, notification.Payload.Message); err == nil { if err := s.SendNotificationSMS(ctx, notification.RecipientID, notification.Payload.Message); err == nil {
notification.DeliveryStatus = domain.DeliveryStatusSent notification.DeliveryStatus = domain.DeliveryStatusSent
if _, err := s.repo.UpdateNotificationStatus(ctx, notification.ID, string(notification.DeliveryStatus), notification.IsRead, notification.Metadata); err != nil { if _, err := s.store.UpdateNotificationStatus(ctx, notification.ID, string(notification.DeliveryStatus), notification.IsRead, notification.Metadata); err != nil {
s.mongoLogger.Error("[NotificationSvc.RetryFailedNotifications] Failed to update after retry", s.mongoLogger.Error("[NotificationSvc.RetryFailedNotifications] Failed to update after retry",
zap.String("id", notification.ID), zap.String("id", notification.ID),
zap.Error(err), zap.Error(err),
@ -440,7 +440,7 @@ func (s *Service) retryFailedNotifications() {
case domain.DeliveryChannelEmail: case domain.DeliveryChannelEmail:
if err := s.SendNotificationEmail(ctx, notification.RecipientID, notification.Payload.Message, notification.Payload.Headline); err == nil { if err := s.SendNotificationEmail(ctx, notification.RecipientID, notification.Payload.Message, notification.Payload.Headline); err == nil {
notification.DeliveryStatus = domain.DeliveryStatusSent notification.DeliveryStatus = domain.DeliveryStatusSent
if _, err := s.repo.UpdateNotificationStatus(ctx, notification.ID, string(notification.DeliveryStatus), notification.IsRead, notification.Metadata); err != nil { if _, err := s.store.UpdateNotificationStatus(ctx, notification.ID, string(notification.DeliveryStatus), notification.IsRead, notification.Metadata); err != nil {
s.mongoLogger.Error("[NotificationSvc.RetryFailedNotifications] Failed to update after retry", s.mongoLogger.Error("[NotificationSvc.RetryFailedNotifications] Failed to update after retry",
zap.String("id", notification.ID), zap.String("id", notification.ID),
zap.Error(err), zap.Error(err),
@ -467,15 +467,15 @@ func (s *Service) retryFailedNotifications() {
} }
func (s *Service) CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error) { func (s *Service) CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error) {
return s.repo.CountUnreadNotifications(ctx, recipient_id) return s.store.CountUnreadNotifications(ctx, recipient_id)
} }
func (s *Service) DeleteOldNotifications(ctx context.Context) error { func (s *Service) DeleteOldNotifications(ctx context.Context) error {
return s.repo.DeleteOldNotifications(ctx) return s.store.DeleteOldNotifications(ctx)
} }
// func (s *Service) GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error){ // func (s *Service) GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error){
// return s.repo.Get(ctx, filter) // return s.store.Get(ctx, filter)
// } // }
// func (s *Service) RunRedisSubscriber(ctx context.Context) { // func (s *Service) RunRedisSubscriber(ctx context.Context) {

View File

@ -1,28 +0,0 @@
package odds
import (
"context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
func (s *ServiceImpl) InsertDisabledOdd(ctx context.Context, odd domain.CreateDisabledOdd) (domain.DisabledOdd, error) {
return s.store.InsertDisabledOdd(ctx, odd)
}
func (s *ServiceImpl) GetAllDisabledOdds(ctx context.Context) ([]domain.DisabledOdd, error) {
return s.store.GetAllDisabledOdds(ctx)
}
func (s *ServiceImpl) GetDisabledOddByRawOddID(ctx context.Context, rawOddID int64) (domain.DisabledOdd, error) {
return s.store.GetDisabledOddByRawOddID(ctx, rawOddID)
}
func (s *ServiceImpl) GetDisabledOddByID(ctx context.Context, id int64) (domain.DisabledOdd, error) {
return s.store.GetDisabledOddByID(ctx, id)
}
func (s *ServiceImpl) DeleteDisabledOddsByID(ctx context.Context, id int64) error {
return s.store.DeleteDisabledOddsByID(ctx, id)
}
func (s *ServiceImpl) DeleteDisabledOddsByRawOddID(ctx context.Context, id int64) error {
return s.store.DeleteDisabledOddsByRawOddID(ctx, id)
}

View File

@ -15,13 +15,14 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
"go.uber.org/zap" "go.uber.org/zap"
) )
type ServiceImpl struct { type ServiceImpl struct {
store *repository.Store store ports.OddStore
config *config.Config config *config.Config
eventSvc *event.Service eventSvc *event.Service
logger *slog.Logger logger *slog.Logger
@ -29,7 +30,7 @@ type ServiceImpl struct {
client *http.Client client *http.Client
} }
func New(store *repository.Store, cfg *config.Config, eventSvc *event.Service, logger *slog.Logger, mongoLogger *zap.Logger) *ServiceImpl { func New(store ports.OddStore, cfg *config.Config, eventSvc *event.Service, logger *slog.Logger, mongoLogger *zap.Logger) *ServiceImpl {
return &ServiceImpl{ return &ServiceImpl{
store: store, store: store,
config: cfg, config: cfg,

View File

@ -0,0 +1,27 @@
package raffle
// import (
// "context"
// dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type RaffleStore interface {
// CreateRaffle(ctx context.Context, raffle domain.CreateRaffle) (domain.Raffle, error)
// AddSportRaffleFilter(ctx context.Context, raffleID int32, sportID, leagueID int64) error
// DeleteRaffle(ctx context.Context, raffleID int32) (domain.Raffle, error)
// GetRafflesOfCompany(ctx context.Context, companyID int32) ([]dbgen.Raffle, error)
// GetRaffleStanding(ctx context.Context, raffleID, limit int32) ([]domain.RaffleStanding, error)
// CreateRaffleWinner(ctx context.Context, raffleWinnerParams domain.RaffleWinnerParams) error
// SetRaffleComplete(ctx context.Context, raffleID int32) error
// CheckValidSportRaffleFilter(ctx context.Context, raffleID int32, sportID, leagueID int64) (bool, error)
// CheckSportRaffleHasFilter(ctx context.Context, raffleID int32) (bool, error)
// CreateRaffleTicket(ctx context.Context, raffleTicketParams domain.CreateRaffleTicket) (domain.RaffleTicket, error)
// GetUserRaffleTickets(ctx context.Context, userID int32) ([]domain.RaffleTicketRes, error)
// SuspendRaffleTicket(ctx context.Context, raffleTicketID int32) error
// UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error
// GetRaffleTicketCount(ctx context.Context, raffleID, userID int32) (int64, error)
// GetRaffleTicketLimit(ctx context.Context, raffleID int32) (int32, error)
// }

View File

@ -5,13 +5,14 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
type Service struct { type Service struct {
raffleStore RaffleStore raffleStore ports.RaffleStore
} }
func NewService(raffleStore RaffleStore) *Service { func NewService(raffleStore ports.RaffleStore) *Service {
return &Service{ return &Service{
raffleStore: raffleStore, raffleStore: raffleStore,
} }

View File

@ -0,0 +1,17 @@
package referralservice
// import (
// "context"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type ReferralStore interface {
// GenerateReferralCode() (string, error)
// CreateReferral(ctx context.Context, userID int64, companyID int64) error
// ProcessReferral(ctx context.Context, referredPhone, referralCode string, companyID int64) error
// ProcessDepositBonus(ctx context.Context, userPhone string, amount float64) error
// ProcessBetReferral(ctx context.Context, userId int64, betAmount float64) error
// GetReferralStats(ctx context.Context, userID int64, companyID int64) (*domain.ReferralStats, error)
// GetReferralCountByID(ctx context.Context, referrerID int64) (int64, error)
// }

View File

@ -1,17 +0,0 @@
package referralservice
import (
"context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
type ReferralStore interface {
GenerateReferralCode() (string, error)
CreateReferral(ctx context.Context, userID int64, companyID int64) error
ProcessReferral(ctx context.Context, referredPhone, referralCode string, companyID int64) error
ProcessDepositBonus(ctx context.Context, userPhone string, amount float64) error
ProcessBetReferral(ctx context.Context, userId int64, betAmount float64) error
GetReferralStats(ctx context.Context, userID int64, companyID int64) (*domain.ReferralStats, error)
GetReferralCountByID(ctx context.Context, referrerID int64) (int64, error)
}

View File

@ -10,14 +10,15 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"go.uber.org/zap" "go.uber.org/zap"
) )
type Service struct { type Service struct {
repo repository.ReferralRepository repo ports.ReferralStore
walletSvc wallet.Service walletSvc wallet.Service
settingSvc settings.Service settingSvc settings.Service
config *config.Config config *config.Config
@ -25,7 +26,14 @@ type Service struct {
mongoLogger *zap.Logger mongoLogger *zap.Logger
} }
func New(repo repository.ReferralRepository, walletSvc wallet.Service, settingSvc settings.Service, cfg *config.Config, logger *slog.Logger, mongoLogger *zap.Logger) *Service { func New(
repo ports.ReferralStore,
walletSvc wallet.Service,
settingSvc settings.Service,
cfg *config.Config,
logger *slog.Logger,
mongoLogger *zap.Logger,
) *Service {
return &Service{ return &Service{
repo: repo, repo: repo,
walletSvc: walletSvc, walletSvc: walletSvc,

View File

@ -29,7 +29,7 @@ func (s *Service) GenerateEventIntervalReport(ctx context.Context, request domai
return "", ErrInvalidInterval return "", ErrInvalidInterval
} }
stats, err := s.eventSvc.GetTotalEventStatsByInterval(ctx, domain.EventStatsByIntervalFilter{ stats, err := s.statService.GetTotalEventStatsByInterval(ctx, domain.EventStatsByIntervalFilter{
Interval: domain.ValidDateInterval{ Interval: domain.ValidDateInterval{
Value: interval, Value: interval,
Valid: true, Valid: true,

View File

@ -6,19 +6,23 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
) )
type ReportStore interface { type ReportService interface {
registerGenerators()
GetDashboardSummary(ctx context.Context, filter domain.ReportFilter) (domain.DashboardSummary, error) GetDashboardSummary(ctx context.Context, filter domain.ReportFilter) (domain.DashboardSummary, error)
GetBetAnalysis(ctx context.Context, filter domain.ReportFilter) ([]domain.BetAnalysis, error) GetBetAnalysis(ctx context.Context, filter domain.ReportFilter) ([]domain.BetAnalysis, error)
GetCustomerActivity(ctx context.Context, filter domain.ReportFilter) ([]domain.CustomerActivity, error) GetCustomerActivity(ctx context.Context, filter domain.ReportFilter) ([]domain.CustomerActivity, error)
GetBranchPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.BranchPerformance, error) GetBranchPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.BranchPerformance, error)
GetSportPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.SportPerformance, error) GetSportPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.SportPerformance, error)
// GetNotificationReport(ctx context.Context, filter domain.ReportFilter) (domain.NotificationReport, error) // GenerateReport(ctx context.Context, from, to time.Time) error
// GetCashierPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.CashierPerformance, error) // fetchReportData(ctx context.Context, from, to time.Time)
// GetCompanyPerformance(ctx context.Context, filter domain.ReportFilter) ([]domain.CompanyPerformance, error)
CreateReportRequest(ctx context.Context, report domain.CreateReportRequest) (domain.ReportRequest, error) CreateReportRequest(ctx context.Context, report domain.CreateReportRequest) (domain.ReportRequest, error)
GetAllReportRequests(ctx context.Context, filter domain.ReportRequestFilter) ([]domain.ReportRequestDetail, int64, error) GetAllReportRequests(ctx context.Context, filter domain.ReportRequestFilter) ([]domain.ReportRequestDetail, int64, error)
GetReportRequestByRequestedByID(ctx context.Context, requestedBy int64, filter domain.ReportRequestFilter) ([]domain.ReportRequestDetail, error) GetReportRequestByRequestedByID(ctx context.Context, requestedBy int64, filter domain.ReportRequestFilter) ([]domain.ReportRequestDetail, error)
GetReportRequestByID(ctx context.Context, ID int64) (domain.ReportRequestDetail, error) GetReportRequestByID(ctx context.Context, ID int64) (domain.ReportRequestDetail, error)
UpdateReportRequest(ctx context.Context, report domain.UpdateRequestRequest) error UpdateReportRequest(ctx context.Context, report domain.UpdateRequestRequest) error
WriteCSV(rows [][]string, filePrefix string) (string, error)
CheckAndFetchReportFile(ctx context.Context, ID int64) (string, error)
ProcessReportRequests(ctx context.Context) error
processSingleReportRequest(ctx context.Context, req domain.ReportRequestDetail) error
GenerateEventIntervalReport(ctx context.Context, request domain.ReportRequestDetail) (string, error)
} }

View File

@ -52,25 +52,19 @@ func (s *Service) processSingleReportRequest(ctx context.Context, req domain.Rep
) )
}() }()
switch req.Type { gen, ok := s.generators[req.Type]
case domain.EventIntervalReportRequest: if !ok {
if req.Metadata.Interval == nil {
status = domain.RejectReportRequest status = domain.RejectReportRequest
rejectReason = "invalid interval provided" rejectReason = fmt.Sprintf("unsupported report type: %s", req.Type)
break s.mongoLogger.Warn("unsupported report type", zap.String("type", string(req.Type)))
} } else {
fp, err := gen(ctx, req)
fp, genErr := s.GenerateEventIntervalReport(ctx, req) if err != nil {
if genErr != nil {
status = domain.RejectReportRequest status = domain.RejectReportRequest
rejectReason = fmt.Sprintf("failed to generate report: %v", genErr) rejectReason = fmt.Sprintf("failed to generate report: %v", err)
} else { } else {
filePath = fp filePath = fp
} }
default:
status = domain.RejectReportRequest
rejectReason = fmt.Sprintf("unsupported report type: %s", req.Type)
} }
update := domain.UpdateRequestRequest{ update := domain.UpdateRequestRequest{
@ -90,6 +84,7 @@ func (s *Service) processSingleReportRequest(ctx context.Context, req domain.Rep
} }
if err := s.UpdateReportRequest(ctx, update); err != nil { if err := s.UpdateReportRequest(ctx, update); err != nil {
s.mongoLogger.Error("failed to update report request", zap.Int64("id", req.ID), zap.Error(err))
return fmt.Errorf("failed to update report request: %w", err) return fmt.Errorf("failed to update report request: %w", err)
} }

View File

@ -2,10 +2,10 @@ package report
import ( import (
"context" "context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
) )
func (s *Service) CreateReportRequest(ctx context.Context, report domain.CreateReportRequest) (domain.ReportRequest, error) { func (s *Service) CreateReportRequest(ctx context.Context, report domain.CreateReportRequest) (domain.ReportRequest, error) {
return s.store.CreateReportRequest(ctx, report) return s.store.CreateReportRequest(ctx, report)
} }

View File

@ -14,19 +14,14 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository" "github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/stats"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
"go.uber.org/zap" "go.uber.org/zap"
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification" notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
// virtualgameservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame" // virtualgameservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
) )
var ( var (
@ -35,43 +30,42 @@ var (
) )
type Service struct { type Service struct {
store *repository.Store store ports.ReportStore
betStore bet.BetStore betStore ports.BetStore
walletStore wallet.WalletStore walletStore ports.WalletStore
transactionStore transaction.TransactionStore transactionStore ports.TransactionStore
branchStore branch.BranchStore branchStore ports.BranchStore
userStore user.UserStore userStore ports.UserStore
repo repository.ReportRepository repo ports.OldReportRepository
companyStore company.CompanyStore companyStore ports.CompanyStore
notificationStore ports.NotificationStore
virtulaGamesStore repository.VirtualGameRepository virtulaGamesStore repository.VirtualGameRepository
notificationStore repository.NotificationRepository
notificationSvc *notificationservice.Service notificationSvc *notificationservice.Service
eventSvc *event.Service statService *stats.Service
companySvc *company.Service
logger *slog.Logger logger *slog.Logger
mongoLogger *zap.Logger mongoLogger *zap.Logger
cfg *config.Config cfg *config.Config
generators map[domain.ReportRequestType]ReportGeneratorFunc
} }
func NewService( func NewService(
store *repository.Store, store ports.ReportStore,
betStore bet.BetStore, betStore ports.BetStore,
walletStore wallet.WalletStore, walletStore ports.WalletStore,
transactionStore transaction.TransactionStore, transactionStore ports.TransactionStore,
branchStore branch.BranchStore, branchStore ports.BranchStore,
userStore user.UserStore, userStore ports.UserStore,
repo repository.ReportRepository, repo ports.OldReportRepository,
companyStore company.CompanyStore, companyStore ports.CompanyStore,
virtulaGamesStore repository.VirtualGameRepository, virtulaGamesStore repository.VirtualGameRepository,
notificationStore repository.NotificationRepository, notificationStore ports.NotificationStore,
notificationSvc *notificationservice.Service, notificationSvc *notificationservice.Service,
eventSvc *event.Service, statService *stats.Service,
companySvc *company.Service,
logger *slog.Logger, logger *slog.Logger,
mongoLogger *zap.Logger, mongoLogger *zap.Logger,
cfg *config.Config, cfg *config.Config,
) *Service { ) ReportService {
return &Service{ s := &Service{
store: store, store: store,
betStore: betStore, betStore: betStore,
walletStore: walletStore, walletStore: walletStore,
@ -83,12 +77,28 @@ func NewService(
virtulaGamesStore: virtulaGamesStore, virtulaGamesStore: virtulaGamesStore,
notificationStore: notificationStore, notificationStore: notificationStore,
notificationSvc: notificationSvc, notificationSvc: notificationSvc,
eventSvc: eventSvc, statService: statService,
companySvc: companySvc,
logger: logger, logger: logger,
mongoLogger: mongoLogger, mongoLogger: mongoLogger,
cfg: cfg, cfg: cfg,
} }
// Initialize the report generators
s.registerGenerators()
return s
}
// This registers all the report generators to make the processing cleaner and easier
// A report generator is a function (ReportGeneratorFunc) which takes a ReportRequestType and returns the path to file
type ReportGeneratorFunc func(ctx context.Context, req domain.ReportRequestDetail) (string, error)
func (s *Service) registerGenerators() {
s.generators = map[domain.ReportRequestType]ReportGeneratorFunc{
domain.EventIntervalReportRequest: s.GenerateEventIntervalReport,
// domain.CompanySummaryReportRequest: s.GenerateCompanySummaryReport,
// domain.BranchPerformanceReportRequest: s.GenerateBranchPerformanceReport,
}
} }
// GetDashboardSummary returns comprehensive dashboard metrics // GetDashboardSummary returns comprehensive dashboard metrics
@ -480,7 +490,7 @@ func (s *Service) GetSportPerformance(ctx context.Context, filter domain.ReportF
return performances, nil return performances, nil
} }
// func (s *Service) GenerateReport(ctx context.Context, from, to time.Time) error { // func (s *service) GenerateReport(ctx context.Context, from, to time.Time) error {
// // Hardcoded output directory // // Hardcoded output directory
// outputDir := "reports" // outputDir := "reports"
@ -630,7 +640,7 @@ func (s *Service) GetSportPerformance(ctx context.Context, filter domain.ReportF
// return nil // return nil
// } // }
// func (s *Service) fetchReportData(ctx context.Context, from, to time.Time) ( // func (s *service) fetchReportData(ctx context.Context, from, to time.Time) (
// []domain.CompanyReport, map[int64][]domain.BranchReport, error, // []domain.CompanyReport, map[int64][]domain.BranchReport, error,
// ) { // ) {
// // --- company level --- // // --- company level ---

View File

@ -0,0 +1,11 @@
package result
import (
"context"
)
type ResultService interface {
FetchAndProcessResults(ctx context.Context) error
FetchAndStoreResult(ctx context.Context, eventID string) error
}

View File

@ -13,7 +13,7 @@ import (
func (s *Service) CheckAndSendResultNotifications(ctx context.Context, createdAfter time.Time) error { func (s *Service) CheckAndSendResultNotifications(ctx context.Context, createdAfter time.Time) error {
resultLog, err := s.repo.GetAllResultLog(ctx, domain.ResultLogFilter{ resultLog, err := s.resultLogStore.GetAllResultLog(ctx, domain.ResultLogFilter{
CreatedAfter: domain.ValidTime{ CreatedAfter: domain.ValidTime{
Value: createdAfter, Value: createdAfter,
Valid: true, Valid: true,

View File

@ -13,7 +13,8 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/league" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/league"
@ -25,7 +26,7 @@ import (
) )
type Service struct { type Service struct {
repo *repository.Store resultLogStore ports.ResultLogStore
config *config.Config config *config.Config
logger *slog.Logger logger *slog.Logger
mongoLogger *zap.Logger mongoLogger *zap.Logger
@ -40,7 +41,7 @@ type Service struct {
} }
func NewService( func NewService(
repo *repository.Store, resultLogStore ports.ResultLogStore,
cfg *config.Config, cfg *config.Config,
logger *slog.Logger, logger *slog.Logger,
mongoLogger *zap.Logger, mongoLogger *zap.Logger,
@ -53,7 +54,7 @@ func NewService(
userSvc user.Service, userSvc user.Service,
) *Service { ) *Service {
return &Service{ return &Service{
repo: repo, resultLogStore: resultLogStore,
config: cfg, config: cfg,
logger: logger, logger: logger,
mongoLogger: mongoLogger, mongoLogger: mongoLogger,
@ -74,7 +75,7 @@ var (
func (s *Service) UpdateResultForOutcomes(ctx context.Context, eventID int64, resultRes json.RawMessage, sportID int64) error { func (s *Service) UpdateResultForOutcomes(ctx context.Context, eventID int64, resultRes json.RawMessage, sportID int64) error {
// TODO: Optimize this since there could be many outcomes with the same event_id and market_id that could be updated the same time // TODO: Optimize this since there could be many outcomes with the same event_id and market_id that could be updated the same time
outcomes, err := s.repo.GetBetOutcomeByEventID(ctx, eventID, true) outcomes, err := s.betSvc.GetBetOutcomeByEventID(ctx, eventID, true)
logger := s.mongoLogger.With( logger := s.mongoLogger.With(
zap.Int64("eventID", eventID), zap.Int64("eventID", eventID),
zap.Int64("sportID", sportID), zap.Int64("sportID", sportID),
@ -138,7 +139,7 @@ func (s *Service) UpdateResultForOutcomes(ctx context.Context, eventID int64, re
} }
func (s *Service) GetTotalBetsForEvents(ctx context.Context, eventID int64) (map[int64]int64, error) { func (s *Service) GetTotalBetsForEvents(ctx context.Context, eventID int64) (map[int64]int64, error) {
outcomes, err := s.repo.GetBetOutcomeByEventID(ctx, eventID, false) outcomes, err := s.betSvc.GetBetOutcomeByEventID(ctx, eventID, false)
if err != nil { if err != nil {
s.mongoLogger.Error( s.mongoLogger.Error(
@ -231,7 +232,7 @@ func (s *Service) RefundAllOutcomes(ctx context.Context, eventID int64) (map[int
func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error { func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error {
// TODO: Optimize this because there could be many bet outcomes for the same odd // TODO: Optimize this because there could be many bet outcomes for the same odd
// Take market id and match result as param and update all the bet outcomes at the same time // Take market id and match result as param and update all the bet outcomes at the same time
events, _, err := s.repo.GetAllEvents(ctx, domain.EventFilter{ events, _, err := s.eventSvc.GetAllEvents(ctx, domain.EventFilter{
LastStartTime: domain.ValidTime{ LastStartTime: domain.ValidTime{
Value: time.Now(), Value: time.Now(),
Valid: true, Valid: true,
@ -318,12 +319,12 @@ func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error {
commonRespLogger.Error("Failed to refund all outcomes", zap.Error(err)) commonRespLogger.Error("Failed to refund all outcomes", zap.Error(err))
continue continue
} }
err = s.repo.DeleteEvent(ctx, event.ID) err = s.eventSvc.DeleteEvent(ctx, event.ID)
if err != nil { if err != nil {
commonRespLogger.Error("Failed to remove event", zap.Error(err)) commonRespLogger.Error("Failed to remove event", zap.Error(err))
continue continue
} }
err = s.repo.DeleteOddsForEvent(ctx, event.ID) err = s.oddSvc.DeleteOddsForEvent(ctx, event.ID)
if err != nil { if err != nil {
commonRespLogger.Error("Failed to remove odds for event", zap.Error(err)) commonRespLogger.Error("Failed to remove odds for event", zap.Error(err))
continue continue
@ -370,12 +371,12 @@ func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error {
if err != nil { if err != nil {
commonRespLogger.Error("Error while updating result for event", zap.Error(err)) commonRespLogger.Error("Error while updating result for event", zap.Error(err))
} }
err = s.repo.DeleteEvent(ctx, event.ID) err = s.eventSvc.DeleteEvent(ctx, event.ID)
if err != nil { if err != nil {
commonRespLogger.Error("Failed to remove event", zap.Error(err)) commonRespLogger.Error("Failed to remove event", zap.Error(err))
continue continue
} }
err = s.repo.DeleteOddsForEvent(ctx, event.ID) err = s.oddSvc.DeleteOddsForEvent(ctx, event.ID)
if err != nil { if err != nil {
commonRespLogger.Error("Failed to remove odds for event", zap.Error(err)) commonRespLogger.Error("Failed to remove odds for event", zap.Error(err))
continue continue
@ -407,12 +408,12 @@ func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error {
commonRespLogger.Error("Failed to refund outcomes", zap.Error(err)) commonRespLogger.Error("Failed to refund outcomes", zap.Error(err))
} }
err = s.repo.DeleteEvent(ctx, event.ID) err = s.eventSvc.DeleteEvent(ctx, event.ID)
if err != nil { if err != nil {
commonRespLogger.Error("Failed to remove event", zap.Error(err)) commonRespLogger.Error("Failed to remove event", zap.Error(err))
continue continue
} }
err = s.repo.DeleteOddsForEvent(ctx, event.ID) err = s.oddSvc.DeleteOddsForEvent(ctx, event.ID)
if err != nil { if err != nil {
commonRespLogger.Error("Failed to remove odds for event", zap.Error(err)) commonRespLogger.Error("Failed to remove odds for event", zap.Error(err))
continue continue
@ -428,7 +429,7 @@ func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error {
} }
// This will be used to send daily notifications, since events will be removed // This will be used to send daily notifications, since events will be removed
_, err = s.repo.CreateResultLog(ctx, resultLog) _, err = s.resultLogStore.CreateResultLog(ctx, resultLog)
if err != nil { if err != nil {
s.mongoLogger.Warn( s.mongoLogger.Warn(
"Failed to store result log", "Failed to store result log",
@ -457,7 +458,7 @@ func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error {
} }
func (s *Service) CheckAndUpdateExpiredB365Events(ctx context.Context) (int64, error) { func (s *Service) CheckAndUpdateExpiredB365Events(ctx context.Context) (int64, error) {
events, _, err := s.repo.GetAllEvents(ctx, domain.EventFilter{ events, _, err := s.eventSvc.GetAllEvents(ctx, domain.EventFilter{
LastStartTime: domain.ValidTime{ LastStartTime: domain.ValidTime{
Value: time.Now(), Value: time.Now(),
Valid: true, Valid: true,

View File

@ -11,6 +11,7 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"github.com/google/uuid" "github.com/google/uuid"
) )
@ -22,11 +23,11 @@ import (
type SantimPayService struct { type SantimPayService struct {
client SantimPayClient client SantimPayClient
cfg *config.Config cfg *config.Config
transferStore wallet.TransferStore transferStore ports.TransferStore
walletSvc *wallet.Service walletSvc *wallet.Service
} }
func NewSantimPayService(client SantimPayClient, cfg *config.Config, transferStore wallet.TransferStore, walletSvc *wallet.Service) *SantimPayService { func NewSantimPayService(client SantimPayClient, cfg *config.Config, transferStore ports.TransferStore, walletSvc *wallet.Service) *SantimPayService {
return &SantimPayService{ return &SantimPayService{
client: client, client: client,
cfg: cfg, cfg: cfg,

View File

@ -0,0 +1,24 @@
package settings
// import (
// "context"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
// )
// type SettingStore interface {
// GetGlobalSettingList(ctx context.Context) (domain.SettingList, error)
// GetGlobalSettings(ctx context.Context) ([]domain.Setting, error)
// GetGlobalSetting(ctx context.Context, key string) (domain.Setting, error)
// UpdateGlobalSetting(ctx context.Context, key, value string) error
// UpdateGlobalSettingList(ctx context.Context, settingList domain.ValidSettingList) error
// InsertCompanySetting(ctx context.Context, key, value string, companyID int64) error
// InsertCompanySettingList(ctx context.Context, settingList domain.ValidSettingList, companyID int64) error
// GetAllCompanySettings(ctx context.Context) ([]domain.CompanySetting, error)
// GetCompanySettingsByKey(ctx context.Context, key string) ([]domain.CompanySetting, error)
// GetOverrideSettings(ctx context.Context, companyID int64) ([]domain.Setting, error)
// GetOverrideSettingsList(ctx context.Context, companyID int64) (domain.SettingList, error)
// DeleteCompanySetting(ctx context.Context, companyID int64, key string) error
// DeleteAllCompanySetting(ctx context.Context, companyID int64) error
// }

View File

@ -4,13 +4,14 @@ import (
"context" "context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
) )
type Service struct { type Service struct {
settingStore SettingStore settingStore ports.SettingStore
} }
func NewService(settingStore SettingStore) *Service { func NewService(settingStore ports.SettingStore) *Service {
return &Service{ return &Service{
settingStore: settingStore, settingStore: settingStore,
} }

View File

@ -1,19 +1,16 @@
package company package stats
import ( import (
"context" "context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
) )
func (s *Service) UpdateCompanyStats(ctx context.Context) error { func (s *Service) UpdateCompanyStats(ctx context.Context) error {
return s.companyStore.UpdateCompanyStats(ctx); return s.UpdateCompanyStats(ctx)
} }
func (s *Service) GetCompanyStatByID(ctx context.Context, companyID int64) ([]domain.CompanyStat, error) { func (s *Service) GetCompanyStatByID(ctx context.Context, companyID int64) ([]domain.CompanyStat, error) {
return s.companyStore.GetCompanyStatByID(ctx, companyID); return s.GetCompanyStatByID(ctx, companyID)
} }
func (s *Service) GetCompanyStatsByInterval(ctx context.Context, filter domain.CompanyStatFilter) ([]domain.CompanyStat, error) { func (s *Service) GetCompanyStatsByInterval(ctx context.Context, filter domain.CompanyStatFilter) ([]domain.CompanyStat, error) {
return s.companyStore.GetCompanyStatsByInterval(ctx, filter) return s.GetCompanyStatsByInterval(ctx, filter)
} }

View File

@ -1,4 +1,4 @@
package event package stats
import ( import (
"context" "context"
@ -7,13 +7,12 @@ import (
) )
func (s *Service) GetTotalEventStats(ctx context.Context, filter domain.EventStatsFilter) (domain.EventStats, error) { func (s *Service) GetTotalEventStats(ctx context.Context, filter domain.EventStatsFilter) (domain.EventStats, error) {
return s.store.GetTotalEventStats(ctx, filter) return s.eventStatStore.GetTotalEventStats(ctx, filter)
} }
func (s *Service) GetTotalEventStatsByInterval(ctx context.Context, filter domain.EventStatsByIntervalFilter) ([]domain.EventStatsByInterval, error) { func (s *Service) GetTotalEventStatsByInterval(ctx context.Context, filter domain.EventStatsByIntervalFilter) ([]domain.EventStatsByInterval, error) {
return s.store.GetTotalEventStatsByInterval(ctx, filter) return s.eventStatStore.GetTotalEventStatsByInterval(ctx, filter)
} }
func (s *Service) UpdateEventBetStats(ctx context.Context) error { func (s *Service) UpdateEventBetStats(ctx context.Context) error {
return s.store.UpdateEventBetStats(ctx) return s.eventStatStore.UpdateEventBetStats(ctx)
} }

View File

@ -0,0 +1,15 @@
package stats
import "github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
type Service struct {
companyStatStore ports.CompanyStatStore
eventStatStore ports.EventStatStore
}
func NewService(companyStatStore ports.CompanyStatStore, eventStatStore ports.EventStatStore) *Service {
return &Service{
companyStatStore: companyStatStore,
eventStatStore: eventStatStore,
}
}

View File

@ -23,6 +23,7 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
) )
@ -31,11 +32,11 @@ import (
type TelebirrService struct { type TelebirrService struct {
// client TelebirrClient // client TelebirrClient
cfg *config.Config cfg *config.Config
transferStore wallet.TransferStore transferStore ports.TransferStore
walletSvc *wallet.Service walletSvc *wallet.Service
} }
func NewTelebirrService(cfg *config.Config, transferStore wallet.TransferStore, walletSvc *wallet.Service) *TelebirrService { func NewTelebirrService(cfg *config.Config, transferStore ports.TransferStore, walletSvc *wallet.Service) *TelebirrService {
return &TelebirrService{ return &TelebirrService{
cfg: cfg, cfg: cfg,
transferStore: transferStore, transferStore: transferStore,

View File

@ -0,0 +1,2 @@
package ticket

Some files were not shown because too many files have changed in this diff Show More