Perbaikan Tools, Perbaikan

This commit is contained in:
2025-08-19 10:48:40 +07:00
parent 4d72e31352
commit 615db47606
9 changed files with 314 additions and 18 deletions

View File

@@ -1,5 +1,15 @@
# 🚀 API Service Guide # 🚀 API Service Guide
## 📖 Introduction
This API service is designed to provide a robust backend for managing products, orders, and user authentication. It integrates with BPJS for health insurance services and offers a comprehensive set of features for developers.
## 🌟 Features
- User authentication with JWT
- CRUD operations for products and orders
- Integration with BPJS services
- Swagger documentation for easy API testing
- Docker support for easy deployment
## 📋 Quick Start (5 Menit) ## 📋 Quick Start (5 Menit)
### 1. Setup Environment ### 1. Setup Environment
@@ -73,6 +83,8 @@ tools/generate.bat product get post put delete
go run tools/generate-handler.go product get post go run tools/generate-handler.go product get post
go run tools/generate-handler.go order get post put delete stats go run tools/generate-handler.go order get post put delete stats
go run tools/generate-bpjs-handler.go reference/peserta get
``` ```
### Method Tersedia ### Method Tersedia
@@ -209,5 +221,3 @@ const products = await axios.get('/api/v1/products');
--- ---
**Total waktu setup: 5 menit** | **Generate CRUD: 30 detik** | **Testing: Langsung di Swagger** **Total waktu setup: 5 menit** | **Generate CRUD: 30 detik** | **Testing: Langsung di Swagger**

View File

