fix: company filter

This commit is contained in:
Samuel Tariku 2025-07-02 19:41:29 +03:00
parent c4328dedf0
commit c2a9de6671
16 changed files with 431 additions and 36 deletions

View File

@ -285,7 +285,9 @@ CREATE TABLE companies (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL, name TEXT NOT NULL,
admin_id BIGINT NOT NULL, admin_id BIGINT NOT NULL,
wallet_id BIGINT NOT NULL wallet_id BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
); );
CREATE TABLE leagues ( CREATE TABLE leagues (
id BIGINT PRIMARY KEY, id BIGINT PRIMARY KEY,

View File

@ -87,7 +87,8 @@ SET name = COALESCE(sqlc.narg(name), name),
branch_manager_id = COALESCE(sqlc.narg(branch_manager_id), branch_manager_id), branch_manager_id = COALESCE(sqlc.narg(branch_manager_id), branch_manager_id),
company_id = COALESCE(sqlc.narg(company_id), company_id), company_id = COALESCE(sqlc.narg(company_id), company_id),
is_self_owned = COALESCE(sqlc.narg(is_self_owned), is_self_owned), is_self_owned = COALESCE(sqlc.narg(is_self_owned), is_self_owned),
is_active = COALESCE(sqlc.narg(is_active), is_active) is_active = COALESCE(sqlc.narg(is_active), is_active),
updated_at = CURRENT_TIMESTAMP
WHERE id = $1 WHERE id = $1
RETURNING *; RETURNING *;
-- name: DeleteBranch :exec -- name: DeleteBranch :exec

View File

@ -8,7 +8,22 @@ VALUES ($1, $2, $3)
RETURNING *; RETURNING *;
-- name: GetAllCompanies :many -- name: GetAllCompanies :many
SELECT * SELECT *
FROM companies_details; FROM companies_details
WHERE (
name ILIKE '%' || sqlc.narg('query') || '%'
OR admin_first_name ILIKE '%' || sqlc.narg('query') || '%'
OR admin_last_name ILIKE '%' || sqlc.narg('query') || '%'
OR admin_phone_number ILIKE '%' || sqlc.narg('query') || '%'
OR sqlc.narg('query') IS NULL
)
AND (
created_at > sqlc.narg('created_before')
OR sqlc.narg('created_before') IS NULL
)
AND (
created_at < sqlc.narg('created_after')
OR sqlc.narg('created_after') IS NULL
);
-- name: GetCompanyByID :one -- name: GetCompanyByID :one
SELECT * SELECT *
FROM companies_details FROM companies_details
@ -20,7 +35,8 @@ WHERE name ILIKE '%' || $1 || '%';
-- name: UpdateCompany :one -- name: UpdateCompany :one
UPDATE companies UPDATE companies
SET name = COALESCE(sqlc.narg(name), name), SET name = COALESCE(sqlc.narg(name), name),
admin_id = COALESCE(sqlc.narg(admin_id), admin_id) admin_id = COALESCE(sqlc.narg(admin_id), admin_id),
updated_at = CURRENT_TIMESTAMP
WHERE id = $1 WHERE id = $1
RETURNING *; RETURNING *;
-- name: DeleteCompany :exec -- name: DeleteCompany :exec

View File

@ -490,7 +490,8 @@ SET name = COALESCE($2, name),
branch_manager_id = COALESCE($4, branch_manager_id), branch_manager_id = COALESCE($4, branch_manager_id),
company_id = COALESCE($5, company_id), company_id = COALESCE($5, company_id),
is_self_owned = COALESCE($6, is_self_owned), is_self_owned = COALESCE($6, is_self_owned),
is_active = COALESCE($7, is_active) is_active = COALESCE($7, is_active),
updated_at = CURRENT_TIMESTAMP
WHERE id = $1 WHERE id = $1
RETURNING id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at RETURNING id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at
` `

View File

@ -18,7 +18,7 @@ INSERT INTO companies (
wallet_id wallet_id
) )
VALUES ($1, $2, $3) VALUES ($1, $2, $3)
RETURNING id, name, admin_id, wallet_id RETURNING id, name, admin_id, wallet_id, created_at, updated_at
` `
type CreateCompanyParams struct { type CreateCompanyParams struct {
@ -35,6 +35,8 @@ func (q *Queries) CreateCompany(ctx context.Context, arg CreateCompanyParams) (C
&i.Name, &i.Name,
&i.AdminID, &i.AdminID,
&i.WalletID, &i.WalletID,
&i.CreatedAt,
&i.UpdatedAt,
) )
return i, err return i, err
} }
@ -50,12 +52,33 @@ func (q *Queries) DeleteCompany(ctx context.Context, id int64) error {
} }
const GetAllCompanies = `-- name: GetAllCompanies :many const GetAllCompanies = `-- name: GetAllCompanies :many
SELECT id, name, admin_id, wallet_id, balance, is_active, admin_first_name, admin_last_name, admin_phone_number SELECT id, name, admin_id, wallet_id, created_at, updated_at, balance, is_active, admin_first_name, admin_last_name, admin_phone_number
FROM companies_details FROM companies_details
WHERE (
name ILIKE '%' || $1 || '%'
OR admin_first_name ILIKE '%' || $1 || '%'
OR admin_last_name ILIKE '%' || $1 || '%'
OR admin_phone_number ILIKE '%' || $1 || '%'
OR $1 IS NULL
)
AND (
created_at > $2
OR $2 IS NULL
)
AND (
created_at < $3
OR $3 IS NULL
)
` `
func (q *Queries) GetAllCompanies(ctx context.Context) ([]CompaniesDetail, error) { type GetAllCompaniesParams struct {
rows, err := q.db.Query(ctx, GetAllCompanies) Query pgtype.Text `json:"query"`
CreatedBefore pgtype.Timestamp `json:"created_before"`
CreatedAfter pgtype.Timestamp `json:"created_after"`
}
func (q *Queries) GetAllCompanies(ctx context.Context, arg GetAllCompaniesParams) ([]CompaniesDetail, error) {
rows, err := q.db.Query(ctx, GetAllCompanies, arg.Query, arg.CreatedBefore, arg.CreatedAfter)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -68,6 +91,8 @@ func (q *Queries) GetAllCompanies(ctx context.Context) ([]CompaniesDetail, error
&i.Name, &i.Name,
&i.AdminID, &i.AdminID,
&i.WalletID, &i.WalletID,
&i.CreatedAt,
&i.UpdatedAt,
&i.Balance, &i.Balance,
&i.IsActive, &i.IsActive,
&i.AdminFirstName, &i.AdminFirstName,
@ -85,7 +110,7 @@ func (q *Queries) GetAllCompanies(ctx context.Context) ([]CompaniesDetail, error
} }
const GetCompanyByID = `-- name: GetCompanyByID :one const GetCompanyByID = `-- name: GetCompanyByID :one
SELECT id, name, admin_id, wallet_id, balance, is_active, admin_first_name, admin_last_name, admin_phone_number SELECT id, name, admin_id, wallet_id, created_at, updated_at, balance, is_active, admin_first_name, admin_last_name, admin_phone_number
FROM companies_details FROM companies_details
WHERE id = $1 WHERE id = $1
` `
@ -98,6 +123,8 @@ func (q *Queries) GetCompanyByID(ctx context.Context, id int64) (CompaniesDetail
&i.Name, &i.Name,
&i.AdminID, &i.AdminID,
&i.WalletID, &i.WalletID,
&i.CreatedAt,
&i.UpdatedAt,
&i.Balance, &i.Balance,
&i.IsActive, &i.IsActive,
&i.AdminFirstName, &i.AdminFirstName,
@ -108,7 +135,7 @@ func (q *Queries) GetCompanyByID(ctx context.Context, id int64) (CompaniesDetail
} }
const SearchCompanyByName = `-- name: SearchCompanyByName :many const SearchCompanyByName = `-- name: SearchCompanyByName :many
SELECT id, name, admin_id, wallet_id, balance, is_active, admin_first_name, admin_last_name, admin_phone_number SELECT id, name, admin_id, wallet_id, created_at, updated_at, balance, is_active, admin_first_name, admin_last_name, admin_phone_number
FROM companies_details FROM companies_details
WHERE name ILIKE '%' || $1 || '%' WHERE name ILIKE '%' || $1 || '%'
` `
@ -127,6 +154,8 @@ func (q *Queries) SearchCompanyByName(ctx context.Context, dollar_1 pgtype.Text)
&i.Name, &i.Name,
&i.AdminID, &i.AdminID,
&i.WalletID, &i.WalletID,
&i.CreatedAt,
&i.UpdatedAt,
&i.Balance, &i.Balance,
&i.IsActive, &i.IsActive,
&i.AdminFirstName, &i.AdminFirstName,
@ -146,9 +175,10 @@ 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 = COALESCE($2, name), SET name = COALESCE($2, name),
admin_id = COALESCE($3, admin_id) admin_id = COALESCE($3, admin_id),
updated_at = CURRENT_TIMESTAMP
WHERE id = $1 WHERE id = $1
RETURNING id, name, admin_id, wallet_id RETURNING id, name, admin_id, wallet_id, created_at, updated_at
` `
type UpdateCompanyParams struct { type UpdateCompanyParams struct {
@ -165,6 +195,8 @@ func (q *Queries) UpdateCompany(ctx context.Context, arg UpdateCompanyParams) (C
&i.Name, &i.Name,
&i.AdminID, &i.AdminID,
&i.WalletID, &i.WalletID,
&i.CreatedAt,
&i.UpdatedAt,
) )
return i, err return i, err
} }

View File

@ -183,6 +183,8 @@ type CompaniesDetail struct {
Name string `json:"name"` Name string `json:"name"`
AdminID int64 `json:"admin_id"` AdminID int64 `json:"admin_id"`
WalletID int64 `json:"wallet_id"` WalletID int64 `json:"wallet_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
Balance int64 `json:"balance"` Balance int64 `json:"balance"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
AdminFirstName string `json:"admin_first_name"` AdminFirstName string `json:"admin_first_name"`
@ -195,6 +197,8 @@ type Company struct {
Name string `json:"name"` Name string `json:"name"`
AdminID int64 `json:"admin_id"` AdminID int64 `json:"admin_id"`
WalletID int64 `json:"wallet_id"` WalletID int64 `json:"wallet_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }
type CustomerWallet struct { type CustomerWallet struct {

View File

@ -253,9 +253,16 @@ WHERE wallet_id = $1
LIMIT 1 LIMIT 1
` `
func (q *Queries) GetCompanyByWalletID(ctx context.Context, walletID int64) (Company, error) { type GetCompanyByWalletIDRow struct {
ID int64 `json:"id"`
Name string `json:"name"`
AdminID int64 `json:"admin_id"`
WalletID int64 `json:"wallet_id"`
}
func (q *Queries) GetCompanyByWalletID(ctx context.Context, walletID int64) (GetCompanyByWalletIDRow, error) {
row := q.db.QueryRow(ctx, GetCompanyByWalletID, walletID) row := q.db.QueryRow(ctx, GetCompanyByWalletID, walletID)
var i Company var i GetCompanyByWalletIDRow
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.Name, &i.Name,

View File

@ -10,6 +10,13 @@ type Company struct {
WalletID int64 WalletID int64
} }
type CompanyFilter struct {
IsActive ValidBool
Query ValidString
CreatedBefore ValidTime
CreatedAfter ValidTime
}
type GetCompany struct { type GetCompany struct {
ID int64 ID int64
Name string Name string

View File

@ -400,7 +400,7 @@ func (s *Store) GetBranchDetails(ctx context.Context, filter domain.ReportFilter
// In internal/repository/branch.go // In internal/repository/branch.go
func (s *Store) GetAllCompaniesBranch(ctx context.Context) ([]domain.Company, error) { func (s *Store) GetAllCompaniesBranch(ctx context.Context) ([]domain.Company, error) {
dbCompanies, err := s.queries.GetAllCompanies(ctx) dbCompanies, err := s.queries.GetAllCompanies(ctx, dbgen.GetAllCompaniesParams{})
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get all companies: %w", err) return nil, fmt.Errorf("failed to get all companies: %w", err)
} }

View File

@ -70,8 +70,21 @@ func (s *Store) CreateCompany(ctx context.Context, company domain.CreateCompany)
return convertDBCompany(dbCompany), nil return convertDBCompany(dbCompany), nil
} }
func (s *Store) GetAllCompanies(ctx context.Context) ([]domain.GetCompany, error) { func (s *Store) GetAllCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.GetCompany, error) {
dbCompanies, err := s.queries.GetAllCompanies(ctx) dbCompanies, err := s.queries.GetAllCompanies(ctx, dbgen.GetAllCompaniesParams{
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 {
return nil, err return nil, err
} }

View File

@ -108,7 +108,7 @@ func (r *Repository) ListNotifications(ctx context.Context, recipientID int64, l
return nil, err return nil, err
} }
var result []domain.Notification var result []domain.Notification = make([]domain.Notification, 0, len(dbNotifications))
for _, dbNotif := range dbNotifications { for _, dbNotif := range dbNotifications {
domainNotif := r.mapDBToDomain(&dbNotif) domainNotif := r.mapDBToDomain(&dbNotif)
result = append(result, *domainNotif) result = append(result, *domainNotif)

View File

@ -8,7 +8,7 @@ import (
type CompanyStore interface { type CompanyStore interface {
CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error) CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error)
GetAllCompanies(ctx context.Context) ([]domain.GetCompany, error) GetAllCompanies(ctx context.Context, filter domain.CompanyFilter) ([]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, company domain.UpdateCompany) (domain.Company, error) UpdateCompany(ctx context.Context, company domain.UpdateCompany) (domain.Company, error)

View File

@ -19,8 +19,8 @@ func NewService(companyStore CompanyStore) *Service {
func (s *Service) CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error) { func (s *Service) CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error) {
return s.companyStore.CreateCompany(ctx, company) return s.companyStore.CreateCompany(ctx, company)
} }
func (s *Service) GetAllCompanies(ctx context.Context) ([]domain.GetCompany, error) { func (s *Service) GetAllCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.GetCompany, error) {
return s.companyStore.GetAllCompanies(ctx) return s.companyStore.GetAllCompanies(ctx, filter)
} }
func (s *Service) GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany, error) { func (s *Service) GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany, error) {

View File

@ -2,6 +2,7 @@ package handlers
import ( import (
"strconv" "strconv"
"time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
@ -137,8 +138,45 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /company [get] // @Router /company [get]
func (h *Handler) GetAllCompanies(c *fiber.Ctx) error { func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
searchQuery := c.Query("query")
searchString := domain.ValidString{
Value: searchQuery,
Valid: searchQuery != "",
}
companies, err := h.companySvc.GetAllCompanies(c.Context()) createdBeforeQuery := c.Query("created_before")
var createdBefore domain.ValidTime
if createdBeforeQuery != "" {
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
if err != nil {
h.logger.Error("invalid start_time format", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
}
createdBefore = domain.ValidTime{
Value: createdBeforeParsed,
Valid: true,
}
}
createdAfterQuery := c.Query("created_after")
var createdAfter domain.ValidTime
if createdAfterQuery != "" {
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
if err != nil {
h.logger.Error("invalid start_time format", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
}
createdAfter = domain.ValidTime{
Value: createdAfterParsed,
Valid: true,
}
}
companies, err := h.companySvc.GetAllCompanies(c.Context(), domain.CompanyFilter{
Query: searchString,
CreatedBefore: createdBefore,
CreatedAfter: createdAfter,
})
if err != nil { if err != nil {
h.logger.Error("Failed to get companies", "error", err) h.logger.Error("Failed to get companies", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil)

View File

@ -0,0 +1,270 @@
package handlers
import (
"strconv"
"time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2"
)
type CustomersRes struct {
ID int64 `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
PhoneNumber string `json:"phone_number"`
Role domain.Role `json:"role"`
EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LastLogin time.Time `json:"last_login"`
SuspendedAt time.Time `json:"suspended_at"`
Suspended bool `json:"suspended"`
}
// GetAllCustomers godoc
// @Summary Get all Customers
// @Description Get all Customers
// @Tags customer
// @Accept json
// @Produce json
// @Param page query int false "Page number"
// @Param page_size query int false "Page size"
// @Success 200 {object} CustomersRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /customer [get]
func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
role := c.Locals("role").(domain.Role)
companyId := c.Locals("company_id").(domain.ValidInt64)
// Checking to make sure that admin user has a company id in the token
if role != domain.RoleSuperAdmin && !companyId.Valid {
return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID")
}
searchQuery := c.Query("query")
searchString := domain.ValidString{
Value: searchQuery,
Valid: searchQuery != "",
}
createdBeforeQuery := c.Query("created_before")
var createdBefore domain.ValidTime
if createdBeforeQuery != "" {
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
if err != nil {
h.logger.Error("invalid start_time format", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
}
createdBefore = domain.ValidTime{
Value: createdBeforeParsed,
Valid: true,
}
}
createdAfterQuery := c.Query("created_after")
var createdAfter domain.ValidTime
if createdAfterQuery != "" {
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
if err != nil {
h.logger.Error("invalid start_time format", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
}
createdAfter = domain.ValidTime{
Value: createdAfterParsed,
Valid: true,
}
}
filter := domain.UserFilter{
Role: string(domain.RoleCustomer),
CompanyID: companyId,
Page: domain.ValidInt{
Value: c.QueryInt("page", 1) - 1,
Valid: true,
},
PageSize: domain.ValidInt{
Value: c.QueryInt("page_size", 10),
Valid: true,
},
Query: searchString,
CreatedBefore: createdBefore,
CreatedAfter: createdAfter,
}
valErrs, ok := h.validator.Validate(c, filter)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
customers, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
if err != nil {
h.logger.Error("GetAllCustomers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Customers", err, nil)
}
var result []CustomersRes = make([]CustomersRes, len(customers))
for index, customer := range customers {
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), customer.ID)
if err != nil {
if err == authentication.ErrRefreshTokenNotFound {
lastLogin = &customer.CreatedAt
} else {
h.logger.Error("Failed to get user last login", "userID", customer.ID, "error", err)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
}
}
result[index] = CustomersRes{
ID: customer.ID,
FirstName: customer.FirstName,
LastName: customer.LastName,
Email: customer.Email,
PhoneNumber: customer.PhoneNumber,
Role: customer.Role,
EmailVerified: customer.EmailVerified,
PhoneVerified: customer.PhoneVerified,
CreatedAt: customer.CreatedAt,
UpdatedAt: customer.UpdatedAt,
SuspendedAt: customer.SuspendedAt,
Suspended: customer.Suspended,
LastLogin: *lastLogin,
}
}
return response.WritePaginatedJSON(c, fiber.StatusOK, "Customers retrieved successfully", result, nil, filter.Page.Value, int(total))
}
// GetCustomerByID godoc
// @Summary Get customer by id
// @Description Get a single customer by id
// @Tags customer
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {object} CustomersRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /customer/{id} [get]
func (h *Handler) GetCustomerByID(c *fiber.Ctx) error {
userIDstr := c.Params("id")
userID, err := strconv.ParseInt(userIDstr, 10, 64)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid customers ID")
}
user, err := h.userSvc.GetUserByID(c.Context(), userID)
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get customers")
}
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
if err != nil {
if err != authentication.ErrRefreshTokenNotFound {
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
}
lastLogin = &user.CreatedAt
}
res := CustomersRes{
ID: user.ID,
FirstName: user.FirstName,
LastName: user.LastName,
Email: user.Email,
PhoneNumber: user.PhoneNumber,
Role: user.Role,
EmailVerified: user.EmailVerified,
PhoneVerified: user.PhoneVerified,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
SuspendedAt: user.SuspendedAt,
Suspended: user.Suspended,
LastLogin: *lastLogin,
}
return response.WriteJSON(c, fiber.StatusOK, "User retrieved successfully", res, nil)
}
type updateCustomerReq struct {
FirstName string `json:"first_name" example:"John"`
LastName string `json:"last_name" example:"Doe"`
Suspended bool `json:"suspended" example:"false"`
CompanyID *int64 `json:"company_id,omitempty" example:"1"`
}
// UpdateCustomers godoc
// @Summary Update Customers
// @Description Update Customers
// @Tags customer
// @Accept json
// @Produce json
// @Param Customers body updateCustomerReq true "Update Customers"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /customer/{id} [put]
func (h *Handler) UpdateCustomer(c *fiber.Ctx) error {
var req updateCustomerReq
if err := c.BodyParser(&req); err != nil {
h.logger.Error("UpdateCustomers failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
CustomersIdStr := c.Params("id")
CustomersId, err := strconv.ParseInt(CustomersIdStr, 10, 64)
if err != nil {
h.logger.Error("UpdateCustomers failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Customers ID", nil, nil)
}
// var companyID domain.ValidInt64
// role := c.Locals("role").(domain.Role)
// if req.CompanyID != nil {
// if role != domain.RoleSuperAdmin {
// h.logger.Error("UpdateCustomers failed", "error", err)
// return response.WriteJSON(c, fiber.StatusUnauthorized, "This user role cannot modify company ID", nil, nil)
// }
// companyID = domain.ValidInt64{
// Value: *req.CompanyID,
// Valid: true,
// }
// }
err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
UserId: CustomersId,
FirstName: domain.ValidString{
Value: req.FirstName,
Valid: req.FirstName != "",
},
LastName: domain.ValidString{
Value: req.LastName,
Valid: req.LastName != "",
},
Suspended: domain.ValidBool{
Value: req.Suspended,
Valid: true,
},
},
)
if err != nil {
h.logger.Error("UpdateCustomers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update Customers", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Customers updated successfully", nil, nil)
}

View File

@ -123,6 +123,10 @@ func (a *App) initAppRoutes() {
a.fiber.Post("/cashiers", a.authMiddleware, h.CreateCashier) a.fiber.Post("/cashiers", a.authMiddleware, h.CreateCashier)
a.fiber.Put("/cashiers/:id", a.authMiddleware, h.UpdateCashier) a.fiber.Put("/cashiers/:id", a.authMiddleware, h.UpdateCashier)
a.fiber.Get("/customer", a.authMiddleware, a.SuperAdminOnly, h.GetAllCustomers)
a.fiber.Get("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCustomerByID)
a.fiber.Put("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCustomer)
a.fiber.Get("/admin", a.authMiddleware, h.GetAllAdmins) a.fiber.Get("/admin", a.authMiddleware, h.GetAllAdmins)
a.fiber.Get("/admin/:id", a.authMiddleware, h.GetAdminByID) a.fiber.Get("/admin/:id", a.authMiddleware, h.GetAdminByID)
a.fiber.Post("/admin", a.authMiddleware, h.CreateAdmin) a.fiber.Post("/admin", a.authMiddleware, h.CreateAdmin)