314 lines
10 KiB
Go
314 lines
10 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
func convertDBShopTransaction(transaction dbgen.ShopTransaction) domain.ShopTransaction {
|
|
return domain.ShopTransaction{
|
|
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) {
|
|
|
|
newTransaction, err := s.queries.CreateShopTransaction(ctx, convertCreateShopTransaction(transaction))
|
|
if err != nil {
|
|
return domain.ShopTransaction{}, err
|
|
}
|
|
return convertDBShopTransaction(newTransaction), err
|
|
}
|
|
|
|
func (s *Store) GetShopTransactionByID(ctx context.Context, id int64) (domain.ShopTransactionDetail, error) {
|
|
transaction, err := s.queries.GetShopTransactionByID(ctx, id)
|
|
if err != nil {
|
|
return domain.ShopTransactionDetail{}, err
|
|
}
|
|
|
|
return convertDBShopTransactionDetail(transaction), nil
|
|
}
|
|
|
|
func (s *Store) GetAllShopTransactions(ctx context.Context, filter domain.ShopTransactionFilter) ([]domain.ShopTransactionDetail, error) {
|
|
transaction, err := s.queries.GetAllShopTransactions(ctx, dbgen.GetAllShopTransactionsParams{
|
|
BranchID: pgtype.Int8{
|
|
Int64: filter.BranchID.Value,
|
|
Valid: filter.BranchID.Valid,
|
|
},
|
|
CompanyID: pgtype.Int8{
|
|
Int64: filter.CompanyID.Value,
|
|
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 {
|
|
return nil, err
|
|
}
|
|
|
|
var result []domain.ShopTransactionDetail = make([]domain.ShopTransactionDetail, 0, len(transaction))
|
|
for _, tAction := range transaction {
|
|
result = append(result, convertDBShopTransactionDetail(tAction))
|
|
}
|
|
return result, nil
|
|
}
|
|
func (s *Store) GetShopTransactionByBranch(ctx context.Context, id int64) ([]domain.ShopTransactionDetail, error) {
|
|
transaction, err := s.queries.GetShopTransactionByBranch(ctx, id)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var result []domain.ShopTransactionDetail = make([]domain.ShopTransactionDetail, 0, len(transaction))
|
|
for _, ticket := range transaction {
|
|
result = append(result, convertDBShopTransactionDetail(ticket))
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (s *Store) UpdateShopTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64, approverName string) error {
|
|
err := s.queries.UpdateShopTransactionVerified(ctx, dbgen.UpdateShopTransactionVerifiedParams{
|
|
ID: id,
|
|
ApprovedBy: pgtype.Int8{
|
|
Int64: approvedBy,
|
|
Valid: true,
|
|
},
|
|
Verified: verified,
|
|
})
|
|
return err
|
|
}
|
|
|
|
|
|
// GetTransactionTotals returns total deposits and withdrawals
|
|
func (s *Store) GetTransactionTotals(ctx context.Context, filter domain.ReportFilter) (deposits, withdrawals domain.Currency, err error) {
|
|
query := `SELECT
|
|
COALESCE(SUM(CASE WHEN type = 1 THEN amount ELSE 0 END), 0) as deposits,
|
|
COALESCE(SUM(CASE WHEN type = 0 THEN amount ELSE 0 END), 0) as withdrawals
|
|
FROM shop_transactions`
|
|
|
|
args := []interface{}{}
|
|
argPos := 1
|
|
|
|
if filter.CompanyID.Valid {
|
|
query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
|
args = append(args, filter.CompanyID.Value)
|
|
argPos++
|
|
} else if filter.BranchID.Valid {
|
|
query += fmt.Sprintf(" WHERE branch_id = $%d", argPos)
|
|
args = append(args, filter.BranchID.Value)
|
|
argPos++
|
|
} else if filter.UserID.Valid {
|
|
query += fmt.Sprintf(" WHERE user_id = $%d", argPos)
|
|
args = append(args, filter.UserID.Value)
|
|
argPos++
|
|
}
|
|
|
|
if filter.StartTime.Valid {
|
|
query += fmt.Sprintf(" AND %screated_at >= $%d", func() string {
|
|
if len(args) == 0 {
|
|
return ""
|
|
}
|
|
return " "
|
|
}(), argPos)
|
|
args = append(args, filter.StartTime.Value)
|
|
argPos++
|
|
}
|
|
if filter.EndTime.Valid {
|
|
query += fmt.Sprintf(" AND created_at <= $%d", argPos)
|
|
args = append(args, filter.EndTime.Value)
|
|
argPos++
|
|
}
|
|
|
|
row := s.conn.QueryRow(ctx, query, args...)
|
|
err = row.Scan(&deposits, &withdrawals)
|
|
if err != nil {
|
|
return 0, 0, fmt.Errorf("failed to get transaction totals: %w", err)
|
|
}
|
|
return deposits, withdrawals, nil
|
|
}
|
|
|
|
// GetBranchTransactionTotals returns transaction totals by branch
|
|
func (s *Store) GetBranchTransactionTotals(ctx context.Context, filter domain.ReportFilter) (map[int64]domain.BranchTransactions, error) {
|
|
query := `SELECT
|
|
branch_id,
|
|
COALESCE(SUM(CASE WHEN type = 1 THEN amount ELSE 0 END), 0) as deposits,
|
|
COALESCE(SUM(CASE WHEN type = 0 THEN amount ELSE 0 END), 0) as withdrawals
|
|
FROM shop_transactions`
|
|
|
|
args := []interface{}{}
|
|
argPos := 1
|
|
|
|
if filter.CompanyID.Valid {
|
|
query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
|
args = append(args, filter.CompanyID.Value)
|
|
argPos++
|
|
}
|
|
if filter.StartTime.Valid {
|
|
query += fmt.Sprintf(" AND %screated_at >= $%d", func() string {
|
|
if len(args) == 0 {
|
|
return " WHERE "
|
|
}
|
|
return " AND "
|
|
}(), argPos)
|
|
args = append(args, filter.StartTime.Value)
|
|
argPos++
|
|
}
|
|
if filter.EndTime.Valid {
|
|
query += fmt.Sprintf(" AND created_at <= $%d", argPos)
|
|
args = append(args, filter.EndTime.Value)
|
|
argPos++
|
|
}
|
|
|
|
query += " GROUP BY branch_id"
|
|
|
|
rows, err := s.conn.Query(ctx, query, args...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to query branch transaction totals: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
totals := make(map[int64]domain.BranchTransactions)
|
|
for rows.Next() {
|
|
var branchID int64
|
|
var transactions domain.BranchTransactions
|
|
if err := rows.Scan(&branchID, &transactions.Deposits, &transactions.Withdrawals); err != nil {
|
|
return nil, fmt.Errorf("failed to scan branch transaction totals: %w", err)
|
|
}
|
|
totals[branchID] = transactions
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("rows error: %w", err)
|
|
}
|
|
return totals, nil
|
|
}
|