Clear generete structur bpjsAll

This commit is contained in:
2025-09-07 11:04:37 +07:00
parent b438fd8dd4
commit 779bbc976c
16 changed files with 13084 additions and 4378 deletions

View File

@@ -134,7 +134,8 @@ make build # Build production
### Update Swagger
```bash
swag init -g cmd/api/main.go --parseDependency --parseInternal
swag init -g cmd/api/main.go --parseDependency --parseInternal # Alternative Kedua
swag init -g cmd/api/main.go -o docs/
```
## 🔧 Environment Variables

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,291 @@
// Package peserta handles Peserta BPJS services
// Generated on: 2025-09-07 11:01:18
package handlers
import (
"context"
"encoding/json"
"net/http"
"strings"
"time"
"api-service/internal/config"
"api-service/internal/models"
"api-service/internal/models/vclaim/peserta"
"api-service/internal/services/bpjs"
"api-service/pkg/logger"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/google/uuid"
)
// PesertaHandler handles Peserta BPJS services
type PesertaHandler struct {
service services.VClaimService
validator *validator.Validate
logger logger.Logger
config config.BpjsConfig
}
// PesertaHandlerConfig contains configuration for PesertaHandler
type PesertaHandlerConfig struct {
BpjsConfig config.BpjsConfig
Logger logger.Logger
Validator *validator.Validate
}
// NewPesertaHandler creates a new PesertaHandler
func NewPesertaHandler(cfg PesertaHandlerConfig) *PesertaHandler {
return &PesertaHandler{
service: services.NewService(cfg.BpjsConfig),
validator: cfg.Validator,
logger: cfg.Logger,
config: cfg.BpjsConfig,
}
}
// GetBynik godoc
// @Summary Get Bynik data
// @Description Get participant eligibility information by NIK
// @Tags Peserta
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Param nik path string true "nik" example("example_value")
// @Success 200 {object} peserta.PesertaResponse "Successfully retrieved Bynik data"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials"
// @Failure 404 {object} models.ErrorResponseBpjs "Not found - Bynik not found"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /Peserta/nik/:nik [get]
func (h *PesertaHandler) GetBynik(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 GetBynik request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/peserta/nik/:nik",
"nik": c.Param("nik"),
})
// Extract path parameters
nik := c.Param("nik")
if nik == "" {
h.logger.Error("Missing required parameter nik", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
Status: "error",
Message: "Missing required parameter nik",
RequestID: requestID,
})
return
}
// Call service method
var response peserta.PesertaResponse
endpoint := "/peserta/nik/:nik"
endpoint = strings.Replace(endpoint, ":nik", nik, 1)
resp, err := h.service.GetRawResponse(ctx, endpoint)
if err != nil {
h.logger.Error("Failed to get Bynik", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &peserta.PesertaData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["peserta"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
c.JSON(http.StatusOK, response)
}
// GetBynokartu godoc
// @Summary Get Bynokartu data
// @Description Get participant eligibility information by card number
// @Tags Peserta
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Param nokartu path string true "nokartu" example("example_value")
// @Success 200 {object} peserta.PesertaResponse "Successfully retrieved Bynokartu data"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials"
// @Failure 404 {object} models.ErrorResponseBpjs "Not found - Bynokartu not found"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /Peserta/nokartu/:nokartu [get]
func (h *PesertaHandler) GetBynokartu(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 GetBynokartu request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/peserta/:nokartu",
"nokartu": c.Param("nokartu"),
})
// Extract path parameters
nokartu := c.Param("nokartu")
if nokartu == "" {
h.logger.Error("Missing required parameter nokartu", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
Status: "error",
Message: "Missing required parameter nokartu",
RequestID: requestID,
})
return
}
// Call service method
var response peserta.PesertaResponse
endpoint := "/peserta/:nokartu"
endpoint = strings.Replace(endpoint, ":nokartu", nokartu, 1)
resp, err := h.service.GetRawResponse(ctx, endpoint)
if err != nil {
h.logger.Error("Failed to get Bynokartu", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &peserta.PesertaData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["peserta"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
c.JSON(http.StatusOK, response)
}

View File

@@ -4,7 +4,7 @@ import (
"api-service/internal/config"
"api-service/internal/database"
models "api-service/internal/models"
modelsretribusi "api-service/internal/models/retribusi"
"api-service/internal/models/retribusi"
utils "api-service/internal/utils/filters"
"api-service/internal/utils/validation"
"api-service/pkg/logger"
@@ -73,7 +73,7 @@ func NewRetribusiHandler() *RetribusiHandler {
// @Param jenis query string false "Filter by jenis"
// @Param dinas query string false "Filter by dinas"
// @Param search query string false "Search in multiple fields"
// @Success 200 {object} modelsretribusi.RetribusiGetResponse "Success response"
// @Success 200 {object} retribusi.RetribusiGetResponse "Success response"
// @Failure 400 {object} models.ErrorResponse "Bad request"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
// @Router /api/v1/retribusis [get]
@@ -102,7 +102,7 @@ func (h *RetribusiHandler) GetRetribusi(c *gin.Context) {
// Execute concurrent operations
var (
retribusis []modelsretribusi.Retribusi
retribusis []retribusi.Retribusi
total int
aggregateData *models.AggregateData
wg sync.WaitGroup
@@ -165,7 +165,7 @@ func (h *RetribusiHandler) GetRetribusi(c *gin.Context) {
// Build response
meta := h.calculateMeta(limit, offset, total)
response := modelsretribusi.RetribusiGetResponse{
response := retribusi.RetribusiGetResponse{
Message: "Data retribusi berhasil diambil",
Data: retribusis,
Meta: meta,
@@ -185,7 +185,7 @@ func (h *RetribusiHandler) GetRetribusi(c *gin.Context) {
// @Accept json
// @Produce json
// @Param id path string true "Retribusi ID (UUID)"
// @Success 200 {object} modelsretribusi.RetribusiGetByIDResponse "Success response"
// @Success 200 {object} retribusi.RetribusiGetByIDResponse "Success response"
// @Failure 400 {object} models.ErrorResponse "Invalid ID format"
// @Failure 404 {object} models.ErrorResponse "Retribusi not found"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
@@ -208,7 +208,7 @@ func (h *RetribusiHandler) GetRetribusiByID(c *gin.Context) {
ctx, cancel := context.WithTimeout(c.Request.Context(), 15*time.Second)
defer cancel()
retribusi, err := h.getRetribusiByID(ctx, dbConn, id)
dataretribusi, err := h.getRetribusiByID(ctx, dbConn, id)
if err != nil {
if err == sql.ErrNoRows {
h.respondError(c, "Retribusi not found", err, http.StatusNotFound)
@@ -218,9 +218,9 @@ func (h *RetribusiHandler) GetRetribusiByID(c *gin.Context) {
return
}
response := modelsretribusi.RetribusiGetByIDResponse{
response := retribusi.RetribusiGetByIDResponse{
Message: "Retribusi details retrieved successfully",
Data: retribusi,
Data: dataretribusi,
}
c.JSON(http.StatusOK, response)
@@ -237,7 +237,7 @@ func (h *RetribusiHandler) GetRetribusiByID(c *gin.Context) {
// @Param sort query string false "Sort fields (e.g., sort=date_created,-Jenis)"
// @Param limit query int false "Limit" default(10)
// @Param offset query int false "Offset" default(0)
// @Success 200 {object} modelsretribusi.RetribusiGetResponse "Success response"
// @Success 200 {object} retribusi.RetribusiGetResponse "Success response"
// @Failure 400 {object} models.ErrorResponse "Bad request"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
// @Router /api/v1/retribusis/dynamic [get]
@@ -270,7 +270,7 @@ func (h *RetribusiHandler) GetRetribusiDynamic(c *gin.Context) {
// Build response
meta := h.calculateMeta(dynamicQuery.Limit, dynamicQuery.Offset, total)
response := modelsretribusi.RetribusiGetResponse{
response := retribusi.RetribusiGetResponse{
Message: "Data retribusi berhasil diambil",
Data: retribusis,
Meta: meta,
@@ -280,7 +280,7 @@ func (h *RetribusiHandler) GetRetribusiDynamic(c *gin.Context) {
}
// fetchRetribusisDynamic executes dynamic query
func (h *RetribusiHandler) fetchRetribusisDynamic(ctx context.Context, dbConn *sql.DB, query utils.DynamicQuery) ([]modelsretribusi.Retribusi, int, error) {
func (h *RetribusiHandler) fetchRetribusisDynamic(ctx context.Context, dbConn *sql.DB, query utils.DynamicQuery) ([]retribusi.Retribusi, int, error) {
// Setup query builder
builder := utils.NewQueryBuilder("data_retribusi").
SetColumnMapping(map[string]string{
@@ -319,7 +319,7 @@ func (h *RetribusiHandler) fetchRetribusisDynamic(ctx context.Context, dbConn *s
// Execute concurrent queries
var (
retribusis []modelsretribusi.Retribusi
retribusis []retribusi.Retribusi
total int
wg sync.WaitGroup
errChan = make(chan error, 2)
@@ -364,7 +364,7 @@ func (h *RetribusiHandler) fetchRetribusisDynamic(ctx context.Context, dbConn *s
}
defer rows.Close()
var results []modelsretribusi.Retribusi
var results []retribusi.Retribusi
for rows.Next() {
retribusi, err := h.scanRetribusi(rows)
if err != nil {
@@ -484,7 +484,7 @@ func (h *RetribusiHandler) SearchRetribusiAdvanced(c *gin.Context) {
// Build response
meta := h.calculateMeta(query.Limit, query.Offset, total)
response := modelsretribusi.RetribusiGetResponse{
response := retribusi.RetribusiGetResponse{
Message: fmt.Sprintf("Search results for '%s'", searchQuery),
Data: retribusis,
Meta: meta,
@@ -499,13 +499,13 @@ func (h *RetribusiHandler) SearchRetribusiAdvanced(c *gin.Context) {
// @Tags Retribusi
// @Accept json
// @Produce json
// @Param request body modelsretribusi.RetribusiCreateRequest true "Retribusi creation request"
// @Success 201 {object} modelsretribusi.RetribusiCreateResponse "Retribusi created successfully"
// @Param request body retribusi.RetribusiCreateRequest true "Retribusi creation request"
// @Success 201 {object} retribusi.RetribusiCreateResponse "Retribusi created successfully"
// @Failure 400 {object} models.ErrorResponse "Bad request or validation error"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
// @Router /api/v1/retribusis [post]
func (h *RetribusiHandler) CreateRetribusi(c *gin.Context) {
var req modelsretribusi.RetribusiCreateRequest
var req retribusi.RetribusiCreateRequest
if err := c.ShouldBindJSON(&req); err != nil {
h.respondError(c, "Invalid request body", err, http.StatusBadRequest)
@@ -533,15 +533,15 @@ func (h *RetribusiHandler) CreateRetribusi(c *gin.Context) {
return
}
retribusi, err := h.createRetribusi(ctx, dbConn, &req)
dataretribusi, err := h.createRetribusi(ctx, dbConn, &req)
if err != nil {
h.logAndRespondError(c, "Failed to create retribusi", err, http.StatusInternalServerError)
return
}
response := modelsretribusi.RetribusiCreateResponse{
response := retribusi.RetribusiCreateResponse{
Message: "Retribusi berhasil dibuat",
Data: retribusi,
Data: dataretribusi,
}
c.JSON(http.StatusCreated, response)
@@ -554,8 +554,8 @@ func (h *RetribusiHandler) CreateRetribusi(c *gin.Context) {
// @Accept json
// @Produce json
// @Param id path string true "Retribusi ID (UUID)"
// @Param request body modelsretribusi.RetribusiUpdateRequest true "Retribusi update request"
// @Success 200 {object} modelsretribusi.RetribusiUpdateResponse "Retribusi updated successfully"
// @Param request body retribusi.RetribusiUpdateRequest true "Retribusi update request"
// @Success 200 {object} retribusi.RetribusiUpdateResponse "Retribusi updated successfully"
// @Failure 400 {object} models.ErrorResponse "Bad request or validation error"
// @Failure 404 {object} models.ErrorResponse "Retribusi not found"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
@@ -569,7 +569,7 @@ func (h *RetribusiHandler) UpdateRetribusi(c *gin.Context) {
return
}
var req modelsretribusi.RetribusiUpdateRequest
var req retribusi.RetribusiUpdateRequest
if err := c.ShouldBindJSON(&req); err != nil {
h.respondError(c, "Invalid request body", err, http.StatusBadRequest)
return
@@ -593,7 +593,7 @@ func (h *RetribusiHandler) UpdateRetribusi(c *gin.Context) {
ctx, cancel := context.WithTimeout(c.Request.Context(), 15*time.Second)
defer cancel()
retribusi, err := h.updateRetribusi(ctx, dbConn, &req)
dataretribusi, err := h.updateRetribusi(ctx, dbConn, &req)
if err != nil {
if err == sql.ErrNoRows {
h.respondError(c, "Retribusi not found", err, http.StatusNotFound)
@@ -603,9 +603,9 @@ func (h *RetribusiHandler) UpdateRetribusi(c *gin.Context) {
return
}
response := modelsretribusi.RetribusiUpdateResponse{
response := retribusi.RetribusiUpdateResponse{
Message: "Retribusi berhasil diperbarui",
Data: retribusi,
Data: dataretribusi,
}
c.JSON(http.StatusOK, response)
@@ -618,7 +618,7 @@ func (h *RetribusiHandler) UpdateRetribusi(c *gin.Context) {
// @Accept json
// @Produce json
// @Param id path string true "Retribusi ID (UUID)"
// @Success 200 {object} modelsretribusi.RetribusiDeleteResponse "Retribusi deleted successfully"
// @Success 200 {object} retribusi.RetribusiDeleteResponse "Retribusi deleted successfully"
// @Failure 400 {object} models.ErrorResponse "Invalid ID format"
// @Failure 404 {object} models.ErrorResponse "Retribusi not found"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
@@ -651,7 +651,7 @@ func (h *RetribusiHandler) DeleteRetribusi(c *gin.Context) {
return
}
response := modelsretribusi.RetribusiDeleteResponse{
response := retribusi.RetribusiDeleteResponse{
Message: "Retribusi berhasil dihapus",
ID: id,
}
@@ -693,7 +693,7 @@ func (h *RetribusiHandler) GetRetribusiStats(c *gin.Context) {
}
// Get retribusi by ID
func (h *RetribusiHandler) getRetribusiByID(ctx context.Context, dbConn *sql.DB, id string) (*modelsretribusi.Retribusi, error) {
func (h *RetribusiHandler) getRetribusiByID(ctx context.Context, dbConn *sql.DB, id string) (*retribusi.Retribusi, error) {
query := `
SELECT
id, status, sort, user_created, date_created, user_updated, date_updated,
@@ -705,7 +705,7 @@ func (h *RetribusiHandler) getRetribusiByID(ctx context.Context, dbConn *sql.DB,
row := dbConn.QueryRowContext(ctx, query, id)
var retribusi modelsretribusi.Retribusi
var retribusi retribusi.Retribusi
err := row.Scan(
&retribusi.ID, &retribusi.Status, &retribusi.Sort, &retribusi.UserCreated,
&retribusi.DateCreated, &retribusi.UserUpdated, &retribusi.DateUpdated,
@@ -723,7 +723,7 @@ func (h *RetribusiHandler) getRetribusiByID(ctx context.Context, dbConn *sql.DB,
}
// Create retribusi
func (h *RetribusiHandler) createRetribusi(ctx context.Context, dbConn *sql.DB, req *modelsretribusi.RetribusiCreateRequest) (*modelsretribusi.Retribusi, error) {
func (h *RetribusiHandler) createRetribusi(ctx context.Context, dbConn *sql.DB, req *retribusi.RetribusiCreateRequest) (*retribusi.Retribusi, error) {
id := uuid.New().String()
now := time.Now()
@@ -747,7 +747,7 @@ func (h *RetribusiHandler) createRetribusi(ctx context.Context, dbConn *sql.DB,
req.RekeningPokok, req.RekeningDenda, req.Uraian1, req.Uraian2, req.Uraian3,
)
var retribusi modelsretribusi.Retribusi
var retribusi retribusi.Retribusi
err := row.Scan(
&retribusi.ID, &retribusi.Status, &retribusi.Sort, &retribusi.UserCreated,
&retribusi.DateCreated, &retribusi.UserUpdated, &retribusi.DateUpdated,
@@ -765,7 +765,7 @@ func (h *RetribusiHandler) createRetribusi(ctx context.Context, dbConn *sql.DB,
}
// Update retribusi
func (h *RetribusiHandler) updateRetribusi(ctx context.Context, dbConn *sql.DB, req *modelsretribusi.RetribusiUpdateRequest) (*modelsretribusi.Retribusi, error) {
func (h *RetribusiHandler) updateRetribusi(ctx context.Context, dbConn *sql.DB, req *retribusi.RetribusiUpdateRequest) (*retribusi.Retribusi, error) {
now := time.Now()
query := `
@@ -788,7 +788,7 @@ func (h *RetribusiHandler) updateRetribusi(ctx context.Context, dbConn *sql.DB,
req.RekeningPokok, req.RekeningDenda, req.Uraian1, req.Uraian2, req.Uraian3,
)
var retribusi modelsretribusi.Retribusi
var retribusi retribusi.Retribusi
err := row.Scan(
&retribusi.ID, &retribusi.Status, &retribusi.Sort, &retribusi.UserCreated,
&retribusi.DateCreated, &retribusi.UserUpdated, &retribusi.DateUpdated,
@@ -889,7 +889,7 @@ func (h *RetribusiHandler) parsePaginationParams(c *gin.Context) (int, int, erro
}
// Build WHERE clause dengan filter parameters
func (h *RetribusiHandler) buildWhereClause(filter modelsretribusi.RetribusiFilter) (string, []interface{}) {
func (h *RetribusiHandler) buildWhereClause(filter retribusi.RetribusiFilter) (string, []interface{}) {
conditions := []string{"status != 'deleted'"}
args := []interface{}{}
paramCount := 1
@@ -950,8 +950,8 @@ func (h *RetribusiHandler) buildWhereClause(filter modelsretribusi.RetribusiFilt
}
// Optimized scanning function yang menggunakan sql.Null* types langsung
func (h *RetribusiHandler) scanRetribusi(rows *sql.Rows) (modelsretribusi.Retribusi, error) {
var retribusi modelsretribusi.Retribusi
func (h *RetribusiHandler) scanRetribusi(rows *sql.Rows) (retribusi.Retribusi, error) {
var retribusi retribusi.Retribusi
return retribusi, rows.Scan(
&retribusi.ID,
@@ -979,8 +979,8 @@ func (h *RetribusiHandler) scanRetribusi(rows *sql.Rows) (modelsretribusi.Retrib
}
// Parse filter parameters dari query string
func (h *RetribusiHandler) parseFilterParams(c *gin.Context) modelsretribusi.RetribusiFilter {
filter := modelsretribusi.RetribusiFilter{}
func (h *RetribusiHandler) parseFilterParams(c *gin.Context) retribusi.RetribusiFilter {
filter := retribusi.RetribusiFilter{}
if status := c.Query("status"); status != "" {
if models.IsValidStatus(status) {
@@ -1021,7 +1021,7 @@ func (h *RetribusiHandler) parseFilterParams(c *gin.Context) modelsretribusi.Ret
}
// Get comprehensive aggregate data dengan filter support
func (h *RetribusiHandler) getAggregateData(ctx context.Context, dbConn *sql.DB, filter modelsretribusi.RetribusiFilter) (*models.AggregateData, error) {
func (h *RetribusiHandler) getAggregateData(ctx context.Context, dbConn *sql.DB, filter retribusi.RetribusiFilter) (*models.AggregateData, error) {
aggregate := &models.AggregateData{
ByStatus: make(map[string]int),
ByDinas: make(map[string]int),
@@ -1211,7 +1211,7 @@ func (h *RetribusiHandler) getAggregateData(ctx context.Context, dbConn *sql.DB,
}
// Get total count dengan filter support
func (h *RetribusiHandler) getTotalCount(ctx context.Context, dbConn *sql.DB, filter modelsretribusi.RetribusiFilter, total *int) error {
func (h *RetribusiHandler) getTotalCount(ctx context.Context, dbConn *sql.DB, filter retribusi.RetribusiFilter, total *int) error {
whereClause, args := h.buildWhereClause(filter)
countQuery := fmt.Sprintf(`SELECT COUNT(*) FROM data_retribusi WHERE %s`, whereClause)
@@ -1223,7 +1223,7 @@ func (h *RetribusiHandler) getTotalCount(ctx context.Context, dbConn *sql.DB, fi
}
// Enhanced fetchRetribusis dengan filter support
func (h *RetribusiHandler) fetchRetribusis(ctx context.Context, dbConn *sql.DB, filter modelsretribusi.RetribusiFilter, limit, offset int) ([]modelsretribusi.Retribusi, error) {
func (h *RetribusiHandler) fetchRetribusis(ctx context.Context, dbConn *sql.DB, filter retribusi.RetribusiFilter, limit, offset int) ([]retribusi.Retribusi, error) {
whereClause, args := h.buildWhereClause(filter)
// Build the main query with pagination
@@ -1249,7 +1249,7 @@ func (h *RetribusiHandler) fetchRetribusis(ctx context.Context, dbConn *sql.DB,
defer rows.Close()
// Pre-allocate slice dengan kapasitas yang tepat
retribusis := make([]modelsretribusi.Retribusi, 0, limit)
retribusis := make([]retribusi.Retribusi, 0, limit)
for rows.Next() {
retribusi, err := h.scanRetribusi(rows)
@@ -1293,7 +1293,7 @@ func (h *RetribusiHandler) calculateMeta(limit, offset, total int) models.MetaRe
}
// validateRetribusiSubmission performs validation for duplicate entries and daily submission limits
func (h *RetribusiHandler) validateRetribusiSubmission(ctx context.Context, dbConn *sql.DB, req *modelsretribusi.RetribusiCreateRequest) error {
func (h *RetribusiHandler) validateRetribusiSubmission(ctx context.Context, dbConn *sql.DB, req *retribusi.RetribusiCreateRequest) error {
// Import the validation utility
validator := validation.NewDuplicateValidator(dbConn)
@@ -1316,7 +1316,7 @@ func (h *RetribusiHandler) validateRetribusiSubmission(ctx context.Context, dbCo
}
// Example usage of the validation utility with custom configuration
func (h *RetribusiHandler) validateWithCustomConfig(ctx context.Context, dbConn *sql.DB, req *modelsretribusi.RetribusiCreateRequest) error {
func (h *RetribusiHandler) validateWithCustomConfig(ctx context.Context, dbConn *sql.DB, req *retribusi.RetribusiCreateRequest) error {
// Create validator instance
validator := validation.NewDuplicateValidator(dbConn)

View File

@@ -0,0 +1,885 @@
// Package rujukan handles Rujukan BPJS services
// Generated on: 2025-09-07 11:01:18
package handlers
import (
"context"
"encoding/json"
"net/http"
"strings"
"time"
"api-service/internal/config"
"api-service/internal/models"
"api-service/internal/models/vclaim/rujukan"
"api-service/internal/services/bpjs"
"api-service/pkg/logger"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/google/uuid"
)
// RujukanHandler handles Rujukan BPJS services
type RujukanHandler struct {
service services.VClaimService
validator *validator.Validate
logger logger.Logger
config config.BpjsConfig
}
// RujukanHandlerConfig contains configuration for RujukanHandler
type RujukanHandlerConfig struct {
BpjsConfig config.BpjsConfig
Logger logger.Logger
Validator *validator.Validate
}
// NewRujukanHandler creates a new RujukanHandler
func NewRujukanHandler(cfg RujukanHandlerConfig) *RujukanHandler {
return &RujukanHandler{
service: services.NewService(cfg.BpjsConfig),
validator: cfg.Validator,
logger: cfg.Logger,
config: cfg.BpjsConfig,
}
}
// CreateRujukan godoc
// @Summary Create new Rujukan
// @Description Create new Rujukan in BPJS system
// @Tags Rujukan
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Param request body rujukan.RujukanRequest true "Rujukan data"
// @Success 201 {object} rujukan.RujukanResponse "Successfully created Rujukan"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized"
// @Failure 409 {object} models.ErrorResponseBpjs "Conflict"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /Rujukan/:norujukan [post]
func (h *RujukanHandler) CreateRujukan(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 CreateRujukan request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/Rujukan",
})
// Bind and validate request body
var req rujukan.RujukanRequest
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.ErrorResponseBpjs{
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.ErrorResponseBpjs{
Status: "error",
Message: "Validation failed: " + err.Error(),
RequestID: requestID,
})
return
}
// Call service method
var response rujukan.RujukanResponse
resp, err := h.service.PostRawResponse(ctx, "/Rujukan", req)
if err != nil {
h.logger.Error("Failed to create Rujukan", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
// Handle specific BPJS errors
if strings.Contains(err.Error(), "409") || strings.Contains(err.Error(), "conflict") {
c.JSON(http.StatusConflict, models.ErrorResponseBpjs{
Status: "error",
Message: "Rujukan already exists or conflict occurred",
RequestID: requestID,
})
return
}
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &rujukan.RujukanData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["rujukan"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
h.logger.Info("Successfully created Rujukan", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusCreated, response)
}
// UpdateRujukan godoc
// @Summary Update existing Rujukan
// @Description Update existing Rujukan in BPJS system
// @Tags Rujukan
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Param request body rujukan.RujukanRequest true "Rujukan update data"
// @Success 200 {object} rujukan.RujukanResponse "Successfully updated Rujukan"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials"
// @Failure 404 {object} models.ErrorResponseBpjs "Not found - Rujukan not found"
// @Failure 409 {object} models.ErrorResponseBpjs "Conflict - update conflict occurred"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /Rujukan/:norujukan [put]
func (h *RujukanHandler) UpdateRujukan(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 UpdateRujukan request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/Rujukan",
})
// Extract path parameters
// Bind and validate request body
var req rujukan.RujukanRequest
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.ErrorResponseBpjs{
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.ErrorResponseBpjs{
Status: "error",
Message: "Validation failed: " + err.Error(),
RequestID: requestID,
})
return
}
// Call service method
var response rujukan.RujukanResponse
resp, err := h.service.PutRawResponse(ctx, "/Rujukan", req)
if err != nil {
h.logger.Error("Failed to update Rujukan", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
// Handle specific BPJS errors
if strings.Contains(err.Error(), "404") || strings.Contains(err.Error(), "not found") {
c.JSON(http.StatusNotFound, models.ErrorResponseBpjs{
Status: "error",
Message: "Rujukan not found",
RequestID: requestID,
})
return
}
if strings.Contains(err.Error(), "409") || strings.Contains(err.Error(), "conflict") {
c.JSON(http.StatusConflict, models.ErrorResponseBpjs{
Status: "error",
Message: "Update conflict occurred",
RequestID: requestID,
})
return
}
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &rujukan.RujukanData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["rujukan"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
h.logger.Info("Successfully updated Rujukan", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusOK, response)
}
// DeleteRujukan godoc
// @Summary Delete existing Rujukan
// @Description Delete existing Rujukan from BPJS system
// @Tags Rujukan
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Success 200 {object} rujukan.RujukanResponse "Successfully deleted Rujukan"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials"
// @Failure 404 {object} models.ErrorResponseBpjs "Not found - Rujukan not found"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /Rujukan/:norujukan [delete]
func (h *RujukanHandler) DeleteRujukan(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 DeleteRujukan request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/Rujukan",
})
// Extract path parameters
// Call service method
var response rujukan.RujukanResponse
resp, err := h.service.DeleteRawResponse(ctx, "/Rujukan")
if err != nil {
h.logger.Error("Failed to delete Rujukan", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
// Handle specific BPJS errors
if strings.Contains(err.Error(), "404") || strings.Contains(err.Error(), "not found") {
c.JSON(http.StatusNotFound, models.ErrorResponseBpjs{
Status: "error",
Message: "Rujukan not found",
RequestID: requestID,
})
return
}
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &rujukan.RujukanData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["rujukan"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
} else {
// For delete operations, sometimes there's no data in response
response.Data = nil
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
h.logger.Info("Successfully deleted Rujukan", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusOK, response)
}
// CreateRujukanbalik godoc
// @Summary Create new Rujukanbalik
// @Description Create new Rujukanbalik in BPJS system
// @Tags Rujukan
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Param request body rujukan.RujukanRequest true "Rujukanbalik data"
// @Success 201 {object} rujukan.RujukanResponse "Successfully created Rujukanbalik"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized"
// @Failure 409 {object} models.ErrorResponseBpjs "Conflict"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /Rujukanbalik/:norujukan [post]
func (h *RujukanHandler) CreateRujukanbalik(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 CreateRujukanbalik request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/Rujukanbalik",
})
// Bind and validate request body
var req rujukan.RujukanRequest
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.ErrorResponseBpjs{
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.ErrorResponseBpjs{
Status: "error",
Message: "Validation failed: " + err.Error(),
RequestID: requestID,
})
return
}
// Call service method
var response rujukan.RujukanResponse
resp, err := h.service.PostRawResponse(ctx, "/Rujukanbalik", req)
if err != nil {
h.logger.Error("Failed to create Rujukanbalik", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
// Handle specific BPJS errors
if strings.Contains(err.Error(), "409") || strings.Contains(err.Error(), "conflict") {
c.JSON(http.StatusConflict, models.ErrorResponseBpjs{
Status: "error",
Message: "Rujukanbalik already exists or conflict occurred",
RequestID: requestID,
})
return
}
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &rujukan.RujukanData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["rujukan"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
h.logger.Info("Successfully created Rujukanbalik", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusCreated, response)
}
// UpdateRujukanbalik godoc
// @Summary Update existing Rujukanbalik
// @Description Update existing Rujukanbalik in BPJS system
// @Tags Rujukan
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Param request body rujukan.RujukanRequest true "Rujukanbalik update data"
// @Success 200 {object} rujukan.RujukanResponse "Successfully updated Rujukanbalik"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials"
// @Failure 404 {object} models.ErrorResponseBpjs "Not found - Rujukanbalik not found"
// @Failure 409 {object} models.ErrorResponseBpjs "Conflict - update conflict occurred"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /Rujukanbalik/:norujukan [put]
func (h *RujukanHandler) UpdateRujukanbalik(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 UpdateRujukanbalik request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/Rujukanbalik",
})
// Extract path parameters
// Bind and validate request body
var req rujukan.RujukanRequest
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.ErrorResponseBpjs{
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.ErrorResponseBpjs{
Status: "error",
Message: "Validation failed: " + err.Error(),
RequestID: requestID,
})
return
}
// Call service method
var response rujukan.RujukanResponse
resp, err := h.service.PutRawResponse(ctx, "/Rujukanbalik", req)
if err != nil {
h.logger.Error("Failed to update Rujukanbalik", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
// Handle specific BPJS errors
if strings.Contains(err.Error(), "404") || strings.Contains(err.Error(), "not found") {
c.JSON(http.StatusNotFound, models.ErrorResponseBpjs{
Status: "error",
Message: "Rujukanbalik not found",
RequestID: requestID,
})
return
}
if strings.Contains(err.Error(), "409") || strings.Contains(err.Error(), "conflict") {
c.JSON(http.StatusConflict, models.ErrorResponseBpjs{
Status: "error",
Message: "Update conflict occurred",
RequestID: requestID,
})
return
}
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &rujukan.RujukanData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["rujukan"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
h.logger.Info("Successfully updated Rujukanbalik", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusOK, response)
}
// DeleteRujukanbalik godoc
// @Summary Delete existing Rujukanbalik
// @Description Delete existing Rujukanbalik from BPJS system
// @Tags Rujukan
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Success 200 {object} rujukan.RujukanResponse "Successfully deleted Rujukanbalik"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials"
// @Failure 404 {object} models.ErrorResponseBpjs "Not found - Rujukanbalik not found"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /Rujukanbalik/:norujukan [delete]
func (h *RujukanHandler) DeleteRujukanbalik(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 DeleteRujukanbalik request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/Rujukanbalik",
})
// Extract path parameters
// Call service method
var response rujukan.RujukanResponse
resp, err := h.service.DeleteRawResponse(ctx, "/Rujukanbalik")
if err != nil {
h.logger.Error("Failed to delete Rujukanbalik", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
// Handle specific BPJS errors
if strings.Contains(err.Error(), "404") || strings.Contains(err.Error(), "not found") {
c.JSON(http.StatusNotFound, models.ErrorResponseBpjs{
Status: "error",
Message: "Rujukanbalik not found",
RequestID: requestID,
})
return
}
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &rujukan.RujukanData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["rujukan"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
} else {
// For delete operations, sometimes there's no data in response
response.Data = nil
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
h.logger.Info("Successfully deleted Rujukanbalik", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusOK, response)
}

View File

@@ -0,0 +1,291 @@
// Package rujukan handles Search BPJS services
// Generated on: 2025-09-07 11:01:18
package handlers
import (
"context"
"encoding/json"
"net/http"
"strings"
"time"
"api-service/internal/config"
"api-service/internal/models"
"api-service/internal/models/vclaim/rujukan"
"api-service/internal/services/bpjs"
"api-service/pkg/logger"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/google/uuid"
)
// SearchHandler handles Search BPJS services
type SearchHandler struct {
service services.VClaimService
validator *validator.Validate
logger logger.Logger
config config.BpjsConfig
}
// SearchHandlerConfig contains configuration for SearchHandler
type SearchHandlerConfig struct {
BpjsConfig config.BpjsConfig
Logger logger.Logger
Validator *validator.Validate
}
// NewSearchHandler creates a new SearchHandler
func NewSearchHandler(cfg SearchHandlerConfig) *SearchHandler {
return &SearchHandler{
service: services.NewService(cfg.BpjsConfig),
validator: cfg.Validator,
logger: cfg.Logger,
config: cfg.BpjsConfig,
}
}
// GetBynorujukan godoc
// @Summary Get Bynorujukan data
// @Description Get rujukan by nomor rujukan
// @Tags Rujukan
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Param norujukan path string true "norujukan" example("example_value")
// @Success 200 {object} rujukan.RujukanResponse "Successfully retrieved Bynorujukan data"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials"
// @Failure 404 {object} models.ErrorResponseBpjs "Not found - Bynorujukan not found"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /bynorujukan/:norujukan [get]
func (h *SearchHandler) GetBynorujukan(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 GetBynorujukan request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/Rujukan/:norujukan",
"norujukan": c.Param("norujukan"),
})
// Extract path parameters
norujukan := c.Param("norujukan")
if norujukan == "" {
h.logger.Error("Missing required parameter norujukan", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
Status: "error",
Message: "Missing required parameter norujukan",
RequestID: requestID,
})
return
}
// Call service method
var response rujukan.RujukanResponse
endpoint := "/Rujukan/:norujukan"
endpoint = strings.Replace(endpoint, ":norujukan", norujukan, 1)
resp, err := h.service.GetRawResponse(ctx, endpoint)
if err != nil {
h.logger.Error("Failed to get Bynorujukan", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &rujukan.RujukanData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["rujukan"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
c.JSON(http.StatusOK, response)
}
// GetBynokartu godoc
// @Summary Get Bynokartu data
// @Description Get rujukan by card number
// @Tags Rujukan
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param X-Request-ID header string false "Request ID for tracking"
// @Param nokartu path string true "nokartu" example("example_value")
// @Success 200 {object} rujukan.RujukanResponse "Successfully retrieved Bynokartu data"
// @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters"
// @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials"
// @Failure 404 {object} models.ErrorResponseBpjs "Not found - Bynokartu not found"
// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error"
// @Router /bynokartu/:nokartu [get]
func (h *SearchHandler) GetBynokartu(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 GetBynokartu request", map[string]interface{}{
"request_id": requestID,
"endpoint": "/Rujukan/:nokartu",
"nokartu": c.Param("nokartu"),
})
// Extract path parameters
nokartu := c.Param("nokartu")
if nokartu == "" {
h.logger.Error("Missing required parameter nokartu", map[string]interface{}{
"request_id": requestID,
})
c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
Status: "error",
Message: "Missing required parameter nokartu",
RequestID: requestID,
})
return
}
// Call service method
var response rujukan.RujukanResponse
endpoint := "/Rujukan/:nokartu"
endpoint = strings.Replace(endpoint, ":nokartu", nokartu, 1)
resp, err := h.service.GetRawResponse(ctx, endpoint)
if err != nil {
h.logger.Error("Failed to get Bynokartu", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
Status: "error",
Message: "Internal server error",
RequestID: requestID,
})
return
}
// Map the raw response
response.MetaData = resp.MetaData
if resp.Response != nil {
response.Data = &rujukan.RujukanData{}
if respStr, ok := resp.Response.(string); ok {
// Decrypt the response string
consID, secretKey, _, tstamp, _ := h.config.SetHeader()
decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
if err != nil {
h.logger.Error("Failed to decrypt response", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
})
} else {
json.Unmarshal([]byte(decryptedResp), response.Data)
}
} else if respMap, ok := resp.Response.(map[string]interface{}); ok {
// Response is already unmarshaled JSON
if dataMap, exists := respMap["rujukan"]; exists {
dataBytes, _ := json.Marshal(dataMap)
json.Unmarshal(dataBytes, response.Data)
} else {
// Try to unmarshal the whole response
respBytes, _ := json.Marshal(resp.Response)
json.Unmarshal(respBytes, response.Data)
}
}
}
// Ensure response has proper fields
response.Status = "success"
response.RequestID = requestID
c.JSON(http.StatusOK, response)
}

View File

@@ -6,7 +6,7 @@ import (
"time"
)
// NullableInt32 is a custom type to replace sql.NullInt32 for swagger compatibility
// NullableInt32 - your existing implementation
type NullableInt32 struct {
Int32 int32 `json:"int32,omitempty"`
Valid bool `json:"valid"`
@@ -31,6 +31,56 @@ func (n NullableInt32) Value() (driver.Value, error) {
return n.Int32, nil
}
// NullableString provides consistent nullable string handling
type NullableString struct {
String string `json:"string,omitempty"`
Valid bool `json:"valid"`
}
// Scan implements the sql.Scanner interface for NullableString
func (n *NullableString) Scan(value interface{}) error {
var ns sql.NullString
if err := ns.Scan(value); err != nil {
return err
}
n.String = ns.String
n.Valid = ns.Valid
return nil
}
// Value implements the driver.Valuer interface for NullableString
func (n NullableString) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
return n.String, nil
}
// NullableTime provides consistent nullable time handling
type NullableTime struct {
Time time.Time `json:"time,omitempty"`
Valid bool `json:"valid"`
}
// Scan implements the sql.Scanner interface for NullableTime
func (n *NullableTime) Scan(value interface{}) error {
var nt sql.NullTime
if err := nt.Scan(value); err != nil {
return err
}
n.Time = nt.Time
n.Valid = nt.Valid
return nil
}
// Value implements the driver.Valuer interface for NullableTime
func (n NullableTime) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
return n.Time, nil
}
// Metadata untuk pagination - dioptimalkan
type MetaResponse struct {
Limit int `json:"limit"`

View File

@@ -1,8 +1,7 @@
package models
package retribusi
import (
"api-service/internal/models"
"database/sql"
"encoding/json"
"time"
)
@@ -10,27 +9,27 @@ import (
// Retribusi represents the data structure for the retribusi table
// with proper null handling and optimized JSON marshaling
type Retribusi struct {
ID string `json:"id" db:"id"`
Status string `json:"status" db:"status"`
Sort models.NullableInt32 `json:"sort,omitempty" db:"sort"`
UserCreated sql.NullString `json:"user_created,omitempty" db:"user_created"`
DateCreated sql.NullTime `json:"date_created,omitempty" db:"date_created"`
UserUpdated sql.NullString `json:"user_updated,omitempty" db:"user_updated"`
DateUpdated sql.NullTime `json:"date_updated,omitempty" db:"date_updated"`
Jenis sql.NullString `json:"jenis,omitempty" db:"Jenis"`
Pelayanan sql.NullString `json:"pelayanan,omitempty" db:"Pelayanan"`
Dinas sql.NullString `json:"dinas,omitempty" db:"Dinas"`
KelompokObyek sql.NullString `json:"kelompok_obyek,omitempty" db:"Kelompok_obyek"`
KodeTarif sql.NullString `json:"kode_tarif,omitempty" db:"Kode_tarif"`
Tarif sql.NullString `json:"tarif,omitempty" db:"Tarif"`
Satuan sql.NullString `json:"satuan,omitempty" db:"Satuan"`
TarifOvertime sql.NullString `json:"tarif_overtime,omitempty" db:"Tarif_overtime"`
SatuanOvertime sql.NullString `json:"satuan_overtime,omitempty" db:"Satuan_overtime"`
RekeningPokok sql.NullString `json:"rekening_pokok,omitempty" db:"Rekening_pokok"`
RekeningDenda sql.NullString `json:"rekening_denda,omitempty" db:"Rekening_denda"`
Uraian1 sql.NullString `json:"uraian_1,omitempty" db:"Uraian_1"`
Uraian2 sql.NullString `json:"uraian_2,omitempty" db:"Uraian_2"`
Uraian3 sql.NullString `json:"uraian_3,omitempty" db:"Uraian_3"`
ID string `json:"id" db:"id"`
Status string `json:"status" db:"status"`
Sort models.NullableInt32 `json:"sort,omitempty" db:"sort"`
UserCreated models.NullableString `json:"user_created,omitempty" db:"user_created"`
DateCreated models.NullableTime `json:"date_created,omitempty" db:"date_created"`
UserUpdated models.NullableString `json:"user_updated,omitempty" db:"user_updated"`
DateUpdated models.NullableTime `json:"date_updated,omitempty" db:"date_updated"`
Jenis models.NullableString `json:"jenis,omitempty" db:"Jenis"`
Pelayanan models.NullableString `json:"pelayanan,omitempty" db:"Pelayanan"`
Dinas models.NullableString `json:"dinas,omitempty" db:"Dinas"`
KelompokObyek models.NullableString `json:"kelompok_obyek,omitempty" db:"Kelompok_obyek"`
KodeTarif models.NullableString `json:"kode_tarif,omitempty" db:"Kode_tarif"`
Tarif models.NullableString `json:"tarif,omitempty" db:"Tarif"`
Satuan models.NullableString `json:"satuan,omitempty" db:"Satuan"`
TarifOvertime models.NullableString `json:"tarif_overtime,omitempty" db:"Tarif_overtime"`
SatuanOvertime models.NullableString `json:"satuan_overtime,omitempty" db:"Satuan_overtime"`
RekeningPokok models.NullableString `json:"rekening_pokok,omitempty" db:"Rekening_pokok"`
RekeningDenda models.NullableString `json:"rekening_denda,omitempty" db:"Rekening_denda"`
Uraian1 models.NullableString `json:"uraian_1,omitempty" db:"Uraian_1"`
Uraian2 models.NullableString `json:"uraian_2,omitempty" db:"Uraian_2"`
Uraian3 models.NullableString `json:"uraian_3,omitempty" db:"Uraian_3"`
}
// Custom JSON marshaling untuk Retribusi agar NULL values tidak muncul di response

View File

@@ -17,7 +17,7 @@ type RujukanData struct {
Keluhan string `json:"keluhan"`
NoKunjungan string `json:"noKunjungan"`
Pelayanan PelayananData `json:"pelayanan"`
Peserta PesertaData `json:"peserta"`
Peserta DataPeserta `json:"peserta"`
PoliRujukan PoliRujukanData `json:"poliRujukan"`
ProvPerujuk ProvPerujukData `json:"provPerujuk"`
TglKunjungan string `json:"tglKunjungan"`
@@ -43,7 +43,7 @@ type ProvPerujukData struct {
Nama string `json:"nama"`
}
type PesertaData struct {
type DataPeserta struct {
NoKartu string `json:"noKartu"`
NIK string `json:"nik"`
Nama string `json:"nama"`

View File

@@ -5,12 +5,15 @@ import (
"api-service/internal/database"
authHandlers "api-service/internal/handlers/auth"
healthcheckHandlers "api-service/internal/handlers/healthcheck"
pesertaHandlers "api-service/internal/handlers/peserta"
retribusiHandlers "api-service/internal/handlers/retribusi"
rujukanHandlers "api-service/internal/handlers/rujukan"
"api-service/internal/middleware"
services "api-service/internal/services/auth"
"api-service/pkg/logger"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)
@@ -42,7 +45,19 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine {
sistem.GET("/health", healthCheckHandler.CheckHealth)
// Swagger UI route
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
router.GET("/swagger/*any", ginSwagger.WrapHandler(
swaggerFiles.Handler, // Models configuration
ginSwagger.DefaultModelsExpandDepth(-1), // Hide models completely
// ginSwagger.DefaultModelExpandDepth(0), // Keep individual models collapsed
// General UI configuration
// ginSwagger.DocExpansion("none"), // Collapse all sections
ginSwagger.DeepLinking(true), // Enable deep linking
// ginSwagger.PersistAuthorization(true), // Persist auth between refreshes
// // Optional: Custom title
// ginSwagger.InstanceName("API Service v1.0.0"),
))
// API v1 group
v1 := router.Group("/api/v1")
@@ -66,37 +81,39 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine {
// ============= PUBLISHED ROUTES ===============================================
// // Rujukan routes
// rujukanHandler := rujukan.NewVClaimHandler(rujukan.VClaimHandlerConfig{
// BpjsConfig: cfg.Bpjs,
// Logger: *logger.Default(),
// Validator: nil,
// })
// rujukanGroup := v1.Group("/rujukan")
// rujukanGroup.GET("/nokartu/:nokartu", rujukanHandler.GetRujukanBynokartu)
// rujukanGroup.GET("/norujukan/:norujukan", rujukanHandler.GetRujukanBynorujukan)
// Participant eligibility information (peserta) routes
pesertaHandler := pesertaHandlers.NewPesertaHandler(pesertaHandlers.PesertaHandlerConfig{
BpjsConfig: cfg.Bpjs,
Logger: *logger.Default(),
Validator: validator.New(),
})
pesertaGroup := v1.Group("/peserta")
pesertaGroup.GET("/Peserta/nokartu/:nokartu", pesertaHandler.GetBynokartu)
pesertaGroup.GET("/Peserta/nik/:nik", pesertaHandler.GetBynik)
// // Peserta routes
// pesertaHandler := peserta.NewVClaimHandler(peserta.VClaimHandlerConfig{
// BpjsConfig: cfg.Bpjs,
// Logger: *logger.Default(),
// Validator: nil,
// })
// pesertaGroup := v1.Group("/peserta")
// pesertaGroup.GET("/nokartu/:nokartu/tglSEP/:tglsep", pesertaHandler.GetPesertaBynokartu)
// pesertaGroup.GET("/nik/:nik/tglSEP/:tglsep", pesertaHandler.GetPesertaBynik)
// Rujukan management endpoints (rujukan) routes
rujukanHandler := rujukanHandlers.NewRujukanHandler(rujukanHandlers.RujukanHandlerConfig{
BpjsConfig: cfg.Bpjs,
Logger: *logger.Default(),
Validator: validator.New(),
})
rujukanGroup := v1.Group("/rujukan")
rujukanGroup.POST("/Rujukan/:norujukan", rujukanHandler.CreateRujukan)
rujukanGroup.PUT("/Rujukan/:norujukan", rujukanHandler.UpdateRujukan)
rujukanGroup.DELETE("/Rujukan/:norujukan", rujukanHandler.DeleteRujukan)
rujukanGroup.POST("/Rujukanbalik/:norujukan", rujukanHandler.CreateRujukanbalik)
rujukanGroup.PUT("/Rujukanbalik/:norujukan", rujukanHandler.UpdateRujukanbalik)
rujukanGroup.DELETE("/Rujukanbalik/:norujukan", rujukanHandler.DeleteRujukanbalik)
// // Sep routes
// sepHandler := sep.NewVClaimHandler(sep.VClaimHandlerConfig{
// BpjsConfig: cfg.Bpjs,
// Logger: *logger.Default(),
// Validator: nil,
// })
// sepGroup := v1.Group("/sep")
// sepGroup.GET("/sep/:nosep", sepHandler.GetSepSep)
// sepGroup.POST("/sep", sepHandler.CreateSepSep)
// sepGroup.PUT("/sep/:nosep", sepHandler.UpdateSepSep)
// sepGroup.DELETE("/sep/:nosep", sepHandler.DeleteSepSep)
// Search for rujukan endpoints (search) routes
searchHandler := rujukanHandlers.NewSearchHandler(rujukanHandlers.SearchHandlerConfig{
BpjsConfig: cfg.Bpjs,
Logger: *logger.Default(),
Validator: validator.New(),
})
searchGroup := v1.Group("/search")
searchGroup.GET("/bynorujukan/:norujukan", searchHandler.GetBynorujukan)
searchGroup.GET("/bynokartu/:nokartu", searchHandler.GetBynokartu)
// // Retribusi endpoints
// retribusiHandler := retribusiHandlers.NewRetribusiHandler()

View File

@@ -19,12 +19,22 @@ services:
description: "Participant eligibility information"
handler_folder: "peserta"
handler_file: "peserta.go"
handler_name: "Peserta"
functions:
bynokartu:
methods: ["GET"]
path: "/peserta/:nokartu"
get_routes: "/Peserta/nokartu/:nokartu"
# post_routes: "/Peserta/nokartu/:nokartu"
# put_routes: "/Peserta/nokartu/:nokartu"
# delete_routes: "/Peserta/nokartu/:nokartu"
get_path: "/peserta/:nokartu"
# post_path: "/peserta"
# put_path: "/peserta/:nokartu"
# delete_path: "/peserta/:nokartu"
model: "PesertaRequest"
response_model: "PesertaResponse"
request_model: "RujukanRequest"
description: "Get participant eligibility information by card number"
summary: "Get Participant Info by No Kartu"
tags: ["Peserta"]
@@ -35,8 +45,17 @@ services:
bynik:
methods: ["GET"]
path: "/peserta/nik/:nik"
get_routes: "/Peserta/nik/:nik"
# post_routes: "/Peserta/nik/:nik"
# put_routes: "/Peserta/nik/:nik"
# delete_routes: "/Peserta/nik/:nik"
get_path: "/peserta/nik/:nik"
# post_path: "/peserta"
# put_path: "/peserta/nik/:nik"
# delete_path: "/peserta/nik/:nik"
model: "PesertaRequest"
response_model: "PesertaResponse"
request_model: "PesertaRequest"
description: "Get participant eligibility information by NIK"
summary: "Get Participant Info by NIK"
tags: ["Peserta"]
@@ -48,23 +67,42 @@ services:
description: "Rujukan management endpoints"
handler_folder: "rujukan"
handler_file: "rujukan.go"
handler_name: "Rujukan"
functions:
rujukan:
methods: ["POST", "PUT", "DELETE"]
path: "/Rujukan"
# get_routes: "/Rujukan/:norujukan"
post_routes: "/Rujukan/:norujukan"
put_routes: "/Rujukan/:norujukan"
delete_routes: "/Rujukan/:norujukan"
# get_path: "/Rujukan/:norujukan"
post_path: "/Rujukan"
put_path: "/Rujukan/:norujukan"
delete_path: "/Rujukan/:norujukan"
model: "RujukanRequest"
response_model: "RujukanResponse"
request_model: "RujukanRequest"
description: "Manage rujukan"
summary: "Rujukan Management"
tags: ["Rujukan"]
require_auth: true
cache_enabled: true
cache_ttl: 180
rujukan:
methods: ["GET"]
path: "/Rujukan"
rujukanbalik:
methods: ["POST", "PUT", "DELETE"]
path: "/Rujukanbalik"
# get_routes: "/Rujukanbalik/:norujukan"
post_routes: "/Rujukanbalik/:norujukan"
put_routes: "/Rujukanbalik/:norujukan"
delete_routes: "/Rujukanbalik/:norujukan"
# get_path: "/Rujukanbalik/:norujukan"
post_path: "/Rujukanbalik"
put_path: "/Rujukanbalik/:norujukan"
delete_path: "/Rujukanbalik/:norujukan"
model: "RujukanRequest"
response_model: "RujukanResponse"
request_model: "RujukanRequest"
description: "Manage rujukan"
summary: "Rujukan Management"
tags: ["Rujukan"]
@@ -76,12 +114,22 @@ services:
description: "Search for rujukan endpoints"
handler_folder: "rujukan"
handler_file: "search.go"
handler_name: "Search"
functions:
bynorujukan:
methods: ["GET"]
path: "/Rujukan/:norujukan"
get_routes: "/bynorujukan/:norujukan"
# post_routes: "/bynorujukan/:norujukan"
# put_routes: "/bynorujukan/:norujukan"
# delete_routes: "/bynorujukan/:norujukan"
get_path: "/Rujukan/:norujukan"
# post_path: "/Rujukan"
# put_path: "/Rujukan/:norujukan"
# delete_path: "/Rujukan/:norujukan"
model: "RujukanRequest"
response_model: "RujukanResponse"
request_model: "RujukanRequest"
description: "Get rujukan by nomor rujukan"
summary: "Rujukan Management"
tags: ["Rujukan"]
@@ -92,11 +140,21 @@ services:
bynokartu:
methods: ["GET"]
path: "/Rujukan/:nokartu"
get_routes: "/bynokartu/:nokartu"
# post_routes: "/bynokartu/:nokartu"
# put_routes: "/bynokartu/:nokartu"
# delete_routes: "/bynokartu/:nokartu"
get_path: "/Rujukan/:nokartu"
# post_path: "/Rujukan"
# put_path: "/Rujukan/:nokartu"
# delete_path: "/Rujukan/:nokartu"
model: "RujukanRequest"
response_model: "RujukanResponse"
request_model: "RujukanRequest"
description: "Get rujukan by card number"
summary: "Rujukan Management"
tags: ["Rujukan"]
require_auth: true
cache_enabled: true
cache_ttl: 300

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3230
tools/bpjs/newgenerete Normal file

File diff suppressed because it is too large Load Diff