303 lines
8.7 KiB
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
|
|
}
|