@@ -1,4 +1,5 @@
// Package docs Code generated by swaggo/swag. DO NOT EDIT // Code generated by swaggo/swag. DO NOT EDIT.
package docs package docs
import "github.com/swaggo/swag" import "github.com/swaggo/swag"
@@ -275,6 +276,50 @@ const docTemplate = `{
} }
} }
}, },
"/api/v1/bpjs/reference/referensi/diagnosa": {
"get": {
"description": "Get all diagnosa reference data",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs/reference"
],
"summary": "Get all diagnosa reference data",
"responses": {
"200": {
"description": "Success response",
"schema": {
"$ref": "#/definitions/models.DiagnosaResponse"
}
},
"400": {
"description": "Bad request",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"404": {
"description": "Data not found",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "Internal server error",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/api/v1/retribusi/{id}": { "/api/v1/retribusi/{id}": {
"get": { "get": {
"description": "Returns a single retribusi by ID", "description": "Returns a single retribusi by ID",
@@ -1118,6 +1163,18 @@ const docTemplate = `{
} }
} }
}, },
"models.DiagnosaResponse": {
"type": "object",
"properties": {
"data": {
"type": "object",
"additionalProperties": true
},
"message": {
"type": "string"
}
}
},
"sql.NullString": { "sql.NullString": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -1155,8 +1212,6 @@ var SwaggerInfo = &swag.Spec{
Description: "A comprehensive Go API service with Swagger documentation", Description: "A comprehensive Go API service with Swagger documentation",
InfoInstanceName: "swagger", InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate, SwaggerTemplate: docTemplate,
LeftDelim: "{{",
RightDelim: "}}",
} }
func init() { func init() {

View File

@@ -273,6 +273,50 @@
} }
} }
}, },
"/api/v1/bpjs/reference/referensi/diagnosa": {
"get": {
"description": "Get all diagnosa reference data",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs/reference"
],
"summary": "Get all diagnosa reference data",
"responses": {
"200": {
"description": "Success response",
"schema": {
"$ref": "#/definitions/models.DiagnosaResponse"
}
},
"400": {
"description": "Bad request",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"404": {
"description": "Data not found",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "Internal server error",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/api/v1/retribusi/{id}": { "/api/v1/retribusi/{id}": {
"get": { "get": {
"description": "Returns a single retribusi by ID", "description": "Returns a single retribusi by ID",
@@ -1116,6 +1160,18 @@
} }
} }
}, },
"models.DiagnosaResponse": {
"type": "object",
"properties": {
"data": {
"type": "object",
"additionalProperties": true
},
"message": {
"type": "string"
}
}
},
"sql.NullString": { "sql.NullString": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -292,6 +292,14 @@ definitions:
message: message:
type: string type: string
type: object type: object
models.DiagnosaResponse:
properties:
data:
additionalProperties: true
type: object
message:
type: string
type: object
sql.NullString: sql.NullString:
properties: properties:
string: string:
@@ -487,6 +495,36 @@ paths:
summary: Get participant data by NIK summary: Get participant data by NIK
tags: tags:
- bpjs - bpjs
/api/v1/bpjs/reference/referensi/diagnosa:
get:
consumes:
- application/json
description: Get all diagnosa reference data
produces:
- application/json
responses:
"200":
description: Success response
schema:
$ref: '#/definitions/models.DiagnosaResponse'
"400":
description: Bad request
schema:
additionalProperties: true
type: object
"404":
description: Data not found
schema:
additionalProperties: true
type: object
"500":
description: Internal server error
schema:
additionalProperties: true
type: object
summary: Get all diagnosa reference data
tags:
- bpjs/reference
/api/v1/retribusi/{id}: /api/v1/retribusi/{id}:
delete: delete:
consumes: consumes:

View File

@@ -41,13 +41,13 @@ MONGODB_MONGOHL7_LOCAL=local
MONGODB_MONGOHL7_SSLMODE=disable MONGODB_MONGOHL7_SSLMODE=disable
# MYSQL Antrian Database # MYSQL Antrian Database
# MYSQL_ANTRIAN_CONNECTION=mysql MYSQL_ANTRIAN_CONNECTION=mysql
# MYSQL_ANTRIAN_HOST=10.10.123.163 MYSQL_ANTRIAN_HOST=10.10.123.163
# MYSQL_ANTRIAN_USERNAME=www-data MYSQL_ANTRIAN_USERNAME=www-data
# MYSQL_ANTRIAN_PASSWORD=www-data MYSQL_ANTRIAN_PASSWORD=www-data
# MYSQL_ANTRIAN_DATABASE=antrian_rssa MYSQL_ANTRIAN_DATABASE=antrian_rssa
# MYSQL_ANTRIAN_PORT=5432 MYSQL_ANTRIAN_PORT=3306
# MYSQL_ANTRIAN_SSLMODE=disable MYSQL_ANTRIAN_SSLMODE=disable
MYSQL_MEDICAL_CONNECTION=mysql MYSQL_MEDICAL_CONNECTION=mysql

View File

@@ -0,0 +1,85 @@
package handlers
import (
"context"
"fmt"
"net/http"
"time"
"api-service/internal/config"
services "api-service/internal/services/bpjs"
"github.com/gin-gonic/gin"
)
// DiagnosaHandler handles BPJS diagnosa operations
type DiagnosaHandler struct {
bpjsService services.VClaimService
}
// NewDiagnosaHandler creates a new DiagnosaHandler instance
func NewDiagnosaHandler(cfg config.BpjsConfig) *DiagnosaHandler {
return &DiagnosaHandler{
bpjsService: services.NewService(cfg),
}
}
// GetAll godoc
// @Summary Get all diagnosa reference data
// @Description Get all diagnosa reference data
// @Tags bpjs/reference
// @Accept json
// @Produce json
// @Success 200 {object} models.DiagnosaResponse "Success response"
// @Failure 400 {object} map[string]interface{} "Bad request"
// @Failure 404 {object} map[string]interface{} "Data not found"
// @Failure 500 {object} map[string]interface{} "Internal server error"
// @Router /api/v1/bpjs/reference/referensi/diagnosa [get]
func (h *DiagnosaHandler) GetAll(c *gin.Context) {
// Create context with timeout
ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
defer cancel()
// Build endpoint URL
endpoint := "/referensi/diagnosa"
// Call BPJS service
var result map[string]interface{}
if err := h.bpjsService.Get(ctx, endpoint, &result); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to fetch diagnosa data",
"message": err.Error(),
})
return
}
// Return successful response
c.JSON(http.StatusOK, gin.H{
"message": "Data diagnosa berhasil diambil",
"data": result,
})
}
// Helper methods for error handling and response formatting
// handleBPJSError handles BPJS service errors and returns appropriate HTTP responses
func (h *DiagnosaHandler) handleBPJSError(c *gin.Context, err error, operation string) {
c.JSON(http.StatusInternalServerError, gin.H{
"error": fmt.Sprintf("Failed to %s", operation),
"message": err.Error(),
})
}
// validateDateFormat validates if the date string is in yyyy-MM-dd format
func (h *DiagnosaHandler) validateDateFormat(dateStr string) error {
_, err := time.Parse("2006-01-02", dateStr)
return err
}
// buildSuccessResponse builds a standardized success response
func (h *DiagnosaHandler) buildSuccessResponse(message string, data interface{}) gin.H {
return gin.H{
"message": message,
"data": data,
}
}

