fixed company-id, admin-id optional parameters for creating company and branch

This commit is contained in:
Samuel Tariku 2025-04-30 18:43:46 +03:00
parent f25f6a3f85
commit ae571d51a6
34 changed files with 480 additions and 145 deletions

View File

@ -1,5 +1,7 @@
{ {
"cSpell.words": [ "cSpell.words": [
"Cashout" "Cashout",
"narg",
"sqlc"
] ]
} }

View File

@ -99,18 +99,6 @@ CREATE TABLE IF NOT EXISTS ticket_outcomes (
status INT NOT NULL DEFAULT 0, status INT NOT NULL DEFAULT 0,
expires TIMESTAMP NOT NULL expires TIMESTAMP NOT NULL
); );
CREATE VIEW bet_with_outcomes AS
SELECT bets.*,
JSON_AGG(bet_outcomes.*) AS outcomes
FROM bets
LEFT JOIN bet_outcomes ON bets.id = bet_outcomes.bet_id
GROUP BY bets.id;
CREATE VIEW ticket_with_outcomes AS
SELECT tickets.*,
JSON_AGG(ticket_outcomes.*) AS outcomes
FROM tickets
LEFT JOIN ticket_outcomes ON tickets.id = ticket_outcomes.ticket_id
GROUP BY tickets.id;
CREATE TABLE IF NOT EXISTS wallets ( CREATE TABLE IF NOT EXISTS wallets (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
balance BIGINT NOT NULL DEFAULT 0, balance BIGINT NOT NULL DEFAULT 0,
@ -148,7 +136,9 @@ CREATE TABLE IF NOT EXISTS transactions (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
amount BIGINT NOT NULL, amount BIGINT NOT NULL,
branch_id BIGINT NOT NULL, branch_id BIGINT NOT NULL,
company_id BIGINT NOT NULL,
cashier_id BIGINT NOT NULL, cashier_id BIGINT NOT NULL,
cashier_name VARCHAR(255) NOT NULL,
bet_id BIGINT NOT NULL, bet_id BIGINT NOT NULL,
number_of_outcomes BIGINT NOT NULL, number_of_outcomes BIGINT NOT NULL,
type BIGINT NOT NULL, type BIGINT NOT NULL,
@ -162,6 +152,9 @@ CREATE TABLE IF NOT EXISTS transactions (
reference_number VARCHAR(255) NOT NULL, reference_number VARCHAR(255) NOT NULL,
verified BOOLEAN NOT NULL DEFAULT false, verified BOOLEAN NOT NULL DEFAULT false,
approved_by BIGINT, approved_by BIGINT,
approver_name VARCHAR(255),
branch_location VARCHAR(255) NOT NULL,
branch_name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
); );
@ -176,17 +169,6 @@ CREATE TABLE IF NOT EXISTS branches (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
); );
CREATE VIEW branch_details AS
SELECT branches.*,
CONCAT(users.first_name, ' ', users.last_name) AS manager_name,
users.phone_number AS manager_phone_number
FROM branches
LEFT JOIN users ON branches.branch_manager_id = users.id;
CREATE TABLE IF NOT EXISTS supported_operations (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description VARCHAR(255) NOT NULL
);
CREATE TABLE IF NOT EXISTS branch_operations ( CREATE TABLE IF NOT EXISTS branch_operations (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
operation_id BIGINT NOT NULL, operation_id BIGINT NOT NULL,
@ -250,12 +232,37 @@ CREATE TABLE companies (
admin_id BIGINT NOT NULL, admin_id BIGINT NOT NULL,
wallet_id BIGINT NOT NULL wallet_id BIGINT NOT NULL
); );
-- Views
CREATE VIEW companies_with_wallets AS CREATE VIEW companies_with_wallets AS
SELECT companies.*, SELECT companies.*,
wallets.balance, wallets.balance,
wallets.is_active wallets.is_active
FROM companies FROM companies
JOIN wallets ON wallets.id = companies.wallet_id; JOIN wallets ON wallets.id = companies.wallet_id;
CREATE VIEW branch_details AS
SELECT branches.*,
CONCAT(users.first_name, ' ', users.last_name) AS manager_name,
users.phone_number AS manager_phone_number
FROM branches
LEFT JOIN users ON branches.branch_manager_id = users.id;
CREATE TABLE IF NOT EXISTS supported_operations (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description VARCHAR(255) NOT NULL
);
CREATE VIEW bet_with_outcomes AS
SELECT bets.*,
JSON_AGG(bet_outcomes.*) AS outcomes
FROM bets
LEFT JOIN bet_outcomes ON bets.id = bet_outcomes.bet_id
GROUP BY bets.id;
CREATE VIEW ticket_with_outcomes AS
SELECT tickets.*,
JSON_AGG(ticket_outcomes.*) AS outcomes
FROM tickets
LEFT JOIN ticket_outcomes ON tickets.id = ticket_outcomes.ticket_id
GROUP BY tickets.id;
-- Foreign Keys
ALTER TABLE refresh_tokens ALTER TABLE refresh_tokens
ADD CONSTRAINT fk_refresh_tokens_users FOREIGN KEY (user_id) REFERENCES users(id); ADD CONSTRAINT fk_refresh_tokens_users FOREIGN KEY (user_id) REFERENCES users(id);
ALTER TABLE bets ALTER TABLE bets
@ -279,8 +286,8 @@ ALTER TABLE branches
ADD CONSTRAINT fk_branches_wallet FOREIGN KEY (wallet_id) REFERENCES wallets(id), ADD CONSTRAINT fk_branches_wallet FOREIGN KEY (wallet_id) REFERENCES wallets(id),
ADD CONSTRAINT fk_branches_manager FOREIGN KEY (branch_manager_id) REFERENCES users(id); ADD CONSTRAINT fk_branches_manager FOREIGN KEY (branch_manager_id) REFERENCES users(id);
ALTER TABLE branch_operations ALTER TABLE branch_operations
ADD CONSTRAINT fk_branch_operations_operations FOREIGN KEY (operation_id) REFERENCES supported_operations(id), ADD CONSTRAINT fk_branch_operations_operations FOREIGN KEY (operation_id) REFERENCES supported_operations(id) ON DELETE CASCADE,
ADD CONSTRAINT fk_branch_operations_branches FOREIGN KEY (branch_id) REFERENCES branches(id); ADD CONSTRAINT fk_branch_operations_branches FOREIGN KEY (branch_id) REFERENCES branches(id) ON DELETE CASCADE;
ALTER TABLE branch_cashiers ALTER TABLE branch_cashiers
ADD CONSTRAINT fk_branch_cashiers_users FOREIGN KEY (user_id) REFERENCES users(id), ADD CONSTRAINT fk_branch_cashiers_users FOREIGN KEY (user_id) REFERENCES users(id),
ADD CONSTRAINT fk_branch_cashiers_branches FOREIGN KEY (branch_id) REFERENCES branches(id); ADD CONSTRAINT fk_branch_cashiers_branches FOREIGN KEY (branch_id) REFERENCES branches(id);

View File

@ -24,7 +24,6 @@ RETURNING *;
-- name: GetAllBranches :many -- name: GetAllBranches :many
SELECT * SELECT *
FROM branch_details; FROM branch_details;
-- name: GetBranchByID :one -- name: GetBranchByID :one
SELECT * SELECT *
FROM branch_details FROM branch_details
@ -67,12 +66,12 @@ FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = users.id; JOIN users ON branch_cashiers.user_id = users.id;
-- name: UpdateBranch :one -- name: UpdateBranch :one
UPDATE branches UPDATE branches
SET name = $1, SET name = COALESCE(sqlc.narg(name), name),
location = $2, location = COALESCE(sqlc.narg(location), location),
branch_manager_id = $3, branch_manager_id = COALESCE(sqlc.narg(branch_manager_id), branch_manager_id),
company_id = $4, company_id = COALESCE(sqlc.narg(company_id), company_id),
is_self_owned = $5 is_self_owned = COALESCE(sqlc.narg(is_self_owned), is_self_owned)
WHERE id = $6 WHERE id = $1
RETURNING *; RETURNING *;
-- name: DeleteBranch :exec -- name: DeleteBranch :exec
DELETE FROM branches DELETE FROM branches

View File

@ -19,9 +19,9 @@ FROM companies_with_wallets
WHERE name ILIKE '%' || $1 || '%'; WHERE name ILIKE '%' || $1 || '%';
-- name: UpdateCompany :one -- name: UpdateCompany :one
UPDATE companies UPDATE companies
SET name = $1, SET name = COALESCE(sqlc.narg(name), name),
admin_id = $2 admin_id = COALESCE(sqlc.narg(admin_id), admin_id)
WHERE id = $3 WHERE id = $1
RETURNING *; RETURNING *;
-- name: DeleteCompany :exec -- name: DeleteCompany :exec
DELETE FROM companies DELETE FROM companies

View File

@ -13,7 +13,11 @@ INSERT INTO transactions (
account_name, account_name,
account_number, account_number,
reference_number, reference_number,
number_of_outcomes number_of_outcomes,
branch_name,
branch_location,
company_id,
cashier_name
) )
VALUES ( VALUES (
$1, $1,
@ -29,7 +33,11 @@ VALUES (
$11, $11,
$12, $12,
$13, $13,
$14 $14,
$15,
$16,
$17,
$18
) )
RETURNING *; RETURNING *;
-- name: GetAllTransactions :many -- name: GetAllTransactions :many
@ -47,5 +55,6 @@ WHERE branch_id = $1;
UPDATE transactions UPDATE transactions
SET verified = $2, SET verified = $2,
approved_by = $3, approved_by = $3,
approver_name = $4,
updated_at = CURRENT_TIMESTAMP updated_at = CURRENT_TIMESTAMP
WHERE id = $1; WHERE id = $1;

View File

@ -1,14 +1,29 @@
-- name: CreateTransfer :one -- name: CreateTransfer :one
INSERT INTO wallet_transfer (amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *; INSERT INTO wallet_transfer (
amount,
type,
receiver_wallet_id,
sender_wallet_id,
cashier_id,
verified,
payment_method
)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING *;
-- name: GetAllTransfers :many -- name: GetAllTransfers :many
SELECT * FROM wallet_transfer; SELECT *
FROM wallet_transfer;
-- name: GetTransfersByWallet :many -- name: GetTransfersByWallet :many
SELECT * FROM wallet_transfer WHERE receiver_wallet_id = $1 OR sender_wallet_id = $1; SELECT *
FROM wallet_transfer
WHERE receiver_wallet_id = $1
OR sender_wallet_id = $1;
-- name: GetTransferByID :one -- name: GetTransferByID :one
SELECT * FROM wallet_transfer WHERE id = $1; SELECT *
FROM wallet_transfer
WHERE id = $1;
-- name: UpdateTransferVerification :exec -- name: UpdateTransferVerification :exec
UPDATE wallet_transfer SET verified = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2; UPDATE wallet_transfer
SET verified = $1,
updated_at = CURRENT_TIMESTAMP
WHERE id = $2;

View File

@ -105,6 +105,11 @@ SET first_name = $1,
role = $5, role = $5,
updated_at = $6 updated_at = $6
WHERE id = $7; WHERE id = $7;
-- name: UpdateUserCompany :exec
UPDATE users
SET company_id = $1
WHERE id = $2;
-- name: SuspendUser :exec -- name: SuspendUser :exec
UPDATE users UPDATE users
SET suspended = $1, SET suspended = $1,

View File

@ -514,32 +514,32 @@ func (q *Queries) SearchBranchByName(ctx context.Context, dollar_1 pgtype.Text)
const UpdateBranch = `-- name: UpdateBranch :one const UpdateBranch = `-- name: UpdateBranch :one
UPDATE branches UPDATE branches
SET name = $1, SET name = COALESCE($2, name),
location = $2, location = COALESCE($3, location),
branch_manager_id = $3, branch_manager_id = COALESCE($4, branch_manager_id),
company_id = $4, company_id = COALESCE($5, company_id),
is_self_owned = $5 is_self_owned = COALESCE($6, is_self_owned)
WHERE id = $6 WHERE id = $1
RETURNING id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at RETURNING id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at
` `
type UpdateBranchParams struct { type UpdateBranchParams struct {
Name string `json:"name"` ID int64 `json:"id"`
Location string `json:"location"` Name pgtype.Text `json:"name"`
BranchManagerID int64 `json:"branch_manager_id"` Location pgtype.Text `json:"location"`
CompanyID int64 `json:"company_id"` BranchManagerID pgtype.Int8 `json:"branch_manager_id"`
IsSelfOwned bool `json:"is_self_owned"` CompanyID pgtype.Int8 `json:"company_id"`
ID int64 `json:"id"` IsSelfOwned pgtype.Bool `json:"is_self_owned"`
} }
func (q *Queries) UpdateBranch(ctx context.Context, arg UpdateBranchParams) (Branch, error) { func (q *Queries) UpdateBranch(ctx context.Context, arg UpdateBranchParams) (Branch, error) {
row := q.db.QueryRow(ctx, UpdateBranch, row := q.db.QueryRow(ctx, UpdateBranch,
arg.ID,
arg.Name, arg.Name,
arg.Location, arg.Location,
arg.BranchManagerID, arg.BranchManagerID,
arg.CompanyID, arg.CompanyID,
arg.IsSelfOwned, arg.IsSelfOwned,
arg.ID,
) )
var i Branch var i Branch
err := row.Scan( err := row.Scan(

View File

@ -136,20 +136,20 @@ func (q *Queries) SearchCompanyByName(ctx context.Context, dollar_1 pgtype.Text)
const UpdateCompany = `-- name: UpdateCompany :one const UpdateCompany = `-- name: UpdateCompany :one
UPDATE companies UPDATE companies
SET name = $1, SET name = COALESCE($2, name),
admin_id = $2 admin_id = COALESCE($3, admin_id)
WHERE id = $3 WHERE id = $1
RETURNING id, name, admin_id, wallet_id RETURNING id, name, admin_id, wallet_id
` `
type UpdateCompanyParams struct { type UpdateCompanyParams struct {
Name string `json:"name"` ID int64 `json:"id"`
AdminID int64 `json:"admin_id"` Name pgtype.Text `json:"name"`
ID int64 `json:"id"` AdminID pgtype.Int8 `json:"admin_id"`
} }
func (q *Queries) UpdateCompany(ctx context.Context, arg UpdateCompanyParams) (Company, error) { func (q *Queries) UpdateCompany(ctx context.Context, arg UpdateCompanyParams) (Company, error) {
row := q.db.QueryRow(ctx, UpdateCompany, arg.Name, arg.AdminID, arg.ID) row := q.db.QueryRow(ctx, UpdateCompany, arg.ID, arg.Name, arg.AdminID)
var i Company var i Company
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,

View File

@ -337,7 +337,9 @@ type Transaction struct {
ID int64 `json:"id"` ID int64 `json:"id"`
Amount int64 `json:"amount"` Amount int64 `json:"amount"`
BranchID int64 `json:"branch_id"` BranchID int64 `json:"branch_id"`
CompanyID int64 `json:"company_id"`
CashierID int64 `json:"cashier_id"` CashierID int64 `json:"cashier_id"`
CashierName string `json:"cashier_name"`
BetID int64 `json:"bet_id"` BetID int64 `json:"bet_id"`
NumberOfOutcomes int64 `json:"number_of_outcomes"` NumberOfOutcomes int64 `json:"number_of_outcomes"`
Type int64 `json:"type"` Type int64 `json:"type"`
@ -351,6 +353,9 @@ type Transaction struct {
ReferenceNumber string `json:"reference_number"` ReferenceNumber string `json:"reference_number"`
Verified bool `json:"verified"` Verified bool `json:"verified"`
ApprovedBy pgtype.Int8 `json:"approved_by"` ApprovedBy pgtype.Int8 `json:"approved_by"`
ApproverName pgtype.Text `json:"approver_name"`
BranchLocation string `json:"branch_location"`
BranchName string `json:"branch_name"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }

View File

@ -26,7 +26,11 @@ INSERT INTO transactions (
account_name, account_name,
account_number, account_number,
reference_number, reference_number,
number_of_outcomes number_of_outcomes,
branch_name,
branch_location,
company_id,
cashier_name
) )
VALUES ( VALUES (
$1, $1,
@ -42,9 +46,13 @@ VALUES (
$11, $11,
$12, $12,
$13, $13,
$14 $14,
$15,
$16,
$17,
$18
) )
RETURNING id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, created_at, updated_at RETURNING id, amount, branch_id, company_id, cashier_id, cashier_name, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, approver_name, branch_location, branch_name, created_at, updated_at
` `
type CreateTransactionParams struct { type CreateTransactionParams struct {
@ -62,6 +70,10 @@ type CreateTransactionParams struct {
AccountNumber string `json:"account_number"` AccountNumber string `json:"account_number"`
ReferenceNumber string `json:"reference_number"` ReferenceNumber string `json:"reference_number"`
NumberOfOutcomes int64 `json:"number_of_outcomes"` NumberOfOutcomes int64 `json:"number_of_outcomes"`
BranchName string `json:"branch_name"`
BranchLocation string `json:"branch_location"`
CompanyID int64 `json:"company_id"`
CashierName string `json:"cashier_name"`
} }
func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionParams) (Transaction, error) { func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionParams) (Transaction, error) {
@ -80,13 +92,19 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
arg.AccountNumber, arg.AccountNumber,
arg.ReferenceNumber, arg.ReferenceNumber,
arg.NumberOfOutcomes, arg.NumberOfOutcomes,
arg.BranchName,
arg.BranchLocation,
arg.CompanyID,
arg.CashierName,
) )
var i Transaction var i Transaction
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.Amount, &i.Amount,
&i.BranchID, &i.BranchID,
&i.CompanyID,
&i.CashierID, &i.CashierID,
&i.CashierName,
&i.BetID, &i.BetID,
&i.NumberOfOutcomes, &i.NumberOfOutcomes,
&i.Type, &i.Type,
@ -100,6 +118,9 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
&i.ReferenceNumber, &i.ReferenceNumber,
&i.Verified, &i.Verified,
&i.ApprovedBy, &i.ApprovedBy,
&i.ApproverName,
&i.BranchLocation,
&i.BranchName,
&i.CreatedAt, &i.CreatedAt,
&i.UpdatedAt, &i.UpdatedAt,
) )
@ -107,7 +128,7 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
} }
const GetAllTransactions = `-- name: GetAllTransactions :many const GetAllTransactions = `-- name: GetAllTransactions :many
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, created_at, updated_at SELECT id, amount, branch_id, company_id, cashier_id, cashier_name, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, approver_name, branch_location, branch_name, created_at, updated_at
FROM transactions FROM transactions
` `
@ -124,7 +145,9 @@ func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error)
&i.ID, &i.ID,
&i.Amount, &i.Amount,
&i.BranchID, &i.BranchID,
&i.CompanyID,
&i.CashierID, &i.CashierID,
&i.CashierName,
&i.BetID, &i.BetID,
&i.NumberOfOutcomes, &i.NumberOfOutcomes,
&i.Type, &i.Type,
@ -138,6 +161,9 @@ func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error)
&i.ReferenceNumber, &i.ReferenceNumber,
&i.Verified, &i.Verified,
&i.ApprovedBy, &i.ApprovedBy,
&i.ApproverName,
&i.BranchLocation,
&i.BranchName,
&i.CreatedAt, &i.CreatedAt,
&i.UpdatedAt, &i.UpdatedAt,
); err != nil { ); err != nil {
@ -152,7 +178,7 @@ func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error)
} }
const GetTransactionByBranch = `-- name: GetTransactionByBranch :many const GetTransactionByBranch = `-- name: GetTransactionByBranch :many
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, created_at, updated_at SELECT id, amount, branch_id, company_id, cashier_id, cashier_name, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, approver_name, branch_location, branch_name, created_at, updated_at
FROM transactions FROM transactions
WHERE branch_id = $1 WHERE branch_id = $1
` `
@ -170,7 +196,9 @@ func (q *Queries) GetTransactionByBranch(ctx context.Context, branchID int64) ([
&i.ID, &i.ID,
&i.Amount, &i.Amount,
&i.BranchID, &i.BranchID,
&i.CompanyID,
&i.CashierID, &i.CashierID,
&i.CashierName,
&i.BetID, &i.BetID,
&i.NumberOfOutcomes, &i.NumberOfOutcomes,
&i.Type, &i.Type,
@ -184,6 +212,9 @@ func (q *Queries) GetTransactionByBranch(ctx context.Context, branchID int64) ([
&i.ReferenceNumber, &i.ReferenceNumber,
&i.Verified, &i.Verified,
&i.ApprovedBy, &i.ApprovedBy,
&i.ApproverName,
&i.BranchLocation,
&i.BranchName,
&i.CreatedAt, &i.CreatedAt,
&i.UpdatedAt, &i.UpdatedAt,
); err != nil { ); err != nil {
@ -198,7 +229,7 @@ func (q *Queries) GetTransactionByBranch(ctx context.Context, branchID int64) ([
} }
const GetTransactionByID = `-- name: GetTransactionByID :one const GetTransactionByID = `-- name: GetTransactionByID :one
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, created_at, updated_at SELECT id, amount, branch_id, company_id, cashier_id, cashier_name, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, approver_name, branch_location, branch_name, created_at, updated_at
FROM transactions FROM transactions
WHERE id = $1 WHERE id = $1
` `
@ -210,7 +241,9 @@ func (q *Queries) GetTransactionByID(ctx context.Context, id int64) (Transaction
&i.ID, &i.ID,
&i.Amount, &i.Amount,
&i.BranchID, &i.BranchID,
&i.CompanyID,
&i.CashierID, &i.CashierID,
&i.CashierName,
&i.BetID, &i.BetID,
&i.NumberOfOutcomes, &i.NumberOfOutcomes,
&i.Type, &i.Type,
@ -224,6 +257,9 @@ func (q *Queries) GetTransactionByID(ctx context.Context, id int64) (Transaction
&i.ReferenceNumber, &i.ReferenceNumber,
&i.Verified, &i.Verified,
&i.ApprovedBy, &i.ApprovedBy,
&i.ApproverName,
&i.BranchLocation,
&i.BranchName,
&i.CreatedAt, &i.CreatedAt,
&i.UpdatedAt, &i.UpdatedAt,
) )
@ -234,17 +270,24 @@ const UpdateTransactionVerified = `-- name: UpdateTransactionVerified :exec
UPDATE transactions UPDATE transactions
SET verified = $2, SET verified = $2,
approved_by = $3, approved_by = $3,
approver_name = $4,
updated_at = CURRENT_TIMESTAMP updated_at = CURRENT_TIMESTAMP
WHERE id = $1 WHERE id = $1
` `
type UpdateTransactionVerifiedParams struct { type UpdateTransactionVerifiedParams struct {
ID int64 `json:"id"` ID int64 `json:"id"`
Verified bool `json:"verified"` Verified bool `json:"verified"`
ApprovedBy pgtype.Int8 `json:"approved_by"` ApprovedBy pgtype.Int8 `json:"approved_by"`
ApproverName pgtype.Text `json:"approver_name"`
} }
func (q *Queries) UpdateTransactionVerified(ctx context.Context, arg UpdateTransactionVerifiedParams) error { func (q *Queries) UpdateTransactionVerified(ctx context.Context, arg UpdateTransactionVerifiedParams) error {
_, err := q.db.Exec(ctx, UpdateTransactionVerified, arg.ID, arg.Verified, arg.ApprovedBy) _, err := q.db.Exec(ctx, UpdateTransactionVerified,
arg.ID,
arg.Verified,
arg.ApprovedBy,
arg.ApproverName,
)
return err return err
} }

View File

@ -12,7 +12,17 @@ import (
) )
const CreateTransfer = `-- name: CreateTransfer :one const CreateTransfer = `-- name: CreateTransfer :one
INSERT INTO wallet_transfer (amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id, amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method, created_at, updated_at INSERT INTO wallet_transfer (
amount,
type,
receiver_wallet_id,
sender_wallet_id,
cashier_id,
verified,
payment_method
)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method, created_at, updated_at
` `
type CreateTransferParams struct { type CreateTransferParams struct {
@ -52,7 +62,8 @@ func (q *Queries) CreateTransfer(ctx context.Context, arg CreateTransferParams)
} }
const GetAllTransfers = `-- name: GetAllTransfers :many const GetAllTransfers = `-- name: GetAllTransfers :many
SELECT id, amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method, created_at, updated_at FROM wallet_transfer SELECT id, amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method, created_at, updated_at
FROM wallet_transfer
` `
func (q *Queries) GetAllTransfers(ctx context.Context) ([]WalletTransfer, error) { func (q *Queries) GetAllTransfers(ctx context.Context) ([]WalletTransfer, error) {
@ -87,7 +98,9 @@ func (q *Queries) GetAllTransfers(ctx context.Context) ([]WalletTransfer, error)
} }
const GetTransferByID = `-- name: GetTransferByID :one const GetTransferByID = `-- name: GetTransferByID :one
SELECT id, amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method, created_at, updated_at FROM wallet_transfer WHERE id = $1 SELECT id, amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method, created_at, updated_at
FROM wallet_transfer
WHERE id = $1
` `
func (q *Queries) GetTransferByID(ctx context.Context, id int64) (WalletTransfer, error) { func (q *Queries) GetTransferByID(ctx context.Context, id int64) (WalletTransfer, error) {
@ -109,7 +122,10 @@ func (q *Queries) GetTransferByID(ctx context.Context, id int64) (WalletTransfer
} }
const GetTransfersByWallet = `-- name: GetTransfersByWallet :many const GetTransfersByWallet = `-- name: GetTransfersByWallet :many
SELECT id, amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method, created_at, updated_at FROM wallet_transfer WHERE receiver_wallet_id = $1 OR sender_wallet_id = $1 SELECT id, amount, type, receiver_wallet_id, sender_wallet_id, cashier_id, verified, payment_method, created_at, updated_at
FROM wallet_transfer
WHERE receiver_wallet_id = $1
OR sender_wallet_id = $1
` `
func (q *Queries) GetTransfersByWallet(ctx context.Context, receiverWalletID int64) ([]WalletTransfer, error) { func (q *Queries) GetTransfersByWallet(ctx context.Context, receiverWalletID int64) ([]WalletTransfer, error) {
@ -144,7 +160,10 @@ func (q *Queries) GetTransfersByWallet(ctx context.Context, receiverWalletID int
} }
const UpdateTransferVerification = `-- name: UpdateTransferVerification :exec const UpdateTransferVerification = `-- name: UpdateTransferVerification :exec
UPDATE wallet_transfer SET verified = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2 UPDATE wallet_transfer
SET verified = $1,
updated_at = CURRENT_TIMESTAMP
WHERE id = $2
` `
type UpdateTransferVerificationParams struct { type UpdateTransferVerificationParams struct {

View File

@ -561,3 +561,19 @@ func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) error {
) )
return err return err
} }
const UpdateUserCompany = `-- name: UpdateUserCompany :exec
UPDATE users
SET company_id = $1
WHERE id = $2
`
type UpdateUserCompanyParams struct {
CompanyID pgtype.Int8 `json:"company_id"`
ID int64 `json:"id"`
}
func (q *Queries) UpdateUserCompany(ctx context.Context, arg UpdateUserCompanyParams) error {
_, err := q.db.Exec(ctx, UpdateUserCompany, arg.CompanyID, arg.ID)
return err
}

View File

@ -44,11 +44,12 @@ type CreateBranch struct {
} }
type UpdateBranch struct { type UpdateBranch struct {
Name string ID int64
Location string Name *string
BranchManagerID int64 Location *string
CompanyID int64 BranchManagerID *int64
IsSelfOwned bool CompanyID *int64
IsSelfOwned *bool
} }
type CreateSupportedOperation struct { type CreateSupportedOperation struct {

View File

@ -26,6 +26,7 @@ type CreateCompany struct {
} }
type UpdateCompany struct { type UpdateCompany struct {
Name string ID int64
AdminID int64 Name *string
AdminID *int64
} }

View File

@ -24,7 +24,11 @@ type Transaction struct {
ID int64 ID int64
Amount Currency Amount Currency
BranchID int64 BranchID int64
BranchName string
BranchLocation string
CompanyID int64
CashierID int64 CashierID int64
CashierName string
BetID int64 BetID int64
NumberOfOutcomes int64 NumberOfOutcomes int64
Type TransactionType Type TransactionType
@ -39,10 +43,10 @@ type Transaction struct {
ReferenceNumber string ReferenceNumber string
Verified bool Verified bool
ApprovedBy ValidInt64 ApprovedBy ValidInt64
ApproverName ValidString
UpdatedAt time.Time UpdatedAt time.Time
CreatedAt time.Time CreatedAt time.Time
} }
type CreateTransaction struct { type CreateTransaction struct {
Amount Currency Amount Currency
BranchID int64 BranchID int64
@ -59,4 +63,8 @@ type CreateTransaction struct {
AccountName string AccountName string
AccountNumber string AccountNumber string
ReferenceNumber string ReferenceNumber string
BranchName string
BranchLocation string
CompanyID int64
CashierName string
} }

View File

@ -45,6 +45,46 @@ func convertDBBranch(dbBranch dbgen.Branch) domain.Branch {
} }
} }
func convertUpdateBranch(updateBranch domain.UpdateBranch) dbgen.UpdateBranchParams {
var newUpdateBranch dbgen.UpdateBranchParams
newUpdateBranch.ID = updateBranch.ID
if updateBranch.Name != nil {
newUpdateBranch.Name = pgtype.Text{
String: *updateBranch.Name,
Valid: true,
}
}
if updateBranch.Location != nil {
newUpdateBranch.Location = pgtype.Text{
String: *updateBranch.Location,
Valid: true,
}
}
if updateBranch.BranchManagerID != nil {
newUpdateBranch.BranchManagerID = pgtype.Int8{
Int64: *updateBranch.BranchManagerID,
Valid: true,
}
}
if updateBranch.CompanyID != nil {
newUpdateBranch.CompanyID = pgtype.Int8{
Int64: *updateBranch.CompanyID,
Valid: true,
}
}
if updateBranch.IsSelfOwned != nil {
newUpdateBranch.IsSelfOwned = pgtype.Bool{
Bool: *updateBranch.IsSelfOwned,
Valid: true,
}
}
return newUpdateBranch
}
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, convertCreateBranch(branch)) dbBranch, err := s.queries.CreateBranch(ctx, convertCreateBranch(branch))
@ -111,14 +151,9 @@ func (s *Store) SearchBranchByName(ctx context.Context, name string) ([]domain.B
return branches, nil return branches, nil
} }
func (s *Store) UpdateBranch(ctx context.Context, id int64, branch domain.UpdateBranch) (domain.Branch, error) { func (s *Store) UpdateBranch(ctx context.Context, branch domain.UpdateBranch) (domain.Branch, error) {
dbBranch, err := s.queries.UpdateBranch(ctx, dbgen.UpdateBranchParams{
ID: id, dbBranch, err := s.queries.UpdateBranch(ctx, convertUpdateBranch(branch))
Name: branch.Name,
Location: branch.Location,
BranchManagerID: branch.BranchManagerID,
IsSelfOwned: branch.IsSelfOwned,
})
if err != nil { if err != nil {
return domain.Branch{}, err return domain.Branch{}, err
} }
@ -209,7 +244,6 @@ func (s *Store) GetBranchByCashier(ctx context.Context, userID int64) (domain.Br
return convertDBBranch(branch), err return convertDBBranch(branch), err
} }
func (s *Store) DeleteBranchOperation(ctx context.Context, branchID int64, operationID int64) error { func (s *Store) DeleteBranchOperation(ctx context.Context, branchID int64, operationID int64) error {
err := s.queries.DeleteBranchOperation(ctx, dbgen.DeleteBranchOperationParams{ err := s.queries.DeleteBranchOperation(ctx, dbgen.DeleteBranchOperationParams{
BranchID: branchID, BranchID: branchID,

View File

@ -36,6 +36,28 @@ func convertDBCompanyWithWallet(dbCompany dbgen.CompaniesWithWallet) domain.GetC
} }
} }
func convertUpdateCompany(updateCompany domain.UpdateCompany) dbgen.UpdateCompanyParams {
var newUpdateCompany dbgen.UpdateCompanyParams
newUpdateCompany.ID = updateCompany.ID
if updateCompany.Name != nil {
newUpdateCompany.Name = pgtype.Text{
String: *updateCompany.Name,
Valid: true,
}
}
if updateCompany.AdminID != nil {
newUpdateCompany.AdminID = pgtype.Int8{
Int64: *updateCompany.AdminID,
Valid: true,
}
}
return newUpdateCompany
}
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, convertCreateCompany(company)) dbCompany, err := s.queries.CreateCompany(ctx, convertCreateCompany(company))
if err != nil { if err != nil {
@ -84,12 +106,8 @@ func (s *Store) GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany
return convertDBCompanyWithWallet(dbCompany), nil return convertDBCompanyWithWallet(dbCompany), nil
} }
func (s *Store) UpdateCompany(ctx context.Context, id int64, company domain.UpdateCompany) (domain.Company, error) { func (s *Store) UpdateCompany(ctx context.Context, company domain.UpdateCompany) (domain.Company, error) {
dbCompany, err := s.queries.UpdateCompany(ctx, dbgen.UpdateCompanyParams{ dbCompany, err := s.queries.UpdateCompany(ctx, convertUpdateCompany(company))
ID: id,
Name: company.Name,
AdminID: company.AdminID,
})
if err != nil { if err != nil {
return domain.Company{}, err return domain.Company{}, err

View File

@ -29,9 +29,17 @@ func convertDBTransaction(transaction dbgen.Transaction) domain.Transaction {
Value: transaction.ApprovedBy.Int64, Value: transaction.ApprovedBy.Int64,
Valid: transaction.ApprovedBy.Valid, Valid: transaction.ApprovedBy.Valid,
}, },
CreatedAt: transaction.CreatedAt.Time, CreatedAt: transaction.CreatedAt.Time,
UpdatedAt: transaction.UpdatedAt.Time, UpdatedAt: transaction.UpdatedAt.Time,
Verified: transaction.Verified, Verified: transaction.Verified,
BranchName: transaction.BranchName,
BranchLocation: transaction.BranchLocation,
CashierName: transaction.CashierName,
CompanyID: transaction.CompanyID,
ApproverName: domain.ValidString{
Value: transaction.ApproverName.String,
Valid: transaction.ApprovedBy.Valid,
},
} }
} }
@ -51,6 +59,10 @@ func convertCreateTransaction(transaction domain.CreateTransaction) dbgen.Create
AccountNumber: transaction.AccountNumber, AccountNumber: transaction.AccountNumber,
ReferenceNumber: transaction.ReferenceNumber, ReferenceNumber: transaction.ReferenceNumber,
NumberOfOutcomes: transaction.NumberOfOutcomes, NumberOfOutcomes: transaction.NumberOfOutcomes,
BranchName: transaction.BranchName,
BranchLocation: transaction.BranchLocation,
CashierName: transaction.CashierName,
CompanyID: transaction.CompanyID,
} }
} }
@ -99,7 +111,7 @@ func (s *Store) GetTransactionByBranch(ctx context.Context, id int64) ([]domain.
return result, nil return result, nil
} }
func (s *Store) UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64) error { func (s *Store) UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64, approverName string) error {
err := s.queries.UpdateTransactionVerified(ctx, dbgen.UpdateTransactionVerifiedParams{ err := s.queries.UpdateTransactionVerified(ctx, dbgen.UpdateTransactionVerifiedParams{
ID: id, ID: id,
ApprovedBy: pgtype.Int8{ ApprovedBy: pgtype.Int8{
@ -107,6 +119,10 @@ func (s *Store) UpdateTransactionVerified(ctx context.Context, id int64, verifie
Valid: true, Valid: true,
}, },
Verified: verified, Verified: verified,
ApproverName: pgtype.Text{
String: approverName,
Valid: true,
},
}) })
return err return err
} }

View File

@ -216,6 +216,20 @@ func (s *Store) UpdateUser(ctx context.Context, user domain.UpdateUserReq) error
} }
return nil return nil
} }
func (s *Store) UpdateUserCompany(ctx context.Context, id int64, companyID int64) error {
err := s.queries.UpdateUserCompany(ctx, dbgen.UpdateUserCompanyParams{
CompanyID: pgtype.Int8{
Int64: companyID,
Valid: true,
},
ID: id,
})
if err != nil {
return err
}
return nil
}
func (s *Store) DeleteUser(ctx context.Context, id int64) error { func (s *Store) DeleteUser(ctx context.Context, id int64) error {
err := s.queries.DeleteUser(ctx, id) err := s.queries.DeleteUser(ctx, id)
if err != nil { if err != nil {

View File

@ -13,7 +13,7 @@ type BranchStore interface {
GetBranchByCompanyID(ctx context.Context, companyID int64) ([]domain.BranchDetail, error) GetBranchByCompanyID(ctx context.Context, companyID int64) ([]domain.BranchDetail, error)
GetAllBranches(ctx context.Context) ([]domain.BranchDetail, error) GetAllBranches(ctx context.Context) ([]domain.BranchDetail, error)
SearchBranchByName(ctx context.Context, name string) ([]domain.BranchDetail, error) SearchBranchByName(ctx context.Context, name string) ([]domain.BranchDetail, error)
UpdateBranch(ctx context.Context, id int64, branch domain.UpdateBranch) (domain.Branch, error) UpdateBranch(ctx context.Context, branch domain.UpdateBranch) (domain.Branch, error)
DeleteBranch(ctx context.Context, id int64) error DeleteBranch(ctx context.Context, id int64) error
CreateBranchOperation(ctx context.Context, branchOperation domain.CreateBranchOperation) error CreateBranchOperation(ctx context.Context, branchOperation domain.CreateBranchOperation) error
CreateSupportedOperation(ctx context.Context, supportedOperation domain.CreateSupportedOperation) (domain.SupportedOperation, error) CreateSupportedOperation(ctx context.Context, supportedOperation domain.CreateSupportedOperation) (domain.SupportedOperation, error)

View File

@ -57,8 +57,8 @@ func (s *Service) GetAllSupportedOperations(ctx context.Context) ([]domain.Suppo
func (s *Service) SearchBranchByName(ctx context.Context, name string) ([]domain.BranchDetail, error) { func (s *Service) SearchBranchByName(ctx context.Context, name string) ([]domain.BranchDetail, error) {
return s.branchStore.SearchBranchByName(ctx, name) return s.branchStore.SearchBranchByName(ctx, name)
} }
func (s *Service) UpdateBranch(ctx context.Context, id int64, branch domain.UpdateBranch) (domain.Branch, error) { func (s *Service) UpdateBranch(ctx context.Context, branch domain.UpdateBranch) (domain.Branch, error) {
return s.branchStore.UpdateBranch(ctx, id, branch) return s.branchStore.UpdateBranch(ctx, branch)
} }
func (s *Service) DeleteBranch(ctx context.Context, id int64) error { func (s *Service) DeleteBranch(ctx context.Context, id int64) error {
return s.branchStore.DeleteBranch(ctx, id) return s.branchStore.DeleteBranch(ctx, id)

View File

@ -11,6 +11,6 @@ type CompanyStore interface {
GetAllCompanies(ctx context.Context) ([]domain.GetCompany, error) GetAllCompanies(ctx context.Context) ([]domain.GetCompany, error)
SearchCompanyByName(ctx context.Context, name string) ([]domain.GetCompany, error) SearchCompanyByName(ctx context.Context, name string) ([]domain.GetCompany, error)
GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany, error) GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany, error)
UpdateCompany(ctx context.Context, id int64, company domain.UpdateCompany) (domain.Company, error) UpdateCompany(ctx context.Context, company domain.UpdateCompany) (domain.Company, error)
DeleteCompany(ctx context.Context, id int64) error DeleteCompany(ctx context.Context, id int64) error
} }

View File

@ -31,8 +31,8 @@ func (s *Service) SearchCompanyByName(ctx context.Context, name string) ([]domai
return s.companyStore.SearchCompanyByName(ctx, name) return s.companyStore.SearchCompanyByName(ctx, name)
} }
func (s *Service) UpdateCompany(ctx context.Context, id int64, company domain.UpdateCompany) (domain.Company, error) { func (s *Service) UpdateCompany(ctx context.Context, company domain.UpdateCompany) (domain.Company, error) {
return s.companyStore.UpdateCompany(ctx, id, company) return s.companyStore.UpdateCompany(ctx, company)
} }
func (s *Service) DeleteCompany(ctx context.Context, id int64) error { func (s *Service) DeleteCompany(ctx context.Context, id int64) error {
return s.companyStore.DeleteCompany(ctx, id) return s.companyStore.DeleteCompany(ctx, id)

View File

@ -99,11 +99,12 @@ func (s *service) FetchLiveEvents(ctx context.Context) error {
func (s *service) FetchUpcomingEvents(ctx context.Context) error { func (s *service) FetchUpcomingEvents(ctx context.Context) error {
sportIDs := []int{1} sportIDs := []int{1}
var totalPages int = 1
var page int = 0
var limit int = 100
var count int = 0
for _, sportID := range sportIDs { for _, sportID := range sportIDs {
var totalPages int = 1
var page int = 0
var limit int = 100
var count int = 0
for page != totalPages { for page != totalPages {
time.Sleep(3 * time.Second) //This will restrict the fetching to 1200 requests per hour time.Sleep(3 * time.Second) //This will restrict the fetching to 1200 requests per hour

View File

@ -11,5 +11,5 @@ type TransactionStore interface {
GetTransactionByID(ctx context.Context, id int64) (domain.Transaction, error) GetTransactionByID(ctx context.Context, id int64) (domain.Transaction, error)
GetAllTransactions(ctx context.Context) ([]domain.Transaction, error) GetAllTransactions(ctx context.Context) ([]domain.Transaction, error)
GetTransactionByBranch(ctx context.Context, id int64) ([]domain.Transaction, error) GetTransactionByBranch(ctx context.Context, id int64) ([]domain.Transaction, error)
UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64) error UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64, approverName string) error
} }

View File

@ -28,6 +28,6 @@ func (s *Service) GetAllTransactions(ctx context.Context) ([]domain.Transaction,
func (s *Service) GetTransactionByBranch(ctx context.Context, id int64) ([]domain.Transaction, error) { func (s *Service) GetTransactionByBranch(ctx context.Context, id int64) ([]domain.Transaction, error) {
return s.transactionStore.GetTransactionByBranch(ctx, id) return s.transactionStore.GetTransactionByBranch(ctx, id)
} }
func (s *Service) UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64) error { func (s *Service) UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64, approverName string) error {
return s.transactionStore.UpdateTransactionVerified(ctx, id, verified, approvedBy) return s.transactionStore.UpdateTransactionVerified(ctx, id, verified, approvedBy, approverName)
} }

View File

@ -14,6 +14,7 @@ type UserStore interface {
GetAllCashiers(ctx context.Context) ([]domain.User, error) GetAllCashiers(ctx context.Context) ([]domain.User, error)
GetCashiersByBranch(ctx context.Context, branchID int64) ([]domain.User, error) GetCashiersByBranch(ctx context.Context, branchID int64) ([]domain.User, error)
UpdateUser(ctx context.Context, user domain.UpdateUserReq) error UpdateUser(ctx context.Context, user domain.UpdateUserReq) error
UpdateUserCompany(ctx context.Context, id int64, companyID int64) error
DeleteUser(ctx context.Context, id int64) error DeleteUser(ctx context.Context, id int64) error
CheckPhoneEmailExist(ctx context.Context, phoneNum, email string) (bool, bool, error) CheckPhoneEmailExist(ctx context.Context, phoneNum, email string) (bool, bool, error)
GetUserByEmail(ctx context.Context, email string) (domain.User, error) GetUserByEmail(ctx context.Context, email string) (domain.User, error)

View File

@ -6,9 +6,6 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
) )
func (s *Service) SearchUserByNameOrPhone(ctx context.Context, searchString string) ([]domain.User, error) { func (s *Service) SearchUserByNameOrPhone(ctx context.Context, searchString string) ([]domain.User, error) {
// Search user // Search user
return s.userStore.SearchUserByNameOrPhone(ctx, searchString) return s.userStore.SearchUserByNameOrPhone(ctx, searchString)
@ -18,6 +15,12 @@ func (s *Service) UpdateUser(ctx context.Context, user domain.UpdateUserReq) err
// update user // update user
return s.userStore.UpdateUser(ctx, user) return s.userStore.UpdateUser(ctx, user)
}
func (s *Service) UpdateUserCompany(ctx context.Context, id int64, companyID int64) error {
// update user
return s.userStore.UpdateUserCompany(ctx, id, companyID)
} }
func (s *Service) GetUserByID(ctx context.Context, id int64) (domain.User, error) { func (s *Service) GetUserByID(ctx context.Context, id int64) (domain.User, error) {
return s.userStore.GetUserByID(ctx, id) return s.userStore.GetUserByID(ctx, id)

View File

@ -1,6 +1,7 @@
package handlers package handlers
import ( import (
"log/slog"
"time" "time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
@ -51,6 +52,11 @@ func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
Valid: false, Valid: false,
} }
} else { } else {
_, err := h.companySvc.GetCompanyByID(c.Context(), *req.CompanyID)
if err != nil {
h.logger.Error("CreateAdmin company id is invalid", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Company ID is invalid", nil, nil)
}
companyID = domain.ValidInt64{ companyID = domain.ValidInt64{
Value: *req.CompanyID, Value: *req.CompanyID,
Valid: true, Valid: true,
@ -66,11 +72,25 @@ func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
Role: string(domain.RoleAdmin), Role: string(domain.RoleAdmin),
CompanyID: companyID, CompanyID: companyID,
} }
_, err := h.userSvc.CreateUser(c.Context(), user, true)
h.logger.Info("CreateAdmin", slog.Bool("company id", req.CompanyID == nil))
newUser, err := h.userSvc.CreateUser(c.Context(), user, true)
if err != nil { if err != nil {
h.logger.Error("CreateAdmin failed", "error", err) h.logger.Error("CreateAdmin failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create admin", nil, nil) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create admin", nil, nil)
} }
if req.CompanyID != nil {
_, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
ID: *req.CompanyID,
AdminID: &newUser.ID,
})
if err != nil {
h.logger.Error("CreateAdmin failed to update company", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update company", nil, nil)
}
}
return response.WriteJSON(c, fiber.StatusOK, "Admin created successfully", nil, nil) return response.WriteJSON(c, fiber.StatusOK, "Admin created successfully", nil, nil)
} }

View File

@ -9,12 +9,20 @@ import (
) )
type CreateBranchReq struct { type CreateBranchReq struct {
Name string `json:"name" example:"4-kilo Branch"` Name string `json:"name" validate:"required,min=3,max=100" example:"4-kilo Branch"`
Location string `json:"location" example:"Addis Ababa"` Location string `json:"location" validate:"required,min=3,max=100" example:"Addis Ababa"`
BranchManagerID int64 `json:"branch_manager_id" example:"1"` BranchManagerID int64 `json:"branch_manager_id" validate:"required,gt=0" example:"1"`
CompanyID int64 `json:"company_id" example:"1"` CompanyID *int64 `json:"company_id,omitempty" example:"1"`
IsSelfOwned bool `json:"is_self_owned" example:"false"` IsSelfOwned *bool `json:"is_self_owned,omitempty" example:"false"`
Operations []int64 `json:"operations"` Operations []int64 `json:"operations" validate:"required,dive,gt=0"`
}
type UpdateBranchReq struct {
Name *string `json:"name,omitempty" example:"4-kilo Branch"`
Location *string `json:"location,omitempty" example:"Addis Ababa"`
BranchManagerID *int64 `json:"branch_manager_id,omitempty" example:"1"`
CompanyID *int64 `json:"company_id,omitempty" example:"1"`
IsSelfOwned *bool `json:"is_self_owned,omitempty" example:"false"`
} }
type CreateSupportedOperationReq struct { type CreateSupportedOperationReq struct {
@ -106,6 +114,9 @@ func (h *Handler) CreateBranch(c *fiber.Ctx) error {
// return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil) // return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
// } // }
role := c.Locals("role").(domain.Role)
companyID := c.Locals("company_id").(domain.ValidInt64)
var req CreateBranchReq var req CreateBranchReq
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
@ -117,6 +128,21 @@ func (h *Handler) CreateBranch(c *fiber.Ctx) error {
if !ok { if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
} }
var IsSelfOwned bool
var checkedCompanyID int64
if role == domain.RoleSuperAdmin {
if req.IsSelfOwned == nil {
return response.WriteJSON(c, fiber.StatusBadRequest, "is_self_owned is required for super admin", nil, nil)
}
if req.CompanyID == nil {
return response.WriteJSON(c, fiber.StatusBadRequest, "company_id is required for super admin", nil, nil)
}
IsSelfOwned = *req.IsSelfOwned
checkedCompanyID = *req.CompanyID
} else {
IsSelfOwned = false
checkedCompanyID = companyID.Value //the company id is always valid when its not a super admin
}
// Create Branch Wallet // Create Branch Wallet
newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{ newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
@ -136,8 +162,8 @@ func (h *Handler) CreateBranch(c *fiber.Ctx) error {
Location: req.Location, Location: req.Location,
WalletID: newWallet.ID, WalletID: newWallet.ID,
BranchManagerID: req.BranchManagerID, BranchManagerID: req.BranchManagerID,
CompanyID: req.CompanyID, CompanyID: checkedCompanyID,
IsSelfOwned: req.IsSelfOwned, IsSelfOwned: IsSelfOwned,
}) })
if err != nil { if err != nil {
@ -519,7 +545,7 @@ func (h *Handler) UpdateBranch(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
} }
var req CreateBranchReq var req UpdateBranchReq
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateBranchReq failed", "error", err) h.logger.Error("CreateBranchReq failed", "error", err)
@ -530,7 +556,8 @@ func (h *Handler) UpdateBranch(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
} }
branch, err := h.branchSvc.UpdateBranch(c.Context(), id, domain.UpdateBranch{ branch, err := h.branchSvc.UpdateBranch(c.Context(), domain.UpdateBranch{
ID: id,
Name: req.Name, Name: req.Name,
Location: req.Location, Location: req.Location,
BranchManagerID: req.BranchManagerID, BranchManagerID: req.BranchManagerID,

View File

@ -12,6 +12,10 @@ type CreateCompanyReq struct {
Name string `json:"name" example:"CompanyName"` Name string `json:"name" example:"CompanyName"`
AdminID int64 `json:"admin_id" example:"1"` AdminID int64 `json:"admin_id" example:"1"`
} }
type UpdateCompanyReq struct {
Name *string `json:"name,omitempty" example:"CompanyName"`
AdminID *int64 `json:"admin_id,omitempty" example:"1"`
}
type CompanyRes struct { type CompanyRes struct {
ID int64 `json:"id" example:"1"` ID int64 `json:"id" example:"1"`
@ -71,7 +75,14 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
if !ok { if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
} }
// Create Branch Wallet
user, err := h.userSvc.GetUserByID(c.Context(), req.AdminID)
if err != nil {
h.logger.Error("Error fetching user", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get user", err, nil)
}
// Create Company Wallet
newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{ newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
IsWithdraw: false, IsWithdraw: false,
IsBettable: true, IsBettable: true,
@ -86,7 +97,7 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
company, err := h.companySvc.CreateCompany(c.Context(), domain.CreateCompany{ company, err := h.companySvc.CreateCompany(c.Context(), domain.CreateCompany{
Name: req.Name, Name: req.Name,
AdminID: req.AdminID, AdminID: user.ID,
WalletID: newWallet.ID, WalletID: newWallet.ID,
}) })
@ -97,6 +108,13 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
}) })
} }
err = h.userSvc.UpdateUserCompany(c.Context(), user.ID, company.ID)
if err != nil {
h.logger.Error("CreateCompanyReq failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
res := convertCompany(company) res := convertCompany(company)
return response.WriteJSON(c, fiber.StatusCreated, "Company Created", res, nil) return response.WriteJSON(c, fiber.StatusCreated, "Company Created", res, nil)
@ -201,7 +219,7 @@ func (h *Handler) SearchCompany(c *fiber.Ctx) error {
// @Accept json // @Accept json
// @Produce json // @Produce json
// @Param id path int true "Company ID" // @Param id path int true "Company ID"
// @Param updateCompany body CreateCompanyReq true "Update Company" // @Param updateCompany body UpdateCompanyReq true "Update Company"
// @Success 200 {object} CompanyRes // @Success 200 {object} CompanyRes
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
@ -215,7 +233,7 @@ func (h *Handler) UpdateCompany(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
} }
var req CreateCompanyReq var req UpdateCompanyReq
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateCompanyReq failed", "error", err) h.logger.Error("CreateCompanyReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
@ -225,7 +243,8 @@ func (h *Handler) UpdateCompany(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
} }
company, err := h.companySvc.UpdateCompany(c.Context(), id, domain.UpdateCompany{ company, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
ID: id,
Name: req.Name, Name: req.Name,
AdminID: req.AdminID, AdminID: req.AdminID,
}) })

View File

@ -14,7 +14,11 @@ type TransactionRes struct {
ID int64 `json:"id" example:"1"` ID int64 `json:"id" example:"1"`
Amount float32 `json:"amount" example:"100.0"` Amount float32 `json:"amount" example:"100.0"`
BranchID int64 `json:"branch_id" example:"1"` BranchID int64 `json:"branch_id" example:"1"`
BranchName string `json:"branch_name" example:"Branch Name"`
BranchLocation string `json:"branch_location" example:"Branch Location"`
CompanyID int64 `json:"company_id" example:"1"`
CashierID int64 `json:"cashier_id" example:"1"` CashierID int64 `json:"cashier_id" example:"1"`
CashierName string `json:"cashier_name" example:"John Smith"`
BetID int64 `json:"bet_id" example:"1"` BetID int64 `json:"bet_id" example:"1"`
NumberOfOutcomes int64 `json:"number_of_outcomes" example:"1"` NumberOfOutcomes int64 `json:"number_of_outcomes" example:"1"`
Type int64 `json:"type" example:"1"` Type int64 `json:"type" example:"1"`
@ -28,6 +32,7 @@ type TransactionRes struct {
ReferenceNumber string `json:"reference_number"` ReferenceNumber string `json:"reference_number"`
Verified bool `json:"verified" example:"true"` Verified bool `json:"verified" example:"true"`
ApprovedBy *int64 `json:"approved_by" example:"1"` ApprovedBy *int64 `json:"approved_by" example:"1"`
ApproverName *string `json:"approver_name" example:"John Smith"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
} }
@ -53,7 +58,11 @@ func convertTransaction(transaction domain.Transaction) TransactionRes {
ID: transaction.ID, ID: transaction.ID,
Amount: transaction.Amount.Float32(), Amount: transaction.Amount.Float32(),
BranchID: transaction.BranchID, BranchID: transaction.BranchID,
BranchName: transaction.BranchName,
BranchLocation: transaction.BranchLocation,
CompanyID: transaction.CompanyID,
CashierID: transaction.CashierID, CashierID: transaction.CashierID,
CashierName: transaction.CashierName,
BetID: transaction.BetID, BetID: transaction.BetID,
Type: int64(transaction.Type), Type: int64(transaction.Type),
PaymentOption: transaction.PaymentOption, PaymentOption: transaction.PaymentOption,
@ -72,6 +81,8 @@ func convertTransaction(transaction domain.Transaction) TransactionRes {
if transaction.ApprovedBy.Valid { if transaction.ApprovedBy.Valid {
newTransaction.ApprovedBy = &transaction.ApprovedBy.Value newTransaction.ApprovedBy = &transaction.ApprovedBy.Value
newTransaction.ApproverName = &transaction.ApproverName.Value
} }
return newTransaction return newTransaction
@ -114,6 +125,9 @@ func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
} }
var branchID int64 var branchID int64
var branchName string
var branchLocation string
var companyID int64
if role == domain.RoleAdmin || role == domain.RoleBranchManager || role == domain.RoleSuperAdmin { if role == domain.RoleAdmin || role == domain.RoleBranchManager || role == domain.RoleSuperAdmin {
if req.BranchID == nil { if req.BranchID == nil {
h.logger.Error("CreateTransactionReq Branch ID is required for this user role") h.logger.Error("CreateTransactionReq Branch ID is required for this user role")
@ -126,7 +140,9 @@ func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
} }
branchID = branch.ID branchID = branch.ID
branchName = branch.Name
branchLocation = branch.Location
companyID = branch.CompanyID
} else { } else {
branch, err := h.branchSvc.GetBranchByCashier(c.Context(), userID) branch, err := h.branchSvc.GetBranchByCashier(c.Context(), userID)
if err != nil { if err != nil {
@ -134,6 +150,9 @@ func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID invalid", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID invalid", err, nil)
} }
branchID = branch.ID branchID = branch.ID
branchName = branch.Name
branchLocation = branch.Location
companyID = branch.CompanyID
} }
bet, err := h.betSvc.GetBetByID(c.Context(), req.BetID) bet, err := h.betSvc.GetBetByID(c.Context(), req.BetID)
@ -152,6 +171,8 @@ func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "This bet has already been cashed out", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "This bet has already been cashed out", err, nil)
} }
user, err := h.userSvc.GetUserByID(c.Context(), userID)
transaction, err := h.transactionSvc.CreateTransaction(c.Context(), domain.CreateTransaction{ transaction, err := h.transactionSvc.CreateTransaction(c.Context(), domain.CreateTransaction{
BranchID: branchID, BranchID: branchID,
CashierID: userID, CashierID: userID,
@ -167,6 +188,10 @@ func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
AccountName: req.AccountName, AccountName: req.AccountName,
AccountNumber: req.AccountNumber, AccountNumber: req.AccountNumber,
ReferenceNumber: req.ReferenceNumber, ReferenceNumber: req.ReferenceNumber,
CashierName: user.FirstName + " " + user.LastName,
BranchName: branchName,
BranchLocation: branchLocation,
CompanyID: companyID,
}) })
if err != nil { if err != nil {
@ -289,7 +314,8 @@ type UpdateTransactionVerifiedReq struct {
func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error { func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error {
transactionID := c.Params("id") transactionID := c.Params("id")
userID := c.Locals("user_id").(int64) userID := c.Locals("user_id").(int64)
// companyID := c.Locals("company_id").(domain.ValidInt64) companyID := c.Locals("company_id").(domain.ValidInt64)
role := c.Locals("role").(domain.Role)
id, err := strconv.ParseInt(transactionID, 10, 64) id, err := strconv.ParseInt(transactionID, 10, 64)
if err != nil { if err != nil {
@ -309,8 +335,20 @@ func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
} }
// TODO: make it so that only people within the company can verify a transaction transaction, err := h.transactionSvc.GetTransactionByID(c.Context(), id)
err = h.transactionSvc.UpdateTransactionVerified(c.Context(), id, req.Verified, userID) if role != domain.RoleSuperAdmin {
if !companyID.Valid || companyID.Value != transaction.CompanyID {
h.logger.Error("Failed to parse UpdateTransactionVerified request", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
}
user, err := h.userSvc.GetUserById(c.Context(), userID)
if err != nil {
h.logger.Error("Invalid user ID", "userID", userID, "error", err)
return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID")
}
err = h.transactionSvc.UpdateTransactionVerified(c.Context(), id, req.Verified, userID, user.FirstName+" "+user.LastName)
if err != nil { if err != nil {
h.logger.Error("Failed to update transaction verification", "transactionID", id, "error", err) h.logger.Error("Failed to update transaction verification", "transactionID", id, "error", err)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update transaction verification") return fiber.NewError(fiber.StatusInternalServerError, "Failed to update transaction verification")

View File

@ -41,6 +41,12 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
// refreshToken = c.Cookies("refresh_token", "") // refreshToken = c.Cookies("refresh_token", "")
// return fiber.NewError(fiber.StatusUnauthorized, "Refresh token missing") // return fiber.NewError(fiber.StatusUnauthorized, "Refresh token missing")
}
// Asserting to make sure that there is no company role without a valid company id
if claim.Role != domain.RoleSuperAdmin && !claim.CompanyID.Valid {
fmt.Println("Company Role without Company ID")
return fiber.NewError(fiber.StatusInternalServerError, "Company Role without Company ID")
} }
c.Locals("user_id", claim.UserId) c.Locals("user_id", claim.UserId)
c.Locals("role", claim.Role) c.Locals("role", claim.Role)
@ -57,3 +63,11 @@ func (a *App) SuperAdminOnly(c *fiber.Ctx) error {
} }
return c.Next() return c.Next()
} }
func (a *App) CompanyOnly(c *fiber.Ctx) error {
userRole := c.Locals("role").(domain.Role)
if userRole == domain.RoleCustomer {
return fiber.NewError(fiber.StatusUnauthorized, "Invalid access token")
}
return c.Next()
}