kontenhumas-be/app/module/clients/service/clients.service.go

303 lines
8.7 KiB
Go

package service
import (
"errors"
"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"
"netidhub-saas-be/utils/paginator"
"github.com/google/uuid"
"github.com/rs/zerolog"
utilSvc "netidhub-saas-be/utils/service"
)
// ClientsService
type clientsService struct {
Repo repository.ClientsRepository
UsersRepo usersRepository.UsersRepository
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)
Save(req request.ClientsCreateRequest, authToken string) (clients *entity.Clients, err error)
Update(id uuid.UUID, 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)
}
// NewClientsService init ClientsService
func NewClientsService(repo repository.ClientsRepository, log zerolog.Logger, usersRepo usersRepository.UsersRepository) ClientsService {
return &clientsService{
Repo: repo,
Log: log,
UsersRepo: usersRepo,
}
}
// 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) Save(req request.ClientsCreateRequest, authToken string) (clients *entity.Clients, err error) {
_i.Log.Info().Interface("data", req).Msg("")
// Convert request to entity
newReq := &entity.Clients{
Name: req.Name,
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,
MaxUsers: req.MaxUsers,
MaxStorage: req.MaxStorage,
Settings: req.Settings,
IsActive: req.IsActive,
}
return _i.Repo.Update(id, 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
// Convert to entity
newReq := &entity.Clients{
Name: req.Name,
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,
Description: client.Description,
ClientType: client.ClientType,
Level: level,
Path: currentPath,
ParentClientId: client.ParentClientId,
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
}