Delete Data yang tidak perlu

This commit is contained in:
2025-09-19 12:15:05 +07:00
parent 98b5742205
commit c267657177
12 changed files with 8 additions and 1290 deletions

187
adapter
View File

@@ -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
}

Binary file not shown.

View File

@@ -1636,6 +1636,9 @@ const docTemplate = `{
}
}
},
"raw_response": {
"type": "string"
},
"sex": {
"type": "string"
},

View File

@@ -1634,6 +1634,9 @@
}
}
},
"raw_response": {
"type": "string"
},
"sex": {
"type": "string"
},

View File

@@ -173,6 +173,8 @@ definitions:
nmProvider:
type: string
type: object
raw_response:
type: string
sex:
type: string
statusPeserta:

View File

@@ -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://<server-address>/api/v1/ws?user_id=<user>&room=<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.

View File

@@ -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,
})
}

View File

@@ -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)
}

View File

@@ -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,
}
}

View File

@@ -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

View File

@@ -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

149
test
View File

@@ -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