diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7c65760..3a797fd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,4 +30,4 @@ deploy: services: - docker:dind script: - - curl --user $JENKINS_USER:$JENKINS_PWD http://38.47.180.165:8080/job/autodeploy-medols-be/build?token=autodeploymedols \ No newline at end of file + - curl --user $JENKINS_USER:$JENKINS_PWD http://38.47.180.165:8080/job/autodeploy-netidhub-be/build?token=autodeploynetidhub \ No newline at end of file diff --git a/app/database/entity/article_category_details/article_category_details.entity.go b/app/database/entity/article_category_details/article_category_details.entity.go index 6c4fe9e..9eb19d2 100644 --- a/app/database/entity/article_category_details/article_category_details.entity.go +++ b/app/database/entity/article_category_details/article_category_details.entity.go @@ -1,8 +1,8 @@ package article_category_details import ( + entity "netidhub-saas-be/app/database/entity" "time" - entity "web-medols-be/app/database/entity" "github.com/google/uuid" ) diff --git a/app/database/entity/clients.entity.go b/app/database/entity/clients.entity.go new file mode 100644 index 0000000..2c8bc9f --- /dev/null +++ b/app/database/entity/clients.entity.go @@ -0,0 +1,26 @@ +package entity + +import ( + "github.com/google/uuid" + "time" +) + +type Clients struct { + ID uuid.UUID `json:"id" gorm:"primaryKey;type:UUID"` + Name string `json:"name" gorm:"type:varchar"` + Description *string `json:"description" gorm:"type:text"` + ClientType string `json:"client_type" gorm:"type:varchar;default:'sub_client'"` // 'parent_client', 'sub_client', 'standalone' + ParentClientId *uuid.UUID `json:"parent_client_id" gorm:"type:UUID;index"` + ParentClient *Clients `json:"parent_client,omitempty" gorm:"foreignKey:ParentClientId;references:ID"` + SubClients []Clients `json:"sub_clients,omitempty" gorm:"foreignKey:ParentClientId;references:ID"` + + // Metadata + Settings *string `json:"settings" gorm:"type:jsonb"` // JSON for custom settings + MaxUsers *int `json:"max_users" gorm:"type:int4"` // Limit for sub clients + MaxStorage *int64 `json:"max_storage" gorm:"type:int8"` // In bytes + + CreatedById *uint `json:"created_by_id" gorm:"type:int4"` + IsActive *bool `json:"is_active" gorm:"type:bool;default:true"` + CreatedAt time.Time `json:"created_at" gorm:"default:now()"` + UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"` +} diff --git a/app/database/entity/clients.go b/app/database/entity/clients.go deleted file mode 100644 index b4ba2f1..0000000 --- a/app/database/entity/clients.go +++ /dev/null @@ -1,15 +0,0 @@ -package entity - -import ( - "github.com/google/uuid" - "time" -) - -type Clients struct { - ID uuid.UUID `json:"id" gorm:"primaryKey;type:UUID"` - Name string `json:"name" gorm:"type:varchar"` - CreatedById *uint `json:"created_by_id" gorm:"type:int4"` - IsActive *bool `json:"is_active" gorm:"type:bool;default:true"` - CreatedAt time.Time `json:"created_at" gorm:"default:now()"` - UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"` -} diff --git a/app/database/entity/user_client_access.entity.go b/app/database/entity/user_client_access.entity.go new file mode 100644 index 0000000..de63122 --- /dev/null +++ b/app/database/entity/user_client_access.entity.go @@ -0,0 +1,38 @@ +package entity + +import ( + "github.com/google/uuid" + "time" +) + +// UserClientAccess represents many-to-many relationship between Users and Clients +// This allows users to have access to multiple clients (multi-tenant access) +type UserClientAccess struct { + ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"` + UserId uint `json:"user_id" gorm:"type:int4;not null;index:idx_user_client_access"` + ClientId uuid.UUID `json:"client_id" gorm:"type:UUID;not null;index:idx_user_client_access"` + + // Access control + AccessType string `json:"access_type" gorm:"type:varchar;default:'read'"` // 'read', 'write', 'admin', 'owner' + CanManage *bool `json:"can_manage" gorm:"type:bool;default:false"` // Can manage client settings + CanDelegate *bool `json:"can_delegate" gorm:"type:bool;default:false"` // Can give access to other users + + // If user has access to parent, they automatically have access to all sub-clients + IncludeSubClients *bool `json:"include_sub_clients" gorm:"type:bool;default:false"` + + // Relationships + User *Users `json:"user,omitempty" gorm:"foreignKey:UserId;references:ID"` + Client *Clients `json:"client,omitempty" gorm:"foreignKey:ClientId;references:ID"` + + GrantedById *uint `json:"granted_by_id" gorm:"type:int4"` // Who granted this access + GrantedBy *Users `json:"granted_by,omitempty" gorm:"foreignKey:GrantedById;references:ID"` + + IsActive *bool `json:"is_active" gorm:"type:bool;default:true"` + CreatedAt time.Time `json:"created_at" gorm:"default:now()"` + UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"` +} + +// TableName overrides the table name +func (UserClientAccess) TableName() string { + return "user_client_access" +} diff --git a/app/database/entity/users.entity.go b/app/database/entity/users.entity.go index 0b0adf0..9cab6e7 100644 --- a/app/database/entity/users.entity.go +++ b/app/database/entity/users.entity.go @@ -29,7 +29,12 @@ type Users struct { ProfilePicturePath *string `json:"profile_picture_path" gorm:"type:varchar"` TempPassword *string `json:"temp_password" gorm:"type:varchar"` IsEmailUpdated *bool `json:"is_email_updated" gorm:"type:bool;default:false"` - ClientId *uuid.UUID `json:"client_id" gorm:"type:UUID"` + + // Multi-tenant access control + IsSuperAdmin *bool `json:"is_super_admin" gorm:"type:bool;default:false"` // Platform super admin (access all clients) + ClientId *uuid.UUID `json:"client_id" gorm:"type:UUID"` // Primary/default client + ClientAccesses []UserClientAccess `json:"client_accesses,omitempty" gorm:"foreignKey:UserId;references:ID"` // Multiple client access + IsActive *bool `json:"is_active" gorm:"type:bool;default:true"` CreatedAt time.Time `json:"created_at" gorm:"default:now()"` UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"` diff --git a/app/database/entity/users/users.entity.go b/app/database/entity/users/users.entity.go index 0a57dc0..74bb54b 100644 --- a/app/database/entity/users/users.entity.go +++ b/app/database/entity/users/users.entity.go @@ -2,8 +2,8 @@ package users import ( "github.com/google/uuid" + "netidhub-saas-be/app/database/entity" "time" - "web-medols-be/app/database/entity" ) type Users struct { diff --git a/app/database/index.database.go b/app/database/index.database.go index d51ed85..18e4017 100644 --- a/app/database/index.database.go +++ b/app/database/index.database.go @@ -1,9 +1,9 @@ package database import ( - "web-medols-be/app/database/entity" - "web-medols-be/app/database/entity/article_category_details" - "web-medols-be/config/config" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/database/entity/article_category_details" + "netidhub-saas-be/config/config" "github.com/rs/zerolog" "gorm.io/driver/postgres" @@ -122,6 +122,7 @@ func Models() []interface{} { entity.UserRoleAccesses{}, entity.Users{}, entity.UserRoleLevelDetails{}, + entity.UserClientAccess{}, // New: Multi-client access for users } } diff --git a/app/database/seeds/activity_log_types.seeds.go b/app/database/seeds/activity_log_types.seeds.go index df07916..29631aa 100644 --- a/app/database/seeds/activity_log_types.seeds.go +++ b/app/database/seeds/activity_log_types.seeds.go @@ -2,7 +2,7 @@ package seeds import ( "gorm.io/gorm" - "web-medols-be/app/database/entity" + "netidhub-saas-be/app/database/entity" ) type ActivityLogsSeeder struct{} diff --git a/app/database/seeds/approval_workflows.seeds.go b/app/database/seeds/approval_workflows.seeds.go index feb41fb..8a8e51b 100644 --- a/app/database/seeds/approval_workflows.seeds.go +++ b/app/database/seeds/approval_workflows.seeds.go @@ -2,7 +2,7 @@ package seeds import ( "gorm.io/gorm" - "web-medols-be/app/database/entity" + "netidhub-saas-be/app/database/entity" ) type ApprovalWorkflowsSeeder struct{} @@ -109,4 +109,4 @@ func (ApprovalWorkflowsSeeder) Count(conn *gorm.DB) (int, error) { } return int(workflowCount + stepCount), nil -} \ No newline at end of file +} diff --git a/app/database/seeds/master_approval_statuses.seeds.go b/app/database/seeds/master_approval_statuses.seeds.go index f24b40d..fdb8dd5 100644 --- a/app/database/seeds/master_approval_statuses.seeds.go +++ b/app/database/seeds/master_approval_statuses.seeds.go @@ -2,7 +2,7 @@ package seeds import ( "gorm.io/gorm" - "web-medols-be/app/database/entity" + "netidhub-saas-be/app/database/entity" ) type MasterApprovalStatusesSeeder struct{} diff --git a/app/database/seeds/master_statuses.seeds.go b/app/database/seeds/master_statuses.seeds.go index ea04d24..f1ed95d 100644 --- a/app/database/seeds/master_statuses.seeds.go +++ b/app/database/seeds/master_statuses.seeds.go @@ -2,7 +2,7 @@ package seeds import ( "gorm.io/gorm" - "web-medols-be/app/database/entity" + "netidhub-saas-be/app/database/entity" ) type MasterStatusesSeeder struct{} diff --git a/app/database/seeds/no_approval_workflow.seeds.go b/app/database/seeds/no_approval_workflow.seeds.go index d9723ab..469b035 100644 --- a/app/database/seeds/no_approval_workflow.seeds.go +++ b/app/database/seeds/no_approval_workflow.seeds.go @@ -1,7 +1,7 @@ package seeds import ( - "web-medols-be/app/database/entity" + "netidhub-saas-be/app/database/entity" "github.com/google/uuid" ) @@ -13,8 +13,8 @@ func CreateNoApprovalWorkflow() *entity.ApprovalWorkflows { Description: &[]string{"Workflow for clients that don't require approval process"}[0], IsDefault: &[]bool{false}[0], IsActive: &[]bool{true}[0], - RequiresApproval: &[]bool{false}[0], // This is the key field - AutoPublish: &[]bool{true}[0], // Auto publish articles + RequiresApproval: &[]bool{false}[0], // This is the key field + AutoPublish: &[]bool{true}[0], // Auto publish articles Steps: []entity.ApprovalWorkflowSteps{}, // No steps needed } } @@ -23,14 +23,14 @@ func CreateNoApprovalWorkflow() *entity.ApprovalWorkflows { func CreateClientApprovalSettings(clientId string, requiresApproval bool) *entity.ClientApprovalSettings { clientUUID, _ := uuid.Parse(clientId) return &entity.ClientApprovalSettings{ - ClientId: clientUUID, - RequiresApproval: &[]bool{requiresApproval}[0], - AutoPublishArticles: &[]bool{!requiresApproval}[0], // Auto publish if no approval needed - IsActive: &[]bool{true}[0], - ApprovalExemptUsers: []uint{}, - ApprovalExemptRoles: []uint{}, + ClientId: clientUUID, + RequiresApproval: &[]bool{requiresApproval}[0], + AutoPublishArticles: &[]bool{!requiresApproval}[0], // Auto publish if no approval needed + IsActive: &[]bool{true}[0], + ApprovalExemptUsers: []uint{}, + ApprovalExemptRoles: []uint{}, ApprovalExemptCategories: []uint{}, - RequireApprovalFor: []string{}, - SkipApprovalFor: []string{}, + RequireApprovalFor: []string{}, + SkipApprovalFor: []string{}, } } diff --git a/app/middleware/audit_trails.middleware.go b/app/middleware/audit_trails.middleware.go index bc3972b..a985fb0 100644 --- a/app/middleware/audit_trails.middleware.go +++ b/app/middleware/audit_trails.middleware.go @@ -5,10 +5,10 @@ import ( "github.com/gofiber/fiber/v2" "gorm.io/gorm" "log" + "netidhub-saas-be/app/database/entity" + utilSvc "netidhub-saas-be/utils/service" "strings" "time" - "web-medols-be/app/database/entity" - utilSvc "web-medols-be/utils/service" ) func AuditTrailsMiddleware(db *gorm.DB) fiber.Handler { diff --git a/app/middleware/client.middleware.go b/app/middleware/client.middleware.go index e7ce610..4c8c25f 100644 --- a/app/middleware/client.middleware.go +++ b/app/middleware/client.middleware.go @@ -1,8 +1,9 @@ package middleware import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/client" "strings" - "web-medols-be/app/database/entity" "github.com/gofiber/fiber/v2" "github.com/google/uuid" @@ -10,8 +11,12 @@ import ( ) const ( - ClientKeyHeader = "X-Client-Key" - ClientContextKey = "client_id" + ClientKeyHeader = "X-Client-Key" + ClientContextKey = "client_id" + UserIDContextKey = "user_id" + IsSuperAdminContextKey = "is_super_admin" + AccessibleClientIDsKey = "accessible_client_ids" + CurrentClientIDKey = "current_client_id" ) // excludedPaths contains paths that don't require client key validation @@ -57,6 +62,7 @@ func isPathExcluded(path string) bool { } // ClientMiddleware extracts and validates the Client Key from request headers +// Enhanced to support multi-client access and super admin func ClientMiddleware(db *gorm.DB) fiber.Handler { return func(c *fiber.Ctx) error { // Check if path should be excluded from client key validation @@ -64,19 +70,65 @@ func ClientMiddleware(db *gorm.DB) fiber.Handler { return c.Next() } - // Extract Client Key from header - clientKey := c.Get(ClientKeyHeader) - - if clientKey == "" { - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ - "success": false, - "code": 400, - "messages": []string{"Client Key is required in header: " + ClientKeyHeader}, - }) + // Check if user ID exists in context (set by auth middleware) + userID := c.Locals(UserIDContextKey) + if userID != nil { + // User authenticated - use multi-client logic + return handleAuthenticatedUser(c, db, userID) } - // Parse UUID - clientUUID, err := uuid.Parse(clientKey) + // Fallback to X-Client-Key validation (backward compatibility) + return handleClientKeyValidation(c, db) + } +} + +// handleAuthenticatedUser handles request from authenticated users +func handleAuthenticatedUser(c *fiber.Ctx, db *gorm.DB, userID interface{}) error { + userId, ok := userID.(uint) + if !ok { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ + "success": false, + "code": 401, + "messages": []string{"Invalid user ID in context"}, + }) + } + + // Get user details + var user entity.Users + if err := db.Select("id, is_super_admin, client_id"). + Where("id = ?", userId). + First(&user).Error; err != nil { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ + "success": false, + "code": 401, + "messages": []string{"User not found"}, + }) + } + + // Store super admin status + isSuperAdmin := user.IsSuperAdmin != nil && *user.IsSuperAdmin + c.Locals(IsSuperAdminContextKey, isSuperAdmin) + + // Get accessible client IDs for this user + accessibleClientIDs, err := client.GetAccessibleClientIDs(db, userId, isSuperAdmin) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "success": false, + "code": 500, + "messages": []string{"Error retrieving client access"}, + }) + } + + // Store accessible client IDs in context + c.Locals(AccessibleClientIDsKey, accessibleClientIDs) + + // Determine current client ID (from header or user's primary client) + var currentClientID *uuid.UUID + clientKeyHeader := c.Get(ClientKeyHeader) + + if clientKeyHeader != "" { + // User specified a client via header + clientUUID, err := uuid.Parse(clientKeyHeader) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "success": false, @@ -85,31 +137,75 @@ func ClientMiddleware(db *gorm.DB) fiber.Handler { }) } - // Validate client exists and is active - var client entity.Clients - if err := db.Where("id = ? AND is_active = ?", clientUUID, true).First(&client).Error; err != nil { - if err == gorm.ErrRecordNotFound { - return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ - "success": false, - "code": 401, - "messages": []string{"Invalid or inactive Client Key"}, - }) - } - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + // Verify user has access to this client + hasAccess, err := client.HasAccessToClient(db, userId, clientUUID, isSuperAdmin) + if err != nil || !hasAccess { + return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ "success": false, - "code": 500, - "messages": []string{"Error validating Client Key"}, + "code": 403, + "messages": []string{"Access denied to this client"}, }) } - // Store client ID in context for use in handlers - c.Locals(ClientContextKey, clientUUID) - - return c.Next() + currentClientID = &clientUUID + } else if user.ClientId != nil { + // Use user's primary client + currentClientID = user.ClientId } + + // Store current client ID + if currentClientID != nil { + c.Locals(CurrentClientIDKey, *currentClientID) + c.Locals(ClientContextKey, *currentClientID) // Backward compatibility + } + + return c.Next() } -// GetClientID retrieves the client ID from the context +// handleClientKeyValidation validates X-Client-Key header (backward compatibility) +func handleClientKeyValidation(c *fiber.Ctx, db *gorm.DB) error { + clientKey := c.Get(ClientKeyHeader) + + if clientKey == "" { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "success": false, + "code": 400, + "messages": []string{"Client Key is required in header: " + ClientKeyHeader}, + }) + } + + clientUUID, err := uuid.Parse(clientKey) + if err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "success": false, + "code": 400, + "messages": []string{"Invalid Client Key format"}, + }) + } + + var clientEntity entity.Clients + if err := db.Where("id = ? AND is_active = ?", clientUUID, true).First(&clientEntity).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ + "success": false, + "code": 401, + "messages": []string{"Invalid or inactive Client Key"}, + }) + } + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "success": false, + "code": 500, + "messages": []string{"Error validating Client Key"}, + }) + } + + c.Locals(ClientContextKey, clientUUID) + c.Locals(CurrentClientIDKey, clientUUID) + + return c.Next() +} + +// GetClientID retrieves the client ID from the context (backward compatibility) func GetClientID(c *fiber.Ctx) *uuid.UUID { if clientID, ok := c.Locals(ClientContextKey).(uuid.UUID); ok { return &clientID @@ -117,6 +213,30 @@ func GetClientID(c *fiber.Ctx) *uuid.UUID { return nil } +// GetAccessibleClientIDs retrieves all accessible client IDs from context +func GetAccessibleClientIDs(c *fiber.Ctx) []uuid.UUID { + if clientIDs, ok := c.Locals(AccessibleClientIDsKey).([]uuid.UUID); ok { + return clientIDs + } + return nil // nil = super admin or no restriction +} + +// GetCurrentClientID retrieves the current working client ID from context +func GetCurrentClientID(c *fiber.Ctx) *uuid.UUID { + if clientID, ok := c.Locals(CurrentClientIDKey).(uuid.UUID); ok { + return &clientID + } + return nil +} + +// IsSuperAdmin checks if the current user is a super admin +func IsSuperAdmin(c *fiber.Ctx) bool { + if isSuperAdmin, ok := c.Locals(IsSuperAdminContextKey).(bool); ok { + return isSuperAdmin + } + return false +} + // AddExcludedPath adds a new path to the excluded paths list func AddExcludedPath(path string) { excludedPaths = append(excludedPaths, path) diff --git a/app/middleware/csrf.middleware.go b/app/middleware/csrf.middleware.go index def2d69..2015846 100644 --- a/app/middleware/csrf.middleware.go +++ b/app/middleware/csrf.middleware.go @@ -3,8 +3,8 @@ package middleware import ( "fmt" "gorm.io/gorm" + "netidhub-saas-be/app/database/entity" "time" - "web-medols-be/app/database/entity" ) type PostgresStorage struct { diff --git a/app/middleware/register.middleware.go b/app/middleware/register.middleware.go index 3b8a1ba..2fa1c49 100644 --- a/app/middleware/register.middleware.go +++ b/app/middleware/register.middleware.go @@ -2,10 +2,10 @@ package middleware import ( "log" + "netidhub-saas-be/app/database" + "netidhub-saas-be/config/config" + utilsSvc "netidhub-saas-be/utils" "time" - "web-medols-be/app/database" - "web-medols-be/config/config" - utilsSvc "web-medols-be/utils" "github.com/gofiber/fiber/v2/middleware/csrf" "github.com/gofiber/fiber/v2/middleware/session" diff --git a/app/middleware/user.middleware.go b/app/middleware/user.middleware.go index fc521b4..7ee8b14 100644 --- a/app/middleware/user.middleware.go +++ b/app/middleware/user.middleware.go @@ -1,9 +1,9 @@ package middleware import ( - "web-medols-be/app/database/entity/users" - "web-medols-be/app/module/users/repository" - utilSvc "web-medols-be/utils/service" + "netidhub-saas-be/app/database/entity/users" + "netidhub-saas-be/app/module/users/repository" + utilSvc "netidhub-saas-be/utils/service" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/activity_logs/activity_logs.module.go b/app/module/activity_logs/activity_logs.module.go index 442f836..77c70f4 100644 --- a/app/module/activity_logs/activity_logs.module.go +++ b/app/module/activity_logs/activity_logs.module.go @@ -1,9 +1,9 @@ package activity_logs import ( - "web-medols-be/app/module/activity_logs/controller" - "web-medols-be/app/module/activity_logs/repository" - "web-medols-be/app/module/activity_logs/service" + "netidhub-saas-be/app/module/activity_logs/controller" + "netidhub-saas-be/app/module/activity_logs/repository" + "netidhub-saas-be/app/module/activity_logs/service" "github.com/gofiber/fiber/v2" "go.uber.org/fx" diff --git a/app/module/activity_logs/controller/activity_logs.controller.go b/app/module/activity_logs/controller/activity_logs.controller.go index 4e6f4d8..32a5894 100644 --- a/app/module/activity_logs/controller/activity_logs.controller.go +++ b/app/module/activity_logs/controller/activity_logs.controller.go @@ -3,12 +3,12 @@ package controller import ( "strconv" "strings" - "web-medols-be/app/middleware" - "web-medols-be/app/module/activity_logs/request" - "web-medols-be/app/module/activity_logs/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/activity_logs/request" + "netidhub-saas-be/app/module/activity_logs/service" + "netidhub-saas-be/utils/paginator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/activity_logs/controller/controller.go b/app/module/activity_logs/controller/controller.go index b76271c..a644c56 100644 --- a/app/module/activity_logs/controller/controller.go +++ b/app/module/activity_logs/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/activity_logs/service" + "netidhub-saas-be/app/module/activity_logs/service" ) type Controller struct { diff --git a/app/module/activity_logs/mapper/activity_logs.mapper.go b/app/module/activity_logs/mapper/activity_logs.mapper.go index 79a1a3f..7482c78 100644 --- a/app/module/activity_logs/mapper/activity_logs.mapper.go +++ b/app/module/activity_logs/mapper/activity_logs.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/activity_logs/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/activity_logs/response" ) func ActivityLogsResponseMapper(activityLogsReq *entity.ActivityLogs) (activityLogsRes *res.ActivityLogsResponse) { diff --git a/app/module/activity_logs/repository/activity_logs.repository.go b/app/module/activity_logs/repository/activity_logs.repository.go index d0844ba..8d6c817 100644 --- a/app/module/activity_logs/repository/activity_logs.repository.go +++ b/app/module/activity_logs/repository/activity_logs.repository.go @@ -4,12 +4,12 @@ import ( "fmt" "github.com/google/uuid" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/activity_logs/request" + "netidhub-saas-be/utils/paginator" "strings" "time" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/activity_logs/request" - "web-medols-be/utils/paginator" ) type activityLogsRepository struct { diff --git a/app/module/activity_logs/request/activity_logs.request.go b/app/module/activity_logs/request/activity_logs.request.go index 8c540d5..66c477a 100644 --- a/app/module/activity_logs/request/activity_logs.request.go +++ b/app/module/activity_logs/request/activity_logs.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type ActivityLogsGeneric interface { diff --git a/app/module/activity_logs/service/activity_logs.service.go b/app/module/activity_logs/service/activity_logs.service.go index 8e7b5f0..5c25a7a 100644 --- a/app/module/activity_logs/service/activity_logs.service.go +++ b/app/module/activity_logs/service/activity_logs.service.go @@ -3,15 +3,15 @@ package service import ( "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/activity_logs/mapper" - "web-medols-be/app/module/activity_logs/repository" - "web-medols-be/app/module/activity_logs/request" - "web-medols-be/app/module/activity_logs/response" - "web-medols-be/app/module/articles/service" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/activity_logs/mapper" + "netidhub-saas-be/app/module/activity_logs/repository" + "netidhub-saas-be/app/module/activity_logs/request" + "netidhub-saas-be/app/module/activity_logs/response" + "netidhub-saas-be/app/module/articles/service" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" ) // ActivityLogsService diff --git a/app/module/advertisement/advertisement.module.go b/app/module/advertisement/advertisement.module.go index fbf27be..e675b96 100644 --- a/app/module/advertisement/advertisement.module.go +++ b/app/module/advertisement/advertisement.module.go @@ -3,9 +3,9 @@ package advertisement import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/advertisement/controller" - "web-medols-be/app/module/advertisement/repository" - "web-medols-be/app/module/advertisement/service" + "netidhub-saas-be/app/module/advertisement/controller" + "netidhub-saas-be/app/module/advertisement/repository" + "netidhub-saas-be/app/module/advertisement/service" ) // struct of AdvertisementRouter diff --git a/app/module/advertisement/controller/advertisement.controller.go b/app/module/advertisement/controller/advertisement.controller.go index 2ba12ae..0a6d6ac 100644 --- a/app/module/advertisement/controller/advertisement.controller.go +++ b/app/module/advertisement/controller/advertisement.controller.go @@ -1,17 +1,17 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/advertisement/request" + "netidhub-saas-be/app/module/advertisement/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/advertisement/request" - "web-medols-be/app/module/advertisement/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type advertisementController struct { diff --git a/app/module/advertisement/controller/controller.go b/app/module/advertisement/controller/controller.go index 5d0b8d8..9d76f81 100644 --- a/app/module/advertisement/controller/controller.go +++ b/app/module/advertisement/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/advertisement/service" + "netidhub-saas-be/app/module/advertisement/service" ) type Controller struct { diff --git a/app/module/advertisement/mapper/advertisement.mapper.go b/app/module/advertisement/mapper/advertisement.mapper.go index 4ea87d9..82eb2e9 100644 --- a/app/module/advertisement/mapper/advertisement.mapper.go +++ b/app/module/advertisement/mapper/advertisement.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/advertisement/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/advertisement/response" ) func AdvertisementResponseMapper(advertisementReq *entity.Advertisement, host string) (advertisementRes *res.AdvertisementResponse) { diff --git a/app/module/advertisement/repository/advertisement.repository.go b/app/module/advertisement/repository/advertisement.repository.go index 29226c3..2950ef6 100644 --- a/app/module/advertisement/repository/advertisement.repository.go +++ b/app/module/advertisement/repository/advertisement.repository.go @@ -4,12 +4,12 @@ import ( "fmt" "github.com/google/uuid" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/advertisement/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/advertisement/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type advertisementRepository struct { diff --git a/app/module/advertisement/request/advertisement.request.go b/app/module/advertisement/request/advertisement.request.go index 608db8a..f49e5ae 100644 --- a/app/module/advertisement/request/advertisement.request.go +++ b/app/module/advertisement/request/advertisement.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type AdvertisementGeneric interface { diff --git a/app/module/advertisement/service/advertisement.service.go b/app/module/advertisement/service/advertisement.service.go index 39a22b5..8dcc77b 100644 --- a/app/module/advertisement/service/advertisement.service.go +++ b/app/module/advertisement/service/advertisement.service.go @@ -11,19 +11,19 @@ import ( "log" "math/rand" "mime" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/advertisement/mapper" + "netidhub-saas-be/app/module/advertisement/repository" + "netidhub-saas-be/app/module/advertisement/request" + "netidhub-saas-be/app/module/advertisement/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + config "netidhub-saas-be/config/config" + minioStorage "netidhub-saas-be/config/config" + "netidhub-saas-be/utils/paginator" "path/filepath" "strconv" "strings" "time" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/advertisement/mapper" - "web-medols-be/app/module/advertisement/repository" - "web-medols-be/app/module/advertisement/request" - "web-medols-be/app/module/advertisement/response" - usersRepository "web-medols-be/app/module/users/repository" - config "web-medols-be/config/config" - minioStorage "web-medols-be/config/config" - "web-medols-be/utils/paginator" ) // AdvertisementService diff --git a/app/module/approval_workflow_steps/approval_workflow_steps.module.go b/app/module/approval_workflow_steps/approval_workflow_steps.module.go index 1c10325..be83551 100644 --- a/app/module/approval_workflow_steps/approval_workflow_steps.module.go +++ b/app/module/approval_workflow_steps/approval_workflow_steps.module.go @@ -3,9 +3,9 @@ package approval_workflow_steps import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/approval_workflow_steps/controller" - "web-medols-be/app/module/approval_workflow_steps/repository" - "web-medols-be/app/module/approval_workflow_steps/service" + "netidhub-saas-be/app/module/approval_workflow_steps/controller" + "netidhub-saas-be/app/module/approval_workflow_steps/repository" + "netidhub-saas-be/app/module/approval_workflow_steps/service" ) // ApprovalWorkflowStepsRouter struct of ApprovalWorkflowStepsRouter @@ -54,4 +54,4 @@ func (_i *ApprovalWorkflowStepsRouter) RegisterApprovalWorkflowStepsRoutes() { router.Post("/bulk", approvalWorkflowStepsController.BulkSave) router.Put("/workflow/:workflowId/reorder", approvalWorkflowStepsController.Reorder) }) -} \ No newline at end of file +} diff --git a/app/module/approval_workflow_steps/controller/approval_workflow_steps.controller.go b/app/module/approval_workflow_steps/controller/approval_workflow_steps.controller.go index 37f2b8a..9a605b1 100644 --- a/app/module/approval_workflow_steps/controller/approval_workflow_steps.controller.go +++ b/app/module/approval_workflow_steps/controller/approval_workflow_steps.controller.go @@ -1,14 +1,14 @@ package controller import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/approval_workflow_steps/request" + "netidhub-saas-be/app/module/approval_workflow_steps/service" + "netidhub-saas-be/utils/paginator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "strconv" - "web-medols-be/app/database/entity" - "web-medols-be/app/middleware" - "web-medols-be/app/module/approval_workflow_steps/request" - "web-medols-be/app/module/approval_workflow_steps/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/approval_workflow_steps/mapper/approval_workflow_steps.mapper.go b/app/module/approval_workflow_steps/mapper/approval_workflow_steps.mapper.go index ff0712c..954a305 100644 --- a/app/module/approval_workflow_steps/mapper/approval_workflow_steps.mapper.go +++ b/app/module/approval_workflow_steps/mapper/approval_workflow_steps.mapper.go @@ -3,9 +3,9 @@ package mapper import ( "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/approval_workflow_steps/response" - usersRepository "web-medols-be/app/module/users/repository" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/approval_workflow_steps/response" + usersRepository "netidhub-saas-be/app/module/users/repository" ) func ApprovalWorkflowStepsResponseMapper( @@ -28,17 +28,17 @@ func ApprovalWorkflowStepsResponseMapper( } approvalWorkflowStepsRes = &res.ApprovalWorkflowStepsResponse{ - ID: approvalWorkflowStepsReq.ID, - WorkflowID: approvalWorkflowStepsReq.WorkflowId, - StepName: approvalWorkflowStepsReq.StepName, - StepOrder: approvalWorkflowStepsReq.StepOrder, - ApproverRoleID: approvalWorkflowStepsReq.RequiredUserLevelId, - IsOptional: isOptional, - RequiresComment: false, // Default value - AutoApprove: autoApprove, - TimeoutHours: approvalWorkflowStepsReq.AutoApproveAfterHours, - CreatedAt: approvalWorkflowStepsReq.CreatedAt, - UpdatedAt: approvalWorkflowStepsReq.UpdatedAt, + ID: approvalWorkflowStepsReq.ID, + WorkflowID: approvalWorkflowStepsReq.WorkflowId, + StepName: approvalWorkflowStepsReq.StepName, + StepOrder: approvalWorkflowStepsReq.StepOrder, + ApproverRoleID: approvalWorkflowStepsReq.RequiredUserLevelId, + IsOptional: isOptional, + RequiresComment: false, // Default value + AutoApprove: autoApprove, + TimeoutHours: approvalWorkflowStepsReq.AutoApproveAfterHours, + CreatedAt: approvalWorkflowStepsReq.CreatedAt, + UpdatedAt: approvalWorkflowStepsReq.UpdatedAt, } } @@ -72,4 +72,4 @@ func ApprovalWorkflowStepsSummaryResponseMapper( } return approvalWorkflowStepsRes -} \ No newline at end of file +} diff --git a/app/module/approval_workflow_steps/repository/approval_workflow_steps.repository.go b/app/module/approval_workflow_steps/repository/approval_workflow_steps.repository.go index cd4833a..6822611 100644 --- a/app/module/approval_workflow_steps/repository/approval_workflow_steps.repository.go +++ b/app/module/approval_workflow_steps/repository/approval_workflow_steps.repository.go @@ -2,10 +2,10 @@ package repository import ( "fmt" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/approval_workflow_steps/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/approval_workflow_steps/request" + "netidhub-saas-be/utils/paginator" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/approval_workflow_steps/service/approval_workflow_steps.service.go b/app/module/approval_workflow_steps/service/approval_workflow_steps.service.go index ab72eff..e467d9f 100644 --- a/app/module/approval_workflow_steps/service/approval_workflow_steps.service.go +++ b/app/module/approval_workflow_steps/service/approval_workflow_steps.service.go @@ -3,11 +3,11 @@ package service import ( "errors" "fmt" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/approval_workflow_steps/repository" - "web-medols-be/app/module/approval_workflow_steps/request" - workflowRepo "web-medols-be/app/module/approval_workflows/repository" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/approval_workflow_steps/repository" + "netidhub-saas-be/app/module/approval_workflow_steps/request" + workflowRepo "netidhub-saas-be/app/module/approval_workflows/repository" + "netidhub-saas-be/utils/paginator" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/approval_workflows/approval_workflows.module.go b/app/module/approval_workflows/approval_workflows.module.go index bf98273..2c3d5a7 100644 --- a/app/module/approval_workflows/approval_workflows.module.go +++ b/app/module/approval_workflows/approval_workflows.module.go @@ -3,9 +3,9 @@ package approval_workflows import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/approval_workflows/controller" - "web-medols-be/app/module/approval_workflows/repository" - "web-medols-be/app/module/approval_workflows/service" + "netidhub-saas-be/app/module/approval_workflows/controller" + "netidhub-saas-be/app/module/approval_workflows/repository" + "netidhub-saas-be/app/module/approval_workflows/service" ) // ApprovalWorkflowsRouter struct of ApprovalWorkflowsRouter @@ -57,4 +57,4 @@ func (_i *ApprovalWorkflowsRouter) RegisterApprovalWorkflowsRoutes() { router.Put("/:id/deactivate", approvalWorkflowsController.Deactivate) router.Delete("/:id", approvalWorkflowsController.Delete) }) -} \ No newline at end of file +} diff --git a/app/module/approval_workflows/controller/approval_workflows.controller.go b/app/module/approval_workflows/controller/approval_workflows.controller.go index 978e04b..e8fca51 100644 --- a/app/module/approval_workflows/controller/approval_workflows.controller.go +++ b/app/module/approval_workflows/controller/approval_workflows.controller.go @@ -3,15 +3,15 @@ package controller import ( "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/approval_workflows/request" + "netidhub-saas-be/app/module/approval_workflows/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/database/entity" - "web-medols-be/app/middleware" - "web-medols-be/app/module/approval_workflows/request" - "web-medols-be/app/module/approval_workflows/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type approvalWorkflowsController struct { @@ -478,4 +478,4 @@ func (_i *approvalWorkflowsController) UpdateWithSteps(c *fiber.Ctx) error { Success: true, Messages: utilRes.Messages{"ApprovalWorkflows with steps successfully updated"}, }) -} \ No newline at end of file +} diff --git a/app/module/approval_workflows/mapper/approval_workflows.mapper.go b/app/module/approval_workflows/mapper/approval_workflows.mapper.go index 547c3b3..14a074d 100644 --- a/app/module/approval_workflows/mapper/approval_workflows.mapper.go +++ b/app/module/approval_workflows/mapper/approval_workflows.mapper.go @@ -3,12 +3,12 @@ package mapper import ( "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - approvalWorkflowStepsMapper "web-medols-be/app/module/approval_workflow_steps/mapper" - approvalWorkflowStepsRepository "web-medols-be/app/module/approval_workflow_steps/repository" - approvalWorkflowStepsResponse "web-medols-be/app/module/approval_workflow_steps/response" - res "web-medols-be/app/module/approval_workflows/response" - usersRepository "web-medols-be/app/module/users/repository" + "netidhub-saas-be/app/database/entity" + approvalWorkflowStepsMapper "netidhub-saas-be/app/module/approval_workflow_steps/mapper" + approvalWorkflowStepsRepository "netidhub-saas-be/app/module/approval_workflow_steps/repository" + approvalWorkflowStepsResponse "netidhub-saas-be/app/module/approval_workflow_steps/response" + res "netidhub-saas-be/app/module/approval_workflows/response" + usersRepository "netidhub-saas-be/app/module/users/repository" ) func ApprovalWorkflowsResponseMapper( @@ -39,8 +39,6 @@ func ApprovalWorkflowsResponseMapper( isActive = *approvalWorkflowsReq.IsActive } - - approvalWorkflowsRes = &res.ApprovalWorkflowsResponse{ ID: approvalWorkflowsReq.ID, Name: approvalWorkflowsReq.Name, @@ -123,4 +121,4 @@ func ApprovalWorkflowsSummaryResponseMapper( } return approvalWorkflowsRes -} \ No newline at end of file +} diff --git a/app/module/approval_workflows/repository/approval_workflows.repository.go b/app/module/approval_workflows/repository/approval_workflows.repository.go index fea217e..06bc003 100644 --- a/app/module/approval_workflows/repository/approval_workflows.repository.go +++ b/app/module/approval_workflows/repository/approval_workflows.repository.go @@ -2,14 +2,14 @@ package repository import ( "fmt" - "strings" "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - approvalWorkflowStepsEntity "web-medols-be/app/database/entity" - "web-medols-be/app/module/approval_workflows/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + approvalWorkflowStepsEntity "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/approval_workflows/request" + "netidhub-saas-be/utils/paginator" + "strings" ) type approvalWorkflowsRepository struct { @@ -176,21 +176,21 @@ func (_i *approvalWorkflowsRepository) GetDefault(clientId *uuid.UUID) (workflow // GetWorkflowSteps gets all steps for a specific workflow func (_i *approvalWorkflowsRepository) GetWorkflowSteps(clientId *uuid.UUID, workflowId uint) (steps []*entity.ApprovalWorkflowSteps, err error) { query := _i.DB.DB.Model(&approvalWorkflowStepsEntity.ApprovalWorkflowSteps{}) - + // Join with approval_workflows to check client_id query = query.Joins("JOIN approval_workflows ON approval_workflow_steps.workflow_id = approval_workflows.id") - + if clientId != nil { query = query.Where("approval_workflows.client_id = ?", clientId) } - + query = query.Where("approval_workflow_steps.workflow_id = ?", workflowId) query = query.Where("approval_workflows.is_active = ?", true) query = query.Order("approval_workflow_steps.step_order ASC") - + // Preload the RequiredUserLevel relation query = query.Preload("RequiredUserLevel") - + err = query.Find(&steps).Error return steps, err -} \ No newline at end of file +} diff --git a/app/module/approval_workflows/request/approval_workflows.request.go b/app/module/approval_workflows/request/approval_workflows.request.go index 5e1d592..95e5067 100644 --- a/app/module/approval_workflows/request/approval_workflows.request.go +++ b/app/module/approval_workflows/request/approval_workflows.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type ApprovalWorkflowsGeneric interface { diff --git a/app/module/approval_workflows/response/approval_workflows.response.go b/app/module/approval_workflows/response/approval_workflows.response.go index e4d6d7c..d4f8695 100644 --- a/app/module/approval_workflows/response/approval_workflows.response.go +++ b/app/module/approval_workflows/response/approval_workflows.response.go @@ -1,8 +1,8 @@ package response import ( + approvalWorkflowStepsResponse "netidhub-saas-be/app/module/approval_workflow_steps/response" "time" - approvalWorkflowStepsResponse "web-medols-be/app/module/approval_workflow_steps/response" ) type ApprovalWorkflowsResponse struct { @@ -40,9 +40,9 @@ type ApprovalWorkflowsSummaryResponse struct { } type ApprovalWorkflowsStatsResponse struct { - TotalWorkflows int `json:"totalWorkflows"` - ActiveWorkflows int `json:"activeWorkflows"` - InactiveWorkflows int `json:"inactiveWorkflows"` + TotalWorkflows int `json:"totalWorkflows"` + ActiveWorkflows int `json:"activeWorkflows"` + InactiveWorkflows int `json:"inactiveWorkflows"` TotalSteps int `json:"totalSteps"` AverageStepsPerFlow int `json:"averageStepsPerFlow"` -} \ No newline at end of file +} diff --git a/app/module/approval_workflows/service/approval_workflows.service.go b/app/module/approval_workflows/service/approval_workflows.service.go index 5bbbf9c..5cd0e7d 100644 --- a/app/module/approval_workflows/service/approval_workflows.service.go +++ b/app/module/approval_workflows/service/approval_workflows.service.go @@ -5,17 +5,17 @@ import ( "fmt" "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/approval_workflows/repository" - "web-medols-be/app/module/approval_workflows/request" - stepRepo "web-medols-be/app/module/approval_workflow_steps/repository" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + stepRepo "netidhub-saas-be/app/module/approval_workflow_steps/repository" + "netidhub-saas-be/app/module/approval_workflows/repository" + "netidhub-saas-be/app/module/approval_workflows/request" + "netidhub-saas-be/utils/paginator" ) type approvalWorkflowsService struct { - ApprovalWorkflowsRepository repository.ApprovalWorkflowsRepository - ApprovalWorkflowStepsRepository stepRepo.ApprovalWorkflowStepsRepository - Log zerolog.Logger + ApprovalWorkflowsRepository repository.ApprovalWorkflowsRepository + ApprovalWorkflowStepsRepository stepRepo.ApprovalWorkflowStepsRepository + Log zerolog.Logger } // ApprovalWorkflowsService define interface of IApprovalWorkflowsService @@ -316,4 +316,4 @@ func (_i *approvalWorkflowsService) CanDeleteWorkflow(clientId *uuid.UUID, id ui // TODO: Implement check for active approval flows return true, "", nil -} \ No newline at end of file +} diff --git a/app/module/article_approval_flows/article_approval_flows.module.go b/app/module/article_approval_flows/article_approval_flows.module.go index 2539e76..ac6a46b 100644 --- a/app/module/article_approval_flows/article_approval_flows.module.go +++ b/app/module/article_approval_flows/article_approval_flows.module.go @@ -3,9 +3,9 @@ package article_approval_flows import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/article_approval_flows/controller" - "web-medols-be/app/module/article_approval_flows/repository" - "web-medols-be/app/module/article_approval_flows/service" + "netidhub-saas-be/app/module/article_approval_flows/controller" + "netidhub-saas-be/app/module/article_approval_flows/repository" + "netidhub-saas-be/app/module/article_approval_flows/service" ) // ArticleApprovalFlowsRouter struct of ArticleApprovalFlowsRouter @@ -58,4 +58,4 @@ func (_i *ArticleApprovalFlowsRouter) RegisterArticleApprovalFlowsRoutes() { router.Put("/:id/request-revision", articleApprovalFlowsController.RequestRevision) router.Put("/:id/resubmit", articleApprovalFlowsController.Resubmit) }) -} \ No newline at end of file +} diff --git a/app/module/article_approval_flows/controller/article_approval_flows.controller.go b/app/module/article_approval_flows/controller/article_approval_flows.controller.go index 840dd26..ab5911c 100644 --- a/app/module/article_approval_flows/controller/article_approval_flows.controller.go +++ b/app/module/article_approval_flows/controller/article_approval_flows.controller.go @@ -1,19 +1,19 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/article_approval_flows/request" + "netidhub-saas-be/app/module/article_approval_flows/service" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/article_approval_flows/request" - "web-medols-be/app/module/article_approval_flows/service" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type articleApprovalFlowsController struct { diff --git a/app/module/article_approval_flows/mapper/article_approval_flows.mapper.go b/app/module/article_approval_flows/mapper/article_approval_flows.mapper.go index b8b4425..1d1498c 100644 --- a/app/module/article_approval_flows/mapper/article_approval_flows.mapper.go +++ b/app/module/article_approval_flows/mapper/article_approval_flows.mapper.go @@ -1,18 +1,18 @@ package mapper import ( - "time" "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - articleApprovalStepLogsResponse "web-medols-be/app/module/article_approval_step_logs/response" - articleApprovalStepLogsRepository "web-medols-be/app/module/article_approval_step_logs/repository" - approvalWorkflowsRepository "web-medols-be/app/module/approval_workflows/repository" - approvalWorkflowsResponse "web-medols-be/app/module/approval_workflows/response" - articlesRepository "web-medols-be/app/module/articles/repository" - articlesResponse "web-medols-be/app/module/articles/response" - usersRepository "web-medols-be/app/module/users/repository" - res "web-medols-be/app/module/article_approval_flows/response" + "netidhub-saas-be/app/database/entity" + approvalWorkflowsRepository "netidhub-saas-be/app/module/approval_workflows/repository" + approvalWorkflowsResponse "netidhub-saas-be/app/module/approval_workflows/response" + res "netidhub-saas-be/app/module/article_approval_flows/response" + articleApprovalStepLogsRepository "netidhub-saas-be/app/module/article_approval_step_logs/repository" + articleApprovalStepLogsResponse "netidhub-saas-be/app/module/article_approval_step_logs/response" + articlesRepository "netidhub-saas-be/app/module/articles/repository" + articlesResponse "netidhub-saas-be/app/module/articles/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + "time" ) func ArticleApprovalFlowsResponseMapper( @@ -26,8 +26,6 @@ func ArticleApprovalFlowsResponseMapper( usersRepo usersRepository.UsersRepository, ) (articleApprovalFlowsRes *res.ArticleApprovalFlowsResponse) { - - // Get article information var articleRes *articlesResponse.ArticlesResponse if articleApprovalFlowsReq.ArticleId != 0 { @@ -84,21 +82,21 @@ func ArticleApprovalFlowsResponseMapper( } articleApprovalFlowsRes = &res.ArticleApprovalFlowsResponse{ - ID: articleApprovalFlowsReq.ID, - ArticleID: articleApprovalFlowsReq.ArticleId, - WorkflowID: articleApprovalFlowsReq.WorkflowId, - CurrentStep: articleApprovalFlowsReq.CurrentStep, - Status: statusStr, - SubmittedBy: articleApprovalFlowsReq.SubmittedById, - SubmittedAt: articleApprovalFlowsReq.SubmittedAt, - CompletedAt: articleApprovalFlowsReq.CompletedAt, - RejectionReason: articleApprovalFlowsReq.RejectionReason, - RevisionReason: articleApprovalFlowsReq.RevisionMessage, - CreatedAt: articleApprovalFlowsReq.CreatedAt, - UpdatedAt: articleApprovalFlowsReq.UpdatedAt, - Article: articleRes, - Workflow: approvalWorkflowRes, - StepLogs: stepLogsArr, + ID: articleApprovalFlowsReq.ID, + ArticleID: articleApprovalFlowsReq.ArticleId, + WorkflowID: articleApprovalFlowsReq.WorkflowId, + CurrentStep: articleApprovalFlowsReq.CurrentStep, + Status: statusStr, + SubmittedBy: articleApprovalFlowsReq.SubmittedById, + SubmittedAt: articleApprovalFlowsReq.SubmittedAt, + CompletedAt: articleApprovalFlowsReq.CompletedAt, + RejectionReason: articleApprovalFlowsReq.RejectionReason, + RevisionReason: articleApprovalFlowsReq.RevisionMessage, + CreatedAt: articleApprovalFlowsReq.CreatedAt, + UpdatedAt: articleApprovalFlowsReq.UpdatedAt, + Article: articleRes, + Workflow: approvalWorkflowRes, + StepLogs: stepLogsArr, } } @@ -164,7 +162,6 @@ func ArticleApprovalFlowsDetailResponseMapper( IsActive: *approvalWorkflow.IsActive, CreatedAt: approvalWorkflow.CreatedAt, UpdatedAt: approvalWorkflow.UpdatedAt, - } } } @@ -187,22 +184,22 @@ func ArticleApprovalFlowsDetailResponseMapper( } articleApprovalFlowsRes = &res.ArticleApprovalFlowsDetailResponse{ - ID: articleApprovalFlowsReq.ID, - ArticleID: articleApprovalFlowsReq.ArticleId, - WorkflowID: articleApprovalFlowsReq.WorkflowId, - CurrentStep: articleApprovalFlowsReq.CurrentStep, - Status: statusStr, - SubmittedBy: articleApprovalFlowsReq.SubmittedById, - SubmittedByName: submittedByName, - SubmittedAt: articleApprovalFlowsReq.SubmittedAt, - CompletedAt: articleApprovalFlowsReq.CompletedAt, - RejectionReason: articleApprovalFlowsReq.RejectionReason, - RevisionReason: articleApprovalFlowsReq.RevisionMessage, - CreatedAt: articleApprovalFlowsReq.CreatedAt, - UpdatedAt: articleApprovalFlowsReq.UpdatedAt, - Article: articleRes, - Workflow: approvalWorkflowRes, - StepLogs: stepLogsArr, + ID: articleApprovalFlowsReq.ID, + ArticleID: articleApprovalFlowsReq.ArticleId, + WorkflowID: articleApprovalFlowsReq.WorkflowId, + CurrentStep: articleApprovalFlowsReq.CurrentStep, + Status: statusStr, + SubmittedBy: articleApprovalFlowsReq.SubmittedById, + SubmittedByName: submittedByName, + SubmittedAt: articleApprovalFlowsReq.SubmittedAt, + CompletedAt: articleApprovalFlowsReq.CompletedAt, + RejectionReason: articleApprovalFlowsReq.RejectionReason, + RevisionReason: articleApprovalFlowsReq.RevisionMessage, + CreatedAt: articleApprovalFlowsReq.CreatedAt, + UpdatedAt: articleApprovalFlowsReq.UpdatedAt, + Article: articleRes, + Workflow: approvalWorkflowRes, + StepLogs: stepLogsArr, } } @@ -254,4 +251,4 @@ func ArticleApprovalFlowsSummaryResponseMapper( } return articleApprovalFlowsRes -} \ No newline at end of file +} diff --git a/app/module/article_approval_flows/repository/article_approval_flows.repository.go b/app/module/article_approval_flows/repository/article_approval_flows.repository.go index 9d8013a..15ce14b 100644 --- a/app/module/article_approval_flows/repository/article_approval_flows.repository.go +++ b/app/module/article_approval_flows/repository/article_approval_flows.repository.go @@ -2,11 +2,11 @@ package repository import ( "fmt" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_approval_flows/request" + "netidhub-saas-be/utils/paginator" "time" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_approval_flows/request" - "web-medols-be/utils/paginator" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/article_approval_flows/request/article_approval_flows.request.go b/app/module/article_approval_flows/request/article_approval_flows.request.go index 3b076a4..cde9848 100644 --- a/app/module/article_approval_flows/request/article_approval_flows.request.go +++ b/app/module/article_approval_flows/request/article_approval_flows.request.go @@ -1,9 +1,9 @@ package request import ( + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/utils/paginator" ) type ArticleApprovalFlowsGeneric interface { @@ -11,14 +11,14 @@ type ArticleApprovalFlowsGeneric interface { } type ArticleApprovalFlowsQueryRequest struct { - ArticleId *int `json:"articleId"` - WorkflowId *int `json:"workflowId"` - StatusId *int `json:"statusId"` - SubmittedBy *int `json:"submittedBy"` - CurrentStep *int `json:"currentStep"` - DateFrom *time.Time `json:"dateFrom"` - DateTo *time.Time `json:"dateTo"` - Pagination *paginator.Pagination `json:"pagination"` + ArticleId *int `json:"articleId"` + WorkflowId *int `json:"workflowId"` + StatusId *int `json:"statusId"` + SubmittedBy *int `json:"submittedBy"` + CurrentStep *int `json:"currentStep"` + DateFrom *time.Time `json:"dateFrom"` + DateTo *time.Time `json:"dateTo"` + Pagination *paginator.Pagination `json:"pagination"` } type SubmitForApprovalRequest struct { @@ -43,13 +43,13 @@ type ResubmitRequest struct { } type ArticleApprovalFlowsQueryRequestContext struct { - ArticleId string `json:"articleId"` - WorkflowId string `json:"workflowId"` - StatusId string `json:"statusId"` - SubmittedBy string `json:"submittedBy"` - CurrentStep string `json:"currentStep"` - DateFrom string `json:"dateFrom"` - DateTo string `json:"dateTo"` + ArticleId string `json:"articleId"` + WorkflowId string `json:"workflowId"` + StatusId string `json:"statusId"` + SubmittedBy string `json:"submittedBy"` + CurrentStep string `json:"currentStep"` + DateFrom string `json:"dateFrom"` + DateTo string `json:"dateTo"` } func (req ArticleApprovalFlowsQueryRequestContext) ToParamRequest() ArticleApprovalFlowsQueryRequest { @@ -112,4 +112,4 @@ func (req ArticleApprovalFlowsQueryRequestContext) ToParamRequest() ArticleAppro DateFrom: dateFrom, DateTo: dateTo, } -} \ No newline at end of file +} diff --git a/app/module/article_approval_flows/response/article_approval_flows.response.go b/app/module/article_approval_flows/response/article_approval_flows.response.go index 2509061..2d749b7 100644 --- a/app/module/article_approval_flows/response/article_approval_flows.response.go +++ b/app/module/article_approval_flows/response/article_approval_flows.response.go @@ -1,10 +1,10 @@ package response import ( + approvalWorkflowsResponse "netidhub-saas-be/app/module/approval_workflows/response" + articleApprovalStepLogsResponse "netidhub-saas-be/app/module/article_approval_step_logs/response" + articlesResponse "netidhub-saas-be/app/module/articles/response" "time" - articlesResponse "web-medols-be/app/module/articles/response" - approvalWorkflowsResponse "web-medols-be/app/module/approval_workflows/response" - articleApprovalStepLogsResponse "web-medols-be/app/module/article_approval_step_logs/response" ) type ArticleApprovalFlowsResponse struct { @@ -25,9 +25,9 @@ type ArticleApprovalFlowsResponse struct { UpdatedAt time.Time `json:"updatedAt"` // Relations - Article *articlesResponse.ArticlesResponse `json:"article,omitempty"` - Workflow *approvalWorkflowsResponse.ApprovalWorkflowsResponse `json:"workflow,omitempty"` - StepLogs []*articleApprovalStepLogsResponse.ArticleApprovalStepLogsResponse `json:"stepLogs,omitempty"` + Article *articlesResponse.ArticlesResponse `json:"article,omitempty"` + Workflow *approvalWorkflowsResponse.ApprovalWorkflowsResponse `json:"workflow,omitempty"` + StepLogs []*articleApprovalStepLogsResponse.ArticleApprovalStepLogsResponse `json:"stepLogs,omitempty"` } type ArticleApprovalFlowsDetailResponse struct { @@ -49,9 +49,9 @@ type ArticleApprovalFlowsDetailResponse struct { UpdatedAt time.Time `json:"updatedAt"` // Relations with full details - Article *articlesResponse.ArticlesResponse `json:"article"` - Workflow *approvalWorkflowsResponse.ApprovalWorkflowsWithStepsResponse `json:"workflow"` - StepLogs []*articleApprovalStepLogsResponse.ArticleApprovalStepLogsResponse `json:"stepLogs"` + Article *articlesResponse.ArticlesResponse `json:"article"` + Workflow *approvalWorkflowsResponse.ApprovalWorkflowsWithStepsResponse `json:"workflow"` + StepLogs []*articleApprovalStepLogsResponse.ArticleApprovalStepLogsResponse `json:"stepLogs"` } type ArticleApprovalFlowsSummaryResponse struct { @@ -69,16 +69,16 @@ type ArticleApprovalFlowsSummaryResponse struct { } type ApprovalQueueResponse struct { - ID uint `json:"id"` - ArticleID uint `json:"articleId"` - ArticleTitle string `json:"articleTitle"` - ArticleAuthor string `json:"articleAuthor"` - WorkflowName string `json:"workflowName"` - CurrentStepName string `json:"currentStepName"` - SubmittedAt time.Time `json:"submittedAt"` - DaysWaiting int `json:"daysWaiting"` - Priority string `json:"priority"` - RequiresComment bool `json:"requiresComment"` + ID uint `json:"id"` + ArticleID uint `json:"articleId"` + ArticleTitle string `json:"articleTitle"` + ArticleAuthor string `json:"articleAuthor"` + WorkflowName string `json:"workflowName"` + CurrentStepName string `json:"currentStepName"` + SubmittedAt time.Time `json:"submittedAt"` + DaysWaiting int `json:"daysWaiting"` + Priority string `json:"priority"` + RequiresComment bool `json:"requiresComment"` } type ApprovalDashboardStatsResponse struct { @@ -108,4 +108,4 @@ type ApprovalAnalyticsResponse struct { TotalRevisions int `json:"totalRevisions"` ApprovalRate float64 `json:"approvalRate"` AverageApprovalTime float64 `json:"averageApprovalTime"` // in hours -} \ No newline at end of file +} diff --git a/app/module/article_approval_flows/service/article_approval_flows.service.go b/app/module/article_approval_flows/service/article_approval_flows.service.go index 02fde27..d060526 100644 --- a/app/module/article_approval_flows/service/article_approval_flows.service.go +++ b/app/module/article_approval_flows/service/article_approval_flows.service.go @@ -2,16 +2,16 @@ package service import ( "errors" + "netidhub-saas-be/app/database/entity" + approvalWorkflowStepsRepo "netidhub-saas-be/app/module/approval_workflow_steps/repository" + approvalWorkflowsRepo "netidhub-saas-be/app/module/approval_workflows/repository" + "netidhub-saas-be/app/module/article_approval_flows/repository" + "netidhub-saas-be/app/module/article_approval_flows/request" + approvalStepLogsRepo "netidhub-saas-be/app/module/article_approval_step_logs/repository" + articlesRepo "netidhub-saas-be/app/module/articles/repository" + usersRepo "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" "time" - "web-medols-be/app/database/entity" - approvalWorkflowStepsRepo "web-medols-be/app/module/approval_workflow_steps/repository" - approvalWorkflowsRepo "web-medols-be/app/module/approval_workflows/repository" - "web-medols-be/app/module/article_approval_flows/repository" - "web-medols-be/app/module/article_approval_flows/request" - approvalStepLogsRepo "web-medols-be/app/module/article_approval_step_logs/repository" - articlesRepo "web-medols-be/app/module/articles/repository" - usersRepo "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/article_approval_step_logs/article_approval_step_logs.module.go b/app/module/article_approval_step_logs/article_approval_step_logs.module.go index b03ab74..43b2f60 100644 --- a/app/module/article_approval_step_logs/article_approval_step_logs.module.go +++ b/app/module/article_approval_step_logs/article_approval_step_logs.module.go @@ -1,9 +1,9 @@ package article_approval_step_logs import ( - "web-medols-be/app/module/article_approval_step_logs/controller" - "web-medols-be/app/module/article_approval_step_logs/repository" - "web-medols-be/app/module/article_approval_step_logs/service" + "netidhub-saas-be/app/module/article_approval_step_logs/controller" + "netidhub-saas-be/app/module/article_approval_step_logs/repository" + "netidhub-saas-be/app/module/article_approval_step_logs/service" "github.com/gofiber/fiber/v2" "go.uber.org/fx" diff --git a/app/module/article_approval_step_logs/controller/article_approval_step_logs.controller.go b/app/module/article_approval_step_logs/controller/article_approval_step_logs.controller.go index aa17dfc..8651724 100644 --- a/app/module/article_approval_step_logs/controller/article_approval_step_logs.controller.go +++ b/app/module/article_approval_step_logs/controller/article_approval_step_logs.controller.go @@ -1,13 +1,13 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/article_approval_step_logs/request" + "netidhub-saas-be/app/module/article_approval_step_logs/service" + "netidhub-saas-be/utils/paginator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/article_approval_step_logs/request" - "web-medols-be/app/module/article_approval_step_logs/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/article_approval_step_logs/mapper/article_approval_step_logs.mapper.go b/app/module/article_approval_step_logs/mapper/article_approval_step_logs.mapper.go index c4dc248..042b41e 100644 --- a/app/module/article_approval_step_logs/mapper/article_approval_step_logs.mapper.go +++ b/app/module/article_approval_step_logs/mapper/article_approval_step_logs.mapper.go @@ -1,9 +1,9 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/article_approval_step_logs/response" - usersRepository "web-medols-be/app/module/users/repository" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/article_approval_step_logs/response" + usersRepository "netidhub-saas-be/app/module/users/repository" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/article_approval_step_logs/repository/article_approval_step_logs.repository.go b/app/module/article_approval_step_logs/repository/article_approval_step_logs.repository.go index 8059f75..0374cf4 100644 --- a/app/module/article_approval_step_logs/repository/article_approval_step_logs.repository.go +++ b/app/module/article_approval_step_logs/repository/article_approval_step_logs.repository.go @@ -2,11 +2,11 @@ package repository import ( "fmt" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_approval_step_logs/request" + "netidhub-saas-be/utils/paginator" "time" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_approval_step_logs/request" - "web-medols-be/utils/paginator" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/article_approval_step_logs/request/article_approval_step_logs.request.go b/app/module/article_approval_step_logs/request/article_approval_step_logs.request.go index bccce61..8bea653 100644 --- a/app/module/article_approval_step_logs/request/article_approval_step_logs.request.go +++ b/app/module/article_approval_step_logs/request/article_approval_step_logs.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type CreateArticleApprovalStepLogsRequest struct { diff --git a/app/module/article_approval_step_logs/response/article_approval_step_logs.response.go b/app/module/article_approval_step_logs/response/article_approval_step_logs.response.go index 5b79985..c3c31d5 100644 --- a/app/module/article_approval_step_logs/response/article_approval_step_logs.response.go +++ b/app/module/article_approval_step_logs/response/article_approval_step_logs.response.go @@ -1,47 +1,47 @@ package response import ( + approvalWorkflowStepsResponse "netidhub-saas-be/app/module/approval_workflow_steps/response" + articlesResponse "netidhub-saas-be/app/module/articles/response" + usersResponse "netidhub-saas-be/app/module/users/response" "time" - approvalWorkflowStepsResponse "web-medols-be/app/module/approval_workflow_steps/response" - articlesResponse "web-medols-be/app/module/articles/response" - usersResponse "web-medols-be/app/module/users/response" ) type ArticleApprovalStepLogsResponse struct { - ID uint `json:"id"` - ApprovalFlowId uint `json:"approvalFlowId"` - StepOrder int `json:"stepOrder"` - StepName string `json:"stepName"` - ApprovedById *uint `json:"approvedById"` - Action string `json:"action"` - Message *string `json:"message"` - ProcessedAt time.Time `json:"processedAt"` - UserLevelId uint `json:"userLevelId"` - ClientId *string `json:"clientId"` - CreatedAt time.Time `json:"createdAt"` + ID uint `json:"id"` + ApprovalFlowId uint `json:"approvalFlowId"` + StepOrder int `json:"stepOrder"` + StepName string `json:"stepName"` + ApprovedById *uint `json:"approvedById"` + Action string `json:"action"` + Message *string `json:"message"` + ProcessedAt time.Time `json:"processedAt"` + UserLevelId uint `json:"userLevelId"` + ClientId *string `json:"clientId"` + CreatedAt time.Time `json:"createdAt"` // Relations ApprovedBy *usersResponse.UsersResponse `json:"approvedBy,omitempty"` } type ArticleApprovalStepLogsDetailResponse struct { - ID uint `json:"id"` - ArticleApprovalFlowID uint `json:"articleApprovalFlowId"` - WorkflowStepID uint `json:"workflowStepId"` - ApproverUserID *uint `json:"approverUserId"` - ApprovalStatusID uint `json:"approvalStatusId"` - ApprovalStatusName *string `json:"approvalStatusName,omitempty"` - Comments *string `json:"comments"` - ApprovedAt *time.Time `json:"approvedAt"` - DueDate *time.Time `json:"dueDate"` - IsAutoApproved bool `json:"isAutoApproved"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID uint `json:"id"` + ArticleApprovalFlowID uint `json:"articleApprovalFlowId"` + WorkflowStepID uint `json:"workflowStepId"` + ApproverUserID *uint `json:"approverUserId"` + ApprovalStatusID uint `json:"approvalStatusId"` + ApprovalStatusName *string `json:"approvalStatusName,omitempty"` + Comments *string `json:"comments"` + ApprovedAt *time.Time `json:"approvedAt"` + DueDate *time.Time `json:"dueDate"` + IsAutoApproved bool `json:"isAutoApproved"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` // Relations with full details WorkflowStep *approvalWorkflowStepsResponse.ApprovalWorkflowStepsResponse `json:"workflowStep,omitempty"` - ApproverUser *usersResponse.UsersResponse `json:"approverUser,omitempty"` - Article *articlesResponse.ArticlesResponse `json:"article,omitempty"` + ApproverUser *usersResponse.UsersResponse `json:"approverUser,omitempty"` + Article *articlesResponse.ArticlesResponse `json:"article,omitempty"` } type ArticleApprovalStepLogsSummaryResponse struct { @@ -58,12 +58,12 @@ type ArticleApprovalStepLogsSummaryResponse struct { } type ApprovalHistoryResponse struct { - ArticleID uint `json:"articleId"` - ArticleTitle string `json:"articleTitle"` - WorkflowName string `json:"workflowName"` - StartedAt time.Time `json:"startedAt"` - CompletedAt *time.Time `json:"completedAt"` - CurrentStep *string `json:"currentStep"` + ArticleID uint `json:"articleId"` + ArticleTitle string `json:"articleTitle"` + WorkflowName string `json:"workflowName"` + StartedAt time.Time `json:"startedAt"` + CompletedAt *time.Time `json:"completedAt"` + CurrentStep *string `json:"currentStep"` Steps []ArticleApprovalStepLogsSummaryResponse `json:"steps"` } @@ -88,4 +88,4 @@ type UserApprovalStatsResponse struct { RejectedCount int `json:"rejectedCount"` AverageProcessingTime float64 `json:"averageProcessingTime"` // in hours OverdueCount int `json:"overdueCount"` -} \ No newline at end of file +} diff --git a/app/module/article_approval_step_logs/service/article_approval_step_logs.service.go b/app/module/article_approval_step_logs/service/article_approval_step_logs.service.go index 86c441f..1ea4d82 100644 --- a/app/module/article_approval_step_logs/service/article_approval_step_logs.service.go +++ b/app/module/article_approval_step_logs/service/article_approval_step_logs.service.go @@ -3,13 +3,13 @@ package service import ( "errors" "fmt" + "netidhub-saas-be/app/database/entity" + stepRepo "netidhub-saas-be/app/module/approval_workflow_steps/repository" + flowRepo "netidhub-saas-be/app/module/article_approval_flows/repository" + "netidhub-saas-be/app/module/article_approval_step_logs/repository" + "netidhub-saas-be/app/module/article_approval_step_logs/request" + "netidhub-saas-be/utils/paginator" "time" - "web-medols-be/app/database/entity" - stepRepo "web-medols-be/app/module/approval_workflow_steps/repository" - flowRepo "web-medols-be/app/module/article_approval_flows/repository" - "web-medols-be/app/module/article_approval_step_logs/repository" - "web-medols-be/app/module/article_approval_step_logs/request" - "web-medols-be/utils/paginator" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/article_approvals/article_approvals.module.go b/app/module/article_approvals/article_approvals.module.go index 8f29692..46ad9e1 100644 --- a/app/module/article_approvals/article_approvals.module.go +++ b/app/module/article_approvals/article_approvals.module.go @@ -3,9 +3,9 @@ package article_approvals import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/article_approvals/controller" - "web-medols-be/app/module/article_approvals/repository" - "web-medols-be/app/module/article_approvals/service" + "netidhub-saas-be/app/module/article_approvals/controller" + "netidhub-saas-be/app/module/article_approvals/repository" + "netidhub-saas-be/app/module/article_approvals/service" ) // struct of ArticleApprovalsRouter diff --git a/app/module/article_approvals/controller/article_approvals.controller.go b/app/module/article_approvals/controller/article_approvals.controller.go index cd82629..c62d1f8 100644 --- a/app/module/article_approvals/controller/article_approvals.controller.go +++ b/app/module/article_approvals/controller/article_approvals.controller.go @@ -1,17 +1,17 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/article_approvals/request" + "netidhub-saas-be/app/module/article_approvals/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/article_approvals/request" - "web-medols-be/app/module/article_approvals/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type articleApprovalsController struct { diff --git a/app/module/article_approvals/controller/controller.go b/app/module/article_approvals/controller/controller.go index 8f12a3f..b031dda 100644 --- a/app/module/article_approvals/controller/controller.go +++ b/app/module/article_approvals/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/article_approvals/service" + "netidhub-saas-be/app/module/article_approvals/service" ) type Controller struct { diff --git a/app/module/article_approvals/mapper/article_approvals.mapper.go b/app/module/article_approvals/mapper/article_approvals.mapper.go index 336fc39..d4e4d31 100644 --- a/app/module/article_approvals/mapper/article_approvals.mapper.go +++ b/app/module/article_approvals/mapper/article_approvals.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/article_approvals/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/article_approvals/response" ) func ArticleApprovalsResponseMapper(articleApprovalsReq *entity.ArticleApprovals) (articleApprovalsRes *res.ArticleApprovalsResponse) { diff --git a/app/module/article_approvals/repository/article_approvals.repository.go b/app/module/article_approvals/repository/article_approvals.repository.go index d658ef3..5d23925 100644 --- a/app/module/article_approvals/repository/article_approvals.repository.go +++ b/app/module/article_approvals/repository/article_approvals.repository.go @@ -3,12 +3,12 @@ package repository import ( "fmt" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_approvals/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_approvals/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type articleApprovalsRepository struct { diff --git a/app/module/article_approvals/request/article_approvals.request.go b/app/module/article_approvals/request/article_approvals.request.go index 4f79252..4700efe 100644 --- a/app/module/article_approvals/request/article_approvals.request.go +++ b/app/module/article_approvals/request/article_approvals.request.go @@ -1,9 +1,9 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type ArticleApprovalsGeneric interface { diff --git a/app/module/article_approvals/service/article_approvals.service.go b/app/module/article_approvals/service/article_approvals.service.go index 0f23692..5465f39 100644 --- a/app/module/article_approvals/service/article_approvals.service.go +++ b/app/module/article_approvals/service/article_approvals.service.go @@ -3,16 +3,16 @@ package service import ( "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_approvals/mapper" - "web-medols-be/app/module/article_approvals/repository" - "web-medols-be/app/module/article_approvals/request" - "web-medols-be/app/module/article_approvals/response" - articlesService "web-medols-be/app/module/articles/service" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_approvals/mapper" + "netidhub-saas-be/app/module/article_approvals/repository" + "netidhub-saas-be/app/module/article_approvals/request" + "netidhub-saas-be/app/module/article_approvals/response" + articlesService "netidhub-saas-be/app/module/articles/service" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" - utilSvc "web-medols-be/utils/service" + utilSvc "netidhub-saas-be/utils/service" ) // ArticleApprovalsService diff --git a/app/module/article_categories/article_categories.module.go b/app/module/article_categories/article_categories.module.go index 3dbda68..47f452a 100644 --- a/app/module/article_categories/article_categories.module.go +++ b/app/module/article_categories/article_categories.module.go @@ -3,9 +3,9 @@ package article_categories import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/article_categories/controller" - "web-medols-be/app/module/article_categories/repository" - "web-medols-be/app/module/article_categories/service" + "netidhub-saas-be/app/module/article_categories/controller" + "netidhub-saas-be/app/module/article_categories/repository" + "netidhub-saas-be/app/module/article_categories/service" ) // struct of ArticleCategoriesRouter diff --git a/app/module/article_categories/controller/article_categories.controller.go b/app/module/article_categories/controller/article_categories.controller.go index 42d5249..03213ba 100644 --- a/app/module/article_categories/controller/article_categories.controller.go +++ b/app/module/article_categories/controller/article_categories.controller.go @@ -1,16 +1,16 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/article_categories/request" + "netidhub-saas-be/app/module/article_categories/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/article_categories/request" - "web-medols-be/app/module/article_categories/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type articleCategoriesController struct { diff --git a/app/module/article_categories/controller/controller.go b/app/module/article_categories/controller/controller.go index 1a0bdd1..a0b9803 100644 --- a/app/module/article_categories/controller/controller.go +++ b/app/module/article_categories/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/article_categories/service" +import "netidhub-saas-be/app/module/article_categories/service" type Controller struct { ArticleCategories ArticleCategoriesController diff --git a/app/module/article_categories/mapper/article_categories.mapper.go b/app/module/article_categories/mapper/article_categories.mapper.go index 1f86ba7..9a9ab3e 100644 --- a/app/module/article_categories/mapper/article_categories.mapper.go +++ b/app/module/article_categories/mapper/article_categories.mapper.go @@ -1,10 +1,10 @@ package mapper import ( + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/article_categories/response" "strconv" "strings" - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/article_categories/response" ) func ArticleCategoriesResponseMapper(articleCategoriesReq *entity.ArticleCategories, host string) (articleCategoriesRes *res.ArticleCategoriesResponse) { diff --git a/app/module/article_categories/repository/article_categories.repository.go b/app/module/article_categories/repository/article_categories.repository.go index 2a65abc..83e8326 100644 --- a/app/module/article_categories/repository/article_categories.repository.go +++ b/app/module/article_categories/repository/article_categories.repository.go @@ -4,12 +4,12 @@ import ( "fmt" "github.com/google/uuid" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_categories/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_categories/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type articleCategoriesRepository struct { diff --git a/app/module/article_categories/request/article_categories.request.go b/app/module/article_categories/request/article_categories.request.go index 9a275f0..f9e5856 100644 --- a/app/module/article_categories/request/article_categories.request.go +++ b/app/module/article_categories/request/article_categories.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type ArticleCategoriesGeneric interface { diff --git a/app/module/article_categories/service/article_categories.service.go b/app/module/article_categories/service/article_categories.service.go index 28701fe..78f0a3d 100644 --- a/app/module/article_categories/service/article_categories.service.go +++ b/app/module/article_categories/service/article_categories.service.go @@ -10,20 +10,20 @@ import ( "log" "math/rand" "mime" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_categories/mapper" + "netidhub-saas-be/app/module/article_categories/repository" + "netidhub-saas-be/app/module/article_categories/request" + "netidhub-saas-be/app/module/article_categories/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + config "netidhub-saas-be/config/config" + minioStorage "netidhub-saas-be/config/config" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "path/filepath" "strconv" "strings" "time" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_categories/mapper" - "web-medols-be/app/module/article_categories/repository" - "web-medols-be/app/module/article_categories/request" - "web-medols-be/app/module/article_categories/response" - usersRepository "web-medols-be/app/module/users/repository" - config "web-medols-be/config/config" - minioStorage "web-medols-be/config/config" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) // ArticleCategoriesService diff --git a/app/module/article_category_details/article_category_details.module.go b/app/module/article_category_details/article_category_details.module.go index c69669a..1950513 100644 --- a/app/module/article_category_details/article_category_details.module.go +++ b/app/module/article_category_details/article_category_details.module.go @@ -3,9 +3,9 @@ package article_category_details import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/article_category_details/controller" - "web-medols-be/app/module/article_category_details/repository" - "web-medols-be/app/module/article_category_details/service" + "netidhub-saas-be/app/module/article_category_details/controller" + "netidhub-saas-be/app/module/article_category_details/repository" + "netidhub-saas-be/app/module/article_category_details/service" ) // struct of ArticleCategoryDetailsRouter diff --git a/app/module/article_category_details/controller/article_category_details.controller.go b/app/module/article_category_details/controller/article_category_details.controller.go index ad8662a..4eaf2c9 100644 --- a/app/module/article_category_details/controller/article_category_details.controller.go +++ b/app/module/article_category_details/controller/article_category_details.controller.go @@ -1,15 +1,15 @@ package controller import ( + "netidhub-saas-be/app/module/article_category_details/request" + "netidhub-saas-be/app/module/article_category_details/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/article_category_details/request" - "web-medols-be/app/module/article_category_details/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type articleCategoryDetailsController struct { diff --git a/app/module/article_category_details/controller/controller.go b/app/module/article_category_details/controller/controller.go index 097b5d8..91a26b2 100644 --- a/app/module/article_category_details/controller/controller.go +++ b/app/module/article_category_details/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/article_category_details/service" +import "netidhub-saas-be/app/module/article_category_details/service" type Controller struct { ArticleCategoryDetails ArticleCategoryDetailsController diff --git a/app/module/article_category_details/mapper/article_category_details.mapper.go b/app/module/article_category_details/mapper/article_category_details.mapper.go index e933de3..c6f2414 100644 --- a/app/module/article_category_details/mapper/article_category_details.mapper.go +++ b/app/module/article_category_details/mapper/article_category_details.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity/article_category_details" - res "web-medols-be/app/module/article_category_details/response" + "netidhub-saas-be/app/database/entity/article_category_details" + res "netidhub-saas-be/app/module/article_category_details/response" ) func ArticleCategoryDetailsResponseMapper(articleCategoryDetailsReq *article_category_details.ArticleCategoryDetails) (articleCategoryDetailsRes *res.ArticleCategoryDetailsResponse) { diff --git a/app/module/article_category_details/repository/article_category_details.repository.go b/app/module/article_category_details/repository/article_category_details.repository.go index 0c560aa..2aa8436 100644 --- a/app/module/article_category_details/repository/article_category_details.repository.go +++ b/app/module/article_category_details/repository/article_category_details.repository.go @@ -1,10 +1,10 @@ package repository import ( - "web-medols-be/app/database" - "web-medols-be/app/database/entity/article_category_details" - "web-medols-be/app/module/article_category_details/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity/article_category_details" + "netidhub-saas-be/app/module/article_category_details/request" + "netidhub-saas-be/utils/paginator" ) type articleCategoryDetailsRepository struct { diff --git a/app/module/article_category_details/request/article_category_details.request.go b/app/module/article_category_details/request/article_category_details.request.go index 88b1e83..13c78f3 100644 --- a/app/module/article_category_details/request/article_category_details.request.go +++ b/app/module/article_category_details/request/article_category_details.request.go @@ -1,9 +1,9 @@ package request import ( + "netidhub-saas-be/app/database/entity/article_category_details" + "netidhub-saas-be/utils/paginator" "time" - "web-medols-be/app/database/entity/article_category_details" - "web-medols-be/utils/paginator" ) type ArticleCategoryDetailsGeneric interface { diff --git a/app/module/article_category_details/service/article_category_details.service.go b/app/module/article_category_details/service/article_category_details.service.go index 9dd6736..10b21d0 100644 --- a/app/module/article_category_details/service/article_category_details.service.go +++ b/app/module/article_category_details/service/article_category_details.service.go @@ -2,11 +2,11 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/module/article_category_details/mapper" - "web-medols-be/app/module/article_category_details/repository" - "web-medols-be/app/module/article_category_details/request" - "web-medols-be/app/module/article_category_details/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/article_category_details/mapper" + "netidhub-saas-be/app/module/article_category_details/repository" + "netidhub-saas-be/app/module/article_category_details/request" + "netidhub-saas-be/app/module/article_category_details/response" + "netidhub-saas-be/utils/paginator" ) // ArticleCategoryDetailsService diff --git a/app/module/article_comments/article_comments.module.go b/app/module/article_comments/article_comments.module.go index b246de0..3aedf9d 100644 --- a/app/module/article_comments/article_comments.module.go +++ b/app/module/article_comments/article_comments.module.go @@ -3,9 +3,9 @@ package article_comments import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/article_comments/controller" - "web-medols-be/app/module/article_comments/repository" - "web-medols-be/app/module/article_comments/service" + "netidhub-saas-be/app/module/article_comments/controller" + "netidhub-saas-be/app/module/article_comments/repository" + "netidhub-saas-be/app/module/article_comments/service" ) // struct of ArticleCommentsRouter diff --git a/app/module/article_comments/controller/article_comments.controller.go b/app/module/article_comments/controller/article_comments.controller.go index 3270221..1e122ef 100644 --- a/app/module/article_comments/controller/article_comments.controller.go +++ b/app/module/article_comments/controller/article_comments.controller.go @@ -1,13 +1,13 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/article_comments/request" + "netidhub-saas-be/app/module/article_comments/service" + "netidhub-saas-be/utils/paginator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/article_comments/request" - "web-medols-be/app/module/article_comments/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/article_comments/controller/controller.go b/app/module/article_comments/controller/controller.go index 1a81285..ef29def 100644 --- a/app/module/article_comments/controller/controller.go +++ b/app/module/article_comments/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/article_comments/service" + "netidhub-saas-be/app/module/article_comments/service" ) type Controller struct { diff --git a/app/module/article_comments/mapper/article_comments.mapper.go b/app/module/article_comments/mapper/article_comments.mapper.go index e6d0962..887c1b4 100644 --- a/app/module/article_comments/mapper/article_comments.mapper.go +++ b/app/module/article_comments/mapper/article_comments.mapper.go @@ -2,9 +2,9 @@ package mapper import ( "github.com/google/uuid" - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/article_comments/response" - usersRepository "web-medols-be/app/module/users/repository" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/article_comments/response" + usersRepository "netidhub-saas-be/app/module/users/repository" ) func ArticleCommentsResponseMapper(clientId *uuid.UUID, articleCommentsReq *entity.ArticleComments, usersRepo usersRepository.UsersRepository) (articleCommentsRes *res.ArticleCommentsResponse) { diff --git a/app/module/article_comments/repository/article_comments.repository.go b/app/module/article_comments/repository/article_comments.repository.go index a2ee5ca..6d9eb2e 100644 --- a/app/module/article_comments/repository/article_comments.repository.go +++ b/app/module/article_comments/repository/article_comments.repository.go @@ -4,12 +4,12 @@ import ( "fmt" "github.com/google/uuid" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_comments/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_comments/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type articleCommentsRepository struct { diff --git a/app/module/article_comments/request/article_comments.request.go b/app/module/article_comments/request/article_comments.request.go index 7b054d7..d034431 100644 --- a/app/module/article_comments/request/article_comments.request.go +++ b/app/module/article_comments/request/article_comments.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type ArticleCommentsGeneric interface { diff --git a/app/module/article_comments/service/article_comments.service.go b/app/module/article_comments/service/article_comments.service.go index 7630443..f57d1f4 100644 --- a/app/module/article_comments/service/article_comments.service.go +++ b/app/module/article_comments/service/article_comments.service.go @@ -3,15 +3,15 @@ package service import ( "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_comments/mapper" - "web-medols-be/app/module/article_comments/repository" - "web-medols-be/app/module/article_comments/request" - "web-medols-be/app/module/article_comments/response" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_comments/mapper" + "netidhub-saas-be/app/module/article_comments/repository" + "netidhub-saas-be/app/module/article_comments/request" + "netidhub-saas-be/app/module/article_comments/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" - utilSvc "web-medols-be/utils/service" + utilSvc "netidhub-saas-be/utils/service" ) // ArticleCommentsService diff --git a/app/module/article_files/article_files.module.go b/app/module/article_files/article_files.module.go index 6f7d757..3b06059 100644 --- a/app/module/article_files/article_files.module.go +++ b/app/module/article_files/article_files.module.go @@ -3,9 +3,9 @@ package article_files import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/article_files/controller" - "web-medols-be/app/module/article_files/repository" - "web-medols-be/app/module/article_files/service" + "netidhub-saas-be/app/module/article_files/controller" + "netidhub-saas-be/app/module/article_files/repository" + "netidhub-saas-be/app/module/article_files/service" ) // struct of ArticleFilesRouter diff --git a/app/module/article_files/controller/article_files.controller.go b/app/module/article_files/controller/article_files.controller.go index 1a731b4..33f9271 100644 --- a/app/module/article_files/controller/article_files.controller.go +++ b/app/module/article_files/controller/article_files.controller.go @@ -2,13 +2,13 @@ package controller import ( "fmt" + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/article_files/request" + "netidhub-saas-be/app/module/article_files/service" + "netidhub-saas-be/utils/paginator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/article_files/request" - "web-medols-be/app/module/article_files/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" "github.com/gofiber/fiber/v2" ) diff --git a/app/module/article_files/controller/controller.go b/app/module/article_files/controller/controller.go index 16163fd..cfbf501 100644 --- a/app/module/article_files/controller/controller.go +++ b/app/module/article_files/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/article_files/service" +import "netidhub-saas-be/app/module/article_files/service" type Controller struct { ArticleFiles ArticleFilesController diff --git a/app/module/article_files/mapper/article_files.mapper.go b/app/module/article_files/mapper/article_files.mapper.go index 9645451..8ca3547 100644 --- a/app/module/article_files/mapper/article_files.mapper.go +++ b/app/module/article_files/mapper/article_files.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/article_files/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/article_files/response" ) func ArticleFilesResponseMapper(articleFilesReq *entity.ArticleFiles, host string) (articleFilesRes *res.ArticleFilesResponse) { diff --git a/app/module/article_files/repository/article_files.repository.go b/app/module/article_files/repository/article_files.repository.go index d55eb82..9602212 100644 --- a/app/module/article_files/repository/article_files.repository.go +++ b/app/module/article_files/repository/article_files.repository.go @@ -3,12 +3,12 @@ package repository import ( "fmt" "github.com/google/uuid" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_files/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_files/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type articleFilesRepository struct { diff --git a/app/module/article_files/request/article_files.request.go b/app/module/article_files/request/article_files.request.go index f6a6861..006cb4d 100644 --- a/app/module/article_files/request/article_files.request.go +++ b/app/module/article_files/request/article_files.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type ArticleFilesGeneric interface { diff --git a/app/module/article_files/service/article_files.service.go b/app/module/article_files/service/article_files.service.go index 72237f9..45dd437 100644 --- a/app/module/article_files/service/article_files.service.go +++ b/app/module/article_files/service/article_files.service.go @@ -12,19 +12,19 @@ import ( "math/rand" "mime" "mime/multipart" + "netidhub-saas-be/app/module/article_files/mapper" + "netidhub-saas-be/app/module/article_files/repository" + "netidhub-saas-be/app/module/article_files/request" + "netidhub-saas-be/app/module/article_files/response" + config "netidhub-saas-be/config/config" + minioStorage "netidhub-saas-be/config/config" + "netidhub-saas-be/utils/paginator" "os" "path/filepath" "strconv" "strings" "sync" "time" - "web-medols-be/app/module/article_files/mapper" - "web-medols-be/app/module/article_files/repository" - "web-medols-be/app/module/article_files/request" - "web-medols-be/app/module/article_files/response" - config "web-medols-be/config/config" - minioStorage "web-medols-be/config/config" - "web-medols-be/utils/paginator" ) // ArticleFilesService diff --git a/app/module/article_nulis_ai/article_nulis_ai.module.go b/app/module/article_nulis_ai/article_nulis_ai.module.go index f47bbee..cdf97ca 100644 --- a/app/module/article_nulis_ai/article_nulis_ai.module.go +++ b/app/module/article_nulis_ai/article_nulis_ai.module.go @@ -3,9 +3,9 @@ package article_nulis_ai import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/article_nulis_ai/controller" - "web-medols-be/app/module/article_nulis_ai/repository" - "web-medols-be/app/module/article_nulis_ai/service" + "netidhub-saas-be/app/module/article_nulis_ai/controller" + "netidhub-saas-be/app/module/article_nulis_ai/repository" + "netidhub-saas-be/app/module/article_nulis_ai/service" ) // struct of ArticleNulisAIRouter diff --git a/app/module/article_nulis_ai/controller/article_nulis_ai.controller.go b/app/module/article_nulis_ai/controller/article_nulis_ai.controller.go index 0e849f7..eb5a698 100644 --- a/app/module/article_nulis_ai/controller/article_nulis_ai.controller.go +++ b/app/module/article_nulis_ai/controller/article_nulis_ai.controller.go @@ -1,12 +1,12 @@ package controller import ( + "netidhub-saas-be/app/module/article_nulis_ai/request" + "netidhub-saas-be/app/module/article_nulis_ai/service" + "netidhub-saas-be/utils/paginator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "strconv" - "web-medols-be/app/module/article_nulis_ai/request" - "web-medols-be/app/module/article_nulis_ai/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/article_nulis_ai/controller/controller.go b/app/module/article_nulis_ai/controller/controller.go index c2f3815..38028dd 100644 --- a/app/module/article_nulis_ai/controller/controller.go +++ b/app/module/article_nulis_ai/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/article_nulis_ai/service" + "netidhub-saas-be/app/module/article_nulis_ai/service" ) type Controller struct { diff --git a/app/module/article_nulis_ai/mapper/article_nulis_ai.mapper.go b/app/module/article_nulis_ai/mapper/article_nulis_ai.mapper.go index a4fdf56..653a8a7 100644 --- a/app/module/article_nulis_ai/mapper/article_nulis_ai.mapper.go +++ b/app/module/article_nulis_ai/mapper/article_nulis_ai.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/article_nulis_ai/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/article_nulis_ai/response" ) func ArticleNulisAIResponseMapper(articleNulisAIReq *entity.ArticleNulisAI) (articleNulisAIRes *res.ArticleNulisAIResponse) { diff --git a/app/module/article_nulis_ai/repository/article_nulis_ai.repository.go b/app/module/article_nulis_ai/repository/article_nulis_ai.repository.go index ac79db8..5de28d8 100644 --- a/app/module/article_nulis_ai/repository/article_nulis_ai.repository.go +++ b/app/module/article_nulis_ai/repository/article_nulis_ai.repository.go @@ -3,11 +3,11 @@ package repository import ( "fmt" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_nulis_ai/request" + "netidhub-saas-be/utils/paginator" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_nulis_ai/request" - "web-medols-be/utils/paginator" ) type articleNulisAIRepository struct { diff --git a/app/module/article_nulis_ai/request/article_nulis_ai.request.go b/app/module/article_nulis_ai/request/article_nulis_ai.request.go index 07dfccc..466a975 100644 --- a/app/module/article_nulis_ai/request/article_nulis_ai.request.go +++ b/app/module/article_nulis_ai/request/article_nulis_ai.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type ArticleNulisAIGeneric interface { diff --git a/app/module/article_nulis_ai/service/article_nulis_ai.service.go b/app/module/article_nulis_ai/service/article_nulis_ai.service.go index ed996b3..20fd1fc 100644 --- a/app/module/article_nulis_ai/service/article_nulis_ai.service.go +++ b/app/module/article_nulis_ai/service/article_nulis_ai.service.go @@ -2,17 +2,17 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/article_nulis_ai/mapper" - "web-medols-be/app/module/article_nulis_ai/repository" - "web-medols-be/app/module/article_nulis_ai/request" - "web-medols-be/app/module/article_nulis_ai/response" - articlesRepository "web-medols-be/app/module/articles/repository" - articles "web-medols-be/app/module/articles/request" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/article_nulis_ai/mapper" + "netidhub-saas-be/app/module/article_nulis_ai/repository" + "netidhub-saas-be/app/module/article_nulis_ai/request" + "netidhub-saas-be/app/module/article_nulis_ai/response" + articlesRepository "netidhub-saas-be/app/module/articles/repository" + articles "netidhub-saas-be/app/module/articles/request" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" - utilSvc "web-medols-be/utils/service" + utilSvc "netidhub-saas-be/utils/service" ) // ArticleNulisAIService diff --git a/app/module/articles/articles.module.go b/app/module/articles/articles.module.go index 79e0ae4..4ef003e 100644 --- a/app/module/articles/articles.module.go +++ b/app/module/articles/articles.module.go @@ -1,11 +1,11 @@ package articles import ( - "web-medols-be/app/middleware" - "web-medols-be/app/module/articles/controller" - "web-medols-be/app/module/articles/repository" - "web-medols-be/app/module/articles/service" - usersRepo "web-medols-be/app/module/users/repository" + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/articles/controller" + "netidhub-saas-be/app/module/articles/repository" + "netidhub-saas-be/app/module/articles/service" + usersRepo "netidhub-saas-be/app/module/users/repository" "github.com/gofiber/fiber/v2" "go.uber.org/fx" diff --git a/app/module/articles/controller/articles.controller.go b/app/module/articles/controller/articles.controller.go index b10766a..86c24f3 100644 --- a/app/module/articles/controller/articles.controller.go +++ b/app/module/articles/controller/articles.controller.go @@ -1,17 +1,17 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/articles/request" + "netidhub-saas-be/app/module/articles/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/articles/request" - "web-medols-be/app/module/articles/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type articlesController struct { diff --git a/app/module/articles/controller/controller.go b/app/module/articles/controller/controller.go index 3b50fe8..cc892a9 100644 --- a/app/module/articles/controller/controller.go +++ b/app/module/articles/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/articles/service" + "netidhub-saas-be/app/module/articles/service" ) type Controller struct { diff --git a/app/module/articles/mapper/articles.mapper.go b/app/module/articles/mapper/articles.mapper.go index b1982e0..8a7350c 100644 --- a/app/module/articles/mapper/articles.mapper.go +++ b/app/module/articles/mapper/articles.mapper.go @@ -3,16 +3,16 @@ package mapper import ( "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - articleCategoriesMapper "web-medols-be/app/module/article_categories/mapper" - articleCategoriesRepository "web-medols-be/app/module/article_categories/repository" - articleCategoriesResponse "web-medols-be/app/module/article_categories/response" - articleCategoryDetailsRepository "web-medols-be/app/module/article_category_details/repository" - articleFilesMapper "web-medols-be/app/module/article_files/mapper" - articleFilesRepository "web-medols-be/app/module/article_files/repository" - articleFilesResponse "web-medols-be/app/module/article_files/response" - res "web-medols-be/app/module/articles/response" - usersRepository "web-medols-be/app/module/users/repository" + "netidhub-saas-be/app/database/entity" + articleCategoriesMapper "netidhub-saas-be/app/module/article_categories/mapper" + articleCategoriesRepository "netidhub-saas-be/app/module/article_categories/repository" + articleCategoriesResponse "netidhub-saas-be/app/module/article_categories/response" + articleCategoryDetailsRepository "netidhub-saas-be/app/module/article_category_details/repository" + articleFilesMapper "netidhub-saas-be/app/module/article_files/mapper" + articleFilesRepository "netidhub-saas-be/app/module/article_files/repository" + articleFilesResponse "netidhub-saas-be/app/module/article_files/response" + res "netidhub-saas-be/app/module/articles/response" + usersRepository "netidhub-saas-be/app/module/users/repository" ) func ArticlesResponseMapper( diff --git a/app/module/articles/repository/articles.repository.go b/app/module/articles/repository/articles.repository.go index 526a27e..53a33b8 100644 --- a/app/module/articles/repository/articles.repository.go +++ b/app/module/articles/repository/articles.repository.go @@ -2,14 +2,14 @@ package repository import ( "fmt" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/articles/request" + "netidhub-saas-be/app/module/articles/response" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" "time" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/articles/request" - "web-medols-be/app/module/articles/response" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/articles/request/articles.request.go b/app/module/articles/request/articles.request.go index 0167b45..c4dc01f 100644 --- a/app/module/articles/request/articles.request.go +++ b/app/module/articles/request/articles.request.go @@ -2,10 +2,10 @@ package request import ( "errors" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type ArticlesGeneric interface { @@ -185,7 +185,7 @@ func (req ArticlesQueryRequestContext) ToParamRequest() ArticlesQueryRequest { // SubmitForApprovalRequest represents the request for submitting an article for approval type SubmitForApprovalRequest struct { - WorkflowId *uint `json:"workflow_id" validate:"omitempty,min=1"` + WorkflowId *uint `json:"workflow_id" validate:"omitempty,min=1"` Message *string `json:"message" validate:"omitempty,max=500"` } diff --git a/app/module/articles/response/articles.response.go b/app/module/articles/response/articles.response.go index 50ee5bc..6757318 100644 --- a/app/module/articles/response/articles.response.go +++ b/app/module/articles/response/articles.response.go @@ -1,9 +1,9 @@ package response import ( + articleCategoriesResponse "netidhub-saas-be/app/module/article_categories/response" + articleFilesResponse "netidhub-saas-be/app/module/article_files/response" "time" - articleCategoriesResponse "web-medols-be/app/module/article_categories/response" - articleFilesResponse "web-medols-be/app/module/article_files/response" ) type ArticlesResponse struct { diff --git a/app/module/articles/service/articles.service.go b/app/module/articles/service/articles.service.go index 94e574c..8091d1e 100644 --- a/app/module/articles/service/articles.service.go +++ b/app/module/articles/service/articles.service.go @@ -8,27 +8,27 @@ import ( "log" "math/rand" "mime" + "netidhub-saas-be/app/database/entity" + approvalWorkflowsRepository "netidhub-saas-be/app/module/approval_workflows/repository" + articleApprovalFlowsRepository "netidhub-saas-be/app/module/article_approval_flows/repository" + articleApprovalsRepository "netidhub-saas-be/app/module/article_approvals/repository" + articleCategoriesRepository "netidhub-saas-be/app/module/article_categories/repository" + articleCategoryDetailsRepository "netidhub-saas-be/app/module/article_category_details/repository" + articleCategoryDetailsReq "netidhub-saas-be/app/module/article_category_details/request" + articleFilesRepository "netidhub-saas-be/app/module/article_files/repository" + "netidhub-saas-be/app/module/articles/mapper" + "netidhub-saas-be/app/module/articles/repository" + "netidhub-saas-be/app/module/articles/request" + "netidhub-saas-be/app/module/articles/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + config "netidhub-saas-be/config/config" + minioStorage "netidhub-saas-be/config/config" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "path/filepath" "strconv" "strings" "time" - "web-medols-be/app/database/entity" - approvalWorkflowsRepository "web-medols-be/app/module/approval_workflows/repository" - articleApprovalFlowsRepository "web-medols-be/app/module/article_approval_flows/repository" - articleApprovalsRepository "web-medols-be/app/module/article_approvals/repository" - articleCategoriesRepository "web-medols-be/app/module/article_categories/repository" - articleCategoryDetailsRepository "web-medols-be/app/module/article_category_details/repository" - articleCategoryDetailsReq "web-medols-be/app/module/article_category_details/request" - articleFilesRepository "web-medols-be/app/module/article_files/repository" - "web-medols-be/app/module/articles/mapper" - "web-medols-be/app/module/articles/repository" - "web-medols-be/app/module/articles/request" - "web-medols-be/app/module/articles/response" - usersRepository "web-medols-be/app/module/users/repository" - config "web-medols-be/config/config" - minioStorage "web-medols-be/config/config" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" "github.com/gofiber/fiber/v2" "github.com/google/uuid" diff --git a/app/module/bookmarks/bookmarks.module.go b/app/module/bookmarks/bookmarks.module.go index 4b6f3a7..e21a00d 100644 --- a/app/module/bookmarks/bookmarks.module.go +++ b/app/module/bookmarks/bookmarks.module.go @@ -1,11 +1,11 @@ package bookmarks import ( - "web-medols-be/app/middleware" - "web-medols-be/app/module/bookmarks/controller" - "web-medols-be/app/module/bookmarks/repository" - "web-medols-be/app/module/bookmarks/service" - usersRepo "web-medols-be/app/module/users/repository" + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/bookmarks/controller" + "netidhub-saas-be/app/module/bookmarks/repository" + "netidhub-saas-be/app/module/bookmarks/service" + usersRepo "netidhub-saas-be/app/module/users/repository" "github.com/gofiber/fiber/v2" "go.uber.org/fx" diff --git a/app/module/bookmarks/controller/bookmarks.controller.go b/app/module/bookmarks/controller/bookmarks.controller.go index 300525f..a0e5ff7 100644 --- a/app/module/bookmarks/controller/bookmarks.controller.go +++ b/app/module/bookmarks/controller/bookmarks.controller.go @@ -1,17 +1,17 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/bookmarks/request" + "netidhub-saas-be/app/module/bookmarks/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/bookmarks/request" - "web-medols-be/app/module/bookmarks/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type bookmarksController struct { diff --git a/app/module/bookmarks/mapper/bookmarks.mapper.go b/app/module/bookmarks/mapper/bookmarks.mapper.go index b2e855b..d1329bc 100644 --- a/app/module/bookmarks/mapper/bookmarks.mapper.go +++ b/app/module/bookmarks/mapper/bookmarks.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - "web-medols-be/app/module/bookmarks/response" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/bookmarks/response" ) func ToBookmarksResponse(bookmark *entity.Bookmarks) *response.BookmarksResponse { diff --git a/app/module/bookmarks/repository/bookmarks.repository.go b/app/module/bookmarks/repository/bookmarks.repository.go index 9e8eca4..c279ab7 100644 --- a/app/module/bookmarks/repository/bookmarks.repository.go +++ b/app/module/bookmarks/repository/bookmarks.repository.go @@ -1,10 +1,10 @@ package repository import ( - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/bookmarks/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/bookmarks/request" + "netidhub-saas-be/utils/paginator" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/bookmarks/request/bookmarks.request.go b/app/module/bookmarks/request/bookmarks.request.go index be3a26f..6469bd8 100644 --- a/app/module/bookmarks/request/bookmarks.request.go +++ b/app/module/bookmarks/request/bookmarks.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type BookmarksGeneric interface { diff --git a/app/module/bookmarks/service/bookmarks.service.go b/app/module/bookmarks/service/bookmarks.service.go index 6b7139f..9e06ac6 100644 --- a/app/module/bookmarks/service/bookmarks.service.go +++ b/app/module/bookmarks/service/bookmarks.service.go @@ -2,15 +2,15 @@ package service import ( "errors" - "web-medols-be/app/database/entity" - articlesRepository "web-medols-be/app/module/articles/repository" - "web-medols-be/app/module/bookmarks/mapper" - "web-medols-be/app/module/bookmarks/repository" - "web-medols-be/app/module/bookmarks/request" - "web-medols-be/app/module/bookmarks/response" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" + "netidhub-saas-be/app/database/entity" + articlesRepository "netidhub-saas-be/app/module/articles/repository" + "netidhub-saas-be/app/module/bookmarks/mapper" + "netidhub-saas-be/app/module/bookmarks/repository" + "netidhub-saas-be/app/module/bookmarks/request" + "netidhub-saas-be/app/module/bookmarks/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/cities/cities.module.go b/app/module/cities/cities.module.go index 105c80d..2fae3f1 100644 --- a/app/module/cities/cities.module.go +++ b/app/module/cities/cities.module.go @@ -3,9 +3,9 @@ package cities import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/cities/controller" - "web-medols-be/app/module/cities/repository" - "web-medols-be/app/module/cities/service" + "netidhub-saas-be/app/module/cities/controller" + "netidhub-saas-be/app/module/cities/repository" + "netidhub-saas-be/app/module/cities/service" ) // struct of CitiesRouter diff --git a/app/module/cities/controller/cities.controller.go b/app/module/cities/controller/cities.controller.go index f8cf0fe..97e4d7c 100644 --- a/app/module/cities/controller/cities.controller.go +++ b/app/module/cities/controller/cities.controller.go @@ -2,13 +2,13 @@ package controller import ( "github.com/gofiber/fiber/v2" + "netidhub-saas-be/app/module/cities/request" + "netidhub-saas-be/app/module/cities/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/cities/request" - "web-medols-be/app/module/cities/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type citiesController struct { diff --git a/app/module/cities/controller/controller.go b/app/module/cities/controller/controller.go index 733acdf..7050180 100644 --- a/app/module/cities/controller/controller.go +++ b/app/module/cities/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/cities/service" +import "netidhub-saas-be/app/module/cities/service" type Controller struct { Cities CitiesController diff --git a/app/module/cities/mapper/cities.mapper.go b/app/module/cities/mapper/cities.mapper.go index 405dafe..3dabcc0 100644 --- a/app/module/cities/mapper/cities.mapper.go +++ b/app/module/cities/mapper/cities.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/cities/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/cities/response" ) func CitiesResponseMapper(citiesReq *entity.Cities) (citiesRes *res.CitiesResponse) { diff --git a/app/module/cities/repository/cities.repository.go b/app/module/cities/repository/cities.repository.go index 21272c3..87474b3 100644 --- a/app/module/cities/repository/cities.repository.go +++ b/app/module/cities/repository/cities.repository.go @@ -1,10 +1,10 @@ package repository import ( - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/cities/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/cities/request" + "netidhub-saas-be/utils/paginator" ) type citiesRepository struct { diff --git a/app/module/cities/request/cities.request.go b/app/module/cities/request/cities.request.go index dcda863..34e3122 100644 --- a/app/module/cities/request/cities.request.go +++ b/app/module/cities/request/cities.request.go @@ -1,8 +1,8 @@ package request import ( - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" ) type CitiesGeneric interface { diff --git a/app/module/cities/service/cities.service.go b/app/module/cities/service/cities.service.go index 6ded9e4..80d9883 100644 --- a/app/module/cities/service/cities.service.go +++ b/app/module/cities/service/cities.service.go @@ -2,11 +2,11 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/module/cities/mapper" - "web-medols-be/app/module/cities/repository" - "web-medols-be/app/module/cities/request" - "web-medols-be/app/module/cities/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/cities/mapper" + "netidhub-saas-be/app/module/cities/repository" + "netidhub-saas-be/app/module/cities/request" + "netidhub-saas-be/app/module/cities/response" + "netidhub-saas-be/utils/paginator" ) // CitiesService diff --git a/app/module/client_approval_settings/client_approval_settings.module.go b/app/module/client_approval_settings/client_approval_settings.module.go index f87d2c7..4d0193d 100644 --- a/app/module/client_approval_settings/client_approval_settings.module.go +++ b/app/module/client_approval_settings/client_approval_settings.module.go @@ -1,9 +1,9 @@ package client_approval_settings import ( - "web-medols-be/app/module/client_approval_settings/controller" - "web-medols-be/app/module/client_approval_settings/repository" - "web-medols-be/app/module/client_approval_settings/service" + "netidhub-saas-be/app/module/client_approval_settings/controller" + "netidhub-saas-be/app/module/client_approval_settings/repository" + "netidhub-saas-be/app/module/client_approval_settings/service" "github.com/gofiber/fiber/v2" "go.uber.org/fx" diff --git a/app/module/client_approval_settings/controller/client_approval_settings.controller.go b/app/module/client_approval_settings/controller/client_approval_settings.controller.go index 38fc859..99cbbf5 100644 --- a/app/module/client_approval_settings/controller/client_approval_settings.controller.go +++ b/app/module/client_approval_settings/controller/client_approval_settings.controller.go @@ -2,12 +2,12 @@ package controller import ( "fmt" + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/client_approval_settings/request" + "netidhub-saas-be/app/module/client_approval_settings/service" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/client_approval_settings/request" - "web-medols-be/app/module/client_approval_settings/service" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/client_approval_settings/controller/controller.go b/app/module/client_approval_settings/controller/controller.go index dd5d80f..3a1491c 100644 --- a/app/module/client_approval_settings/controller/controller.go +++ b/app/module/client_approval_settings/controller/controller.go @@ -1,7 +1,7 @@ package controller import ( - "web-medols-be/app/module/client_approval_settings/service" + "netidhub-saas-be/app/module/client_approval_settings/service" "github.com/rs/zerolog" ) diff --git a/app/module/client_approval_settings/mapper/client_approval_settings.mapper.go b/app/module/client_approval_settings/mapper/client_approval_settings.mapper.go index c6e69cb..5c318b0 100644 --- a/app/module/client_approval_settings/mapper/client_approval_settings.mapper.go +++ b/app/module/client_approval_settings/mapper/client_approval_settings.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/client_approval_settings/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/client_approval_settings/response" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/client_approval_settings/repository/client_approval_settings.repository.go b/app/module/client_approval_settings/repository/client_approval_settings.repository.go index 0d5d43c..4bd9fd2 100644 --- a/app/module/client_approval_settings/repository/client_approval_settings.repository.go +++ b/app/module/client_approval_settings/repository/client_approval_settings.repository.go @@ -1,7 +1,7 @@ package repository import ( - "web-medols-be/app/database/entity" + "netidhub-saas-be/app/database/entity" "github.com/google/uuid" ) diff --git a/app/module/client_approval_settings/repository/client_approval_settings.repository.impl.go b/app/module/client_approval_settings/repository/client_approval_settings.repository.impl.go index 828bad6..78a9acb 100644 --- a/app/module/client_approval_settings/repository/client_approval_settings.repository.impl.go +++ b/app/module/client_approval_settings/repository/client_approval_settings.repository.impl.go @@ -2,8 +2,8 @@ package repository import ( "errors" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/client_approval_settings/service/client_approval_settings.service.go b/app/module/client_approval_settings/service/client_approval_settings.service.go index 5e911c1..9ff8dd5 100644 --- a/app/module/client_approval_settings/service/client_approval_settings.service.go +++ b/app/module/client_approval_settings/service/client_approval_settings.service.go @@ -2,11 +2,11 @@ package service import ( "fmt" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/client_approval_settings/mapper" - "web-medols-be/app/module/client_approval_settings/repository" - "web-medols-be/app/module/client_approval_settings/request" - "web-medols-be/app/module/client_approval_settings/response" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/client_approval_settings/mapper" + "netidhub-saas-be/app/module/client_approval_settings/repository" + "netidhub-saas-be/app/module/client_approval_settings/request" + "netidhub-saas-be/app/module/client_approval_settings/response" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/clients/clients.module.go b/app/module/clients/clients.module.go index c13bd03..3665247 100644 --- a/app/module/clients/clients.module.go +++ b/app/module/clients/clients.module.go @@ -3,9 +3,9 @@ package clients import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/clients/controller" - "web-medols-be/app/module/clients/repository" - "web-medols-be/app/module/clients/service" + "netidhub-saas-be/app/module/clients/controller" + "netidhub-saas-be/app/module/clients/repository" + "netidhub-saas-be/app/module/clients/service" ) // struct of ClientsRouter diff --git a/app/module/clients/controller/clients.controller.go b/app/module/clients/controller/clients.controller.go index c858cbd..9625cc3 100644 --- a/app/module/clients/controller/clients.controller.go +++ b/app/module/clients/controller/clients.controller.go @@ -1,15 +1,17 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/clients/request" + "netidhub-saas-be/app/module/clients/service" + "netidhub-saas-be/utils/paginator" + "github.com/gofiber/fiber/v2" "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/module/clients/request" - "web-medols-be/app/module/clients/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type clientsController struct { @@ -23,6 +25,14 @@ type ClientsController interface { Save(c *fiber.Ctx) error Update(c *fiber.Ctx) error Delete(c *fiber.Ctx) error + + // New hierarchy endpoints + GetHierarchy(c *fiber.Ctx) error + GetSubClients(c *fiber.Ctx) error + CreateSubClient(c *fiber.Ctx) error + MoveClient(c *fiber.Ctx) error + GetClientStats(c *fiber.Ctx) error + BulkCreateSubClients(c *fiber.Ctx) error } func NewClientsController(clientsService service.ClientsService, log zerolog.Logger) ClientsController { @@ -34,11 +44,24 @@ func NewClientsController(clientsService service.ClientsService, log zerolog.Log // All get all Clients // @Summary Get all Clients -// @Description API for getting all Clients +// @Description API for getting all Clients with hierarchy filtering // @Tags Clients // @Security Bearer -// @Param req query request.ClientsQueryRequest false "query parameters" -// @Param req query paginator.Pagination false "pagination parameters" +// @Param X-Client-Key header string true "Insert the X-Client-Key" +// @Param Authorization header string false "Insert your access token" default(Bearer ) +// @Param name query string false "Filter by client name" +// @Param clientType query string false "Filter by client type (parent_client, sub_client, standalone)" +// @Param parentClientId query string false "Filter by parent client ID" +// @Param includeSubClients query boolean false "Include all descendants" +// @Param onlyParentClients query boolean false "Only clients with children" +// @Param onlyStandalone query boolean false "Only standalone clients" +// @Param onlyRootClients query boolean false "Only root level clients" +// @Param isActive query boolean false "Filter by active status" +// @Param createdById query string false "Filter by creator ID" +// @Param page query int false "Page number" +// @Param limit query int false "Items per page" +// @Param sort query string false "Sort field" +// @Param sortBy query string false "Sort direction (asc, desc)" // @Success 200 {object} response.Response // @Failure 400 {object} response.BadRequestError // @Failure 401 {object} response.UnauthorizedError @@ -51,13 +74,23 @@ func (_i *clientsController) All(c *fiber.Ctx) error { } reqContext := request.ClientsQueryRequestContext{ - Name: c.Query("name"), - CreatedById: c.Query("createdById"), + Name: c.Query("name"), + ClientType: c.Query("clientType"), + ParentClientId: c.Query("parentClientId"), + IncludeSubClients: c.Query("includeSubClients"), + OnlyParentClients: c.Query("onlyParentClients"), + OnlyStandalone: c.Query("onlyStandalone"), + IsActive: c.Query("isActive"), + CreatedById: c.Query("createdById"), } req := reqContext.ToParamRequest() req.Pagination = paginate - clientsData, paging, err := _i.clientsService.All(req) + // Get ClientId from context + clientId := middleware.GetClientID(c) + _i.Log.Info().Interface("clientId", clientId).Msg("") + + clientsData, paging, err := _i.clientsService.All(clientId, req) if err != nil { return err } @@ -113,7 +146,7 @@ func (_i *clientsController) Show(c *fiber.Ctx) error { // @Failure 500 {object} response.InternalServerError // @Router /clients [post] func (_i *clientsController) Save(c *fiber.Ctx) error { - req := new(request.ClientsCreateRequest) + req := new(request.CreateClientRequest) if err := utilVal.ParseAndValidate(c, req); err != nil { return err } @@ -150,7 +183,7 @@ func (_i *clientsController) Update(c *fiber.Ctx) error { return err } - req := new(request.ClientsUpdateRequest) + req := new(request.UpdateClientRequest) if err := utilVal.ParseAndValidate(c, req); err != nil { return err } @@ -194,3 +227,231 @@ func (_i *clientsController) Delete(c *fiber.Ctx) error { Messages: utilRes.Messages{"Clients successfully deleted"}, }) } + +// ===================================================================== +// NEW HIERARCHY ENDPOINTS +// ===================================================================== + +// GetHierarchy gets client tree structure +// @Summary Get client hierarchy +// @Description API for getting client tree structure +// @Tags Clients +// @Security Bearer +// @Param id path string true "Client ID" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /clients/{id}/hierarchy [get] +func (_i *clientsController) GetHierarchy(c *fiber.Ctx) error { + clientId, err := uuid.Parse(c.Params("id")) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{"Invalid client ID"}, + }) + } + + hierarchy, err := _i.clientsService.GetHierarchy(clientId) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{"Client not found"}, + }) + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Client hierarchy successfully retrieved"}, + Data: hierarchy, + }) +} + +// GetSubClients gets direct children +// @Summary Get sub-clients +// @Description API for getting direct children of a client +// @Tags Clients +// @Security Bearer +// @Param id path string true "Parent Client ID" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /clients/{id}/sub-clients [get] +func (_i *clientsController) GetSubClients(c *fiber.Ctx) error { + parentId, err := uuid.Parse(c.Params("id")) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{"Invalid parent client ID"}, + }) + } + + // For now, use GetAll with parent filter + req := request.ClientsQueryRequest{ + ParentClientId: &parentId, + Pagination: &paginator.Pagination{Page: 1, Limit: 100}, + } + + subClients, _, err := _i.clientsService.All(nil, req) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{"Failed to get sub-clients"}, + }) + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Sub-clients successfully retrieved"}, + Data: subClients, + }) +} + +// CreateSubClient creates client under parent +// @Summary Create sub-client +// @Description API for creating a client under a parent +// @Tags Clients +// @Security Bearer +// @Param id path string true "Parent Client ID" +// @Param payload body request.CreateClientRequest true "Required payload" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /clients/{id}/sub-clients [post] +func (_i *clientsController) CreateSubClient(c *fiber.Ctx) error { + parentId, err := uuid.Parse(c.Params("id")) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{"Invalid parent client ID"}, + }) + } + + req := new(request.CreateClientRequest) + if err := utilVal.ParseAndValidate(c, req); err != nil { + return err + } + + client, err := _i.clientsService.CreateSubClient(parentId, *req) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{err.Error()}, + }) + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Sub-client successfully created"}, + Data: client, + }) +} + +// MoveClient moves client to different parent +// @Summary Move client +// @Description API for moving a client to different parent +// @Tags Clients +// @Security Bearer +// @Param id path string true "Client ID" +// @Param payload body request.MoveClientRequest true "Required payload" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /clients/{id}/move [put] +func (_i *clientsController) MoveClient(c *fiber.Ctx) error { + clientId, err := uuid.Parse(c.Params("id")) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{"Invalid client ID"}, + }) + } + + req := new(request.MoveClientRequest) + if err := utilVal.ParseAndValidate(c, req); err != nil { + return err + } + + err = _i.clientsService.MoveClient(clientId, *req) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{err.Error()}, + }) + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Client moved successfully"}, + }) +} + +// GetClientStats gets statistics +// @Summary Get client statistics +// @Description API for getting client statistics +// @Tags Clients +// @Security Bearer +// @Param id path string true "Client ID" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /clients/{id}/stats [get] +func (_i *clientsController) GetClientStats(c *fiber.Ctx) error { + clientId, err := uuid.Parse(c.Params("id")) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{"Invalid client ID"}, + }) + } + + stats, err := _i.clientsService.GetClientStats(clientId) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{"Client not found"}, + }) + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Client statistics successfully retrieved"}, + Data: stats, + }) +} + +// BulkCreateSubClients creates multiple sub-clients +// @Summary Bulk create sub-clients +// @Description API for creating multiple sub-clients at once +// @Tags Clients +// @Security Bearer +// @Param payload body request.BulkCreateSubClientsRequest true "Required payload" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /clients/bulk-sub-clients [post] +func (_i *clientsController) BulkCreateSubClients(c *fiber.Ctx) error { + req := new(request.BulkCreateSubClientsRequest) + if err := utilVal.ParseAndValidate(c, req); err != nil { + return err + } + + result, err := _i.clientsService.BulkCreateSubClients(*req) + if err != nil { + return utilRes.Resp(c, utilRes.Response{ + Success: false, + Messages: utilRes.Messages{err.Error()}, + }) + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Bulk operation completed"}, + Data: result, + }) +} diff --git a/app/module/clients/controller/controller.go b/app/module/clients/controller/controller.go index 05936e6..a5113d0 100644 --- a/app/module/clients/controller/controller.go +++ b/app/module/clients/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/clients/service" + "netidhub-saas-be/app/module/clients/service" ) type Controller struct { diff --git a/app/module/clients/mapper/clients.mapper.go b/app/module/clients/mapper/clients.mapper.go index 9f9e3d7..f2ef8b6 100644 --- a/app/module/clients/mapper/clients.mapper.go +++ b/app/module/clients/mapper/clients.mapper.go @@ -1,17 +1,17 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/clients/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/clients/response" ) func ClientsResponseMapper(clientsReq *entity.Clients) (clientsRes *res.ClientsResponse) { if clientsReq != nil { clientsRes = &res.ClientsResponse{ - ClientID: clientsReq.ID, + ID: clientsReq.ID, Name: clientsReq.Name, - CreatedById: *clientsReq.CreatedById, - IsActive: *clientsReq.IsActive, + CreatedById: clientsReq.CreatedById, + IsActive: clientsReq.IsActive, CreatedAt: clientsReq.CreatedAt, UpdatedAt: clientsReq.UpdatedAt, } diff --git a/app/module/clients/repository/clients.repository.go b/app/module/clients/repository/clients.repository.go index 8388f76..2322169 100644 --- a/app/module/clients/repository/clients.repository.go +++ b/app/module/clients/repository/clients.repository.go @@ -2,13 +2,16 @@ package repository import ( "fmt" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/clients/request" + "netidhub-saas-be/utils/client" + "netidhub-saas-be/utils/paginator" + "strings" + "github.com/google/uuid" "github.com/rs/zerolog" - "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/clients/request" - "web-medols-be/utils/paginator" + "gorm.io/gorm" ) type clientsRepository struct { @@ -23,6 +26,15 @@ type ClientsRepository interface { Create(clients *entity.Clients) (clientsReturn *entity.Clients, err error) Update(id uuid.UUID, clients *entity.Clients) (err error) Delete(id uuid.UUID) (err error) + + // New hierarchy methods + GetWithHierarchy(clientId uuid.UUID) (*entity.Clients, error) + GetSubClients(parentId uuid.UUID, includeInactive bool) ([]entity.Clients, error) + GetAllSubClients(parentId uuid.UUID) ([]entity.Clients, error) + GetRootClients() ([]entity.Clients, error) + GetClientStats(clientId uuid.UUID) (map[string]interface{}, error) + MoveClient(clientId, newParentId uuid.UUID) error + IsParentClient(clientId uuid.UUID) (bool, error) } func NewClientsRepository(db *database.Database, logger zerolog.Logger) ClientsRepository { @@ -37,34 +49,82 @@ func (_i *clientsRepository) GetAll(req request.ClientsQueryRequest) (clientss [ var count int64 query := _i.DB.DB.Model(&entity.Clients{}) - query = query.Where("is_active = ?", true) + // Name filter if req.Name != nil && *req.Name != "" { name := strings.ToLower(*req.Name) query = query.Where("LOWER(name) LIKE ?", "%"+strings.ToLower(name)+"%") } - if req.CreatedById != nil { - query = query.Where("created_by_id = ?", req.CreatedById) + + // Type filter + if req.ClientType != nil && *req.ClientType != "" && *req.ClientType != "all" { + query = query.Where("client_type = ?", *req.ClientType) } + + // Parent filter + if req.ParentClientId != nil { + query = query.Where("parent_client_id = ?", *req.ParentClientId) + } + + // Only parent clients + if req.OnlyParentClients != nil && *req.OnlyParentClients { + query = query.Where("id IN (SELECT DISTINCT parent_client_id FROM clients WHERE parent_client_id IS NOT NULL)") + } + + // Only standalone + if req.OnlyStandalone != nil && *req.OnlyStandalone { + query = query.Where("client_type = ?", "standalone") + } + + // Active filter + if req.IsActive != nil { + query = query.Where("is_active = ?", *req.IsActive) + } else { + query = query.Where("is_active = ?", true) // Default: only active + } + + // Preload relationships + query = query.Preload("ParentClient").Preload("SubClients", "is_active = ?", true) + + // Count total records query.Count(&count) + // Apply sorting if req.Pagination.SortBy != "" { direction := "ASC" if req.Pagination.Sort == "desc" { direction = "DESC" } query.Order(fmt.Sprintf("%s %s", req.Pagination.SortBy, direction)) + } else { + direction := "DESC" + sortBy := "created_at" + query.Order(fmt.Sprintf("%s %s", sortBy, direction)) } - req.Pagination.Count = count - req.Pagination = paginator.Paging(req.Pagination) + // Apply pagination (manual calculation for better performance) + page := req.Pagination.Page + limit := req.Pagination.Limit + if page <= 0 { + page = 1 + } + if limit <= 0 { + limit = 10 + } - err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&clientss).Error + offset := (page - 1) * limit + err = query.Offset(offset).Limit(limit).Find(&clientss).Error if err != nil { return } - paging = *req.Pagination + // Create pagination response + paging = paginator.Pagination{ + Page: page, + Limit: limit, + Count: count, + TotalPage: int((count + int64(limit) - 1) / int64(limit)), + } return } @@ -91,3 +151,99 @@ func (_i *clientsRepository) Update(id uuid.UUID, clients *entity.Clients) (err func (_i *clientsRepository) Delete(id uuid.UUID) error { return _i.DB.DB.Delete(&entity.Clients{}, id).Error } + +// ===================================================================== +// NEW HIERARCHY METHODS +// ===================================================================== + +// GetWithHierarchy gets client with parent and sub-clients loaded +func (_i *clientsRepository) GetWithHierarchy(clientId uuid.UUID) (*entity.Clients, error) { + var client entity.Clients + err := _i.DB.DB.Preload("ParentClient"). + Preload("SubClients", "is_active = ?", true). + Where("id = ?", clientId). + First(&client).Error + return &client, err +} + +// GetSubClients gets direct children of a client +func (_i *clientsRepository) GetSubClients(parentId uuid.UUID, includeInactive bool) ([]entity.Clients, error) { + var clients []entity.Clients + query := _i.DB.DB.Where("parent_client_id = ?", parentId) + + if !includeInactive { + query = query.Where("is_active = ?", true) + } + + err := query.Find(&clients).Error + return clients, err +} + +// GetAllSubClients gets all descendants recursively +func (_i *clientsRepository) GetAllSubClients(parentId uuid.UUID) ([]entity.Clients, error) { + subClientIDs, err := client.GetSubClientIDs(_i.DB.DB, parentId) + if err != nil || len(subClientIDs) == 0 { + return []entity.Clients{}, err + } + + var clients []entity.Clients + err = _i.DB.DB.Where("id IN ?", subClientIDs).Find(&clients).Error + return clients, err +} + +// GetRootClients gets all clients without parent +func (_i *clientsRepository) GetRootClients() ([]entity.Clients, error) { + var clients []entity.Clients + err := _i.DB.DB.Where("parent_client_id IS NULL AND is_active = ?", true). + Find(&clients).Error + return clients, err +} + +// GetClientStats gets statistics for a client +func (_i *clientsRepository) GetClientStats(clientId uuid.UUID) (map[string]interface{}, error) { + stats := make(map[string]interface{}) + + // Count users + var userCount int64 + _i.DB.DB.Model(&entity.Users{}).Where("client_id = ? AND is_active = ?", clientId, true).Count(&userCount) + stats["total_users"] = userCount + + // Count articles + var articleCount int64 + _i.DB.DB.Model(&entity.Articles{}).Where("client_id = ? AND is_active = ?", clientId, true).Count(&articleCount) + stats["total_articles"] = articleCount + + // Count sub-clients + var subClientCount int64 + _i.DB.DB.Model(&entity.Clients{}).Where("parent_client_id = ? AND is_active = ?", clientId, true).Count(&subClientCount) + stats["sub_client_count"] = subClientCount + + return stats, nil +} + +// MoveClient moves a client to a different parent +func (_i *clientsRepository) MoveClient(clientId, newParentId uuid.UUID) error { + // Validate no circular reference + if newParentId != uuid.Nil { + // Check if newParent is a descendant of client (would create circle) + descendants, _ := client.GetSubClientIDs(_i.DB.DB, clientId) + for _, descId := range descendants { + if descId == newParentId { + return gorm.ErrInvalidData // Circular reference + } + } + } + + return _i.DB.DB.Model(&entity.Clients{}). + Where("id = ?", clientId). + Update("parent_client_id", newParentId).Error +} + +// IsParentClient checks if client has children +func (_i *clientsRepository) IsParentClient(clientId uuid.UUID) (bool, error) { + var count int64 + err := _i.DB.DB.Model(&entity.Clients{}). + Where("parent_client_id = ? AND is_active = ?", clientId, true). + Count(&count).Error + return count > 0, err +} diff --git a/app/module/clients/request/clients.request.go b/app/module/clients/request/clients.request.go index 0e8167c..8c19dd7 100644 --- a/app/module/clients/request/clients.request.go +++ b/app/module/clients/request/clients.request.go @@ -1,66 +1,143 @@ package request import ( - "strconv" - "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" + "netidhub-saas-be/utils/paginator" + + "github.com/google/uuid" ) -type ClientsGeneric interface { - ToEntity() +// ======================================================================== +// REQUEST STRUCTS - Updated for Multi-Client Hierarchy Support (camelCase) +// ======================================================================== + +// CreateClientRequest for creating new client with hierarchy support +type CreateClientRequest struct { + Name string `json:"name" validate:"required"` + Description *string `json:"description"` + ClientType string `json:"clientType" validate:"required,oneof=parent_client sub_client standalone"` // Enum validation + ParentClientId *uuid.UUID `json:"parentClientId"` // Optional: only for sub_client type + + // Resource limits + MaxUsers *int `json:"maxUsers"` + MaxStorage *int64 `json:"maxStorage"` + + // Custom settings (JSON string) + Settings *string `json:"settings"` } +// UpdateClientRequest for updating existing client +type UpdateClientRequest struct { + Name *string `json:"name"` + Description *string `json:"description"` + ClientType *string `json:"clientType" validate:"omitempty,oneof=parent_client sub_client standalone"` + ParentClientId *uuid.UUID `json:"parentClientId"` + + // Resource limits + MaxUsers *int `json:"maxUsers"` + MaxStorage *int64 `json:"maxStorage"` + + // Custom settings + Settings *string `json:"settings"` + + IsActive *bool `json:"isActive"` +} + +// ClientsQueryRequest for filtering and pagination type ClientsQueryRequest struct { - Name *string `json:"name"` - CreatedById *uint `json:"createdBy"` - Pagination *paginator.Pagination `json:"pagination"` + // Search filters + Name *string `query:"name"` + ClientType *string `query:"clientType" validate:"omitempty,oneof=parent_client sub_client standalone"` + + // Hierarchy filters + ParentClientId *uuid.UUID `query:"parentClientId"` // Get children of specific parent + IncludeSubClients *bool `query:"includeSubClients"` // Include all descendants + OnlyParentClients *bool `query:"onlyParentClients"` // Only clients with children + OnlyStandalone *bool `query:"onlyStandalone"` // Only standalone clients + + // Status filter + IsActive *bool `query:"isActive"` + + Pagination *paginator.Pagination } -type ClientsCreateRequest struct { - Name string `json:"name" validate:"required"` - CreatedById *uint `json:"createdById"` +// MoveClientRequest for moving client to different parent +type MoveClientRequest struct { + TargetParentId *uuid.UUID `json:"targetParentId"` // null = move to root (standalone) } -func (req ClientsCreateRequest) ToEntity() *entity.Clients { - return &entity.Clients{ - Name: req.Name, - CreatedById: req.CreatedById, - CreatedAt: time.Now(), - } +// BulkCreateSubClientsRequest for creating multiple sub-clients at once +type BulkCreateSubClientsRequest struct { + ParentClientId uuid.UUID `json:"parentClientId" validate:"required"` + SubClients []CreateSubClientDetail `json:"subClients" validate:"required,min=1,dive"` } -type ClientsUpdateRequest struct { - Name string `json:"name" validate:"required"` - CreatedById *uint `json:"createdById"` +type CreateSubClientDetail struct { + Name string `json:"name" validate:"required"` + Description *string `json:"description"` + MaxUsers *int `json:"maxUsers"` + MaxStorage *int64 `json:"maxStorage"` } -func (req ClientsUpdateRequest) ToEntity() *entity.Clients { - return &entity.Clients{ - Name: req.Name, - CreatedById: req.CreatedById, - UpdatedAt: time.Now(), - } +// ClientHierarchyRequest for getting client tree structure +type ClientHierarchyRequest struct { + ClientId uuid.UUID `json:"clientId" validate:"required"` + MaxDepth *int `json:"maxDepth"` // Limit recursion depth + IncludeInactive *bool `json:"includeInactive"` } +// ClientsQueryRequestContext for parsing query parameters from HTTP context type ClientsQueryRequestContext struct { - Name string `json:"name"` - CreatedById string `json:"createdById"` + Name string `query:"name"` + ClientType string `query:"clientType"` + ParentClientId string `query:"parentClientId"` + IncludeSubClients string `query:"includeSubClients"` + OnlyParentClients string `query:"onlyParentClients"` + OnlyStandalone string `query:"onlyStandalone"` + IsActive string `query:"isActive"` + CreatedById string `query:"createdById"` } -func (req ClientsQueryRequestContext) ToParamRequest() ClientsQueryRequest { - var request ClientsQueryRequest +// ToParamRequest converts context to ClientsQueryRequest +func (ctx *ClientsQueryRequestContext) ToParamRequest() ClientsQueryRequest { + req := ClientsQueryRequest{} - if name := req.Name; name != "" { - request.Name = &name + // Name filter + if ctx.Name != "" { + req.Name = &ctx.Name } - if createdByStr := req.CreatedById; createdByStr != "" { - createdBy, err := strconv.Atoi(createdByStr) - if err == nil { - createdByIdUint := uint(createdBy) - request.CreatedById = &createdByIdUint + + // Client type filter + if ctx.ClientType != "" { + req.ClientType = &ctx.ClientType + } + + // Parent client ID filter + if ctx.ParentClientId != "" { + if parentId, err := uuid.Parse(ctx.ParentClientId); err == nil { + req.ParentClientId = &parentId } } - return request + // Boolean filters + if ctx.IncludeSubClients != "" { + includeSubClients := ctx.IncludeSubClients == "true" + req.IncludeSubClients = &includeSubClients + } + + if ctx.OnlyParentClients != "" { + onlyParentClients := ctx.OnlyParentClients == "true" + req.OnlyParentClients = &onlyParentClients + } + + if ctx.OnlyStandalone != "" { + onlyStandalone := ctx.OnlyStandalone == "true" + req.OnlyStandalone = &onlyStandalone + } + + if ctx.IsActive != "" { + isActive := ctx.IsActive == "true" + req.IsActive = &isActive + } + + return req } diff --git a/app/module/clients/response/clients.response.go b/app/module/clients/response/clients.response.go index e832b38..aa75262 100644 --- a/app/module/clients/response/clients.response.go +++ b/app/module/clients/response/clients.response.go @@ -1,15 +1,161 @@ package response import ( - "github.com/google/uuid" "time" + + "github.com/google/uuid" ) +// ======================================================================== +// RESPONSE STRUCTS - Updated for Multi-Client Hierarchy Support (camelCase) +// ======================================================================== + +// ClientResponse for single client with hierarchy info type ClientsResponse struct { - ClientID uuid.UUID `json:"clientId"` - Name string `json:"name"` - CreatedById uint `json:"createdById"` - IsActive bool `json:"isActive"` + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Description *string `json:"description"` + ClientType string `json:"clientType"` + ParentClientId *uuid.UUID `json:"parentClientId"` + + // Parent info (if sub_client) + ParentClient *ParentClientInfo `json:"parentClient,omitempty"` + + // Children info (if parent_client) + SubClients []SubClientInfo `json:"subClients,omitempty"` + SubClientCount int `json:"subClientCount"` + + // Resource limits & usage + MaxUsers *int `json:"maxUsers"` + MaxStorage *int64 `json:"maxStorage"` + CurrentUsers int `json:"currentUsers"` // Count of active users + CurrentStorage *int64 `json:"currentStorage"` // Current storage usage (if tracked) + + // Settings + Settings *string `json:"settings"` + + // Metadata + CreatedById *uint `json:"createdById"` + CreatedBy *UserInfo `json:"createdBy,omitempty"` + IsActive *bool `json:"isActive"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } + +// ParentClientInfo minimal parent info +type ParentClientInfo struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + ClientType string `json:"clientType"` +} + +// SubClientInfo minimal child info +type SubClientInfo struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + ClientType string `json:"clientType"` + CurrentUsers int `json:"currentUsers"` + IsActive *bool `json:"isActive"` +} + +// UserInfo minimal user info +type UserInfo struct { + ID uint `json:"id"` + Username string `json:"username"` + Fullname string `json:"fullname"` +} + +// ClientHierarchyResponse full tree structure +type ClientHierarchyResponse struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Description *string `json:"description"` + ClientType string `json:"clientType"` + Level int `json:"level"` // Depth in tree (0 = root) + Path []string `json:"path"` // Breadcrumb path + ParentClientId *uuid.UUID `json:"parentClientId"` + SubClients []ClientHierarchyResponse `json:"subClients,omitempty"` + CurrentUsers int `json:"currentUsers"` + IsActive *bool `json:"isActive"` +} + +// ClientStatsResponse statistics for a client +type ClientStatsResponse struct { + ClientId uuid.UUID `json:"clientId"` + ClientName string `json:"clientName"` + + // User stats + TotalUsers int `json:"totalUsers"` + ActiveUsers int `json:"activeUsers"` + InactiveUsers int `json:"inactiveUsers"` + + // Content stats + TotalArticles int `json:"totalArticles"` + PublishedArticles int `json:"publishedArticles"` + DraftArticles int `json:"draftArticles"` + + // Storage stats + StorageUsed *int64 `json:"storageUsed"` + StorageLimit *int64 `json:"storageLimit"` + StoragePercent *float64 `json:"storagePercent"` + + // Hierarchy stats + IsParent bool `json:"isParent"` + SubClientCount int `json:"subClientCount"` + TotalDescendants int `json:"totalDescendants"` // All nested sub-clients +} + +// ClientListResponse for list endpoint +type ClientListResponse struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + ClientType string `json:"clientType"` + ParentClientId *uuid.UUID `json:"parentClientId"` + ParentName *string `json:"parentName,omitempty"` + SubClientCount int `json:"subClientCount"` + CurrentUsers int `json:"currentUsers"` + IsActive *bool `json:"isActive"` + CreatedAt time.Time `json:"createdAt"` +} + +// ClientAccessResponse for user's accessible clients +type ClientAccessResponse struct { + // User info + UserId uint `json:"userId"` + Username string `json:"username"` + + // Access summary + IsSuperAdmin bool `json:"isSuperAdmin"` + PrimaryClientId *uuid.UUID `json:"primaryClientId"` + TotalAccessible int `json:"totalAccessibleClients"` + + // Accessible clients + Clients []AccessibleClientInfo `json:"clients"` +} + +type AccessibleClientInfo struct { + ClientId uuid.UUID `json:"clientId"` + ClientName string `json:"clientName"` + ClientType string `json:"clientType"` + AccessType string `json:"accessType"` // read, write, admin, owner + CanManage bool `json:"canManage"` + CanDelegate bool `json:"canDelegate"` + IncludeSubClients bool `json:"includeSubClients"` + IsPrimaryClient bool `json:"isPrimaryClient"` +} + +// BulkOperationResponse for bulk operations +type BulkOperationResponse struct { + TotalRequested int `json:"totalRequested"` + Successful int `json:"successful"` + Failed int `json:"failed"` + Results []BulkOperationResult `json:"results"` +} + +type BulkOperationResult struct { + Index int `json:"index"` + ClientId *uuid.UUID `json:"clientId,omitempty"` + Name string `json:"name"` + Success bool `json:"success"` + Error *string `json:"error,omitempty"` +} \ No newline at end of file diff --git a/app/module/clients/service/clients.service.go b/app/module/clients/service/clients.service.go index 8304840..f27ce89 100644 --- a/app/module/clients/service/clients.service.go +++ b/app/module/clients/service/clients.service.go @@ -1,17 +1,19 @@ 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" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/clients/mapper" - "web-medols-be/app/module/clients/repository" - "web-medols-be/app/module/clients/request" - "web-medols-be/app/module/clients/response" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" + utilSvc "netidhub-saas-be/utils/service" ) // ClientsService @@ -23,11 +25,18 @@ type clientsService struct { // ClientsService define interface of IClientsService type ClientsService interface { - All(req request.ClientsQueryRequest) (clients []*response.ClientsResponse, paging paginator.Pagination, err error) + All(clientId *uuid.UUID, 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) + Save(req request.CreateClientRequest, authToken string) (clients *entity.Clients, err error) + Update(id uuid.UUID, req request.UpdateClientRequest) (err error) Delete(id uuid.UUID) error + + // New hierarchy methods + CreateSubClient(parentId uuid.UUID, req request.CreateClientRequest) (*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 @@ -41,7 +50,7 @@ func NewClientsService(repo repository.ClientsRepository, log zerolog.Logger, us } // All implement interface of ClientsService -func (_i *clientsService) All(req request.ClientsQueryRequest) (clientss []*response.ClientsResponse, paging paginator.Pagination, err error) { +func (_i *clientsService) All(clientId *uuid.UUID, req request.ClientsQueryRequest) (clientss []*response.ClientsResponse, paging paginator.Pagination, err error) { results, paging, err := _i.Repo.GetAll(req) if err != nil { return @@ -63,9 +72,20 @@ func (_i *clientsService) Show(id uuid.UUID) (clients *response.ClientsResponse, return mapper.ClientsResponseMapper(result), nil } -func (_i *clientsService) Save(req request.ClientsCreateRequest, authToken string) (clients *entity.Clients, err error) { +func (_i *clientsService) Save(req request.CreateClientRequest, authToken string) (clients *entity.Clients, err error) { _i.Log.Info().Interface("data", req).Msg("") - newReq := req.ToEntity() + + // 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("") @@ -78,9 +98,22 @@ func (_i *clientsService) Save(req request.ClientsCreateRequest, authToken strin return _i.Repo.Create(newReq) } -func (_i *clientsService) Update(id uuid.UUID, req request.ClientsUpdateRequest) (err error) { +func (_i *clientsService) Update(id uuid.UUID, req request.UpdateClientRequest) (err error) { _i.Log.Info().Interface("data", req).Msg("") - return _i.Repo.Update(id, req.ToEntity()) + + // 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 { @@ -93,3 +126,167 @@ func (_i *clientsService) Delete(id uuid.UUID) error { 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.CreateClientRequest) (*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.CreateClientRequest{ + 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 +} diff --git a/app/module/custom_static_pages/controller/controller.go b/app/module/custom_static_pages/controller/controller.go index 549337d..597f2fe 100644 --- a/app/module/custom_static_pages/controller/controller.go +++ b/app/module/custom_static_pages/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/custom_static_pages/service" + "netidhub-saas-be/app/module/custom_static_pages/service" ) type Controller struct { diff --git a/app/module/custom_static_pages/controller/custom_static_pages.controller.go b/app/module/custom_static_pages/controller/custom_static_pages.controller.go index 760e2db..bd5824d 100644 --- a/app/module/custom_static_pages/controller/custom_static_pages.controller.go +++ b/app/module/custom_static_pages/controller/custom_static_pages.controller.go @@ -1,17 +1,17 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/custom_static_pages/request" + "netidhub-saas-be/app/module/custom_static_pages/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/custom_static_pages/request" - "web-medols-be/app/module/custom_static_pages/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type customStaticPagesController struct { diff --git a/app/module/custom_static_pages/custom_static_pages.module.go b/app/module/custom_static_pages/custom_static_pages.module.go index f08e351..c22ab9d 100644 --- a/app/module/custom_static_pages/custom_static_pages.module.go +++ b/app/module/custom_static_pages/custom_static_pages.module.go @@ -3,9 +3,9 @@ package custom_static_pages import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/custom_static_pages/controller" - "web-medols-be/app/module/custom_static_pages/repository" - "web-medols-be/app/module/custom_static_pages/service" + "netidhub-saas-be/app/module/custom_static_pages/controller" + "netidhub-saas-be/app/module/custom_static_pages/repository" + "netidhub-saas-be/app/module/custom_static_pages/service" ) // struct of CustomStaticPagesRouter diff --git a/app/module/custom_static_pages/mapper/custom_static_pages.mapper.go b/app/module/custom_static_pages/mapper/custom_static_pages.mapper.go index 609d255..ac10a83 100644 --- a/app/module/custom_static_pages/mapper/custom_static_pages.mapper.go +++ b/app/module/custom_static_pages/mapper/custom_static_pages.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/custom_static_pages/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/custom_static_pages/response" ) func CustomStaticPagesResponseMapper(customStaticPagesReq *entity.CustomStaticPages) (customStaticPagesRes *res.CustomStaticPagesResponse) { diff --git a/app/module/custom_static_pages/repository/custom_static_pages.repository.go b/app/module/custom_static_pages/repository/custom_static_pages.repository.go index b187cae..8593078 100644 --- a/app/module/custom_static_pages/repository/custom_static_pages.repository.go +++ b/app/module/custom_static_pages/repository/custom_static_pages.repository.go @@ -4,12 +4,12 @@ import ( "fmt" "github.com/google/uuid" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/custom_static_pages/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/custom_static_pages/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type customStaticPagesRepository struct { diff --git a/app/module/custom_static_pages/request/custom_static_pages.request.go b/app/module/custom_static_pages/request/custom_static_pages.request.go index 600768d..651ed99 100644 --- a/app/module/custom_static_pages/request/custom_static_pages.request.go +++ b/app/module/custom_static_pages/request/custom_static_pages.request.go @@ -1,9 +1,9 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type CustomStaticPagesGeneric interface { diff --git a/app/module/custom_static_pages/service/custom_static_pages.service.go b/app/module/custom_static_pages/service/custom_static_pages.service.go index 794c93b..19e3abe 100644 --- a/app/module/custom_static_pages/service/custom_static_pages.service.go +++ b/app/module/custom_static_pages/service/custom_static_pages.service.go @@ -3,13 +3,13 @@ package service import ( "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/custom_static_pages/mapper" - "web-medols-be/app/module/custom_static_pages/repository" - "web-medols-be/app/module/custom_static_pages/request" - "web-medols-be/app/module/custom_static_pages/response" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/custom_static_pages/mapper" + "netidhub-saas-be/app/module/custom_static_pages/repository" + "netidhub-saas-be/app/module/custom_static_pages/request" + "netidhub-saas-be/app/module/custom_static_pages/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" ) // CustomStaticPagesService diff --git a/app/module/districts/controller/controller.go b/app/module/districts/controller/controller.go index 7544c1e..dcd4d89 100644 --- a/app/module/districts/controller/controller.go +++ b/app/module/districts/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/districts/service" +import "netidhub-saas-be/app/module/districts/service" type Controller struct { Districts DistrictsController diff --git a/app/module/districts/controller/districts.controller.go b/app/module/districts/controller/districts.controller.go index ff6d84b..81e494d 100644 --- a/app/module/districts/controller/districts.controller.go +++ b/app/module/districts/controller/districts.controller.go @@ -2,13 +2,13 @@ package controller import ( "github.com/gofiber/fiber/v2" + "netidhub-saas-be/app/module/districts/request" + "netidhub-saas-be/app/module/districts/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/districts/request" - "web-medols-be/app/module/districts/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type districtsController struct { diff --git a/app/module/districts/districts.module.go b/app/module/districts/districts.module.go index 2b50122..16a899d 100644 --- a/app/module/districts/districts.module.go +++ b/app/module/districts/districts.module.go @@ -3,9 +3,9 @@ package districts import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/districts/controller" - "web-medols-be/app/module/districts/repository" - "web-medols-be/app/module/districts/service" + "netidhub-saas-be/app/module/districts/controller" + "netidhub-saas-be/app/module/districts/repository" + "netidhub-saas-be/app/module/districts/service" ) // DistrictsRouter struct of DistrictsRouter diff --git a/app/module/districts/mapper/districts.mapper.go b/app/module/districts/mapper/districts.mapper.go index 5e45c29..b1505d5 100644 --- a/app/module/districts/mapper/districts.mapper.go +++ b/app/module/districts/mapper/districts.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/districts/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/districts/response" ) func DistrictsResponseMapper(districtsReq *entity.Districts) (districtsRes *res.DistrictsResponse) { diff --git a/app/module/districts/repository/districts.repository.go b/app/module/districts/repository/districts.repository.go index 50a566f..44e1117 100644 --- a/app/module/districts/repository/districts.repository.go +++ b/app/module/districts/repository/districts.repository.go @@ -1,10 +1,10 @@ package repository import ( - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/districts/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/districts/request" + "netidhub-saas-be/utils/paginator" ) type districtsRepository struct { diff --git a/app/module/districts/request/districts.request.go b/app/module/districts/request/districts.request.go index 5ee79fe..d2aece6 100644 --- a/app/module/districts/request/districts.request.go +++ b/app/module/districts/request/districts.request.go @@ -1,8 +1,8 @@ package request import ( - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" ) type DistrictsGeneric interface { diff --git a/app/module/districts/service/districts.service.go b/app/module/districts/service/districts.service.go index 0963d08..7699a89 100644 --- a/app/module/districts/service/districts.service.go +++ b/app/module/districts/service/districts.service.go @@ -2,11 +2,11 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/module/districts/mapper" - "web-medols-be/app/module/districts/repository" - "web-medols-be/app/module/districts/request" - "web-medols-be/app/module/districts/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/districts/mapper" + "netidhub-saas-be/app/module/districts/repository" + "netidhub-saas-be/app/module/districts/request" + "netidhub-saas-be/app/module/districts/response" + "netidhub-saas-be/utils/paginator" ) // DistrictsService diff --git a/app/module/feedbacks/controller/controller.go b/app/module/feedbacks/controller/controller.go index ddead37..7cfc724 100644 --- a/app/module/feedbacks/controller/controller.go +++ b/app/module/feedbacks/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/feedbacks/service" + "netidhub-saas-be/app/module/feedbacks/service" ) type Controller struct { diff --git a/app/module/feedbacks/controller/feedbacks.controller.go b/app/module/feedbacks/controller/feedbacks.controller.go index 0b7681e..d771c61 100644 --- a/app/module/feedbacks/controller/feedbacks.controller.go +++ b/app/module/feedbacks/controller/feedbacks.controller.go @@ -1,13 +1,13 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/feedbacks/request" + "netidhub-saas-be/app/module/feedbacks/service" + "netidhub-saas-be/utils/paginator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/feedbacks/request" - "web-medols-be/app/module/feedbacks/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/feedbacks/feedbacks.module.go b/app/module/feedbacks/feedbacks.module.go index d33ac91..e8731e0 100644 --- a/app/module/feedbacks/feedbacks.module.go +++ b/app/module/feedbacks/feedbacks.module.go @@ -3,9 +3,9 @@ package feedbacks import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/feedbacks/controller" - "web-medols-be/app/module/feedbacks/repository" - "web-medols-be/app/module/feedbacks/service" + "netidhub-saas-be/app/module/feedbacks/controller" + "netidhub-saas-be/app/module/feedbacks/repository" + "netidhub-saas-be/app/module/feedbacks/service" ) // struct of FeedbacksRouter diff --git a/app/module/feedbacks/mapper/feedbacks.mapper.go b/app/module/feedbacks/mapper/feedbacks.mapper.go index 9895057..f813435 100644 --- a/app/module/feedbacks/mapper/feedbacks.mapper.go +++ b/app/module/feedbacks/mapper/feedbacks.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/feedbacks/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/feedbacks/response" ) func FeedbacksResponseMapper(feedbacksReq *entity.Feedbacks) (feedbacksRes *res.FeedbacksResponse) { diff --git a/app/module/feedbacks/repository/feedbacks.repository.go b/app/module/feedbacks/repository/feedbacks.repository.go index a505f79..5cec065 100644 --- a/app/module/feedbacks/repository/feedbacks.repository.go +++ b/app/module/feedbacks/repository/feedbacks.repository.go @@ -4,14 +4,14 @@ import ( "fmt" "github.com/google/uuid" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/feedbacks/request" + "netidhub-saas-be/app/module/feedbacks/response" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" "time" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/feedbacks/request" - "web-medols-be/app/module/feedbacks/response" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type feedbacksRepository struct { diff --git a/app/module/feedbacks/request/feedbacks.request.go b/app/module/feedbacks/request/feedbacks.request.go index 31e03ad..8ff153e 100644 --- a/app/module/feedbacks/request/feedbacks.request.go +++ b/app/module/feedbacks/request/feedbacks.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type FeedbacksGeneric interface { diff --git a/app/module/feedbacks/service/feedbacks.service.go b/app/module/feedbacks/service/feedbacks.service.go index 33f26b8..c7e4fc0 100644 --- a/app/module/feedbacks/service/feedbacks.service.go +++ b/app/module/feedbacks/service/feedbacks.service.go @@ -3,13 +3,13 @@ package service import ( "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/feedbacks/mapper" - "web-medols-be/app/module/feedbacks/repository" - "web-medols-be/app/module/feedbacks/request" - "web-medols-be/app/module/feedbacks/response" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/feedbacks/mapper" + "netidhub-saas-be/app/module/feedbacks/repository" + "netidhub-saas-be/app/module/feedbacks/request" + "netidhub-saas-be/app/module/feedbacks/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" ) // FeedbacksService diff --git a/app/module/magazine_files/controller/controller.go b/app/module/magazine_files/controller/controller.go index ab456ea..0d06d0c 100644 --- a/app/module/magazine_files/controller/controller.go +++ b/app/module/magazine_files/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/magazine_files/service" +import "netidhub-saas-be/app/module/magazine_files/service" type Controller struct { MagazineFiles MagazineFilesController diff --git a/app/module/magazine_files/controller/magazine_files.controller.go b/app/module/magazine_files/controller/magazine_files.controller.go index 26e3d18..1aea8dd 100644 --- a/app/module/magazine_files/controller/magazine_files.controller.go +++ b/app/module/magazine_files/controller/magazine_files.controller.go @@ -1,15 +1,15 @@ package controller import ( + "netidhub-saas-be/app/module/magazine_files/request" + "netidhub-saas-be/app/module/magazine_files/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/magazine_files/request" - "web-medols-be/app/module/magazine_files/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type magazineFilesController struct { diff --git a/app/module/magazine_files/magazine_files.module.go b/app/module/magazine_files/magazine_files.module.go index 4196044..85ca8bd 100644 --- a/app/module/magazine_files/magazine_files.module.go +++ b/app/module/magazine_files/magazine_files.module.go @@ -3,9 +3,9 @@ package magazine_files import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/magazine_files/controller" - "web-medols-be/app/module/magazine_files/repository" - "web-medols-be/app/module/magazine_files/service" + "netidhub-saas-be/app/module/magazine_files/controller" + "netidhub-saas-be/app/module/magazine_files/repository" + "netidhub-saas-be/app/module/magazine_files/service" ) // struct of MagazineFilesRouter diff --git a/app/module/magazine_files/mapper/magazine_files.mapper.go b/app/module/magazine_files/mapper/magazine_files.mapper.go index 4acdc14..071e94b 100644 --- a/app/module/magazine_files/mapper/magazine_files.mapper.go +++ b/app/module/magazine_files/mapper/magazine_files.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/magazine_files/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/magazine_files/response" ) func MagazineFilesResponseMapper(magazineFilesReq *entity.MagazineFiles, host string) (magazineFilesRes *res.MagazineFilesResponse) { diff --git a/app/module/magazine_files/repository/magazine_files.repository.go b/app/module/magazine_files/repository/magazine_files.repository.go index afdb397..27e203b 100644 --- a/app/module/magazine_files/repository/magazine_files.repository.go +++ b/app/module/magazine_files/repository/magazine_files.repository.go @@ -2,12 +2,12 @@ package repository import ( "fmt" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/magazine_files/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/magazine_files/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type magazineFilesRepository struct { diff --git a/app/module/magazine_files/request/magazine_files.request.go b/app/module/magazine_files/request/magazine_files.request.go index d6f9e80..59bc34c 100644 --- a/app/module/magazine_files/request/magazine_files.request.go +++ b/app/module/magazine_files/request/magazine_files.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type MagazineFilesGeneric interface { diff --git a/app/module/magazine_files/service/magazine_files.service.go b/app/module/magazine_files/service/magazine_files.service.go index 0d5bff8..c4f4272 100644 --- a/app/module/magazine_files/service/magazine_files.service.go +++ b/app/module/magazine_files/service/magazine_files.service.go @@ -10,17 +10,17 @@ import ( "log" "math/rand" "mime" + "netidhub-saas-be/app/module/magazine_files/mapper" + "netidhub-saas-be/app/module/magazine_files/repository" + "netidhub-saas-be/app/module/magazine_files/request" + "netidhub-saas-be/app/module/magazine_files/response" + config "netidhub-saas-be/config/config" + minioStorage "netidhub-saas-be/config/config" + "netidhub-saas-be/utils/paginator" "path/filepath" "strconv" "strings" "time" - "web-medols-be/app/module/magazine_files/mapper" - "web-medols-be/app/module/magazine_files/repository" - "web-medols-be/app/module/magazine_files/request" - "web-medols-be/app/module/magazine_files/response" - config "web-medols-be/config/config" - minioStorage "web-medols-be/config/config" - "web-medols-be/utils/paginator" ) // MagazineFilesService diff --git a/app/module/magazines/controller/controller.go b/app/module/magazines/controller/controller.go index 4b0b03d..983cd7a 100644 --- a/app/module/magazines/controller/controller.go +++ b/app/module/magazines/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/magazines/service" +import "netidhub-saas-be/app/module/magazines/service" type Controller struct { Magazines MagazinesController diff --git a/app/module/magazines/controller/magazines.controller.go b/app/module/magazines/controller/magazines.controller.go index fa65c62..36a7860 100644 --- a/app/module/magazines/controller/magazines.controller.go +++ b/app/module/magazines/controller/magazines.controller.go @@ -1,16 +1,16 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/magazines/request" + "netidhub-saas-be/app/module/magazines/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/magazines/request" - "web-medols-be/app/module/magazines/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type magazinesController struct { diff --git a/app/module/magazines/magazines.module.go b/app/module/magazines/magazines.module.go index 16f0f8f..c011fdc 100644 --- a/app/module/magazines/magazines.module.go +++ b/app/module/magazines/magazines.module.go @@ -3,9 +3,9 @@ package magazines import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/magazines/controller" - "web-medols-be/app/module/magazines/repository" - "web-medols-be/app/module/magazines/service" + "netidhub-saas-be/app/module/magazines/controller" + "netidhub-saas-be/app/module/magazines/repository" + "netidhub-saas-be/app/module/magazines/service" ) // struct of MagazinesRouter diff --git a/app/module/magazines/mapper/magazines.mapper.go b/app/module/magazines/mapper/magazines.mapper.go index 4c68619..2233347 100644 --- a/app/module/magazines/mapper/magazines.mapper.go +++ b/app/module/magazines/mapper/magazines.mapper.go @@ -1,11 +1,11 @@ package mapper import ( - "web-medols-be/app/database/entity" - magazineFilesMapper "web-medols-be/app/module/magazine_files/mapper" - magazineFilesRepository "web-medols-be/app/module/magazine_files/repository" - magazineFilesResponse "web-medols-be/app/module/magazine_files/response" - res "web-medols-be/app/module/magazines/response" + "netidhub-saas-be/app/database/entity" + magazineFilesMapper "netidhub-saas-be/app/module/magazine_files/mapper" + magazineFilesRepository "netidhub-saas-be/app/module/magazine_files/repository" + magazineFilesResponse "netidhub-saas-be/app/module/magazine_files/response" + res "netidhub-saas-be/app/module/magazines/response" ) func MagazinesResponseMapper(magazinesReq *entity.Magazines, magazineFilesRepo magazineFilesRepository.MagazineFilesRepository, host string) (magazinesRes *res.MagazinesResponse) { diff --git a/app/module/magazines/repository/magazines.repository.go b/app/module/magazines/repository/magazines.repository.go index 43a3b28..f1912c3 100644 --- a/app/module/magazines/repository/magazines.repository.go +++ b/app/module/magazines/repository/magazines.repository.go @@ -3,12 +3,12 @@ package repository import ( "fmt" "github.com/google/uuid" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/magazines/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/magazines/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type magazinesRepository struct { diff --git a/app/module/magazines/request/magazines.request.go b/app/module/magazines/request/magazines.request.go index 87870b4..2b01cdb 100644 --- a/app/module/magazines/request/magazines.request.go +++ b/app/module/magazines/request/magazines.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type MagazinesGeneric interface { diff --git a/app/module/magazines/response/magazines.response.go b/app/module/magazines/response/magazines.response.go index 937491f..d581244 100644 --- a/app/module/magazines/response/magazines.response.go +++ b/app/module/magazines/response/magazines.response.go @@ -1,8 +1,8 @@ package response import ( + magazineFilesResponse "netidhub-saas-be/app/module/magazine_files/response" "time" - magazineFilesResponse "web-medols-be/app/module/magazine_files/response" ) type MagazinesResponse struct { diff --git a/app/module/magazines/service/magazines.service.go b/app/module/magazines/service/magazines.service.go index 0fbc668..61a0f7d 100644 --- a/app/module/magazines/service/magazines.service.go +++ b/app/module/magazines/service/magazines.service.go @@ -11,21 +11,21 @@ import ( "log" "math/rand" "mime" + "netidhub-saas-be/app/database/entity" + magazineFilesRepository "netidhub-saas-be/app/module/magazine_files/repository" + "netidhub-saas-be/app/module/magazines/mapper" + "netidhub-saas-be/app/module/magazines/repository" + "netidhub-saas-be/app/module/magazines/request" + "netidhub-saas-be/app/module/magazines/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + config "netidhub-saas-be/config/config" + minioStorage "netidhub-saas-be/config/config" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "path/filepath" "strconv" "strings" "time" - "web-medols-be/app/database/entity" - magazineFilesRepository "web-medols-be/app/module/magazine_files/repository" - "web-medols-be/app/module/magazines/mapper" - "web-medols-be/app/module/magazines/repository" - "web-medols-be/app/module/magazines/request" - "web-medols-be/app/module/magazines/response" - usersRepository "web-medols-be/app/module/users/repository" - config "web-medols-be/config/config" - minioStorage "web-medols-be/config/config" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) // MagazinesService diff --git a/app/module/master_menus/controller/controller.go b/app/module/master_menus/controller/controller.go index ccf95e2..1f1e253 100644 --- a/app/module/master_menus/controller/controller.go +++ b/app/module/master_menus/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/master_menus/service" +import "netidhub-saas-be/app/module/master_menus/service" type Controller struct { MasterMenus MasterMenusController diff --git a/app/module/master_menus/controller/master_menus.controller.go b/app/module/master_menus/controller/master_menus.controller.go index a5d2b8f..cc32653 100644 --- a/app/module/master_menus/controller/master_menus.controller.go +++ b/app/module/master_menus/controller/master_menus.controller.go @@ -1,15 +1,15 @@ package controller import ( + "netidhub-saas-be/app/module/master_menus/request" + "netidhub-saas-be/app/module/master_menus/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/master_menus/request" - "web-medols-be/app/module/master_menus/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type masterMenusController struct { diff --git a/app/module/master_menus/mapper/master_menus.mapper.go b/app/module/master_menus/mapper/master_menus.mapper.go index a890f31..ad34d80 100644 --- a/app/module/master_menus/mapper/master_menus.mapper.go +++ b/app/module/master_menus/mapper/master_menus.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/master_menus/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/master_menus/response" ) func MasterMenusResponseMapper(masterMenusReq *entity.MasterMenus) (masterMenusRes *res.MasterMenusResponse) { diff --git a/app/module/master_menus/master_menus.module.go b/app/module/master_menus/master_menus.module.go index 11a5e77..ffd5c5f 100644 --- a/app/module/master_menus/master_menus.module.go +++ b/app/module/master_menus/master_menus.module.go @@ -3,9 +3,9 @@ package master_menus import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/master_menus/controller" - "web-medols-be/app/module/master_menus/repository" - "web-medols-be/app/module/master_menus/service" + "netidhub-saas-be/app/module/master_menus/controller" + "netidhub-saas-be/app/module/master_menus/repository" + "netidhub-saas-be/app/module/master_menus/service" ) // struct of MasterMenusRouter diff --git a/app/module/master_menus/repository/master_menus.repository.go b/app/module/master_menus/repository/master_menus.repository.go index f0bb90f..97002a4 100644 --- a/app/module/master_menus/repository/master_menus.repository.go +++ b/app/module/master_menus/repository/master_menus.repository.go @@ -2,11 +2,11 @@ package repository import ( "fmt" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/master_menus/request" + "netidhub-saas-be/utils/paginator" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/master_menus/request" - "web-medols-be/utils/paginator" ) type masterMenusRepository struct { diff --git a/app/module/master_menus/request/master_menus.request.go b/app/module/master_menus/request/master_menus.request.go index e0ba9cc..a50338f 100644 --- a/app/module/master_menus/request/master_menus.request.go +++ b/app/module/master_menus/request/master_menus.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type MasterMenusGeneric interface { diff --git a/app/module/master_menus/service/master_menus.service.go b/app/module/master_menus/service/master_menus.service.go index 58db25c..3542447 100644 --- a/app/module/master_menus/service/master_menus.service.go +++ b/app/module/master_menus/service/master_menus.service.go @@ -2,11 +2,11 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/module/master_menus/mapper" - "web-medols-be/app/module/master_menus/repository" - "web-medols-be/app/module/master_menus/request" - "web-medols-be/app/module/master_menus/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/master_menus/mapper" + "netidhub-saas-be/app/module/master_menus/repository" + "netidhub-saas-be/app/module/master_menus/request" + "netidhub-saas-be/app/module/master_menus/response" + "netidhub-saas-be/utils/paginator" ) // MasterMenusService diff --git a/app/module/master_modules/controller/controller.go b/app/module/master_modules/controller/controller.go index 88b91d6..a7bb2f6 100644 --- a/app/module/master_modules/controller/controller.go +++ b/app/module/master_modules/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/master_modules/service" +import "netidhub-saas-be/app/module/master_modules/service" type Controller struct { MasterModules MasterModulesController diff --git a/app/module/master_modules/controller/master_modules.controller.go b/app/module/master_modules/controller/master_modules.controller.go index d6240b5..cd25a8c 100644 --- a/app/module/master_modules/controller/master_modules.controller.go +++ b/app/module/master_modules/controller/master_modules.controller.go @@ -1,15 +1,15 @@ package controller import ( + "netidhub-saas-be/app/module/master_modules/request" + "netidhub-saas-be/app/module/master_modules/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/master_modules/request" - "web-medols-be/app/module/master_modules/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type masterModulesController struct { diff --git a/app/module/master_modules/mapper/master_modules.mapper.go b/app/module/master_modules/mapper/master_modules.mapper.go index c51cf91..f316bce 100644 --- a/app/module/master_modules/mapper/master_modules.mapper.go +++ b/app/module/master_modules/mapper/master_modules.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/master_modules/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/master_modules/response" ) func MasterModulesResponseMapper(masterModulesReq *entity.MasterModules) (masterModulesRes *res.MasterModulesResponse) { diff --git a/app/module/master_modules/master_modules.module.go b/app/module/master_modules/master_modules.module.go index 55497f2..6e312d3 100644 --- a/app/module/master_modules/master_modules.module.go +++ b/app/module/master_modules/master_modules.module.go @@ -3,9 +3,9 @@ package master_modules import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/master_modules/controller" - "web-medols-be/app/module/master_modules/repository" - "web-medols-be/app/module/master_modules/service" + "netidhub-saas-be/app/module/master_modules/controller" + "netidhub-saas-be/app/module/master_modules/repository" + "netidhub-saas-be/app/module/master_modules/service" ) // struct of MasterModulesRouter diff --git a/app/module/master_modules/repository/master_modules.repository.go b/app/module/master_modules/repository/master_modules.repository.go index e27e776..d1723a7 100644 --- a/app/module/master_modules/repository/master_modules.repository.go +++ b/app/module/master_modules/repository/master_modules.repository.go @@ -2,11 +2,11 @@ package repository import ( "fmt" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/master_modules/request" + "netidhub-saas-be/utils/paginator" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/master_modules/request" - "web-medols-be/utils/paginator" ) type masterModulesRepository struct { diff --git a/app/module/master_modules/request/master_modules.request.go b/app/module/master_modules/request/master_modules.request.go index a667e86..d774c5a 100644 --- a/app/module/master_modules/request/master_modules.request.go +++ b/app/module/master_modules/request/master_modules.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type MasterModulesGeneric interface { diff --git a/app/module/master_modules/service/master_modules.service.go b/app/module/master_modules/service/master_modules.service.go index 9b995e5..0fed6c6 100644 --- a/app/module/master_modules/service/master_modules.service.go +++ b/app/module/master_modules/service/master_modules.service.go @@ -2,11 +2,11 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/module/master_modules/mapper" - "web-medols-be/app/module/master_modules/repository" - "web-medols-be/app/module/master_modules/request" - "web-medols-be/app/module/master_modules/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/master_modules/mapper" + "netidhub-saas-be/app/module/master_modules/repository" + "netidhub-saas-be/app/module/master_modules/request" + "netidhub-saas-be/app/module/master_modules/response" + "netidhub-saas-be/utils/paginator" ) // MasterModulesService diff --git a/app/module/master_statuses/controller/controller.go b/app/module/master_statuses/controller/controller.go index d77d741..82fab99 100644 --- a/app/module/master_statuses/controller/controller.go +++ b/app/module/master_statuses/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/master_statuses/service" +import "netidhub-saas-be/app/module/master_statuses/service" type Controller struct { MasterStatuses MasterStatusesController diff --git a/app/module/master_statuses/controller/master_statuses.controller.go b/app/module/master_statuses/controller/master_statuses.controller.go index 04c54ab..db0722f 100644 --- a/app/module/master_statuses/controller/master_statuses.controller.go +++ b/app/module/master_statuses/controller/master_statuses.controller.go @@ -2,13 +2,13 @@ package controller import ( "github.com/gofiber/fiber/v2" + "netidhub-saas-be/app/module/master_statuses/request" + "netidhub-saas-be/app/module/master_statuses/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/master_statuses/request" - "web-medols-be/app/module/master_statuses/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type masterStatusesController struct { diff --git a/app/module/master_statuses/mapper/master_statuses.mapper.go b/app/module/master_statuses/mapper/master_statuses.mapper.go index da03264..03d75f7 100644 --- a/app/module/master_statuses/mapper/master_statuses.mapper.go +++ b/app/module/master_statuses/mapper/master_statuses.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/master_statuses/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/master_statuses/response" ) func MasterStatusesResponseMapper(masterStatusesReq *entity.MasterStatuses) (masterStatusesRes *res.MasterStatusesResponse) { diff --git a/app/module/master_statuses/master_statuses.module.go b/app/module/master_statuses/master_statuses.module.go index 17707ba..f87c686 100644 --- a/app/module/master_statuses/master_statuses.module.go +++ b/app/module/master_statuses/master_statuses.module.go @@ -3,9 +3,9 @@ package master_statuses import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/master_statuses/controller" - "web-medols-be/app/module/master_statuses/repository" - "web-medols-be/app/module/master_statuses/service" + "netidhub-saas-be/app/module/master_statuses/controller" + "netidhub-saas-be/app/module/master_statuses/repository" + "netidhub-saas-be/app/module/master_statuses/service" ) // struct of MasterStatusesRouter diff --git a/app/module/master_statuses/repository/master_statuses.repository.go b/app/module/master_statuses/repository/master_statuses.repository.go index f836c3d..dec8073 100644 --- a/app/module/master_statuses/repository/master_statuses.repository.go +++ b/app/module/master_statuses/repository/master_statuses.repository.go @@ -1,10 +1,10 @@ package repository import ( - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/master_statuses/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/master_statuses/request" + "netidhub-saas-be/utils/paginator" ) type masterStatusesRepository struct { diff --git a/app/module/master_statuses/request/master_statuses.request.go b/app/module/master_statuses/request/master_statuses.request.go index 80ba3bb..46bfd15 100644 --- a/app/module/master_statuses/request/master_statuses.request.go +++ b/app/module/master_statuses/request/master_statuses.request.go @@ -1,8 +1,8 @@ package request import ( - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" ) type MasterStatusesGeneric interface { diff --git a/app/module/master_statuses/service/master_statuses.service.go b/app/module/master_statuses/service/master_statuses.service.go index b54108d..043a652 100644 --- a/app/module/master_statuses/service/master_statuses.service.go +++ b/app/module/master_statuses/service/master_statuses.service.go @@ -2,11 +2,11 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/module/master_statuses/mapper" - "web-medols-be/app/module/master_statuses/repository" - "web-medols-be/app/module/master_statuses/request" - "web-medols-be/app/module/master_statuses/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/master_statuses/mapper" + "netidhub-saas-be/app/module/master_statuses/repository" + "netidhub-saas-be/app/module/master_statuses/request" + "netidhub-saas-be/app/module/master_statuses/response" + "netidhub-saas-be/utils/paginator" ) // MasterStatusesService diff --git a/app/module/provinces/controller/controller.go b/app/module/provinces/controller/controller.go index 67342d2..bd6ac34 100644 --- a/app/module/provinces/controller/controller.go +++ b/app/module/provinces/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/provinces/service" +import "netidhub-saas-be/app/module/provinces/service" type Controller struct { Provinces ProvincesController diff --git a/app/module/provinces/controller/provinces.controller.go b/app/module/provinces/controller/provinces.controller.go index c0cf771..5522077 100644 --- a/app/module/provinces/controller/provinces.controller.go +++ b/app/module/provinces/controller/provinces.controller.go @@ -2,13 +2,13 @@ package controller import ( "github.com/gofiber/fiber/v2" + "netidhub-saas-be/app/module/provinces/request" + "netidhub-saas-be/app/module/provinces/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/provinces/request" - "web-medols-be/app/module/provinces/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type provincesController struct { diff --git a/app/module/provinces/mapper/provinces.mapper.go b/app/module/provinces/mapper/provinces.mapper.go index 1a5d51e..143e56f 100644 --- a/app/module/provinces/mapper/provinces.mapper.go +++ b/app/module/provinces/mapper/provinces.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/provinces/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/provinces/response" ) func ProvincesResponseMapper(provincesReq *entity.Provinces) (provincesRes *res.ProvincesResponse) { diff --git a/app/module/provinces/provinces.module.go b/app/module/provinces/provinces.module.go index 3f1fa40..d8446a8 100644 --- a/app/module/provinces/provinces.module.go +++ b/app/module/provinces/provinces.module.go @@ -3,9 +3,9 @@ package provinces import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/provinces/controller" - "web-medols-be/app/module/provinces/repository" - "web-medols-be/app/module/provinces/service" + "netidhub-saas-be/app/module/provinces/controller" + "netidhub-saas-be/app/module/provinces/repository" + "netidhub-saas-be/app/module/provinces/service" ) // struct of ProvincesRouter diff --git a/app/module/provinces/repository/provinces.repository.go b/app/module/provinces/repository/provinces.repository.go index e7b8194..4c8629a 100644 --- a/app/module/provinces/repository/provinces.repository.go +++ b/app/module/provinces/repository/provinces.repository.go @@ -1,10 +1,10 @@ package repository import ( - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/provinces/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/provinces/request" + "netidhub-saas-be/utils/paginator" ) type provincesRepository struct { diff --git a/app/module/provinces/request/provinces.request.go b/app/module/provinces/request/provinces.request.go index a57080e..1a43771 100644 --- a/app/module/provinces/request/provinces.request.go +++ b/app/module/provinces/request/provinces.request.go @@ -1,8 +1,8 @@ package request import ( - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" ) type ProvincesGeneric interface { diff --git a/app/module/provinces/service/provinces.service.go b/app/module/provinces/service/provinces.service.go index 274098f..9c1dc70 100644 --- a/app/module/provinces/service/provinces.service.go +++ b/app/module/provinces/service/provinces.service.go @@ -2,11 +2,11 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/module/provinces/mapper" - "web-medols-be/app/module/provinces/repository" - "web-medols-be/app/module/provinces/request" - "web-medols-be/app/module/provinces/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/provinces/mapper" + "netidhub-saas-be/app/module/provinces/repository" + "netidhub-saas-be/app/module/provinces/request" + "netidhub-saas-be/app/module/provinces/response" + "netidhub-saas-be/utils/paginator" ) // ProvincesService diff --git a/app/module/schedules/controller/schedules.controller.go b/app/module/schedules/controller/schedules.controller.go index 810e587..9c4650c 100644 --- a/app/module/schedules/controller/schedules.controller.go +++ b/app/module/schedules/controller/schedules.controller.go @@ -1,17 +1,17 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/schedules/request" + "netidhub-saas-be/app/module/schedules/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/schedules/request" - "web-medols-be/app/module/schedules/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type schedulesController struct { diff --git a/app/module/schedules/mapper/schedules.mapper.go b/app/module/schedules/mapper/schedules.mapper.go index 5c37ef9..3cd978d 100644 --- a/app/module/schedules/mapper/schedules.mapper.go +++ b/app/module/schedules/mapper/schedules.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - schedulesResponse "web-medols-be/app/module/schedules/response" + "netidhub-saas-be/app/database/entity" + schedulesResponse "netidhub-saas-be/app/module/schedules/response" ) func ToSchedulesResponse(schedule *entity.Schedules) *schedulesResponse.SchedulesResponse { diff --git a/app/module/schedules/repository/schedules.repository.go b/app/module/schedules/repository/schedules.repository.go index bf4040d..e8ba265 100644 --- a/app/module/schedules/repository/schedules.repository.go +++ b/app/module/schedules/repository/schedules.repository.go @@ -1,10 +1,10 @@ package repository import ( - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/schedules/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/schedules/request" + "netidhub-saas-be/utils/paginator" "github.com/google/uuid" ) diff --git a/app/module/schedules/request/schedules.request.go b/app/module/schedules/request/schedules.request.go index 450765f..8c2138c 100644 --- a/app/module/schedules/request/schedules.request.go +++ b/app/module/schedules/request/schedules.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type SchedulesGeneric interface { diff --git a/app/module/schedules/schedules.module.go b/app/module/schedules/schedules.module.go index 936bbfe..71b7e72 100644 --- a/app/module/schedules/schedules.module.go +++ b/app/module/schedules/schedules.module.go @@ -1,11 +1,11 @@ package schedules import ( - "web-medols-be/app/middleware" - "web-medols-be/app/module/schedules/controller" - "web-medols-be/app/module/schedules/repository" - "web-medols-be/app/module/schedules/service" - usersRepo "web-medols-be/app/module/users/repository" + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/schedules/controller" + "netidhub-saas-be/app/module/schedules/repository" + "netidhub-saas-be/app/module/schedules/service" + usersRepo "netidhub-saas-be/app/module/users/repository" "github.com/gofiber/fiber/v2" "go.uber.org/fx" diff --git a/app/module/schedules/service/schedules.service.go b/app/module/schedules/service/schedules.service.go index 4a98c98..5022210 100644 --- a/app/module/schedules/service/schedules.service.go +++ b/app/module/schedules/service/schedules.service.go @@ -1,11 +1,11 @@ package service import ( - "web-medols-be/app/module/schedules/mapper" - "web-medols-be/app/module/schedules/repository" - "web-medols-be/app/module/schedules/request" - schedulesResponse "web-medols-be/app/module/schedules/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/schedules/mapper" + "netidhub-saas-be/app/module/schedules/repository" + "netidhub-saas-be/app/module/schedules/request" + schedulesResponse "netidhub-saas-be/app/module/schedules/response" + "netidhub-saas-be/utils/paginator" "github.com/google/uuid" ) diff --git a/app/module/subscription/controller/controller.go b/app/module/subscription/controller/controller.go index 36dde87..8d063b8 100644 --- a/app/module/subscription/controller/controller.go +++ b/app/module/subscription/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/subscription/service" + "netidhub-saas-be/app/module/subscription/service" ) type Controller struct { diff --git a/app/module/subscription/controller/subscription.controller.go b/app/module/subscription/controller/subscription.controller.go index dea0a37..c290e2f 100644 --- a/app/module/subscription/controller/subscription.controller.go +++ b/app/module/subscription/controller/subscription.controller.go @@ -1,13 +1,13 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/subscription/request" + "netidhub-saas-be/app/module/subscription/service" + "netidhub-saas-be/utils/paginator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/subscription/request" - "web-medols-be/app/module/subscription/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/subscription/mapper/subscription.mapper.go b/app/module/subscription/mapper/subscription.mapper.go index f8f9c11..fedee54 100644 --- a/app/module/subscription/mapper/subscription.mapper.go +++ b/app/module/subscription/mapper/subscription.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/subscription/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/subscription/response" ) func SubscriptionResponseMapper(subscriptionReq *entity.Subscription) (subscriptionRes *res.SubscriptionResponse) { diff --git a/app/module/subscription/repository/subscription.repository.go b/app/module/subscription/repository/subscription.repository.go index 484e307..8710b2b 100644 --- a/app/module/subscription/repository/subscription.repository.go +++ b/app/module/subscription/repository/subscription.repository.go @@ -4,11 +4,11 @@ import ( "fmt" "github.com/google/uuid" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/subscription/request" + "netidhub-saas-be/utils/paginator" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/subscription/request" - "web-medols-be/utils/paginator" ) type subscriptionRepository struct { diff --git a/app/module/subscription/request/subscription.request.go b/app/module/subscription/request/subscription.request.go index d8e7869..57dc863 100644 --- a/app/module/subscription/request/subscription.request.go +++ b/app/module/subscription/request/subscription.request.go @@ -1,9 +1,9 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type SubscriptionGeneric interface { diff --git a/app/module/subscription/service/subscription.service.go b/app/module/subscription/service/subscription.service.go index 0fcf425..2c4bdf1 100644 --- a/app/module/subscription/service/subscription.service.go +++ b/app/module/subscription/service/subscription.service.go @@ -3,13 +3,13 @@ package service import ( "github.com/google/uuid" "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/subscription/mapper" - "web-medols-be/app/module/subscription/repository" - "web-medols-be/app/module/subscription/request" - "web-medols-be/app/module/subscription/response" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/subscription/mapper" + "netidhub-saas-be/app/module/subscription/repository" + "netidhub-saas-be/app/module/subscription/request" + "netidhub-saas-be/app/module/subscription/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" ) // SubscriptionService diff --git a/app/module/subscription/subscription.module.go b/app/module/subscription/subscription.module.go index 09aa2a8..5940769 100644 --- a/app/module/subscription/subscription.module.go +++ b/app/module/subscription/subscription.module.go @@ -3,9 +3,9 @@ package subscription import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/subscription/controller" - "web-medols-be/app/module/subscription/repository" - "web-medols-be/app/module/subscription/service" + "netidhub-saas-be/app/module/subscription/controller" + "netidhub-saas-be/app/module/subscription/repository" + "netidhub-saas-be/app/module/subscription/service" ) // struct of SubscriptionRouter diff --git a/app/module/user_levels/controller/controller.go b/app/module/user_levels/controller/controller.go index ea2e278..1804e28 100644 --- a/app/module/user_levels/controller/controller.go +++ b/app/module/user_levels/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/user_levels/service" +import "netidhub-saas-be/app/module/user_levels/service" type Controller struct { UserLevels UserLevelsController diff --git a/app/module/user_levels/controller/user_levels.controller.go b/app/module/user_levels/controller/user_levels.controller.go index 2723c70..0c2030d 100644 --- a/app/module/user_levels/controller/user_levels.controller.go +++ b/app/module/user_levels/controller/user_levels.controller.go @@ -1,17 +1,17 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/user_levels/request" + "netidhub-saas-be/app/module/user_levels/service" + "netidhub-saas-be/utils/paginator" "strconv" "strings" - "web-medols-be/app/middleware" - "web-medols-be/app/module/user_levels/request" - "web-medols-be/app/module/user_levels/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type userLevelsController struct { diff --git a/app/module/user_levels/mapper/user_levels.mapper.go b/app/module/user_levels/mapper/user_levels.mapper.go index 27a00b3..6103d75 100644 --- a/app/module/user_levels/mapper/user_levels.mapper.go +++ b/app/module/user_levels/mapper/user_levels.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/user_levels/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/user_levels/response" ) func UserLevelsResponseMapper(userLevelsReq *entity.UserLevels) (userLevelsRes *res.UserLevelsResponse) { diff --git a/app/module/user_levels/repository/user_levels.repository.go b/app/module/user_levels/repository/user_levels.repository.go index d68828e..0fdd9ae 100644 --- a/app/module/user_levels/repository/user_levels.repository.go +++ b/app/module/user_levels/repository/user_levels.repository.go @@ -2,12 +2,12 @@ package repository import ( "fmt" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/user_levels/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/user_levels/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" "github.com/google/uuid" ) diff --git a/app/module/user_levels/request/user_levels.request.go b/app/module/user_levels/request/user_levels.request.go index 8d06599..7598596 100644 --- a/app/module/user_levels/request/user_levels.request.go +++ b/app/module/user_levels/request/user_levels.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type UserLevelsGeneric interface { diff --git a/app/module/user_levels/service/user_levels.service.go b/app/module/user_levels/service/user_levels.service.go index 0dc96c7..745c999 100644 --- a/app/module/user_levels/service/user_levels.service.go +++ b/app/module/user_levels/service/user_levels.service.go @@ -1,12 +1,12 @@ package service import ( - "web-medols-be/app/database/entity" - "web-medols-be/app/module/user_levels/mapper" - "web-medols-be/app/module/user_levels/repository" - "web-medols-be/app/module/user_levels/request" - "web-medols-be/app/module/user_levels/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/user_levels/mapper" + "netidhub-saas-be/app/module/user_levels/repository" + "netidhub-saas-be/app/module/user_levels/request" + "netidhub-saas-be/app/module/user_levels/response" + "netidhub-saas-be/utils/paginator" "github.com/google/uuid" "github.com/rs/zerolog" diff --git a/app/module/user_levels/user_levels.module.go b/app/module/user_levels/user_levels.module.go index c408f81..39d51ff 100644 --- a/app/module/user_levels/user_levels.module.go +++ b/app/module/user_levels/user_levels.module.go @@ -3,9 +3,9 @@ package user_levels import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/user_levels/controller" - "web-medols-be/app/module/user_levels/repository" - "web-medols-be/app/module/user_levels/service" + "netidhub-saas-be/app/module/user_levels/controller" + "netidhub-saas-be/app/module/user_levels/repository" + "netidhub-saas-be/app/module/user_levels/service" ) // struct of UserLevelsRouter diff --git a/app/module/user_role_accesses/controller/controller.go b/app/module/user_role_accesses/controller/controller.go index 2761762..fe73894 100644 --- a/app/module/user_role_accesses/controller/controller.go +++ b/app/module/user_role_accesses/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/user_role_accesses/service" +import "netidhub-saas-be/app/module/user_role_accesses/service" type Controller struct { UserRoleAccesses UserRoleAccessesController diff --git a/app/module/user_role_accesses/controller/user_role_accesses.controller.go b/app/module/user_role_accesses/controller/user_role_accesses.controller.go index ad706c8..fb5cc18 100644 --- a/app/module/user_role_accesses/controller/user_role_accesses.controller.go +++ b/app/module/user_role_accesses/controller/user_role_accesses.controller.go @@ -1,15 +1,15 @@ package controller import ( + "netidhub-saas-be/app/module/user_role_accesses/request" + "netidhub-saas-be/app/module/user_role_accesses/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/user_role_accesses/request" - "web-medols-be/app/module/user_role_accesses/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type userRoleAccessesController struct { diff --git a/app/module/user_role_accesses/mapper/user_role_accesses.mapper.go b/app/module/user_role_accesses/mapper/user_role_accesses.mapper.go index de83710..cd8d82d 100644 --- a/app/module/user_role_accesses/mapper/user_role_accesses.mapper.go +++ b/app/module/user_role_accesses/mapper/user_role_accesses.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/user_role_accesses/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/user_role_accesses/response" ) func UserRoleAccessesResponseMapper(userRoleAccessesReq *entity.UserRoleAccesses) (userRoleAccessesRes *res.UserRoleAccessesResponse) { diff --git a/app/module/user_role_accesses/repository/user_role_accesses.repository.go b/app/module/user_role_accesses/repository/user_role_accesses.repository.go index 7f3b6b8..e16f785 100644 --- a/app/module/user_role_accesses/repository/user_role_accesses.repository.go +++ b/app/module/user_role_accesses/repository/user_role_accesses.repository.go @@ -1,10 +1,10 @@ package repository import ( - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/user_role_accesses/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/user_role_accesses/request" + "netidhub-saas-be/utils/paginator" ) type userRoleAccessesRepository struct { diff --git a/app/module/user_role_accesses/request/user_role_accesses.request.go b/app/module/user_role_accesses/request/user_role_accesses.request.go index 46d8f52..6c137b2 100644 --- a/app/module/user_role_accesses/request/user_role_accesses.request.go +++ b/app/module/user_role_accesses/request/user_role_accesses.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type UserRoleAccessesGeneric interface { diff --git a/app/module/user_role_accesses/service/user_role_accesses.service.go b/app/module/user_role_accesses/service/user_role_accesses.service.go index 379f7ff..52e66d6 100644 --- a/app/module/user_role_accesses/service/user_role_accesses.service.go +++ b/app/module/user_role_accesses/service/user_role_accesses.service.go @@ -2,11 +2,11 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/module/user_role_accesses/mapper" - "web-medols-be/app/module/user_role_accesses/repository" - "web-medols-be/app/module/user_role_accesses/request" - "web-medols-be/app/module/user_role_accesses/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/user_role_accesses/mapper" + "netidhub-saas-be/app/module/user_role_accesses/repository" + "netidhub-saas-be/app/module/user_role_accesses/request" + "netidhub-saas-be/app/module/user_role_accesses/response" + "netidhub-saas-be/utils/paginator" ) // UserRoleAccessesService diff --git a/app/module/user_role_accesses/user_role_accesses.module.go b/app/module/user_role_accesses/user_role_accesses.module.go index e473866..6ec6643 100644 --- a/app/module/user_role_accesses/user_role_accesses.module.go +++ b/app/module/user_role_accesses/user_role_accesses.module.go @@ -3,9 +3,9 @@ package user_role_accesses import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/user_role_accesses/controller" - "web-medols-be/app/module/user_role_accesses/repository" - "web-medols-be/app/module/user_role_accesses/service" + "netidhub-saas-be/app/module/user_role_accesses/controller" + "netidhub-saas-be/app/module/user_role_accesses/repository" + "netidhub-saas-be/app/module/user_role_accesses/service" ) // struct of UserRoleAccessesRouter diff --git a/app/module/user_role_level_details/controller/controller.go b/app/module/user_role_level_details/controller/controller.go index 4bcc65e..c63df1e 100644 --- a/app/module/user_role_level_details/controller/controller.go +++ b/app/module/user_role_level_details/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/user_role_level_details/service" +import "netidhub-saas-be/app/module/user_role_level_details/service" type Controller struct { UserRoleLevelDetails UserRoleLevelDetailsController diff --git a/app/module/user_role_level_details/controller/user_role_level_details.controller.go b/app/module/user_role_level_details/controller/user_role_level_details.controller.go index 5454e8a..ba63c5a 100644 --- a/app/module/user_role_level_details/controller/user_role_level_details.controller.go +++ b/app/module/user_role_level_details/controller/user_role_level_details.controller.go @@ -2,13 +2,13 @@ package controller import ( "github.com/gofiber/fiber/v2" + "netidhub-saas-be/app/module/user_role_level_details/request" + "netidhub-saas-be/app/module/user_role_level_details/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/module/user_role_level_details/request" - "web-medols-be/app/module/user_role_level_details/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type userRoleLevelDetailsController struct { diff --git a/app/module/user_role_level_details/mapper/user_role_level_details.mapper.go b/app/module/user_role_level_details/mapper/user_role_level_details.mapper.go index 9ade682..7a2fbc2 100644 --- a/app/module/user_role_level_details/mapper/user_role_level_details.mapper.go +++ b/app/module/user_role_level_details/mapper/user_role_level_details.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/user_role_level_details/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/user_role_level_details/response" ) func UserRoleLevelDetailsResponseMapper(userRoleLevelDetailsReq *entity.UserRoleLevelDetails) (userRoleLevelDetailsRes *res.UserRoleLevelDetailsResponse) { diff --git a/app/module/user_role_level_details/repository/user_role_level_details.repository.go b/app/module/user_role_level_details/repository/user_role_level_details.repository.go index d9826dd..26c90c7 100644 --- a/app/module/user_role_level_details/repository/user_role_level_details.repository.go +++ b/app/module/user_role_level_details/repository/user_role_level_details.repository.go @@ -1,10 +1,10 @@ package repository import ( - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/user_role_level_details/request" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/user_role_level_details/request" + "netidhub-saas-be/utils/paginator" ) type userRoleLevelDetailsRepository struct { diff --git a/app/module/user_role_level_details/request/user_role_level_details.request.go b/app/module/user_role_level_details/request/user_role_level_details.request.go index 05c80f3..c6c524f 100644 --- a/app/module/user_role_level_details/request/user_role_level_details.request.go +++ b/app/module/user_role_level_details/request/user_role_level_details.request.go @@ -1,9 +1,9 @@ package request import ( + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/utils/paginator" "time" - "web-medols-be/app/database/entity" - "web-medols-be/utils/paginator" ) type UserRoleLevelDetailsGeneric interface { diff --git a/app/module/user_role_level_details/service/user_role_level_details.service.go b/app/module/user_role_level_details/service/user_role_level_details.service.go index 9929967..7ac1db4 100644 --- a/app/module/user_role_level_details/service/user_role_level_details.service.go +++ b/app/module/user_role_level_details/service/user_role_level_details.service.go @@ -2,11 +2,11 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/module/user_role_level_details/mapper" - "web-medols-be/app/module/user_role_level_details/repository" - "web-medols-be/app/module/user_role_level_details/request" - "web-medols-be/app/module/user_role_level_details/response" - "web-medols-be/utils/paginator" + "netidhub-saas-be/app/module/user_role_level_details/mapper" + "netidhub-saas-be/app/module/user_role_level_details/repository" + "netidhub-saas-be/app/module/user_role_level_details/request" + "netidhub-saas-be/app/module/user_role_level_details/response" + "netidhub-saas-be/utils/paginator" ) // UserRoleLevelDetailsService diff --git a/app/module/user_role_level_details/user_role_level_details.module.go b/app/module/user_role_level_details/user_role_level_details.module.go index b37d765..771894a 100644 --- a/app/module/user_role_level_details/user_role_level_details.module.go +++ b/app/module/user_role_level_details/user_role_level_details.module.go @@ -3,9 +3,9 @@ package user_role_level_details import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/user_role_level_details/controller" - "web-medols-be/app/module/user_role_level_details/repository" - "web-medols-be/app/module/user_role_level_details/service" + "netidhub-saas-be/app/module/user_role_level_details/controller" + "netidhub-saas-be/app/module/user_role_level_details/repository" + "netidhub-saas-be/app/module/user_role_level_details/service" ) // struct of UserRoleLevelDetailsRouter diff --git a/app/module/user_roles/controller/controller.go b/app/module/user_roles/controller/controller.go index 41a3fc8..96391ca 100644 --- a/app/module/user_roles/controller/controller.go +++ b/app/module/user_roles/controller/controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/rs/zerolog" - "web-medols-be/app/module/user_roles/service" + "netidhub-saas-be/app/module/user_roles/service" ) type Controller struct { diff --git a/app/module/user_roles/controller/user_roles.controller.go b/app/module/user_roles/controller/user_roles.controller.go index 50e47f4..7be20a1 100644 --- a/app/module/user_roles/controller/user_roles.controller.go +++ b/app/module/user_roles/controller/user_roles.controller.go @@ -1,12 +1,12 @@ package controller import ( + "netidhub-saas-be/app/module/user_roles/request" + "netidhub-saas-be/app/module/user_roles/service" + "netidhub-saas-be/utils/paginator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" "strconv" - "web-medols-be/app/module/user_roles/request" - "web-medols-be/app/module/user_roles/service" - "web-medols-be/utils/paginator" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" diff --git a/app/module/user_roles/mapper/user_roles.mapper.go b/app/module/user_roles/mapper/user_roles.mapper.go index 990e68e..1b09e08 100644 --- a/app/module/user_roles/mapper/user_roles.mapper.go +++ b/app/module/user_roles/mapper/user_roles.mapper.go @@ -1,8 +1,8 @@ package mapper import ( - "web-medols-be/app/database/entity" - res "web-medols-be/app/module/user_roles/response" + "netidhub-saas-be/app/database/entity" + res "netidhub-saas-be/app/module/user_roles/response" ) func UserRolesResponseMapper(userRolesReq *entity.UserRoles) (userRolesRes *res.UserRolesResponse) { diff --git a/app/module/user_roles/repository/user_roles.repository.go b/app/module/user_roles/repository/user_roles.repository.go index e8424ba..6b4bf91 100644 --- a/app/module/user_roles/repository/user_roles.repository.go +++ b/app/module/user_roles/repository/user_roles.repository.go @@ -3,12 +3,12 @@ package repository import ( "fmt" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/module/user_roles/request" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/module/user_roles/request" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" ) type userRolesRepository struct { diff --git a/app/module/user_roles/request/user_roles.request.go b/app/module/user_roles/request/user_roles.request.go index 8e498f5..9c14987 100644 --- a/app/module/user_roles/request/user_roles.request.go +++ b/app/module/user_roles/request/user_roles.request.go @@ -1,11 +1,11 @@ package request import ( + "netidhub-saas-be/app/database/entity" + userRoleAccessReq "netidhub-saas-be/app/module/user_role_accesses/request" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity" - userRoleAccessReq "web-medols-be/app/module/user_role_accesses/request" - "web-medols-be/utils/paginator" ) type UserRolesGeneric interface { diff --git a/app/module/user_roles/service/user_roles.service.go b/app/module/user_roles/service/user_roles.service.go index 12ac9b8..c7ca342 100644 --- a/app/module/user_roles/service/user_roles.service.go +++ b/app/module/user_roles/service/user_roles.service.go @@ -2,17 +2,17 @@ package service import ( "github.com/rs/zerolog" - "web-medols-be/app/database/entity" - userLevelsRepository "web-medols-be/app/module/user_levels/repository" - userRoleAccessRepository "web-medols-be/app/module/user_role_accesses/repository" - userRoleLevelDetailsRepository "web-medols-be/app/module/user_role_level_details/repository" - "web-medols-be/app/module/user_roles/mapper" - "web-medols-be/app/module/user_roles/repository" - "web-medols-be/app/module/user_roles/request" - "web-medols-be/app/module/user_roles/response" - usersRepository "web-medols-be/app/module/users/repository" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" + "netidhub-saas-be/app/database/entity" + userLevelsRepository "netidhub-saas-be/app/module/user_levels/repository" + userRoleAccessRepository "netidhub-saas-be/app/module/user_role_accesses/repository" + userRoleLevelDetailsRepository "netidhub-saas-be/app/module/user_role_level_details/repository" + "netidhub-saas-be/app/module/user_roles/mapper" + "netidhub-saas-be/app/module/user_roles/repository" + "netidhub-saas-be/app/module/user_roles/request" + "netidhub-saas-be/app/module/user_roles/response" + usersRepository "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" ) // UserRolesService diff --git a/app/module/user_roles/user_roles.module.go b/app/module/user_roles/user_roles.module.go index 1f9d86d..9e41645 100644 --- a/app/module/user_roles/user_roles.module.go +++ b/app/module/user_roles/user_roles.module.go @@ -3,9 +3,9 @@ package user_roles import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/user_roles/controller" - "web-medols-be/app/module/user_roles/repository" - "web-medols-be/app/module/user_roles/service" + "netidhub-saas-be/app/module/user_roles/controller" + "netidhub-saas-be/app/module/user_roles/repository" + "netidhub-saas-be/app/module/user_roles/service" ) // struct of UserRolesRouter diff --git a/app/module/users/controller/controller.go b/app/module/users/controller/controller.go index 8768992..5c01ea5 100644 --- a/app/module/users/controller/controller.go +++ b/app/module/users/controller/controller.go @@ -1,6 +1,6 @@ package controller -import "web-medols-be/app/module/users/service" +import "netidhub-saas-be/app/module/users/service" type Controller struct { Users UsersController diff --git a/app/module/users/controller/users.controller.go b/app/module/users/controller/users.controller.go index 77fb3ba..98e88b7 100644 --- a/app/module/users/controller/users.controller.go +++ b/app/module/users/controller/users.controller.go @@ -1,17 +1,17 @@ package controller import ( + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/users/request" + "netidhub-saas-be/app/module/users/service" + "netidhub-saas-be/utils/paginator" "strconv" - "web-medols-be/app/middleware" - "web-medols-be/app/module/users/request" - "web-medols-be/app/module/users/service" - "web-medols-be/utils/paginator" "github.com/gofiber/fiber/v2" _ "github.com/gofiber/fiber/v2" - utilRes "web-medols-be/utils/response" - utilVal "web-medols-be/utils/validator" + utilRes "netidhub-saas-be/utils/response" + utilVal "netidhub-saas-be/utils/validator" ) type usersController struct { diff --git a/app/module/users/mapper/users.mapper.go b/app/module/users/mapper/users.mapper.go index 7fc50f9..d1d354a 100644 --- a/app/module/users/mapper/users.mapper.go +++ b/app/module/users/mapper/users.mapper.go @@ -1,9 +1,9 @@ package mapper import ( - "web-medols-be/app/database/entity/users" - userLevelsRepository "web-medols-be/app/module/user_levels/repository" - res "web-medols-be/app/module/users/response" + "netidhub-saas-be/app/database/entity/users" + userLevelsRepository "netidhub-saas-be/app/module/user_levels/repository" + res "netidhub-saas-be/app/module/users/response" "github.com/google/uuid" ) diff --git a/app/module/users/repository/users.repository.go b/app/module/users/repository/users.repository.go index d03a615..b528f08 100644 --- a/app/module/users/repository/users.repository.go +++ b/app/module/users/repository/users.repository.go @@ -5,12 +5,12 @@ import ( "fmt" "github.com/google/uuid" "github.com/rs/zerolog" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/database/entity/users" + "netidhub-saas-be/app/module/users/request" + "netidhub-saas-be/utils/paginator" "strings" - "web-medols-be/app/database" - "web-medols-be/app/database/entity" - "web-medols-be/app/database/entity/users" - "web-medols-be/app/module/users/request" - "web-medols-be/utils/paginator" ) type usersRepository struct { diff --git a/app/module/users/request/users.request.go b/app/module/users/request/users.request.go index 66228f1..5ce42a6 100644 --- a/app/module/users/request/users.request.go +++ b/app/module/users/request/users.request.go @@ -1,10 +1,10 @@ package request import ( + "netidhub-saas-be/app/database/entity/users" + "netidhub-saas-be/utils/paginator" "strconv" "time" - "web-medols-be/app/database/entity/users" - "web-medols-be/utils/paginator" ) type UsersGeneric interface { diff --git a/app/module/users/service/users.service.go b/app/module/users/service/users.service.go index aab79af..b283824 100644 --- a/app/module/users/service/users.service.go +++ b/app/module/users/service/users.service.go @@ -4,18 +4,18 @@ import ( "encoding/base64" "encoding/json" "fmt" + "netidhub-saas-be/app/database/entity" + "netidhub-saas-be/app/database/entity/users" + userLevelsRepository "netidhub-saas-be/app/module/user_levels/repository" + "netidhub-saas-be/app/module/users/mapper" + "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/app/module/users/request" + "netidhub-saas-be/app/module/users/response" + "netidhub-saas-be/config/config" + "netidhub-saas-be/utils/paginator" + utilSvc "netidhub-saas-be/utils/service" "strings" "time" - "web-medols-be/app/database/entity" - "web-medols-be/app/database/entity/users" - userLevelsRepository "web-medols-be/app/module/user_levels/repository" - "web-medols-be/app/module/users/mapper" - "web-medols-be/app/module/users/repository" - "web-medols-be/app/module/users/request" - "web-medols-be/app/module/users/response" - "web-medols-be/config/config" - "web-medols-be/utils/paginator" - utilSvc "web-medols-be/utils/service" paseto "aidanwoods.dev/go-paseto" "github.com/Nerzal/gocloak/v13" diff --git a/app/module/users/users.module.go b/app/module/users/users.module.go index 216a320..1f415f8 100644 --- a/app/module/users/users.module.go +++ b/app/module/users/users.module.go @@ -3,9 +3,9 @@ package users import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" - "web-medols-be/app/module/users/controller" - "web-medols-be/app/module/users/repository" - "web-medols-be/app/module/users/service" + "netidhub-saas-be/app/module/users/controller" + "netidhub-saas-be/app/module/users/repository" + "netidhub-saas-be/app/module/users/service" ) // struct of UsersRouter diff --git a/app/router/api.go b/app/router/api.go index 5d4860f..7b82684 100644 --- a/app/router/api.go +++ b/app/router/api.go @@ -1,39 +1,39 @@ package router import ( - "web-medols-be/app/module/activity_logs" - "web-medols-be/app/module/advertisement" - "web-medols-be/app/module/approval_workflow_steps" - "web-medols-be/app/module/approval_workflows" - "web-medols-be/app/module/article_approval_flows" - "web-medols-be/app/module/article_approval_step_logs" - "web-medols-be/app/module/article_approvals" - "web-medols-be/app/module/article_categories" - "web-medols-be/app/module/article_category_details" - "web-medols-be/app/module/article_comments" - "web-medols-be/app/module/article_files" - "web-medols-be/app/module/article_nulis_ai" - "web-medols-be/app/module/articles" - "web-medols-be/app/module/bookmarks" - "web-medols-be/app/module/cities" - "web-medols-be/app/module/client_approval_settings" - "web-medols-be/app/module/clients" - "web-medols-be/app/module/custom_static_pages" - "web-medols-be/app/module/districts" - "web-medols-be/app/module/feedbacks" - "web-medols-be/app/module/magazine_files" - "web-medols-be/app/module/magazines" - "web-medols-be/app/module/master_menus" - "web-medols-be/app/module/master_modules" - "web-medols-be/app/module/provinces" - "web-medols-be/app/module/schedules" - "web-medols-be/app/module/subscription" - "web-medols-be/app/module/user_levels" - "web-medols-be/app/module/user_role_accesses" - "web-medols-be/app/module/user_roles" - "web-medols-be/app/module/users" - "web-medols-be/config/config" - _ "web-medols-be/docs/swagger" + "netidhub-saas-be/app/module/activity_logs" + "netidhub-saas-be/app/module/advertisement" + "netidhub-saas-be/app/module/approval_workflow_steps" + "netidhub-saas-be/app/module/approval_workflows" + "netidhub-saas-be/app/module/article_approval_flows" + "netidhub-saas-be/app/module/article_approval_step_logs" + "netidhub-saas-be/app/module/article_approvals" + "netidhub-saas-be/app/module/article_categories" + "netidhub-saas-be/app/module/article_category_details" + "netidhub-saas-be/app/module/article_comments" + "netidhub-saas-be/app/module/article_files" + "netidhub-saas-be/app/module/article_nulis_ai" + "netidhub-saas-be/app/module/articles" + "netidhub-saas-be/app/module/bookmarks" + "netidhub-saas-be/app/module/cities" + "netidhub-saas-be/app/module/client_approval_settings" + "netidhub-saas-be/app/module/clients" + "netidhub-saas-be/app/module/custom_static_pages" + "netidhub-saas-be/app/module/districts" + "netidhub-saas-be/app/module/feedbacks" + "netidhub-saas-be/app/module/magazine_files" + "netidhub-saas-be/app/module/magazines" + "netidhub-saas-be/app/module/master_menus" + "netidhub-saas-be/app/module/master_modules" + "netidhub-saas-be/app/module/provinces" + "netidhub-saas-be/app/module/schedules" + "netidhub-saas-be/app/module/subscription" + "netidhub-saas-be/app/module/user_levels" + "netidhub-saas-be/app/module/user_role_accesses" + "netidhub-saas-be/app/module/user_roles" + "netidhub-saas-be/app/module/users" + "netidhub-saas-be/config/config" + _ "netidhub-saas-be/docs/swagger" swagger "github.com/arsmn/fiber-swagger/v2" "github.com/gofiber/fiber/v2" diff --git a/config/logger/index.logger.go b/config/logger/index.logger.go index 6b7e72d..9da6492 100644 --- a/config/logger/index.logger.go +++ b/config/logger/index.logger.go @@ -3,8 +3,8 @@ package logger import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "netidhub-saas-be/config/config" "os" - "web-medols-be/config/config" ) // NewLogger : initialize logger diff --git a/config/toml/config.toml b/config/toml/config.toml index 2069708..41c7247 100644 --- a/config/toml/config.toml +++ b/config/toml/config.toml @@ -12,7 +12,7 @@ production = false body-limit = 1048576000 # "100 * 1024 * 1024" [db.postgres] -dsn = "postgresql://medols_user:MedolsDB@2025@38.47.180.165:5432/medols_db" # ://:@:/ +dsn = "postgresql://netidhub_user:NetidhubDB@2025@38.47.180.165:5432/netidhub_db" # ://:@:/ log-mode = "ERROR" migrate = true seed = false @@ -28,7 +28,7 @@ endpoint = "38.47.180.165:9009" access-key-id = "lBtjqWidHz1ktBbduwGy" secret-access-key = "nsedJIa2FI7SqsEVcSFqJrlP4JuFRWGLauNpzD0i" use-ssl = false -bucket-name = "mikulnews" +bucket-name = "netidhub" location = "us-east-1" [middleware.compress] diff --git a/config/webserver/webserver.config.go b/config/webserver/webserver.config.go index ba5bc5d..33429d7 100644 --- a/config/webserver/webserver.config.go +++ b/config/webserver/webserver.config.go @@ -9,17 +9,17 @@ import ( futils "github.com/gofiber/fiber/v2/utils" "github.com/rs/zerolog" "go.uber.org/fx" + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/database/seeds" + md "netidhub-saas-be/app/middleware" + articlesService "netidhub-saas-be/app/module/articles/service" + "netidhub-saas-be/app/router" + "netidhub-saas-be/config/config" + "netidhub-saas-be/utils/response" "os" "runtime" "strings" "time" - "web-medols-be/app/database" - "web-medols-be/app/database/seeds" - md "web-medols-be/app/middleware" - articlesService "web-medols-be/app/module/articles/service" - "web-medols-be/app/router" - "web-medols-be/config/config" - "web-medols-be/utils/response" ) // NewFiber : initialize the webserver @@ -126,11 +126,11 @@ func Start(lifecycle fx.Lifecycle, cfg *config.Config, fiber *fiber.App, router if *seedFlag { // init seed models - masterStatusSeeder := seeds.MasterStatusesSeeder{} - masterApprovalStatusSeeder := seeds.MasterApprovalStatusesSeeder{} - activityLogsSeeder := seeds.ActivityLogsSeeder{} - approvalWorkflowsSeeder := seeds.ApprovalWorkflowsSeeder{} - allSeeders := []database.Seeder{masterStatusSeeder, masterApprovalStatusSeeder, activityLogsSeeder, approvalWorkflowsSeeder} + masterStatusSeeder := seeds.MasterStatusesSeeder{} + masterApprovalStatusSeeder := seeds.MasterApprovalStatusesSeeder{} + activityLogsSeeder := seeds.ActivityLogsSeeder{} + approvalWorkflowsSeeder := seeds.ApprovalWorkflowsSeeder{} + allSeeders := []database.Seeder{masterStatusSeeder, masterApprovalStatusSeeder, activityLogsSeeder, approvalWorkflowsSeeder} db.SeedModels(allSeeders) } diff --git a/docs/CLIENTS_QUERY_CONTEXT_GUIDE.md b/docs/CLIENTS_QUERY_CONTEXT_GUIDE.md new file mode 100644 index 0000000..c2c24c4 --- /dev/null +++ b/docs/CLIENTS_QUERY_CONTEXT_GUIDE.md @@ -0,0 +1,316 @@ +# ๐Ÿ“‹ ClientsQueryRequestContext - Usage Guide (camelCase) + +## ๐ŸŽฏ **Overview** + +`ClientsQueryRequestContext` adalah struct yang memudahkan parsing query parameters dari HTTP request untuk filtering clients dengan hierarchy support. **Semua JSON fields menggunakan camelCase format.** + +## ๐Ÿ”ง **Available Query Parameters (camelCase)** + +### **Basic Filters** +```bash +# Filter by name (case-insensitive, partial match) +GET /api/clients?name=company + +# Filter by client type +GET /api/clients?clientType=parent_client +GET /api/clients?clientType=sub_client +GET /api/clients?clientType=standalone + +# Filter by parent client ID +GET /api/clients?parentClientId=123e4567-e89b-12d3-a456-426614174000 + +# Filter by active status +GET /api/clients?isActive=true +GET /api/clients?isActive=false +``` + +### **Hierarchy Filters** +```bash +# Only show clients that have children (parent clients) +GET /api/clients?onlyParentClients=true + +# Only show standalone clients (no parent, no children) +GET /api/clients?onlyStandalone=true + +# Only show root level clients (no parent) +GET /api/clients?onlyRootClients=true + +# Include all descendants when filtering by parent +GET /api/clients?parentClientId=uuid&includeSubClients=true +``` + +### **Pagination** +```bash +# Pagination +GET /api/clients?page=1&limit=10 +GET /api/clients?page=2&limit=20 + +# Sorting +GET /api/clients?sort=name&sort_by=asc +GET /api/clients?sort=created_at&sort_by=desc +``` + +## ๐Ÿš€ **Usage Examples (camelCase)** + +### **1. Get All Parent Clients** +```bash +GET /api/clients?clientType=parent_client&isActive=true +``` + +### **2. Get Sub-Clients of Specific Parent** +```bash +GET /api/clients?parentClientId=123e4567-e89b-12d3-a456-426614174000 +``` + +### **3. Get All Root Level Clients** +```bash +GET /api/clients?onlyRootClients=true +``` + +### **4. Search Clients by Name** +```bash +GET /api/clients?name=company&isActive=true +``` + +### **5. Get All Standalone Clients** +```bash +GET /api/clients?onlyStandalone=true +``` + +### **6. Complex Filtering** +```bash +GET /api/clients?clientType=sub_client&isActive=true&page=1&limit=20&sort=name&sort_by=asc +``` + +## ๐Ÿ“Š **Response Structure (camelCase)** + +```json +{ + "success": true, + "messages": ["Clients list successfully retrieved"], + "data": [ + { + "id": "123e4567-e89b-12d3-a456-426614174000", + "name": "Parent Company", + "description": "Main company", + "clientType": "parent_client", + "parentClientId": null, + "parentClient": null, + "subClients": [ + { + "id": "456e7890-e89b-12d3-a456-426614174001", + "name": "Sub Company 1", + "clientType": "sub_client", + "currentUsers": 25, + "isActive": true + } + ], + "subClientCount": 1, + "maxUsers": 100, + "maxStorage": 1073741824, + "currentUsers": 50, + "currentStorage": 536870912, + "settings": "{\"theme\": \"dark\"}", + "createdById": 1, + "createdBy": { + "id": 1, + "username": "admin", + "fullname": "Admin User" + }, + "isActive": true, + "createdAt": "2024-01-01T00:00:00Z", + "updatedAt": "2024-01-01T00:00:00Z" + } + ], + "meta": { + "page": 1, + "limit": 10, + "total": 1, + "total_pages": 1 + } +} +``` + +## ๐Ÿ” **Filter Combinations** + +### **Common Use Cases** + +1. **Dashboard - Show Parent Clients Only** + ```bash + GET /api/clients?onlyParentClients=true&isActive=true&page=1&limit=10 + ``` + +2. **Client Management - Show All Active Clients** + ```bash + GET /api/clients?isActive=true&sort=name&sort_by=asc + ``` + +3. **Hierarchy View - Show Root Clients** + ```bash + GET /api/clients?onlyRootClients=true&includeSubClients=true + ``` + +4. **Search - Find Clients by Name** + ```bash + GET /api/clients?name=company&isActive=true + ``` + +5. **Sub-Client Management - Show Children of Parent** + ```bash + GET /api/clients?parentClientId=uuid&isActive=true + ``` + +## ๐Ÿ“ **Request Body Examples (camelCase)** + +### **Create Client** +```json +{ + "name": "New Company", + "description": "Company description", + "clientType": "parent_client", + "parentClientId": null, + "maxUsers": 100, + "maxStorage": 1073741824, + "settings": "{\"theme\": \"dark\"}" +} +``` + +### **Update Client** +```json +{ + "name": "Updated Company", + "clientType": "standalone", + "parentClientId": null, + "isActive": true +} +``` + +### **Move Client** +```json +{ + "targetParentId": "123e4567-e89b-12d3-a456-426614174000" +} +``` + +### **Bulk Create Sub-Clients** +```json +{ + "parentClientId": "123e4567-e89b-12d3-a456-426614174000", + "subClients": [ + { + "name": "Sub Client 1", + "description": "First sub client", + "maxUsers": 50, + "maxStorage": 536870912 + }, + { + "name": "Sub Client 2", + "description": "Second sub client", + "maxUsers": 25, + "maxStorage": 268435456 + } + ] +} +``` + +## โšก **Performance Tips** + +1. **Use specific filters** - Always include `isActive=true` for better performance +2. **Limit results** - Use pagination (`page` & `limit`) for large datasets +3. **Use hierarchy filters** - `onlyParentClients`, `onlyStandalone`, `onlyRootClients` are optimized +4. **Combine filters** - Multiple filters work together efficiently + +## ๐Ÿ›  **Implementation Details** + +### **Controller Usage** +```go +func (_i *clientsController) All(c *fiber.Ctx) error { + paginate, err := paginator.Paginate(c) + if err != nil { + return err + } + + reqContext := request.ClientsQueryRequestContext{ + Name: c.Query("name"), + ClientType: c.Query("clientType"), + ParentClientId: c.Query("parentClientId"), + IncludeSubClients: c.Query("includeSubClients"), + OnlyParentClients: c.Query("onlyParentClients"), + OnlyStandalone: c.Query("onlyStandalone"), + OnlyRootClients: c.Query("onlyRootClients"), + IsActive: c.Query("isActive"), + CreatedById: c.Query("createdById"), + } + req := reqContext.ToParamRequest() + req.Pagination = paginate + + clientsData, paging, err := _i.clientsService.All(req) + // ... rest of implementation +} +``` + +## โœ… **Testing (camelCase)** + +### **Test Cases** +```bash +# Test basic filtering +curl "http://localhost:8080/api/clients?name=test&isActive=true" + +# Test hierarchy filtering +curl "http://localhost:8080/api/clients?onlyParentClients=true" + +# Test pagination +curl "http://localhost:8080/api/clients?page=1&limit=5" + +# Test sorting +curl "http://localhost:8080/api/clients?sort=name&sort_by=asc" + +# Test complex filtering +curl "http://localhost:8080/api/clients?clientType=sub_client&isActive=true&page=1&limit=10" +``` + +## ๐Ÿ”„ **Migration from snake_case** + +### **Before (snake_case)** +```bash +GET /api/clients?client_type=parent_client&parent_client_id=uuid&is_active=true +``` + +### **After (camelCase)** +```bash +GET /api/clients?clientType=parent_client&parentClientId=uuid&isActive=true +``` + +### **Request Body Migration** +```json +// Before +{ + "client_type": "parent_client", + "parent_client_id": "uuid", + "max_users": 100, + "max_storage": 1073741824 +} + +// After +{ + "clientType": "parent_client", + "parentClientId": "uuid", + "maxUsers": 100, + "maxStorage": 1073741824 +} +``` + +--- + +## ๐ŸŽ‰ **Ready to Use!** + +`ClientsQueryRequestContext` sekarang sudah terintegrasi dengan: +- โœ… Controller parsing (camelCase) +- โœ… Repository filtering +- โœ… Swagger documentation (camelCase) +- โœ… Type safety dengan UUID parsing +- โœ… Boolean conversion +- โœ… Pagination support +- โœ… **Full camelCase JSON support** + +Semua query parameters dan response fields menggunakan camelCase format! ๐Ÿš€ \ No newline at end of file diff --git a/docs/IMPLEMENTATION_SUMMARY.md b/docs/IMPLEMENTATION_SUMMARY.md new file mode 100644 index 0000000..ca7f8e9 --- /dev/null +++ b/docs/IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,440 @@ +# ๐ŸŽฏ Multi-Client Access Implementation Summary + +## Tanggal: 30 September 2025 + +## ๐Ÿ“Š Executive Summary + +Sistem telah diupgrade dari **single-client tenant isolation** menjadi **hierarchical multi-tenancy** dengan fitur: + +โœ… **Parent-Child Client Hierarchy** - Client bisa memiliki sub-clients (unlimited depth) +โœ… **Multi-Client User Access** - User bisa mengakses multiple clients sekaligus +โœ… **Super Admin Support** - Platform admin dengan akses ke semua clients +โœ… **Granular Access Control** - Read, Write, Admin, Owner levels +โœ… **Backward Compatible** - Kode lama tetap berfungsi + +--- + +## ๐ŸŽฏ Problem yang Dipecahkan + +### Before (Kondisi Lama) +``` +โŒ 1 User = 1 Client saja (rigid) +โŒ Tidak ada hierarchy client +โŒ Tidak ada super admin +โŒ Sulit monitor multiple clients +``` + +### After (Kondisi Baru) +``` +โœ… 1 User = Multiple Clients (flexible) +โœ… Parent Client โ†’ Sub Clients (unlimited depth) +โœ… Super Admin bisa akses semua +โœ… Manager bisa monitor beberapa client sekaligus +``` + +--- + +## ๐Ÿ“ฆ File-File yang Dibuat/Dimodifikasi + +### โœจ Entity Changes + +#### 1. **app/database/entity/clients.go** (MODIFIED) +```go ++ ClientType // 'parent_client', 'sub_client', 'standalone' ++ ParentClientId // UUID reference to parent ++ ParentClient // Relationship ++ SubClients // Array of children ++ Settings // JSONB custom config ++ MaxUsers // Limit untuk sub-clients ++ MaxStorage // Storage limit +``` + +#### 2. **app/database/entity/users.entity.go** (MODIFIED) +```go ++ IsSuperAdmin // Platform super admin flag ++ ClientAccesses // Many-to-Many relationship +``` + +#### 3. **app/database/entity/user_client_access.entity.go** (NEW โญ) +```go +// Many-to-Many table untuk User โ†” Client access +- UserId +- ClientId +- AccessType (read/write/admin/owner) +- CanManage +- CanDelegate +- IncludeSubClients (auto-access sub-clients) +``` + +### ๐Ÿ”ง Middleware & Utilities + +#### 4. **app/middleware/client_v2.middleware.go** (NEW โญ) +Enhanced middleware dengan support: +- Super admin detection +- Multi-client access retrieval +- Current client context +- Backward compatible dengan X-Client-Key header + +#### 5. **utils/client/client_hierarchy.go** (NEW โญ) +Helper functions: +- `GetAccessibleClientIDs()` - Get all accessible clients +- `GetSubClientIDs()` - Recursive sub-client retrieval +- `HasAccessToClient()` - Access validation +- `GetClientHierarchy()` - Parent-child structure +- `IsParentClient()` - Check if has children + +#### 6. **utils/middleware/client_utils_v2.go** (NEW โญ) +Query utilities: +- `AddMultiClientFilter()` - Auto filter by accessible clients +- `SetCurrentClientID()` - Set client on create +- `ValidateMultiClientAccess()` - Resource access check +- `FilterByCurrentClient()` - Filter by active client only + +### ๐Ÿ“š Documentation + +#### 7. **docs/MULTI_CLIENT_ACCESS_GUIDE.md** (NEW โญ) +Comprehensive guide: +- Architecture overview +- Database schema +- Migration steps +- Code examples +- Use cases +- Troubleshooting + +#### 8. **docs/migrations/001_add_multi_client_support.sql** (NEW โญ) +SQL migration script: +- ALTER TABLE statements +- CREATE TABLE user_client_access +- Indexes & constraints +- Helper functions (PostgreSQL) +- Views for reporting +- Rollback script + +#### 9. **docs/examples/articles_controller_example.go** (NEW โญ) +Real-world examples: +- GetAll dengan multi-client filter +- GetOne dengan access validation +- Create dengan target client selection +- Super admin dashboard +- Grant access endpoint +- Client hierarchy endpoints + +### ๐Ÿ—„๏ธ Database Migration + +#### 10. **app/database/index.database.go** (MODIFIED) +```go ++ entity.UserClientAccess{} // Added to Models() +``` + +--- + +## ๐Ÿš€ How to Deploy + +### Step 1: Backup Database +```bash +pg_dump netidhub_db > backup_before_multi_client.sql +``` + +### Step 2: Run Application (Auto-migrate) +```bash +# Pastikan config.toml: migrate = true +go run main.go +``` + +GORM AutoMigrate akan otomatis: +- Tambah columns di `clients` table +- Tambah column di `users` table +- Create `user_client_access` table + +### Step 3: Run SQL Migration (Optional) +```bash +# Untuk functions, views, dan indexes tambahan +psql -U netidhub_user -d netidhub_db -f docs/migrations/001_add_multi_client_support.sql +``` + +### Step 4: Migrate Data +```sql +-- Set existing clients sebagai 'standalone' +UPDATE clients SET client_type = 'standalone'; + +-- Create super admin +UPDATE users SET is_super_admin = true WHERE id = 1; +``` + +### Step 5: Update Code (Bertahap) + +**Option A: Full Migration** +```go +// Di config/webserver/webserver.config.go +app.Use(middleware.ClientMiddlewareV2(db.DB)) +``` + +**Option B: Gradual Migration** +```go +// Keep old middleware +app.Use(middleware.ClientMiddleware(db.DB)) + +// New routes use V2 +apiV2 := app.Group("/api/v2") +apiV2.Use(middleware.ClientMiddlewareV2(db.DB)) +``` + +--- + +## ๐Ÿ’ป Usage Examples + +### Example 1: Setup Parent-Child Clients + +```go +// Parent Client (Polda Metro) +parentClient := entity.Clients{ + ID: uuid.New(), + Name: "Polda Metro Jaya", + ClientType: "parent_client", +} +db.Create(&parentClient) + +// Sub Client (Polres) +subClient := entity.Clients{ + ID: uuid.New(), + Name: "Polres Jakarta Pusat", + ClientType: "sub_client", + ParentClientId: &parentClient.ID, +} +db.Create(&subClient) +``` + +### Example 2: Grant Multi-Client Access + +```go +// Manager bisa akses 3 Polres +access := entity.UserClientAccess{ + UserId: managerUserId, + ClientId: parentClientId, + AccessType: "admin", + IncludeSubClients: &trueVal, // Auto-access semua sub-clients + CanManage: &trueVal, +} +db.Create(&access) +``` + +### Example 3: Repository dengan Multi-Client Filter + +```go +func (r *ArticleRepository) GetAll(c *fiber.Ctx) ([]entity.Articles, error) { + query := r.DB.Model(&entity.Articles{}) + + // One line - auto filter by accessible clients! + query = middlewareUtils.AddMultiClientFilter(query, c) + + var articles []entity.Articles + query.Find(&articles) + return articles, nil +} +``` + +### Example 4: Check Access + +```go +func (ctrl *Controller) GetArticle(c *fiber.Ctx) error { + userId := c.Locals(customMiddleware.UserIDContextKey).(uint) + isSuperAdmin := customMiddleware.IsSuperAdmin(c) + + hasAccess, _ := clientUtils.HasAccessToClient( + db, userId, article.ClientId, isSuperAdmin, + ) + + if !hasAccess { + return c.Status(403).JSON(fiber.Map{"error": "Access denied"}) + } +} +``` + +--- + +## ๐ŸŽจ Use Case Scenarios + +### Scenario 1: Regional Manager +**Kebutuhan:** Manager regional monitor 5 Polres + +**Solusi:** +```go +// Grant access ke parent dengan IncludeSubClients +UserClientAccess{ + UserId: regionalManagerId, + ClientId: parentPolresId, + IncludeSubClients: true, // โœ… Auto-access semua sub-Polres +} +``` + +### Scenario 2: Super Admin Dashboard +**Kebutuhan:** Admin platform lihat semua data + +**Solusi:** +```go +// Set is_super_admin = true +users.IsSuperAdmin = true + +// Di controller +if customMiddleware.IsSuperAdmin(c) { + // No filtering - get ALL data +} +``` + +### Scenario 3: Multi-Organization User +**Kebutuhan:** User kerja di 2 organisasi berbeda + +**Solusi:** +```go +// Grant access ke 2 clients +UserClientAccess{ UserId: 123, ClientId: orgA } +UserClientAccess{ UserId: 123, ClientId: orgB } + +// User bisa switch via header: X-Client-Key +``` + +--- + +## โš ๏ธ Breaking Changes + +### NONE! ๐ŸŽ‰ + +Implementasi ini **BACKWARD COMPATIBLE**: + +โœ… Existing `ClientId` di Users tetap berfungsi +โœ… Middleware lama (`ClientMiddleware`) masih bisa dipakai +โœ… Repository dengan single-client filter masih work +โœ… Header `X-Client-Key` masih didukung + +Migration bisa dilakukan **bertahap** per module. + +--- + +## ๐Ÿ”’ Security Considerations + +1. โœ… **Super admin flag protected** - Cannot be set via API +2. โœ… **Access validation** - Always check before showing data +3. โœ… **Delegation control** - Only users with `CanDelegate` can grant access +4. โœ… **Audit trail** - Track who granted access (GrantedById) +5. โœ… **Cascade rules** - Proper foreign key constraints + +--- + +## ๐Ÿ“ˆ Performance Impact + +### Optimizations Implemented: +- โœ… Database indexes on `parent_client_id`, `user_id`, `client_id` +- โœ… Unique constraint on `(user_id, client_id)` +- โœ… Efficient recursive queries dengan PostgreSQL CTEs +- โœ… Preload relationships untuk avoid N+1 queries + +### Recommendations: +- ๐Ÿ”ธ Cache accessible client IDs di Redis (per user) +- ๐Ÿ”ธ Pagination untuk multi-client data +- ๐Ÿ”ธ Database read replicas untuk super admin queries + +--- + +## ๐Ÿงช Testing Checklist + +- [ ] Create parent client +- [ ] Create sub-client under parent +- [ ] Grant multi-client access to user +- [ ] Test `IncludeSubClients` = true +- [ ] Test super admin access all clients +- [ ] Test single-client user (backward compat) +- [ ] Test access validation on resources +- [ ] Test client hierarchy retrieval +- [ ] Test switching between clients +- [ ] Load test multi-client queries + +--- + +## ๐Ÿ“ž Next Steps + +### Recommended Actions: + +1. **Test di Development Environment** + ```bash + # Run migration + go run main.go + + # Verify tables + psql -c "\d user_client_access" + ``` + +2. **Create Sample Data** + ```sql + -- Parent client + INSERT INTO clients (id, name, client_type) VALUES (uuid_generate_v4(), 'Parent', 'parent_client'); + + -- Super admin + UPDATE users SET is_super_admin = true WHERE id = 1; + ``` + +3. **Update 1-2 Modules sebagai Pilot** + - Update Articles module dulu + - Test thoroughly + - Rollout to other modules + +4. **Monitor Performance** + - Check query performance + - Monitor database load + - Optimize if needed + +5. **User Training** + - Explain new multi-client concept + - Show how to switch clients + - Train admin on granting access + +--- + +## ๐Ÿ“Š Architecture Diagram + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ SUPER ADMIN (Platform) โ”‚ +โ”‚ Access: ALL clients, ALL data โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ โ”‚ โ”‚ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ PARENT CLIENT Aโ”‚ โ”‚PARENT CLIENT Bโ”‚ โ”‚STANDALONEโ”‚ +โ”‚ Manager User 1 โ”‚ โ”‚Manager User 2 โ”‚ โ”‚ CLIENT โ”‚ +โ”‚ (Multi-access) โ”‚ โ”‚(Multi-access) โ”‚ โ”‚ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ” + โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ +โ”Œโ”€โ”€โ–ผโ”€โ”€โ” โ”Œโ”€โ”€โ–ผโ”€โ” โ”Œโ–ผโ”€โ”€โ”€โ” โ”Œโ–ผโ”€โ”€โ”€โ” โ”Œโ”€โ–ผโ”€โ”€โ” +โ”‚SUB 1โ”‚ โ”‚SUB2โ”‚ โ”‚SUB3โ”‚ โ”‚SUB1โ”‚ โ”‚SUB2โ”‚ +โ”‚Usersโ”‚ โ”‚Userโ”‚ โ”‚Userโ”‚ โ”‚Userโ”‚ โ”‚Userโ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”˜ +``` + +--- + +## โœ… Conclusion + +Implementasi multi-client access ini memberikan **flexibility** yang sangat besar untuk: +- ๐ŸŽฏ **Scalability** - Support unlimited clients & hierarchy +- ๐ŸŽฏ **Flexibility** - User bisa manage multiple clients +- ๐ŸŽฏ **Security** - Granular access control +- ๐ŸŽฏ **Usability** - Easy untuk monitor & manage + +**Status:** โœ… Ready for Testing & Deployment + +--- + +## ๐Ÿ“š References + +- ๐Ÿ“– `docs/MULTI_CLIENT_ACCESS_GUIDE.md` - Comprehensive guide +- ๐Ÿ“– `docs/migrations/001_add_multi_client_support.sql` - SQL migration +- ๐Ÿ“– `docs/examples/articles_controller_example.go` - Code examples + +--- + +**Prepared by:** AI Assistant +**Date:** September 30, 2025 +**Version:** 1.0 diff --git a/docs/MODULE_UPDATE_CHECKLIST.md b/docs/MODULE_UPDATE_CHECKLIST.md new file mode 100644 index 0000000..ceea4fd --- /dev/null +++ b/docs/MODULE_UPDATE_CHECKLIST.md @@ -0,0 +1,382 @@ +# ๐Ÿ“‹ Module Update Checklist untuk Multi-Client Support + +## Status Saat Ini + +โŒ **Module BELUM disesuaikan** dengan entity baru +โœ… **Entity sudah diupdate** (Clients, Users, UserClientAccess) +โœ… **Middleware baru sudah dibuat** (ClientMiddlewareV2) +โœ… **Utilities sudah dibuat** (client_hierarchy, client_utils_v2) + +--- + +## ๐ŸŽฏ Module yang PERLU Diupdate + +### Priority 1: CRITICAL (Harus diupdate dulu) + +#### โœ… 1. Module: `clients` (PARTIALLY DONE) +**Status:** Request & Response V2 sudah dibuat +**TODO:** +- [ ] Update `clients.repository.go` - Add hierarchy queries +- [ ] Update `clients.service.go` - Add hierarchy logic +- [ ] Update `clients.controller.go` - Add new endpoints +- [ ] Update `clients.mapper.go` - Support new fields + +**Files Updated:** +- โœ… `request/clients.request.v2.go` - NEW +- โœ… `response/clients.response.v2.go` - NEW + +**New Endpoints Needed:** +```go +GET /api/v2/clients/:id/hierarchy // Get client tree +GET /api/v2/clients/:id/sub-clients // Get direct children +POST /api/v2/clients/:id/sub-clients // Create sub-client +PUT /api/v2/clients/:id/move // Move to different parent +GET /api/v2/clients/:id/stats // Get client statistics +POST /api/v2/clients/bulk-sub-clients // Bulk create sub-clients +``` + +--- + +#### โš ๏ธ 2. Module: `users` +**Impact:** HIGH - Users sekarang bisa multi-client access +**TODO:** +- [ ] Add endpoint untuk get accessible clients +- [ ] Add endpoint untuk switch current client +- [ ] Update user creation untuk set is_super_admin +- [ ] Update user list untuk show client access info + +**New Endpoints Needed:** +```go +GET /api/v2/users/me/accessible-clients // Get my accessible clients +POST /api/v2/users/me/switch-client // Switch active client +GET /api/v2/users/:id/client-access // Get user's client access +POST /api/v2/users/:id/grant-client-access // Grant multi-client access +DELETE /api/v2/users/:id/revoke-client-access // Revoke client access +``` + +--- + +#### โš ๏ธ 3. Module: `user_client_access` (NEW MODULE) +**Status:** NEED TO CREATE +**Purpose:** Manage many-to-many User โ†” Client relationships + +**Structure:** +``` +app/module/user_client_access/ +โ”œโ”€โ”€ user_client_access.module.go +โ”œโ”€โ”€ controller/ +โ”‚ โ””โ”€โ”€ user_client_access.controller.go +โ”œโ”€โ”€ service/ +โ”‚ โ””โ”€โ”€ user_client_access.service.go +โ”œโ”€โ”€ repository/ +โ”‚ โ””โ”€โ”€ user_client_access.repository.go +โ”œโ”€โ”€ request/ +โ”‚ โ””โ”€โ”€ user_client_access.request.go +โ””โ”€โ”€ response/ + โ””โ”€โ”€ user_client_access.response.go +``` + +**Endpoints:** +```go +GET /api/v2/user-client-access // List all access grants +POST /api/v2/user-client-access // Grant access +DELETE /api/v2/user-client-access/:id // Revoke access +GET /api/v2/user-client-access/user/:id // Get by user +GET /api/v2/user-client-access/client/:id // Get by client +``` + +--- + +### Priority 2: MEDIUM (Update untuk consistency) + +#### ๐Ÿ”ธ 4. Module: `articles` +**Impact:** MEDIUM - Perlu support multi-client filtering +**TODO:** +- [ ] Update repository `GetAll()` - Use `AddMultiClientFilter()` +- [ ] Update repository `FindOne()` - Validate client access +- [ ] Update service untuk validate user has access to target client +- [ ] Update controller untuk support `?client_id=xxx` filter + +**Changes Needed:** +```go +// OLD +func (r *Repository) GetAll(clientId *uuid.UUID, req request.QueryRequest) { + query := r.DB.Model(&entity.Articles{}) + if clientId != nil { + query = query.Where("client_id = ?", clientId) + } +} + +// NEW +func (r *Repository) GetAll(c *fiber.Ctx, req request.QueryRequest) { + query := r.DB.Model(&entity.Articles{}) + + // Auto-filter by accessible clients + query = middlewareUtils.AddMultiClientFilter(query, c) + + // Optional: specific client filter + if req.ClientId != nil { + // Validate access first + query = query.Where("client_id = ?", req.ClientId) + } +} +``` + +--- + +#### ๐Ÿ”ธ 5. Module: `user_roles` +**Impact:** MEDIUM - Roles mungkin specific per client +**TODO:** +- [ ] Update untuk support multi-client role access +- [ ] Add logic untuk inherit roles dari parent client (optional) + +--- + +#### ๐Ÿ”ธ 6. Module: `user_levels` +**Impact:** MEDIUM - Levels mungkin berbeda per client +**TODO:** +- [ ] Update untuk support multi-client level definitions +- [ ] Add hierarchy logic untuk levels across clients + +--- + +### Priority 3: LOW (Optional updates) + +Modules berikut juga punya `ClientId` field, tapi update bisa dilakukan bertahap: + +- `schedules` - Update filtering +- `feedbacks` - Update filtering +- `subscriptions` - Update filtering +- `magazines` - Update filtering +- `advertisements` - Update filtering +- `article_categories` - Update filtering +- `bookmarks` - Update filtering + +**Pattern sama untuk semua:** +```go +// Replace single-client filter +query = query.Where("client_id = ?", clientId) + +// With multi-client filter +query = middlewareUtils.AddMultiClientFilter(query, c) +``` + +--- + +## ๐Ÿš€ Quick Start Guide + +### Step 1: Update Module Clients (Paling Penting) + +```bash +# 1. Buat file baru +touch app/module/clients/repository/clients.repository.v2.go +touch app/module/clients/service/clients.service.v2.go +touch app/module/clients/controller/clients.controller.v2.go +``` + +### Step 2: Create UserClientAccess Module + +```bash +# 2. Buat module baru +mkdir -p app/module/user_client_access/{controller,service,repository,request,response} + +# Generate files (atau copy template) +``` + +### Step 3: Update Existing Modules Bertahap + +Update per module, testing setiap perubahan: +1. โœ… Update `articles` (most used) +2. โœ… Update `users` +3. โœ… Update other modules one by one + +--- + +## ๐Ÿ“ Template untuk Update Repository + +```go +package repository + +import ( + "netidhub-saas-be/app/database/entity" + middlewareUtils "netidhub-saas-be/utils/middleware" + "github.com/gofiber/fiber/v2" + "gorm.io/gorm" +) + +type Repository struct { + DB *gorm.DB +} + +// OLD VERSION (single-client) +func (r *Repository) GetAllOld(clientId *uuid.UUID, req request.QueryRequest) ([]entity.Model, error) { + query := r.DB.Model(&entity.Model{}) + + if clientId != nil { + query = query.Where("client_id = ?", clientId) + } + + var results []entity.Model + query.Find(&results) + return results, nil +} + +// NEW VERSION (multi-client) +func (r *Repository) GetAll(c *fiber.Ctx, req request.QueryRequest) ([]entity.Model, error) { + query := r.DB.Model(&entity.Model{}) + + // โœจ One line - auto multi-client filtering! + query = middlewareUtils.AddMultiClientFilter(query, c) + + // Rest of your existing logic + var results []entity.Model + query.Find(&results) + return results, nil +} +``` + +--- + +## ๐Ÿ“ Template untuk Update Service + +```go +package service + +import ( + customMiddleware "netidhub-saas-be/app/middleware" + clientUtils "netidhub-saas-be/utils/client" + "github.com/gofiber/fiber/v2" +) + +type Service struct { + repo Repository +} + +// Before creating/updating, validate client access +func (s *Service) Create(c *fiber.Ctx, req request.CreateRequest) error { + userId := c.Locals(customMiddleware.UserIDContextKey).(uint) + isSuperAdmin := customMiddleware.IsSuperAdmin(c) + + // If user specified a client, verify access + if req.ClientId != nil { + hasAccess, err := clientUtils.HasAccessToClient( + s.repo.DB, + userId, + *req.ClientId, + isSuperAdmin, + ) + + if err != nil || !hasAccess { + return fiber.NewError(403, "No access to this client") + } + } + + // Continue with creation + return s.repo.Create(req) +} +``` + +--- + +## ๐Ÿ“ Template untuk Update Controller + +```go +package controller + +import ( + customMiddleware "netidhub-saas-be/app/middleware" + "github.com/gofiber/fiber/v2" +) + +type Controller struct { + service Service +} + +// List with multi-client support +func (ctrl *Controller) GetAll(c *fiber.Ctx) error { + var req request.QueryRequest + c.QueryParser(&req) + + // Service/Repository will handle multi-client filtering + results, err := ctrl.service.GetAll(c, req) + + if err != nil { + return c.Status(500).JSON(fiber.Map{ + "success": false, + "message": "Failed to retrieve data", + }) + } + + // Show current context info (helpful for debugging) + isSuperAdmin := customMiddleware.IsSuperAdmin(c) + accessibleClients := customMiddleware.GetAccessibleClientIDs(c) + + return c.JSON(fiber.Map{ + "success": true, + "data": results, + "meta": fiber.Map{ + "is_super_admin": isSuperAdmin, + "accessible_clients_count": len(accessibleClients), + }, + }) +} +``` + +--- + +## โœ… Testing Checklist + +Untuk setiap module yang diupdate: + +- [ ] **Super Admin** bisa lihat semua data (no client filter) +- [ ] **Multi-client user** hanya lihat data dari accessible clients +- [ ] **Single-client user** hanya lihat data dari 1 client (backward compat) +- [ ] **Create** data dengan client_id validation +- [ ] **Update** data dengan access check +- [ ] **Delete** data dengan access check +- [ ] **Filter by client_id** works correctly +- [ ] **Performance** tidak menurun significant + +--- + +## ๐Ÿ“Š Progress Tracking + +| Module | Priority | Status | Updated By | Date | +|--------|----------|--------|------------|------| +| clients | P1 | ๐ŸŸก In Progress | - | - | +| users | P1 | โšช Not Started | - | - | +| user_client_access | P1 | โšช Not Started | - | - | +| articles | P2 | โšช Not Started | - | - | +| user_roles | P2 | โšช Not Started | - | - | +| user_levels | P2 | โšช Not Started | - | - | +| schedules | P3 | โšช Not Started | - | - | +| feedbacks | P3 | โšช Not Started | - | - | +| subscriptions | P3 | โšช Not Started | - | - | + +**Legend:** +- โšช Not Started +- ๐ŸŸก In Progress +- ๐ŸŸข Completed +- ๐Ÿ”ด Blocked + +--- + +## ๐Ÿ†˜ Need Help? + +Jika stuck atau ada pertanyaan: +1. Lihat `docs/examples/articles_controller_example.go` untuk contoh lengkap +2. Lihat `docs/MULTI_CLIENT_ACCESS_GUIDE.md` untuk penjelasan konsep +3. Check `docs/IMPLEMENTATION_SUMMARY.md` untuk overview + +--- + +## ๐ŸŽฏ Estimated Timeline + +- **Week 1:** Update module `clients` + Create `user_client_access` module +- **Week 2:** Update module `users` + `articles` +- **Week 3:** Update remaining P2 modules +- **Week 4:** Update P3 modules + Testing + +**Total: ~1 month** untuk full implementation semua modules. + +Bisa lebih cepat jika dikerjakan parallel atau prioritas hanya module penting saja. diff --git a/docs/MULTI_CLIENT_ACCESS_GUIDE.md b/docs/MULTI_CLIENT_ACCESS_GUIDE.md new file mode 100644 index 0000000..f9744f7 --- /dev/null +++ b/docs/MULTI_CLIENT_ACCESS_GUIDE.md @@ -0,0 +1,428 @@ +# Multi-Client Access & Client Hierarchy Guide + +## ๐Ÿ“‹ Overview + +Sistem ini mendukung **hierarchical multi-tenancy** dengan fitur: +- โœ… Parent-Child Client relationships (unlimited depth) +- โœ… User dapat memiliki akses ke multiple clients +- โœ… Super Admin dengan akses ke semua clients +- โœ… Fine-grained access control (read, write, admin, owner) +- โœ… Automatic sub-client inheritance + +--- + +## ๐Ÿ—๏ธ Arsitektur + +### Client Types + +1. **Standalone Client** - Client mandiri tanpa parent/child +2. **Parent Client** - Client yang memiliki sub-clients +3. **Sub Client** - Client yang berada di bawah parent client + +### User Types + +1. **Super Admin** - Platform administrator, akses ke SEMUA clients +2. **Multi-Client User** - User dengan akses ke beberapa clients (misal: manager regional) +3. **Single-Client User** - User regular dengan akses ke 1 client saja + +--- + +## ๐Ÿ—„๏ธ Database Schema + +### Entity: Clients + +```go +type Clients struct { + ID uuid.UUID + Name string + Description *string + ClientType string // 'parent_client', 'sub_client', 'standalone' + ParentClientId *uuid.UUID // Reference to parent + + Settings *string // JSONB custom settings + MaxUsers *int + MaxStorage *int64 + + CreatedById *uint + IsActive *bool +} +``` + +### Entity: UserClientAccess (Many-to-Many) + +```go +type UserClientAccess struct { + ID uint + UserId uint + ClientId uuid.UUID + + AccessType string // 'read', 'write', 'admin', 'owner' + CanManage *bool // Can manage client settings + CanDelegate *bool // Can give access to other users + IncludeSubClients *bool // Auto-access to all sub-clients + + GrantedById *uint + IsActive *bool +} +``` + +### Entity: Users (Updated) + +```go +type Users struct { + // ... existing fields + + IsSuperAdmin *bool // Platform super admin + ClientId *uuid.UUID // Primary client + ClientAccesses []UserClientAccess // Multiple client access +} +``` + +--- + +## ๐Ÿš€ Migration Steps + +### Step 1: Run Database Migration + +```bash +# Migration akan otomatis dijalankan saat aplikasi start +# Pastikan config migrate = true di config.toml + +go run main.go +``` + +### Step 2: Migrate Existing Data + +```sql +-- 1. Set semua existing clients sebagai 'standalone' +UPDATE clients +SET client_type = 'standalone' +WHERE client_type IS NULL; + +-- 2. Create super admin user (contoh) +UPDATE users +SET is_super_admin = true +WHERE id = 1; -- Ganti dengan ID admin utama Anda + +-- 3. Migrasi user existing ke UserClientAccess (optional) +-- Untuk user yang perlu akses ke multiple clients +INSERT INTO user_client_access (user_id, client_id, access_type, can_manage, is_active, created_at, updated_at) +SELECT + id as user_id, + client_id, + 'admin' as access_type, + true as can_manage, + true as is_active, + NOW(), + NOW() +FROM users +WHERE client_id IS NOT NULL +AND is_super_admin = false; +``` + +### Step 3: Update Code + +#### Option A: Gunakan Middleware V2 (Recommended) + +Update di `config/webserver/webserver.config.go`: + +```go +// Ganti middleware lama +// app.Use(middleware.ClientMiddleware(db.DB)) + +// Dengan middleware baru +app.Use(middleware.ClientMiddlewareV2(db.DB)) +``` + +#### Option B: Bertahap (Backward Compatible) + +Kedua middleware bisa berjalan bersamaan: +```go +// Keep old middleware for backward compatibility +app.Use(middleware.ClientMiddleware(db.DB)) + +// Routes baru bisa pakai V2 +apiV2 := app.Group("/api/v2") +apiV2.Use(middleware.ClientMiddlewareV2(db.DB)) +``` + +--- + +## ๐Ÿ’ป Contoh Penggunaan + +### 1. Setup Parent-Child Clients + +```go +// Create Parent Client +parentClient := entity.Clients{ + ID: uuid.New(), + Name: "Polda Metro Jaya", + ClientType: "parent_client", + IsActive: &trueVal, +} +db.Create(&parentClient) + +// Create Sub Clients +subClient1 := entity.Clients{ + ID: uuid.New(), + Name: "Polres Jakarta Pusat", + ClientType: "sub_client", + ParentClientId: &parentClient.ID, + IsActive: &trueVal, +} +db.Create(&subClient1) + +subClient2 := entity.Clients{ + ID: uuid.New(), + Name: "Polres Jakarta Barat", + ClientType: "sub_client", + ParentClientId: &parentClient.ID, + IsActive: &trueVal, +} +db.Create(&subClient2) +``` + +### 2. Grant Multi-Client Access + +```go +import "netidhub-saas-be/app/database/entity" + +// User bisa manage multiple clients +access1 := entity.UserClientAccess{ + UserId: managerUser.ID, + ClientId: parentClient.ID, + AccessType: "admin", + CanManage: &trueVal, + IncludeSubClients: &trueVal, // Auto-access semua sub-clients + IsActive: &trueVal, +} +db.Create(&access1) + +access2 := entity.UserClientAccess{ + UserId: managerUser.ID, + ClientId: anotherClient.ID, + AccessType: "read", + IsActive: &trueVal, +} +db.Create(&access2) +``` + +### 3. Update Repository dengan Multi-Client Filter + +**OLD CODE:** +```go +func (r *Repository) GetAll(clientId *uuid.UUID, req request.QueryRequest) { + query := r.DB.Model(&entity.Articles{}) + + if clientId != nil { + query = query.Where("client_id = ?", clientId) + } + // ... rest of code +} +``` + +**NEW CODE:** +```go +import middlewareUtils "netidhub-saas-be/utils/middleware" + +func (r *Repository) GetAll(c *fiber.Ctx, req request.QueryRequest) { + query := r.DB.Model(&entity.Articles{}) + + // Automatically filter by accessible clients + query = middlewareUtils.AddMultiClientFilter(query, c) + + // ... rest of code +} +``` + +### 4. Check User Access di Controller + +```go +import ( + customMiddleware "netidhub-saas-be/app/middleware" + clientUtils "netidhub-saas-be/utils/client" +) + +func (ctrl *Controller) GetArticle(c *fiber.Ctx) error { + articleId := c.Params("id") + + // Get user info + userId := c.Locals(customMiddleware.UserIDContextKey).(uint) + isSuperAdmin := customMiddleware.IsSuperAdmin(c) + + // Get article + var article entity.Articles + db.First(&article, articleId) + + // Check access + hasAccess, _ := clientUtils.HasAccessToClient( + db, + userId, + *article.ClientId, + isSuperAdmin, + ) + + if !hasAccess { + return c.Status(403).JSON(fiber.Map{ + "error": "Access denied", + }) + } + + return c.JSON(article) +} +``` + +### 5. Get Client Hierarchy + +```go +import clientUtils "netidhub-saas-be/utils/client" + +func (ctrl *Controller) GetClientInfo(c *fiber.Ctx) error { + clientId := c.Params("id") + clientUUID, _ := uuid.Parse(clientId) + + // Get full hierarchy + client, err := clientUtils.GetClientHierarchy(db, clientUUID) + + return c.JSON(fiber.Map{ + "client": client, + "parent": client.ParentClient, + "sub_clients": client.SubClients, + }) +} +``` + +--- + +## ๐ŸŽฏ Use Cases + +### Use Case 1: Regional Manager + +**Scenario:** Manager regional yang mengawasi 3 Polres + +```go +// Grant access dengan IncludeSubClients +access := entity.UserClientAccess{ + UserId: regionalManagerId, + ClientId: parentPolresId, + AccessType: "admin", + IncludeSubClients: &trueVal, // Auto-akses semua polres di bawahnya + CanManage: &trueVal, + IsActive: &trueVal, +} +``` + +### Use Case 2: Super Admin Dashboard + +```go +func (ctrl *AdminController) GetAllArticles(c *fiber.Ctx) error { + // Super admin bisa lihat semua artikel dari semua clients + if !customMiddleware.IsSuperAdmin(c) { + return c.Status(403).JSON(fiber.Map{ + "error": "Super admin only", + }) + } + + var articles []entity.Articles + // No client filtering for super admin + db.Find(&articles) + + return c.JSON(articles) +} +``` + +### Use Case 3: User Switching Between Clients + +```go +// User bisa switch antara clients yang dia punya akses +func (ctrl *UserController) SwitchClient(c *fiber.Ctx) error { + targetClientId := c.Params("client_id") + clientUUID, _ := uuid.Parse(targetClientId) + + userId := c.Locals(customMiddleware.UserIDContextKey).(uint) + + // Verify user has access + hasAccess, _ := clientUtils.HasAccessToClient( + db, + userId, + clientUUID, + false, + ) + + if !hasAccess { + return c.Status(403).JSON(fiber.Map{ + "error": "No access to this client", + }) + } + + // Update user's primary client or set in session + // Return success +} +``` + +--- + +## ๐Ÿ”’ Security Considerations + +1. **Always validate client access** sebelum menampilkan/memodifikasi data +2. **Super admin flag** harus di-protect dengan ketat (database constraint) +3. **Audit trail** untuk perubahan UserClientAccess +4. **Cascade rules** untuk delete parent client +5. **Rate limiting** untuk multi-client queries + +--- + +## ๐Ÿ› Troubleshooting + +### Issue: User tidak bisa akses client + +```go +// Debug: Check accessible clients +accessibleClients, _ := clientUtils.GetAccessibleClientIDs(db, userId, false) +fmt.Println("Accessible clients:", accessibleClients) +``` + +### Issue: Sub-clients tidak muncul + +```go +// Pastikan IncludeSubClients = true +db.Model(&entity.UserClientAccess{}). + Where("user_id = ?", userId). + Update("include_sub_clients", true) +``` + +### Issue: Super admin tidak bisa akses + +```go +// Verify super admin flag +var user entity.Users +db.First(&user, userId) +fmt.Println("Is Super Admin:", *user.IsSuperAdmin) +``` + +--- + +## ๐Ÿ“Š Performance Tips + +1. **Index** pada `parent_client_id` dan `user_id, client_id` (sudah ada di entity) +2. **Cache** accessible client IDs per user (Redis recommended) +3. **Batch queries** untuk sub-client retrieval +4. **Pagination** untuk multi-client data + +--- + +## ๐Ÿ”„ Backward Compatibility + +Kode lama tetap berfungsi: +- โœ… `middleware.GetClientID(c)` masih tersedia +- โœ… `ClientId` di Users tetap ada sebagai primary client +- โœ… Single-client filtering tetap work +- โœ… Header `X-Client-Key` masih didukung + +Migration ke V2 bisa dilakukan bertahap per module. + +--- + +## ๐Ÿ“ž Support + +Untuk pertanyaan atau issue, silakan hubungi tim development. diff --git a/docs/UPDATE_INSTRUCTIONS.md b/docs/UPDATE_INSTRUCTIONS.md new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/docs/UPDATE_INSTRUCTIONS.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/VERIFICATION_CHECKLIST.md b/docs/VERIFICATION_CHECKLIST.md new file mode 100644 index 0000000..7d692c9 --- /dev/null +++ b/docs/VERIFICATION_CHECKLIST.md @@ -0,0 +1,541 @@ +# โœ… Verification Checklist - Multi-Client Implementation + +## Status Lengkap Semua Komponen + +--- + +## ๐Ÿ“ฆ 1. DATABASE ENTITIES + +### โœ… Entity: `clients.entity.go` +**Status:** โœ… COMPLETE +**Location:** `app/database/entity/clients.entity.go` + +**Fields yang HARUS ada:** +- [x] `ID` (uuid.UUID) +- [x] `Name` (string) +- [x] `Description` (*string) - NEW +- [x] `ClientType` (string) - NEW: 'parent_client', 'sub_client', 'standalone' +- [x] `ParentClientId` (*uuid.UUID) - NEW +- [x] `ParentClient` (*Clients) - NEW: relationship +- [x] `SubClients` ([]Clients) - NEW: relationship +- [x] `Settings` (*string) - NEW: JSONB +- [x] `MaxUsers` (*int) - NEW +- [x] `MaxStorage` (*int64) - NEW +- [x] `CreatedById` (*uint) +- [x] `IsActive` (*bool) +- [x] `CreatedAt` (time.Time) +- [x] `UpdatedAt` (time.Time) + +--- + +### โœ… Entity: `users.entity.go` +**Status:** โœ… COMPLETE +**Location:** `app/database/entity/users.entity.go` + +**Fields yang HARUS ada:** +- [x] Semua existing fields (ID, Username, Email, dll) +- [x] `IsSuperAdmin` (*bool) - NEW +- [x] `ClientId` (*uuid.UUID) - EXISTING (primary client) +- [x] `ClientAccesses` ([]UserClientAccess) - NEW: relationship + +--- + +### โœ… Entity: `user_client_access.entity.go` +**Status:** โœ… COMPLETE +**Location:** `app/database/entity/user_client_access.entity.go` + +**Fields yang HARUS ada:** +- [x] `ID` (uint) +- [x] `UserId` (uint) +- [x] `ClientId` (uuid.UUID) +- [x] `AccessType` (string) - 'read', 'write', 'admin', 'owner' +- [x] `CanManage` (*bool) +- [x] `CanDelegate` (*bool) +- [x] `IncludeSubClients` (*bool) +- [x] `User` (*Users) - relationship +- [x] `Client` (*Clients) - relationship +- [x] `GrantedById` (*uint) +- [x] `GrantedBy` (*Users) - relationship +- [x] `IsActive` (*bool) +- [x] `CreatedAt` (time.Time) +- [x] `UpdatedAt` (time.Time) + +--- + +## ๐Ÿ—„๏ธ 2. DATABASE MIGRATION + +### โœ… Migration Registry +**Status:** โœ… COMPLETE +**Location:** `app/database/index.database.go` + +**Check:** +- [x] `entity.UserClientAccess{}` added to `Models()` function + +--- + +## ๐Ÿ”ง 3. MIDDLEWARE + +### โœ… Original Middleware (Backward Compatibility) +**Status:** โœ… EXISTS +**Location:** `app/middleware/client.middleware.go` + +**Should have:** +- [x] `ClientMiddleware()` function +- [x] `GetClientID()` helper +- [x] Validates X-Client-Key header +- [x] Stores client_id in context + +--- + +### โœ… Enhanced Middleware V2 +**Status:** โœ… COMPLETE +**Location:** `app/middleware/client_v2.middleware.go` + +**Should have:** +- [x] `ClientMiddlewareV2()` function +- [x] `GetAccessibleClientIDs()` helper +- [x] `GetCurrentClientID()` helper +- [x] `IsSuperAdmin()` helper +- [x] Super admin detection +- [x] Multi-client access retrieval +- [x] Backward compatible with X-Client-Key + +**Context Keys:** +- [x] `UserIDContextKey` +- [x] `IsSuperAdminContextKey` +- [x] `AccessibleClientIDsKey` +- [x] `CurrentClientIDKey` + +--- + +## ๐Ÿ› ๏ธ 4. UTILITY FUNCTIONS + +### โœ… Client Hierarchy Utilities +**Status:** โœ… COMPLETE +**Location:** `utils/client/client_hierarchy.go` + +**Functions yang HARUS ada:** +- [x] `GetAccessibleClientIDs(db, userId, isSuperAdmin)` - Get all accessible clients +- [x] `GetSubClientIDs(db, parentClientId)` - Recursive sub-clients +- [x] `GetClientHierarchy(db, clientId)` - Full hierarchy with relations +- [x] `HasAccessToClient(db, userId, clientId, isSuperAdmin)` - Access validation +- [x] `GetParentClientID(db, clientId)` - Get root parent +- [x] `IsParentClient(db, clientId)` - Check if has children +- [x] `removeDuplicateUUIDs(uuids)` - Helper + +--- + +### โœ… Query Utilities +**Status:** โœ… COMPLETE +**Location:** `utils/middleware/client_utils_v2.go` + +**Functions yang HARUS ada:** +- [x] `AddMultiClientFilter(db, c)` - Auto-filter by accessible clients +- [x] `SetCurrentClientID(c, model)` - Set client on create +- [x] `ValidateMultiClientAccess(db, c, table, resourceId)` - Validate access +- [x] `FilterByCurrentClient(db, c)` - Filter by active client only + +--- + +### โœ… Original Utilities (Backward Compatibility) +**Status:** โœ… EXISTS +**Location:** `utils/middleware/client_utils.go` + +**Functions yang HARUS tetap ada:** +- [x] `AddClientFilter(db, c)` - Single client filter +- [x] `SetClientID(c, model)` - Set single client +- [x] `ValidateClientAccess(db, c, table, resourceId)` - Validate single client + +--- + +## ๐Ÿ“š 5. DOCUMENTATION + +### โœ… Main Guide +**Status:** โœ… COMPLETE +**Location:** `docs/MULTI_CLIENT_ACCESS_GUIDE.md` + +**Sections:** +- [x] Overview & Architecture +- [x] Database Schema +- [x] Migration Steps +- [x] Usage Examples +- [x] Use Cases +- [x] Security Considerations +- [x] Troubleshooting +- [x] Backward Compatibility + +--- + +### โœ… SQL Migration +**Status:** โœ… COMPLETE +**Location:** `docs/migrations/001_add_multi_client_support.sql` + +**Includes:** +- [x] ALTER TABLE clients (add new columns) +- [x] ALTER TABLE users (add is_super_admin) +- [x] CREATE TABLE user_client_access +- [x] Indexes & Constraints +- [x] Helper Functions (PostgreSQL) +- [x] Views for reporting +- [x] Data migration queries +- [x] Rollback script + +--- + +### โœ… Code Examples +**Status:** โœ… COMPLETE +**Location:** `docs/examples/articles_controller_example.go` + +**Examples:** +- [x] GetAll with multi-client filter +- [x] GetOne with access validation +- [x] Create with client selection +- [x] Super admin dashboard +- [x] Grant client access +- [x] Get accessible clients +- [x] Client hierarchy endpoints +- [x] Route setup + +--- + +### โœ… Implementation Summary +**Status:** โœ… COMPLETE +**Location:** `docs/IMPLEMENTATION_SUMMARY.md` + +**Includes:** +- [x] Executive Summary +- [x] Problem & Solution +- [x] File Changes List +- [x] Deployment Steps +- [x] Usage Examples +- [x] Use Case Scenarios +- [x] Testing Checklist +- [x] Architecture Diagram + +--- + +### โœ… Module Update Guide +**Status:** โœ… COMPLETE +**Location:** `docs/MODULE_UPDATE_CHECKLIST.md` + +**Includes:** +- [x] Module Priority List +- [x] Update Templates (Repository, Service, Controller) +- [x] Testing Checklist +- [x] Progress Tracking Table +- [x] Timeline Estimation + +--- + +### โœ… Test Script +**Status:** โœ… COMPLETE +**Location:** `scripts/test_multi_client.sql` + +**Includes:** +- [x] Create super admin +- [x] Create parent client +- [x] Create sub-clients +- [x] Create manager with multi-access +- [x] Create regular user +- [x] Verification queries +- [x] Test queries + +--- + +## ๐Ÿ“ 6. MODULE: CLIENTS + +### โš ๏ธ Request DTOs +**Status:** โš ๏ธ NEEDS UPDATE +**Location:** `app/module/clients/request/clients.request.go` + +**Should include:** +- [ ] `CreateClientRequest` - with ClientType, ParentClientId +- [ ] `UpdateClientRequest` - with new fields +- [ ] `ClientsQueryRequest` - with hierarchy filters +- [ ] `MoveClientRequest` - for moving to different parent +- [ ] `BulkCreateSubClientsRequest` - bulk operations + +**Action Required:** UPDATE existing file to support new fields + +--- + +### โš ๏ธ Response DTOs +**Status:** โš ๏ธ NEEDS UPDATE +**Location:** `app/module/clients/response/clients.response.go` + +**Should include:** +- [ ] `ClientResponse` - with parent/sub-client info +- [ ] `ClientHierarchyResponse` - tree structure +- [ ] `ClientStatsResponse` - statistics +- [ ] `ClientListResponse` - list view +- [ ] `ClientAccessResponse` - user's accessible clients + +**Action Required:** UPDATE existing file to support new fields + +--- + +### โŒ Repository +**Status:** โŒ NEEDS UPDATE +**Location:** `app/module/clients/repository/clients.repository.go` + +**New Methods Needed:** +- [ ] `GetHierarchy(clientId)` - Get parent and children +- [ ] `GetSubClients(parentId)` - Get direct children +- [ ] `GetAllSubClients(parentId)` - Recursive all descendants +- [ ] `MoveClient(clientId, newParentId)` - Move to different parent +- [ ] `GetClientStats(clientId)` - Get statistics +- [ ] Update `GetAll()` - support hierarchy filters + +--- + +### โŒ Service +**Status:** โŒ NEEDS UPDATE +**Location:** `app/module/clients/service/clients.service.go` + +**New Methods Needed:** +- [ ] `CreateSubClient(parentId, req)` - Create under parent +- [ ] `MoveClient(clientId, newParentId)` - Validate and move +- [ ] `GetClientHierarchy(clientId)` - Get full tree +- [ ] `BulkCreateSubClients(parentId, subClients)` - Bulk create +- [ ] `ValidateClientType(type)` - Validate enum +- [ ] Update `Create()` - validate parent exists if sub_client + +--- + +### โŒ Controller +**Status:** โŒ NEEDS UPDATE +**Location:** `app/module/clients/controller/clients.controller.go` + +**New Endpoints Needed:** +- [ ] `GET /api/v2/clients/:id/hierarchy` - Get tree +- [ ] `GET /api/v2/clients/:id/sub-clients` - Get children +- [ ] `POST /api/v2/clients/:id/sub-clients` - Create sub-client +- [ ] `PUT /api/v2/clients/:id/move` - Move client +- [ ] `GET /api/v2/clients/:id/stats` - Get statistics +- [ ] `POST /api/v2/clients/bulk-sub-clients` - Bulk create + +--- + +## ๐Ÿ“ 7. MODULE: USER_CLIENT_ACCESS + +### โŒ Module Structure +**Status:** โŒ NEEDS TO BE CREATED +**Location:** `app/module/user_client_access/` + +**Required Files:** +- [ ] `user_client_access.module.go` +- [ ] `controller/user_client_access.controller.go` +- [ ] `service/user_client_access.service.go` +- [ ] `repository/user_client_access.repository.go` +- [ ] `request/user_client_access.request.go` +- [ ] `response/user_client_access.response.go` +- [ ] `mapper/user_client_access.mapper.go` + +**Endpoints Needed:** +- [ ] `GET /api/v2/user-client-access` - List all +- [ ] `POST /api/v2/user-client-access` - Grant access +- [ ] `DELETE /api/v2/user-client-access/:id` - Revoke access +- [ ] `GET /api/v2/user-client-access/user/:userId` - By user +- [ ] `GET /api/v2/user-client-access/client/:clientId` - By client + +--- + +## ๐Ÿ“ 8. MODULE: USERS (Updates) + +### โš ๏ธ Controller Updates +**Status:** โš ๏ธ NEEDS UPDATE +**Location:** `app/module/users/controller/users.controller.go` + +**New Endpoints Needed:** +- [ ] `GET /api/v2/users/me/accessible-clients` - Get my clients +- [ ] `POST /api/v2/users/me/switch-client` - Switch active client +- [ ] `GET /api/v2/users/:id/client-access` - Get user's access +- [ ] `POST /api/v2/users/:id/grant-client-access` - Grant access +- [ ] `DELETE /api/v2/users/:id/revoke-client-access/:accessId` - Revoke + +--- + +## ๐Ÿ“ 9. OTHER MODULES (Updates) + +### โš ๏ธ Articles Module +**Status:** โš ๏ธ NEEDS UPDATE +**Files:** repository, service, controller + +**Updates:** +- [ ] Repository: Use `AddMultiClientFilter()` instead of single client +- [ ] Service: Validate user has access to target client +- [ ] Controller: Support `?client_id=xxx` parameter + +--- + +### โš ๏ธ Other Modules with ClientId +**Status:** โš ๏ธ NEEDS UPDATE (Lower Priority) + +Modules to update (same pattern): +- [ ] `schedules` +- [ ] `feedbacks` +- [ ] `subscription` +- [ ] `magazines` +- [ ] `advertisement` +- [ ] `article_categories` +- [ ] `bookmarks` +- [ ] `user_roles` +- [ ] `user_levels` + +--- + +## ๐Ÿ”ง 10. CONFIGURATION + +### โš ๏ธ Router Registration +**Status:** โš ๏ธ NEEDS UPDATE +**Location:** `app/router/api.go` + +**Check:** +- [ ] ClientMiddlewareV2 applied to routes +- [ ] Or: V2 routes group created +- [ ] UserClientAccess routes registered (when module created) + +--- + +### โš ๏ธ Main Application +**Status:** โš ๏ธ CHECK +**Location:** `main.go` + +**Verify:** +- [ ] UserClientAccess module imported (when created) +- [ ] Module registered in fx.Provide + +--- + +## ๐Ÿงช 11. TESTING + +### โŒ Unit Tests +**Status:** โŒ NOT CREATED + +**Need to create:** +- [ ] `client_hierarchy_test.go` - Test utility functions +- [ ] `client_middleware_v2_test.go` - Test middleware +- [ ] `clients_repository_test.go` - Test repository methods +- [ ] `user_client_access_repository_test.go` - Test access queries + +--- + +### โŒ Integration Tests +**Status:** โŒ NOT CREATED + +**Scenarios to test:** +- [ ] Super admin can access all clients +- [ ] Multi-client user sees only accessible clients +- [ ] Single-client user sees only their client +- [ ] IncludeSubClients grants access to children +- [ ] Access validation prevents unauthorized access +- [ ] Parent-child hierarchy works correctly + +--- + +## ๐Ÿ“Š SUMMARY + +### โœ… Infrastructure (COMPLETE) +- โœ… Database Entities +- โœ… Middleware V2 +- โœ… Utility Functions +- โœ… Documentation +- โœ… Migration Scripts +- โœ… Test Scripts + +### โš ๏ธ Application Logic (IN PROGRESS) +- โš ๏ธ Module Clients - DTOs need update +- โŒ Module UserClientAccess - Need to create +- โŒ Module Users - Need endpoints +- โŒ Other Modules - Need updates + +### โŒ Not Started +- โŒ Repository implementations +- โŒ Service implementations +- โŒ Controller implementations +- โŒ Unit tests +- โŒ Integration tests + +--- + +## ๐ŸŽฏ PRIORITY ACTION ITEMS + +### ๐Ÿ”ฅ Critical (Do First) +1. **Update `clients.request.go`** - Add new fields +2. **Update `clients.response.go`** - Add hierarchy responses +3. **Update `clients.repository.go`** - Add hierarchy queries +4. **Update `clients.service.go`** - Add business logic +5. **Update `clients.controller.go`** - Add new endpoints + +### ๐Ÿ”ธ Important (Do Next) +6. **Create `user_client_access` module** - Full CRUD +7. **Update `users` module** - Add access management endpoints +8. **Update `articles` repository** - Use multi-client filter + +### ๐Ÿ”น Nice to Have (Do Later) +9. Update other modules (schedules, feedbacks, etc) +10. Create unit tests +11. Create integration tests +12. Performance optimization + +--- + +## โœ… VERIFICATION COMMANDS + +Run these to verify setup: + +```bash +# 1. Check database tables +psql -c "\d clients" +psql -c "\d users" +psql -c "\d user_client_access" + +# 2. Check new columns +psql -c "SELECT column_name FROM information_schema.columns WHERE table_name = 'clients';" + +# 3. Test data +psql -f scripts/test_multi_client.sql + +# 4. Check Go imports +go mod tidy +go build + +# 5. Run linter +golangci-lint run +``` + +--- + +## ๐Ÿ“ˆ COMPLETION PERCENTAGE + +| Component | Status | Progress | +|-----------|--------|----------| +| Database & Entities | โœ… Complete | 100% | +| Middleware | โœ… Complete | 100% | +| Utilities | โœ… Complete | 100% | +| Documentation | โœ… Complete | 100% | +| Module: Clients (DTOs) | โš ๏ธ In Progress | 30% | +| Module: Clients (Logic) | โŒ Not Started | 0% | +| Module: UserClientAccess | โŒ Not Started | 0% | +| Module: Users (Updates) | โŒ Not Started | 0% | +| Module: Articles (Updates) | โŒ Not Started | 0% | +| Other Modules | โŒ Not Started | 0% | +| Testing | โŒ Not Started | 0% | + +**Overall Progress:** ~40% (Infrastructure complete, Application logic pending) + +--- + +## ๐ŸŽฏ NEXT IMMEDIATE STEPS + +1. โœ… Run database migration +2. โœ… Run test SQL script +3. โš ๏ธ Update `clients.request.go` +4. โš ๏ธ Update `clients.response.go` +5. โŒ Update `clients.repository.go` +6. โŒ Update `clients.service.go` +7. โŒ Update `clients.controller.go` +8. โŒ Test endpoints + +**Estimated time for Clients module:** 1-2 days +**Estimated time for full implementation:** 2-4 weeks diff --git a/docs/migrations/001_add_multi_client_support.sql b/docs/migrations/001_add_multi_client_support.sql new file mode 100644 index 0000000..3a6bddd --- /dev/null +++ b/docs/migrations/001_add_multi_client_support.sql @@ -0,0 +1,379 @@ +-- ============================================================================ +-- Migration: Add Multi-Client Access & Client Hierarchy Support +-- Version: 1.0 +-- Date: 2025-09-30 +-- Description: Menambahkan support untuk parent-child clients dan +-- multi-client access per user +-- ============================================================================ + +-- ---------------------------------------------------------------------------- +-- STEP 1: Update Clients Table +-- ---------------------------------------------------------------------------- + +-- Add new columns to clients table +ALTER TABLE clients +ADD COLUMN IF NOT EXISTS description TEXT, +ADD COLUMN IF NOT EXISTS client_type VARCHAR DEFAULT 'sub_client', +ADD COLUMN IF NOT EXISTS parent_client_id UUID, +ADD COLUMN IF NOT EXISTS settings JSONB, +ADD COLUMN IF NOT EXISTS max_users INT4, +ADD COLUMN IF NOT EXISTS max_storage INT8; + +-- Add index for parent_client_id +CREATE INDEX IF NOT EXISTS idx_clients_parent_client_id +ON clients(parent_client_id); + +-- Add foreign key constraint +ALTER TABLE clients +ADD CONSTRAINT fk_clients_parent_client +FOREIGN KEY (parent_client_id) +REFERENCES clients(id) +ON DELETE SET NULL; + +-- Update existing clients to 'standalone' type +UPDATE clients +SET client_type = 'standalone' +WHERE client_type IS NULL OR client_type = ''; + +COMMENT ON COLUMN clients.client_type IS 'parent_client, sub_client, or standalone'; +COMMENT ON COLUMN clients.parent_client_id IS 'Reference to parent client for hierarchy'; +COMMENT ON COLUMN clients.settings IS 'JSONB custom settings for the client'; + +-- ---------------------------------------------------------------------------- +-- STEP 2: Update Users Table +-- ---------------------------------------------------------------------------- + +-- Add super admin flag +ALTER TABLE users +ADD COLUMN IF NOT EXISTS is_super_admin BOOLEAN DEFAULT FALSE; + +-- Create index for super admin lookups +CREATE INDEX IF NOT EXISTS idx_users_is_super_admin +ON users(is_super_admin) +WHERE is_super_admin = TRUE; + +COMMENT ON COLUMN users.is_super_admin IS 'Platform super admin with access to all clients'; +COMMENT ON COLUMN users.client_id IS 'Primary/default client for the user'; + +-- ---------------------------------------------------------------------------- +-- STEP 3: Create UserClientAccess Table (Many-to-Many) +-- ---------------------------------------------------------------------------- + +CREATE TABLE IF NOT EXISTS user_client_access ( + id SERIAL PRIMARY KEY, + user_id INT4 NOT NULL, + client_id UUID NOT NULL, + + -- Access control + access_type VARCHAR DEFAULT 'read', + can_manage BOOLEAN DEFAULT FALSE, + can_delegate BOOLEAN DEFAULT FALSE, + include_sub_clients BOOLEAN DEFAULT FALSE, + + -- Audit + granted_by_id INT4, + is_active BOOLEAN DEFAULT TRUE, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW(), + + -- Constraints + CONSTRAINT fk_user_client_access_user + FOREIGN KEY (user_id) + REFERENCES users(id) + ON DELETE CASCADE, + + CONSTRAINT fk_user_client_access_client + FOREIGN KEY (client_id) + REFERENCES clients(id) + ON DELETE CASCADE, + + CONSTRAINT fk_user_client_access_granted_by + FOREIGN KEY (granted_by_id) + REFERENCES users(id) + ON DELETE SET NULL, + + -- Prevent duplicate access entries + CONSTRAINT uk_user_client_access_unique + UNIQUE (user_id, client_id) +); + +-- Create indexes for performance +CREATE INDEX IF NOT EXISTS idx_user_client_access_user_id +ON user_client_access(user_id); + +CREATE INDEX IF NOT EXISTS idx_user_client_access_client_id +ON user_client_access(client_id); + +CREATE INDEX IF NOT EXISTS idx_user_client_access_user_client +ON user_client_access(user_id, client_id); + +CREATE INDEX IF NOT EXISTS idx_user_client_access_active +ON user_client_access(user_id, is_active) +WHERE is_active = TRUE; + +-- Add comments +COMMENT ON TABLE user_client_access IS 'Many-to-many relationship between users and clients for multi-tenant access'; +COMMENT ON COLUMN user_client_access.access_type IS 'Access level: read, write, admin, or owner'; +COMMENT ON COLUMN user_client_access.can_manage IS 'Can manage client settings'; +COMMENT ON COLUMN user_client_access.can_delegate IS 'Can grant access to other users'; +COMMENT ON COLUMN user_client_access.include_sub_clients IS 'Automatically grant access to all sub-clients'; + +-- ---------------------------------------------------------------------------- +-- STEP 4: Data Migration (Optional but Recommended) +-- ---------------------------------------------------------------------------- + +-- Create UserClientAccess entries for existing users with client_id +-- This is optional - only if you want existing users to have explicit access records +INSERT INTO user_client_access ( + user_id, + client_id, + access_type, + can_manage, + is_active, + created_at, + updated_at +) +SELECT + id as user_id, + client_id, + 'admin' as access_type, -- Default existing users as admin + TRUE as can_manage, + TRUE as is_active, + NOW(), + NOW() +FROM users +WHERE client_id IS NOT NULL + AND (is_super_admin IS NULL OR is_super_admin = FALSE) + AND NOT EXISTS ( + SELECT 1 FROM user_client_access uca + WHERE uca.user_id = users.id + AND uca.client_id = users.client_id + ); + +-- ---------------------------------------------------------------------------- +-- STEP 5: Create Helper Functions (Optional) +-- ---------------------------------------------------------------------------- + +-- Function to get all accessible client IDs for a user (including sub-clients) +CREATE OR REPLACE FUNCTION get_user_accessible_client_ids(p_user_id INT4) +RETURNS TABLE(client_id UUID) AS $$ +BEGIN + RETURN QUERY + WITH RECURSIVE client_hierarchy AS ( + -- Base case: direct client access + SELECT uca.client_id, uca.include_sub_clients + FROM user_client_access uca + WHERE uca.user_id = p_user_id + AND uca.is_active = TRUE + + UNION + + -- User's primary client + SELECT u.client_id, FALSE as include_sub_clients + FROM users u + WHERE u.id = p_user_id + AND u.client_id IS NOT NULL + + UNION + + -- Recursive case: sub-clients if include_sub_clients is true + SELECT c.id, FALSE + FROM clients c + INNER JOIN client_hierarchy ch ON c.parent_client_id = ch.client_id + WHERE ch.include_sub_clients = TRUE + AND c.is_active = TRUE + ) + SELECT DISTINCT ch.client_id + FROM client_hierarchy ch + WHERE ch.client_id IS NOT NULL; +END; +$$ LANGUAGE plpgsql; + +COMMENT ON FUNCTION get_user_accessible_client_ids IS 'Returns all client IDs accessible by a user including sub-clients'; + +-- Function to check if client is a parent (has sub-clients) +CREATE OR REPLACE FUNCTION is_parent_client(p_client_id UUID) +RETURNS BOOLEAN AS $$ +DECLARE + v_count INT; +BEGIN + SELECT COUNT(*) INTO v_count + FROM clients + WHERE parent_client_id = p_client_id + AND is_active = TRUE; + + RETURN v_count > 0; +END; +$$ LANGUAGE plpgsql; + +COMMENT ON FUNCTION is_parent_client IS 'Check if a client has sub-clients'; + +-- Function to get all sub-client IDs recursively +CREATE OR REPLACE FUNCTION get_sub_client_ids(p_parent_client_id UUID) +RETURNS TABLE(client_id UUID) AS $$ +BEGIN + RETURN QUERY + WITH RECURSIVE sub_clients AS ( + -- Base case: direct children + SELECT id as client_id + FROM clients + WHERE parent_client_id = p_parent_client_id + AND is_active = TRUE + + UNION + + -- Recursive case: children of children + SELECT c.id + FROM clients c + INNER JOIN sub_clients sc ON c.parent_client_id = sc.client_id + WHERE c.is_active = TRUE + ) + SELECT sc.client_id FROM sub_clients sc; +END; +$$ LANGUAGE plpgsql; + +COMMENT ON FUNCTION get_sub_client_ids IS 'Get all sub-client IDs recursively for a parent client'; + +-- ---------------------------------------------------------------------------- +-- STEP 6: Create Views for Common Queries (Optional) +-- ---------------------------------------------------------------------------- + +-- View: User Client Access with Details +CREATE OR REPLACE VIEW v_user_client_access_details AS +SELECT + uca.id, + uca.user_id, + u.username, + u.fullname, + u.email, + uca.client_id, + c.name as client_name, + c.client_type, + c.parent_client_id, + pc.name as parent_client_name, + uca.access_type, + uca.can_manage, + uca.can_delegate, + uca.include_sub_clients, + uca.granted_by_id, + gb.username as granted_by_username, + uca.is_active, + uca.created_at, + uca.updated_at +FROM user_client_access uca +INNER JOIN users u ON uca.user_id = u.id +INNER JOIN clients c ON uca.client_id = c.id +LEFT JOIN clients pc ON c.parent_client_id = pc.id +LEFT JOIN users gb ON uca.granted_by_id = gb.id; + +COMMENT ON VIEW v_user_client_access_details IS 'User client access with user and client details'; + +-- View: Client Hierarchy +CREATE OR REPLACE VIEW v_client_hierarchy AS +SELECT + c.id, + c.name, + c.description, + c.client_type, + c.parent_client_id, + pc.name as parent_client_name, + (SELECT COUNT(*) FROM clients WHERE parent_client_id = c.id AND is_active = TRUE) as sub_client_count, + c.max_users, + c.max_storage, + (SELECT COUNT(*) FROM users WHERE client_id = c.id AND is_active = TRUE) as current_users, + c.is_active, + c.created_at, + c.updated_at +FROM clients c +LEFT JOIN clients pc ON c.parent_client_id = pc.id; + +COMMENT ON VIEW v_client_hierarchy IS 'Client hierarchy with parent info and statistics'; + +-- ---------------------------------------------------------------------------- +-- STEP 7: Create Triggers (Optional - for audit/auto-update) +-- ---------------------------------------------------------------------------- + +-- Trigger to update updated_at on user_client_access +CREATE OR REPLACE FUNCTION update_user_client_access_timestamp() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +DROP TRIGGER IF EXISTS trg_update_user_client_access_timestamp ON user_client_access; +CREATE TRIGGER trg_update_user_client_access_timestamp + BEFORE UPDATE ON user_client_access + FOR EACH ROW + EXECUTE FUNCTION update_user_client_access_timestamp(); + +-- ---------------------------------------------------------------------------- +-- STEP 8: Grant Permissions (Adjust based on your DB user) +-- ---------------------------------------------------------------------------- + +-- Grant permissions to application user (adjust user name as needed) +-- GRANT SELECT, INSERT, UPDATE, DELETE ON user_client_access TO your_app_user; +-- GRANT USAGE, SELECT ON SEQUENCE user_client_access_id_seq TO your_app_user; +-- GRANT SELECT ON v_user_client_access_details TO your_app_user; +-- GRANT SELECT ON v_client_hierarchy TO your_app_user; + +-- ---------------------------------------------------------------------------- +-- VERIFICATION QUERIES +-- ---------------------------------------------------------------------------- + +-- Verify clients table structure +SELECT column_name, data_type, column_default +FROM information_schema.columns +WHERE table_name = 'clients' +ORDER BY ordinal_position; + +-- Verify users table has is_super_admin +SELECT column_name, data_type, column_default +FROM information_schema.columns +WHERE table_name = 'users' AND column_name = 'is_super_admin'; + +-- Verify user_client_access table +SELECT column_name, data_type, column_default +FROM information_schema.columns +WHERE table_name = 'user_client_access' +ORDER BY ordinal_position; + +-- Check indexes +SELECT indexname, tablename, indexdef +FROM pg_indexes +WHERE tablename IN ('clients', 'users', 'user_client_access') +ORDER BY tablename, indexname; + +-- ============================================================================ +-- ROLLBACK SCRIPT (Use with caution!) +-- ============================================================================ + +/* +-- To rollback this migration (WARNING: Will lose data!) + +-- Drop functions +DROP FUNCTION IF EXISTS get_user_accessible_client_ids(INT4); +DROP FUNCTION IF EXISTS is_parent_client(UUID); +DROP FUNCTION IF EXISTS get_sub_client_ids(UUID); +DROP FUNCTION IF EXISTS update_user_client_access_timestamp(); + +-- Drop views +DROP VIEW IF EXISTS v_user_client_access_details; +DROP VIEW IF EXISTS v_client_hierarchy; + +-- Drop table +DROP TABLE IF EXISTS user_client_access; + +-- Remove columns from users +ALTER TABLE users DROP COLUMN IF EXISTS is_super_admin; + +-- Remove columns from clients +ALTER TABLE clients DROP COLUMN IF EXISTS description; +ALTER TABLE clients DROP COLUMN IF EXISTS client_type; +ALTER TABLE clients DROP COLUMN IF EXISTS parent_client_id; +ALTER TABLE clients DROP COLUMN IF EXISTS settings; +ALTER TABLE clients DROP COLUMN IF EXISTS max_users; +ALTER TABLE clients DROP COLUMN IF EXISTS max_storage; + +*/ diff --git a/docs/swagger/docs.go b/docs/swagger/docs.go index fe6ae91..ef8fe8d 100644 --- a/docs/swagger/docs.go +++ b/docs/swagger/docs.go @@ -2865,7 +2865,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/web-medols-be_app_module_article_approval_flows_request.SubmitForApprovalRequest" + "$ref": "#/definitions/netidhub-saas-be_app_module_article_approval_flows_request.SubmitForApprovalRequest" } } ], @@ -7938,7 +7938,7 @@ const docTemplate = `{ "name": "req", "in": "body", "schema": { - "$ref": "#/definitions/web-medols-be_app_module_articles_request.SubmitForApprovalRequest" + "$ref": "#/definitions/netidhub-saas-be_app_module_articles_request.SubmitForApprovalRequest" } } ], @@ -18012,7 +18012,7 @@ const docTemplate = `{ } } }, - "web-medols-be_app_module_article_approval_flows_request.SubmitForApprovalRequest": { + "netidhub-saas-be_app_module_article_approval_flows_request.SubmitForApprovalRequest": { "type": "object", "required": [ "articleId" @@ -18026,7 +18026,7 @@ const docTemplate = `{ } } }, - "web-medols-be_app_module_articles_request.SubmitForApprovalRequest": { + "netidhub-saas-be_app_module_articles_request.SubmitForApprovalRequest": { "type": "object", "properties": { "message": { diff --git a/go.mod b/go.mod index 5ce2af4..847cfc5 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/go-playground/validator/v10 v10.17.0 github.com/gofiber/fiber/v2 v2.52.4 github.com/golang-jwt/jwt/v5 v5.2.1 + github.com/google/uuid v1.6.0 github.com/minio/minio-go/v7 v7.0.68 github.com/pelletier/go-toml/v2 v2.1.1 github.com/rs/zerolog v1.31.0 @@ -34,7 +35,6 @@ require ( github.com/go-openapi/spec v0.20.15 // indirect github.com/go-openapi/swag v0.22.10 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.4.3 // indirect diff --git a/main.go b/main.go index 66361aa..94efe47 100644 --- a/main.go +++ b/main.go @@ -1,45 +1,45 @@ package main import ( + "netidhub-saas-be/app/database" + "netidhub-saas-be/app/middleware" + "netidhub-saas-be/app/module/activity_logs" + "netidhub-saas-be/app/module/advertisement" + "netidhub-saas-be/app/module/approval_workflow_steps" + "netidhub-saas-be/app/module/approval_workflows" + "netidhub-saas-be/app/module/article_approval_flows" + "netidhub-saas-be/app/module/article_approval_step_logs" + "netidhub-saas-be/app/module/article_approvals" + "netidhub-saas-be/app/module/article_categories" + "netidhub-saas-be/app/module/article_category_details" + "netidhub-saas-be/app/module/article_comments" + "netidhub-saas-be/app/module/article_files" + "netidhub-saas-be/app/module/article_nulis_ai" + "netidhub-saas-be/app/module/articles" + "netidhub-saas-be/app/module/bookmarks" + "netidhub-saas-be/app/module/cities" + "netidhub-saas-be/app/module/client_approval_settings" + "netidhub-saas-be/app/module/clients" + "netidhub-saas-be/app/module/custom_static_pages" + "netidhub-saas-be/app/module/districts" + "netidhub-saas-be/app/module/feedbacks" + "netidhub-saas-be/app/module/magazine_files" + "netidhub-saas-be/app/module/magazines" + "netidhub-saas-be/app/module/master_menus" + "netidhub-saas-be/app/module/master_modules" + "netidhub-saas-be/app/module/provinces" + "netidhub-saas-be/app/module/schedules" + "netidhub-saas-be/app/module/subscription" + "netidhub-saas-be/app/module/user_levels" + "netidhub-saas-be/app/module/user_role_accesses" + "netidhub-saas-be/app/module/user_role_level_details" + "netidhub-saas-be/app/module/user_roles" + "netidhub-saas-be/app/module/users" + "netidhub-saas-be/app/router" + "netidhub-saas-be/config/config" + "netidhub-saas-be/config/logger" + "netidhub-saas-be/config/webserver" "time" - "web-medols-be/app/database" - "web-medols-be/app/middleware" - "web-medols-be/app/module/activity_logs" - "web-medols-be/app/module/advertisement" - "web-medols-be/app/module/approval_workflow_steps" - "web-medols-be/app/module/approval_workflows" - "web-medols-be/app/module/article_approval_flows" - "web-medols-be/app/module/article_approval_step_logs" - "web-medols-be/app/module/article_approvals" - "web-medols-be/app/module/article_categories" - "web-medols-be/app/module/article_category_details" - "web-medols-be/app/module/article_comments" - "web-medols-be/app/module/article_files" - "web-medols-be/app/module/article_nulis_ai" - "web-medols-be/app/module/articles" - "web-medols-be/app/module/bookmarks" - "web-medols-be/app/module/cities" - "web-medols-be/app/module/client_approval_settings" - "web-medols-be/app/module/clients" - "web-medols-be/app/module/custom_static_pages" - "web-medols-be/app/module/districts" - "web-medols-be/app/module/feedbacks" - "web-medols-be/app/module/magazine_files" - "web-medols-be/app/module/magazines" - "web-medols-be/app/module/master_menus" - "web-medols-be/app/module/master_modules" - "web-medols-be/app/module/provinces" - "web-medols-be/app/module/schedules" - "web-medols-be/app/module/subscription" - "web-medols-be/app/module/user_levels" - "web-medols-be/app/module/user_role_accesses" - "web-medols-be/app/module/user_role_level_details" - "web-medols-be/app/module/user_roles" - "web-medols-be/app/module/users" - "web-medols-be/app/router" - "web-medols-be/config/config" - "web-medols-be/config/logger" - "web-medols-be/config/webserver" fxzerolog "github.com/efectn/fx-zerolog" "go.uber.org/fx" diff --git a/scripts/test_multi_client.sql b/scripts/test_multi_client.sql new file mode 100644 index 0000000..71abb74 --- /dev/null +++ b/scripts/test_multi_client.sql @@ -0,0 +1,353 @@ +-- ============================================================================ +-- Quick Test Script for Multi-Client Hierarchy +-- Run this after migration to test the new features +-- ============================================================================ + +-- Prerequisites: Database migration already done (tables created) + +-- ============================================================================ +-- STEP 1: Create Super Admin +-- ============================================================================ +UPDATE users +SET is_super_admin = true +WHERE id = 1; -- Ganti dengan ID admin Anda + +SELECT id, username, email, is_super_admin +FROM users +WHERE is_super_admin = true; + +-- ============================================================================ +-- STEP 2: Create Parent Client (Polda Metro) +-- ============================================================================ +DO $$ +DECLARE + v_parent_id UUID; +BEGIN + -- Create parent + INSERT INTO clients (id, name, description, client_type, is_active, created_at, updated_at) + VALUES ( + gen_random_uuid(), + 'Polda Metro Jaya', + 'Parent client untuk wilayah Jakarta', + 'parent_client', + true, + NOW(), + NOW() + ) + RETURNING id INTO v_parent_id; + + RAISE NOTICE 'Parent Client ID: %', v_parent_id; + + -- Store for next steps + CREATE TEMP TABLE IF NOT EXISTS temp_client_ids ( + client_type VARCHAR, + client_id UUID, + client_name VARCHAR + ); + + INSERT INTO temp_client_ids VALUES ('parent', v_parent_id, 'Polda Metro Jaya'); +END $$; + +-- ============================================================================ +-- STEP 3: Create Sub-Clients (Polres) +-- ============================================================================ +DO $$ +DECLARE + v_parent_id UUID; + v_sub1_id UUID; + v_sub2_id UUID; + v_sub3_id UUID; +BEGIN + -- Get parent ID + SELECT client_id INTO v_parent_id + FROM temp_client_ids + WHERE client_type = 'parent'; + + -- Create Polres Jakarta Pusat + INSERT INTO clients (id, name, description, client_type, parent_client_id, max_users, is_active, created_at, updated_at) + VALUES ( + gen_random_uuid(), + 'Polres Jakarta Pusat', + 'Sub-client Jakarta Pusat', + 'sub_client', + v_parent_id, + 100, + true, + NOW(), + NOW() + ) + RETURNING id INTO v_sub1_id; + + -- Create Polres Jakarta Barat + INSERT INTO clients (id, name, description, client_type, parent_client_id, max_users, is_active, created_at, updated_at) + VALUES ( + gen_random_uuid(), + 'Polres Jakarta Barat', + 'Sub-client Jakarta Barat', + 'sub_client', + v_parent_id, + 150, + true, + NOW(), + NOW() + ) + RETURNING id INTO v_sub2_id; + + -- Create Polres Jakarta Selatan + INSERT INTO clients (id, name, description, client_type, parent_client_id, max_users, is_active, created_at, updated_at) + VALUES ( + gen_random_uuid(), + 'Polres Jakarta Selatan', + 'Sub-client Jakarta Selatan', + 'sub_client', + v_parent_id, + 120, + true, + NOW(), + NOW() + ) + RETURNING id INTO v_sub3_id; + + INSERT INTO temp_client_ids VALUES ('sub1', v_sub1_id, 'Polres Jakarta Pusat'); + INSERT INTO temp_client_ids VALUES ('sub2', v_sub2_id, 'Polres Jakarta Barat'); + INSERT INTO temp_client_ids VALUES ('sub3', v_sub3_id, 'Polres Jakarta Selatan'); + + RAISE NOTICE 'Sub-Client 1 ID: %', v_sub1_id; + RAISE NOTICE 'Sub-Client 2 ID: %', v_sub2_id; + RAISE NOTICE 'Sub-Client 3 ID: %', v_sub3_id; +END $$; + +-- ============================================================================ +-- STEP 4: View Client Hierarchy +-- ============================================================================ +SELECT + c.id, + c.name, + c.client_type, + c.parent_client_id, + pc.name as parent_name, + (SELECT COUNT(*) FROM clients WHERE parent_client_id = c.id) as sub_client_count +FROM clients c +LEFT JOIN clients pc ON c.parent_client_id = pc.id +ORDER BY c.client_type, c.name; + +-- ============================================================================ +-- STEP 5: Create Manager User with Multi-Client Access +-- ============================================================================ +DO $$ +DECLARE + v_manager_id INT; + v_parent_id UUID; +BEGIN + -- Create manager user (adjust as needed) + INSERT INTO users ( + username, + email, + fullname, + user_role_id, + user_level_id, + is_super_admin, + is_active, + created_at, + updated_at + ) + VALUES ( + 'regional.manager', + 'manager@example.com', + 'Regional Manager', + 1, -- Adjust role ID + 1, -- Adjust level ID + false, + true, + NOW(), + NOW() + ) + RETURNING id INTO v_manager_id; + + -- Get parent client ID + SELECT client_id INTO v_parent_id + FROM temp_client_ids + WHERE client_type = 'parent'; + + -- Grant access to parent with sub-clients included + INSERT INTO user_client_access ( + user_id, + client_id, + access_type, + can_manage, + can_delegate, + include_sub_clients, + is_active, + created_at, + updated_at + ) + VALUES ( + v_manager_id, + v_parent_id, + 'admin', + true, + true, + true, -- โœจ This gives access to all sub-clients automatically! + true, + NOW(), + NOW() + ); + + RAISE NOTICE 'Manager User ID: %', v_manager_id; + RAISE NOTICE 'Manager has access to parent and ALL sub-clients'; +END $$; + +-- ============================================================================ +-- STEP 6: Create Regular User (Single Client Access) +-- ============================================================================ +DO $$ +DECLARE + v_user_id INT; + v_sub1_id UUID; +BEGIN + -- Get sub-client ID + SELECT client_id INTO v_sub1_id + FROM temp_client_ids + WHERE client_type = 'sub1'; + + -- Create regular user + INSERT INTO users ( + username, + email, + fullname, + user_role_id, + user_level_id, + client_id, -- Primary client + is_super_admin, + is_active, + created_at, + updated_at + ) + VALUES ( + 'regular.user', + 'user@example.com', + 'Regular User', + 2, -- Adjust role ID + 2, -- Adjust level ID + v_sub1_id, + false, + true, + NOW(), + NOW() + ) + RETURNING id INTO v_user_id; + + RAISE NOTICE 'Regular User ID: % (only access to %)', v_user_id, v_sub1_id; +END $$; + +-- ============================================================================ +-- STEP 7: Verify Setup +-- ============================================================================ + +-- Show all clients with hierarchy +SELECT + CASE + WHEN c.parent_client_id IS NULL THEN c.name + ELSE ' โ””โ”€ ' || c.name + END as hierarchy, + c.client_type, + c.max_users, + (SELECT COUNT(*) FROM users WHERE client_id = c.id) as user_count, + c.is_active +FROM clients c +ORDER BY COALESCE(c.parent_client_id, c.id), c.name; + +-- Show user access summary +SELECT + u.id, + u.username, + u.fullname, + u.is_super_admin, + u.client_id as primary_client_id, + c.name as primary_client_name, + ( + SELECT COUNT(*) + FROM user_client_access + WHERE user_id = u.id AND is_active = true + ) as multi_client_access_count +FROM users u +LEFT JOIN clients c ON u.client_id = c.id +WHERE u.is_active = true +ORDER BY u.is_super_admin DESC, u.id; + +-- Show detailed multi-client access +SELECT + u.username, + c.name as client_name, + c.client_type, + uca.access_type, + uca.can_manage, + uca.can_delegate, + uca.include_sub_clients, + CASE + WHEN uca.include_sub_clients = true + THEN (SELECT COUNT(*) FROM clients WHERE parent_client_id = c.id AND is_active = true) + ELSE 0 + END as accessible_sub_clients +FROM user_client_access uca +JOIN users u ON uca.user_id = u.id +JOIN clients c ON uca.client_id = c.id +WHERE uca.is_active = true +ORDER BY u.username, c.name; + +-- ============================================================================ +-- STEP 8: Test Queries +-- ============================================================================ + +-- Test: Get accessible client IDs for manager +-- (This simulates what the application does) +WITH RECURSIVE accessible_clients AS ( + -- Direct access + SELECT uca.client_id, uca.include_sub_clients + FROM user_client_access uca + WHERE uca.user_id = (SELECT id FROM users WHERE username = 'regional.manager' LIMIT 1) + AND uca.is_active = true + + UNION + + -- Sub-clients if include_sub_clients = true + SELECT c.id, false + FROM clients c + INNER JOIN accessible_clients ac ON c.parent_client_id = ac.client_id + WHERE ac.include_sub_clients = true + AND c.is_active = true +) +SELECT + c.id, + c.name, + c.client_type +FROM accessible_clients ac +JOIN clients c ON ac.client_id = c.id +ORDER BY c.client_type, c.name; + +-- ============================================================================ +-- Cleanup (Optional) +-- ============================================================================ +-- DROP TABLE IF EXISTS temp_client_ids; + +-- ============================================================================ +-- NOTES +-- ============================================================================ +/* +After running this script, you should have: + +1. Super Admin user (ID 1) +2. Parent Client: "Polda Metro Jaya" +3. Sub-Clients: + - Polres Jakarta Pusat + - Polres Jakarta Barat + - Polres Jakarta Selatan +4. Manager User with access to ALL clients (via include_sub_clients) +5. Regular User with access to 1 client only + +Next steps: +- Test via API endpoints +- Create articles in different clients +- Test filtering and access control +- Monitor performance +*/ diff --git a/utils/client/client_hierarchy.go b/utils/client/client_hierarchy.go new file mode 100644 index 0000000..7608825 --- /dev/null +++ b/utils/client/client_hierarchy.go @@ -0,0 +1,159 @@ +package client + +import ( + "github.com/google/uuid" + "gorm.io/gorm" + "netidhub-saas-be/app/database/entity" +) + +// GetAccessibleClientIDs returns all client IDs that a user has access to +// This includes: +// - User's primary client +// - Clients granted via UserClientAccess +// - Sub-clients if IncludeSubClients is true +func GetAccessibleClientIDs(db *gorm.DB, userId uint, isSuperAdmin bool) ([]uuid.UUID, error) { + if isSuperAdmin { + // Super admin has access to ALL clients + return nil, nil // nil means no filter (all clients) + } + + var clientIDs []uuid.UUID + + // Get user's primary client + var user entity.Users + if err := db.Select("client_id").Where("id = ?", userId).First(&user).Error; err == nil { + if user.ClientId != nil { + clientIDs = append(clientIDs, *user.ClientId) + } + } + + // Get additional client accesses + var accesses []entity.UserClientAccess + err := db.Where("user_id = ? AND is_active = ?", userId, true). + Preload("Client"). + Find(&accesses).Error + + if err != nil { + return clientIDs, err + } + + for _, access := range accesses { + clientIDs = append(clientIDs, access.ClientId) + + // If IncludeSubClients is true, get all sub-clients + if access.IncludeSubClients != nil && *access.IncludeSubClients { + subClientIDs, err := GetSubClientIDs(db, access.ClientId) + if err == nil { + clientIDs = append(clientIDs, subClientIDs...) + } + } + } + + return removeDuplicateUUIDs(clientIDs), nil +} + +// GetSubClientIDs returns all sub-client IDs for a given parent client (recursive) +func GetSubClientIDs(db *gorm.DB, parentClientId uuid.UUID) ([]uuid.UUID, error) { + var clientIDs []uuid.UUID + var subClients []entity.Clients + + // Get direct children + err := db.Where("parent_client_id = ? AND is_active = ?", parentClientId, true). + Find(&subClients).Error + + if err != nil { + return nil, err + } + + for _, subClient := range subClients { + clientIDs = append(clientIDs, subClient.ID) + + // Recursively get sub-clients of sub-clients + nestedSubClientIDs, err := GetSubClientIDs(db, subClient.ID) + if err == nil { + clientIDs = append(clientIDs, nestedSubClientIDs...) + } + } + + return clientIDs, nil +} + +// GetClientHierarchy returns the full client hierarchy (parent chain and children) +func GetClientHierarchy(db *gorm.DB, clientId uuid.UUID) (*entity.Clients, error) { + var client entity.Clients + + err := db.Preload("ParentClient"). + Preload("SubClients", "is_active = ?", true). + Where("id = ?", clientId). + First(&client).Error + + return &client, err +} + +// HasAccessToClient checks if a user has access to a specific client +func HasAccessToClient(db *gorm.DB, userId uint, clientId uuid.UUID, isSuperAdmin bool) (bool, error) { + if isSuperAdmin { + return true, nil + } + + accessibleClientIDs, err := GetAccessibleClientIDs(db, userId, isSuperAdmin) + if err != nil { + return false, err + } + + // nil means all clients (super admin case) + if accessibleClientIDs == nil { + return true, nil + } + + for _, id := range accessibleClientIDs { + if id == clientId { + return true, nil + } + } + + return false, nil +} + +// GetParentClientID returns the root/parent client ID for a given client +func GetParentClientID(db *gorm.DB, clientId uuid.UUID) (*uuid.UUID, error) { + var client entity.Clients + + err := db.Preload("ParentClient").Where("id = ?", clientId).First(&client).Error + if err != nil { + return nil, err + } + + // If has parent, recursively get the root parent + if client.ParentClientId != nil { + return GetParentClientID(db, *client.ParentClientId) + } + + // This is the root parent + return &client.ID, nil +} + +// IsParentClient checks if a client is a parent client (has sub-clients) +func IsParentClient(db *gorm.DB, clientId uuid.UUID) (bool, error) { + var count int64 + err := db.Model(&entity.Clients{}). + Where("parent_client_id = ? AND is_active = ?", clientId, true). + Count(&count).Error + + return count > 0, err +} + +// removeDuplicateUUIDs removes duplicate UUIDs from a slice +func removeDuplicateUUIDs(uuids []uuid.UUID) []uuid.UUID { + encountered := map[uuid.UUID]bool{} + result := []uuid.UUID{} + + for _, uuid := range uuids { + if !encountered[uuid] { + encountered[uuid] = true + result = append(result, uuid) + } + } + + return result +} diff --git a/utils/middleware/client_utils.go b/utils/middleware/client_utils.go index 866352b..0ec1a3b 100644 --- a/utils/middleware/client_utils.go +++ b/utils/middleware/client_utils.go @@ -4,47 +4,106 @@ import ( "github.com/gofiber/fiber/v2" "github.com/google/uuid" "gorm.io/gorm" - "web-medols-be/app/middleware" + customMiddleware "netidhub-saas-be/app/middleware" ) // AddClientFilter adds client_id filter to GORM query +// Enhanced to support multi-client access and super admin func AddClientFilter(db *gorm.DB, c *fiber.Ctx) *gorm.DB { if c == nil { return db } - clientID := middleware.GetClientID(c) - if clientID != nil { - return db.Where("client_id = ?", clientID) + + // Check if super admin + if customMiddleware.IsSuperAdmin(c) { + return db // No filtering for super admin } - return db + + // Get accessible client IDs + accessibleClientIDs := customMiddleware.GetAccessibleClientIDs(c) + + if accessibleClientIDs == nil { + // Super admin or no restriction + return db + } + + if len(accessibleClientIDs) == 0 { + // User has no client access - return empty result + return db.Where("1 = 0") + } + + if len(accessibleClientIDs) == 1 { + // Single client access (backward compatible) + return db.Where("client_id = ?", accessibleClientIDs[0]) + } + + // Multiple client access + return db.Where("client_id IN ?", accessibleClientIDs) } // SetClientID sets client_id in the given struct if it has a ClientId field +// Uses the current working client ID from context func SetClientID(c *fiber.Ctx, model interface{}) { if c == nil { return } - clientID := middleware.GetClientID(c) + + // Try to get current client ID first (multi-client support) + currentClientID := customMiddleware.GetCurrentClientID(c) + if currentClientID != nil { + if setter, ok := model.(interface{ SetClientID(*uuid.UUID) }); ok { + setter.SetClientID(currentClientID) + } + return + } + + // Fallback to old GetClientID (backward compatibility) + clientID := customMiddleware.GetClientID(c) if clientID != nil { - // Use reflection to set ClientId field if it exists if setter, ok := model.(interface{ SetClientID(*uuid.UUID) }); ok { setter.SetClientID(clientID) } } } -// ValidateClientAccess validates if the current client has access to the resource +// ValidateClientAccess validates if the current user has access to a resource +// Enhanced to check against all accessible clients for multi-client users func ValidateClientAccess(db *gorm.DB, c *fiber.Ctx, tableName string, resourceID interface{}) error { if c == nil { return nil // Skip validation for background jobs } - clientID := middleware.GetClientID(c) - if clientID == nil { - return fiber.NewError(fiber.StatusUnauthorized, "Client not authenticated") + + // Super admin has access to everything + if customMiddleware.IsSuperAdmin(c) { + return nil + } + + accessibleClientIDs := customMiddleware.GetAccessibleClientIDs(c) + if accessibleClientIDs == nil { + // Super admin case (should not reach here, but for safety) + return nil + } + + if len(accessibleClientIDs) == 0 { + return fiber.NewError(fiber.StatusForbidden, "No client access configured") } var count int64 - if err := db.Table(tableName).Where("id = ? AND client_id = ?", resourceID, clientID).Count(&count).Error; err != nil { + var err error + + if len(accessibleClientIDs) == 1 { + // Single client (backward compatible) + err = db.Table(tableName). + Where("id = ? AND client_id = ?", resourceID, accessibleClientIDs[0]). + Count(&count).Error + } else { + // Multiple clients + err = db.Table(tableName). + Where("id = ? AND client_id IN ?", resourceID, accessibleClientIDs). + Count(&count).Error + } + + if err != nil { return err } @@ -54,3 +113,28 @@ func ValidateClientAccess(db *gorm.DB, c *fiber.Ctx, tableName string, resourceI return nil } + +// FilterByCurrentClient filters query by the current working client only +// Different from AddClientFilter - this only filters by the ACTIVE client +func FilterByCurrentClient(db *gorm.DB, c *fiber.Ctx) *gorm.DB { + if c == nil { + return db + } + + // Super admin with no specific client selected + if customMiddleware.IsSuperAdmin(c) { + currentClientID := customMiddleware.GetCurrentClientID(c) + if currentClientID == nil { + return db // No filter + } + return db.Where("client_id = ?", currentClientID) + } + + // Regular user - filter by current client + currentClientID := customMiddleware.GetCurrentClientID(c) + if currentClientID != nil { + return db.Where("client_id = ?", currentClientID) + } + + return db +} diff --git a/utils/response/index.response.go b/utils/response/index.response.go index 7120562..e4a922b 100644 --- a/utils/response/index.response.go +++ b/utils/response/index.response.go @@ -5,8 +5,8 @@ import ( validator "github.com/go-playground/validator/v10" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog/log" + val "netidhub-saas-be/utils/validator" "strings" - val "web-medols-be/utils/validator" ) // Alias for any slice @@ -104,8 +104,8 @@ func Unauthorized() *Response { // ErrorBadRequest returns a bad request error response func ErrorBadRequest(c *fiber.Ctx, message string) error { return c.Status(fiber.StatusBadRequest).JSON(Response{ - Success: false, - Code: 400, + Success: false, + Code: 400, Messages: Messages{message}, }) } diff --git a/utils/service/user_utils.service.go b/utils/service/user_utils.service.go index 09d74d5..e45dd35 100644 --- a/utils/service/user_utils.service.go +++ b/utils/service/user_utils.service.go @@ -3,10 +3,10 @@ package service import ( "github.com/golang-jwt/jwt/v5" "github.com/rs/zerolog" + "netidhub-saas-be/app/database/entity/users" + "netidhub-saas-be/app/module/users/repository" "strings" "time" - "web-medols-be/app/database/entity/users" - "web-medols-be/app/module/users/repository" ) func GetUserInfo(log zerolog.Logger, repo repository.UsersRepository, bearerToken string) *users.Users {