View File

@@ -0,0 +1,47 @@
package models
// DiagnosaResponse represents the response structure for BPJS diagnosa data
type DiagnosaResponse struct {
Message string `json:"message"`
Data map[string]interface{} `json:"data"`
}
// DiagnosaRawResponse represents the raw response structure from BPJS API
type DiagnosaRawResponse struct {
MetaData struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"metaData"`
Response interface{} `json:"response"`
}
// DiagnosaData represents the diagnosa reference data structure
type DiagnosaData struct {
KdDiag string `json:"kdDiag"`
NmDiag string `json:"nmDiag"`
}
// DiagnosaListResponse represents the response structure for diagnosa list
type DiagnosaListResponse struct {
Diagnosa []DiagnosaData `json:"diagnosa"`
}
// ErrorResponse represents error response structure
type ErrorResponse struct {
Error string `json:"error"`
Message string `json:"message"`
Code int `json:"code,omitempty"`
}
// BPJSMetaData represents BPJS API metadata structure
type BPJSMetaData struct {
Code string `json:"code"`
Message string `json:"message"`
}
// DiagnosaFilter represents filter parameters for diagnosa queries
type DiagnosaFilter struct {
NIK *string `form:"nik" json:"nik,omitempty"`
TglSEP *string `form:"tglSEP" json:"tglSEP,omitempty"`
}

View File

@@ -1,6 +1,7 @@
package v1 package v1
import ( import (
bpjsDiagnosaHandlers "api-service/internal/handlers/bpjs/reference"
bpjsPesertaHandlers "api-service/internal/handlers/bpjs/reference" bpjsPesertaHandlers "api-service/internal/handlers/bpjs/reference"
retribusiHandlers "api-service/internal/handlers/retribusi" retribusiHandlers "api-service/internal/handlers/retribusi"
@@ -61,6 +62,10 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine {
bpjsPesertaHandler := bpjsPesertaHandlers.NewPesertaHandler(cfg.Bpjs) bpjsPesertaHandler := bpjsPesertaHandlers.NewPesertaHandler(cfg.Bpjs)
v1.GET("/bpjs/Peserta/nik/:nik/tglSEP/:tglSEP", bpjsPesertaHandler.GetPesertaByNIK) v1.GET("/bpjs/Peserta/nik/:nik/tglSEP/:tglSEP", bpjsPesertaHandler.GetPesertaByNIK)
// BPJS Diagnosa endpoints
bpjsDiagnosaHandler := bpjsDiagnosaHandlers.NewDiagnosaHandler(cfg.Bpjs)
v1.GET("/bpjs/reference/referensi/diagnosa", bpjsDiagnosaHandler.GetAll)
protected := v1.Group("/") protected := v1.Group("/")
protected.Use(middleware.JWTAuthMiddleware(authService)) protected.Use(middleware.JWTAuthMiddleware(authService))
{ {

View File

@@ -203,12 +203,12 @@ func generateDefaultEndpoints(data BpjsHandlerData) []BpjsEndpoint {
func generateBpjsHandlerFile(data BpjsHandlerData, handlerDir string) { func generateBpjsHandlerFile(data BpjsHandlerData, handlerDir string) {
// Determine import path based on category // Determine import path based on category
var modelsImportPath string // var modelsImportPath string
if data.Category != "" { // if data.Category != "" {
modelsImportPath = `models "` + data.ModuleName + `/internal/models/bpjs/` + data.Category + `"` // modelsImportPath = `models "` + data.ModuleName + `/internal/models/bpjs/` + data.Category + `"`
} else { // } else {
modelsImportPath = `models "` + data.ModuleName + `/internal/models/bpjs/` + data.NameLower + `"` // modelsImportPath = `models "` + data.ModuleName + `/internal/models/bpjs/` + data.NameLower + `"`
} // }
handlerContent := `package handlers handlerContent := `package handlers