Perubahan tool dan dokumentasi

This commit is contained in:
2025-08-22 15:49:30 +07:00
parent ce7d12f20c
commit 9838c48eab
14 changed files with 4077 additions and 329 deletions

View File

@@ -352,19 +352,19 @@ const docTemplate = `{
"400": {
"description": "Invalid ID format",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"404": {
"description": "Retribusi not found",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -409,19 +409,19 @@ const docTemplate = `{
"400": {
"description": "Bad request or validation error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"404": {
"description": "Retribusi not found",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -457,19 +457,19 @@ const docTemplate = `{
"400": {
"description": "Invalid ID format",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"404": {
"description": "Retribusi not found",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -545,13 +545,13 @@ const docTemplate = `{
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -589,13 +589,82 @@ const docTemplate = `{
"400": {
"description": "Bad request or validation error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
}
},
"/api/v1/retribusis/dynamic": {
"get": {
"description": "Returns retribusis with advanced dynamic filtering like Directus",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"retribusi"
],
"summary": "Get retribusi with dynamic filtering",
"parameters": [
{
"type": "string",
"description": "Fields to select (e.g., fields=*.*)",
"name": "fields",
"in": "query"
},
{
"type": "string",
"description": "Dynamic filters (e.g., filter[Jenis][_eq]=value)",
"name": "filter[column][operator]",
"in": "query"
},
{
"type": "string",
"description": "Sort fields (e.g., sort=date_created,-Jenis)",
"name": "sort",
"in": "query"
},
{
"type": "integer",
"default": 10,
"description": "Limit",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"default": 0,
"description": "Offset",
"name": "offset",
"in": "query"
}
],
"responses": {
"200": {
"description": "Success response",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.RetribusiGetResponse"
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -626,13 +695,13 @@ const docTemplate = `{
"200": {
"description": "Statistics data",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.AggregateData"
"$ref": "#/definitions/api-service_internal_models.AggregateData"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -735,9 +804,287 @@ const docTemplate = `{
}
}
}
},
"/sep": {
"put": {
"description": "Update an existing Surat Eligibilitas Peserta",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs"
],
"summary": "Update an existing SEP",
"parameters": [
{
"description": "SEP update request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.SepPutRequest"
}
}
],
"responses": {
"200": {
"description": "SEP updated successfully",
"schema": {
"$ref": "#/definitions/models.SepResponse"
}
},
"400": {
"description": "Invalid request",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
},
"post": {
"description": "Create a new Surat Eligibilitas Peserta",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs"
],
"summary": "Create a new SEP",
"parameters": [
{
"description": "SEP creation request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.SepPostRequest"
}
}
],
"responses": {
"200": {
"description": "SEP created successfully",
"schema": {
"$ref": "#/definitions/models.SepResponse"
}
},
"400": {
"description": "Invalid request",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
}
},
"/sep/{noSep}": {
"get": {
"description": "Retrieve a Surat Eligibilitas Peserta by noSep",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs"
],
"summary": "Get an existing SEP",
"parameters": [
{
"type": "string",
"description": "No SEP",
"name": "noSep",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Data SEP retrieved successfully",
"schema": {
"$ref": "#/definitions/models.SepResponse"
}
},
"400": {
"description": "Invalid request",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
},
"delete": {
"description": "Delete a Surat Eligibilitas Peserta by noSep",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs"
],
"summary": "Delete an existing SEP",
"parameters": [
{
"type": "string",
"description": "No SEP",
"name": "noSep",
"in": "path",
"required": true
},
{
"type": "string",
"description": "User",
"name": "user",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "SEP deleted successfully",
"schema": {
"$ref": "#/definitions/models.SepResponse"
}
},
"400": {
"description": "Invalid request",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
}
}
},
"definitions": {
"api-service_internal_models.AggregateData": {
"type": "object",
"properties": {
"by_dinas": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"by_jenis": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"by_status": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"created_today": {
"type": "integer"
},
"last_updated": {
"type": "string"
},
"total_active": {
"type": "integer"
},
"total_draft": {
"type": "integer"
},
"total_inactive": {
"type": "integer"
},
"updated_today": {
"type": "integer"
}
}
},
"api-service_internal_models.ErrorResponse": {
"type": "object",
"properties": {
"code": {
"type": "integer"
},
"error": {
"type": "string"
},
"message": {
"type": "string"
},
"timestamp": {
"type": "string"
}
}
},
"api-service_internal_models.MetaResponse": {
"type": "object",
"properties": {
"current_page": {
"type": "integer"
},
"has_next": {
"type": "boolean"
},
"has_prev": {
"type": "boolean"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
},
"total": {
"type": "integer"
},
"total_pages": {
"type": "integer"
}
}
},
"api-service_internal_models.NullableInt32": {
"type": "object",
"properties": {
"int32": {
"type": "integer"
},
"valid": {
"type": "boolean"
}
}
},
"api-service_internal_models_auth.LoginRequest": {
"type": "object",
"required": [
@@ -784,101 +1131,6 @@ const docTemplate = `{
}
}
},
"api-service_internal_models_retribusi.AggregateData": {
"type": "object",
"properties": {
"by_dinas": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"by_jenis": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"by_status": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"created_today": {
"type": "integer"
},
"last_updated": {
"type": "string"
},
"total_active": {
"type": "integer"
},
"total_draft": {
"type": "integer"
},
"total_inactive": {
"type": "integer"
},
"updated_today": {
"type": "integer"
}
}
},
"api-service_internal_models_retribusi.ErrorResponse": {
"type": "object",
"properties": {
"code": {
"type": "integer"
},
"error": {
"type": "string"
},
"message": {
"type": "string"
},
"timestamp": {
"type": "string"
}
}
},
"api-service_internal_models_retribusi.MetaResponse": {
"type": "object",
"properties": {
"current_page": {
"type": "integer"
},
"has_next": {
"type": "boolean"
},
"has_prev": {
"type": "boolean"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
},
"total": {
"type": "integer"
},
"total_pages": {
"type": "integer"
}
}
},
"api-service_internal_models_retribusi.NullableInt32": {
"type": "object",
"properties": {
"int32": {
"type": "integer"
},
"valid": {
"type": "boolean"
}
}
},
"api-service_internal_models_retribusi.Retribusi": {
"type": "object",
"properties": {
@@ -919,7 +1171,7 @@ const docTemplate = `{
"$ref": "#/definitions/sql.NullString"
},
"sort": {
"$ref": "#/definitions/api-service_internal_models_retribusi.NullableInt32"
"$ref": "#/definitions/api-service_internal_models.NullableInt32"
},
"status": {
"type": "string"
@@ -1069,10 +1321,10 @@ const docTemplate = `{
"type": "string"
},
"meta": {
"$ref": "#/definitions/api-service_internal_models_retribusi.MetaResponse"
"$ref": "#/definitions/api-service_internal_models.MetaResponse"
},
"summary": {
"$ref": "#/definitions/api-service_internal_models_retribusi.AggregateData"
"$ref": "#/definitions/api-service_internal_models.AggregateData"
}
}
},
@@ -1163,6 +1415,10 @@ const docTemplate = `{
}
}
},
"gin.H": {
"type": "object",
"additionalProperties": {}
},
"models.DiagnosaResponse": {
"type": "object",
"properties": {
@@ -1175,6 +1431,329 @@ const docTemplate = `{
}
}
},
"models.Flag": {
"type": "object",
"required": [
"cob"
],
"properties": {
"cob": {
"type": "string"
}
}
},
"models.Jaminan": {
"type": "object",
"required": [
"lakaLantas"
],
"properties": {
"lakaLantas": {
"type": "string"
},
"noLP": {
"type": "string"
},
"penjamin": {
"$ref": "#/definitions/models.Penjamin"
}
}
},
"models.KlsRawatPost": {
"type": "object",
"required": [
"klsRawatHak"
],
"properties": {
"klsRawatHak": {
"type": "string"
},
"klsRawatNaik": {
"type": "string"
},
"pembiayaan": {
"type": "string"
},
"penanggungJawab": {
"type": "string"
}
}
},
"models.KlsRawatPut": {
"type": "object",
"properties": {
"klsRawatHak": {
"type": "string"
},
"klsRawatNaik": {
"type": "string"
},
"pembiayaan": {
"type": "string"
},
"penanggungJawab": {
"type": "string"
}
}
},
"models.LokasiLaka": {
"type": "object",
"properties": {
"kdKabupaten": {
"type": "string"
},
"kdKecamatan": {
"type": "string"
},
"kdPropinsi": {
"type": "string"
}
}
},
"models.Penjamin": {
"type": "object",
"properties": {
"keterangan": {
"type": "string"
},
"suplesi": {
"$ref": "#/definitions/models.Suplesi"
},
"tglKejadian": {
"type": "string"
}
}
},
"models.Poli": {
"type": "object",
"required": [
"eksekutif"
],
"properties": {
"eksekutif": {
"type": "string"
},
"tujuan": {
"type": "string"
}
}
},
"models.Rujukan": {
"type": "object",
"required": [
"asalRujukan",
"noRujukan",
"ppkRujukan",
"tglRujukan"
],
"properties": {
"asalRujukan": {
"type": "string"
},
"noRujukan": {
"type": "string"
},
"ppkRujukan": {
"type": "string"
},
"tglRujukan": {
"type": "string"
}
}
},
"models.SepPostRequest": {
"type": "object",
"required": [
"t_sep"
],
"properties": {
"t_sep": {
"$ref": "#/definitions/models.TSepPost"
}
}
},
"models.SepPutRequest": {
"type": "object",
"required": [
"t_sep"
],
"properties": {
"t_sep": {
"$ref": "#/definitions/models.TSepPut"
}
}
},
"models.SepResponse": {
"type": "object",
"properties": {
"data": {
"type": "object",
"additionalProperties": true
},
"message": {
"type": "string"
}
}
},
"models.Skdp": {
"type": "object",
"required": [
"kodeDPJP",
"noSurat"
],
"properties": {
"kodeDPJP": {
"type": "string"
},
"noSurat": {
"type": "string"
}
}
},
"models.Suplesi": {
"type": "object",
"properties": {
"lokasiLaka": {
"$ref": "#/definitions/models.LokasiLaka"
},
"noSepSuplesi": {
"type": "string"
},
"suplesi": {
"type": "string"
}
}
},
"models.TSepPost": {
"type": "object",
"required": [
"cob",
"diagAwal",
"jaminan",
"jnsPelayanan",
"katarak",
"klsRawat",
"noKartu",
"noMR",
"poli",
"ppkPelayanan",
"rujukan",
"skdp",
"tglSep",
"user"
],
"properties": {
"assesmentPel": {
"type": "string"
},
"catatan": {
"type": "string"
},
"cob": {
"$ref": "#/definitions/models.Flag"
},
"diagAwal": {
"type": "string"
},
"dpjpLayan": {
"type": "string"
},
"flagProcedure": {
"type": "string"
},
"jaminan": {
"$ref": "#/definitions/models.Jaminan"
},
"jnsPelayanan": {
"type": "string"
},
"katarak": {
"$ref": "#/definitions/models.Flag"
},
"kdPenunjang": {
"type": "string"
},
"klsRawat": {
"$ref": "#/definitions/models.KlsRawatPost"
},
"noKartu": {
"type": "string"
},
"noMR": {
"type": "string"
},
"noTelp": {
"type": "string"
},
"poli": {
"$ref": "#/definitions/models.Poli"
},
"ppkPelayanan": {
"type": "string"
},
"rujukan": {
"$ref": "#/definitions/models.Rujukan"
},
"skdp": {
"$ref": "#/definitions/models.Skdp"
},
"tglSep": {
"description": "yyyy-MM-dd",
"type": "string"
},
"tujuanKunj": {
"type": "string"
},
"user": {
"type": "string"
}
}
},
"models.TSepPut": {
"type": "object",
"required": [
"noSep",
"user"
],
"properties": {
"catatan": {
"type": "string"
},
"cob": {
"$ref": "#/definitions/models.Flag"
},
"diagAwal": {
"type": "string"
},
"dpjpLayan": {
"type": "string"
},
"jaminan": {
"$ref": "#/definitions/models.Jaminan"
},
"katarak": {
"$ref": "#/definitions/models.Flag"
},
"klsRawat": {
"$ref": "#/definitions/models.KlsRawatPut"
},
"noMR": {
"type": "string"
},
"noSep": {
"type": "string"
},
"noTelp": {
"type": "string"
},
"poli": {
"$ref": "#/definitions/models.Poli"
},
"user": {
"type": "string"
}
}
},
"sql.NullString": {
"type": "object",
"properties": {

View File

@@ -349,19 +349,19 @@
"400": {
"description": "Invalid ID format",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"404": {
"description": "Retribusi not found",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -406,19 +406,19 @@
"400": {
"description": "Bad request or validation error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"404": {
"description": "Retribusi not found",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -454,19 +454,19 @@
"400": {
"description": "Invalid ID format",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"404": {
"description": "Retribusi not found",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -542,13 +542,13 @@
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -586,13 +586,82 @@
"400": {
"description": "Bad request or validation error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
}
},
"/api/v1/retribusis/dynamic": {
"get": {
"description": "Returns retribusis with advanced dynamic filtering like Directus",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"retribusi"
],
"summary": "Get retribusi with dynamic filtering",
"parameters": [
{
"type": "string",
"description": "Fields to select (e.g., fields=*.*)",
"name": "fields",
"in": "query"
},
{
"type": "string",
"description": "Dynamic filters (e.g., filter[Jenis][_eq]=value)",
"name": "filter[column][operator]",
"in": "query"
},
{
"type": "string",
"description": "Sort fields (e.g., sort=date_created,-Jenis)",
"name": "sort",
"in": "query"
},
{
"type": "integer",
"default": 10,
"description": "Limit",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"default": 0,
"description": "Offset",
"name": "offset",
"in": "query"
}
],
"responses": {
"200": {
"description": "Success response",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.RetribusiGetResponse"
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -623,13 +692,13 @@
"200": {
"description": "Statistics data",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.AggregateData"
"$ref": "#/definitions/api-service_internal_models.AggregateData"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/api-service_internal_models_retribusi.ErrorResponse"
"$ref": "#/definitions/api-service_internal_models.ErrorResponse"
}
}
}
@@ -732,9 +801,287 @@
}
}
}
},
"/sep": {
"put": {
"description": "Update an existing Surat Eligibilitas Peserta",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs"
],
"summary": "Update an existing SEP",
"parameters": [
{
"description": "SEP update request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.SepPutRequest"
}
}
],
"responses": {
"200": {
"description": "SEP updated successfully",
"schema": {
"$ref": "#/definitions/models.SepResponse"
}
},
"400": {
"description": "Invalid request",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
},
"post": {
"description": "Create a new Surat Eligibilitas Peserta",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs"
],
"summary": "Create a new SEP",
"parameters": [
{
"description": "SEP creation request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.SepPostRequest"
}
}
],
"responses": {
"200": {
"description": "SEP created successfully",
"schema": {
"$ref": "#/definitions/models.SepResponse"
}
},
"400": {
"description": "Invalid request",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
}
},
"/sep/{noSep}": {
"get": {
"description": "Retrieve a Surat Eligibilitas Peserta by noSep",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs"
],
"summary": "Get an existing SEP",
"parameters": [
{
"type": "string",
"description": "No SEP",
"name": "noSep",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Data SEP retrieved successfully",
"schema": {
"$ref": "#/definitions/models.SepResponse"
}
},
"400": {
"description": "Invalid request",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
},
"delete": {
"description": "Delete a Surat Eligibilitas Peserta by noSep",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"bpjs"
],
"summary": "Delete an existing SEP",
"parameters": [
{
"type": "string",
"description": "No SEP",
"name": "noSep",
"in": "path",
"required": true
},
{
"type": "string",
"description": "User",
"name": "user",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "SEP deleted successfully",
"schema": {
"$ref": "#/definitions/models.SepResponse"
}
},
"400": {
"description": "Invalid request",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
}
}
},
"definitions": {
"api-service_internal_models.AggregateData": {
"type": "object",
"properties": {
"by_dinas": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"by_jenis": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"by_status": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"created_today": {
"type": "integer"
},
"last_updated": {
"type": "string"
},
"total_active": {
"type": "integer"
},
"total_draft": {
"type": "integer"
},
"total_inactive": {
"type": "integer"
},
"updated_today": {
"type": "integer"
}
}
},
"api-service_internal_models.ErrorResponse": {
"type": "object",
"properties": {
"code": {
"type": "integer"
},
"error": {
"type": "string"
},
"message": {
"type": "string"
},
"timestamp": {
"type": "string"
}
}
},
"api-service_internal_models.MetaResponse": {
"type": "object",
"properties": {
"current_page": {
"type": "integer"
},
"has_next": {
"type": "boolean"
},
"has_prev": {
"type": "boolean"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
},
"total": {
"type": "integer"
},
"total_pages": {
"type": "integer"
}
}
},
"api-service_internal_models.NullableInt32": {
"type": "object",
"properties": {
"int32": {
"type": "integer"
},
"valid": {
"type": "boolean"
}
}
},
"api-service_internal_models_auth.LoginRequest": {
"type": "object",
"required": [
@@ -781,101 +1128,6 @@
}
}
},
"api-service_internal_models_retribusi.AggregateData": {
"type": "object",
"properties": {
"by_dinas": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"by_jenis": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"by_status": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"created_today": {
"type": "integer"
},
"last_updated": {
"type": "string"
},
"total_active": {
"type": "integer"
},
"total_draft": {
"type": "integer"
},
"total_inactive": {
"type": "integer"
},
"updated_today": {
"type": "integer"
}
}
},
"api-service_internal_models_retribusi.ErrorResponse": {
"type": "object",
"properties": {
"code": {
"type": "integer"
},
"error": {
"type": "string"
},
"message": {
"type": "string"
},
"timestamp": {
"type": "string"
}
}
},
"api-service_internal_models_retribusi.MetaResponse": {
"type": "object",
"properties": {
"current_page": {
"type": "integer"
},
"has_next": {
"type": "boolean"
},
"has_prev": {
"type": "boolean"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
},
"total": {
"type": "integer"
},
"total_pages": {
"type": "integer"
}
}
},
"api-service_internal_models_retribusi.NullableInt32": {
"type": "object",
"properties": {
"int32": {
"type": "integer"
},
"valid": {
"type": "boolean"
}
}
},
"api-service_internal_models_retribusi.Retribusi": {
"type": "object",
"properties": {
@@ -916,7 +1168,7 @@
"$ref": "#/definitions/sql.NullString"
},
"sort": {
"$ref": "#/definitions/api-service_internal_models_retribusi.NullableInt32"
"$ref": "#/definitions/api-service_internal_models.NullableInt32"
},
"status": {
"type": "string"
@@ -1066,10 +1318,10 @@
"type": "string"
},
"meta": {
"$ref": "#/definitions/api-service_internal_models_retribusi.MetaResponse"
"$ref": "#/definitions/api-service_internal_models.MetaResponse"
},
"summary": {
"$ref": "#/definitions/api-service_internal_models_retribusi.AggregateData"
"$ref": "#/definitions/api-service_internal_models.AggregateData"
}
}
},
@@ -1160,6 +1412,10 @@
}
}
},
"gin.H": {
"type": "object",
"additionalProperties": {}
},
"models.DiagnosaResponse": {
"type": "object",
"properties": {
@@ -1172,6 +1428,329 @@
}
}
},
"models.Flag": {
"type": "object",
"required": [
"cob"
],
"properties": {
"cob": {
"type": "string"
}
}
},
"models.Jaminan": {
"type": "object",
"required": [
"lakaLantas"
],
"properties": {
"lakaLantas": {
"type": "string"
},
"noLP": {
"type": "string"
},
"penjamin": {
"$ref": "#/definitions/models.Penjamin"
}
}
},
"models.KlsRawatPost": {
"type": "object",
"required": [
"klsRawatHak"
],
"properties": {
"klsRawatHak": {
"type": "string"
},
"klsRawatNaik": {
"type": "string"
},
"pembiayaan": {
"type": "string"
},
"penanggungJawab": {
"type": "string"
}
}
},
"models.KlsRawatPut": {
"type": "object",
"properties": {
"klsRawatHak": {
"type": "string"
},
"klsRawatNaik": {
"type": "string"
},
"pembiayaan": {
"type": "string"
},
"penanggungJawab": {
"type": "string"
}
}
},
"models.LokasiLaka": {
"type": "object",
"properties": {
"kdKabupaten": {
"type": "string"
},
"kdKecamatan": {
"type": "string"
},
"kdPropinsi": {
"type": "string"
}
}
},
"models.Penjamin": {
"type": "object",
"properties": {
"keterangan": {
"type": "string"
},
"suplesi": {
"$ref": "#/definitions/models.Suplesi"
},
"tglKejadian": {
"type": "string"
}
}
},
"models.Poli": {
"type": "object",
"required": [
"eksekutif"
],
"properties": {
"eksekutif": {
"type": "string"
},
"tujuan": {
"type": "string"
}
}
},
"models.Rujukan": {
"type": "object",
"required": [
"asalRujukan",
"noRujukan",
"ppkRujukan",
"tglRujukan"
],
"properties": {
"asalRujukan": {
"type": "string"
},
"noRujukan": {
"type": "string"
},
"ppkRujukan": {
"type": "string"
},
"tglRujukan": {
"type": "string"
}
}
},
"models.SepPostRequest": {
"type": "object",
"required": [
"t_sep"
],
"properties": {
"t_sep": {
"$ref": "#/definitions/models.TSepPost"
}
}
},
"models.SepPutRequest": {
"type": "object",
"required": [
"t_sep"
],
"properties": {
"t_sep": {
"$ref": "#/definitions/models.TSepPut"
}
}
},
"models.SepResponse": {
"type": "object",
"properties": {
"data": {
"type": "object",
"additionalProperties": true
},
"message": {
"type": "string"
}
}
},
"models.Skdp": {
"type": "object",
"required": [
"kodeDPJP",
"noSurat"
],
"properties": {
"kodeDPJP": {
"type": "string"
},
"noSurat": {
"type": "string"
}
}
},
"models.Suplesi": {
"type": "object",
"properties": {
"lokasiLaka": {
"$ref": "#/definitions/models.LokasiLaka"
},
"noSepSuplesi": {
"type": "string"
},
"suplesi": {
"type": "string"
}
}
},
"models.TSepPost": {
"type": "object",
"required": [
"cob",
"diagAwal",
"jaminan",
"jnsPelayanan",
"katarak",
"klsRawat",
"noKartu",
"noMR",
"poli",
"ppkPelayanan",
"rujukan",
"skdp",
"tglSep",
"user"
],
"properties": {
"assesmentPel": {
"type": "string"
},
"catatan": {
"type": "string"
},
"cob": {
"$ref": "#/definitions/models.Flag"
},
"diagAwal": {
"type": "string"
},
"dpjpLayan": {
"type": "string"
},
"flagProcedure": {
"type": "string"
},
"jaminan": {
"$ref": "#/definitions/models.Jaminan"
},
"jnsPelayanan": {
"type": "string"
},
"katarak": {
"$ref": "#/definitions/models.Flag"
},
"kdPenunjang": {
"type": "string"
},
"klsRawat": {
"$ref": "#/definitions/models.KlsRawatPost"
},
"noKartu": {
"type": "string"
},
"noMR": {
"type": "string"
},
"noTelp": {
"type": "string"
},
"poli": {
"$ref": "#/definitions/models.Poli"
},
"ppkPelayanan": {
"type": "string"
},
"rujukan": {
"$ref": "#/definitions/models.Rujukan"
},
"skdp": {
"$ref": "#/definitions/models.Skdp"
},
"tglSep": {
"description": "yyyy-MM-dd",
"type": "string"
},
"tujuanKunj": {
"type": "string"
},
"user": {
"type": "string"
}
}
},
"models.TSepPut": {
"type": "object",
"required": [
"noSep",
"user"
],
"properties": {
"catatan": {
"type": "string"
},
"cob": {
"$ref": "#/definitions/models.Flag"
},
"diagAwal": {
"type": "string"
},
"dpjpLayan": {
"type": "string"
},
"jaminan": {
"$ref": "#/definitions/models.Jaminan"
},
"katarak": {
"$ref": "#/definitions/models.Flag"
},
"klsRawat": {
"$ref": "#/definitions/models.KlsRawatPut"
},
"noMR": {
"type": "string"
},
"noSep": {
"type": "string"
},
"noTelp": {
"type": "string"
},
"poli": {
"$ref": "#/definitions/models.Poli"
},
"user": {
"type": "string"
}
}
},
"sql.NullString": {
"type": "object",
"properties": {

View File

@@ -1,5 +1,67 @@
basePath: /api/v1
definitions:
api-service_internal_models.AggregateData:
properties:
by_dinas:
additionalProperties:
type: integer
type: object
by_jenis:
additionalProperties:
type: integer
type: object
by_status:
additionalProperties:
type: integer
type: object
created_today:
type: integer
last_updated:
type: string
total_active:
type: integer
total_draft:
type: integer
total_inactive:
type: integer
updated_today:
type: integer
type: object
api-service_internal_models.ErrorResponse:
properties:
code:
type: integer
error:
type: string
message:
type: string
timestamp:
type: string
type: object
api-service_internal_models.MetaResponse:
properties:
current_page:
type: integer
has_next:
type: boolean
has_prev:
type: boolean
limit:
type: integer
offset:
type: integer
total:
type: integer
total_pages:
type: integer
type: object
api-service_internal_models.NullableInt32:
properties:
int32:
type: integer
valid:
type: boolean
type: object
api-service_internal_models_auth.LoginRequest:
properties:
password:
@@ -30,68 +92,6 @@ definitions:
username:
type: string
type: object
api-service_internal_models_retribusi.AggregateData:
properties:
by_dinas:
additionalProperties:
type: integer
type: object
by_jenis:
additionalProperties:
type: integer
type: object
by_status:
additionalProperties:
type: integer
type: object
created_today:
type: integer
last_updated:
type: string
total_active:
type: integer
total_draft:
type: integer
total_inactive:
type: integer
updated_today:
type: integer
type: object
api-service_internal_models_retribusi.ErrorResponse:
properties:
code:
type: integer
error:
type: string
message:
type: string
timestamp:
type: string
type: object
api-service_internal_models_retribusi.MetaResponse:
properties:
current_page:
type: integer
has_next:
type: boolean
has_prev:
type: boolean
limit:
type: integer
offset:
type: integer
total:
type: integer
total_pages:
type: integer
type: object
api-service_internal_models_retribusi.NullableInt32:
properties:
int32:
type: integer
valid:
type: boolean
type: object
api-service_internal_models_retribusi.Retribusi:
properties:
date_created:
@@ -119,7 +119,7 @@ definitions:
satuan_overtime:
$ref: '#/definitions/sql.NullString'
sort:
$ref: '#/definitions/api-service_internal_models_retribusi.NullableInt32'
$ref: '#/definitions/api-service_internal_models.NullableInt32'
status:
type: string
tarif:
@@ -224,9 +224,9 @@ definitions:
message:
type: string
meta:
$ref: '#/definitions/api-service_internal_models_retribusi.MetaResponse'
$ref: '#/definitions/api-service_internal_models.MetaResponse'
summary:
$ref: '#/definitions/api-service_internal_models_retribusi.AggregateData'
$ref: '#/definitions/api-service_internal_models.AggregateData'
type: object
api-service_internal_models_retribusi.RetribusiUpdateRequest:
properties:
@@ -292,6 +292,9 @@ definitions:
message:
type: string
type: object
gin.H:
additionalProperties: {}
type: object
models.DiagnosaResponse:
properties:
data:
@@ -300,6 +303,223 @@ definitions:
message:
type: string
type: object
models.Flag:
properties:
cob:
type: string
required:
- cob
type: object
models.Jaminan:
properties:
lakaLantas:
type: string
noLP:
type: string
penjamin:
$ref: '#/definitions/models.Penjamin'
required:
- lakaLantas
type: object
models.KlsRawatPost:
properties:
klsRawatHak:
type: string
klsRawatNaik:
type: string
pembiayaan:
type: string
penanggungJawab:
type: string
required:
- klsRawatHak
type: object
models.KlsRawatPut:
properties:
klsRawatHak:
type: string
klsRawatNaik:
type: string
pembiayaan:
type: string
penanggungJawab:
type: string
type: object
models.LokasiLaka:
properties:
kdKabupaten:
type: string
kdKecamatan:
type: string
kdPropinsi:
type: string
type: object
models.Penjamin:
properties:
keterangan:
type: string
suplesi:
$ref: '#/definitions/models.Suplesi'
tglKejadian:
type: string
type: object
models.Poli:
properties:
eksekutif:
type: string
tujuan:
type: string
required:
- eksekutif
type: object
models.Rujukan:
properties:
asalRujukan:
type: string
noRujukan:
type: string
ppkRujukan:
type: string
tglRujukan:
type: string
required:
- asalRujukan
- noRujukan
- ppkRujukan
- tglRujukan
type: object
models.SepPostRequest:
properties:
t_sep:
$ref: '#/definitions/models.TSepPost'
required:
- t_sep
type: object
models.SepPutRequest:
properties:
t_sep:
$ref: '#/definitions/models.TSepPut'
required:
- t_sep
type: object
models.SepResponse:
properties:
data:
additionalProperties: true
type: object
message:
type: string
type: object
models.Skdp:
properties:
kodeDPJP:
type: string
noSurat:
type: string
required:
- kodeDPJP
- noSurat
type: object
models.Suplesi:
properties:
lokasiLaka:
$ref: '#/definitions/models.LokasiLaka'
noSepSuplesi:
type: string
suplesi:
type: string
type: object
models.TSepPost:
properties:
assesmentPel:
type: string
catatan:
type: string
cob:
$ref: '#/definitions/models.Flag'
diagAwal:
type: string
dpjpLayan:
type: string
flagProcedure:
type: string
jaminan:
$ref: '#/definitions/models.Jaminan'
jnsPelayanan:
type: string
katarak:
$ref: '#/definitions/models.Flag'
kdPenunjang:
type: string
klsRawat:
$ref: '#/definitions/models.KlsRawatPost'
noKartu:
type: string
noMR:
type: string
noTelp:
type: string
poli:
$ref: '#/definitions/models.Poli'
ppkPelayanan:
type: string
rujukan:
$ref: '#/definitions/models.Rujukan'
skdp:
$ref: '#/definitions/models.Skdp'
tglSep:
description: yyyy-MM-dd
type: string
tujuanKunj:
type: string
user:
type: string
required:
- cob
- diagAwal
- jaminan
- jnsPelayanan
- katarak
- klsRawat
- noKartu
- noMR
- poli
- ppkPelayanan
- rujukan
- skdp
- tglSep
- user
type: object
models.TSepPut:
properties:
catatan:
type: string
cob:
$ref: '#/definitions/models.Flag'
diagAwal:
type: string
dpjpLayan:
type: string
jaminan:
$ref: '#/definitions/models.Jaminan'
katarak:
$ref: '#/definitions/models.Flag'
klsRawat:
$ref: '#/definitions/models.KlsRawatPut'
noMR:
type: string
noSep:
type: string
noTelp:
type: string
poli:
$ref: '#/definitions/models.Poli'
user:
type: string
required:
- noSep
- user
type: object
sql.NullString:
properties:
string:
@@ -546,15 +766,15 @@ paths:
"400":
description: Invalid ID format
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
"404":
description: Retribusi not found
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
summary: Delete retribusi
tags:
- retribusi
@@ -578,15 +798,15 @@ paths:
"400":
description: Invalid ID format
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
"404":
description: Retribusi not found
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
summary: Get Retribusi by ID
tags:
- retribusi
@@ -616,15 +836,15 @@ paths:
"400":
description: Bad request or validation error
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
"404":
description: Retribusi not found
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
summary: Update retribusi
tags:
- retribusi
@@ -675,11 +895,11 @@ paths:
"400":
description: Bad request
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
summary: Get retribusi with pagination and optional aggregation
tags:
- retribusi
@@ -704,14 +924,60 @@ paths:
"400":
description: Bad request or validation error
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
summary: Create retribusi
tags:
- retribusi
/api/v1/retribusis/dynamic:
get:
consumes:
- application/json
description: Returns retribusis with advanced dynamic filtering like Directus
parameters:
- description: Fields to select (e.g., fields=*.*)
in: query
name: fields
type: string
- description: Dynamic filters (e.g., filter[Jenis][_eq]=value)
in: query
name: filter[column][operator]
type: string
- description: Sort fields (e.g., sort=date_created,-Jenis)
in: query
name: sort
type: string
- default: 10
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: Success response
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.RetribusiGetResponse'
"400":
description: Bad request
schema:
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
summary: Get retribusi with dynamic filtering
tags:
- retribusi
/api/v1/retribusis/stats:
get:
consumes:
@@ -728,11 +994,11 @@ paths:
"200":
description: Statistics data
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.AggregateData'
$ref: '#/definitions/api-service_internal_models.AggregateData'
"500":
description: Internal server error
schema:
$ref: '#/definitions/api-service_internal_models_retribusi.ErrorResponse'
$ref: '#/definitions/api-service_internal_models.ErrorResponse'
summary: Get retribusi statistics
tags:
- retribusi
@@ -801,6 +1067,127 @@ paths:
summary: Generate token directly
tags:
- Token
/sep:
post:
consumes:
- application/json
description: Create a new Surat Eligibilitas Peserta
parameters:
- description: SEP creation request
in: body
name: request
required: true
schema:
$ref: '#/definitions/models.SepPostRequest'
produces:
- application/json
responses:
"200":
description: SEP created successfully
schema:
$ref: '#/definitions/models.SepResponse'
"400":
description: Invalid request
schema:
$ref: '#/definitions/gin.H'
"500":
description: Internal server error
schema:
$ref: '#/definitions/gin.H'
summary: Create a new SEP
tags:
- bpjs
put:
consumes:
- application/json
description: Update an existing Surat Eligibilitas Peserta
parameters:
- description: SEP update request
in: body
name: request
required: true
schema:
$ref: '#/definitions/models.SepPutRequest'
produces:
- application/json
responses:
"200":
description: SEP updated successfully
schema:
$ref: '#/definitions/models.SepResponse'
"400":
description: Invalid request
schema:
$ref: '#/definitions/gin.H'
"500":
description: Internal server error
schema:
$ref: '#/definitions/gin.H'
summary: Update an existing SEP
tags:
- bpjs
/sep/{noSep}:
delete:
consumes:
- application/json
description: Delete a Surat Eligibilitas Peserta by noSep
parameters:
- description: No SEP
in: path
name: noSep
required: true
type: string
- description: User
in: query
name: user
required: true
type: string
produces:
- application/json
responses:
"200":
description: SEP deleted successfully
schema:
$ref: '#/definitions/models.SepResponse'
"400":
description: Invalid request
schema:
$ref: '#/definitions/gin.H'
"500":
description: Internal server error
schema:
$ref: '#/definitions/gin.H'
summary: Delete an existing SEP
tags:
- bpjs
get:
consumes:
- application/json
description: Retrieve a Surat Eligibilitas Peserta by noSep
parameters:
- description: No SEP
in: path
name: noSep
required: true
type: string
produces:
- application/json
responses:
"200":
description: Data SEP retrieved successfully
schema:
$ref: '#/definitions/models.SepResponse'
"400":
description: Invalid request
schema:
$ref: '#/definitions/gin.H'
"500":
description: Internal server error
schema:
$ref: '#/definitions/gin.H'
summary: Get an existing SEP
tags:
- bpjs
schemes:
- http
- https

View File

@@ -68,4 +68,13 @@ KEYCLOAK_ENABLED=true
BPJS_BASEURL=https://apijkn.bpjs-kesehatan.go.id/vclaim-rest
BPJS_CONSID=5257
BPJS_USERKEY=4cf1cbef8c008440bbe9ef9ba789e482
BPJS_SECRETKEY=1bV363512D
BPJS_SECRETKEY=1bV363512D
BRIDGING_SATUSEHAT_ORG_ID=100026555
BRIDGING_SATUSEHAT_FASYAKES_ID=3573011
BRIDGING_SATUSEHAT_CLIENT_ID=l1ZgJGW6K5pnrqGUikWM7fgIoquA2AQ5UUG0U8WqHaq2VEyZ
BRIDGING_SATUSEHAT_CLIENT_SECRET=Al3PTYAW6axPiAFwaFlpn8qShLFW5YGMgG8w1qhexgCc7lGTEjjcR6zxa06ThPDy
BRIDGING_SATUSEHAT_AUTH_URL=https://api-satusehat.kemkes.go.id/oauth2/v1
BRIDGING_SATUSEHAT_BASE_URL=https://api-satusehat.kemkes.go.id/fhir-r4/v1
BRIDGING_SATUSEHAT_CONSENT_URL=https://api-satusehat.dto.kemkes.go.id/consent/v1
BRIDGING_SATUSEHAT_KFA_URL=https://api-satusehat.kemkes.go.id/kfa-v2

View File

@@ -19,6 +19,7 @@ type Config struct {
ReadReplicas map[string][]DatabaseConfig // For read replicas
Keycloak KeycloakConfig
Bpjs BpjsConfig
SatuSehat SatuSehatConfig
}
type ServerConfig struct {
@@ -58,6 +59,18 @@ type BpjsConfig struct {
Timeout time.Duration `json:"timeout"`
}
type SatuSehatConfig struct {
OrgID string `json:"org_id"`
FasyakesID string `json:"fasyakes_id"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
AuthURL string `json:"auth_url"`
BaseURL string `json:"base_url"`
ConsentURL string `json:"consent_url"`
KFAURL string `json:"kfa_url"`
Timeout time.Duration `json:"timeout"`
}
// SetHeader generates required headers for BPJS VClaim API
func (cfg BpjsConfig) SetHeader() (string, string, string, string, string) {
timenow := time.Now().UTC()
@@ -117,6 +130,17 @@ func LoadConfig() *Config {
SecretKey: getEnv("BPJS_SECRETKEY", ""),
Timeout: parseDuration(getEnv("BPJS_TIMEOUT", "30s")),
},
SatuSehat: SatuSehatConfig{
OrgID: getEnv("BRIDGING_SATUSEHAT_ORG_ID", ""),
FasyakesID: getEnv("BRIDGING_SATUSEHAT_FASYAKES_ID", ""),
ClientID: getEnv("BRIDGING_SATUSEHAT_CLIENT_ID", ""),
ClientSecret: getEnv("BRIDGING_SATUSEHAT_CLIENT_SECRET", ""),
AuthURL: getEnv("BRIDGING_SATUSEHAT_AUTH_URL", "https://api-satusehat.kemkes.go.id/oauth2/v1"),
BaseURL: getEnv("BRIDGING_SATUSEHAT_BASE_URL", "https://api-satusehat.kemkes.go.id/fhir-r4/v1"),
ConsentURL: getEnv("BRIDGING_SATUSEHAT_CONSENT_URL", "https://api-satusehat.dto.kemkes.go.id/consent/v1"),
KFAURL: getEnv("BRIDGING_SATUSEHAT_KFA_URL", "https://api-satusehat.kemkes.go.id/kfa-v2"),
Timeout: parseDuration(getEnv("BRIDGING_SATUSEHAT_TIMEOUT", "30s")),
},
}
// Load database configurations
@@ -622,5 +646,25 @@ func (c *Config) Validate() error {
}
}
// Validate SatuSehat configuration
if c.SatuSehat.OrgID == "" {
log.Fatal("SatuSehat Organization ID is required")
}
if c.SatuSehat.FasyakesID == "" {
log.Fatal("SatuSehat Fasyankes ID is required")
}
if c.SatuSehat.ClientID == "" {
log.Fatal("SatuSehat Client ID is required")
}
if c.SatuSehat.ClientSecret == "" {
log.Fatal("SatuSehat Client Secret is required")
}
if c.SatuSehat.AuthURL == "" {
log.Fatal("SatuSehat Auth URL is required")
}
if c.SatuSehat.BaseURL == "" {
log.Fatal("SatuSehat Base URL is required")
}
return nil
}

View File

@@ -74,8 +74,8 @@ func NewRetribusiHandler() *RetribusiHandler {
// @Param dinas query string false "Filter by dinas"
// @Param search query string false "Search in multiple fields"
// @Success 200 {object} modelsretribusi.RetribusiGetResponse "Success response"
// @Failure 400 {object} modelsretribusi.ErrorResponse "Bad request"
// @Failure 500 {object} modelsretribusi.ErrorResponse "Internal server error"
// @Failure 400 {object} models.ErrorResponse "Bad request"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
// @Router /api/v1/retribusis [get]
func (h *RetribusiHandler) GetRetribusi(c *gin.Context) {
// Parse pagination parameters
@@ -186,9 +186,9 @@ func (h *RetribusiHandler) GetRetribusi(c *gin.Context) {
// @Produce json
// @Param id path string true "Retribusi ID (UUID)"
// @Success 200 {object} modelsretribusi.RetribusiGetByIDResponse "Success response"
// @Failure 400 {object} modelsretribusi.ErrorResponse "Invalid ID format"
// @Failure 404 {object} modelsretribusi.ErrorResponse "Retribusi not found"
// @Failure 500 {object} modelsretribusi.ErrorResponse "Internal server error"
// @Failure 400 {object} models.ErrorResponse "Invalid ID format"
// @Failure 404 {object} models.ErrorResponse "Retribusi not found"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
// @Router /api/v1/retribusi/{id} [get]
func (h *RetribusiHandler) GetRetribusiByID(c *gin.Context) {
id := c.Param("id")
@@ -238,8 +238,8 @@ func (h *RetribusiHandler) GetRetribusiByID(c *gin.Context) {
// @Param limit query int false "Limit" default(10)
// @Param offset query int false "Offset" default(0)
// @Success 200 {object} modelsretribusi.RetribusiGetResponse "Success response"
// @Failure 400 {object} modelsretribusi.ErrorResponse "Bad request"
// @Failure 500 {object} modelsretribusi.ErrorResponse "Internal server error"
// @Failure 400 {object} models.ErrorResponse "Bad request"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
// @Router /api/v1/retribusis/dynamic [get]
func (h *RetribusiHandler) GetRetribusiDynamic(c *gin.Context) {
// Parse query parameters
@@ -501,8 +501,8 @@ func (h *RetribusiHandler) SearchRetribusiAdvanced(c *gin.Context) {
// @Produce json
// @Param request body modelsretribusi.RetribusiCreateRequest true "Retribusi creation request"
// @Success 201 {object} modelsretribusi.RetribusiCreateResponse "Retribusi created successfully"
// @Failure 400 {object} modelsretribusi.ErrorResponse "Bad request or validation error"
// @Failure 500 {object} modelsretribusi.ErrorResponse "Internal server error"
// @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
@@ -556,9 +556,9 @@ func (h *RetribusiHandler) CreateRetribusi(c *gin.Context) {
// @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"
// @Failure 400 {object} modelsretribusi.ErrorResponse "Bad request or validation error"
// @Failure 404 {object} modelsretribusi.ErrorResponse "Retribusi not found"
// @Failure 500 {object} modelsretribusi.ErrorResponse "Internal server error"
// @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"
// @Router /api/v1/retribusi/{id} [put]
func (h *RetribusiHandler) UpdateRetribusi(c *gin.Context) {
id := c.Param("id")
@@ -619,9 +619,9 @@ func (h *RetribusiHandler) UpdateRetribusi(c *gin.Context) {
// @Produce json
// @Param id path string true "Retribusi ID (UUID)"
// @Success 200 {object} modelsretribusi.RetribusiDeleteResponse "Retribusi deleted successfully"
// @Failure 400 {object} modelsretribusi.ErrorResponse "Invalid ID format"
// @Failure 404 {object} modelsretribusi.ErrorResponse "Retribusi not found"
// @Failure 500 {object} modelsretribusi.ErrorResponse "Internal server error"
// @Failure 400 {object} models.ErrorResponse "Invalid ID format"
// @Failure 404 {object} models.ErrorResponse "Retribusi not found"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
// @Router /api/v1/retribusi/{id} [delete]
func (h *RetribusiHandler) DeleteRetribusi(c *gin.Context) {
id := c.Param("id")
@@ -666,8 +666,8 @@ func (h *RetribusiHandler) DeleteRetribusi(c *gin.Context) {
// @Accept json
// @Produce json
// @Param status query string false "Filter statistics by status"
// @Success 200 {object} modelsretribusi.AggregateData "Statistics data"
// @Failure 500 {object} modelsretribusi.ErrorResponse "Internal server error"
// @Success 200 {object} models.AggregateData "Statistics data"
// @Failure 500 {object} models.ErrorResponse "Internal server error"
// @Router /api/v1/retribusis/stats [get]
func (h *RetribusiHandler) GetRetribusiStats(c *gin.Context) {
dbConn, err := h.db.GetDB("postgres_satudata")

View File

@@ -0,0 +1,192 @@
package satusehat
import (
"net/http"
"api-service/internal/services/satusehat"
"github.com/gin-gonic/gin"
)
type PatientHandler struct {
service *satusehat.SatuSehatService
}
func NewPatientHandler(service *satusehat.SatuSehatService) *PatientHandler {
return &PatientHandler{
service: service,
}
}
// SearchPatientByNIK godoc
// @Summary Search patient by NIK
// @Description Search patient data from SatuSehat by National Identity Number (NIK)
// @Tags SatuSehat
// @Accept json
// @Produce json
// @Param nik query string true "National Identity Number (NIK)"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} map[string]interface{}
// @Failure 500 {object} map[string]interface{}
// @Router /satusehat/patient/search/nik [get]
func (h *PatientHandler) SearchPatientByNIK(c *gin.Context) {
nik := c.Query("nik")
if nik == "" {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Bad Request",
"message": "NIK parameter is required",
})
return
}
patientResp, err := h.service.SearchPatientByNIK(c.Request.Context(), nik)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Internal Server Error",
"message": err.Error(),
})
return
}
patientInfo, err := satusehat.ExtractPatientInfo(patientResp)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{
"error": "Not Found",
"message": "Patient not found",
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": patientInfo,
})
}
// SearchPatientByName godoc
// @Summary Search patient by name
// @Description Search patient data from SatuSehat by name
// @Tags SatuSehat
// @Accept json
// @Produce json
// @Param name query string true "Patient name"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} map[string]interface{}
// @Failure 500 {object} map[string]interface{}
// @Router /satusehat/patient/search/name [get]
func (h *PatientHandler) SearchPatientByName(c *gin.Context) {
name := c.Query("name")
if name == "" {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Bad Request",
"message": "Name parameter is required",
})
return
}
patientResp, err := h.service.SearchPatientByName(c.Request.Context(), name)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Internal Server Error",
"message": err.Error(),
})
return
}
if patientResp == nil || len(patientResp.Entry) == 0 {
c.JSON(http.StatusNotFound, gin.H{
"error": "Not Found",
"message": "Patient not found",
})
return
}
// Return all found patients
var patients []map[string]interface{}
for _, entry := range patientResp.Entry {
patientInfo := map[string]interface{}{
"id": entry.Resource.ID,
"name": satusehat.ExtractPatientName(entry.Resource.Name),
"nik": satusehat.ExtractNIK(entry.Resource.Identifier),
"gender": entry.Resource.Gender,
"birthDate": entry.Resource.BirthDate,
"address": satusehat.ExtractAddress(entry.Resource.Address),
"phone": satusehat.ExtractPhone(entry.Resource.Telecom),
"lastUpdated": entry.Resource.Meta.LastUpdated,
}
patients = append(patients, patientInfo)
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": patients,
"total": len(patients),
})
}
// CreatePatient godoc
// @Summary Create new patient
// @Description Create new patient data in SatuSehat
// @Tags SatuSehat
// @Accept json
// @Produce json
// @Param patient body map[string]interface{} true "Patient data"
// @Success 201 {object} map[string]interface{}
// @Failure 400 {object} map[string]interface{}
// @Failure 500 {object} map[string]interface{}
// @Router /satusehat/patient [post]
func (h *PatientHandler) CreatePatient(c *gin.Context) {
var patientData map[string]interface{}
if err := c.ShouldBindJSON(&patientData); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Bad Request",
"message": "Invalid JSON format",
})
return
}
response, err := h.service.CreatePatient(c.Request.Context(), patientData)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Internal Server Error",
"message": err.Error(),
})
return
}
c.JSON(http.StatusCreated, gin.H{
"success": true,
"data": response,
})
}
// GetAccessToken godoc
// @Summary Get access token
// @Description Get SatuSehat access token
// @Tags SatuSehat
// @Accept json
// @Produce json
// @Success 200 {object} map[string]interface{}
// @Failure 500 {object} map[string]interface{}
// @Router /satusehat/token [get]
func (h *PatientHandler) GetAccessToken(c *gin.Context) {
token, err := h.service.GetAccessToken(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Internal Server Error",
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": map[string]interface{}{
"access_token": token.AccessToken,
"token_type": token.TokenType,
"expires_in": token.ExpiresIn,
"scope": token.Scope,
"issued_at": token.IssuedAt,
},
})
}

View File

@@ -5,8 +5,10 @@ import (
authHandlers "api-service/internal/handlers/auth"
bpjsPesertaHandlers "api-service/internal/handlers/bpjs/reference"
retribusiHandlers "api-service/internal/handlers/retribusi"
satusehatHandlers "api-service/internal/handlers/satusehat"
"api-service/internal/middleware"
services "api-service/internal/services/auth"
satusehatServices "api-service/internal/services/satusehat"
"api-service/pkg/logger"
"github.com/gin-gonic/gin"
@@ -32,6 +34,12 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine {
logger.Fatal("Failed to initialize auth service")
}
// Initialize SatuSehat service
satusehatService := satusehatServices.NewSatuSehatService(&cfg.SatuSehat)
if satusehatService == nil {
logger.Fatal("Failed to initialize SatuSehat service")
}
// Swagger UI route
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
@@ -59,6 +67,16 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine {
bpjsPesertaHandler := bpjsPesertaHandlers.NewPesertaHandler(cfg.Bpjs)
v1.GET("/bpjs/peserta/nik/:nik/tglSEP/:tglSEP", bpjsPesertaHandler.GetPesertaByNIK)
// SatuSehat endpoints
satusehatPatientHandler := satusehatHandlers.NewPatientHandler(satusehatService)
satusehatGroup := v1.Group("/satusehat")
{
satusehatGroup.GET("/patient/search/nik", satusehatPatientHandler.SearchPatientByNIK)
satusehatGroup.GET("/patient/search/name", satusehatPatientHandler.SearchPatientByName)
satusehatGroup.POST("/patient", satusehatPatientHandler.CreatePatient)
satusehatGroup.GET("/token", satusehatPatientHandler.GetAccessToken)
}
// ============= PUBLISHED ROUTES ===============================================
// // Retribusi endpoints

View File

@@ -0,0 +1,350 @@
package satusehat
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"api-service/internal/config"
)
type SatuSehatService struct {
config *config.SatuSehatConfig
client *http.Client
token *TokenResponse
}
type TokenResponse struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"`
Scope string `json:"scope"`
IssuedAt time.Time
}
type PatientResponse struct {
ResourceType string `json:"resourceType"`
ID string `json:"id"`
Meta struct {
VersionID string `json:"versionId"`
LastUpdated string `json:"lastUpdated"`
} `json:"meta"`
Type string `json:"type"`
Total int `json:"total"`
Link []Link `json:"link"`
Entry []Entry `json:"entry"`
}
type Link struct {
Relation string `json:"relation"`
URL string `json:"url"`
}
type Entry struct {
FullURL string `json:"fullUrl"`
Resource struct {
ResourceType string `json:"resourceType"`
ID string `json:"id"`
Meta struct {
VersionID string `json:"versionId"`
LastUpdated string `json:"lastUpdated"`
Profile []string `json:"profile"`
} `json:"meta"`
Identifier []Identifier `json:"identifier"`
Name []Name `json:"name"`
Telecom []Telecom `json:"telecom"`
Gender string `json:"gender"`
BirthDate string `json:"birthDate"`
Deceased bool `json:"deceasedBoolean"`
Address []Address `json:"address"`
MaritalStatus struct {
Coding []Coding `json:"coding"`
} `json:"maritalStatus"`
MultipleBirth bool `json:"multipleBirthBoolean"`
Contact []Contact `json:"contact"`
Communication []Communication `json:"communication"`
Extension []Extension `json:"extension"`
} `json:"resource"`
Search struct {
Mode string `json:"mode"`
} `json:"search"`
}
type Identifier struct {
System string `json:"system"`
Value string `json:"value"`
Use string `json:"use,omitempty"`
}
type Name struct {
Use string `json:"use"`
Text string `json:"text"`
Family string `json:"family"`
Given []string `json:"given"`
}
type Telecom struct {
System string `json:"system"`
Value string `json:"value"`
Use string `json:"use,omitempty"`
}
type Address struct {
Use string `json:"use"`
Type string `json:"type"`
Line []string `json:"line"`
City string `json:"city"`
PostalCode string `json:"postalCode"`
Country string `json:"country"`
Extension []Extension `json:"extension"`
}
type Coding struct {
System string `json:"system"`
Code string `json:"code"`
Display string `json:"display"`
}
type Contact struct {
Relationship []Coding `json:"relationship"`
Name Name `json:"name"`
Telecom []Telecom `json:"telecom"`
Address Address `json:"address"`
Gender string `json:"gender"`
}
type Communication struct {
Language Coding `json:"language"`
Preferred bool `json:"preferred"`
}
type Extension struct {
URL string `json:"url"`
ValueAddress Address `json:"valueAddress,omitempty"`
ValueCode string `json:"valueCode,omitempty"`
}
func NewSatuSehatService(cfg *config.SatuSehatConfig) *SatuSehatService {
return &SatuSehatService{
config: cfg,
client: &http.Client{
Timeout: cfg.Timeout,
},
}
}
func (s *SatuSehatService) GetAccessToken(ctx context.Context) (*TokenResponse, error) {
// Check if we have a valid token
if s.token != nil && time.Since(s.token.IssuedAt) < time.Duration(s.token.ExpiresIn-60)*time.Second {
return s.token, nil
}
url := fmt.Sprintf("%s/accesstoken?grant_type=client_credentials", s.config.AuthURL)
req, err := http.NewRequestWithContext(ctx, "POST", url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %v", err)
}
req.SetBasicAuth(s.config.ClientID, s.config.ClientSecret)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := s.client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to get access token: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get access token, status: %s", resp.Status)
}
var tokenResp TokenResponse
if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
return nil, fmt.Errorf("failed to decode token response: %v", err)
}
tokenResp.IssuedAt = time.Now()
s.token = &tokenResp
return &tokenResp, nil
}
func (s *SatuSehatService) SearchPatientByNIK(ctx context.Context, nik string) (*PatientResponse, error) {
token, err := s.GetAccessToken(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get access token: %v", err)
}
url := fmt.Sprintf("%s/Patient?identifier=https://fhir.kemkes.go.id/id/nik|%s", s.config.BaseURL, nik)
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %v", err)
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.AccessToken))
req.Header.Set("Content-Type", "application/json")
resp, err := s.client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to search patient: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to search patient, status: %s", resp.Status)
}
var patientResp PatientResponse
if err := json.NewDecoder(resp.Body).Decode(&patientResp); err != nil {
return nil, fmt.Errorf("failed to decode patient response: %v", err)
}
return &patientResp, nil
}
func (s *SatuSehatService) SearchPatientByName(ctx context.Context, name string) (*PatientResponse, error) {
token, err := s.GetAccessToken(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get access token: %v", err)
}
url := fmt.Sprintf("%s/Patient?name=%s", s.config.BaseURL, name)
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %v", err)
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.AccessToken))
req.Header.Set("Content-Type", "application/json")
resp, err := s.client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to search patient: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to search patient, status: %s", resp.Status)
}
var patientResp PatientResponse
if err := json.NewDecoder(resp.Body).Decode(&patientResp); err != nil {
return nil, fmt.Errorf("failed to decode patient response: %v", err)
}
return &patientResp, nil
}
func (s *SatuSehatService) CreatePatient(ctx context.Context, patientData map[string]interface{}) (map[string]interface{}, error) {
token, err := s.GetAccessToken(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get access token: %v", err)
}
url := fmt.Sprintf("%s/Patient", s.config.BaseURL)
patientData["resourceType"] = "Patient"
jsonData, err := json.Marshal(patientData)
if err != nil {
return nil, fmt.Errorf("failed to marshal patient data: %v", err)
}
req, err := http.NewRequestWithContext(ctx, "POST", url, strings.NewReader(string(jsonData)))
if err != nil {
return nil, fmt.Errorf("failed to create request: %v", err)
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.AccessToken))
req.Header.Set("Content-Type", "application/json")
resp, err := s.client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to create patient: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
return nil, fmt.Errorf("failed to create patient, status: %s", resp.Status)
}
var response map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return nil, fmt.Errorf("failed to decode response: %v", err)
}
return response, nil
}
// Helper function to extract patient information
func ExtractPatientInfo(patientResp *PatientResponse) (map[string]interface{}, error) {
if patientResp == nil || len(patientResp.Entry) == 0 {
return nil, fmt.Errorf("no patient data found")
}
entry := patientResp.Entry[0]
resource := entry.Resource
patientInfo := map[string]interface{}{
"id": resource.ID,
"name": ExtractPatientName(resource.Name),
"nik": ExtractNIK(resource.Identifier),
"gender": resource.Gender,
"birthDate": resource.BirthDate,
"address": ExtractAddress(resource.Address),
"phone": ExtractPhone(resource.Telecom),
"lastUpdated": resource.Meta.LastUpdated,
}
return patientInfo, nil
}
func ExtractPatientName(names []Name) string {
for _, name := range names {
if name.Use == "official" || name.Text != "" {
if name.Text != "" {
return name.Text
}
return fmt.Sprintf("%s %s", strings.Join(name.Given, " "), name.Family)
}
}
return ""
}
func ExtractNIK(identifiers []Identifier) string {
for _, ident := range identifiers {
if ident.System == "https://fhir.kemkes.go.id/id/nik" {
return ident.Value
}
}
return ""
}
func ExtractAddress(addresses []Address) map[string]interface{} {
if len(addresses) == 0 {
return nil
}
addr := addresses[0]
return map[string]interface{}{
"line": strings.Join(addr.Line, ", "),
"city": addr.City,
"postalCode": addr.PostalCode,
"country": addr.Country,
}
}
func ExtractPhone(telecoms []Telecom) string {
for _, telecom := range telecoms {
if telecom.System == "phone" {
return telecom.Value
}
}
return ""
}

