671 lines
22 KiB
Go
671 lines
22 KiB
Go
package service
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"netidhub-saas-be/app/database/entity"
|
|
"netidhub-saas-be/app/module/clients/mapper"
|
|
"netidhub-saas-be/app/module/clients/repository"
|
|
"netidhub-saas-be/app/module/clients/request"
|
|
"netidhub-saas-be/app/module/clients/response"
|
|
usersRepository "netidhub-saas-be/app/module/users/repository"
|
|
usersRequest "netidhub-saas-be/app/module/users/request"
|
|
usersService "netidhub-saas-be/app/module/users/service"
|
|
"netidhub-saas-be/utils/paginator"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/google/uuid"
|
|
"github.com/rs/zerolog"
|
|
|
|
config "netidhub-saas-be/config/config"
|
|
utilSvc "netidhub-saas-be/utils/service"
|
|
)
|
|
|
|
// ClientsService
|
|
type clientsService struct {
|
|
Repo repository.ClientsRepository
|
|
Cfg *config.Config
|
|
UsersRepo usersRepository.UsersRepository
|
|
UsersSvc usersService.UsersService
|
|
ClientLogoUploadSvc *ClientLogoUploadService
|
|
Log zerolog.Logger
|
|
}
|
|
|
|
// ClientsService define interface of IClientsService
|
|
type ClientsService interface {
|
|
All(authToken string, req request.ClientsQueryRequest) (clients []*response.ClientsResponse, paging paginator.Pagination, err error)
|
|
Show(id uuid.UUID) (clients *response.ClientsResponse, err error)
|
|
CheckClientNameExists(name string) (exists bool, err error)
|
|
ShowWithAuth(authToken string) (clients *response.ClientsResponse, err error)
|
|
Save(req request.ClientsCreateRequest, authToken string) (clients *entity.Clients, err error)
|
|
Update(id uuid.UUID, req request.ClientsUpdateRequest) (err error)
|
|
UpdateWithAuth(authToken string, req request.ClientsUpdateRequest) (err error)
|
|
Delete(id uuid.UUID) error
|
|
|
|
// New hierarchy methods
|
|
CreateSubClient(parentId uuid.UUID, req request.ClientsCreateRequest) (*entity.Clients, error)
|
|
MoveClient(clientId uuid.UUID, req request.MoveClientRequest) error
|
|
GetHierarchy(clientId uuid.UUID) (*response.ClientHierarchyResponse, error)
|
|
GetClientStats(clientId uuid.UUID) (*response.ClientStatsResponse, error)
|
|
BulkCreateSubClients(req request.BulkCreateSubClientsRequest) (*response.BulkOperationResponse, error)
|
|
|
|
// Client with user creation
|
|
CreateClientWithUser(req request.ClientWithUserCreateRequest) (*response.ClientWithUserResponse, error)
|
|
|
|
// Logo upload methods
|
|
UploadLogo(authToken string, c *fiber.Ctx) (string, error)
|
|
DeleteLogo(clientId uuid.UUID, imagePath string) error
|
|
GetLogoURL(imagePath string) (string, error)
|
|
ViewLogo(filename string) ([]byte, string, error)
|
|
}
|
|
|
|
// NewClientsService init ClientsService
|
|
func NewClientsService(repo repository.ClientsRepository, cfg *config.Config, log zerolog.Logger, usersRepo usersRepository.UsersRepository, usersSvc usersService.UsersService, clientLogoUploadSvc *ClientLogoUploadService) ClientsService {
|
|
|
|
return &clientsService{
|
|
Repo: repo,
|
|
Cfg: cfg,
|
|
Log: log,
|
|
UsersRepo: usersRepo,
|
|
UsersSvc: usersSvc,
|
|
ClientLogoUploadSvc: clientLogoUploadSvc,
|
|
}
|
|
}
|
|
|
|
// All implement interface of ClientsService
|
|
func (_i *clientsService) All(authToken string, req request.ClientsQueryRequest) (clientss []*response.ClientsResponse, paging paginator.Pagination, err error) {
|
|
// Extract clientId from authToken
|
|
var clientId *uuid.UUID
|
|
if authToken != "" {
|
|
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
|
|
if user != nil && user.ClientId != nil {
|
|
clientId = user.ClientId
|
|
_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
|
|
}
|
|
}
|
|
|
|
results, paging, err := _i.Repo.GetAll(req)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
for _, result := range results {
|
|
clientss = append(clientss, mapper.ClientsResponseMapper(result))
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (_i *clientsService) Show(id uuid.UUID) (clients *response.ClientsResponse, err error) {
|
|
result, err := _i.Repo.FindOne(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return mapper.ClientsResponseMapper(result), nil
|
|
}
|
|
|
|
func (_i *clientsService) CheckClientNameExists(name string) (exists bool, err error) {
|
|
_i.Log.Info().Str("name", name).Msg("Checking if client name exists")
|
|
|
|
// Check if client name exists in repository
|
|
result, err := _i.Repo.FindByName(name)
|
|
if err != nil {
|
|
// If error is "record not found", name doesn't exist
|
|
if strings.Contains(err.Error(), "record not found") {
|
|
return false, nil
|
|
}
|
|
_i.Log.Error().Err(err).Str("name", name).Msg("Failed to check client name existence")
|
|
return false, err
|
|
}
|
|
|
|
// If result is not nil, name exists
|
|
if result != nil {
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func (_i *clientsService) ShowWithAuth(authToken string) (clients *response.ClientsResponse, err error) {
|
|
// Extract clientId from authToken
|
|
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
|
|
if user == nil {
|
|
_i.Log.Error().Msg("User not found from auth token")
|
|
return nil, fmt.Errorf("user not found")
|
|
}
|
|
|
|
if user.ClientId == nil {
|
|
_i.Log.Error().Msg("Client ID not found in user token")
|
|
return nil, fmt.Errorf("client ID not found in user token")
|
|
}
|
|
|
|
clientId := *user.ClientId
|
|
_i.Log.Info().Str("clientId", clientId.String()).Msg("Getting client details with auth token")
|
|
|
|
result, err := _i.Repo.FindOne(clientId)
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Str("clientId", clientId.String()).Msg("Failed to find client")
|
|
return nil, err
|
|
}
|
|
|
|
return mapper.ClientsResponseMapper(result), nil
|
|
}
|
|
|
|
func (_i *clientsService) Save(req request.ClientsCreateRequest, authToken string) (clients *entity.Clients, err error) {
|
|
_i.Log.Info().Interface("data", req).Msg("")
|
|
|
|
// Generate slug from client name
|
|
slug := utilSvc.MakeSlug(req.Name)
|
|
|
|
// Convert request to entity
|
|
newReq := &entity.Clients{
|
|
Name: req.Name,
|
|
Slug: slug,
|
|
Description: req.Description,
|
|
ClientType: req.ClientType,
|
|
ParentClientId: req.ParentClientId,
|
|
MaxUsers: req.MaxUsers,
|
|
MaxStorage: req.MaxStorage,
|
|
Settings: req.Settings,
|
|
}
|
|
|
|
_i.Log.Info().Interface("token", authToken).Msg("")
|
|
createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
|
|
_i.Log.Info().Interface("token", authToken).Msg("")
|
|
newReq.CreatedById = &createdBy.ID
|
|
|
|
newReq.ID = uuid.New()
|
|
|
|
_i.Log.Info().Interface("new data", newReq).Msg("")
|
|
|
|
return _i.Repo.Create(newReq)
|
|
}
|
|
|
|
func (_i *clientsService) Update(id uuid.UUID, req request.ClientsUpdateRequest) (err error) {
|
|
_i.Log.Info().Interface("data", req).Msg("")
|
|
|
|
// Convert request to entity
|
|
updateReq := &entity.Clients{
|
|
Name: *req.Name,
|
|
Description: req.Description,
|
|
ClientType: *req.ClientType,
|
|
ParentClientId: req.ParentClientId,
|
|
LogoUrl: req.LogoUrl,
|
|
LogoImagePath: req.LogoImagePath,
|
|
Address: req.Address,
|
|
PhoneNumber: req.PhoneNumber,
|
|
Website: req.Website,
|
|
MaxUsers: req.MaxUsers,
|
|
MaxStorage: req.MaxStorage,
|
|
Settings: req.Settings,
|
|
IsActive: req.IsActive,
|
|
}
|
|
|
|
return _i.Repo.Update(id, updateReq)
|
|
}
|
|
|
|
func (_i *clientsService) UpdateWithAuth(authToken string, req request.ClientsUpdateRequest) (err error) {
|
|
_i.Log.Info().Interface("data", req).Msg("")
|
|
|
|
// Extract clientId from authToken
|
|
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
|
|
if user == nil {
|
|
_i.Log.Error().Msg("User not found from auth token")
|
|
return fmt.Errorf("user not found")
|
|
}
|
|
|
|
if user.ClientId == nil {
|
|
_i.Log.Error().Msg("Client ID not found in user token")
|
|
return fmt.Errorf("client ID not found in user token")
|
|
}
|
|
|
|
clientId := *user.ClientId
|
|
_i.Log.Info().Str("clientId", clientId.String()).Msg("Updating client with auth token")
|
|
|
|
// Convert request to entity
|
|
updateReq := &entity.Clients{
|
|
Name: *req.Name,
|
|
Description: req.Description,
|
|
ParentClientId: req.ParentClientId,
|
|
LogoUrl: req.LogoUrl,
|
|
LogoImagePath: req.LogoImagePath,
|
|
Address: req.Address,
|
|
PhoneNumber: req.PhoneNumber,
|
|
Website: req.Website,
|
|
MaxUsers: req.MaxUsers,
|
|
MaxStorage: req.MaxStorage,
|
|
Settings: req.Settings,
|
|
IsActive: req.IsActive,
|
|
}
|
|
|
|
_i.Log.Info().Interface("Updating client with auth token", updateReq).Msg("")
|
|
|
|
return _i.Repo.Update(clientId, updateReq)
|
|
}
|
|
|
|
func (_i *clientsService) Delete(id uuid.UUID) error {
|
|
result, err := _i.Repo.FindOne(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
isActive := false
|
|
result.IsActive = &isActive
|
|
return _i.Repo.Update(id, result)
|
|
}
|
|
|
|
// =====================================================================
|
|
// NEW HIERARCHY METHODS
|
|
// =====================================================================
|
|
|
|
// CreateSubClient creates a client under a parent
|
|
func (_i *clientsService) CreateSubClient(parentId uuid.UUID, req request.ClientsCreateRequest) (*entity.Clients, error) {
|
|
// Validate parent exists
|
|
_, err := _i.Repo.FindOne(parentId)
|
|
if err != nil {
|
|
return nil, errors.New("parent client not found")
|
|
}
|
|
|
|
// Set client type and parent
|
|
req.ClientType = "sub_client"
|
|
req.ParentClientId = &parentId
|
|
|
|
// Generate slug from client name
|
|
slug := utilSvc.MakeSlug(req.Name)
|
|
|
|
// Convert to entity
|
|
newReq := &entity.Clients{
|
|
Name: req.Name,
|
|
Slug: slug,
|
|
Description: req.Description,
|
|
ClientType: req.ClientType,
|
|
ParentClientId: req.ParentClientId,
|
|
MaxUsers: req.MaxUsers,
|
|
MaxStorage: req.MaxStorage,
|
|
Settings: req.Settings,
|
|
}
|
|
|
|
newReq.ID = uuid.New()
|
|
|
|
return _i.Repo.Create(newReq)
|
|
}
|
|
|
|
// MoveClient moves a client to different parent
|
|
func (_i *clientsService) MoveClient(clientId uuid.UUID, req request.MoveClientRequest) error {
|
|
client, err := _i.Repo.FindOne(clientId)
|
|
if err != nil {
|
|
return errors.New("client not found")
|
|
}
|
|
|
|
// If moving to root (standalone)
|
|
if req.TargetParentId == nil {
|
|
client.ClientType = "standalone"
|
|
client.ParentClientId = nil
|
|
return _i.Repo.Update(clientId, client)
|
|
}
|
|
|
|
// Validate target parent exists
|
|
_, err = _i.Repo.FindOne(*req.TargetParentId)
|
|
if err != nil {
|
|
return errors.New("target parent not found")
|
|
}
|
|
|
|
// Move
|
|
return _i.Repo.MoveClient(clientId, *req.TargetParentId)
|
|
}
|
|
|
|
// GetHierarchy gets full client tree
|
|
func (_i *clientsService) GetHierarchy(clientId uuid.UUID) (*response.ClientHierarchyResponse, error) {
|
|
client, err := _i.Repo.GetWithHierarchy(clientId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return _i.buildHierarchyResponse(client, 0, []string{}), nil
|
|
}
|
|
|
|
// buildHierarchyResponse recursively builds hierarchy
|
|
func (_i *clientsService) buildHierarchyResponse(client *entity.Clients, level int, path []string) *response.ClientHierarchyResponse {
|
|
currentPath := append(path, client.Name)
|
|
|
|
resp := &response.ClientHierarchyResponse{
|
|
ID: client.ID,
|
|
Name: client.Name,
|
|
Slug: client.Slug,
|
|
Description: client.Description,
|
|
ClientType: client.ClientType,
|
|
Level: level,
|
|
Path: currentPath,
|
|
ParentClientId: client.ParentClientId,
|
|
LogoUrl: client.LogoUrl,
|
|
LogoImagePath: client.LogoImagePath,
|
|
Address: client.Address,
|
|
PhoneNumber: client.PhoneNumber,
|
|
Website: client.Website,
|
|
IsActive: client.IsActive,
|
|
}
|
|
|
|
// Count users (simplified - would need proper DB access)
|
|
resp.CurrentUsers = 0 // TODO: implement user count
|
|
|
|
// Build sub-clients recursively
|
|
if client.SubClients != nil {
|
|
for _, subClient := range client.SubClients {
|
|
resp.SubClients = append(resp.SubClients,
|
|
*_i.buildHierarchyResponse(&subClient, level+1, currentPath))
|
|
}
|
|
}
|
|
|
|
return resp
|
|
}
|
|
|
|
// GetClientStats gets comprehensive statistics
|
|
func (_i *clientsService) GetClientStats(clientId uuid.UUID) (*response.ClientStatsResponse, error) {
|
|
client, err := _i.Repo.FindOne(clientId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
stats, err := _i.Repo.GetClientStats(clientId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
isParent, _ := _i.Repo.IsParentClient(clientId)
|
|
|
|
return &response.ClientStatsResponse{
|
|
ClientId: client.ID,
|
|
ClientName: client.Name,
|
|
TotalUsers: stats["total_users"].(int),
|
|
TotalArticles: stats["total_articles"].(int),
|
|
SubClientCount: stats["sub_client_count"].(int),
|
|
IsParent: isParent,
|
|
}, nil
|
|
}
|
|
|
|
// BulkCreateSubClients creates multiple sub-clients
|
|
func (_i *clientsService) BulkCreateSubClients(req request.BulkCreateSubClientsRequest) (*response.BulkOperationResponse, error) {
|
|
results := []response.BulkOperationResult{}
|
|
successful := 0
|
|
failed := 0
|
|
|
|
for i, subClientReq := range req.SubClients {
|
|
createReq := request.ClientsCreateRequest{
|
|
Name: subClientReq.Name,
|
|
Description: subClientReq.Description,
|
|
ClientType: "sub_client",
|
|
ParentClientId: &req.ParentClientId,
|
|
MaxUsers: subClientReq.MaxUsers,
|
|
MaxStorage: subClientReq.MaxStorage,
|
|
}
|
|
|
|
client, err := _i.CreateSubClient(req.ParentClientId, createReq)
|
|
if err != nil {
|
|
failed++
|
|
errMsg := err.Error()
|
|
results = append(results, response.BulkOperationResult{
|
|
Index: i,
|
|
Name: subClientReq.Name,
|
|
Success: false,
|
|
Error: &errMsg,
|
|
})
|
|
} else {
|
|
successful++
|
|
results = append(results, response.BulkOperationResult{
|
|
Index: i,
|
|
ClientId: &client.ID,
|
|
Name: client.Name,
|
|
Success: true,
|
|
})
|
|
}
|
|
}
|
|
|
|
return &response.BulkOperationResponse{
|
|
TotalRequested: len(req.SubClients),
|
|
Successful: successful,
|
|
Failed: failed,
|
|
Results: results,
|
|
}, nil
|
|
}
|
|
|
|
// CreateClientWithUser creates a client and admin user in one transaction
|
|
func (_i *clientsService) CreateClientWithUser(req request.ClientWithUserCreateRequest) (*response.ClientWithUserResponse, error) {
|
|
_i.Log.Info().Interface("data", req).Msg("Creating client with admin user (Public endpoint)")
|
|
|
|
// Step 1: Create the client
|
|
clientReq := req.Client
|
|
|
|
// Generate slug from client name
|
|
slug := utilSvc.MakeSlug(clientReq.Name)
|
|
|
|
newClient := &entity.Clients{
|
|
Name: clientReq.Name,
|
|
Slug: slug,
|
|
Description: clientReq.Description,
|
|
ClientType: clientReq.ClientType,
|
|
ParentClientId: clientReq.ParentClientId,
|
|
MaxUsers: clientReq.MaxUsers,
|
|
MaxStorage: clientReq.MaxStorage,
|
|
Settings: clientReq.Settings,
|
|
}
|
|
|
|
// Generate new UUID for client
|
|
newClient.ID = uuid.New()
|
|
|
|
// For public endpoint, no created by user
|
|
newClient.CreatedById = nil
|
|
|
|
// Create client
|
|
createdClient, err := _i.Repo.Create(newClient)
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Msg("Failed to create client")
|
|
return nil, fmt.Errorf("failed to create client: %w", err)
|
|
}
|
|
|
|
_i.Log.Info().Interface("clientId", createdClient.ID).Msg("Client created successfully")
|
|
|
|
// Step 2: Create admin user for the client
|
|
adminUserReq := req.AdminUser
|
|
|
|
// Convert to UsersCreateRequest format
|
|
userCreateReq := usersRequest.UsersCreateRequest{
|
|
Username: adminUserReq.Username,
|
|
Email: adminUserReq.Email,
|
|
Fullname: adminUserReq.Fullname,
|
|
Password: adminUserReq.Password,
|
|
PhoneNumber: adminUserReq.PhoneNumber,
|
|
Address: adminUserReq.Address,
|
|
WorkType: adminUserReq.WorkType,
|
|
GenderType: adminUserReq.GenderType,
|
|
IdentityType: adminUserReq.IdentityType,
|
|
IdentityGroup: adminUserReq.IdentityGroup,
|
|
IdentityGroupNumber: adminUserReq.IdentityGroupNumber,
|
|
IdentityNumber: adminUserReq.IdentityNumber,
|
|
DateOfBirth: adminUserReq.DateOfBirth,
|
|
LastEducation: adminUserReq.LastEducation,
|
|
ClientId: &createdClient.ID,
|
|
// Set default admin level and role (you may need to adjust these based on your system)
|
|
UserLevelId: 1, // Assuming level 1 is generic level
|
|
UserRoleId: 2, // Assuming role 1 is admin client role
|
|
}
|
|
|
|
// Create user with the new client ID
|
|
createdUser, err := _i.UsersSvc.Save("", userCreateReq)
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Msg("Failed to create admin user")
|
|
// Rollback: delete the created client
|
|
_i.Repo.Delete(createdClient.ID)
|
|
return nil, fmt.Errorf("failed to create admin user: %w", err)
|
|
}
|
|
|
|
_i.Log.Info().Interface("userId", createdUser.ID).Msg("Admin user created successfully")
|
|
_i.Log.Info().Interface("createdClient", createdClient).Msg("Created Client")
|
|
|
|
// Step 3: Prepare response
|
|
clientResponse := mapper.ClientsResponseMapper(createdClient)
|
|
|
|
adminUserResponse := response.AdminUserResponse{
|
|
ID: createdUser.ID,
|
|
Username: createdUser.Username,
|
|
Email: createdUser.Email,
|
|
Fullname: createdUser.Fullname,
|
|
UserLevelId: createdUser.UserLevelId,
|
|
UserRoleId: createdUser.UserRoleId,
|
|
PhoneNumber: createdUser.PhoneNumber,
|
|
Address: createdUser.Address,
|
|
WorkType: createdUser.WorkType,
|
|
GenderType: createdUser.GenderType,
|
|
IdentityType: createdUser.IdentityType,
|
|
IdentityGroup: createdUser.IdentityGroup,
|
|
IdentityGroupNumber: createdUser.IdentityGroupNumber,
|
|
IdentityNumber: createdUser.IdentityNumber,
|
|
DateOfBirth: createdUser.DateOfBirth,
|
|
LastEducation: createdUser.LastEducation,
|
|
KeycloakId: createdUser.KeycloakId,
|
|
ClientId: *createdUser.ClientId,
|
|
IsActive: *createdUser.IsActive,
|
|
CreatedAt: createdUser.CreatedAt,
|
|
UpdatedAt: createdUser.UpdatedAt,
|
|
}
|
|
|
|
return &response.ClientWithUserResponse{
|
|
Client: *clientResponse,
|
|
AdminUser: adminUserResponse,
|
|
Message: fmt.Sprintf("Client '%s' and admin user '%s' created successfully", createdClient.Name, createdUser.Username),
|
|
}, nil
|
|
}
|
|
|
|
// =====================================================================
|
|
// LOGO UPLOAD METHODS
|
|
// =====================================================================
|
|
|
|
// UploadLogo uploads client logo to MinIO
|
|
func (_i *clientsService) UploadLogo(authToken string, c *fiber.Ctx) (string, error) {
|
|
// Extract clientId from authToken
|
|
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
|
|
if user == nil {
|
|
_i.Log.Error().Msg("User not found from auth token")
|
|
return "", fmt.Errorf("user not found")
|
|
}
|
|
|
|
if user.ClientId == nil {
|
|
_i.Log.Error().Msg("Client ID not found in user token")
|
|
return "", fmt.Errorf("client ID not found in user token")
|
|
}
|
|
|
|
clientId := *user.ClientId
|
|
_i.Log.Info().Str("clientId", clientId.String()).Msg("Uploading client logo")
|
|
|
|
// Fetch client data to get client name
|
|
client, err := _i.Repo.FindOne(clientId)
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Str("clientId", clientId.String()).Msg("Failed to fetch client data")
|
|
return "", fmt.Errorf("failed to fetch client data: %w", err)
|
|
}
|
|
|
|
// Upload logo using the upload service
|
|
imagePath, newFilename, err := _i.ClientLogoUploadSvc.UploadLogo(c, clientId.String(), client.Slug)
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Str("clientId", clientId.String()).Msg("Failed to upload client logo")
|
|
return "", err
|
|
}
|
|
|
|
_i.Log.Info().
|
|
Str("Upload imagePath", imagePath).Msg("Client upload logo files")
|
|
|
|
logoUrl := fmt.Sprintf("%s/%s/%s", _i.Cfg.App.Domain, "clients/logo", newFilename)
|
|
|
|
// Update client with new logo image path
|
|
updateReq := request.ClientsUpdateRequest{
|
|
LogoImagePath: &imagePath,
|
|
LogoUrl: &logoUrl,
|
|
}
|
|
|
|
_i.Log.Info().
|
|
Str("Upload Update Request", imagePath).Interface("updateReq ", updateReq).Msg("Client upload logo files")
|
|
|
|
err = _i.Repo.Update(clientId, updateReq.ToEntity())
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Str("clientId", clientId.String()).Str("imagePath", imagePath).Msg("Failed to update client with logo path")
|
|
|
|
// Try to clean up uploaded file
|
|
cleanupErr := _i.ClientLogoUploadSvc.DeleteLogo(clientId.String(), imagePath)
|
|
if cleanupErr != nil {
|
|
_i.Log.Error().Err(cleanupErr).Str("imagePath", imagePath).Msg("Failed to cleanup uploaded logo after update failure")
|
|
}
|
|
|
|
return "", fmt.Errorf("failed to update client with logo path: %w", err)
|
|
}
|
|
|
|
_i.Log.Info().Str("clientId", clientId.String()).Str("imagePath", imagePath).Msg("Client logo uploaded and updated successfully")
|
|
return imagePath, nil
|
|
}
|
|
|
|
// DeleteLogo deletes client logo from MinIO
|
|
func (_i *clientsService) DeleteLogo(clientId uuid.UUID, imagePath string) error {
|
|
_i.Log.Info().Str("clientId", clientId.String()).Str("imagePath", imagePath).Msg("Deleting client logo")
|
|
|
|
err := _i.ClientLogoUploadSvc.DeleteLogo(clientId.String(), imagePath)
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Str("clientId", clientId.String()).Str("imagePath", imagePath).Msg("Failed to delete client logo")
|
|
return err
|
|
}
|
|
|
|
// Clear logo image path from client
|
|
emptyPath := ""
|
|
updateReq := request.ClientsUpdateRequest{
|
|
LogoImagePath: &emptyPath,
|
|
}
|
|
|
|
err = _i.Repo.Update(clientId, updateReq.ToEntity())
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Str("clientId", clientId.String()).Msg("Failed to clear logo path from client")
|
|
return fmt.Errorf("failed to clear logo path from client: %w", err)
|
|
}
|
|
|
|
_i.Log.Info().Str("clientId", clientId.String()).Msg("Client logo deleted successfully")
|
|
return nil
|
|
}
|
|
|
|
// GetLogoURL generates a presigned URL for the logo
|
|
func (_i *clientsService) GetLogoURL(imagePath string) (string, error) {
|
|
if imagePath == "" {
|
|
return "", nil
|
|
}
|
|
|
|
_i.Log.Info().Str("imagePath", imagePath).Msg("Generating logo URL")
|
|
|
|
// Generate presigned URL valid for 24 hours
|
|
url, err := _i.ClientLogoUploadSvc.GetLogoURL(imagePath, 24*time.Hour)
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Str("imagePath", imagePath).Msg("Failed to generate logo URL")
|
|
return "", err
|
|
}
|
|
|
|
_i.Log.Info().Str("imagePath", imagePath).Str("url", url).Msg("Logo URL generated successfully")
|
|
return url, nil
|
|
}
|
|
|
|
// ViewLogo retrieves logo file from MinIO
|
|
func (_i *clientsService) ViewLogo(filename string) ([]byte, string, error) {
|
|
_i.Log.Info().Str("filename", filename).Msg("Retrieving logo file")
|
|
|
|
client, err := _i.Repo.FindByImagePathName(filename)
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Str("filename", filename).Msg("Failed to find client by image path name")
|
|
return nil, "", err
|
|
}
|
|
|
|
data, contentType, err := _i.ClientLogoUploadSvc.GetLogoFile(client.ID.String(), filename)
|
|
if err != nil {
|
|
_i.Log.Error().Err(err).Str("filename", filename).Msg("Failed to retrieve logo file")
|
|
return nil, "", err
|
|
}
|
|
|
|
_i.Log.Info().Str("filename", filename).Str("contentType", contentType).Int("dataSize", len(data)).Msg("Logo file retrieved successfully")
|
|
return data, contentType, nil
|
|
}
|