// Package patient handles Patient services // Generated on: 2025-09-07 17:42:51 package patient import ( "api-service/internal/config" models "api-service/internal/models/patient" satusehat "api-service/internal/services/satusehat" "api-service/pkg/logger" "context" "net/http" "strconv" "time" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "github.com/google/uuid" ) // Patient handles Patient services type Patient struct { satusehatService satusehat.SatuSehatService validator *validator.Validate logger logger.Logger config *config.Config } // PatientConfig contains configuration for Patient type PatientConfig struct { Config *config.Config Logger logger.Logger Validator *validator.Validate SatusehatService satusehat.SatuSehatService } // NewPatient creates a new Patient func NewPatient(cfg PatientConfig) *Patient { return &Patient{ satusehatService: cfg.SatusehatService, validator: cfg.Validator, logger: cfg.Logger, config: cfg.Config, } } // CreateBasic creates a new resource // @Summary Create a new resource // @Description Create a new resource in the system // @Tags Patient // @Accept json // @Produce json // @Param Authorization header string true "Bearer token" // @Param request body models.PatientCreateRequest true "Resource creation request" // @Success 201 {object} models.PatientCreateRequest "Resource created successfully" // @Failure 400 {object} models.ErrorResponse "Bad request" // @Failure 401 {object} models.ErrorResponse "Unauthorized" // @Failure 500 {object} models.ErrorResponse "Internal server error" // @Router [post] func (h *Patient) CreateBasic(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() // Generate request ID if not present requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.New().String() c.Header("X-Request-ID", requestID) } h.logger.Info("Processing CreateBasic request", map[string]interface{}{ "request_id": requestID, "endpoint": "", }) // Bind and validate request body var req models.PatientCreateRequest if err := c.ShouldBindJSON(&req); err != nil { h.logger.Error("Failed to bind request body", map[string]interface{}{ "error": err.Error(), "request_id": requestID, }) c.JSON(http.StatusBadRequest, models.ErrorResponse{ Status: "error", Message: "Invalid request body: " + err.Error(), RequestID: requestID, }) return } // Validate request structure if err := h.validator.Struct(&req); err != nil { h.logger.Error("Request validation failed", map[string]interface{}{ "error": err.Error(), "request_id": requestID, }) c.JSON(http.StatusBadRequest, models.ErrorResponse{ Status: "error", Message: "Validation failed: " + err.Error(), RequestID: requestID, }) return } // Call SATUSEHAT service to create patient resp := h.satusehatService.Post(ctx, "/Patient", req, &models.PatientResponse{}) response := models.PatientResponse{ BaseResponse: models.BaseResponse{ Status: "success", Message: "Patient created successfully", RequestID: requestID, Data: resp, }, } h.logger.Info("Successfully created Basic", map[string]interface{}{ "request_id": requestID, }) c.JSON(http.StatusCreated, response) } // GetBasic retrieves a specific resource by ID // @Summary Get a specific resource by ID // @Description Retrieve a specific resource from the system // @Tags Patient // @Accept json // @Produce json // @Param Authorization header string true "Bearer token" // @Param id path string true "Resource ID" // @Success 200 {object} models.PatientResponse "Resource retrieved successfully" // @Failure 400 {object} models.ErrorResponse "Bad request" // @Failure 401 {object} models.ErrorResponse "Unauthorized" // @Failure 404 {object} models.ErrorResponse "Resource not found" // @Failure 500 {object} models.ErrorResponse "Internal server error" // @Router /:id [get] func (h *Patient) GetBasic(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() // Generate request ID if not present requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.New().String() c.Header("X-Request-ID", requestID) } id := c.Param("id") if id == "" { h.logger.Error("Missing required parameter id", map[string]interface{}{ "request_id": requestID, }) c.JSON(http.StatusBadRequest, models.ErrorResponse{ Status: "error", Message: "Missing required parameter id", RequestID: requestID, }) return } h.logger.Info("Processing GetBasic request", map[string]interface{}{ "request_id": requestID, "endpoint": "/:id", "id": id, }) // Call SATUSEHAT service to get patient by ID resp, err := h.satusehatService.GetResourceByID(ctx, "Patient", id) if err != nil { h.logger.Error("Failed to get patient via SATUSEHAT", map[string]interface{}{ "error": err.Error(), "request_id": requestID, "id": id, }) c.JSON(http.StatusInternalServerError, models.ErrorResponse{ Status: "error", Message: "Failed to get patient: " + err.Error(), RequestID: requestID, }) return } response := models.PatientResponse{ BaseResponse: models.BaseResponse{ Status: "success", Message: "Patient retrieved successfully", RequestID: requestID, Data: resp, }, } h.logger.Info("Successfully retrieved Basic", map[string]interface{}{ "request_id": requestID, "id": id, }) c.JSON(http.StatusOK, response) } // UpdateBasic updates an existing resource // @Summary Update an existing resource // @Description Update an existing resource in the system // @Tags Patient // @Accept json // @Produce json // @Param Authorization header string true "Bearer token" // @Param id path string true "Resource ID" // @Param request body models.BasicUpdateRequest true "Resource update request" // @Success 200 {object} models.PatientResponse "Resource updated successfully" // @Failure 400 {object} models.ErrorResponse "Bad request" // @Failure 401 {object} models.ErrorResponse "Unauthorized" // @Failure 404 {object} models.ErrorResponse "Resource not found" // @Failure 500 {object} models.ErrorResponse "Internal server error" // @Router /:id [put] func (h *Patient) UpdateBasic(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() // Generate request ID if not present requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.New().String() c.Header("X-Request-ID", requestID) } id := c.Param("id") if id == "" { h.logger.Error("Missing required parameter id", map[string]interface{}{ "request_id": requestID, }) c.JSON(http.StatusBadRequest, models.ErrorResponse{ Status: "error", Message: "Missing required parameter id", RequestID: requestID, }) return } h.logger.Info("Processing UpdateBasic request", map[string]interface{}{ "request_id": requestID, "endpoint": "/:id", "id": id, }) // Bind and validate request body var req models.PatientUpdateRequest if err := c.ShouldBindJSON(&req); err != nil { h.logger.Error("Failed to bind request body", map[string]interface{}{ "error": err.Error(), "request_id": requestID, }) c.JSON(http.StatusBadRequest, models.ErrorResponse{ Status: "error", Message: "Invalid request body: " + err.Error(), RequestID: requestID, }) return } // Validate request structure if err := h.validator.Struct(&req); err != nil { h.logger.Error("Request validation failed", map[string]interface{}{ "error": err.Error(), "request_id": requestID, }) c.JSON(http.StatusBadRequest, models.ErrorResponse{ Status: "error", Message: "Validation failed: " + err.Error(), RequestID: requestID, }) return } // Call SATUSEHAT service to update patient resp := h.satusehatService.Put(ctx, "/Patient/"+id, req, &models.PatientResponse{}) response := models.PatientResponse{ BaseResponse: models.BaseResponse{ Status: "success", Message: "Patient updated successfully", RequestID: requestID, Data: resp, }, } h.logger.Info("Successfully updated Basic", map[string]interface{}{ "request_id": requestID, "id": id, }) c.JSON(http.StatusOK, response) } func (h *Patient) DeleteBasic(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() // Generate request ID if not present requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.New().String() c.Header("X-Request-ID", requestID) } id := c.Param("id") if id == "" { h.logger.Error("Missing required parameter id", map[string]interface{}{ "request_id": requestID, }) c.JSON(http.StatusBadRequest, models.ErrorResponse{ Status: "error", Message: "Missing required parameter id", RequestID: requestID, }) return } h.logger.Info("Processing DeleteBasic request", map[string]interface{}{ "request_id": requestID, "endpoint": "/:id", "id": id, }) // Call SATUSEHAT service to delete patient err := h.satusehatService.Delete(ctx, "/Patient/"+id, nil) if err != nil { h.logger.Error("Failed to delete patient via SATUSEHAT", map[string]interface{}{ "error": err.Error(), "request_id": requestID, "id": id, }) c.JSON(http.StatusInternalServerError, models.ErrorResponse{ Status: "error", Message: "Failed to delete patient: " + err.Error(), RequestID: requestID, }) return } response := models.SuccessResponse{ Status: "success", Message: "Patient deleted successfully", RequestID: requestID, } h.logger.Info("Successfully deleted Patient", map[string]interface{}{ "request_id": requestID, "id": id, }) c.JSON(http.StatusOK, response) } // SearchBasic searches for resources // @Summary Search for resources // @Description Search for resources in the system // @Tags Patient // @Accept json // @Produce json // @Param Authorization header string true "Bearer token" // @Param query query string false "Search query" // @Param limit query int false "Limit results" default(10) // @Param offset query int false "Offset results" default(0) // @Success 200 {object} models.BasicSearchResponse "Search results" // @Failure 400 {object} models.ErrorResponse "Bad request" // @Failure 401 {object} models.ErrorResponse "Unauthorized" // @Failure 500 {object} models.ErrorResponse "Internal server error" // @Router [get] func (h *Patient) SearchBasic(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() // Generate request ID if not present requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.New().String() c.Header("X-Request-ID", requestID) } // Get query parameters query := c.Query("query") limit := 10 if l := c.Query("limit"); l != "" { if parsed, err := strconv.Atoi(l); err == nil && parsed > 0 { limit = parsed } } offset := 0 if o := c.Query("offset"); o != "" { if parsed, err := strconv.Atoi(o); err == nil && parsed >= 0 { offset = parsed } } h.logger.Info("Processing SearchBasic request", map[string]interface{}{ "request_id": requestID, "endpoint": "", "query": query, "limit": limit, "offset": offset, }) // Build search query for SATUSEHAT endpoint := "/Patient" if query != "" { endpoint += "?name=" + query } if limit > 0 { if query == "" { endpoint += "?" } else { endpoint += "&" } endpoint += "_count=" + strconv.Itoa(limit) } // Call SATUSEHAT service to search patients resp, err := h.satusehatService.GetRawResponse(ctx, endpoint) if err != nil { h.logger.Error("Failed to search patients via SATUSEHAT", map[string]interface{}{ "error": err.Error(), "request_id": requestID, "query": query, }) c.JSON(http.StatusInternalServerError, models.ErrorResponse{ Status: "error", Message: "Failed to search patients: " + err.Error(), RequestID: requestID, }) return } response := models.PatientSearchResponse{ BaseResponse: models.BaseResponse{ Status: "success", Message: "Search completed successfully", RequestID: requestID, Data: resp, }, } h.logger.Info("Successfully completed search", map[string]interface{}{ "request_id": requestID, "query": query, "results": len(response.Data.Results), }) c.JSON(http.StatusOK, response) }