View File

@@ -182,7 +182,7 @@ func New` + data.Name + `Handler(cfg config.BpjsConfig) *` + data.Name + `Handle
handlerContent += generateBpjsGetMethod(data)
}
writeFile(filepath.Join(handlerDir, data.NameLower+".go"), handlerContent)
writeFileBpjs(filepath.Join(handlerDir, data.NameLower+".go"), handlerContent)
}
func generateBpjsCreateMethod(data BpjsHandlerData) string {
@@ -490,7 +490,7 @@ func IsValidStatus(status string) bool {
return false
}`
writeFile(filepath.Join(modelDir, data.NameLower+".go"), modelContent)
writeFileBpjs(filepath.Join(modelDir, data.NameLower+".go"), modelContent)
}
// ================= ROUTES GENERATION =====================
@@ -634,7 +634,7 @@ func printBpjsRoutesSample(data BpjsHandlerData) {
// ================= UTILITY FUNCTIONS =====================
func writeFile(filename, content string) {
func writeFileBpjs(filename, content string) {
if err := os.WriteFile(filename, []byte(content), 0644); err != nil {
fmt.Printf("❌ Error creating file %s: %v\n", filename, err)
return

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@ echo Generating handler: %HANDLER_NAME% with methods: %METHODS%
echo.
cd /d "%~dp0.."
go run tools/generate-handler.go %HANDLER_NAME% %METHODS%
go run tools/general/generate-handler.go %HANDLER_NAME% %METHODS%
echo.
echo Handler generated successfully!

View File

@@ -26,7 +26,7 @@ echo
cd "$(dirname "$0")/.."
# Run the generator
go run tools/generate-handler.go "$HANDLER_NAME" $METHODS
go run tools/general/generate-handler.go "$HANDLER_NAME" $METHODS
echo
echo "Handler generated successfully!"