Yimaru-BackEnd/internal/web_server/handlers/transaction_approver.go

436 lines
14 KiB
Go

package handlers
import (
"Yimaru-Backend/internal/domain"
"Yimaru-Backend/internal/services/authentication"
"Yimaru-Backend/internal/web_server/response"
"fmt"
"strconv"
"time"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
type CreateTransactionApproverReq struct {
FirstName string `json:"first_name" example:"John"`
LastName string `json:"last_name" example:"Doe"`
Email string `json:"email" example:"john.doe@example.com"`
PhoneNumber string `json:"phone_number" example:"1234567890"`
Password string `json:"password" example:"password123"`
CompanyID int64 `json:"company_id" example:"1"`
}
// CreateTransactionApprover godoc
// @Summary Create transaction approver
// @Description Create transaction approver
// @Tags admin
// @Accept json
// @Produce json
// @Param manger body CreateTransactionApproverReq true "Create transaction approver"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/admin [post]
// func (h *Handler) CreateTransactionApprover(c *fiber.Ctx) error {
// var companyID domain.ValidInt64
// var req CreateTransactionApproverReq
// if err := c.BodyParser(&req); err != nil {
// h.mongoLoggerSvc.Info("failed to parse CreateAdmin request",
// zap.Int64("status_code", fiber.StatusBadRequest),
// zap.Error(err),
// zap.Time("timestamp", time.Now()),
// )
// return fiber.NewError(fiber.StatusBadRequest, "Invalid request:"+err.Error())
// }
// valErrs, ok := h.validator.Validate(c, req)
// if !ok {
// var errMsg string
// for field, msg := range valErrs {
// errMsg += fmt.Sprintf("%s: %s; ", field, msg)
// }
// h.mongoLoggerSvc.Error("validation failed for CreateAdmin request",
// zap.Int64("status_code", fiber.StatusBadRequest),
// zap.Any("validation_errors", valErrs),
// zap.Time("timestamp", time.Now()),
// )
// return fiber.NewError(fiber.StatusBadRequest, errMsg)
// }
// // _, err := h.companySvc.GetCompanyByID(c.Context(), req.CompanyID)
// // if err != nil {
// // h.mongoLoggerSvc.Error("invalid company ID for CreateAdmin",
// // zap.Int64("status_code", fiber.StatusInternalServerError),
// // zap.Int64("company_id", req.CompanyID),
// // zap.Error(err),
// // zap.Time("timestamp", time.Now()),
// // )
// // return fiber.NewError(fiber.StatusInternalServerError, "Company ID is invalid:"+err.Error())
// // }
// companyID = domain.ValidInt64{
// Value: req.CompanyID,
// Valid: true,
// }
// user := domain.CreateUserReq{
// FirstName: req.FirstName,
// LastName: req.LastName,
// Email: req.Email,
// PhoneNumber: req.PhoneNumber,
// Password: req.Password,
// Role: string(domain.RoleTransactionApprover),
// OrganizationID: companyID,
// }
// newUser, err := h.userSvc.CreateUser(c.Context(), user, true)
// if err != nil {
// h.mongoLoggerSvc.Error("failed to create admin user",
// zap.Int64("status_code", fiber.StatusInternalServerError),
// zap.Any("request", req),
// zap.Error(err),
// zap.Time("timestamp", time.Now()),
// )
// return fiber.NewError(fiber.StatusInternalServerError, "Failed to create admin:"+err.Error())
// }
// h.mongoLoggerSvc.Info("transaction_approver created successfully",
// zap.Int64("transaction_approver_id", newUser.ID),
// zap.String("email", newUser.Email),
// zap.Time("timestamp", time.Now()),
// )
// return response.WriteJSON(c, fiber.StatusOK, "Transaction Approver created successfully", nil, nil)
// }
type TransactionApproverRes 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"`
}
// GetAllAdmins godoc
// @Summary Get all Admins
// @Description Get all Admins
// @Tags admin
// @Accept json
// @Produce json
// @Param page query int false "Page number"
// @Param page_size query int false "Page size"
// @Success 200 {object} AdminRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/t-approver [get]
// func (h *Handler) GetAllTransactionApprovers(c *fiber.Ctx) error {
// role := c.Locals("role").(domain.Role)
// companyID := c.Locals("company_id").(domain.ValidInt64)
// 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.Info("invalid start_time format", "error", err)
// return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
// }
// 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.Info("invalid start_time format", "error", err)
// return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
// }
// createdAfter = domain.ValidTime{
// Value: createdAfterParsed,
// Valid: true,
// }
// }
// var companyIDFilter domain.ValidInt64
// if role == domain.RoleSuperAdmin {
// companyIDQuery := int64(c.QueryInt("company_id"))
// companyIDFilter = domain.ValidInt64{
// Value: companyIDQuery,
// Valid: companyIDQuery != 0,
// }
// } else {
// if !companyID.Valid {
// h.logger.Info("invalid companyID")
// return fiber.NewError(fiber.StatusBadRequest, "Unable to get company ID")
// }
// companyIDFilter = companyID
// }
// filter := domain.UserFilter{
// Role: string(domain.RoleTransactionApprover),
// OrganizationID: companyIDFilter,
// 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 {
// var errMsg string
// for field, msg := range valErrs {
// errMsg += fmt.Sprintf("%s: %s; ", field, msg)
// }
// h.mongoLoggerSvc.Info("invalid filter values in GetAllAdmins request",
// zap.Int("status_code", fiber.StatusBadRequest),
// zap.Any("validation_errors", valErrs),
// zap.Time("timestamp", time.Now()),
// )
// return fiber.NewError(fiber.StatusBadRequest, errMsg)
// }
// users, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
// if err != nil {
// h.mongoLoggerSvc.Error("failed to get users from user service",
// zap.Int("status_code", fiber.StatusInternalServerError),
// zap.Any("filter", filter),
// zap.Error(err),
// zap.Time("timestamp", time.Now()),
// )
// return fiber.NewError(fiber.StatusInternalServerError, "Failed to get users"+err.Error())
// }
// result := make([]TransactionApproverRes, len(users))
// for index, admin := range users {
// lastLogin, err := h.authSvc.GetLastLogin(c.Context(), admin.ID)
// if err != nil {
// if err == authentication.ErrRefreshTokenNotFound {
// lastLogin = &admin.CreatedAt
// } else {
// h.mongoLoggerSvc.Error("failed to get last login for admin",
// zap.Int("status_code", fiber.StatusInternalServerError),
// zap.Int64("admin_id", admin.ID),
// zap.Error(err),
// zap.Time("timestamp", time.Now()),
// )
// return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login"+err.Error())
// }
// }
// result[index] = TransactionApproverRes{
// ID: admin.ID,
// FirstName: admin.FirstName,
// LastName: admin.LastName,
// Email: admin.Email,
// PhoneNumber: admin.PhoneNumber,
// Role: admin.Role,
// EmailVerified: admin.EmailVerified,
// PhoneVerified: admin.PhoneVerified,
// CreatedAt: admin.CreatedAt,
// UpdatedAt: admin.UpdatedAt,
// SuspendedAt: admin.SuspendedAt,
// Suspended: admin.Suspended,
// LastLogin: *lastLogin,
// }
// }
// h.mongoLoggerSvc.Info("approvers retrieved successfully",
// zap.Int("status_code", fiber.StatusOK),
// zap.Int("count", len(result)),
// zap.Int("page", filter.Page.Value+1),
// zap.Time("timestamp", time.Now()),
// )
// return response.WritePaginatedJSON(c, fiber.StatusOK, "Admins retrieved successfully", result, nil, filter.Page.Value, int(total))
// }
// GetAdminByID godoc
// @Summary Get admin by id
// @Description Get a single admin by id
// @Tags admin
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {object} AdminRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/t-approver/{id} [get]
func (h *Handler) GetTransactionApproverByID(c *fiber.Ctx) error {
userIDstr := c.Params("id")
userID, err := strconv.ParseInt(userIDstr, 10, 64)
if err != nil {
h.mongoLoggerSvc.Error("invalid admin ID param",
zap.Int("status_code", fiber.StatusBadRequest),
zap.String("param", userIDstr),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid admin ID")
}
user, err := h.userSvc.GetUserByID(c.Context(), userID)
if err != nil {
h.mongoLoggerSvc.Error("failed to fetch admin by ID",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Int64("admin_id", userID),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get admin"+err.Error())
}
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
if err != nil && err != authentication.ErrRefreshTokenNotFound {
h.mongoLoggerSvc.Error("failed to get admin last login",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Int64("admin_id", user.ID),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
}
if err == authentication.ErrRefreshTokenNotFound {
lastLogin = &user.CreatedAt
}
res := TransactionApproverRes{
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,
// SuspendedAt: user.SuspendedAt,
// Suspended: user.Suspended,
LastLogin: *lastLogin,
}
h.mongoLoggerSvc.Info("admin retrieved successfully",
zap.Int("status_code", fiber.StatusOK),
zap.Int64("admin_id", user.ID),
zap.Time("timestamp", time.Now()),
)
return response.WriteJSON(c, fiber.StatusOK, "Admin retrieved successfully", res, nil)
}
type updateTransactionApproverReq struct {
FirstName string `json:"first_name" example:"John"`
LastName string `json:"last_name" example:"Doe"`
Suspended bool `json:"suspended" example:"false"`
}
// UpdateAdmin godoc
// @Summary Update Admin
// @Description Update Admin
// @Tags admin
// @Accept json
// @Produce json
// @Param admin body updateAdminReq true "Update Admin"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/t-approver/{id} [put]
func (h *Handler) UpdateTransactionApprover(c *fiber.Ctx) error {
var req updateTransactionApproverReq
if err := c.BodyParser(&req); err != nil {
h.mongoLoggerSvc.Error("UpdateTransactionApprover failed - invalid request body",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body: "+err.Error())
}
if valErrs, ok := h.validator.Validate(c, req); !ok {
var errMsg string
for field, msg := range valErrs {
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
}
h.mongoLoggerSvc.Error("UpdateTransactionApprover failed - validation errors",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Any("validation_errors", valErrs),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
approverIDStr := c.Params("id")
approverID, err := strconv.ParseInt(approverIDStr, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("UpdateTransactionApprover failed - invalid approver ID",
zap.Int("status_code", fiber.StatusBadRequest),
zap.String("approver_id_param", approverIDStr),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid approver ID")
}
updateReq := domain.UpdateUserReq{
UserID: approverID,
FirstName: domain.ValidString{
Value: req.FirstName,
Valid: req.FirstName != "",
},
LastName: domain.ValidString{
Value: req.LastName,
Valid: req.LastName != "",
},
}
err = h.userSvc.UpdateUser(c.Context(), updateReq)
if err != nil {
h.mongoLoggerSvc.Error("UpdateTransactionApprover failed - user service error",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Int64("approver_id", approverID),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update approver: "+err.Error())
}
h.mongoLoggerSvc.Info("UpdateTransactionApprover succeeded",
zap.Int("status_code", fiber.StatusOK),
zap.Int64("approver_id", approverID),
zap.Time("timestamp", time.Now()),
)
return response.WriteJSON(c, fiber.StatusOK, "Transaction approver updated successfully", nil, nil)
}