diff --git a/adapter b/adapter deleted file mode 100644 index 4523da46..00000000 --- a/adapter +++ /dev/null @@ -1,187 +0,0 @@ -package services - -import ( - "context" - "fmt" - - "api-service/internal/models/reference" -) - -// VClaimAdapter adapts the generic VClaimService to implement the reference.VClaimService interface -type VClaimAdapter struct { - service VClaimService -} - -// NewVClaimAdapter creates a new VClaimAdapter -func NewVClaimAdapter(service VClaimService) *VClaimAdapter { - return &VClaimAdapter{ - service: service, - } -} - -// Get implements VClaimService.Get -func (a *VClaimAdapter) Get(ctx context.Context, endpoint string, result interface{}) error { - return a.service.Get(ctx, endpoint, result) -} - -// Post implements VClaimService.Post -func (a *VClaimAdapter) Post(ctx context.Context, endpoint string, payload interface{}, result interface{}) error { - return a.service.Post(ctx, endpoint, payload, result) -} - -// Put implements VClaimService.Put -func (a *VClaimAdapter) Put(ctx context.Context, endpoint string, payload interface{}, result interface{}) error { - return a.service.Put(ctx, endpoint, payload, result) -} - -// Delete implements VClaimService.Delete -func (a *VClaimAdapter) Delete(ctx context.Context, endpoint string, result interface{}) error { - return a.service.Delete(ctx, endpoint, result) -} - -// GetRawResponse implements VClaimService.GetRawResponse -func (a *VClaimAdapter) GetRawResponse(ctx context.Context, endpoint string) (*ResponDTOVclaim, error) { - return a.service.GetRawResponse(ctx, endpoint) -} - -// PostRawResponse implements VClaimService.PostRawResponse -func (a *VClaimAdapter) PostRawResponse(ctx context.Context, endpoint string, payload interface{}) (*ResponDTOVclaim, error) { - return a.service.PostRawResponse(ctx, endpoint, payload) -} - -// GetPeserta implements reference.VClaimService.GetPeserta -func (a *VClaimAdapter) GetPeserta(ctx context.Context, noKartu string) (*reference.PesertaData, error) { - var response struct { - MetaData struct { - Code string `json:"code"` - Message string `json:"message"` - } `json:"metaData"` - Response reference.PesertaData `json:"response"` - } - - endpoint := fmt.Sprintf("/Peserta/%s", noKartu) - err := a.service.Get(ctx, endpoint, &response) - if err != nil { - return nil, err - } - - if response.MetaData.Code != "200" { - return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message) - } - - return &response.Response, nil -} - -// GetSEP implements reference.VClaimService.GetSEP -func (a *VClaimAdapter) GetSEP(ctx context.Context, noSep string) (*reference.SEPData, error) { - var response struct { - MetaData struct { - Code string `json:"code"` - Message string `json:"message"` - } `json:"metaData"` - Response reference.SEPData `json:"response"` - } - - endpoint := fmt.Sprintf("/SEP/%s", noSep) - err := a.service.Get(ctx, endpoint, &response) - if err != nil { - return nil, err - } - - if response.MetaData.Code != "200" { - return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message) - } - - return &response.Response, nil -} - -// CreateSEP implements reference.VClaimService.CreateSEP -func (a *VClaimAdapter) CreateSEP(ctx context.Context, req *reference.SEPRequest) (*reference.SEPData, error) { - var response struct { - MetaData struct { - Code string `json:"code"` - Message string `json:"message"` - } `json:"metaData"` - Response reference.SEPData `json:"response"` - } - - endpoint := "/SEP/2.0/insert" - err := a.service.Post(ctx, endpoint, req, &response) - if err != nil { - return nil, err - } - - if response.MetaData.Code != "200" { - return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message) - } - - return &response.Response, nil -} - -// UpdateSEP implements reference.VClaimService.UpdateSEP -func (a *VClaimAdapter) UpdateSEP(ctx context.Context, noSep string, req *reference.SEPRequest) (*reference.SEPData, error) { - var response struct { - MetaData struct { - Code string `json:"code"` - Message string `json:"message"` - } `json:"metaData"` - Response reference.SEPData `json:"response"` - } - - endpoint := fmt.Sprintf("/SEP/%s", noSep) - err := a.service.Put(ctx, endpoint, req, &response) - if err != nil { - return nil, err - } - - if response.MetaData.Code != "200" { - return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message) - } - - return &response.Response, nil -} - -// DeleteSEP implements reference.VClaimService.DeleteSEP -func (a *VClaimAdapter) DeleteSEP(ctx context.Context, noSep string) error { - var response struct { - MetaData struct { - Code string `json:"code"` - Message string `json:"message"` - } `json:"metaData"` - } - - endpoint := fmt.Sprintf("/SEP/%s", noSep) - err := a.service.Delete(ctx, endpoint, &response) - if err != nil { - return err - } - - if response.MetaData.Code != "200" { - return fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message) - } - - return nil -} - -// GetRujukan implements reference.VClaimService.GetRujukan -func (a *VClaimAdapter) GetRujukan(ctx context.Context, noRujukan string) (*reference.RujukanData, error) { - var response struct { - MetaData struct { - Code string `json:"code"` - Message string `json:"message"` - } `json:"metaData"` - Response reference.RujukanData `json:"response"` - } - - endpoint := fmt.Sprintf("/Rujukan/%s", noRujukan) - err := a.service.Get(ctx, endpoint, &response) - if err != nil { - return nil, err - } - - if response.MetaData.Code != "200" { - return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message) - } - - return &response.Response, nil -} diff --git a/api-service b/api-service deleted file mode 100644 index 6a4f638b..00000000 Binary files a/api-service and /dev/null differ diff --git a/docs/docs.go b/docs/docs.go index 85e298ca..12f27b3d 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1636,6 +1636,9 @@ const docTemplate = `{ } } }, + "raw_response": { + "type": "string" + }, "sex": { "type": "string" }, diff --git a/docs/swagger.json b/docs/swagger.json index 4636193f..47b3b1cc 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1634,6 +1634,9 @@ } } }, + "raw_response": { + "type": "string" + }, "sex": { "type": "string" }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 596dcf7d..84640d0c 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -173,6 +173,8 @@ definitions: nmProvider: type: string type: object + raw_response: + type: string sex: type: string statusPeserta: diff --git a/docs/websocket.md b/docs/websocket.md deleted file mode 100644 index c79a5db1..00000000 --- a/docs/websocket.md +++ /dev/null @@ -1,83 +0,0 @@ -# WebSocket Server and Nuxt 3 Client Documentation - -## Overview - -This document describes the WebSocket server implementation in the Go API service and how to use the Nuxt 3 client example to connect and interact with the WebSocket server. - ---- - -## WebSocket Server - -- Implemented using Gorilla WebSocket and Gin framework. -- Located at `internal/handlers/websocket/websocket.go`. -- WebSocket endpoint is registered at `/api/v1/ws`. -- Supports client connections with optional `user_id` and `room` query parameters. -- Supports broadcasting messages to all clients, specific rooms, or individual clients. -- Includes heartbeat and simulated data stream features for demonstration. - -### Server Usage - -- Connect to the WebSocket endpoint: `ws:///api/v1/ws?user_id=&room=` -- Messages are JSON objects with the following structure: - -```json -{ - "type": "message_type", - "data": { ... }, - "timestamp": "ISO8601 timestamp", - "client_id": "optional client id" -} -``` - -- The server broadcasts messages to all clients or specific rooms based on message type and data. - ---- - -## Nuxt 3 WebSocket Client Example - -- Located in `examples/nuxt3-websocket-client/`. -- Connects to the WebSocket server using the URL configured in `nuxt.config.ts` (`public.websocketUrl`). -- Uses a Vue composable `useWebSocket` to manage connection, messages, and sending. -- UI allows sending messages and displays received messages. - -### Running the Nuxt 3 Client - -1. Navigate to the client directory: - -```bash -cd examples/nuxt3-websocket-client -``` - -2. Install dependencies: - -```bash -npm install -``` - -3. Run the development server: - -```bash -npm run dev -``` - -4. Open the browser at `http://localhost:3000` (or the port shown in the terminal). - -5. The client will connect to the WebSocket server and display connection status and messages. - -### Configuration - -- The WebSocket URL can be configured via environment variable `WEBSOCKET_URL` or defaults to `ws://localhost:8080/api/v1/ws`. - ---- - -## Notes - -- Ensure the Go API server is running and accessible at the configured WebSocket URL. -- The WebSocket server allows cross-origin connections for development; adjust origin checks for production. -- The client example uses Tailwind CSS for styling. - ---- - -## Summary - -This setup provides a full WebSocket server in Go with a modern Nuxt 3 client example demonstrating real-time communication. Use this as a foundation for building real-time features in your applications. diff --git a/handler.tmpl b/handler.tmpl deleted file mode 100644 index 94a8a915..00000000 --- a/handler.tmpl +++ /dev/null @@ -1,163 +0,0 @@ -// Code generated by genhandler; DO NOT EDIT. - -package handlers - -import ( - "context" - "net/http" - "time" - "{{.ModuleName}}/internal/models/reference" - "github.com/gin-gonic/gin" - "github.com/google/uuid" -) - -/* ===== HANDLER STRUCT & CONSTRUCTOR ===== */ -type {{.ServiceName}}Handler struct { - svc reference.{{.ServiceName}}Service - timeout time.Duration -} - -func New{{.ServiceName}}Handler(svc reference.{{.ServiceName}}Service) *{{.ServiceName}}Handler { - return &{{.ServiceName}}Handler{ - svc: svc, - timeout: time.Duration({{.Timeout}}) * time.Second, - } -} - -/* ===== ENDPOINTS ===== */ -{{range .Endpoints}} -{{/* ---------- GET ---------- */}} -{{if .HasGet}} -{{if $.HasSwagger}} -// @Summary {{.Summary}} -// @Description {{.Description}} -// @Tags {{ join .Tags "," }} -// @Accept json -// @Produce json -{{range .PathParams}} -// @Param {{.}} path string true "{{.}}" -{{end}} -{{if .RequireAuth}} -// @Security ApiKeyAuth -{{end}} -// @Success 200 {object} reference.{{.ResponseModel}} -// @Failure 400 {object} reference.ErrorResponse -// @Failure 500 {object} reference.ErrorResponse -// @Router {{.GetPath}} [get] -{{end}} -func (h *{{$.ServiceName}}Handler) Get{{.NameCamel}}(c *gin.Context) { - // ... (isi fungsi handler) -} -{{end}} -{{/* ---------- POST ---------- */}} -{{if .HasPost}} -{{if $.HasSwagger}} -// @Summary {{.Summary}} -// @Description {{.Description}} -// @Tags {{ join .Tags "," }} -// @Accept json -// @Produce json -{{if .RequireAuth}} -// @Security ApiKeyAuth -{{end}} -// @Param request body reference.{{.Model}} true "{{.Name}} data" -// @Success 201 {object} reference.{{.ResponseModel}} -// @Failure 400 {object} reference.ErrorResponse -// @Failure 500 {object} reference.ErrorResponse -// @Router {{.PostPath}} [post] -{{end}} -func (h *{{$.ServiceName}}Handler) Create{{.NameCamel}}(c *gin.Context) { - // ... (isi fungsi handler) -} -{{end}} -{{/* ---------- PUT ---------- */}} -{{if .HasPut}} -{{if $.HasSwagger}} -// @Summary Update {{.Name}} -// @Description {{.Description}} -// @Tags {{ join .Tags "," }} -// @Accept json -// @Produce json -{{range .PathParams}} -// @Param {{.}} path string true "{{.}}" -{{end}} -{{if .RequireAuth}} -// @Security ApiKeyAuth -{{end}} -// @Param request body reference.{{.Model}} true "{{.Name}} data" -// @Success 200 {object} reference.{{.ResponseModel}} -// @Failure 400 {object} reference.ErrorResponse -// @Failure 500 {object} reference.ErrorResponse -// @Router {{.PutPath}} [put] -{{end}} -func (h *{{$.ServiceName}}Handler) Update{{.NameCamel}}(c *gin.Context) { - // ... (isi fungsi handler) -} -{{end}} -{{/* ---------- PATCH ---------- */}} -{{if .HasPatch}} -{{if $.HasSwagger}} -// @Summary Patch {{.Name}} -// @Description {{.Description}} -// @Tags {{ join .Tags "," }} -// @Accept json -// @Produce json -{{range .PathParams}} -// @Param {{.}} path string true "{{.}}" -{{end}} -{{if .RequireAuth}} -// @Security ApiKeyAuth -{{end}} -// @Param request body reference.{{.Model}} true "Partial {{.Name}} data" -// @Success 200 {object} reference.{{.ResponseModel}} -// @Failure 400 {object} reference.ErrorResponse -// @Failure 500 {object} reference.ErrorResponse -// @Router {{.PatchPath}} [patch] -{{end}} -func (h *{{$.ServiceName}}Handler) Patch{{.NameCamel}}(c *gin.Context) { - // ... (isi fungsi handler) -} -{{end}} -{{/* ---------- DELETE ---------- */}} -{{if .HasDelete}} -{{if $.HasSwagger}} -// @Summary Delete {{.Name}} -// @Description {{.Description}} -// @Tags {{ join .Tags "," }} -// @Accept json -// @Produce json -{{range .PathParams}} -// @Param {{.}} path string true "{{.}}" -{{end}} -{{if .RequireAuth}} -// @Security ApiKeyAuth -{{end}} -// @Success 204 {object} nil -// @Failure 400 {object} reference.ErrorResponse -// @Failure 500 {object} reference.ErrorResponse -// @Router {{.DeletePath}} [delete] -{{end}} -func (h *{{$.ServiceName}}Handler) Delete{{.NameCamel}}(c *gin.Context) { - // ... (isi fungsi handler) -} -{{end}} -{{end}} - - -/* ===== HELPER FUNCTIONS ===== */ -func getOrSetRequestID(c *gin.Context) string { - id := c.GetHeader("X-Request-ID") - if id == "" { - id = uuid.New().String() - c.Header("X-Request-ID", id) - } - return id -} - -func errorJSON(c *gin.Context, code int, reqID string, err error) { - c.JSON(code, gin.H{ - "status": "error", - "message": err.Error(), - "request_id": reqID, - }) -} diff --git a/internal/handlers/patient/patient.go b/internal/handlers/patient/patient.go deleted file mode 100644 index c4d24787..00000000 --- a/internal/handlers/patient/patient.go +++ /dev/null @@ -1,466 +0,0 @@ -// 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) -} diff --git a/internal/models/patient/patient.go b/internal/models/patient/patient.go deleted file mode 100644 index 0ad8ad79..00000000 --- a/internal/models/patient/patient.go +++ /dev/null @@ -1,105 +0,0 @@ -package models - -import ( - "time" - "github.com/go-playground/validator/v10" -) - -// BaseRequest contains common fields for all requests -type BaseRequest struct { - RequestID string `json:"request_id,omitempty"` - Timestamp time.Time `json:"timestamp,omitempty"` -} - -// BaseResponse contains common fields for all responses -type BaseResponse struct { - Status string `json:"status"` - Message string `json:"message"` - Data interface{} `json:"data,omitempty"` - RequestID string `json:"request_id,omitempty"` -} - -// ErrorResponse represents an error response -type ErrorResponse struct { - Status string `json:"status"` - Message string `json:"message"` - RequestID string `json:"request_id,omitempty"` -} - -// SuccessResponse represents a success response -type SuccessResponse struct { - Status string `json:"status"` - Message string `json:"message"` - RequestID string `json:"request_id,omitempty"` -} - -// SearchData contains search results -type SearchData struct { - Results []interface{} `json:"results"` - Total int `json:"total"` - Limit int `json:"limit"` - Offset int `json:"offset"` -} - -// Patient Models -// Generated at: 2025-09-07 17:42:51 - -// PatientCreateRequest represents a request to create a Patient -type PatientCreateRequest struct { - BaseRequest - // Add fields specific to Patient creation - Name string `json:"name" validate:"required"` - Description string `json:"description" validate:"omitempty"` -} - -// PatientUpdateRequest represents a request to update a Patient -type PatientUpdateRequest struct { - BaseRequest - ID string `json:"id" validate:"required,uuid"` - Name string `json:"name" validate:"required"` - Description string `json:"description" validate:"omitempty"` -} - -// PatientResponse represents a response for Patient operations -type PatientResponse struct { - BaseResponse -} - -// PatientSearchResponse represents a response for Patient search -type PatientSearchResponse struct { - BaseResponse - Data SearchData `json:"data"` -} - -// PatientData represents the data structure for Patient -type PatientData struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at,omitempty"` -} - -// Validate validates the PatientCreateRequest -func (r *PatientCreateRequest) Validate() error { - validate := validator.New() - return validate.Struct(r) -} - -// Validate validates the PatientUpdateRequest -func (r *PatientUpdateRequest) Validate() error { - validate := validator.New() - return validate.Struct(r) -} - -// NewPatientData creates a new PatientData with default values -func NewPatientData(name, description string) *PatientData { - now := time.Now() - return &PatientData{ - ID: "", // Will be set by the database - Name: name, - Description: description, - CreatedAt: now, - UpdatedAt: now, - } -} \ No newline at end of file diff --git a/services-config-bpjs.yamlcopy.backup b/services-config-bpjs.yamlcopy.backup deleted file mode 100644 index e6809f61..00000000 --- a/services-config-bpjs.yamlcopy.backup +++ /dev/null @@ -1,61 +0,0 @@ -# services-config-simple.yaml -global: - module_name: "api-service" - output_dir: "internal/handlers" - enable_swagger: true - enable_logging: true - -services: - vclaim: - name: "VClaim" - category: "vclaim" - package: "vclaim" - description: "BPJS VClaim service for eligibility and SEP management" - base_url: "https://apijkn.bpjs-kesehatan.go.id/vclaim-rest" - timeout: 30 - retry_count: 3 - endpoints: - peserta: - methods: ["GET"] - get_path: "/peserta/:nokartu" - model: "PesertaRequest" - response_model: "PesertaResponse" - description: "Get participant eligibility information" - summary: "Get Participant Info" - tags: ["vclaim", "peserta"] - cache_enabled: true - cache_ttl: 300 - sep: - methods: ["GET", "POST", "PUT", "DELETE"] - get_path: "/sep/:nosep" - post_path: "/sep" - put_path: "/sep/:nosep" - delete_path: "/sep/:nosep" - model: "SepRequest" - response_model: "SepResponse" - description: "Manage SEP (Surat Eligibilitas Peserta)" - summary: "SEP Management" - tags: ["vclaim", "sep"] - cache_enabled: true - cache_ttl: 180 - - eclaim: - name: "EClaim" - category: "eclaim" - package: "eclaim" - description: "BPJS EClaim service for claim processing" - base_url: "https://apijkn.bpjs-kesehatan.go.id/new-eclaim-rest" - timeout: 60 - retry_count: 2 - endpoints: - klaim: - methods: ["GET", "POST", "PUT"] - get_path: "/klaim/:noklaim" - post_path: "/klaim" - put_path: "/klaim/:noklaim" - model: "KlaimRequest" - response_model: "KlaimResponse" - description: "Manage insurance claims" - summary: "Claim Management" - tags: ["eclaim", "klaim"] - cache_enabled: false diff --git a/services-config-old.yaml b/services-config-old.yaml deleted file mode 100644 index ff692189..00000000 --- a/services-config-old.yaml +++ /dev/null @@ -1,76 +0,0 @@ -# BPJS Services Configuration -global: - module_name: "api-service" - output_dir: "internal/handlers" - enable_swagger: true - enable_logging: true - -services: - vclaim: - name: "VClaim" - category: "vclaim" - package: "vclaim" - description: "BPJS VClaim service for eligibility and SEP management" - base_url: "https://apijkn.bpjs-kesehatan.go.id/vclaim-rest" - timeout: 30 - retry_count: 3 - endpoints: - peserta: # file .go handler file dan directori folder name - bynokartu: #fuction - methods: ["GET"] - get_path: "/peserta/:nokartu" - model: "PesertaRequest" - response_model: "PesertaResponse" - description: "Get participant eligibility information by card number" - summary: "Get Participant Info by No Kartu" - tags: ["Peserta"] - require_auth: true - cache_enabled: true - cache_ttl: 300 - bynik: #fuction - methods: ["GET"] - get_path: "/peserta/nik/:nik" - model: "PesertaRequest" - response_model: "PesertaResponse" - description: "Get participant eligibility information by NIK" - summary: "Get Participant Info by NIK" - tags: ["Peserta"] - require_auth: true - cache_enabled: true - cache_ttl: 300 - rujukan: # directori folder name - rujukan: # file .go handler file - methods: ["POST,PUT, DELETE"] - post_path: "/Rujukan" - model: "RujukanRequest" - response_model: "RujukanResponse" - description: "Manage rujukan" - summary: "Rujukan Management" - tags: ["Rujukan"] - require_auth: true - cache_enabled: true - cache_ttl: 180 - search: # file .go handler file - bynorujukan: #fuction - methods: ["GET"] - get_path: "/Rujukan/:norujukan" - model: "RujukanRequest" - response_model: "RujukanResponse" - description: "Manage rujukan" - summary: "Rujukan Management" - tags: ["Rujukan"] - require_auth: true - cache_enabled: true - cache_ttl: 300 - bynokartu: #fuction - methods: ["GET"] - get_path: "/Rujukan/:nokartu" - model: "RujukanRequest" - response_model: "RujukanResponse" - description: "Manage rujukan" - summary: "Rujukan Management" - tags: ["Rujukan"] - require_auth: true - cache_enabled: true - cache_ttl: 300 - \ No newline at end of file diff --git a/test b/test deleted file mode 100644 index ad0ee5ee..00000000 --- a/test +++ /dev/null @@ -1,149 +0,0 @@ -# services-config-complete.yaml -global: - module_name: "api-service" - output_dir: "internal/handlers" - package_prefix: "api-service" - enable_swagger: true - enable_logging: true - enable_metrics: true - -services: - vclaim: - name: "VClaim" - category: "vclaim" - package: "vclaim" - description: "BPJS VClaim service for eligibility and SEP management" - base_url: "https://apijkn.bpjs-kesehatan.go.id/vclaim-rest" - timeout: 30 - retry_count: 3 - middleware: - - "RequestLogger" - - "ResponseLogger" - - "RateLimiter" - dependencies: - - "database" - - "redis" - endpoints: - peserta: - methods: ["GET"] - get_path: "/Peserta/:nokartu" - model: "PesertaRequest" - response_model: "PesertaResponse" - description: "Get participant eligibility information" - summary: "Get Participant Info" - tags: ["vclaim", "peserta"] - require_auth: true - rate_limit: 100 - cache_enabled: true - cache_ttl: 300 - sep: - methods: ["GET", "POST", "PUT", "DELETE"] - get_path: "/SEP/:nosep" - post_path: "/sep" - put_path: "/sep/:nosep" - delete_path: "/sep/:nosep" - model: "SEPRequest" - response_model: "SEPResponse" - description: "Manage SEP (Surat Eligibilitas Peserta)" - summary: "SEP Management" - tags: ["vclaim", "sep"] - require_auth: true - rate_limit: 50 - cache_enabled: true - cache_ttl: 180 - custom_headers: - X-Service: "VClaim" - X-Version: "2.0" - rujukan: - methods: ["GET"] - get_path: "/rujukan/:norujukan" - model: "RujukanRequest" - response_model: "RujukanResponse" - description: "Get referral information" - summary: "Get Referral Info" - tags: ["vclaim", "rujukan"] - require_auth: true - rate_limit: 100 - cache_enabled: true - cache_ttl: 600 - - eclaim: - name: "EClaim" - category: "eclaim" - package: "eclaim" - description: "BPJS EClaim service for claim processing and grouper" - base_url: "https://apijkn.bpjs-kesehatan.go.id/new-eclaim-rest" - timeout: 60 - retry_count: 2 - middleware: - - "RequestLogger" - - "ResponseLogger" - - "ClaimValidator" - dependencies: - - "database" - - "grouper_service" - endpoints: - klaim: - methods: ["GET", "POST", "PUT"] - get_path: "/klaim/:noklaim" - post_path: "/klaim" - put_path: "/klaim/:noklaim" - model: "KlaimRequest" - response_model: "KlaimResponse" - description: "Manage insurance claims" - summary: "Claim Management" - tags: ["eclaim", "klaim"] - require_auth: true - rate_limit: 30 - cache_enabled: false - grouper: - methods: ["POST"] - post_path: "/grouper" - model: "GrouperRequest" - response_model: "GrouperResponse" - description: "Process claim grouping and pricing" - summary: "Claim Grouper" - tags: ["eclaim", "grouper"] - require_auth: true - rate_limit: 20 - cache_enabled: true - cache_ttl: 120 - - aplicare: - name: "Aplicare" - category: "aplicare" - package: "aplicare" - description: "BPJS Aplicare service for reference data and monitoring" - base_url: "https://apijkn.bpjs-kesehatan.go.id/aplicaresws" - timeout: 45 - retry_count: 3 - middleware: - - "RequestLogger" - - "ResponseLogger" - dependencies: - - "database" - endpoints: - referensi: - methods: ["GET"] - get_path: "/referensi/:jenis" - model: "ReferensiRequest" - response_model: "ReferensiResponse" - description: "Get reference data (diagnoses, procedures, etc.)" - summary: "Get Reference Data" - tags: ["aplicare", "referensi"] - require_auth: true - rate_limit: 200 - cache_enabled: true - cache_ttl: 3600 - monitoring: - methods: ["GET", "POST"] - get_path: "/monitoring/:tanggal" - post_path: "/monitoring" - model: "MonitoringRequest" - response_model: "MonitoringResponse" - description: "Healthcare monitoring and reporting" - summary: "Monitoring Data" - tags: ["aplicare", "monitoring"] - require_auth: true - rate_limit: 50 - cache_enabled: false