diff --git a/app/module/articles/controller/articles.controller.go b/app/module/articles/controller/articles.controller.go index d4a6498..cc70cb9 100644 --- a/app/module/articles/controller/articles.controller.go +++ b/app/module/articles/controller/articles.controller.go @@ -77,6 +77,7 @@ func (_i *articlesController) All(c *fiber.Ctx) error { IsPublish: c.Query("isPublish"), IsDraft: c.Query("isDraft"), IsBanner: c.Query("isBanner"), + ClientSlug: c.Query("clientSlug"), } req := reqContext.ToParamRequest() req.Pagination = paginate diff --git a/app/module/articles/request/articles.request.go b/app/module/articles/request/articles.request.go index c4dc01f..24871f0 100644 --- a/app/module/articles/request/articles.request.go +++ b/app/module/articles/request/articles.request.go @@ -24,6 +24,7 @@ type ArticlesQueryRequest struct { IsBanner *bool `json:"isBanner"` IsPublish *bool `json:"isPublish"` IsDraft *bool `json:"isDraft"` + ClientSlug *string `json:"clientSlug"` Pagination *paginator.Pagination `json:"pagination"` } @@ -119,6 +120,7 @@ type ArticlesQueryRequestContext struct { IsPublish string `json:"isPublish"` IsDraft string `json:"isDraft"` StatusId string `json:"statusId"` + ClientSlug string `json:"clientSlug"` } func (req ArticlesQueryRequestContext) ToParamRequest() ArticlesQueryRequest { @@ -179,6 +181,9 @@ func (req ArticlesQueryRequestContext) ToParamRequest() ArticlesQueryRequest { request.CreatedById = &createdById } } + if clientSlug := req.ClientSlug; clientSlug != "" { + request.ClientSlug = &clientSlug + } return request } diff --git a/app/module/articles/service/articles.service.go b/app/module/articles/service/articles.service.go index cc3b76d..765f08c 100644 --- a/app/module/articles/service/articles.service.go +++ b/app/module/articles/service/articles.service.go @@ -152,6 +152,19 @@ func (_i *articlesService) All(authToken string, req request.ArticlesQueryReques req.CategoryId = &findCategory.ID } + // Handle clientSlug filter - find client by slug and set clientId + if req.ClientSlug != nil { + findClient, err := _i.ClientsRepo.FindBySlug(*req.ClientSlug) + if err != nil { + _i.Log.Error().Err(err).Str("clientSlug", *req.ClientSlug).Msg("Failed to find client by slug") + return nil, paging, err + } + if findClient != nil { + clientId = &findClient.ID + _i.Log.Info().Str("clientSlug", *req.ClientSlug).Str("clientId", findClient.ID.String()).Msg("Found client by slug") + } + } + results, paging, err := _i.Repo.GetAll(clientId, userLevelId, userId, req) if err != nil { return diff --git a/app/module/clients/clients.module.go b/app/module/clients/clients.module.go index 1e7fd19..312b615 100644 --- a/app/module/clients/clients.module.go +++ b/app/module/clients/clients.module.go @@ -49,6 +49,7 @@ func (_i *ClientsRouter) RegisterClientsRoutes() { // define routes _i.App.Route("/clients", func(router fiber.Router) { router.Get("/", clientsController.All) + router.Get("/public", clientsController.PublicAll) router.Get("/profile", clientsController.ShowWithAuth) router.Get("/check-name/:name", clientsController.CheckClientNameExists) router.Get("/:id", clientsController.Show) diff --git a/app/module/clients/controller/clients.controller.go b/app/module/clients/controller/clients.controller.go index 667513e..d5ee047 100644 --- a/app/module/clients/controller/clients.controller.go +++ b/app/module/clients/controller/clients.controller.go @@ -20,6 +20,7 @@ type clientsController struct { type ClientsController interface { All(c *fiber.Ctx) error + PublicAll(c *fiber.Ctx) error Show(c *fiber.Ctx) error ShowWithAuth(c *fiber.Ctx) error CheckClientNameExists(c *fiber.Ctx) error @@ -113,6 +114,50 @@ func (_i *clientsController) All(c *fiber.Ctx) error { }) } +// PublicAll get all Clients for public consumption +// @Summary Get all Clients (Public) +// @Description API for getting all Clients for public consumption without sensitive data +// @Tags Clients +// @Param req query request.ClientsQueryRequest false "query parameters" +// @Param req query paginator.Pagination false "pagination parameters" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 500 {object} response.InternalServerError +// @Router /clients/public [get] +func (_i *clientsController) PublicAll(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"), + IsActive: c.Query("isActive"), + CreatedById: c.Query("createdById"), + } + req := reqContext.ToParamRequest() + req.Pagination = paginate + + _i.Log.Info().Interface("req", req).Msg("Getting public clients list") + + clientsData, paging, err := _i.clientsService.PublicAll(req) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Public clients list successfully retrieved"}, + Data: clientsData, + Meta: paging, + }) +} + // Show get one Clients // @Summary Get one Clients // @Description API for getting one Clients diff --git a/app/module/clients/mapper/clients.mapper.go b/app/module/clients/mapper/clients.mapper.go index 9f8bb4b..9530317 100644 --- a/app/module/clients/mapper/clients.mapper.go +++ b/app/module/clients/mapper/clients.mapper.go @@ -30,3 +30,21 @@ func ClientsResponseMapper(clientsReq *entity.Clients) (clientsRes *res.ClientsR } return clientsRes } + +func PublicClientsResponseMapper(clientsReq *entity.Clients) (clientsRes *res.PublicClientsResponse) { + if clientsReq != nil { + clientsRes = &res.PublicClientsResponse{ + Name: clientsReq.Name, + Slug: clientsReq.Slug, + Description: clientsReq.Description, + ClientType: clientsReq.ClientType, + LogoUrl: clientsReq.LogoUrl, + Address: clientsReq.Address, + PhoneNumber: clientsReq.PhoneNumber, + Website: clientsReq.Website, + IsActive: clientsReq.IsActive, + CreatedAt: clientsReq.CreatedAt, + } + } + return clientsRes +} diff --git a/app/module/clients/repository/clients.repository.go b/app/module/clients/repository/clients.repository.go index b9b087a..3b7e264 100644 --- a/app/module/clients/repository/clients.repository.go +++ b/app/module/clients/repository/clients.repository.go @@ -25,6 +25,7 @@ type ClientsRepository interface { FindOne(id uuid.UUID) (clients *entity.Clients, err error) FindOneByClientId(clientId *uuid.UUID) (clients *entity.Clients, err error) FindByName(name string) (clients *entity.Clients, err error) + FindBySlug(slug string) (clients *entity.Clients, err error) FindByImagePathName(name string) (clients *entity.Clients, err error) Create(clients *entity.Clients) (clientsReturn *entity.Clients, err error) Update(id uuid.UUID, clients *entity.Clients) (err error) @@ -160,6 +161,14 @@ func (_i *clientsRepository) FindByName(name string) (clients *entity.Clients, e return clients, nil } +func (_i *clientsRepository) FindBySlug(slug string) (clients *entity.Clients, err error) { + if err := _i.DB.DB.Where("slug = ?", slug).First(&clients).Error; err != nil { + return nil, err + } + + return clients, nil +} + func (_i *clientsRepository) FindByImagePathName(name string) (clients *entity.Clients, err error) { if err := _i.DB.DB.Where("logo_image_path like ?", "%"+name+"%").First(&clients).Error; err != nil { return nil, err diff --git a/app/module/clients/response/clients.response.go b/app/module/clients/response/clients.response.go index d989ccd..4090d7b 100644 --- a/app/module/clients/response/clients.response.go +++ b/app/module/clients/response/clients.response.go @@ -10,6 +10,23 @@ import ( // RESPONSE STRUCTS - Updated for Multi-Client Hierarchy Support (camelCase) // ======================================================================== +// PublicClientsResponse for public consumption without sensitive data +type PublicClientsResponse struct { + Name string `json:"name"` + Slug string `json:"slug"` + Description *string `json:"description"` + ClientType string `json:"clientType"` + + // Additional tenant information fields + LogoUrl *string `json:"logoUrl"` // Logo tenant URL + Address *string `json:"address"` // Alamat + PhoneNumber *string `json:"phoneNumber"` // Nomor telepon + Website *string `json:"website"` // Website resmi + + IsActive *bool `json:"isActive"` + CreatedAt time.Time `json:"createdAt"` +} + // ClientResponse for single client with hierarchy info type ClientsResponse struct { ID uuid.UUID `json:"id"` diff --git a/app/module/clients/service/clients.service.go b/app/module/clients/service/clients.service.go index 07c8cd2..64ba837 100644 --- a/app/module/clients/service/clients.service.go +++ b/app/module/clients/service/clients.service.go @@ -36,6 +36,7 @@ type clientsService struct { // ClientsService define interface of IClientsService type ClientsService interface { All(authToken string, req request.ClientsQueryRequest) (clients []*response.ClientsResponse, paging paginator.Pagination, err error) + PublicAll(req request.ClientsQueryRequest) (clients []*response.PublicClientsResponse, paging paginator.Pagination, err error) Show(id uuid.UUID) (clients *response.ClientsResponse, err error) CheckClientNameExists(name string) (exists bool, err error) ShowWithAuth(authToken string) (clients *response.ClientsResponse, err error) @@ -98,6 +99,26 @@ func (_i *clientsService) All(authToken string, req request.ClientsQueryRequest) return } +func (_i *clientsService) PublicAll(req request.ClientsQueryRequest) (clientss []*response.PublicClientsResponse, paging paginator.Pagination, err error) { + _i.Log.Info().Interface("data", req).Msg("Getting public clients list") + + // Only return active clients for public consumption + isActive := true + req.IsActive = &isActive + + results, paging, err := _i.Repo.GetAll(req) + if err != nil { + return + } + + for _, result := range results { + clientss = append(clientss, mapper.PublicClientsResponseMapper(result)) + } + + _i.Log.Info().Int("count", len(clientss)).Msg("Public clients retrieved successfully") + return +} + func (_i *clientsService) Show(id uuid.UUID) (clients *response.ClientsResponse, err error) { result, err := _i.Repo.FindOne(id) if err != nil { diff --git a/docs/swagger/docs.go b/docs/swagger/docs.go index 07c66a4..f87810c 100644 --- a/docs/swagger/docs.go +++ b/docs/swagger/docs.go @@ -7005,6 +7005,11 @@ const docTemplate = `{ "name": "categoryId", "in": "query" }, + { + "type": "string", + "name": "clientSlug", + "in": "query" + }, { "type": "integer", "name": "createdById", @@ -9931,6 +9936,123 @@ const docTemplate = `{ } } }, + "/clients/public": { + "get": { + "description": "API for getting all Clients for public consumption without sensitive data", + "tags": [ + "Clients" + ], + "summary": "Get all Clients (Public)", + "parameters": [ + { + "enum": [ + "parent_client", + "sub_client", + "standalone" + ], + "type": "string", + "name": "clientType", + "in": "query" + }, + { + "type": "boolean", + "description": "Include all descendants", + "name": "includeSubClients", + "in": "query" + }, + { + "type": "boolean", + "description": "Status filter", + "name": "isActive", + "in": "query" + }, + { + "type": "string", + "description": "Search filters", + "name": "name", + "in": "query" + }, + { + "type": "boolean", + "description": "Only clients with children", + "name": "onlyParentClients", + "in": "query" + }, + { + "type": "boolean", + "description": "Only standalone clients", + "name": "onlyStandalone", + "in": "query" + }, + { + "type": "string", + "description": "Hierarchy filters", + "name": "parentClientId", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/clients/update": { "put": { "security": [ diff --git a/docs/swagger/swagger.json b/docs/swagger/swagger.json index 38c0cb8..31c8633 100644 --- a/docs/swagger/swagger.json +++ b/docs/swagger/swagger.json @@ -6994,6 +6994,11 @@ "name": "categoryId", "in": "query" }, + { + "type": "string", + "name": "clientSlug", + "in": "query" + }, { "type": "integer", "name": "createdById", @@ -9920,6 +9925,123 @@ } } }, + "/clients/public": { + "get": { + "description": "API for getting all Clients for public consumption without sensitive data", + "tags": [ + "Clients" + ], + "summary": "Get all Clients (Public)", + "parameters": [ + { + "enum": [ + "parent_client", + "sub_client", + "standalone" + ], + "type": "string", + "name": "clientType", + "in": "query" + }, + { + "type": "boolean", + "description": "Include all descendants", + "name": "includeSubClients", + "in": "query" + }, + { + "type": "boolean", + "description": "Status filter", + "name": "isActive", + "in": "query" + }, + { + "type": "string", + "description": "Search filters", + "name": "name", + "in": "query" + }, + { + "type": "boolean", + "description": "Only clients with children", + "name": "onlyParentClients", + "in": "query" + }, + { + "type": "boolean", + "description": "Only standalone clients", + "name": "onlyStandalone", + "in": "query" + }, + { + "type": "string", + "description": "Hierarchy filters", + "name": "parentClientId", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/clients/update": { "put": { "security": [ diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index 97cce64..0830d82 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -6157,6 +6157,9 @@ paths: - in: query name: categoryId type: integer + - in: query + name: clientSlug + type: string - in: query name: createdById type: integer @@ -8362,6 +8365,82 @@ paths: summary: Get Clients detail with auth token tags: - Clients + /clients/public: + get: + description: API for getting all Clients for public consumption without sensitive + data + parameters: + - enum: + - parent_client + - sub_client + - standalone + in: query + name: clientType + type: string + - description: Include all descendants + in: query + name: includeSubClients + type: boolean + - description: Status filter + in: query + name: isActive + type: boolean + - description: Search filters + in: query + name: name + type: string + - description: Only clients with children + in: query + name: onlyParentClients + type: boolean + - description: Only standalone clients + in: query + name: onlyStandalone + type: boolean + - description: Hierarchy filters + in: query + name: parentClientId + type: string + - in: query + name: count + type: integer + - in: query + name: limit + type: integer + - in: query + name: nextPage + type: integer + - in: query + name: page + type: integer + - in: query + name: previousPage + type: integer + - in: query + name: sort + type: string + - in: query + name: sortBy + type: string + - in: query + name: totalPage + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + summary: Get all Clients (Public) + tags: + - Clients /clients/update: put: description: API for update Clients using client ID from auth token diff --git a/netidhub-saas-be.exe b/netidhub-saas-be.exe index 88e8fc7..6748efc 100644 Binary files a/netidhub-saas-be.exe and b/netidhub-saas-be.exe differ