From 8311311615510bcd14eb239bd55f56c80061edea Mon Sep 17 00:00:00 2001 From: Meninjar Mulyono Date: Wed, 3 Sep 2025 19:24:55 +0700 Subject: [PATCH] Perbaikan tool bpjs --- docs/docs.go | 598 ++++++++++++++++---- docs/swagger.json | 593 +++++++++++++++---- docs/swagger.yaml | 397 ++++++++++--- internal/handlers/vclaim/peserta/peserta.go | 87 +-- internal/handlers/vclaim/rujukan/rujukan.go | 261 +++++++++ internal/models/vclaim/rujukan/rujukan.go | 101 +++- internal/routes/v1/routes.go | 15 +- internal/services/bpjs/vclaimBridge.go | 39 ++ services-config-bpjs.yaml | 24 + tools/bpjs/generate-handler.go | 98 +++- tools/bpjs/generete | 98 +++- 11 files changed, 1896 insertions(+), 415 deletions(-) create mode 100644 internal/handlers/vclaim/rujukan/rujukan.go diff --git a/docs/docs.go b/docs/docs.go index d744e8ad..0a0937d6 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,4 +1,5 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT +// Code generated by swaggo/swag. DO NOT EDIT. + package docs import "github.com/swaggo/swag" @@ -24,6 +25,210 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/Peserta/nik/nik/:nik/tglSEP/:tglsep": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Get participant eligibility information by NIK", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Peserta" + ], + "summary": "Get PesertaBynik data", + "parameters": [ + { + "type": "string", + "description": "Request ID for tracking", + "name": "X-Request-ID", + "in": "header" + }, + { + "type": "string", + "example": "\"example_value\"", + "description": "nik", + "name": "nik", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved PesertaBynik data", + "schema": { + "$ref": "#/definitions/internal_handlers_vclaim_peserta.PesertaResponse" + } + }, + "400": { + "description": "Bad request - invalid parameters", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "401": { + "description": "Unauthorized - invalid API credentials", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "404": { + "description": "Not found - PesertaBynik not found", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + } + } + } + }, + "/Rujukan/:norujukan": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Manage rujukan", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Rujukan" + ], + "summary": "Get RujukanBynorujukan data", + "parameters": [ + { + "type": "string", + "description": "Request ID for tracking", + "name": "X-Request-ID", + "in": "header" + }, + { + "type": "string", + "example": "\"example_value\"", + "description": "norujukan", + "name": "norujukan", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved RujukanBynorujukan data", + "schema": { + "$ref": "#/definitions/api-service_internal_models_vclaim_rujukan.RujukanResponse" + } + }, + "400": { + "description": "Bad request - invalid parameters", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "401": { + "description": "Unauthorized - invalid API credentials", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "404": { + "description": "Not found - RujukanBynorujukan not found", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + } + } + } + }, + "/Rujukan/Peserta/:nokartu": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Manage rujukan", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Rujukan" + ], + "summary": "Get RujukanBynokartu data", + "parameters": [ + { + "type": "string", + "description": "Request ID for tracking", + "name": "X-Request-ID", + "in": "header" + }, + { + "type": "string", + "example": "\"example_value\"", + "description": "nokartu", + "name": "nokartu", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved RujukanBynokartu data", + "schema": { + "$ref": "#/definitions/api-service_internal_models_vclaim_rujukan.RujukanResponse" + } + }, + "400": { + "description": "Bad request - invalid parameters", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "401": { + "description": "Unauthorized - invalid API credentials", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "404": { + "description": "Not found - RujukanBynokartu not found", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + } + } + } + }, "/api/v1/auth/login": { "post": { "description": "Authenticate user with username and password to receive JWT token", @@ -699,7 +904,7 @@ const docTemplate = `{ } } }, - "/peserta/:nokartu": { + "/peserta/nokartu/:nokartu/tglSEP/:tglsep": { "get": { "security": [ { @@ -737,7 +942,7 @@ const docTemplate = `{ "200": { "description": "Successfully retrieved PesertaBynokartu data", "schema": { - "$ref": "#/definitions/api-service_internal_models_vclaim_peserta.PesertaResponse" + "$ref": "#/definitions/internal_handlers_vclaim_peserta.PesertaResponse" } }, "400": { @@ -767,74 +972,6 @@ const docTemplate = `{ } } }, - "/peserta/nik/:nik": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Get participant eligibility information by NIK", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Peserta" - ], - "summary": "Get PesertaBynik data", - "parameters": [ - { - "type": "string", - "description": "Request ID for tracking", - "name": "X-Request-ID", - "in": "header" - }, - { - "type": "string", - "example": "\"example_value\"", - "description": "nik", - "name": "nik", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "Successfully retrieved PesertaBynik data", - "schema": { - "$ref": "#/definitions/api-service_internal_models_vclaim_peserta.PesertaResponse" - } - }, - "400": { - "description": "Bad request - invalid parameters", - "schema": { - "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" - } - }, - "401": { - "description": "Unauthorized - invalid API credentials", - "schema": { - "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" - } - }, - "404": { - "description": "Not found - PesertaBynik not found", - "schema": { - "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" - } - }, - "500": { - "description": "Internal server error", - "schema": { - "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" - } - } - } - } - }, "/sep": { "post": { "security": [ @@ -1564,43 +1701,55 @@ const docTemplate = `{ "api-service_internal_models_vclaim_peserta.PesertaData": { "type": "object", "properties": { - "aktif": { - "type": "string" - }, - "asuransi": { - "type": "string" - }, "cob": { - "type": "string" + "type": "object", + "properties": { + "nmAsuransi": {}, + "noAsuransi": {}, + "tglTAT": {}, + "tglTMT": {} + } }, - "kdCabang": { - "type": "string" + "hakKelas": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } }, - "kdJnsPst": { - "type": "string" + "informasi": { + "type": "object", + "properties": { + "dinsos": {}, + "eSEP": {}, + "noSKTM": {}, + "prolanisPRB": { + "type": "string" + } + } }, - "ketAktif": { - "type": "string" - }, - "klsRawat": { - "type": "string" + "jenisPeserta": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } }, "mr": { "type": "object", "properties": { - "nmMR": { - "type": "string" - }, "noMR": { "type": "string" }, - "sex": { - "type": "string" - }, - "tglLahir": { - "type": "string" - }, - "tglMeninggal": { + "noTelepon": { "type": "string" } } @@ -1611,28 +1760,38 @@ const docTemplate = `{ "nik": { "type": "string" }, - "nmCabang": { - "type": "string" - }, - "nmJnsPst": { - "type": "string" - }, "noKartu": { "type": "string" }, - "noKtp": { - "type": "string" - }, - "noSKTM": { - "type": "string" - }, "pisa": { "type": "string" }, + "provUmum": { + "type": "object", + "properties": { + "kdProvider": { + "type": "string" + }, + "nmProvider": { + "type": "string" + } + } + }, "sex": { "type": "string" }, "statusPeserta": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } + }, + "tglCetakKartu": { "type": "string" }, "tglLahir": { @@ -1644,21 +1803,93 @@ const docTemplate = `{ "tglTMT": { "type": "string" }, - "tglTunggak": { + "umur": { + "type": "object", + "properties": { + "umurSaatPelayanan": { + "type": "string" + }, + "umurSekarang": { + "type": "string" + } + } + } + } + }, + "api-service_internal_models_vclaim_rujukan.RujukanData": { + "type": "object", + "properties": { + "diagnosa": { + "type": "object", + "properties": { + "kdDiagnosa": { + "type": "string" + }, + "nmDiagnosa": { + "type": "string" + } + } + }, + "kelasRawat": { + "type": "string" + }, + "nama": { + "type": "string" + }, + "noKartu": { + "type": "string" + }, + "noRujukan": { + "type": "string" + }, + "pelayanan": { + "type": "string" + }, + "poliRujukan": { + "type": "object", + "properties": { + "kdPoli": { + "type": "string" + }, + "nmPoli": { + "type": "string" + } + } + }, + "provPerujuk": { + "type": "object", + "properties": { + "kdProvider": { + "type": "string" + }, + "nmProvider": { + "type": "string" + } + } + }, + "statusRujukan": { + "type": "string" + }, + "tglRujukan": { "type": "string" } } }, - "api-service_internal_models_vclaim_peserta.PesertaResponse": { + "api-service_internal_models_vclaim_rujukan.RujukanResponse": { "type": "object", "properties": { "data": { - "$ref": "#/definitions/api-service_internal_models_vclaim_peserta.PesertaData" + "$ref": "#/definitions/api-service_internal_models_vclaim_rujukan.RujukanData" + }, + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/api-service_internal_models_vclaim_rujukan.RujukanData" + } }, "message": { "type": "string" }, - "metaData": {}, "request_id": { "type": "string" }, @@ -1836,6 +2067,145 @@ const docTemplate = `{ } } }, + "internal_handlers_vclaim_peserta.PesertaData": { + "type": "object", + "properties": { + "cob": { + "type": "object", + "properties": { + "nmAsuransi": {}, + "noAsuransi": {}, + "tglTAT": {}, + "tglTMT": {} + } + }, + "hakKelas": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } + }, + "informasi": { + "type": "object", + "properties": { + "dinsos": {}, + "eSEP": {}, + "noSKTM": {}, + "prolanisPRB": { + "type": "string" + } + } + }, + "jenisPeserta": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } + }, + "mr": { + "type": "object", + "properties": { + "noMR": { + "type": "string" + }, + "noTelepon": { + "type": "string" + } + } + }, + "nama": { + "type": "string" + }, + "nik": { + "type": "string" + }, + "noKartu": { + "type": "string" + }, + "pisa": { + "type": "string" + }, + "provUmum": { + "type": "object", + "properties": { + "kdProvider": { + "type": "string" + }, + "nmProvider": { + "type": "string" + } + } + }, + "sex": { + "type": "string" + }, + "statusPeserta": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } + }, + "tglCetakKartu": { + "type": "string" + }, + "tglLahir": { + "type": "string" + }, + "tglTAT": { + "type": "string" + }, + "tglTMT": { + "type": "string" + }, + "umur": { + "type": "object", + "properties": { + "umurSaatPelayanan": { + "type": "string" + }, + "umurSekarang": { + "type": "string" + } + } + } + } + }, + "internal_handlers_vclaim_peserta.PesertaResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/internal_handlers_vclaim_peserta.PesertaData" + }, + "message": { + "type": "string" + }, + "metaData": {}, + "request_id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + } + }, "sql.NullString": { "type": "object", "properties": { @@ -1873,8 +2243,6 @@ var SwaggerInfo = &swag.Spec{ Description: "A comprehensive Go API service with Swagger documentation", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, - LeftDelim: "{{", - RightDelim: "}}", } func init() { diff --git a/docs/swagger.json b/docs/swagger.json index 74ce1526..1c847b7d 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -22,6 +22,210 @@ "host": "localhost:8080", "basePath": "/api/v1", "paths": { + "/Peserta/nik/nik/:nik/tglSEP/:tglsep": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Get participant eligibility information by NIK", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Peserta" + ], + "summary": "Get PesertaBynik data", + "parameters": [ + { + "type": "string", + "description": "Request ID for tracking", + "name": "X-Request-ID", + "in": "header" + }, + { + "type": "string", + "example": "\"example_value\"", + "description": "nik", + "name": "nik", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved PesertaBynik data", + "schema": { + "$ref": "#/definitions/internal_handlers_vclaim_peserta.PesertaResponse" + } + }, + "400": { + "description": "Bad request - invalid parameters", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "401": { + "description": "Unauthorized - invalid API credentials", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "404": { + "description": "Not found - PesertaBynik not found", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + } + } + } + }, + "/Rujukan/:norujukan": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Manage rujukan", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Rujukan" + ], + "summary": "Get RujukanBynorujukan data", + "parameters": [ + { + "type": "string", + "description": "Request ID for tracking", + "name": "X-Request-ID", + "in": "header" + }, + { + "type": "string", + "example": "\"example_value\"", + "description": "norujukan", + "name": "norujukan", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved RujukanBynorujukan data", + "schema": { + "$ref": "#/definitions/api-service_internal_models_vclaim_rujukan.RujukanResponse" + } + }, + "400": { + "description": "Bad request - invalid parameters", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "401": { + "description": "Unauthorized - invalid API credentials", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "404": { + "description": "Not found - RujukanBynorujukan not found", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + } + } + } + }, + "/Rujukan/Peserta/:nokartu": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Manage rujukan", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Rujukan" + ], + "summary": "Get RujukanBynokartu data", + "parameters": [ + { + "type": "string", + "description": "Request ID for tracking", + "name": "X-Request-ID", + "in": "header" + }, + { + "type": "string", + "example": "\"example_value\"", + "description": "nokartu", + "name": "nokartu", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved RujukanBynokartu data", + "schema": { + "$ref": "#/definitions/api-service_internal_models_vclaim_rujukan.RujukanResponse" + } + }, + "400": { + "description": "Bad request - invalid parameters", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "401": { + "description": "Unauthorized - invalid API credentials", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "404": { + "description": "Not found - RujukanBynokartu not found", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" + } + } + } + } + }, "/api/v1/auth/login": { "post": { "description": "Authenticate user with username and password to receive JWT token", @@ -697,7 +901,7 @@ } } }, - "/peserta/:nokartu": { + "/peserta/nokartu/:nokartu/tglSEP/:tglsep": { "get": { "security": [ { @@ -735,7 +939,7 @@ "200": { "description": "Successfully retrieved PesertaBynokartu data", "schema": { - "$ref": "#/definitions/api-service_internal_models_vclaim_peserta.PesertaResponse" + "$ref": "#/definitions/internal_handlers_vclaim_peserta.PesertaResponse" } }, "400": { @@ -765,74 +969,6 @@ } } }, - "/peserta/nik/:nik": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Get participant eligibility information by NIK", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Peserta" - ], - "summary": "Get PesertaBynik data", - "parameters": [ - { - "type": "string", - "description": "Request ID for tracking", - "name": "X-Request-ID", - "in": "header" - }, - { - "type": "string", - "example": "\"example_value\"", - "description": "nik", - "name": "nik", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "Successfully retrieved PesertaBynik data", - "schema": { - "$ref": "#/definitions/api-service_internal_models_vclaim_peserta.PesertaResponse" - } - }, - "400": { - "description": "Bad request - invalid parameters", - "schema": { - "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" - } - }, - "401": { - "description": "Unauthorized - invalid API credentials", - "schema": { - "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" - } - }, - "404": { - "description": "Not found - PesertaBynik not found", - "schema": { - "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" - } - }, - "500": { - "description": "Internal server error", - "schema": { - "$ref": "#/definitions/api-service_internal_models.ErrorResponseBpjs" - } - } - } - } - }, "/sep": { "post": { "security": [ @@ -1562,43 +1698,55 @@ "api-service_internal_models_vclaim_peserta.PesertaData": { "type": "object", "properties": { - "aktif": { - "type": "string" - }, - "asuransi": { - "type": "string" - }, "cob": { - "type": "string" + "type": "object", + "properties": { + "nmAsuransi": {}, + "noAsuransi": {}, + "tglTAT": {}, + "tglTMT": {} + } }, - "kdCabang": { - "type": "string" + "hakKelas": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } }, - "kdJnsPst": { - "type": "string" + "informasi": { + "type": "object", + "properties": { + "dinsos": {}, + "eSEP": {}, + "noSKTM": {}, + "prolanisPRB": { + "type": "string" + } + } }, - "ketAktif": { - "type": "string" - }, - "klsRawat": { - "type": "string" + "jenisPeserta": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } }, "mr": { "type": "object", "properties": { - "nmMR": { - "type": "string" - }, "noMR": { "type": "string" }, - "sex": { - "type": "string" - }, - "tglLahir": { - "type": "string" - }, - "tglMeninggal": { + "noTelepon": { "type": "string" } } @@ -1609,28 +1757,38 @@ "nik": { "type": "string" }, - "nmCabang": { - "type": "string" - }, - "nmJnsPst": { - "type": "string" - }, "noKartu": { "type": "string" }, - "noKtp": { - "type": "string" - }, - "noSKTM": { - "type": "string" - }, "pisa": { "type": "string" }, + "provUmum": { + "type": "object", + "properties": { + "kdProvider": { + "type": "string" + }, + "nmProvider": { + "type": "string" + } + } + }, "sex": { "type": "string" }, "statusPeserta": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } + }, + "tglCetakKartu": { "type": "string" }, "tglLahir": { @@ -1642,21 +1800,93 @@ "tglTMT": { "type": "string" }, - "tglTunggak": { + "umur": { + "type": "object", + "properties": { + "umurSaatPelayanan": { + "type": "string" + }, + "umurSekarang": { + "type": "string" + } + } + } + } + }, + "api-service_internal_models_vclaim_rujukan.RujukanData": { + "type": "object", + "properties": { + "diagnosa": { + "type": "object", + "properties": { + "kdDiagnosa": { + "type": "string" + }, + "nmDiagnosa": { + "type": "string" + } + } + }, + "kelasRawat": { + "type": "string" + }, + "nama": { + "type": "string" + }, + "noKartu": { + "type": "string" + }, + "noRujukan": { + "type": "string" + }, + "pelayanan": { + "type": "string" + }, + "poliRujukan": { + "type": "object", + "properties": { + "kdPoli": { + "type": "string" + }, + "nmPoli": { + "type": "string" + } + } + }, + "provPerujuk": { + "type": "object", + "properties": { + "kdProvider": { + "type": "string" + }, + "nmProvider": { + "type": "string" + } + } + }, + "statusRujukan": { + "type": "string" + }, + "tglRujukan": { "type": "string" } } }, - "api-service_internal_models_vclaim_peserta.PesertaResponse": { + "api-service_internal_models_vclaim_rujukan.RujukanResponse": { "type": "object", "properties": { "data": { - "$ref": "#/definitions/api-service_internal_models_vclaim_peserta.PesertaData" + "$ref": "#/definitions/api-service_internal_models_vclaim_rujukan.RujukanData" + }, + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/api-service_internal_models_vclaim_rujukan.RujukanData" + } }, "message": { "type": "string" }, - "metaData": {}, "request_id": { "type": "string" }, @@ -1834,6 +2064,145 @@ } } }, + "internal_handlers_vclaim_peserta.PesertaData": { + "type": "object", + "properties": { + "cob": { + "type": "object", + "properties": { + "nmAsuransi": {}, + "noAsuransi": {}, + "tglTAT": {}, + "tglTMT": {} + } + }, + "hakKelas": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } + }, + "informasi": { + "type": "object", + "properties": { + "dinsos": {}, + "eSEP": {}, + "noSKTM": {}, + "prolanisPRB": { + "type": "string" + } + } + }, + "jenisPeserta": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } + }, + "mr": { + "type": "object", + "properties": { + "noMR": { + "type": "string" + }, + "noTelepon": { + "type": "string" + } + } + }, + "nama": { + "type": "string" + }, + "nik": { + "type": "string" + }, + "noKartu": { + "type": "string" + }, + "pisa": { + "type": "string" + }, + "provUmum": { + "type": "object", + "properties": { + "kdProvider": { + "type": "string" + }, + "nmProvider": { + "type": "string" + } + } + }, + "sex": { + "type": "string" + }, + "statusPeserta": { + "type": "object", + "properties": { + "keterangan": { + "type": "string" + }, + "kode": { + "type": "string" + } + } + }, + "tglCetakKartu": { + "type": "string" + }, + "tglLahir": { + "type": "string" + }, + "tglTAT": { + "type": "string" + }, + "tglTMT": { + "type": "string" + }, + "umur": { + "type": "object", + "properties": { + "umurSaatPelayanan": { + "type": "string" + }, + "umurSekarang": { + "type": "string" + } + } + } + } + }, + "internal_handlers_vclaim_peserta.PesertaResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/internal_handlers_vclaim_peserta.PesertaData" + }, + "message": { + "type": "string" + }, + "metaData": {}, + "request_id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + } + }, "sql.NullString": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 4101dea2..03796b60 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -308,52 +308,67 @@ definitions: type: object api-service_internal_models_vclaim_peserta.PesertaData: properties: - aktif: - type: string - asuransi: - type: string cob: - type: string - kdCabang: - type: string - kdJnsPst: - type: string - ketAktif: - type: string - klsRawat: - type: string + properties: + nmAsuransi: {} + noAsuransi: {} + tglTAT: {} + tglTMT: {} + type: object + hakKelas: + properties: + keterangan: + type: string + kode: + type: string + type: object + informasi: + properties: + dinsos: {} + eSEP: {} + noSKTM: {} + prolanisPRB: + type: string + type: object + jenisPeserta: + properties: + keterangan: + type: string + kode: + type: string + type: object mr: properties: - nmMR: - type: string noMR: type: string - sex: - type: string - tglLahir: - type: string - tglMeninggal: + noTelepon: type: string type: object nama: type: string nik: type: string - nmCabang: - type: string - nmJnsPst: - type: string noKartu: type: string - noKtp: - type: string - noSKTM: - type: string pisa: type: string + provUmum: + properties: + kdProvider: + type: string + nmProvider: + type: string + type: object sex: type: string statusPeserta: + properties: + keterangan: + type: string + kode: + type: string + type: object + tglCetakKartu: type: string tglLahir: type: string @@ -361,16 +376,62 @@ definitions: type: string tglTMT: type: string - tglTunggak: + umur: + properties: + umurSaatPelayanan: + type: string + umurSekarang: + type: string + type: object + type: object + api-service_internal_models_vclaim_rujukan.RujukanData: + properties: + diagnosa: + properties: + kdDiagnosa: + type: string + nmDiagnosa: + type: string + type: object + kelasRawat: + type: string + nama: + type: string + noKartu: + type: string + noRujukan: + type: string + pelayanan: + type: string + poliRujukan: + properties: + kdPoli: + type: string + nmPoli: + type: string + type: object + provPerujuk: + properties: + kdProvider: + type: string + nmProvider: + type: string + type: object + statusRujukan: + type: string + tglRujukan: type: string type: object - api-service_internal_models_vclaim_peserta.PesertaResponse: + api-service_internal_models_vclaim_rujukan.RujukanResponse: properties: data: - $ref: '#/definitions/api-service_internal_models_vclaim_peserta.PesertaData' + $ref: '#/definitions/api-service_internal_models_vclaim_rujukan.RujukanData' + list: + items: + $ref: '#/definitions/api-service_internal_models_vclaim_rujukan.RujukanData' + type: array message: type: string - metaData: {} request_id: type: string status: @@ -492,6 +553,98 @@ definitions: - ppkRujukan - tglRujukan type: object + internal_handlers_vclaim_peserta.PesertaData: + properties: + cob: + properties: + nmAsuransi: {} + noAsuransi: {} + tglTAT: {} + tglTMT: {} + type: object + hakKelas: + properties: + keterangan: + type: string + kode: + type: string + type: object + informasi: + properties: + dinsos: {} + eSEP: {} + noSKTM: {} + prolanisPRB: + type: string + type: object + jenisPeserta: + properties: + keterangan: + type: string + kode: + type: string + type: object + mr: + properties: + noMR: + type: string + noTelepon: + type: string + type: object + nama: + type: string + nik: + type: string + noKartu: + type: string + pisa: + type: string + provUmum: + properties: + kdProvider: + type: string + nmProvider: + type: string + type: object + sex: + type: string + statusPeserta: + properties: + keterangan: + type: string + kode: + type: string + type: object + tglCetakKartu: + type: string + tglLahir: + type: string + tglTAT: + type: string + tglTMT: + type: string + umur: + properties: + umurSaatPelayanan: + type: string + umurSekarang: + type: string + type: object + type: object + internal_handlers_vclaim_peserta.PesertaResponse: + properties: + data: + $ref: '#/definitions/internal_handlers_vclaim_peserta.PesertaData' + message: + type: string + metaData: {} + request_id: + type: string + status: + type: string + timestamp: + type: string + type: object sql.NullString: properties: string: @@ -522,6 +675,138 @@ info: title: API Service version: 1.0.0 paths: + /Peserta/nik/nik/:nik/tglSEP/:tglsep: + get: + consumes: + - application/json + description: Get participant eligibility information by NIK + parameters: + - description: Request ID for tracking + in: header + name: X-Request-ID + type: string + - description: nik + example: '"example_value"' + in: path + name: nik + required: true + type: string + produces: + - application/json + responses: + "200": + description: Successfully retrieved PesertaBynik data + schema: + $ref: '#/definitions/internal_handlers_vclaim_peserta.PesertaResponse' + "400": + description: Bad request - invalid parameters + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + "401": + description: Unauthorized - invalid API credentials + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + "404": + description: Not found - PesertaBynik not found + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + "500": + description: Internal server error + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + security: + - ApiKeyAuth: [] + summary: Get PesertaBynik data + tags: + - Peserta + /Rujukan/:norujukan: + get: + consumes: + - application/json + description: Manage rujukan + parameters: + - description: Request ID for tracking + in: header + name: X-Request-ID + type: string + - description: norujukan + example: '"example_value"' + in: path + name: norujukan + required: true + type: string + produces: + - application/json + responses: + "200": + description: Successfully retrieved RujukanBynorujukan data + schema: + $ref: '#/definitions/api-service_internal_models_vclaim_rujukan.RujukanResponse' + "400": + description: Bad request - invalid parameters + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + "401": + description: Unauthorized - invalid API credentials + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + "404": + description: Not found - RujukanBynorujukan not found + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + "500": + description: Internal server error + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + security: + - ApiKeyAuth: [] + summary: Get RujukanBynorujukan data + tags: + - Rujukan + /Rujukan/Peserta/:nokartu: + get: + consumes: + - application/json + description: Manage rujukan + parameters: + - description: Request ID for tracking + in: header + name: X-Request-ID + type: string + - description: nokartu + example: '"example_value"' + in: path + name: nokartu + required: true + type: string + produces: + - application/json + responses: + "200": + description: Successfully retrieved RujukanBynokartu data + schema: + $ref: '#/definitions/api-service_internal_models_vclaim_rujukan.RujukanResponse' + "400": + description: Bad request - invalid parameters + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + "401": + description: Unauthorized - invalid API credentials + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + "404": + description: Not found - RujukanBynokartu not found + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + "500": + description: Internal server error + schema: + $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' + security: + - ApiKeyAuth: [] + summary: Get RujukanBynokartu data + tags: + - Rujukan /api/v1/auth/login: post: consumes: @@ -967,7 +1252,7 @@ paths: summary: Generate token directly tags: - Token - /peserta/:nokartu: + /peserta/nokartu/:nokartu/tglSEP/:tglsep: get: consumes: - application/json @@ -989,7 +1274,7 @@ paths: "200": description: Successfully retrieved PesertaBynokartu data schema: - $ref: '#/definitions/api-service_internal_models_vclaim_peserta.PesertaResponse' + $ref: '#/definitions/internal_handlers_vclaim_peserta.PesertaResponse' "400": description: Bad request - invalid parameters schema: @@ -1011,50 +1296,6 @@ paths: summary: Get PesertaBynokartu data tags: - Peserta - /peserta/nik/:nik: - get: - consumes: - - application/json - description: Get participant eligibility information by NIK - parameters: - - description: Request ID for tracking - in: header - name: X-Request-ID - type: string - - description: nik - example: '"example_value"' - in: path - name: nik - required: true - type: string - produces: - - application/json - responses: - "200": - description: Successfully retrieved PesertaBynik data - schema: - $ref: '#/definitions/api-service_internal_models_vclaim_peserta.PesertaResponse' - "400": - description: Bad request - invalid parameters - schema: - $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' - "401": - description: Unauthorized - invalid API credentials - schema: - $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' - "404": - description: Not found - PesertaBynik not found - schema: - $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' - "500": - description: Internal server error - schema: - $ref: '#/definitions/api-service_internal_models.ErrorResponseBpjs' - security: - - ApiKeyAuth: [] - summary: Get PesertaBynik data - tags: - - Peserta /sep: post: consumes: diff --git a/internal/handlers/vclaim/peserta/peserta.go b/internal/handlers/vclaim/peserta/peserta.go index 709277da..b5dd65c8 100644 --- a/internal/handlers/vclaim/peserta/peserta.go +++ b/internal/handlers/vclaim/peserta/peserta.go @@ -12,6 +12,7 @@ import ( "api-service/internal/config" "api-service/internal/models" + "api-service/internal/models/vclaim/peserta" services "api-service/internal/services/bpjs" "api-service/pkg/logger" @@ -20,62 +21,6 @@ import ( "github.com/google/uuid" ) -// PesertaData represents peserta information from BPJS -type PesertaData struct { - NoKartu string `json:"noKartu"` - NIK string `json:"nik"` - Nama string `json:"nama"` - Pisa string `json:"pisa"` - Sex string `json:"sex"` - TanggalLahir string `json:"tglLahir"` - TglCetakKartu string `json:"tglCetakKartu"` - TglTAT string `json:"tglTAT"` - TglTMT string `json:"tglTMT"` - StatusPeserta struct { - Kode string `json:"kode"` - Keterangan string `json:"keterangan"` - } `json:"statusPeserta"` - ProvUmum struct { - KdProvider string `json:"kdProvider"` - NmProvider string `json:"nmProvider"` - } `json:"provUmum"` - JenisPeserta struct { - Kode string `json:"kode"` - Keterangan string `json:"keterangan"` - } `json:"jenisPeserta"` - HakKelas struct { - Kode string `json:"kode"` - Keterangan string `json:"keterangan"` - } `json:"hakKelas"` - Umur struct { - UmurSekarang string `json:"umurSekarang"` - UmurSaatPelayanan string `json:"umurSaatPelayanan"` - } `json:"umur"` - Informasi struct { - Dinsos interface{} `json:"dinsos"` - ProlanisPRB string `json:"prolanisPRB"` - NoSKTM interface{} `json:"noSKTM"` - ESEP interface{} `json:"eSEP"` - } `json:"informasi"` - Cob struct { - NoAsuransi interface{} `json:"noAsuransi"` - NmAsuransi interface{} `json:"nmAsuransi"` - TglTMT interface{} `json:"tglTMT"` - TglTAT interface{} `json:"tglTAT"` - } `json:"cob"` - MR struct { - NoMR string `json:"noMR"` - NoTelepon string `json:"noTelepon"` - } `json:"mr,omitempty"` -} - -// PesertaResponse represents peserta API response -type PesertaResponse struct { - models.BaseResponse - Data *PesertaData `json:"data,omitempty"` - MetaData interface{} `json:"metaData,omitempty"` -} - // VClaimHandler handles VClaim BPJS services type VClaimHandler struct { service services.VClaimService @@ -115,7 +60,7 @@ func NewVClaimHandler(cfg VClaimHandlerConfig) *VClaimHandler { // @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials" // @Failure 404 {object} models.ErrorResponseBpjs "Not found - PesertaBynokartu not found" // @Failure 500 {object} models.ErrorResponseBpjs "Internal server error" -// @Router /peserta/:nokartu [get] +// @Router /peserta/nokartu/:nokartu/tglSEP/:tglsep [get] func (h *VClaimHandler) GetPesertaBynokartu(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() @@ -152,7 +97,7 @@ func (h *VClaimHandler) GetPesertaBynokartu(c *gin.Context) { } // Call service method - var response PesertaResponse + var response peserta.PesertaResponse endpoint := "/Peserta/nokartu/:nokartu/tglSEP/:tglsep" @@ -177,7 +122,7 @@ func (h *VClaimHandler) GetPesertaBynokartu(c *gin.Context) { // Map the raw response response.MetaData = resp.MetaData if resp.Response != nil { - response.Data = &PesertaData{} + response.Data = &peserta.PesertaData{} if respStr, ok := resp.Response.(string); ok { // Decrypt the response string consID, secretKey, _, tstamp, _ := h.config.SetHeader() @@ -223,7 +168,7 @@ func (h *VClaimHandler) GetPesertaBynokartu(c *gin.Context) { // @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials" // @Failure 404 {object} models.ErrorResponseBpjs "Not found - PesertaBynik not found" // @Failure 500 {object} models.ErrorResponseBpjs "Internal server error" -// @Router /peserta/nik/:nik [get] +// @Router /Peserta/nik/nik/:nik/tglSEP/:tglsep [get] func (h *VClaimHandler) GetPesertaBynik(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() @@ -237,7 +182,7 @@ func (h *VClaimHandler) GetPesertaBynik(c *gin.Context) { h.logger.Info("Processing GetPesertaBynik request", map[string]interface{}{ "request_id": requestID, - "endpoint": "/peserta/nik/:nik", + "endpoint": "/peserta/nik/:nik/tglSEP/:tglsep", "nik": c.Param("nik"), }) @@ -245,6 +190,7 @@ func (h *VClaimHandler) GetPesertaBynik(c *gin.Context) { // Extract path parameters nik := c.Param("nik") + tglsep := c.Param("tglsep") if nik == "" { h.logger.Error("Missing required parameter nik", map[string]interface{}{ @@ -258,13 +204,26 @@ func (h *VClaimHandler) GetPesertaBynik(c *gin.Context) { }) return } + if tglsep == "" { + h.logger.Error("Missing required parameter Tanggal SEP", map[string]interface{}{ + "request_id": requestID, + }) + + c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{ + Status: "error", + Message: "Missing required parameter Tanggal SEP", + RequestID: requestID, + }) + return + } // Call service method - var response PesertaResponse + var response peserta.PesertaResponse - endpoint := "/peserta/nik/:nik" + endpoint := "/Peserta/nik/:nik/tglSEP/:tglsep" endpoint = strings.Replace(endpoint, ":nik", nik, 1) + endpoint = strings.Replace(endpoint, ":tglsep", tglsep, 1) resp, err := h.service.GetRawResponse(ctx, endpoint) if err != nil { @@ -284,7 +243,7 @@ func (h *VClaimHandler) GetPesertaBynik(c *gin.Context) { // Map the raw response response.MetaData = resp.MetaData if resp.Response != nil { - response.Data = &PesertaData{} + response.Data = &peserta.PesertaData{} if respStr, ok := resp.Response.(string); ok { // Decrypt the response string consID, secretKey, _, tstamp, _ := h.config.SetHeader() diff --git a/internal/handlers/vclaim/rujukan/rujukan.go b/internal/handlers/vclaim/rujukan/rujukan.go new file mode 100644 index 00000000..a483556d --- /dev/null +++ b/internal/handlers/vclaim/rujukan/rujukan.go @@ -0,0 +1,261 @@ +// Service: VClaim (vclaim) +// Description: BPJS VClaim service for eligibility and SEP management + +package rujukan + +import ( + "context" + "encoding/json" + "net/http" + "strings" + "time" + + "api-service/internal/config" + "api-service/internal/models" + "api-service/internal/models/vclaim/rujukan" + services "api-service/internal/services/bpjs" + "api-service/pkg/logger" + + "github.com/gin-gonic/gin" + "github.com/go-playground/validator/v10" + "github.com/google/uuid" +) + +// VClaimHandler handles VClaim BPJS services +type VClaimHandler struct { + service services.VClaimService + validator *validator.Validate + logger logger.Logger + config config.BpjsConfig +} + +// VClaimHandlerConfig contains configuration for VClaimHandler +type VClaimHandlerConfig struct { + BpjsConfig config.BpjsConfig + Logger logger.Logger + Validator *validator.Validate +} + +// NewVClaimHandler creates a new VClaimHandler +func NewVClaimHandler(cfg VClaimHandlerConfig) *VClaimHandler { + return &VClaimHandler{ + service: services.NewService(cfg.BpjsConfig), + validator: cfg.Validator, + logger: cfg.Logger, + config: cfg.BpjsConfig, + } +} + +// GetRujukanBynorujukan godoc +// @Summary Get RujukanBynorujukan data +// @Description Manage 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 RujukanBynorujukan 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 - RujukanBynorujukan not found" +// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error" +// @Router /Rujukan/:norujukan [get] +func (h *VClaimHandler) GetRujukanBynorujukan(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 GetRujukanBynorujukan 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/RS/:norujukan" + + endpoint = strings.Replace(endpoint, ":norujukan", norujukan, 1) + + resp, err := h.service.GetRawResponse(ctx, endpoint) + if err != nil { + h.logger.Error("Failed to get PesertaBynokartu", 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 pesertaMap, exists := respMap["rujukan"]; exists { + pesertaBytes, _ := json.Marshal(pesertaMap) + json.Unmarshal(pesertaBytes, 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) +} + +// GetRujukanBynokartu godoc +// @Summary Get RujukanBynokartu data +// @Description Manage rujukan +// @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 RujukanBynokartu 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 - RujukanBynokartu not found" +// @Failure 500 {object} models.ErrorResponseBpjs "Internal server error" +// @Router /Rujukan/Peserta/:nokartu [get] +func (h *VClaimHandler) GetRujukanBynokartu(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 GetRujukanBynokartu request", map[string]interface{}{ + "request_id": requestID, + "endpoint": "/Rujukan/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 rujukan.RujukanResponse + + endpoint := "/Rujukan/RS/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 PesertaBynokartu", 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 pesertaMap, exists := respMap["rujukan"]; exists { + pesertaBytes, _ := json.Marshal(pesertaMap) + json.Unmarshal(pesertaBytes, 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) +} diff --git a/internal/models/vclaim/rujukan/rujukan.go b/internal/models/vclaim/rujukan/rujukan.go index 78e83afe..2379ed73 100644 --- a/internal/models/vclaim/rujukan/rujukan.go +++ b/internal/models/vclaim/rujukan/rujukan.go @@ -1,4 +1,4 @@ -package vclaim +package rujukan import "api-service/internal/models" @@ -13,30 +13,87 @@ type RujukanRequest struct { // RujukanData represents rujukan information type RujukanData struct { - NoRujukan string `json:"noRujukan"` - TglRujukan string `json:"tglRujukan"` - NoKartu string `json:"noKartu"` - Nama string `json:"nama"` - KelasRawat string `json:"kelasRawat"` - Diagnosa struct { - KodeDiagnosa string `json:"kdDiagnosa"` - NamaDiagnosa string `json:"nmDiagnosa"` - } `json:"diagnosa"` - PoliRujukan struct { - KodePoli string `json:"kdPoli"` - NamaPoli string `json:"nmPoli"` - } `json:"poliRujukan"` - ProvPerujuk struct { - KodeProvider string `json:"kdProvider"` - NamaProvider string `json:"nmProvider"` - } `json:"provPerujuk"` - PelayananInfo string `json:"pelayanan"` - StatusRujukan string `json:"statusRujukan"` + Diagnosa DiagnosaData `json:"diagnosa"` + Keluhan string `json:"keluhan"` + NoKunjungan string `json:"noKunjungan"` + Pelayanan PelayananData `json:"pelayanan"` + Peserta PesertaData `json:"peserta"` + PoliRujukan PoliRujukanData `json:"poliRujukan"` + ProvPerujuk ProvPerujukData `json:"provPerujuk"` + TglKunjungan string `json:"tglKunjungan"` +} + +type DiagnosaData struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type PelayananData struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type PoliRujukanData struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type ProvPerujukData struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} + +type PesertaData struct { + NoKartu string `json:"noKartu"` + NIK string `json:"nik"` + Nama string `json:"nama"` + Pisa string `json:"pisa"` + Sex string `json:"sex"` + TanggalLahir string `json:"tglLahir"` + TglCetakKartu string `json:"tglCetakKartu"` + TglTAT string `json:"tglTAT"` + TglTMT string `json:"tglTMT"` + StatusPeserta struct { + Kode string `json:"kode"` + Keterangan string `json:"keterangan"` + } `json:"statusPeserta"` + ProvUmum struct { + KdProvider string `json:"kdProvider"` + NmProvider string `json:"nmProvider"` + } `json:"provUmum"` + JenisPeserta struct { + Kode string `json:"kode"` + Keterangan string `json:"keterangan"` + } `json:"jenisPeserta"` + HakKelas struct { + Kode string `json:"kode"` + Keterangan string `json:"keterangan"` + } `json:"hakKelas"` + Umur struct { + UmurSekarang string `json:"umurSekarang"` + UmurSaatPelayanan string `json:"umurSaatPelayanan"` + } `json:"umur"` + Informasi struct { + Dinsos interface{} `json:"dinsos"` + ProlanisPRB interface{} `json:"prolanisPRB"` + NoSKTM interface{} `json:"noSKTM"` + } `json:"informasi"` + Cob struct { + NoAsuransi interface{} `json:"noAsuransi"` + NmAsuransi interface{} `json:"nmAsuransi"` + TglTMT interface{} `json:"tglTMT"` + TglTAT interface{} `json:"tglTAT"` + } `json:"cob"` + MR struct { + NoMR string `json:"noMR"` + NoTelepon interface{} `json:"noTelepon"` + } `json:"mr"` } // RujukanResponse represents rujukan API response type RujukanResponse struct { models.BaseResponse - Data *RujukanData `json:"data,omitempty"` - List []RujukanData `json:"list,omitempty"` + Data *RujukanData `json:"data,omitempty"` + List []RujukanData `json:"list,omitempty"` + MetaData interface{} `json:"metaData,omitempty"` } diff --git a/internal/routes/v1/routes.go b/internal/routes/v1/routes.go index 0b0d56cc..952e8192 100644 --- a/internal/routes/v1/routes.go +++ b/internal/routes/v1/routes.go @@ -7,6 +7,7 @@ import ( healthcheckHandlers "api-service/internal/handlers/healthcheck" retribusiHandlers "api-service/internal/handlers/retribusi" "api-service/internal/handlers/vclaim/peserta" + "api-service/internal/handlers/vclaim/rujukan" "api-service/internal/handlers/vclaim/sep" "api-service/internal/middleware" services "api-service/internal/services/auth" @@ -68,6 +69,16 @@ 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) + // Peserta routes pesertaHandler := peserta.NewVClaimHandler(peserta.VClaimHandlerConfig{ BpjsConfig: cfg.Bpjs, @@ -75,8 +86,8 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine { Validator: nil, }) pesertaGroup := v1.Group("/peserta") - pesertaGroup.GET("/peserta/:nokartu/tglSEP/:tglsep", pesertaHandler.GetPesertaBynokartu) - pesertaGroup.GET("/peserta/nik/:nik", pesertaHandler.GetPesertaBynik) + pesertaGroup.GET("/nokartu/:nokartu/tglSEP/:tglsep", pesertaHandler.GetPesertaBynokartu) + pesertaGroup.GET("/nik/:nik/tglSEP/:tglsep", pesertaHandler.GetPesertaBynik) // Sep routes sepHandler := sep.NewVClaimHandler(sep.VClaimHandlerConfig{ diff --git a/internal/services/bpjs/vclaimBridge.go b/internal/services/bpjs/vclaimBridge.go index 6ef09324..9dfd7645 100644 --- a/internal/services/bpjs/vclaimBridge.go +++ b/internal/services/bpjs/vclaimBridge.go @@ -25,7 +25,9 @@ type VClaimService interface { Delete(ctx context.Context, endpoint string, result interface{}) error GetRawResponse(ctx context.Context, endpoint string) (*ResponDTOVclaim, error) PostRawResponse(ctx context.Context, endpoint string, payload interface{}) (*ResponDTOVclaim, error) + PutRawResponse(ctx context.Context, endpoint string, payload interface{}) (*ResponDTOVclaim, error) PatchRawResponse(ctx context.Context, endpoint string, payload interface{}) (*ResponDTOVclaim, error) + DeleteRawResponse(ctx context.Context, endpoint string) (*ResponDTOVclaim, error) } // Service struct for VClaim service @@ -351,6 +353,43 @@ func (s *Service) PatchRawResponse(ctx context.Context, endpoint string, payload return s.processResponse(res) } +// PutRawResponse returns raw response without mapping +func (s *Service) PutRawResponse(ctx context.Context, endpoint string, payload interface{}) (*ResponDTOVclaim, error) { + var buf bytes.Buffer + if payload != nil { + if err := json.NewEncoder(&buf).Encode(payload); err != nil { + return nil, fmt.Errorf("failed to encode payload: %w", err) + } + } + + req, err := s.prepareRequest(ctx, http.MethodPut, endpoint, &buf) + if err != nil { + return nil, err + } + + res, err := s.httpClient.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to execute PUT request: %w", err) + } + + return s.processResponse(res) +} + +// DeleteRawResponse returns raw response without mapping +func (s *Service) DeleteRawResponse(ctx context.Context, endpoint string) (*ResponDTOVclaim, error) { + req, err := s.prepareRequest(ctx, http.MethodDelete, endpoint, nil) + if err != nil { + return nil, err + } + + res, err := s.httpClient.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to execute DELETE request: %w", err) + } + + return s.processResponse(res) +} + // mapToResult maps the final response to the result interface func mapToResult(resp *ResponDTOVclaim, result interface{}) error { respBytes, err := json.Marshal(resp) diff --git a/services-config-bpjs.yaml b/services-config-bpjs.yaml index 1614fad4..bd5d0629 100644 --- a/services-config-bpjs.yaml +++ b/services-config-bpjs.yaml @@ -53,3 +53,27 @@ services: require_auth: true cache_enabled: true cache_ttl: 180 + rujukan: + bynorujukan: + 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: + methods: ["GET"] + get_path: "/Rujukan/:nokartu" + model: "RujukanRequest" + response_model: "RujukanResponse" + description: "Manage rujukan" + summary: "Rujukan Management" + tags: ["Rujukan"] + require_auth: true + cache_enabled: true + cache_ttl: 300 + \ No newline at end of file diff --git a/tools/bpjs/generate-handler.go b/tools/bpjs/generate-handler.go index f87c00e5..8432f6ff 100644 --- a/tools/bpjs/generate-handler.go +++ b/tools/bpjs/generate-handler.go @@ -42,6 +42,7 @@ type Service struct { Name string `yaml:"name"` Category string `yaml:"category"` Package string `yaml:"package"` + SubPackage string `yaml:"sub_package"` Description string `yaml:"description"` BaseURL string `yaml:"base_url"` Timeout int `yaml:"timeout"` @@ -113,6 +114,7 @@ type EndpointData struct { PatchPath string Model string ResponseModel string + DataModel string // Data model name (e.g., PesertaData) Description string Summary string Tags []string @@ -142,6 +144,7 @@ package {{.Package}} import ( "context" + "encoding/json" "strings" "net/http" "time" @@ -244,9 +247,9 @@ func (h *{{$.ServiceName}}Handler) Get{{.Name}}(c *gin.Context) { {{range .PathParams}} endpoint = strings.Replace(endpoint, ":{{.}}", {{.}}, 1) {{end}} - err := h.service.Get(ctx, endpoint, &response) + rawResponse, err := h.service.GetRawResponse(ctx, endpoint) {{else}} - err := h.service.Get(ctx, "{{.GetPath}}", &response) + rawResponse, err := h.service.GetRawResponse(ctx, "{{.GetPath}}") {{end}} if err != nil { {{if $.HasLogger}} @@ -263,7 +266,25 @@ func (h *{{$.ServiceName}}Handler) Get{{.Name}}(c *gin.Context) { return } - // Ensure response has proper fields + // Map raw response to structured data + var data {{.ModelPackage}}.{{.DataModel}} + if err := json.Unmarshal(rawResponse, &data); err != nil { + {{if $.HasLogger}} + h.logger.Error("Failed to unmarshal {{.Name}} data", map[string]interface{}{ + "error": err.Error(), + "request_id": requestID, + }) + {{end}} + c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ + Status: "error", + Message: "Failed to process response data", + RequestID: requestID, + }) + return + } + + // Set response data + response.Data = data response.Status = "success" response.RequestID = requestID c.JSON(http.StatusOK, response) @@ -336,7 +357,7 @@ func (h *{{$.ServiceName}}Handler) Create{{.Name}}(c *gin.Context) { // Call service method var response {{.ModelPackage}}.{{.ResponseModel}} - err := h.service.Post(ctx, "{{.PostPath}}", &req, &response) + rawResponse, err := h.service.PostRawResponse(ctx, "{{.PostPath}}", &req) if err != nil { {{if $.HasLogger}} h.logger.Error("Failed to create {{.Name}}", map[string]interface{}{ @@ -352,7 +373,25 @@ func (h *{{$.ServiceName}}Handler) Create{{.Name}}(c *gin.Context) { return } - // Ensure response has proper fields + // Map raw response to structured data + var data {{.ModelPackage}}.{{.DataModel}} + if err := json.Unmarshal(rawResponse, &data); err != nil { + {{if $.HasLogger}} + h.logger.Error("Failed to unmarshal {{.Name}} data", map[string]interface{}{ + "error": err.Error(), + "request_id": requestID, + }) + {{end}} + c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ + Status: "error", + Message: "Failed to process response data", + RequestID: requestID, + }) + return + } + + // Set response data + response.Data = data response.Status = "success" response.RequestID = requestID c.JSON(http.StatusCreated, response) @@ -448,9 +487,9 @@ func (h *{{$.ServiceName}}Handler) Update{{.Name}}(c *gin.Context) { {{range .PathParams}} endpoint = strings.Replace(endpoint, ":{{.}}", {{.}}, 1) {{end}} - err := h.service.Put(ctx, endpoint, &req, &response) + rawResponse, err := h.service.PutRawResponse(ctx, endpoint, &req) {{else}} - err := h.service.Put(ctx, "{{.PutPath}}", &req, &response) + rawResponse, err := h.service.PutRawResponse(ctx, "{{.PutPath}}", &req) {{end}} if err != nil { {{if $.HasLogger}} @@ -467,7 +506,25 @@ func (h *{{$.ServiceName}}Handler) Update{{.Name}}(c *gin.Context) { return } - // Ensure response has proper fields + // Map raw response to structured data + var data {{.ModelPackage}}.{{.DataModel}} + if err := json.Unmarshal(rawResponse, &data); err != nil { + {{if $.HasLogger}} + h.logger.Error("Failed to unmarshal {{.Name}} data", map[string]interface{}{ + "error": err.Error(), + "request_id": requestID, + }) + {{end}} + c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ + Status: "error", + Message: "Failed to process response data", + RequestID: requestID, + }) + return + } + + // Set response data + response.Data = data response.Status = "success" response.RequestID = requestID c.JSON(http.StatusOK, response) @@ -530,9 +587,9 @@ func (h *{{$.ServiceName}}Handler) Delete{{.Name}}(c *gin.Context) { {{range .PathParams}} endpoint = strings.Replace(endpoint, ":{{.}}", {{.}}, 1) {{end}} - err := h.service.Delete(ctx, endpoint, &response) + rawResponse, err := h.service.DeleteRawResponse(ctx, endpoint) {{else}} - err := h.service.Delete(ctx, "{{.DeletePath}}", &response) + rawResponse, err := h.service.DeleteRawResponse(ctx, "{{.DeletePath}}") {{end}} if err != nil { {{if $.HasLogger}} @@ -549,7 +606,25 @@ func (h *{{$.ServiceName}}Handler) Delete{{.Name}}(c *gin.Context) { return } - // Ensure response has proper fields + // Map raw response to structured data + var data {{.ModelPackage}}.{{.DataModel}} + if err := json.Unmarshal(rawResponse, &data); err != nil { + {{if $.HasLogger}} + h.logger.Error("Failed to unmarshal {{.Name}} data", map[string]interface{}{ + "error": err.Error(), + "request_id": requestID, + }) + {{end}} + c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ + Status: "error", + Message: "Failed to process response data", + RequestID: requestID, + }) + return + } + + // Set response data + response.Data = data response.Status = "success" response.RequestID = requestID c.JSON(http.StatusOK, response) @@ -940,6 +1015,7 @@ func processEndpoint(name string, endpoint Endpoint, endpointGroup string) Endpo PatchPath: endpoint.PatchPath, Model: endpoint.Model, ResponseModel: endpoint.ResponseModel, + DataModel: strings.Replace(endpoint.ResponseModel, "Response", "Data", 1), Description: endpoint.Description, Summary: endpoint.Summary, Tags: endpoint.Tags, diff --git a/tools/bpjs/generete b/tools/bpjs/generete index f87c00e5..8432f6ff 100644 --- a/tools/bpjs/generete +++ b/tools/bpjs/generete @@ -42,6 +42,7 @@ type Service struct { Name string `yaml:"name"` Category string `yaml:"category"` Package string `yaml:"package"` + SubPackage string `yaml:"sub_package"` Description string `yaml:"description"` BaseURL string `yaml:"base_url"` Timeout int `yaml:"timeout"` @@ -113,6 +114,7 @@ type EndpointData struct { PatchPath string Model string ResponseModel string + DataModel string // Data model name (e.g., PesertaData) Description string Summary string Tags []string @@ -142,6 +144,7 @@ package {{.Package}} import ( "context" + "encoding/json" "strings" "net/http" "time" @@ -244,9 +247,9 @@ func (h *{{$.ServiceName}}Handler) Get{{.Name}}(c *gin.Context) { {{range .PathParams}} endpoint = strings.Replace(endpoint, ":{{.}}", {{.}}, 1) {{end}} - err := h.service.Get(ctx, endpoint, &response) + rawResponse, err := h.service.GetRawResponse(ctx, endpoint) {{else}} - err := h.service.Get(ctx, "{{.GetPath}}", &response) + rawResponse, err := h.service.GetRawResponse(ctx, "{{.GetPath}}") {{end}} if err != nil { {{if $.HasLogger}} @@ -263,7 +266,25 @@ func (h *{{$.ServiceName}}Handler) Get{{.Name}}(c *gin.Context) { return } - // Ensure response has proper fields + // Map raw response to structured data + var data {{.ModelPackage}}.{{.DataModel}} + if err := json.Unmarshal(rawResponse, &data); err != nil { + {{if $.HasLogger}} + h.logger.Error("Failed to unmarshal {{.Name}} data", map[string]interface{}{ + "error": err.Error(), + "request_id": requestID, + }) + {{end}} + c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ + Status: "error", + Message: "Failed to process response data", + RequestID: requestID, + }) + return + } + + // Set response data + response.Data = data response.Status = "success" response.RequestID = requestID c.JSON(http.StatusOK, response) @@ -336,7 +357,7 @@ func (h *{{$.ServiceName}}Handler) Create{{.Name}}(c *gin.Context) { // Call service method var response {{.ModelPackage}}.{{.ResponseModel}} - err := h.service.Post(ctx, "{{.PostPath}}", &req, &response) + rawResponse, err := h.service.PostRawResponse(ctx, "{{.PostPath}}", &req) if err != nil { {{if $.HasLogger}} h.logger.Error("Failed to create {{.Name}}", map[string]interface{}{ @@ -352,7 +373,25 @@ func (h *{{$.ServiceName}}Handler) Create{{.Name}}(c *gin.Context) { return } - // Ensure response has proper fields + // Map raw response to structured data + var data {{.ModelPackage}}.{{.DataModel}} + if err := json.Unmarshal(rawResponse, &data); err != nil { + {{if $.HasLogger}} + h.logger.Error("Failed to unmarshal {{.Name}} data", map[string]interface{}{ + "error": err.Error(), + "request_id": requestID, + }) + {{end}} + c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ + Status: "error", + Message: "Failed to process response data", + RequestID: requestID, + }) + return + } + + // Set response data + response.Data = data response.Status = "success" response.RequestID = requestID c.JSON(http.StatusCreated, response) @@ -448,9 +487,9 @@ func (h *{{$.ServiceName}}Handler) Update{{.Name}}(c *gin.Context) { {{range .PathParams}} endpoint = strings.Replace(endpoint, ":{{.}}", {{.}}, 1) {{end}} - err := h.service.Put(ctx, endpoint, &req, &response) + rawResponse, err := h.service.PutRawResponse(ctx, endpoint, &req) {{else}} - err := h.service.Put(ctx, "{{.PutPath}}", &req, &response) + rawResponse, err := h.service.PutRawResponse(ctx, "{{.PutPath}}", &req) {{end}} if err != nil { {{if $.HasLogger}} @@ -467,7 +506,25 @@ func (h *{{$.ServiceName}}Handler) Update{{.Name}}(c *gin.Context) { return } - // Ensure response has proper fields + // Map raw response to structured data + var data {{.ModelPackage}}.{{.DataModel}} + if err := json.Unmarshal(rawResponse, &data); err != nil { + {{if $.HasLogger}} + h.logger.Error("Failed to unmarshal {{.Name}} data", map[string]interface{}{ + "error": err.Error(), + "request_id": requestID, + }) + {{end}} + c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ + Status: "error", + Message: "Failed to process response data", + RequestID: requestID, + }) + return + } + + // Set response data + response.Data = data response.Status = "success" response.RequestID = requestID c.JSON(http.StatusOK, response) @@ -530,9 +587,9 @@ func (h *{{$.ServiceName}}Handler) Delete{{.Name}}(c *gin.Context) { {{range .PathParams}} endpoint = strings.Replace(endpoint, ":{{.}}", {{.}}, 1) {{end}} - err := h.service.Delete(ctx, endpoint, &response) + rawResponse, err := h.service.DeleteRawResponse(ctx, endpoint) {{else}} - err := h.service.Delete(ctx, "{{.DeletePath}}", &response) + rawResponse, err := h.service.DeleteRawResponse(ctx, "{{.DeletePath}}") {{end}} if err != nil { {{if $.HasLogger}} @@ -549,7 +606,25 @@ func (h *{{$.ServiceName}}Handler) Delete{{.Name}}(c *gin.Context) { return } - // Ensure response has proper fields + // Map raw response to structured data + var data {{.ModelPackage}}.{{.DataModel}} + if err := json.Unmarshal(rawResponse, &data); err != nil { + {{if $.HasLogger}} + h.logger.Error("Failed to unmarshal {{.Name}} data", map[string]interface{}{ + "error": err.Error(), + "request_id": requestID, + }) + {{end}} + c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ + Status: "error", + Message: "Failed to process response data", + RequestID: requestID, + }) + return + } + + // Set response data + response.Data = data response.Status = "success" response.RequestID = requestID c.JSON(http.StatusOK, response) @@ -940,6 +1015,7 @@ func processEndpoint(name string, endpoint Endpoint, endpointGroup string) Endpo PatchPath: endpoint.PatchPath, Model: endpoint.Model, ResponseModel: endpoint.ResponseModel, + DataModel: strings.Replace(endpoint.ResponseModel, "Response", "Data", 1), Description: endpoint.Description, Summary: endpoint.Summary, Tags: endpoint.Tags,