diff --git a/Dockerfile.dev b/Dockerfile.dev index 6748ee3..20c7d9c 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -14,7 +14,7 @@ RUN go mod download COPY . . # Expose port -EXPOSE 8094 +EXPOSE 8098 # Run air untuk hot reload CMD ["air", "-c", ".air.toml"] \ No newline at end of file diff --git a/cmd/api/main.go b/cmd/api/main.go index 817ba70..7791c14 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -10,30 +10,12 @@ import ( "syscall" "service/internal/auth" - antrol "service/internal/bpjs/antrol/reference" - aplicareBed "service/internal/bpjs/aplicare/bed" - apotekDpho "service/internal/bpjs/apotek/reference/dpho" - apotekPoli "service/internal/bpjs/apotek/reference/poli" - "service/internal/bpjs/vclaim/peserta" - "service/internal/bpjs/vclaim/sep" "service/internal/infrastructure/cache" "service/internal/infrastructure/config" "service/internal/infrastructure/database" - grpcHandlers "service/internal/infrastructure/transport/grpc/handlers" httpServer "service/internal/infrastructure/transport/http/servers" - bpjsFactory "service/internal/interfaces/bpjs" "service/internal/interfaces/minio" - satuSehatFactory "service/internal/interfaces/satusehat" - satuSehatAuth "service/internal/satusehat/reference/auth" - satuSehatKfa "service/internal/satusehat/reference/kfa" - satuSehatLocation "service/internal/satusehat/reference/location" - satuSehatOrganization "service/internal/satusehat/reference/organization" - satuSehatPatient "service/internal/satusehat/reference/patient" - satuSehatPractitioner "service/internal/satusehat/reference/practitioner" - satuSehatCondition "service/internal/satusehat/usecase/condition" - satuSehatEncounter "service/internal/satusehat/usecase/encounter" - satuSehatProcedure "service/internal/satusehat/usecase/procedure" "service/pkg/logger" imagingStudyWorker "service/internal/worker/satusehat/imagingstudy" @@ -169,69 +151,6 @@ func main() { // roleComponentCmdRepo := roleComponent.NewCommandRepository(dbService, "postgres") // roleComponentQueryRepo := roleComponent.NewQueryRepository(dbService, "postgres") // roleComponentService := roleComponent.NewService(roleComponentCmdRepo, roleComponentQueryRepo) - - // --- [NEW] Inisialisasi Modul CQRS Baru (Memanfaatkan DB Service) --- - // Contoh ketika mengimplementasikan entity "Province" atau "Person": - // provinceCmdRepo := province.NewCommandRepository(dbService, "default") - // provinceQueryRepo := province.NewQueryRepository(dbService, "default") - // provinceSvc := province.NewService(provinceCmdRepo, provinceQueryRepo) - - // --- [NEW] Inisialisasi Factory BPJS --- - bpjsServices := bpjsFactory.NewBPJSFactory(cfg.Bpjs) - - // 1. Modul VClaim (Lama) - vclaimServiceEngine := bpjsServices.VClaim() - sepRepo := sep.NewRepository(vclaimServiceEngine) - sepService := sep.NewService(sepRepo) - pesertaRepo := peserta.NewRepository(vclaimServiceEngine) - pesertaService := peserta.NewService(pesertaRepo) - - // 2. Modul Antrean RS (Baru) - antreanClient := bpjsServices.AntreanRS() - antrolRepo := antrol.NewRepository(antreanClient) - antrolService := antrol.NewService(antrolRepo) - - // 3. Modul Aplicares (Bed Ketersediaan Tempat Tidur) - aplicareClient := bpjsServices.Aplicare() - bedRepo := aplicareBed.NewRepository(aplicareClient) - bedService := aplicareBed.NewService(bedRepo) - - // 4. Modul Apotek (Referensi DPHO dan Poli) - apotekClient := bpjsServices.Apotek() - dphoRepo := apotekDpho.NewRepository(apotekClient) - dphoService := apotekDpho.NewService(dphoRepo) - - poliApotekRepo := apotekPoli.NewRepository(apotekClient) - poliApotekService := apotekPoli.NewService(poliApotekRepo) - - // --- [NEW] Inisialisasi Modul Satu Sehat --- - satusehatFact := satuSehatFactory.NewSatuSehatFactory(cfg.SatuSehat) - satusehatClient := satusehatFact.Client() - satuSehatAuthSvc := satuSehatAuth.NewService(satusehatClient, cacheManager) - satuSehatPatientRepo := satuSehatPatient.NewRepository(satusehatClient) - satuSehatPatientSvc := satuSehatPatient.NewService(satuSehatPatientRepo) - - satuSehatPractitionerRepo := satuSehatPractitioner.NewRepository(satusehatClient) - satuSehatPractitionerSvc := satuSehatPractitioner.NewService(satuSehatPractitionerRepo) - - satuSehatOrganizationRepo := satuSehatOrganization.NewRepository(satusehatClient) - satuSehatOrganizationSvc := satuSehatOrganization.NewService(satuSehatOrganizationRepo) - - satuSehatLocationRepo := satuSehatLocation.NewRepository(satusehatClient) - satuSehatLocationSvc := satuSehatLocation.NewService(satuSehatLocationRepo) - - satuSehatKfaRepo := satuSehatKfa.NewRepository(satusehatClient) - satuSehatKfaSvc := satuSehatKfa.NewService(satuSehatKfaRepo) - - satuSehatEncounterRepo := satuSehatEncounter.NewRepository(satusehatClient, dbService) - satuSehatEncounterSvc := satuSehatEncounter.NewService(satuSehatEncounterRepo) - - satuSehatProcedureRepo := satuSehatProcedure.NewRepository(satusehatClient) - satuSehatProcedureSvc := satuSehatProcedure.NewService(satuSehatProcedureRepo) - - satuSehatConditionRepo := satuSehatCondition.NewRepository(satusehatClient) - satuSehatConditionSvc := satuSehatCondition.NewService(satuSehatConditionRepo) - // 6. Server Orchestration (Dual Protocol & Background Workers) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -273,48 +192,6 @@ func main() { RolePermission: rolePermissionService, RoleMaster: roleMasterService, }, - VClaim: &httpServer.VClaimServices{ - Sep: sepService, - Peserta: pesertaService, - }, - Antrol: &httpServer.AntrolServices{ - Reference: antrolService, - }, - Aplicare: &httpServer.AplicaresServices{ - Bed: bedService, - }, - Apotek: &httpServer.ApotekServices{ - DPHO: dphoService, - Poli: poliApotekService, - }, - SatuSehat: &httpServer.SatuSehatServices{ - Auth: satuSehatAuthSvc, - Patient: satuSehatPatientSvc, - Practitioner: satuSehatPractitionerSvc, - Organization: satuSehatOrganizationSvc, - Location: satuSehatLocationSvc, - KFA: satuSehatKfaSvc, - Encounter: satuSehatEncounterSvc, - Procedure: satuSehatProcedureSvc, - Condition: satuSehatConditionSvc, - // TODO: Inisialisasi service sisanya di sini saat repo & service usecase lainnya sudah Anda buat, contoh: - // AllergyIntolerance: allergySvc, - // CarePlan: careplanSvc, - // ClinicalImpression: clinicalImpressionSvc, - // Composition: compositionSvc, - // DiagnosticReport: diagnosticReportSvc, - // EpisodeOfCare: episodeOfCareSvc, - // ImagingStudy: imagingStudySvc, - // Immunization: immunizationSvc, - // Medication: medicationSvc, - // MedicationDispense: medicationDispenseSvc, - // MedicationRequest: medicationRequestSvc, - // MedicationStatement: medicationStatementSvc, - // Observation: observationSvc, - // QuestionnaireResponse: questionnaireResponseSvc, - // ServiceRequest: serviceRequestSvc, - // Specimen: specimenSvc, - }, } restSrv := httpServer.NewHTTPServer(&cfg.Server.REST, registry) @@ -334,10 +211,10 @@ func main() { serverCount++ // 1. Buat gRPC handlers - permissionHandler := grpcHandlers.NewPermissionHandler(rolePermissionService) + // permissionHandler := grpcHandlers.NewPermissionHandler(rolePermissionService) // 2. Buat dan isi gRPC service registry grpcRegistry := &grpcServers.ServiceRegistry{ - PermissionHandler: permissionHandler, + // PermissionHandler: permissionHandler, } // 3. Buat gRPC server dengan registry yang sudah diisi diff --git a/cmd/satusehat/main.go b/cmd/satusehat/main.go deleted file mode 100644 index ebe70b7..0000000 --- a/cmd/satusehat/main.go +++ /dev/null @@ -1,141 +0,0 @@ -package main - -import ( - "context" - "net/http" - "os" - "os/signal" - "syscall" - - "service/internal/infrastructure/cache" - "service/internal/infrastructure/config" - "service/internal/infrastructure/database" - httpServer "service/internal/infrastructure/transport/http/servers" - satuSehatFactory "service/internal/interfaces/satusehat" - "service/pkg/logger" - - satuSehatAuth "service/internal/satusehat/reference/auth" - satuSehatKfa "service/internal/satusehat/reference/kfa" - satuSehatLocation "service/internal/satusehat/reference/location" - satuSehatOrganization "service/internal/satusehat/reference/organization" - satuSehatPatient "service/internal/satusehat/reference/patient" - satuSehatPractitioner "service/internal/satusehat/reference/practitioner" - satuSehatCondition "service/internal/satusehat/usecase/condition" - satuSehatEncounter "service/internal/satusehat/usecase/encounter" - satuSehatProcedure "service/internal/satusehat/usecase/procedure" - - _ "service/docs/swagger" // Import swagger docs - - "golang.org/x/sync/errgroup" -) - -func main() { - // 1. Load Config - cfg := config.LoadConfig() - - // 2. Init Logger khusus untuk service Satu Sehat - loggerConfig := logger.Config{ - Level: cfg.Logger.Level, - Format: cfg.Logger.Format, - Output: "both", - ServiceName: "service-satusehat", // Penanda log - EnableCaller: cfg.Server.Mode != "production", - Environment: cfg.Server.Mode, - } - logger.Init(loggerConfig) - - logger.Default().Info("SatuSehat Microservice starting...", - logger.String("environment", cfg.Server.Mode), - logger.String("log_level", cfg.Logger.Level), - ) - - if err := cfg.Validate(); err != nil { - logger.Default().Fatal("Config validation failed", logger.ErrorField(err)) - } - - // 3. Init Database Manager - dbService := database.New(cfg) - defer dbService.Close() - - gormDB, err := dbService.GetGormDB("default") - if err != nil { - logger.Default().Fatal("Failed to get primary database", logger.ErrorField(err)) - } - - // 4. Init Cache - cacheFactory := cache.NewFactory(cfg.Cache) - cacheManager, err := cacheFactory.CreateManager() - if err != nil { - logger.Default().Fatal("Failed to initialize cache manager", logger.ErrorField(err)) - } - defer cacheManager.Close() - - // 5. Init Layers (Hanya Modul Satu Sehat) - satusehatFact := satuSehatFactory.NewSatuSehatFactory(cfg.SatuSehat) - satusehatClient := satusehatFact.Client() - - // - Reference Services - satuSehatAuthSvc := satuSehatAuth.NewService(satusehatClient, cacheManager) - satuSehatPatientSvc := satuSehatPatient.NewService(satuSehatPatient.NewRepository(satusehatClient)) - satuSehatPractitionerSvc := satuSehatPractitioner.NewService(satuSehatPractitioner.NewRepository(satusehatClient)) - satuSehatOrganizationSvc := satuSehatOrganization.NewService(satuSehatOrganization.NewRepository(satusehatClient)) - satuSehatLocationSvc := satuSehatLocation.NewService(satuSehatLocation.NewRepository(satusehatClient)) - satuSehatKfaSvc := satuSehatKfa.NewService(satuSehatKfa.NewRepository(satusehatClient)) - - // - Usecase Services - satuSehatEncounterSvc := satuSehatEncounter.NewService(satuSehatEncounter.NewRepository(satusehatClient, dbService)) - satuSehatProcedureSvc := satuSehatProcedure.NewService(satuSehatProcedure.NewRepository(satusehatClient)) - satuSehatConditionSvc := satuSehatCondition.NewService(satuSehatCondition.NewRepository(satusehatClient)) - - // 6. Server Orchestration - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - g, ctx := errgroup.WithContext(ctx) - - // --- Start REST Server (Hanya me-load endpoint Satu Sehat & Health) --- - if cfg.Server.REST.Enabled { - registry := &httpServer.ServiceRegistry{ - Config: cfg, - DBManager: dbService, - PrimaryDB: gormDB, - CacheManager: cacheManager, - SatuSehat: &httpServer.SatuSehatServices{ - Auth: satuSehatAuthSvc, - Patient: satuSehatPatientSvc, - Practitioner: satuSehatPractitionerSvc, - Organization: satuSehatOrganizationSvc, - Location: satuSehatLocationSvc, - KFA: satuSehatKfaSvc, - Encounter: satuSehatEncounterSvc, - Procedure: satuSehatProcedureSvc, - Condition: satuSehatConditionSvc, - }, - } - - restSrv := httpServer.NewHTTPServer(&cfg.Server.REST, registry) - g.Go(func() error { - logger.Default().Info("SatuSehat REST API running", logger.Int("port", cfg.Server.REST.Port)) - if err := restSrv.Start(&cfg.Server); err != nil && err != http.ErrServerClosed { - return err - } - return nil - }) - } - - // --- Graceful Shutdown Listener --- - g.Go(func() error { - quit := make(chan os.Signal, 1) - signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) - <-quit - logger.Default().Warn("Signal received, shutting down SatuSehat service...") - cancel() - return nil - }) - - if err := g.Wait(); err != nil { - logger.Default().Error("SatuSehat service shutdown with error", logger.ErrorField(err)) - } else { - logger.Default().Info("SatuSehat service shutdown successful") - } -} diff --git a/cmd/seeder/main.go b/cmd/seeder/main.go deleted file mode 100644 index 550a4da..0000000 --- a/cmd/seeder/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "service/internal/infrastructure/database/seeders" -) - -func main() { - seeders.MainCLI() -} diff --git a/internal/bpjs/antrol/reference/dto.go b/internal/bpjs/antrol/reference/dto.go deleted file mode 100644 index a587349..0000000 --- a/internal/bpjs/antrol/reference/dto.go +++ /dev/null @@ -1,9 +0,0 @@ -package antrol - -// Poli merepresentasikan data referensi poli dari API Antrean RS BPJS -type Poli struct { - KdPoli string `json:"kdpoli"` - NmPoli string `json:"nmpoli"` - KdSubSpesialis string `json:"kdsubspesialis"` - NmSubSpesialis string `json:"nmsubspesialis"` -} diff --git a/internal/bpjs/antrol/reference/repository.go b/internal/bpjs/antrol/reference/repository.go deleted file mode 100644 index 5e26e7a..0000000 --- a/internal/bpjs/antrol/reference/repository.go +++ /dev/null @@ -1,47 +0,0 @@ -package antrol - -import ( - "context" - "encoding/json" - "fmt" - "service/internal/interfaces/bpjs" -) - -type Repository interface { - GetRefPoli(ctx context.Context) ([]Poli, error) -} - -type repository struct { - client bpjs.BpjsClient -} - -func NewRepository(client bpjs.BpjsClient) Repository { - return &repository{client: client} -} - -// GetRefPoli fetches referensi poli from BPJS API -// -// # This function will return an array of Poli and error if any -// -// Context is used to pass the request context to the underlying -// client -// -// The function will return an error if the request to BPJS API -// fails or if the response cannot be unmarshalled into an array -// of Poli -// -// The function will return an empty array and nil error if the request -// to BPJS API succeeds but the response is an empty array -func (r *repository) GetRefPoli(ctx context.Context) ([]Poli, error) { - respBytes, err := r.client.DoRequest(ctx, "GET", "ref/poli", nil) - if err != nil { - return nil, err - } - - var result []Poli - if err := json.Unmarshal(respBytes, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal ref poli antrol response: %w", err) - } - - return result, nil -} diff --git a/internal/bpjs/antrol/reference/service.go b/internal/bpjs/antrol/reference/service.go deleted file mode 100644 index eb87208..0000000 --- a/internal/bpjs/antrol/reference/service.go +++ /dev/null @@ -1,26 +0,0 @@ -package antrol - -import ( - "context" - "service/pkg/errors" -) - -type Service interface { - GetRefPoli(ctx context.Context) ([]Poli, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetRefPoli(ctx context.Context) ([]Poli, error) { - res, err := s.repo.GetRefPoli(ctx) - if err != nil { - return nil, errors.ExternalError().Message("Gagal mengambil referensi poli Antrean RS BPJS").Cause(err).Build() - } - return res, nil -} diff --git a/internal/bpjs/aplicare/bed/dto.go b/internal/bpjs/aplicare/bed/dto.go deleted file mode 100644 index 6730e30..0000000 --- a/internal/bpjs/aplicare/bed/dto.go +++ /dev/null @@ -1,24 +0,0 @@ -package bed - -// BedData merepresentasikan payload untuk membuat, mengubah, atau mengambil data ketersediaan Bed -type BedData struct { - KodeKelas string `json:"kodekelas"` - KodeRuang string `json:"koderuang"` - NamaRuang string `json:"namaruang"` - Kapasitas int `json:"kapasitas"` - Tersedia int `json:"tersedia"` - TersediaPria int `json:"tersediapria"` - TersediaWanita int `json:"tersediawanita"` - TersediaPriaWanita int `json:"tersediapriawanita"` -} - -// BedDeletePayload merepresentasikan payload untuk menghapus data Bed -type BedDeletePayload struct { - KodeKelas string `json:"kodekelas"` - KodeRuang string `json:"koderuang"` -} - -// BedReadResponse merepresentasikan balikan dari endpoint GET Read Bed -type BedReadResponse struct { - List []BedData `json:"list"` -} diff --git a/internal/bpjs/aplicare/bed/repository.go b/internal/bpjs/aplicare/bed/repository.go deleted file mode 100644 index d0e40af..0000000 --- a/internal/bpjs/aplicare/bed/repository.go +++ /dev/null @@ -1,60 +0,0 @@ -package bed - -import ( - "context" - "encoding/json" - "fmt" - - "service/internal/interfaces/bpjs" -) - -type Repository interface { - Read(ctx context.Context, kdPpk string, start, limit int) ([]BedData, error) - Create(ctx context.Context, kdPpk string, payload BedData) error - Update(ctx context.Context, kdPpk string, payload BedData) error - Delete(ctx context.Context, kdPpk string, payload BedDeletePayload) error -} - -type repository struct { - client bpjs.BpjsClient -} - -func NewRepository(client bpjs.BpjsClient) Repository { - return &repository{client: client} -} - -func (r *repository) Read(ctx context.Context, kdPpk string, start, limit int) ([]BedData, error) { - endpoint := fmt.Sprintf("rest/bed/read/%s/%d/%d", kdPpk, start, limit) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - return nil, err - } - - var result BedReadResponse - if err := json.Unmarshal(respBytes, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal applicare read response: %w", err) - } - - return result.List, nil -} - -func (r *repository) Create(ctx context.Context, kdPpk string, payload BedData) error { - endpoint := fmt.Sprintf("rest/bed/create/%s", kdPpk) - _, err := r.client.DoRequest(ctx, "POST", endpoint, payload) - // Aplicares biasanya mengembalikan sukses di metadata yang sudah dihandle oleh client.go - return err -} - -func (r *repository) Update(ctx context.Context, kdPpk string, payload BedData) error { - // Endpoint Update Aplicares menggunakan method POST, bukan PUT - endpoint := fmt.Sprintf("rest/bed/update/%s", kdPpk) - _, err := r.client.DoRequest(ctx, "POST", endpoint, payload) - return err -} - -func (r *repository) Delete(ctx context.Context, kdPpk string, payload BedDeletePayload) error { - // Endpoint Delete Aplicares juga menggunakan method POST - endpoint := fmt.Sprintf("rest/bed/delete/%s", kdPpk) - _, err := r.client.DoRequest(ctx, "POST", endpoint, payload) - return err -} diff --git a/internal/bpjs/aplicare/bed/service.go b/internal/bpjs/aplicare/bed/service.go deleted file mode 100644 index e9f4a00..0000000 --- a/internal/bpjs/aplicare/bed/service.go +++ /dev/null @@ -1,57 +0,0 @@ -package bed - -import ( - "context" - "service/pkg/errors" -) - -type Service interface { - GetBedList(ctx context.Context, kdPpk string, start, limit int) ([]BedData, error) - CreateBed(ctx context.Context, kdPpk string, req BedData) error - UpdateBed(ctx context.Context, kdPpk string, req BedData) error - DeleteBed(ctx context.Context, kdPpk string, req BedDeletePayload) error -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetBedList(ctx context.Context, kdPpk string, start, limit int) ([]BedData, error) { - if kdPpk == "" { - return nil, errors.NewValidationError().Message("Kode PPK (Kode Faskes) wajib diisi").Build() - } - - res, err := s.repo.Read(ctx, kdPpk, start, limit) - if err != nil { - return nil, errors.ExternalError().Message("Gagal mengambil data ketersediaan tempat tidur (Aplicares)").Cause(err).Build() - } - return res, nil -} - -func (s *service) CreateBed(ctx context.Context, kdPpk string, req BedData) error { - err := s.repo.Create(ctx, kdPpk, req) - if err != nil { - return errors.ExternalError().Message("Gagal membuat data tempat tidur baru (Aplicares)").Cause(err).Build() - } - return nil -} - -func (s *service) UpdateBed(ctx context.Context, kdPpk string, req BedData) error { - err := s.repo.Update(ctx, kdPpk, req) - if err != nil { - return errors.ExternalError().Message("Gagal memperbarui data tempat tidur (Aplicares)").Cause(err).Build() - } - return nil -} - -func (s *service) DeleteBed(ctx context.Context, kdPpk string, req BedDeletePayload) error { - err := s.repo.Delete(ctx, kdPpk, req) - if err != nil { - return errors.ExternalError().Message("Gagal menghapus data tempat tidur (Aplicares)").Cause(err).Build() - } - return nil -} diff --git a/internal/bpjs/apotek/reference/dpho/dto.go b/internal/bpjs/apotek/reference/dpho/dto.go deleted file mode 100644 index e8bca9c..0000000 --- a/internal/bpjs/apotek/reference/dpho/dto.go +++ /dev/null @@ -1,11 +0,0 @@ -package dpho - -// DPHOData merepresentasikan detail referensi DPHO dari API Apotek -type DPHOData struct { - KodeObat string `json:"kodeobat"` - NamaObat string `json:"namaobat"` - PRB string `json:"prb"` - Kronis string `json:"kronis"` - Kemo string `json:"kemo"` - Harga string `json:"harga"` -} diff --git a/internal/bpjs/apotek/reference/dpho/repository.go b/internal/bpjs/apotek/reference/dpho/repository.go deleted file mode 100644 index b3574e9..0000000 --- a/internal/bpjs/apotek/reference/dpho/repository.go +++ /dev/null @@ -1,42 +0,0 @@ -package dpho - -import ( - "context" - "encoding/json" - "fmt" - - "service/internal/interfaces/bpjs" -) - -type Repository interface { - GetDPHO(ctx context.Context) ([]DPHOData, error) -} - -type repository struct { - client bpjs.BpjsClient -} - -func NewRepository(client bpjs.BpjsClient) Repository { - return &repository{client: client} -} - -func (r *repository) GetDPHO(ctx context.Context) ([]DPHOData, error) { - respBytes, err := r.client.DoRequest(ctx, "GET", "referensi/dpho", nil) - if err != nil { - return nil, err - } - - // Coba parsing ke dalam format object { "list": [...] } - var result struct { - List []DPHOData `json:"list"` - } - if err := json.Unmarshal(respBytes, &result); err != nil { - // Fallback jika API mengembalikan array langsung [...] - var directList []DPHOData - if err2 := json.Unmarshal(respBytes, &directList); err2 == nil { - return directList, nil - } - return nil, fmt.Errorf("failed to unmarshal apotek dpho response: %w", err) - } - return result.List, nil -} diff --git a/internal/bpjs/apotek/reference/dpho/service.go b/internal/bpjs/apotek/reference/dpho/service.go deleted file mode 100644 index 8812176..0000000 --- a/internal/bpjs/apotek/reference/dpho/service.go +++ /dev/null @@ -1,26 +0,0 @@ -package dpho - -import ( - "context" - "service/pkg/errors" -) - -type Service interface { - GetDPHO(ctx context.Context) ([]DPHOData, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetDPHO(ctx context.Context) ([]DPHOData, error) { - res, err := s.repo.GetDPHO(ctx) - if err != nil { - return nil, errors.ExternalError().Message("Gagal mengambil referensi DPHO Apotek BPJS").Cause(err).Build() - } - return res, nil -} diff --git a/internal/bpjs/apotek/reference/poli/dto.go b/internal/bpjs/apotek/reference/poli/dto.go deleted file mode 100644 index 4862b07..0000000 --- a/internal/bpjs/apotek/reference/poli/dto.go +++ /dev/null @@ -1,7 +0,0 @@ -package poli - -// PoliData merepresentasikan detail referensi Poli dari API Apotek -type PoliData struct { - KodePoli string `json:"kodepoli"` - NamaPoli string `json:"namapoli"` -} diff --git a/internal/bpjs/apotek/reference/poli/repository.go b/internal/bpjs/apotek/reference/poli/repository.go deleted file mode 100644 index e458c61..0000000 --- a/internal/bpjs/apotek/reference/poli/repository.go +++ /dev/null @@ -1,41 +0,0 @@ -package poli - -import ( - "context" - "encoding/json" - "fmt" - - "service/internal/interfaces/bpjs" -) - -type Repository interface { - GetPoli(ctx context.Context, param string) ([]PoliData, error) -} - -type repository struct { - client bpjs.BpjsClient -} - -func NewRepository(client bpjs.BpjsClient) Repository { - return &repository{client: client} -} - -func (r *repository) GetPoli(ctx context.Context, param string) ([]PoliData, error) { - endpoint := fmt.Sprintf("referensi/poli/%s", param) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - return nil, err - } - - var result struct { - List []PoliData `json:"list"` - } - if err := json.Unmarshal(respBytes, &result); err != nil { - var directList []PoliData - if err2 := json.Unmarshal(respBytes, &directList); err2 == nil { - return directList, nil - } - return nil, fmt.Errorf("failed to unmarshal apotek poli response: %w", err) - } - return result.List, nil -} diff --git a/internal/bpjs/apotek/reference/poli/service.go b/internal/bpjs/apotek/reference/poli/service.go deleted file mode 100644 index 86db3aa..0000000 --- a/internal/bpjs/apotek/reference/poli/service.go +++ /dev/null @@ -1,29 +0,0 @@ -package poli - -import ( - "context" - "service/pkg/errors" -) - -type Service interface { - GetPoli(ctx context.Context, param string) ([]PoliData, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetPoli(ctx context.Context, param string) ([]PoliData, error) { - if param == "" { - return nil, errors.NewValidationError().Message("Parameter pencarian Poli wajib diisi").Build() - } - res, err := s.repo.GetPoli(ctx, param) - if err != nil { - return nil, errors.ExternalError().Message("Gagal mengambil referensi Poli Apotek BPJS").Cause(err).Build() - } - return res, nil -} diff --git a/internal/bpjs/vclaim/peserta/dto.go b/internal/bpjs/vclaim/peserta/dto.go deleted file mode 100644 index bd5fe8e..0000000 --- a/internal/bpjs/vclaim/peserta/dto.go +++ /dev/null @@ -1,53 +0,0 @@ -package peserta - -// PesertaResponse merepresentasikan wrapper data dari API BPJS VClaim -type PesertaResponse struct { - Peserta PesertaData `json:"peserta"` -} - -// PesertaData merepresentasikan entitas detail Peserta BPJS -type PesertaData struct { - NoKartu string `json:"noKartu"` - Nik string `json:"nik"` - Nama string `json:"nama"` - Pisa string `json:"pisa"` - Sex string `json:"sex"` - Umur Umur `json:"umur"` - TglLahir string `json:"tglLahir"` - StatusPeserta StatusPeserta `json:"statusPeserta"` - ProviderUmum ProviderUmum `json:"provUmum"` - JenisPeserta JenisPeserta `json:"jenisPeserta"` - HakKelas HakKelas `json:"hakKelas"` - Informasi Informasi `json:"informasi"` -} - -type Umur struct { - UmurSaatPelayanan string `json:"umurSaatPelayanan"` - UmurSekarang string `json:"umurSekarang"` -} - -type StatusPeserta struct { - Kode string `json:"kode"` - Keterangan string `json:"keterangan"` -} - -type ProviderUmum struct { - KdProvider string `json:"kdProvider"` - NmProvider string `json:"nmProvider"` -} - -type JenisPeserta struct { - Kode string `json:"kode"` - Keterangan string `json:"keterangan"` -} - -type HakKelas struct { - Kode string `json:"kode"` - Keterangan string `json:"keterangan"` -} - -type Informasi struct { - Dinsos string `json:"dinsos"` - ProlanisPRB string `json:"prolanisPRB"` - NoSKTM string `json:"noSKTM"` -} diff --git a/internal/bpjs/vclaim/peserta/repository.go b/internal/bpjs/vclaim/peserta/repository.go deleted file mode 100644 index 00b9f03..0000000 --- a/internal/bpjs/vclaim/peserta/repository.go +++ /dev/null @@ -1,52 +0,0 @@ -package peserta - -import ( - "context" - "encoding/json" - "fmt" - - "service/internal/interfaces/bpjs" -) - -type Repository interface { - GetByNoKartu(ctx context.Context, noKartu, tglSEP string) (*PesertaData, error) - GetByNIK(ctx context.Context, nik, tglSEP string) (*PesertaData, error) -} - -type repository struct { - client bpjs.BpjsClient -} - -func NewRepository(client bpjs.BpjsClient) Repository { - return &repository{client: client} -} - -func (r *repository) GetByNoKartu(ctx context.Context, noKartu, tglSEP string) (*PesertaData, error) { - endpoint := fmt.Sprintf("Peserta/nokartu/%s/tglSEP/%s", noKartu, tglSEP) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - return nil, err - } - - var result PesertaResponse - if err := json.Unmarshal(respBytes, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal peserta response: %w", err) - } - - return &result.Peserta, nil -} - -func (r *repository) GetByNIK(ctx context.Context, nik, tglSEP string) (*PesertaData, error) { - endpoint := fmt.Sprintf("Peserta/nik/%s/tglSEP/%s", nik, tglSEP) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - return nil, err - } - - var result PesertaResponse - if err := json.Unmarshal(respBytes, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal peserta response: %w", err) - } - - return &result.Peserta, nil -} diff --git a/internal/bpjs/vclaim/peserta/service.go b/internal/bpjs/vclaim/peserta/service.go deleted file mode 100644 index d132f69..0000000 --- a/internal/bpjs/vclaim/peserta/service.go +++ /dev/null @@ -1,43 +0,0 @@ -package peserta - -import ( - "context" - "service/pkg/errors" -) - -type Service interface { - GetPesertaByNoKartu(ctx context.Context, noKartu, tglSEP string) (*PesertaData, error) - GetPesertaByNIK(ctx context.Context, nik, tglSEP string) (*PesertaData, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetPesertaByNoKartu(ctx context.Context, noKartu, tglSEP string) (*PesertaData, error) { - if noKartu == "" || tglSEP == "" { - return nil, errors.NewValidationError().Message("Nomor Kartu dan Tanggal SEP wajib diisi").Build() - } - - res, err := s.repo.GetByNoKartu(ctx, noKartu, tglSEP) - if err != nil { - return nil, errors.ExternalError().Message("Gagal mengambil data peserta BPJS berdasarkan No Kartu").Cause(err).Build() - } - return res, nil -} - -func (s *service) GetPesertaByNIK(ctx context.Context, nik, tglSEP string) (*PesertaData, error) { - if nik == "" || tglSEP == "" { - return nil, errors.NewValidationError().Message("NIK dan Tanggal SEP wajib diisi").Build() - } - - res, err := s.repo.GetByNIK(ctx, nik, tglSEP) - if err != nil { - return nil, errors.ExternalError().Message("Gagal mengambil data peserta BPJS berdasarkan NIK").Cause(err).Build() - } - return res, nil -} diff --git a/internal/bpjs/vclaim/sep/dto.go b/internal/bpjs/vclaim/sep/dto.go deleted file mode 100644 index abb3c14..0000000 --- a/internal/bpjs/vclaim/sep/dto.go +++ /dev/null @@ -1,136 +0,0 @@ -package sep - -// CreateSEPRequest adalah data payload untuk insert pembuatan SEP. -// Strukturnya mengikuti format yang dibutuhkan oleh API VClaim 2.0. -type CreateSEPRequest struct { - Request struct { - Sep `json:"t_sep"` - } `json:"request"` -} - -// Sep adalah detail data untuk pembuatan SEP. -type Sep struct { - NoKartu string `json:"noKartu"` - TglSep string `json:"tglSep"` - PpkPelayanan string `json:"ppkPelayanan"` - JnsPelayanan string `json:"jnsPelayanan"` - KlsRawat KlsRawat `json:"klsRawat"` - NoMR string `json:"noMR"` - Rujukan Rujukan `json:"rujukan"` - Catatan string `json:"catatan"` - DiagAwal string `json:"diagAwal"` - Poli Poli `json:"poli"` - Cob string `json:"cob"` - Katarak string `json:"katarak"` - Jaminan Jaminan `json:"jaminan"` - Tujuan string `json:"tujuan"` - FlagProcedure string `json:"flagProcedure"` - KdPenunjang string `json:"kdPenunjang"` - AssesmentPel string `json:"assesmentPel"` - NoSurat string `json:"noSurat"` - KodeDPJP string `json:"kodeDPJP"` - DpjpLayan string `json:"dpjpLayan"` - NoTelp string `json:"noTelp"` - User string `json:"user"` -} - -type KlsRawat struct { - KlsRawatHak string `json:"klsRawatHak"` - KlsRawatNaik string `json:"klsRawatNaik,omitempty"` - Pembiayaan string `json:"pembiayaan,omitempty"` - PenanggungJawab string `json:"penanggungJawab,omitempty"` -} - -type Rujukan struct { - AsalRujukan string `json:"asalRujukan"` - TglRujukan string `json:"tglRujukan"` - NoRujukan string `json:"noRujukan"` - PpkRujukan string `json:"ppkRujukan"` -} - -type Poli struct { - Tujuan string `json:"tujuan"` - Eksekutif string `json:"eksekutif"` -} - -type Jaminan struct { - LakaLantas string `json:"lakaLantas"` - NoLP string `json:"noLP,omitempty"` - Penjamin Penjamin `json:"penjamin,omitempty"` -} - -type Penjamin struct { - TglKejadian string `json:"tglKejadian,omitempty"` - Keterangan string `json:"keterangan,omitempty"` - Suplesi struct { - Suplesi string `json:"suplesi"` - NoSepSuplesi string `json:"noSepSuplesi,omitempty"` - LokasiLaka struct { - KdPropinsi string `json:"kdPropinsi"` - KdKabupaten string `json:"kdKabupaten"` - KdKecamatan string `json:"kdKecamatan"` - } `json:"lokasiLaka,omitempty"` - } `json:"suplesi,omitempty"` -} - -// CreateSEPResponse adalah data balikan setelah SEP berhasil dicreate. -type CreateSEPResponse struct { - Sep struct { - NoSep string `json:"noSep"` - TglSep string `json:"tglSep"` - Poli string `json:"poli"` - Diagnosa string `json:"diagnosa"` - Catatan string `json:"catatan"` - JnsRawat string `json:"jnsRawat"` - KlsRawat string `json:"klsRawat"` - Penjamin string `json:"penjamin"` - } `json:"sep"` -} - -// UpdateSEPRequest adalah data payload untuk update SEP. -type UpdateSEPRequest struct { - Request struct { - Sep struct { - NoSep string `json:"noSep"` - KlsRawat KlsRawat `json:"klsRawat"` - NoMR string `json:"noMR"` - Catatan string `json:"catatan"` - DiagAwal string `json:"diagAwal"` - Poli Poli `json:"poli"` - Eksekutif string `json:"eksekutif"` - Cob string `json:"cob"` - Katarak string `json:"katarak"` - Jaminan Jaminan `json:"jaminan"` - NoTelp string `json:"noTelp"` - User string `json:"user"` - } `json:"t_sep"` - } `json:"request"` -} - -// DeleteSEPRequest adalah data payload untuk menghapus SEP. -type DeleteSEPRequest struct { - Request struct { - Sep struct { - NoSep string `json:"noSep"` - User string `json:"user"` - } `json:"t_sep"` - } `json:"request"` -} - -// SEPDetailResponse adalah data balikan untuk detail SEP. -type SEPDetailResponse struct { - Catatan string `json:"catatan"` - Diagnosa string `json:"diagnosa"` - JnsPelayanan string `json:"jnsPelayanan"` - KelasRawat string `json:"kelasRawat"` - NoRujukan string `json:"noRujukan"` - NoSep string `json:"noSep"` - Penjamin string `json:"penjamin"` - Peserta struct { - Nama string `json:"nama"` - NoKartu string `json:"noKartu"` - NoMr string `json:"noMr"` - } `json:"peserta"` - Poli string `json:"poli"` - TglSep string `json:"tglSep"` -} diff --git a/internal/bpjs/vclaim/sep/repository.go b/internal/bpjs/vclaim/sep/repository.go deleted file mode 100644 index 68aa63f..0000000 --- a/internal/bpjs/vclaim/sep/repository.go +++ /dev/null @@ -1,67 +0,0 @@ -package sep - -import ( - "context" - "encoding/json" - "fmt" - "service/internal/interfaces/bpjs" -) - -type Repository interface { - CreateSEP(ctx context.Context, req CreateSEPRequest) (*CreateSEPResponse, error) - UpdateSEP(ctx context.Context, req UpdateSEPRequest) (string, error) - DeleteSEP(ctx context.Context, req DeleteSEPRequest) (string, error) - GetSEP(ctx context.Context, noSEP string) (*SEPDetailResponse, error) -} - -type repository struct { - client bpjs.BpjsClient -} - -func NewRepository(client bpjs.BpjsClient) Repository { - return &repository{client: client} -} - -func (r *repository) CreateSEP(ctx context.Context, req CreateSEPRequest) (*CreateSEPResponse, error) { - endpoint := "SEP/2.0/insert" - decryptedBytes, err := r.client.DoRequest(ctx, "POST", endpoint, req) - if err != nil { - return nil, err - } - var result CreateSEPResponse - return &result, json.Unmarshal(decryptedBytes, &result) -} - -func (r *repository) UpdateSEP(ctx context.Context, req UpdateSEPRequest) (string, error) { - endpoint := "SEP/2.0/update" - decryptedBytes, err := r.client.DoRequest(ctx, "PUT", endpoint, req) - if err != nil { - return "", err - } - // Response dari update SEP biasanya hanya string nomor SEP itu sendiri - return string(decryptedBytes), nil -} - -func (r *repository) DeleteSEP(ctx context.Context, req DeleteSEPRequest) (string, error) { - endpoint := "SEP/2.0/delete" - // BPJS API untuk delete menggunakan POST method dengan payload spesifik - decryptedBytes, err := r.client.DoRequest(ctx, "POST", endpoint, req) - if err != nil { - return "", err - } - // Response dari delete SEP biasanya hanya string "OK" atau pesan konfirmasi - return string(decryptedBytes), nil -} - -func (r *repository) GetSEP(ctx context.Context, noSEP string) (*SEPDetailResponse, error) { - endpoint := fmt.Sprintf("SEP/%s", noSEP) - decryptedBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - return nil, err - } - var result SEPDetailResponse - if err := json.Unmarshal(decryptedBytes, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal SEP detail response: %w", err) - } - return &result, nil -} diff --git a/internal/bpjs/vclaim/sep/service.go b/internal/bpjs/vclaim/sep/service.go deleted file mode 100644 index 3cc571c..0000000 --- a/internal/bpjs/vclaim/sep/service.go +++ /dev/null @@ -1,41 +0,0 @@ -package sep - -import ( - "context" -) - -type Service interface { - Create(ctx context.Context, req CreateSEPRequest) (*CreateSEPResponse, error) - Update(ctx context.Context, req UpdateSEPRequest) (string, error) - Delete(ctx context.Context, req DeleteSEPRequest) (string, error) - GetDetail(ctx context.Context, noSEP string) (*SEPDetailResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req CreateSEPRequest) (*CreateSEPResponse, error) { - // Anda bisa menambahkan validasi atau logika bisnis di sini sebelum memanggil repository. - return s.repo.CreateSEP(ctx, req) -} - -func (s *service) Update(ctx context.Context, req UpdateSEPRequest) (string, error) { - // TODO: Tambahkan validasi untuk request update di sini. - // Contoh: if req.Request.Sep.NoSep == "" { return "", errors.New("nomor SEP wajib diisi") } - return s.repo.UpdateSEP(ctx, req) -} - -func (s *service) Delete(ctx context.Context, req DeleteSEPRequest) (string, error) { - // TODO: Tambahkan validasi untuk request delete di sini. - return s.repo.DeleteSEP(ctx, req) -} - -func (s *service) GetDetail(ctx context.Context, noSEP string) (*SEPDetailResponse, error) { - // TODO: Tambahkan validasi untuk noSEP di sini. - return s.repo.GetSEP(ctx, noSEP) -} diff --git a/internal/infrastructure/transport/grpc/gen/permission/v1/permission.pb.go b/internal/infrastructure/transport/grpc/gen/permission/v1/permission.pb.go deleted file mode 100644 index 19f32fe..0000000 --- a/internal/infrastructure/transport/grpc/gen/permission/v1/permission.pb.go +++ /dev/null @@ -1,484 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc v3.12.4 -// source: internal/infrastructure/transport/grpc/proto/permission/v1/permission.proto - -package permissionV1 - -import ( - reflect "reflect" - sync "sync" - unsafe "unsafe" - - wrappers "github.com/golang/protobuf/ptypes/wrappers" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Pesan request untuk RPC GetRolePermissionTree. -type GetRolePermissionTreeRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RoleKeycloak string `protobuf:"bytes,1,opt,name=role_keycloak,json=roleKeycloak,proto3" json:"role_keycloak,omitempty"` - GroupKeycloak []string `protobuf:"bytes,2,rep,name=group_keycloak,json=groupKeycloak,proto3" json:"group_keycloak,omitempty"` - // Menggunakan wrapper BoolValue untuk membedakan antara 'false' dan 'tidak diset'. - ActiveOnly *wrappers.BoolValue `protobuf:"bytes,3,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetRolePermissionTreeRequest) Reset() { - *x = GetRolePermissionTreeRequest{} - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetRolePermissionTreeRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetRolePermissionTreeRequest) ProtoMessage() {} - -func (x *GetRolePermissionTreeRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetRolePermissionTreeRequest.ProtoReflect.Descriptor instead. -func (*GetRolePermissionTreeRequest) Descriptor() ([]byte, []int) { - return file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescGZIP(), []int{0} -} - -func (x *GetRolePermissionTreeRequest) GetRoleKeycloak() string { - if x != nil { - return x.RoleKeycloak - } - return "" -} - -func (x *GetRolePermissionTreeRequest) GetGroupKeycloak() []string { - if x != nil { - return x.GroupKeycloak - } - return nil -} - -func (x *GetRolePermissionTreeRequest) GetActiveOnly() *wrappers.BoolValue { - if x != nil { - return x.ActiveOnly - } - return nil -} - -// Pesan response untuk RPC GetRolePermissionTree. -type RolePermissionTreeResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Data *RolePermissionData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *RolePermissionTreeResponse) Reset() { - *x = RolePermissionTreeResponse{} - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *RolePermissionTreeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RolePermissionTreeResponse) ProtoMessage() {} - -func (x *RolePermissionTreeResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RolePermissionTreeResponse.ProtoReflect.Descriptor instead. -func (*RolePermissionTreeResponse) Descriptor() ([]byte, []int) { - return file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescGZIP(), []int{1} -} - -func (x *RolePermissionTreeResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *RolePermissionTreeResponse) GetData() *RolePermissionData { - if x != nil { - return x.Data - } - return nil -} - -type RolePermissionData struct { - state protoimpl.MessageState `protogen:"open.v1"` - Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"` - Group []string `protobuf:"bytes,2,rep,name=group,proto3" json:"group,omitempty"` - Access []*AccessTreeItem `protobuf:"bytes,3,rep,name=access,proto3" json:"access,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *RolePermissionData) Reset() { - *x = RolePermissionData{} - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *RolePermissionData) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RolePermissionData) ProtoMessage() {} - -func (x *RolePermissionData) ProtoReflect() protoreflect.Message { - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RolePermissionData.ProtoReflect.Descriptor instead. -func (*RolePermissionData) Descriptor() ([]byte, []int) { - return file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescGZIP(), []int{2} -} - -func (x *RolePermissionData) GetRole() string { - if x != nil { - return x.Role - } - return "" -} - -func (x *RolePermissionData) GetGroup() []string { - if x != nil { - return x.Group - } - return nil -} - -func (x *RolePermissionData) GetAccess() []*AccessTreeItem { - if x != nil { - return x.Access - } - return nil -} - -type AccessTreeItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Icon string `protobuf:"bytes,3,opt,name=icon,proto3" json:"icon,omitempty"` - Url string `protobuf:"bytes,4,opt,name=url,proto3" json:"url,omitempty"` - Level int32 `protobuf:"varint,5,opt,name=level,proto3" json:"level,omitempty"` - Sort int32 `protobuf:"varint,6,opt,name=sort,proto3" json:"sort,omitempty"` - Active bool `protobuf:"varint,7,opt,name=active,proto3" json:"active,omitempty"` - Permission *Permission `protobuf:"bytes,8,opt,name=permission,proto3,oneof" json:"permission,omitempty"` - Children []*AccessTreeItem `protobuf:"bytes,9,rep,name=children,proto3" json:"children,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AccessTreeItem) Reset() { - *x = AccessTreeItem{} - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AccessTreeItem) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AccessTreeItem) ProtoMessage() {} - -func (x *AccessTreeItem) ProtoReflect() protoreflect.Message { - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AccessTreeItem.ProtoReflect.Descriptor instead. -func (*AccessTreeItem) Descriptor() ([]byte, []int) { - return file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescGZIP(), []int{3} -} - -func (x *AccessTreeItem) GetId() int64 { - if x != nil { - return x.Id - } - return 0 -} - -func (x *AccessTreeItem) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *AccessTreeItem) GetIcon() string { - if x != nil { - return x.Icon - } - return "" -} - -func (x *AccessTreeItem) GetUrl() string { - if x != nil { - return x.Url - } - return "" -} - -func (x *AccessTreeItem) GetLevel() int32 { - if x != nil { - return x.Level - } - return 0 -} - -func (x *AccessTreeItem) GetSort() int32 { - if x != nil { - return x.Sort - } - return 0 -} - -func (x *AccessTreeItem) GetActive() bool { - if x != nil { - return x.Active - } - return false -} - -func (x *AccessTreeItem) GetPermission() *Permission { - if x != nil { - return x.Permission - } - return nil -} - -func (x *AccessTreeItem) GetChildren() []*AccessTreeItem { - if x != nil { - return x.Children - } - return nil -} - -type Permission struct { - state protoimpl.MessageState `protogen:"open.v1"` - Create bool `protobuf:"varint,1,opt,name=create,proto3" json:"create,omitempty"` - Read bool `protobuf:"varint,2,opt,name=read,proto3" json:"read,omitempty"` - Update bool `protobuf:"varint,3,opt,name=update,proto3" json:"update,omitempty"` - Delete bool `protobuf:"varint,4,opt,name=delete,proto3" json:"delete,omitempty"` - Disable bool `protobuf:"varint,5,opt,name=disable,proto3" json:"disable,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Permission) Reset() { - *x = Permission{} - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Permission) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Permission) ProtoMessage() {} - -func (x *Permission) ProtoReflect() protoreflect.Message { - mi := &file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Permission.ProtoReflect.Descriptor instead. -func (*Permission) Descriptor() ([]byte, []int) { - return file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescGZIP(), []int{4} -} - -func (x *Permission) GetCreate() bool { - if x != nil { - return x.Create - } - return false -} - -func (x *Permission) GetRead() bool { - if x != nil { - return x.Read - } - return false -} - -func (x *Permission) GetUpdate() bool { - if x != nil { - return x.Update - } - return false -} - -func (x *Permission) GetDelete() bool { - if x != nil { - return x.Delete - } - return false -} - -func (x *Permission) GetDisable() bool { - if x != nil { - return x.Disable - } - return false -} - -var File_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto protoreflect.FileDescriptor - -const file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDesc = "" + - "\n" + - "Kinternal/infrastructure/transport/grpc/proto/permission/v1/permission.proto\x12\rpermission.v1\x1a\x1egoogle/protobuf/wrappers.proto\"\xa7\x01\n" + - "\x1cGetRolePermissionTreeRequest\x12#\n" + - "\rrole_keycloak\x18\x01 \x01(\tR\froleKeycloak\x12%\n" + - "\x0egroup_keycloak\x18\x02 \x03(\tR\rgroupKeycloak\x12;\n" + - "\vactive_only\x18\x03 \x01(\v2\x1a.google.protobuf.BoolValueR\n" + - "activeOnly\"m\n" + - "\x1aRolePermissionTreeResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x125\n" + - "\x04data\x18\x02 \x01(\v2!.permission.v1.RolePermissionDataR\x04data\"u\n" + - "\x12RolePermissionData\x12\x12\n" + - "\x04role\x18\x01 \x01(\tR\x04role\x12\x14\n" + - "\x05group\x18\x02 \x03(\tR\x05group\x125\n" + - "\x06access\x18\x03 \x03(\v2\x1d.permission.v1.AccessTreeItemR\x06access\"\xa6\x02\n" + - "\x0eAccessTreeItem\x12\x0e\n" + - "\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" + - "\x04icon\x18\x03 \x01(\tR\x04icon\x12\x10\n" + - "\x03url\x18\x04 \x01(\tR\x03url\x12\x14\n" + - "\x05level\x18\x05 \x01(\x05R\x05level\x12\x12\n" + - "\x04sort\x18\x06 \x01(\x05R\x04sort\x12\x16\n" + - "\x06active\x18\a \x01(\bR\x06active\x12>\n" + - "\n" + - "permission\x18\b \x01(\v2\x19.permission.v1.PermissionH\x00R\n" + - "permission\x88\x01\x01\x129\n" + - "\bchildren\x18\t \x03(\v2\x1d.permission.v1.AccessTreeItemR\bchildrenB\r\n" + - "\v_permission\"\x82\x01\n" + - "\n" + - "Permission\x12\x16\n" + - "\x06create\x18\x01 \x01(\bR\x06create\x12\x12\n" + - "\x04read\x18\x02 \x01(\bR\x04read\x12\x16\n" + - "\x06update\x18\x03 \x01(\bR\x06update\x12\x16\n" + - "\x06delete\x18\x04 \x01(\bR\x06delete\x12\x18\n" + - "\adisable\x18\x05 \x01(\bR\adisable2\x87\x01\n" + - "\x14RolPermissionService\x12o\n" + - "\x15GetRolePermissionTree\x12+.permission.v1.GetRolePermissionTreeRequest\x1a).permission.v1.RolePermissionTreeResponseBGZEinternal/infrastructure/transport/grpc/gen/permission/v1;permissionV1b\x06proto3" - -var ( - file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescOnce sync.Once - file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescData []byte -) - -func file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescGZIP() []byte { - file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescOnce.Do(func() { - file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDesc), len(file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDesc))) - }) - return file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDescData -} - -var file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_goTypes = []any{ - (*GetRolePermissionTreeRequest)(nil), // 0: permission.v1.GetRolePermissionTreeRequest - (*RolePermissionTreeResponse)(nil), // 1: permission.v1.RolePermissionTreeResponse - (*RolePermissionData)(nil), // 2: permission.v1.RolePermissionData - (*AccessTreeItem)(nil), // 3: permission.v1.AccessTreeItem - (*Permission)(nil), // 4: permission.v1.Permission - (*wrappers.BoolValue)(nil), // 5: google.protobuf.BoolValue -} -var file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_depIdxs = []int32{ - 5, // 0: permission.v1.GetRolePermissionTreeRequest.active_only:type_name -> google.protobuf.BoolValue - 2, // 1: permission.v1.RolePermissionTreeResponse.data:type_name -> permission.v1.RolePermissionData - 3, // 2: permission.v1.RolePermissionData.access:type_name -> permission.v1.AccessTreeItem - 4, // 3: permission.v1.AccessTreeItem.permission:type_name -> permission.v1.Permission - 3, // 4: permission.v1.AccessTreeItem.children:type_name -> permission.v1.AccessTreeItem - 0, // 5: permission.v1.RolPermissionService.GetRolePermissionTree:input_type -> permission.v1.GetRolePermissionTreeRequest - 1, // 6: permission.v1.RolPermissionService.GetRolePermissionTree:output_type -> permission.v1.RolePermissionTreeResponse - 6, // [6:7] is the sub-list for method output_type - 5, // [5:6] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name -} - -func init() { file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_init() } -func file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_init() { - if File_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto != nil { - return - } - file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes[3].OneofWrappers = []any{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDesc), len(file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_rawDesc)), - NumEnums: 0, - NumMessages: 5, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_goTypes, - DependencyIndexes: file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_depIdxs, - MessageInfos: file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_msgTypes, - }.Build() - File_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto = out.File - file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_goTypes = nil - file_internal_infrastructure_transport_grpc_proto_permission_v1_permission_proto_depIdxs = nil -} diff --git a/internal/infrastructure/transport/grpc/gen/permission/v1/permission_grpc.pb.go b/internal/infrastructure/transport/grpc/gen/permission/v1/permission_grpc.pb.go deleted file mode 100644 index 91911f4..0000000 --- a/internal/infrastructure/transport/grpc/gen/permission/v1/permission_grpc.pb.go +++ /dev/null @@ -1,128 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.0 -// - protoc v3.12.4 -// source: internal/infrastructure/transport/grpc/proto/permission/v1/permission.proto - -package permissionV1 - -import ( - context "context" - - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - RolPermissionService_GetRolePermissionTree_FullMethodName = "/permission.v1.RolPermissionService/GetRolePermissionTree" -) - -// RolPermissionServiceClient is the client API for RolPermissionService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -// -// Definisi service. -type RolPermissionServiceClient interface { - // Mengambil permission tree untuk role dan/atau group tertentu. - GetRolePermissionTree(ctx context.Context, in *GetRolePermissionTreeRequest, opts ...grpc.CallOption) (*RolePermissionTreeResponse, error) -} - -type rolPermissionServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewRolPermissionServiceClient(cc grpc.ClientConnInterface) RolPermissionServiceClient { - return &rolPermissionServiceClient{cc} -} - -func (c *rolPermissionServiceClient) GetRolePermissionTree(ctx context.Context, in *GetRolePermissionTreeRequest, opts ...grpc.CallOption) (*RolePermissionTreeResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(RolePermissionTreeResponse) - err := c.cc.Invoke(ctx, RolPermissionService_GetRolePermissionTree_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -// RolPermissionServiceServer is the server API for RolPermissionService service. -// All implementations must embed UnimplementedRolPermissionServiceServer -// for forward compatibility. -// -// Definisi service. -type RolPermissionServiceServer interface { - // Mengambil permission tree untuk role dan/atau group tertentu. - GetRolePermissionTree(context.Context, *GetRolePermissionTreeRequest) (*RolePermissionTreeResponse, error) - mustEmbedUnimplementedRolPermissionServiceServer() -} - -// UnimplementedRolPermissionServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedRolPermissionServiceServer struct{} - -func (UnimplementedRolPermissionServiceServer) GetRolePermissionTree(context.Context, *GetRolePermissionTreeRequest) (*RolePermissionTreeResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetRolePermissionTree not implemented") -} -func (UnimplementedRolPermissionServiceServer) mustEmbedUnimplementedRolPermissionServiceServer() {} -func (UnimplementedRolPermissionServiceServer) testEmbeddedByValue() {} - -// UnsafeRolPermissionServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to RolPermissionServiceServer will -// result in compilation errors. -type UnsafeRolPermissionServiceServer interface { - mustEmbedUnimplementedRolPermissionServiceServer() -} - -func RegisterRolPermissionServiceServer(s grpc.ServiceRegistrar, srv RolPermissionServiceServer) { - // If the following call panics, it indicates UnimplementedRolPermissionServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&RolPermissionService_ServiceDesc, srv) -} - -func _RolPermissionService_GetRolePermissionTree_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetRolePermissionTreeRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RolPermissionServiceServer).GetRolePermissionTree(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: RolPermissionService_GetRolePermissionTree_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RolPermissionServiceServer).GetRolePermissionTree(ctx, req.(*GetRolePermissionTreeRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// RolPermissionService_ServiceDesc is the grpc.ServiceDesc for RolPermissionService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var RolPermissionService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "permission.v1.RolPermissionService", - HandlerType: (*RolPermissionServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetRolePermissionTree", - Handler: _RolPermissionService_GetRolePermissionTree_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "internal/infrastructure/transport/grpc/proto/permission/v1/permission.proto", -} diff --git a/internal/infrastructure/transport/grpc/handlers/handler.go b/internal/infrastructure/transport/grpc/handlers/handler.go deleted file mode 100644 index 0dc2a57..0000000 --- a/internal/infrastructure/transport/grpc/handlers/handler.go +++ /dev/null @@ -1,32 +0,0 @@ -package handlers - -import ( - "service/pkg/errors" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// / handleServiceError mengkonversi error dari service layer ke gRPC status error -func handleServiceError(err error) error { - appErr := errors.FromError(err) - if appErr == nil { - return status.Error(codes.Internal, "internal server error") - } - - // Mapping kategori error ke gRPC codes - switch appErr.Category() { - case errors.CategoryValidation: - return status.Error(codes.InvalidArgument, appErr.Error()) - case errors.CategoryNotFound: - return status.Error(codes.NotFound, appErr.Error()) - case errors.CategoryConflict: - return status.Error(codes.AlreadyExists, appErr.Error()) - case errors.CategoryUnauthorized: - return status.Error(codes.Unauthenticated, appErr.Error()) - case errors.CategoryForbidden: - return status.Error(codes.PermissionDenied, appErr.Error()) - default: - return status.Error(codes.Internal, appErr.Error()) - } -} diff --git a/internal/infrastructure/transport/grpc/handlers/permission_handler.go b/internal/infrastructure/transport/grpc/handlers/permission_handler.go deleted file mode 100644 index fd3a207..0000000 --- a/internal/infrastructure/transport/grpc/handlers/permission_handler.go +++ /dev/null @@ -1,50 +0,0 @@ -package handlers - -import ( - "context" - "service/internal/infrastructure/transport/grpc/mappers" - "service/internal/master/role/permission" - - // Asumsi path ke proto-generated file - permissionV1 "service/internal/infrastructure/transport/grpc/gen/permission/v1" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// PermissionHandler mengimplementasikan gRPC service untuk role permission. -type PermissionHandler struct { - permissionV1.UnimplementedRolPermissionServiceServer - service permission.Service -} - -// NewPermissionHandler membuat instance baru dari PermissionHandler. -func NewPermissionHandler(service permission.Service) *PermissionHandler { - return &PermissionHandler{ - service: service, - } -} - -// GetRolePermissionTree adalah implementasi dari RPC. -func (h *PermissionHandler) GetRolePermissionTree(ctx context.Context, req *permissionV1.GetRolePermissionTreeRequest) (*permissionV1.RolePermissionTreeResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "request cannot be nil") - } - - // Konversi wrapper BoolValue ke pointer *bool yang diharapkan oleh service - var activeOnly *bool - if val := req.GetActiveOnly(); val != nil { - b := val.GetValue() - activeOnly = &b - } - - tree, err := h.service.GetRolePermissionTree(ctx, req.GetRoleKeycloak(), req.GetGroupKeycloak(), activeOnly) - if err != nil { - return nil, handleServiceError(err) - } - - // Menggunakan mapper untuk mengubah hasil dari service ke format proto - protoResponse := mappers.MapRolePermissionTreeToProto(tree) - - return protoResponse, nil -} diff --git a/internal/infrastructure/transport/grpc/mappers/mapper.go b/internal/infrastructure/transport/grpc/mappers/mapper.go deleted file mode 100644 index dc9b60a..0000000 --- a/internal/infrastructure/transport/grpc/mappers/mapper.go +++ /dev/null @@ -1,18 +0,0 @@ -package mappers - -import "fmt" - -func convertToString(value interface{}) string { - if value == nil { - return "" - } - - switch v := value.(type) { - case string: - return v - case int, int64, float64: - return fmt.Sprintf("%v", v) - default: - return fmt.Sprintf("%v", v) - } -} diff --git a/internal/infrastructure/transport/grpc/mappers/permission_mapper.go b/internal/infrastructure/transport/grpc/mappers/permission_mapper.go deleted file mode 100644 index 3d5c4af..0000000 --- a/internal/infrastructure/transport/grpc/mappers/permission_mapper.go +++ /dev/null @@ -1,55 +0,0 @@ -package mappers - -import ( - permissionV1 "service/internal/infrastructure/transport/grpc/gen/permission/v1" - "service/internal/master/role/permission" -) - -// mapAccessTreeToProto secara rekursif mengubah tree dari service ke format proto. -func mapAccessTreeToProto(serviceAccess []*permission.AccessTreeItem) []*permissionV1.AccessTreeItem { - if serviceAccess == nil { - return nil - } - - protoAccess := make([]*permissionV1.AccessTreeItem, len(serviceAccess)) - for i, item := range serviceAccess { - protoItem := &permissionV1.AccessTreeItem{ - Id: item.ID, - Name: item.Name, - Icon: item.Icon, - Url: item.URL, - Level: int32(item.Level), - Sort: int32(item.Sort), - Active: item.Active, - Children: mapAccessTreeToProto(item.Children), // Panggilan rekursif - } - - if item.Permission != nil { - protoItem.Permission = &permissionV1.Permission{ - Create: item.Permission.Create, - Read: item.Permission.Read, - Update: item.Permission.Update, - Delete: item.Permission.Delete, - Disable: item.Permission.Disable, - } - } - protoAccess[i] = protoItem - } - return protoAccess -} - -// MapRolePermissionTreeToProto adalah fungsi utama untuk mengubah seluruh respons tree. -func MapRolePermissionTreeToProto(serviceResponse *permission.RolePermissionTreeResponse) *permissionV1.RolePermissionTreeResponse { - if serviceResponse == nil { - return nil - } - - return &permissionV1.RolePermissionTreeResponse{ - Success: serviceResponse.Success, - Data: &permissionV1.RolePermissionData{ - Role: serviceResponse.Data.Role, - // Group: serviceResponse.Data.Group, - Access: mapAccessTreeToProto(serviceResponse.Data.Access), - }, - } -} diff --git a/internal/infrastructure/transport/grpc/proto/master/role/master/v1/master.proto b/internal/infrastructure/transport/grpc/proto/master/role/master/v1/master.proto deleted file mode 100644 index 7c71650..0000000 --- a/internal/infrastructure/transport/grpc/proto/master/role/master/v1/master.proto +++ /dev/null @@ -1,83 +0,0 @@ -syntax = "proto3"; - -package master.v1; - -// Path should be relative to the module root. -// The package name is specified after the semicolon. -option go_package = "internal/infrastructure/transport/grpc/gen/master/role/master/v1;masterV1"; - -import "google/protobuf/wrappers.proto"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/empty.proto"; - -// Service definition for RoleAccessRolMaster. -service RoleAccessRolMasterService { - // Get a single RoleAccessRolMaster by its ID. - rpc GetRoleAccessRolMaster(GetRoleAccessRolMasterRequest) returns (RoleAccessRolMasterResponse); - - // Get a list of RoleAccessRolMasters with pagination and filtering. - rpc ListRoleAccessRolMasters(ListRoleAccessRolMastersRequest) returns (ListRoleAccessRolMastersResponse); - - // Create a new RoleAccessRolMaster. - rpc CreateRoleAccessRolMaster(CreateRoleAccessRolMasterRequest) returns (RoleAccessRolMasterResponse); - - // Update an existing RoleAccessRolMaster. - rpc UpdateRoleAccessRolMaster(UpdateRoleAccessRolMasterRequest) returns (RoleAccessRolMasterResponse); - - // Delete a RoleAccessRolMaster by its ID. - rpc DeleteRoleAccessRolMaster(DeleteRoleAccessRolMasterRequest) returns (google.protobuf.Empty); -} - -// The main message representing a RoleAccessRolMaster. -message RoleAccessRolMaster { - string id = 1; - optional string name = 2; - optional bool active = 3; - optional google.protobuf.Timestamp created_at = 4; - optional google.protobuf.Timestamp updated_at = 5; - optional string s_e_l_e_c_t = 6; -} - -// --- Request/Response Messages --- - -message GetRoleAccessRolMasterRequest { - int64 id = 1; -} - -message RoleAccessRolMasterResponse { - RoleAccessRolMaster data = 1; -} - -message ListRoleAccessRolMastersRequest { - int32 page = 1; - int32 page_size = 2; - // Add filter fields here if needed -} - -message ListRoleAccessRolMastersResponse { - repeated RoleAccessRolMaster data = 1; - int64 total_items = 2; -} - -message CreateRoleAccessRolMasterRequest { - string id = 1; - string name = 2; - bool active = 3; - google.protobuf.Timestamp created_at = 4; - google.protobuf.Timestamp updated_at = 5; - string s_e_l_e_c_t = 6; -} - -message UpdateRoleAccessRolMasterRequest { - int64 id = 1; - optional string id = 2; - optional string name = 3; - optional bool active = 4; - optional google.protobuf.Timestamp created_at = 5; - optional google.protobuf.Timestamp updated_at = 6; - optional string s_e_l_e_c_t = 7; -} - -message DeleteRoleAccessRolMasterRequest { - int64 id = 1; -} diff --git a/internal/infrastructure/transport/grpc/proto/permission/v1/permission.proto b/internal/infrastructure/transport/grpc/proto/permission/v1/permission.proto deleted file mode 100644 index be806ae..0000000 --- a/internal/infrastructure/transport/grpc/proto/permission/v1/permission.proto +++ /dev/null @@ -1,56 +0,0 @@ -syntax = "proto3"; - -package permission.v1; - -// Opsi go_package ini sangat penting. -// Path harus relatif terhadap root modul (tanpa nama modul "service-general"). -// Nama paket eksplisit (permissionV1) ditambahkan setelah titik koma. -option go_package = "internal/infrastructure/transport/grpc/gen/permission/v1;permissionV1"; - -import "google/protobuf/wrappers.proto"; - -// Definisi service. -service RolPermissionService { - // Mengambil permission tree untuk role dan/atau group tertentu. - rpc GetRolePermissionTree(GetRolePermissionTreeRequest) returns (RolePermissionTreeResponse); -} - -// Pesan request untuk RPC GetRolePermissionTree. -message GetRolePermissionTreeRequest { - string role_keycloak = 1; - repeated string group_keycloak = 2; - // Menggunakan wrapper BoolValue untuk membedakan antara 'false' dan 'tidak diset'. - google.protobuf.BoolValue active_only = 3; -} - -// Pesan response untuk RPC GetRolePermissionTree. -message RolePermissionTreeResponse { - bool success = 1; - RolePermissionData data = 2; -} - -message RolePermissionData { - string role = 1; - repeated string group = 2; - repeated AccessTreeItem access = 3; -} - -message AccessTreeItem { - int64 id = 1; - string name = 2; - string icon = 3; - string url = 4; - int32 level = 5; - int32 sort = 6; - bool active = 7; - optional Permission permission = 8; - repeated AccessTreeItem children = 9; -} - -message Permission { - bool create = 1; - bool read = 2; - bool update = 3; - bool delete = 4; - bool disable = 5; -} \ No newline at end of file diff --git a/internal/infrastructure/transport/grpc/proto/v1/auth.proto b/internal/infrastructure/transport/grpc/proto/v1/auth.proto deleted file mode 100644 index 4e0e22d..0000000 --- a/internal/infrastructure/transport/grpc/proto/v1/auth.proto +++ /dev/null @@ -1,64 +0,0 @@ -syntax = "proto3"; - -package auth; - -// PERBAIKAN: Tambahkan 'transport' dan hapus suffix '/auth' agar sesuai direktori import -option go_package = "gen/auth/v1;auth"; - -message LoginRequest { - string username = 1; - string password = 2; -} - -message LoginResponse { - string token = 1; - string expires_at = 2; - User user = 3; -} - -message RegisterRequest { - string username = 1; - string email = 2; - string password = 3; - string full_name = 4; - string role = 5; -} - -message RegisterResponse { - string id = 1; - string username = 2; - string email = 3; - string full_name = 4; -} - -message ValidateTokenRequest { - string token = 1; -} - -message ValidateTokenResponse { - bool valid = 1; - User user = 2; -} - -message LogoutRequest { - string token = 1; -} - -message LogoutResponse { - bool success = 1; -} - -message User { - string id = 1; - string username = 2; - string email = 3; - string full_name = 4; - string role = 5; -} - -service AuthService { - rpc Register (RegisterRequest) returns (RegisterResponse); - rpc Login(LoginRequest) returns (LoginResponse); - rpc ValidateToken (ValidateTokenRequest) returns (ValidateTokenResponse); - rpc Logout (LogoutRequest) returns (LogoutResponse); -} \ No newline at end of file diff --git a/internal/infrastructure/transport/grpc/servers/server.go b/internal/infrastructure/transport/grpc/servers/server.go index 4a85ade..959b8b2 100644 --- a/internal/infrastructure/transport/grpc/servers/server.go +++ b/internal/infrastructure/transport/grpc/servers/server.go @@ -4,18 +4,15 @@ import ( "fmt" "net" "service/internal/infrastructure/config" - "service/internal/infrastructure/transport/grpc/handlers" - "service/pkg/logger" // Import generated proto files. Asumsi path ini benar. - permissionV1 "service/internal/infrastructure/transport/grpc/gen/permission/v1" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) type ServiceRegistry struct { - PermissionHandler *handlers.PermissionHandler + // PermissionHandler *handlers.PermissionHandler } // GRPCServer membungkus instance grpc.Server. @@ -30,10 +27,10 @@ func NewGRPCServer(config *config.ServerGRPCConfig, registry *ServiceRegistry) * srv := grpc.NewServer() // Daftarkan semua service yang ada di registry - if registry.PermissionHandler != nil { - permissionV1.RegisterRolPermissionServiceServer(srv, registry.PermissionHandler) - logger.Default().Info("Registered RolPermission gRPC service") - } + // if registry.PermissionHandler != nil { + // permissionV1.RegisterRolPermissionServiceServer(srv, registry.PermissionHandler) + // logger.Default().Info("Registered RolPermission gRPC service") + // } // Aktifkan reflection agar bisa di-debug dengan tools seperti grpcurl reflection.Register(srv) diff --git a/internal/infrastructure/transport/http/handlers/bpjs/antrol/antrol_handler.go b/internal/infrastructure/transport/http/handlers/bpjs/antrol/antrol_handler.go deleted file mode 100644 index 476fa68..0000000 --- a/internal/infrastructure/transport/http/handlers/bpjs/antrol/antrol_handler.go +++ /dev/null @@ -1,38 +0,0 @@ -package antrol - -import ( - "net/http" - - antrolService "service/internal/bpjs/antrol/reference" - "service/pkg/errors" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -type AntrolHandler struct { - service antrolService.Service -} - -func NewAntrolHandler(service antrolService.Service) *AntrolHandler { - return &AntrolHandler{service: service} -} - -func (h *AntrolHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/bpjs/antrol/reference") - { - group.GET("/poli", h.GetRefPoli) - } -} - -func (h *AntrolHandler) GetRefPoli(c *gin.Context) { - ctx := c.Request.Context() - res, err := h.service.GetRefPoli(ctx) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) - return - } - - response.Success(c, http.StatusOK, "Successfully retrieved BPJS Antrol Poli reference", res) -} diff --git a/internal/infrastructure/transport/http/handlers/bpjs/aplicare/bed_handler.go b/internal/infrastructure/transport/http/handlers/bpjs/aplicare/bed_handler.go deleted file mode 100644 index 143631d..0000000 --- a/internal/infrastructure/transport/http/handlers/bpjs/aplicare/bed_handler.go +++ /dev/null @@ -1,100 +0,0 @@ -package aplicare - -import ( - "net/http" - "strconv" - - bedService "service/internal/bpjs/aplicare/bed" - "service/pkg/errors" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -type BedHandler struct { - service bedService.Service -} - -func NewBedHandler(service bedService.Service) *BedHandler { - return &BedHandler{service: service} -} - -func (h *BedHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/bpjs/aplicare/bed") - { - group.GET("/:kdppk/:start/:limit", h.GetBedList) - group.POST("/:kdppk", h.CreateBed) - group.PUT("/:kdppk", h.UpdateBed) - group.DELETE("/:kdppk", h.DeleteBed) - } -} - -func (h *BedHandler) GetBedList(c *gin.Context) { - kdPpk := c.Param("kdppk") - start, _ := strconv.Atoi(c.Param("start")) - limit, _ := strconv.Atoi(c.Param("limit")) - - ctx := c.Request.Context() - res, err := h.service.GetBedList(ctx, kdPpk, start, limit) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) - return - } - - response.Success(c, http.StatusOK, "Successfully retrieved BPJS Aplicares bed list", res) -} - -func (h *BedHandler) CreateBed(c *gin.Context) { - kdPpk := c.Param("kdppk") - var req bedService.BedData - if err := c.ShouldBindJSON(&req); err != nil { - response.Error(c, http.StatusBadRequest, "Invalid request body", err.Error()) - return - } - - ctx := c.Request.Context() - if err := h.service.CreateBed(ctx, kdPpk, req); err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) - return - } - - response.Success(c, http.StatusCreated, "Successfully created BPJS Aplicares bed data", nil) -} - -func (h *BedHandler) UpdateBed(c *gin.Context) { - kdPpk := c.Param("kdppk") - var req bedService.BedData - if err := c.ShouldBindJSON(&req); err != nil { - response.Error(c, http.StatusBadRequest, "Invalid request body", err.Error()) - return - } - - ctx := c.Request.Context() - if err := h.service.UpdateBed(ctx, kdPpk, req); err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) - return - } - - response.Success(c, http.StatusOK, "Successfully updated BPJS Aplicares bed data", nil) -} - -func (h *BedHandler) DeleteBed(c *gin.Context) { - kdPpk := c.Param("kdppk") - var req bedService.BedDeletePayload - if err := c.ShouldBindJSON(&req); err != nil { - response.Error(c, http.StatusBadRequest, "Invalid request body", err.Error()) - return - } - - ctx := c.Request.Context() - if err := h.service.DeleteBed(ctx, kdPpk, req); err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) - return - } - - response.Success(c, http.StatusOK, "Successfully deleted BPJS Aplicares bed data", nil) -} diff --git a/internal/infrastructure/transport/http/handlers/bpjs/apotek/reference_handler.go b/internal/infrastructure/transport/http/handlers/bpjs/apotek/reference_handler.go deleted file mode 100644 index bbc0c0a..0000000 --- a/internal/infrastructure/transport/http/handlers/bpjs/apotek/reference_handler.go +++ /dev/null @@ -1,53 +0,0 @@ -package apotek - -import ( - "net/http" - - dphoService "service/internal/bpjs/apotek/reference/dpho" - poliService "service/internal/bpjs/apotek/reference/poli" - "service/pkg/errors" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -type ReferenceHandler struct { - dphoService dphoService.Service - poliService poliService.Service -} - -func NewReferenceHandler(dpho dphoService.Service, poli poliService.Service) *ReferenceHandler { - return &ReferenceHandler{ - dphoService: dpho, - poliService: poli, - } -} - -func (h *ReferenceHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/bpjs/apotek/reference") - { - group.GET("/dpho", h.GetDPHO) - group.GET("/poli/:param", h.GetPoli) - } -} - -func (h *ReferenceHandler) GetDPHO(c *gin.Context) { - res, err := h.dphoService.GetDPHO(c.Request.Context()) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved BPJS Apotek DPHO reference", res) -} - -func (h *ReferenceHandler) GetPoli(c *gin.Context) { - param := c.Param("param") - res, err := h.poliService.GetPoli(c.Request.Context(), param) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved BPJS Apotek Poli reference", res) -} diff --git a/internal/infrastructure/transport/http/handlers/bpjs/vclaim/peserta_handler.go b/internal/infrastructure/transport/http/handlers/bpjs/vclaim/peserta_handler.go deleted file mode 100644 index 917ee76..0000000 --- a/internal/infrastructure/transport/http/handlers/bpjs/vclaim/peserta_handler.go +++ /dev/null @@ -1,64 +0,0 @@ -package vclaim - -import ( - "net/http" - "time" - - pesertaService "service/internal/bpjs/vclaim/peserta" - "service/pkg/errors" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -type PesertaHandler struct { - service pesertaService.Service -} - -func NewPesertaHandler(service pesertaService.Service) *PesertaHandler { - return &PesertaHandler{service: service} -} - -func (h *PesertaHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/bpjs/vclaim/peserta") - { - group.GET("/nik/:nik", h.GetPesertaByNIK) - group.GET("/nokartu/:nokartu", h.GetPesertaByNoKartu) - } -} - -func (h *PesertaHandler) GetPesertaByNIK(c *gin.Context) { - nik := c.Param("nik") - tglSEP := c.Query("tgl_sep") - if tglSEP == "" { - tglSEP = time.Now().Format("2006-01-02") - } - - ctx := c.Request.Context() - res, err := h.service.GetPesertaByNIK(ctx, nik, tglSEP) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) - return - } - - response.Success(c, http.StatusOK, "Successfully retrieved participant data by NIK", res) -} - -func (h *PesertaHandler) GetPesertaByNoKartu(c *gin.Context) { - noKartu := c.Param("nokartu") - tglSEP := c.Query("tgl_sep") - if tglSEP == "" { - tglSEP = time.Now().Format("2006-01-02") - } - - ctx := c.Request.Context() - res, err := h.service.GetPesertaByNoKartu(ctx, noKartu, tglSEP) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) - return - } - - response.Success(c, http.StatusOK, "Successfully retrieved participant data by card number", res) -} diff --git a/internal/infrastructure/transport/http/handlers/bpjs/vclaim/sep_handler.go b/internal/infrastructure/transport/http/handlers/bpjs/vclaim/sep_handler.go deleted file mode 100644 index 651569d..0000000 --- a/internal/infrastructure/transport/http/handlers/bpjs/vclaim/sep_handler.go +++ /dev/null @@ -1,105 +0,0 @@ -package vclaim - -import ( - "net/http" - sepService "service/internal/bpjs/vclaim/sep" - "service/pkg/errors" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -// SepHandler menangani semua request HTTP terkait VClaim. -type SepHandler struct { - sepService sepService.Service -} - -// NewSepHandler membuat instance SepHandler baru. -func NewSepHandler(sepService sepService.Service) *SepHandler { - return &SepHandler{ - sepService: sepService, - } -} - -// RegisterRoutes mendaftarkan semua rute untuk BPJS VClaim. -func (h *SepHandler) RegisterRoutes(router *gin.RouterGroup) { - bpjsGroup := router.Group("/bpjs/vclaim") - { - sepGroup := bpjsGroup.Group("/sep") - { - sepGroup.POST("", h.CreateSEP) - sepGroup.PUT("", h.UpdateSEP) - // BPJS API untuk delete menggunakan method POST, tapi kita ekspos sebagai DELETE untuk konsistensi RESTful. - sepGroup.DELETE("", h.DeleteSEP) - sepGroup.GET("/:nosep", h.GetSEPDetail) - } - } -} - -// CreateSEP menangani request untuk membuat SEP baru. -func (h *SepHandler) CreateSEP(c *gin.Context) { - var req sepService.CreateSEPRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.Error(c, http.StatusBadRequest, "Invalid request body", err.Error()) - return - } - - result, err := h.sepService.Create(c.Request.Context(), req) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), nil) - return - } - - response.Success(c, http.StatusCreated, "Successfully created SEP", result) -} - -// UpdateSEP menangani request untuk memperbarui SEP. -func (h *SepHandler) UpdateSEP(c *gin.Context) { - var req sepService.UpdateSEPRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.Error(c, http.StatusBadRequest, "Invalid request body", err.Error()) - return - } - - result, err := h.sepService.Update(c.Request.Context(), req) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), nil) - return - } - - response.Success(c, http.StatusOK, "Successfully updated SEP", result) -} - -// GetSEPDetail menangani request untuk mendapatkan detail SEP. -func (h *SepHandler) GetSEPDetail(c *gin.Context) { - noSEP := c.Param("no_sep") - - result, err := h.sepService.GetDetail(c.Request.Context(), noSEP) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), nil) - return - } - - response.Success(c, http.StatusOK, "Successfully retrieved SEP detail", result) -} - -// DeleteSEP menangani request untuk menghapus SEP. -func (h *SepHandler) DeleteSEP(c *gin.Context) { - var req sepService.DeleteSEPRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.Error(c, http.StatusBadRequest, "Invalid request body for SEP deletion", err.Error()) - return - } - - result, err := h.sepService.Delete(c.Request.Context(), req) - if err != nil { - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), nil) - return - } - - response.Success(c, http.StatusOK, "Successfully deleted SEP", result) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/reference/auth_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/reference/auth_handler.go deleted file mode 100644 index 1cb8091..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/reference/auth_handler.go +++ /dev/null @@ -1,90 +0,0 @@ -package reference - -import ( - stdErrors "errors" - "net/http" - "service/internal/interfaces/satusehat" - "service/internal/satusehat/reference/auth" - "service/pkg/errors" - "service/pkg/response" - "time" - - "github.com/gin-gonic/gin" -) - -// AuthHandler menangani endpoint HTTP untuk Auth Satu Sehat. -type AuthHandler struct { - service auth.Service -} - -// RegisterRoutes mendaftarkan endpoint handler ini ke router Gin -func (h *AuthHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/reference") - { - group.GET("/auth/token", h.GetToken) - group.POST("/auth/token/refresh", h.RefreshToken) - } -} - -// NewAuthHandler membuat instance baru dari AuthHandler. -func NewAuthHandler(service auth.Service) *AuthHandler { - return &AuthHandler{ - service: service, - } -} - -// handleSatuSehatError mengekstrak OperationOutcome agar JSON bisa tampil terstruktur di response -func handleSatuSehatError(c *gin.Context, err error) { - var ssErr *satusehat.ErrorOperationOutcome - if stdErrors.As(err, &ssErr) { - c.JSON(ssErr.StatusCode, gin.H{ - "status": "error", - "message": ssErr.Outcome, - "error": gin.H{ - "severity": "error", - "timestamp": time.Now().UTC().Format(time.RFC3339), - }, - }) - return - } - appErr := errors.FromError(err) - response.Error(c, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) -} - -// GetToken godoc -// -// @Summary Get SatuSehat Access Token -// @Description Mendapatkan token aktif untuk API Satu Sehat Kemenkes (menggunakan cache internal) -// @Tags Satu Sehat - Auth -// @Produce json -// @Success 200 {object} response.Response -// @Failure 500 {object} response.Response -// @Router /satusehat/reference/auth/token [get] -// @Security BearerAuth -func (h *AuthHandler) GetToken(c *gin.Context) { - data, err := h.service.GetToken(c.Request.Context()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan token Satu Sehat", data) -} - -// RefreshToken godoc -// -// @Summary Refresh SatuSehat Access Token -// @Description Memaksa request token baru dari API Satu Sehat Kemenkes (bypass cache) -// @Tags Satu Sehat - Auth -// @Produce json -// @Success 200 {object} response.Response -// @Failure 500 {object} response.Response -// @Router /satusehat/reference/auth/token/refresh [post] -// @Security BearerAuth -func (h *AuthHandler) RefreshToken(c *gin.Context) { - data, err := h.service.RefreshToken(c.Request.Context()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil me-refresh token Satu Sehat", data) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/reference/kfa_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/reference/kfa_handler.go deleted file mode 100644 index 6d4d762..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/reference/kfa_handler.go +++ /dev/null @@ -1,77 +0,0 @@ -package reference - -import ( - "net/http" - - "service/internal/satusehat/reference/kfa" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -type KFAHandler struct { - service kfa.Service -} - -func NewKFAHandler(service kfa.Service) *KFAHandler { - return &KFAHandler{ - service: service, - } -} - -// GetByCode godoc -// -// @Summary Cari Produk KFA berdasarkan Kode -// @Description Mencari detail produk farmasi/alkes dari API Kamus Farmasi dan Alat Kesehatan (KFA) Satu Sehat -// @Tags Satu Sehat - KFA -// @Produce json -// @Param code path string true "Kode KFA (contoh: 93000469)" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/kfa/products/{code} [get] -// @Security BearerAuth -func (h *KFAHandler) GetByCode(c *gin.Context) { - code := c.Param("code") - data, err := h.service.GetByCode(c.Request.Context(), code) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data produk KFA", data) -} - -// GetProducts godoc -// -// @Summary Daftar Produk KFA -// @Description Mengambil daftar produk KFA dengan kapabilitas paginasi -// @Tags Satu Sehat - KFA -// @Produce json -// @Param page query int false "Nomor Halaman (default: 1)" -// @Param size query int false "Jumlah Data (default: 10)" -// @Param product_type query string false "Tipe Produk (farmasi/alkes)" -// @Param keyword query string false "Kata Kunci Pencarian" -// @Param from_ query string false "Parameter waktu (from_)" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/kfa/products [get] -// @Security BearerAuth -func (h *KFAHandler) GetProducts(c *gin.Context) { - var params kfa.KFASearchParams - if err := c.ShouldBindQuery(¶ms); err != nil { - response.Error(c, http.StatusBadRequest, "Format parameter tidak valid", err.Error()) - return - } - - data, err := h.service.GetProducts(c.Request.Context(), params) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mengambil daftar produk KFA", data) -} - -func (h *KFAHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/reference/kfa") - { - group.GET("/products/:code", h.GetByCode) - group.GET("/products", h.GetProducts) - } -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/reference/location_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/reference/location_handler.go deleted file mode 100644 index b384f58..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/reference/location_handler.go +++ /dev/null @@ -1,126 +0,0 @@ -package reference - -import ( - "net/http" - - "service/internal/satusehat/reference/location" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -type LocationHandler struct { - service location.Service -} - -func NewLocationHandler(service location.Service) *LocationHandler { - return &LocationHandler{ - service: service, - } -} - -// GetByID godoc -// -// @Summary Cari Lokasi (Satu Sehat) berdasarkan ID -// @Description Mencari data Location FHIR Satu Sehat berdasarkan ID -// @Tags Satu Sehat - Location -// @Produce json -// @Param id path string true "Location ID" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/location/{id} [get] -// @Security BearerAuth -func (h *LocationHandler) GetByID(c *gin.Context) { - id := c.Param("id") - data, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data lokasi", data) -} - -// Search godoc -// -// @Summary Pencarian Lokasi (Satu Sehat) -// @Description Mencari data Location berdasarkan parameter -// @Tags Satu Sehat - Location -// @Produce json -// @Param name query string false "Nama Lokasi" -// @Param organization query string false "ID Organisasi Pemilik" -// @Param identifier query string false "Identifier Lokasi" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/location [get] -// @Security BearerAuth -func (h *LocationHandler) Search(c *gin.Context) { - var params location.LocationSearchParams - if err := c.ShouldBindQuery(¶ms); err != nil { - response.Error(c, http.StatusBadRequest, "Format pencarian tidak valid", err.Error()) - return - } - - data, err := h.service.Search(c.Request.Context(), params) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data lokasi", data) -} - -func (h *LocationHandler) Create(c *gin.Context) { - var payload map[string]interface{} - if err := c.ShouldBindJSON(&payload); err != nil { - response.Error(c, http.StatusBadRequest, "Format request tidak valid", err.Error()) - return - } - - data, err := h.service.Create(c.Request.Context(), payload) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Berhasil membuat data lokasi", data) -} - -func (h *LocationHandler) Update(c *gin.Context) { - id := c.Param("id") - var payload map[string]interface{} - if err := c.ShouldBindJSON(&payload); err != nil { - response.Error(c, http.StatusBadRequest, "Format request tidak valid", err.Error()) - return - } - - data, err := h.service.Update(c.Request.Context(), id, payload) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mengubah data lokasi", data) -} - -func (h *LocationHandler) Patch(c *gin.Context) { - id := c.Param("id") - var payload interface{} - if err := c.ShouldBindJSON(&payload); err != nil { - response.Error(c, http.StatusBadRequest, "Format request tidak valid", err.Error()) - return - } - - data, err := h.service.Patch(c.Request.Context(), id, payload) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil melakukan patch data lokasi", data) -} - -// RegisterRoutes mendaftarkan endpoint handler ini ke router Gin -func (h *LocationHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/reference") - { - group.GET("/location/:id", h.GetByID) - group.GET("/location", h.Search) - group.POST("/location", h.Create) - group.PUT("/location/:id", h.Update) - group.PATCH("/location/:id", h.Patch) - } -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/reference/organization_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/reference/organization_handler.go deleted file mode 100644 index 627bbcb..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/reference/organization_handler.go +++ /dev/null @@ -1,133 +0,0 @@ -package reference - -import ( - "net/http" - - "service/internal/satusehat/reference/organization" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -type OrganizationHandler struct { - service organization.Service -} - -func NewOrganizationHandler(service organization.Service) *OrganizationHandler { - return &OrganizationHandler{ - service: service, - } -} - -// GetByID godoc -// -// @Summary Cari Organisasi (Satu Sehat) berdasarkan ID -// @Description Mencari data Organization FHIR Satu Sehat berdasarkan ID -// @Tags Satu Sehat - Organization -// @Produce json -// @Param id path string true "Organization ID" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/organization/{id} [get] -// @Security BearerAuth -func (h *OrganizationHandler) GetByID(c *gin.Context) { - id := c.Param("id") - data, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data organisasi", data) -} - -// Search godoc -// -// @Summary Pencarian Organisasi (Satu Sehat) -// @Description Mencari data Organization berdasarkan Name atau PartOf -// @Tags Satu Sehat - Organization -// @Produce json -// @Param name query string false "Nama Organisasi" -// @Param partof query string false "ID Organisasi Induk" -// @Param identifier query string false "Identifier Organisasi" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/organization [get] -// @Security BearerAuth -func (h *OrganizationHandler) Search(c *gin.Context) { - var params organization.OrganizationSearchParams - if err := c.ShouldBindQuery(¶ms); err != nil { - response.Error(c, http.StatusBadRequest, "Format pencarian tidak valid", err.Error()) - return - } - - // Validasi mandiri sebelum menembak ke API Kemenkes - if params.Name == "" && params.PartOf == "" && params.Identifier == "" { - response.Error(c, http.StatusBadRequest, "Parameter pencarian tidak lengkap", "Harap masukkan minimal salah satu parameter query: name, partof, atau identifier") - return - } - - data, err := h.service.Search(c.Request.Context(), params) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data organisasi", data) -} - -func (h *OrganizationHandler) Create(c *gin.Context) { - var payload map[string]interface{} - if err := c.ShouldBindJSON(&payload); err != nil { - response.Error(c, http.StatusBadRequest, "Format request tidak valid", err.Error()) - return - } - - data, err := h.service.Create(c.Request.Context(), payload) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Berhasil membuat data organisasi", data) -} - -func (h *OrganizationHandler) Update(c *gin.Context) { - id := c.Param("id") - var payload map[string]interface{} - if err := c.ShouldBindJSON(&payload); err != nil { - response.Error(c, http.StatusBadRequest, "Format request tidak valid", err.Error()) - return - } - - data, err := h.service.Update(c.Request.Context(), id, payload) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mengubah data organisasi", data) -} - -func (h *OrganizationHandler) Patch(c *gin.Context) { - id := c.Param("id") - // JSON Patch biasanya array of objects, jadi gunakan interface{} general - var payload interface{} - if err := c.ShouldBindJSON(&payload); err != nil { - response.Error(c, http.StatusBadRequest, "Format request tidak valid", err.Error()) - return - } - - data, err := h.service.Patch(c.Request.Context(), id, payload) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil melakukan patch data organisasi", data) -} - -// RegisterRoutes mendaftarkan endpoint handler ini ke router Gin -func (h *OrganizationHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/reference") - { - group.GET("/organization/:id", h.GetByID) - group.GET("/organization", h.Search) - group.POST("/organization", h.Create) - group.PUT("/organization/:id", h.Update) - group.PATCH("/organization/:id", h.Patch) - } -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/reference/patient_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/reference/patient_handler.go deleted file mode 100644 index b33abe5..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/reference/patient_handler.go +++ /dev/null @@ -1,127 +0,0 @@ -package reference - -import ( - "net/http" - "service/internal/satusehat/reference/patient" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -// PatientHandler menangani endpoint HTTP untuk resource Patient Satu Sehat. -type PatientHandler struct { - service patient.Service -} - -// RegisterRoutes mendaftarkan endpoint handler ini ke router Gin -func (h *PatientHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/reference") - { - group.GET("/patient/nik/:nik", h.GetByNIK) - group.GET("/patient/:id", h.GetByID) - group.GET("/patient", h.Search) - group.POST("/patient", h.Create) - } -} - -// NewPatientHandler membuat instance baru dari PatientHandler. -func NewPatientHandler(service patient.Service) *PatientHandler { - return &PatientHandler{ - service: service, - } -} - -// GetByNIK godoc -// -// @Summary Cari Pasien (Satu Sehat) berdasarkan NIK -// @Description Mencari data pasien FHIR Satu Sehat berdasarkan Nomor Induk Kependudukan (NIK) -// @Tags Satu Sehat - Patient -// @Produce json -// @Param nik path string true "Nomor Induk Kependudukan" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/patient/nik/{nik} [get] -// @Security BearerAuth -func (h *PatientHandler) GetByNIK(c *gin.Context) { - nik := c.Param("nik") - data, err := h.service.GetByNIK(c.Request.Context(), nik) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data pasien", data) -} - -// GetByID godoc -// -// @Summary Cari Pasien (Satu Sehat) berdasarkan ID -// @Description Mencari data pasien FHIR Satu Sehat berdasarkan IHS Number / ID -// @Tags Satu Sehat - Patient -// @Produce json -// @Param id path string true "IHS Number / Patient ID" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/patient/{id} [get] -// @Security BearerAuth -func (h *PatientHandler) GetByID(c *gin.Context) { - id := c.Param("id") - data, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data pasien", data) -} - -// Search godoc -// -// @Summary Pencarian Pasien (Satu Sehat) Multi-Parameter -// @Description Mencari data pasien FHIR Satu Sehat berdasarkan kombinasi parameter (Nama, NIK, NIK Ibu, Tanggal Lahir, Gender) -// @Tags Satu Sehat - Patient -// @Produce json -// @Param nik query string false "Nomor Induk Kependudukan" -// @Param nik_ibu query string false "Nomor Induk Kependudukan Ibu (Untuk bayi)" -// @Param name query string false "Nama Pasien" -// @Param birthdate query string false "Tanggal Lahir (YYYY-MM-DD)" -// @Param gender query string false "Jenis Kelamin (male/female)" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/patient [get] -// @Security BearerAuth -func (h *PatientHandler) Search(c *gin.Context) { - var params patient.PatientSearchParams - if err := c.ShouldBindQuery(¶ms); err != nil { - response.Error(c, http.StatusBadRequest, "Format pencarian tidak valid", err.Error()) - return - } - - data, err := h.service.Search(c.Request.Context(), params) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data pasien", data) -} - -// Create godoc -// -// @Summary Daftar Pasien Baru (Satu Sehat) -// @Description Mendaftarkan data pasien baru ke API Satu Sehat dan mengembalikan IHS Number -// @Tags Satu Sehat - Patient -// @Accept json -// @Produce json -// @Param request body patient.CreatePatientRequest true "Data Pasien Baru" -// @Success 201 {object} response.Response -// @Router /satusehat/reference/patient [post] -// @Security BearerAuth -func (h *PatientHandler) Create(c *gin.Context) { - var req patient.CreatePatientRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.Error(c, http.StatusBadRequest, "Format request tidak valid", err.Error()) - return - } - - data, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Berhasil mendaftarkan pasien", data) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/reference/practitioner_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/reference/practitioner_handler.go deleted file mode 100644 index 23064c5..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/reference/practitioner_handler.go +++ /dev/null @@ -1,98 +0,0 @@ -package reference - -import ( - "net/http" - - "service/internal/satusehat/reference/practitioner" - "service/pkg/response" - - "github.com/gin-gonic/gin" -) - -type PractitionerHandler struct { - service practitioner.Service -} - -func NewPractitionerHandler(service practitioner.Service) *PractitionerHandler { - return &PractitionerHandler{ - service: service, - } -} - -// GetByNIK godoc -// -// @Summary Cari Tenaga Medis (Satu Sehat) berdasarkan NIK -// @Description Mencari data Practitioner FHIR Satu Sehat berdasarkan NIK -// @Tags Satu Sehat - Practitioner -// @Produce json -// @Param nik path string true "Nomor Induk Kependudukan" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/practitioner/nik/{nik} [get] -// @Security BearerAuth -func (h *PractitionerHandler) GetByNIK(c *gin.Context) { - nik := c.Param("nik") - data, err := h.service.GetByNIK(c.Request.Context(), nik) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data tenaga medis", data) -} - -// GetByID godoc -// -// @Summary Cari Tenaga Medis (Satu Sehat) berdasarkan ID -// @Description Mencari data Practitioner FHIR Satu Sehat berdasarkan IHS Number / ID -// @Tags Satu Sehat - Practitioner -// @Produce json -// @Param id path string true "IHS Number / Practitioner ID" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/practitioner/{id} [get] -// @Security BearerAuth -func (h *PractitionerHandler) GetByID(c *gin.Context) { - id := c.Param("id") - data, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data tenaga medis", data) -} - -// Search godoc -// -// @Summary Pencarian Tenaga Medis (Satu Sehat) Multi-Parameter -// @Description Mencari data Practitioner FHIR Satu Sehat berdasarkan parameter -// @Tags Satu Sehat - Practitioner -// @Produce json -// @Param nik query string false "Nomor Induk Kependudukan" -// @Param name query string false "Nama Tenaga Medis" -// @Param gender query string false "Jenis Kelamin (male/female)" -// @Param birthdate query string false "Tanggal Lahir (YYYY-MM-DD)" -// @Success 200 {object} response.Response -// @Router /satusehat/reference/practitioner [get] -// @Security BearerAuth -func (h *PractitionerHandler) Search(c *gin.Context) { - var params practitioner.PractitionerSearchParams - if err := c.ShouldBindQuery(¶ms); err != nil { - response.Error(c, http.StatusBadRequest, "Format pencarian tidak valid", err.Error()) - return - } - - data, err := h.service.Search(c.Request.Context(), params) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Berhasil mendapatkan data tenaga medis", data) -} - -// RegisterRoutes mendaftarkan endpoint handler ini ke router Gin -func (h *PractitionerHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/reference") - { - group.GET("/practitioner/nik/:nik", h.GetByNIK) - group.GET("/practitioner/:id", h.GetByID) - group.GET("/practitioner", h.Search) - } -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/allergyintolerance_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/allergyintolerance_handler.go deleted file mode 100644 index 3e3a686..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/allergyintolerance_handler.go +++ /dev/null @@ -1,81 +0,0 @@ -package usecase - -import ( - "net/http" - "service/internal/satusehat/usecase/allergyintolerance" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type AllergyIntoleranceHandler struct{ service allergyintolerance.Service } - -func NewAllergyIntoleranceHandler(s allergyintolerance.Service) *AllergyIntoleranceHandler { - return &AllergyIntoleranceHandler{service: s} -} - -func (h *AllergyIntoleranceHandler) RegisterRoutes(router *gin.RouterGroup) { - g := router.Group("/satusehat/allergyintolerance") - g.POST("", h.Create) - g.GET("", h.Search) - g.GET("/:id", h.GetByID) - g.PUT("/:id", h.Update) - g.PATCH("/:id", h.Patch) -} - -func (h *AllergyIntoleranceHandler) Create(c *gin.Context) { - var req allergyintolerance.AllergyIntoleranceRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Success", res.FullResponse) -} -func (h *AllergyIntoleranceHandler) Update(c *gin.Context) { - var req allergyintolerance.AllergyIntoleranceRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Update(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *AllergyIntoleranceHandler) Patch(c *gin.Context) { - var req allergyintolerance.AllergyIntolerancePatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid patch", validator.TranslateError(err)) - return - } - res, err := h.service.Patch(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *AllergyIntoleranceHandler) GetByID(c *gin.Context) { - res, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *AllergyIntoleranceHandler) Search(c *gin.Context) { - res, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/careplan_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/careplan_handler.go deleted file mode 100644 index 0a71c08..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/careplan_handler.go +++ /dev/null @@ -1,79 +0,0 @@ -package usecase - -import ( - "net/http" - "service/internal/satusehat/usecase/careplan" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type CarePlanHandler struct{ service careplan.Service } - -func NewCarePlanHandler(s careplan.Service) *CarePlanHandler { return &CarePlanHandler{service: s} } - -func (h *CarePlanHandler) RegisterRoutes(router *gin.RouterGroup) { - g := router.Group("/satusehat/careplan") - g.POST("", h.Create) - g.GET("", h.Search) - g.GET("/:id", h.GetByID) - g.PUT("/:id", h.Update) - g.PATCH("/:id", h.Patch) -} - -func (h *CarePlanHandler) Create(c *gin.Context) { - var req careplan.CarePlanRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Success", res.FullResponse) -} -func (h *CarePlanHandler) Update(c *gin.Context) { - var req careplan.CarePlanRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Update(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *CarePlanHandler) Patch(c *gin.Context) { - var req careplan.CarePlanPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid patch", validator.TranslateError(err)) - return - } - res, err := h.service.Patch(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *CarePlanHandler) GetByID(c *gin.Context) { - res, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *CarePlanHandler) Search(c *gin.Context) { - res, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/clinicalImpression_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/clinicalImpression_handler.go deleted file mode 100644 index 2fcd1bf..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/clinicalImpression_handler.go +++ /dev/null @@ -1,81 +0,0 @@ -package usecase - -import ( - "net/http" - clinicalimpression "service/internal/satusehat/usecase/clinicalImpression" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type ClinicalImpressionHandler struct{ service clinicalimpression.Service } - -func NewClinicalImpressionHandler(s clinicalimpression.Service) *ClinicalImpressionHandler { - return &ClinicalImpressionHandler{service: s} -} - -func (h *ClinicalImpressionHandler) RegisterRoutes(router *gin.RouterGroup) { - g := router.Group("/satusehat/clinicalimpression") - g.POST("", h.Create) - g.GET("", h.Search) - g.GET("/:id", h.GetByID) - g.PUT("/:id", h.Update) - g.PATCH("/:id", h.Patch) -} - -func (h *ClinicalImpressionHandler) Create(c *gin.Context) { - var req clinicalimpression.ClinicalImpressionRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Success", res.FullResponse) -} -func (h *ClinicalImpressionHandler) Update(c *gin.Context) { - var req clinicalimpression.ClinicalImpressionRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Update(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *ClinicalImpressionHandler) Patch(c *gin.Context) { - var req clinicalimpression.ClinicalImpressionPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid patch", validator.TranslateError(err)) - return - } - res, err := h.service.Patch(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *ClinicalImpressionHandler) GetByID(c *gin.Context) { - res, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *ClinicalImpressionHandler) Search(c *gin.Context) { - res, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/composition_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/composition_handler.go deleted file mode 100644 index 64bb4fb..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/composition_handler.go +++ /dev/null @@ -1,102 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/composition" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type CompositionHandler struct { - service composition.Service -} - -func NewCompositionHandler(service composition.Service) *CompositionHandler { - return &CompositionHandler{ - service: service, - } -} - -func (h *CompositionHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/composition") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *CompositionHandler) Create(c *gin.Context) { - var req composition.CompositionRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created Composition", result.FullResponse) -} - -func (h *CompositionHandler) Update(c *gin.Context) { - id := c.Param("id") - var req composition.CompositionRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated Composition", result.FullResponse) -} - -func (h *CompositionHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req composition.CompositionPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", customErr) - return - } - - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched Composition", result.FullResponse) -} - -func (h *CompositionHandler) GetByID(c *gin.Context) { - id := c.Param("id") - result, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Composition", result.FullResponse) -} - -func (h *CompositionHandler) Search(c *gin.Context) { - queryParams := c.Request.URL.Query() - result, err := h.service.Search(c.Request.Context(), queryParams) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Compositions", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/condition_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/condition_handler.go deleted file mode 100644 index 19ec3be..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/condition_handler.go +++ /dev/null @@ -1,102 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/condition" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type ConditionHandler struct { - service condition.Service -} - -func NewConditionHandler(service condition.Service) *ConditionHandler { - return &ConditionHandler{ - service: service, - } -} - -func (h *ConditionHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/condition") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *ConditionHandler) Create(c *gin.Context) { - var req condition.ConditionRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created Condition", result) -} - -func (h *ConditionHandler) Update(c *gin.Context) { - id := c.Param("id") - var req condition.ConditionRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated Condition", result) -} - -func (h *ConditionHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req condition.ConditionPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", customErr) - return - } - - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched Condition", result) -} - -func (h *ConditionHandler) GetByID(c *gin.Context) { - id := c.Param("id") - result, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Condition", result) -} - -func (h *ConditionHandler) Search(c *gin.Context) { - queryParams := c.Request.URL.Query() - result, err := h.service.Search(c.Request.Context(), queryParams) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Conditions", result) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/diagnosticreport_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/diagnosticreport_handler.go deleted file mode 100644 index 830a1ef..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/diagnosticreport_handler.go +++ /dev/null @@ -1,81 +0,0 @@ -package usecase - -import ( - "net/http" - "service/internal/satusehat/usecase/diagnosticreport" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type DiagnosticReportHandler struct{ service diagnosticreport.Service } - -func NewDiagnosticReportHandler(s diagnosticreport.Service) *DiagnosticReportHandler { - return &DiagnosticReportHandler{service: s} -} - -func (h *DiagnosticReportHandler) RegisterRoutes(router *gin.RouterGroup) { - g := router.Group("/satusehat/diagnosticreport") - g.POST("", h.Create) - g.GET("", h.Search) - g.GET("/:id", h.GetByID) - g.PUT("/:id", h.Update) - g.PATCH("/:id", h.Patch) -} - -func (h *DiagnosticReportHandler) Create(c *gin.Context) { - var req diagnosticreport.DiagnosticReportRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Success", res.FullResponse) -} -func (h *DiagnosticReportHandler) Update(c *gin.Context) { - var req diagnosticreport.DiagnosticReportRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Update(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *DiagnosticReportHandler) Patch(c *gin.Context) { - var req diagnosticreport.DiagnosticReportPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid patch", validator.TranslateError(err)) - return - } - res, err := h.service.Patch(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *DiagnosticReportHandler) GetByID(c *gin.Context) { - res, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *DiagnosticReportHandler) Search(c *gin.Context) { - res, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/encounter_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/encounter_handler.go deleted file mode 100644 index a30ff03..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/encounter_handler.go +++ /dev/null @@ -1,149 +0,0 @@ -package usecase - -import ( - "errors" - "net/http" - "strconv" - "time" - - "service/internal/interfaces/satusehat" - "service/internal/satusehat/usecase/encounter" - pkgErrors "service/pkg/errors" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type EncounterHandler struct { - service encounter.Service -} - -func NewEncounterHandler(service encounter.Service) *EncounterHandler { - return &EncounterHandler{ - service: service, - } -} - -func (h *EncounterHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/encounter") - { - group.POST("", h.Create) - group.POST("/sync/:idxdaftar", h.SyncFromSIMRS) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -// handleSatuSehatError mengekstrak OperationOutcome agar JSON bisa tampil terstruktur -func handleSatuSehatError(c *gin.Context, err error) { - var ssErr *satusehat.ErrorOperationOutcome - if errors.As(err, &ssErr) { - c.Error(err) // Log error asli - c.JSON(ssErr.StatusCode, gin.H{ - "status": "error", - "message": ssErr.Outcome, - "error": gin.H{ - "severity": "error", - "timestamp": time.Now().UTC().Format(time.RFC3339), - }, - }) - return - } - appErr := pkgErrors.FromError(err) - response.ErrorWithLog(c, err, appErr.HTTPStatus(), appErr.Error(), appErr.Metadata()) -} - -func (h *EncounterHandler) Create(c *gin.Context) { - var req encounter.EncounterRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - - // Di sini, Anda bisa menyimpan result.RawResponse atau result.ID ke database log jika diperlukan. - // Contoh: - // go logService.Create(c.Request.Context(), "encounter_create", req, result.RawResponse, http.StatusCreated) - - response.Success(c, http.StatusCreated, "Successfully created Encounter", result.FullResponse) -} - -func (h *EncounterHandler) Update(c *gin.Context) { - id := c.Param("id") - var req encounter.EncounterRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated Encounter", result.FullResponse) -} - -func (h *EncounterHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req encounter.EncounterPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", customErr) - return - } - - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched Encounter", result.FullResponse) -} - -func (h *EncounterHandler) GetByID(c *gin.Context) { - id := c.Param("id") - result, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Encounter", result.FullResponse) -} - -func (h *EncounterHandler) Search(c *gin.Context) { - // Get query parameters string natively and fetch it directly (like: ?patient=xxx&status=active) - queryParams := c.Request.URL.Query() - result, err := h.service.Search(c.Request.Context(), queryParams) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Encounters", result.FullResponse) -} - -func (h *EncounterHandler) SyncFromSIMRS(c *gin.Context) { - idxdaftarStr := c.Param("idxdaftar") - idxdaftar, err := strconv.ParseInt(idxdaftarStr, 10, 64) - if err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format idxdaftar tidak valid", nil) - return - } - - result, err := h.service.SyncFromSIMRS(c.Request.Context(), idxdaftar) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully synced Encounter from SIMRS", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/episodeofcare_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/episodeofcare_handler.go deleted file mode 100644 index e76bf03..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/episodeofcare_handler.go +++ /dev/null @@ -1,102 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/episodeofcare" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type EpisodeOfCareHandler struct { - service episodeofcare.Service -} - -func NewEpisodeOfCareHandler(service episodeofcare.Service) *EpisodeOfCareHandler { - return &EpisodeOfCareHandler{ - service: service, - } -} - -func (h *EpisodeOfCareHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/episodeofcare") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *EpisodeOfCareHandler) Create(c *gin.Context) { - var req episodeofcare.EpisodeOfCareRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created EpisodeOfCare", result) -} - -func (h *EpisodeOfCareHandler) Update(c *gin.Context) { - id := c.Param("id") - var req episodeofcare.EpisodeOfCareRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated EpisodeOfCare", result) -} - -func (h *EpisodeOfCareHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req episodeofcare.EpisodeOfCarePatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", customErr) - return - } - - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched EpisodeOfCare", result) -} - -func (h *EpisodeOfCareHandler) GetByID(c *gin.Context) { - id := c.Param("id") - result, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved EpisodeOfCare", result) -} - -func (h *EpisodeOfCareHandler) Search(c *gin.Context) { - queryParams := c.Request.URL.Query() - result, err := h.service.Search(c.Request.Context(), queryParams) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved EpisodeOfCare records", result) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/imagingstudy_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/imagingstudy_handler.go deleted file mode 100644 index 3c28094..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/imagingstudy_handler.go +++ /dev/null @@ -1,102 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/imagingstudy" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type ImagingStudyHandler struct { - service imagingstudy.Service -} - -func NewImagingStudyHandler(service imagingstudy.Service) *ImagingStudyHandler { - return &ImagingStudyHandler{ - service: service, - } -} - -func (h *ImagingStudyHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/imagingstudy") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *ImagingStudyHandler) Create(c *gin.Context) { - var req imagingstudy.ImagingStudyRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created ImagingStudy", result) -} - -func (h *ImagingStudyHandler) Update(c *gin.Context) { - id := c.Param("id") - var req imagingstudy.ImagingStudyRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated ImagingStudy", result) -} - -func (h *ImagingStudyHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req imagingstudy.ImagingStudyPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", customErr) - return - } - - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched ImagingStudy", result) -} - -func (h *ImagingStudyHandler) GetByID(c *gin.Context) { - id := c.Param("id") - result, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved ImagingStudy", result) -} - -func (h *ImagingStudyHandler) Search(c *gin.Context) { - queryParams := c.Request.URL.Query() - result, err := h.service.Search(c.Request.Context(), queryParams) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved ImagingStudies", result) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/immunization_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/immunization_handler.go deleted file mode 100644 index dd9df2b..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/immunization_handler.go +++ /dev/null @@ -1,81 +0,0 @@ -package usecase - -import ( - "net/http" - "service/internal/satusehat/usecase/immunization" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type ImmunizationHandler struct{ service immunization.Service } - -func NewImmunizationHandler(s immunization.Service) *ImmunizationHandler { - return &ImmunizationHandler{service: s} -} - -func (h *ImmunizationHandler) RegisterRoutes(router *gin.RouterGroup) { - g := router.Group("/satusehat/immunization") - g.POST("", h.Create) - g.GET("", h.Search) - g.GET("/:id", h.GetByID) - g.PUT("/:id", h.Update) - g.PATCH("/:id", h.Patch) -} - -func (h *ImmunizationHandler) Create(c *gin.Context) { - var req immunization.ImmunizationRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Success", res.FullResponse) -} -func (h *ImmunizationHandler) Update(c *gin.Context) { - var req immunization.ImmunizationRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Update(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *ImmunizationHandler) Patch(c *gin.Context) { - var req immunization.ImmunizationPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid patch", validator.TranslateError(err)) - return - } - res, err := h.service.Patch(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *ImmunizationHandler) GetByID(c *gin.Context) { - res, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *ImmunizationHandler) Search(c *gin.Context) { - res, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/medication_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/medication_handler.go deleted file mode 100644 index 8b50c08..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/medication_handler.go +++ /dev/null @@ -1,102 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/medication" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type MedicationHandler struct { - service medication.Service -} - -func NewMedicationHandler(service medication.Service) *MedicationHandler { - return &MedicationHandler{ - service: service, - } -} - -func (h *MedicationHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/medication") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *MedicationHandler) Create(c *gin.Context) { - var req medication.MedicationRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created Medication", result.FullResponse) -} - -func (h *MedicationHandler) Update(c *gin.Context) { - id := c.Param("id") - var req medication.MedicationRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated Medication", result.FullResponse) -} - -func (h *MedicationHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req medication.MedicationPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", customErr) - return - } - - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched Medication", result.FullResponse) -} - -func (h *MedicationHandler) GetByID(c *gin.Context) { - id := c.Param("id") - result, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Medication", result.FullResponse) -} - -func (h *MedicationHandler) Search(c *gin.Context) { - queryParams := c.Request.URL.Query() - result, err := h.service.Search(c.Request.Context(), queryParams) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Medications", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/medicationdispense_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/medicationdispense_handler.go deleted file mode 100644 index 15425ad..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/medicationdispense_handler.go +++ /dev/null @@ -1,91 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/medicationdispense" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type MedicationDispenseHandler struct { - service medicationdispense.Service -} - -func NewMedicationDispenseHandler(service medicationdispense.Service) *MedicationDispenseHandler { - return &MedicationDispenseHandler{service: service} -} - -func (h *MedicationDispenseHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/medicationdispense") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *MedicationDispenseHandler) Create(c *gin.Context) { - var req medicationdispense.MedicationDispenseRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created MedicationDispense", result.FullResponse) -} - -func (h *MedicationDispenseHandler) Update(c *gin.Context) { - id := c.Param("id") - var req medicationdispense.MedicationDispenseRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated MedicationDispense", result.FullResponse) -} - -func (h *MedicationDispenseHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req medicationdispense.MedicationDispensePatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched MedicationDispense", result.FullResponse) -} - -func (h *MedicationDispenseHandler) GetByID(c *gin.Context) { - result, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved", result.FullResponse) -} -func (h *MedicationDispenseHandler) Search(c *gin.Context) { - result, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/medicationrequest_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/medicationrequest_handler.go deleted file mode 100644 index 7298025..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/medicationrequest_handler.go +++ /dev/null @@ -1,91 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/medicationrequest" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type MedicationRequestHandler struct { - service medicationrequest.Service -} - -func NewMedicationRequestHandler(service medicationrequest.Service) *MedicationRequestHandler { - return &MedicationRequestHandler{service: service} -} - -func (h *MedicationRequestHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/medicationrequest") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *MedicationRequestHandler) Create(c *gin.Context) { - var req medicationrequest.MedicationRequestRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created MedicationRequest", result.FullResponse) -} - -func (h *MedicationRequestHandler) Update(c *gin.Context) { - id := c.Param("id") - var req medicationrequest.MedicationRequestRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated MedicationRequest", result.FullResponse) -} - -func (h *MedicationRequestHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req medicationrequest.MedicationRequestPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched MedicationRequest", result.FullResponse) -} - -func (h *MedicationRequestHandler) GetByID(c *gin.Context) { - result, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved", result.FullResponse) -} -func (h *MedicationRequestHandler) Search(c *gin.Context) { - result, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/medicationstatement_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/medicationstatement_handler.go deleted file mode 100644 index b658812..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/medicationstatement_handler.go +++ /dev/null @@ -1,91 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/medicationstatement" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type MedicationStatementHandler struct { - service medicationstatement.Service -} - -func NewMedicationStatementHandler(service medicationstatement.Service) *MedicationStatementHandler { - return &MedicationStatementHandler{service: service} -} - -func (h *MedicationStatementHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/medicationstatement") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *MedicationStatementHandler) Create(c *gin.Context) { - var req medicationstatement.MedicationStatementRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created MedicationStatement", result.FullResponse) -} - -func (h *MedicationStatementHandler) Update(c *gin.Context) { - id := c.Param("id") - var req medicationstatement.MedicationStatementRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated MedicationStatement", result.FullResponse) -} - -func (h *MedicationStatementHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req medicationstatement.MedicationStatementPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched MedicationStatement", result.FullResponse) -} - -func (h *MedicationStatementHandler) GetByID(c *gin.Context) { - result, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved", result.FullResponse) -} -func (h *MedicationStatementHandler) Search(c *gin.Context) { - result, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/observation_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/observation_handler.go deleted file mode 100644 index 71ce7f9..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/observation_handler.go +++ /dev/null @@ -1,102 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/observation" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type ObservationHandler struct { - service observation.Service -} - -func NewObservationHandler(service observation.Service) *ObservationHandler { - return &ObservationHandler{ - service: service, - } -} - -func (h *ObservationHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/observation") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *ObservationHandler) Create(c *gin.Context) { - var req observation.ObservationRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created Observation", result.FullResponse) -} - -func (h *ObservationHandler) Update(c *gin.Context) { - id := c.Param("id") - var req observation.ObservationRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated Observation", result.FullResponse) -} - -func (h *ObservationHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req observation.ObservationPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", customErr) - return - } - - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched Observation", result.FullResponse) -} - -func (h *ObservationHandler) GetByID(c *gin.Context) { - id := c.Param("id") - result, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Observation", result.FullResponse) -} - -func (h *ObservationHandler) Search(c *gin.Context) { - queryParams := c.Request.URL.Query() - result, err := h.service.Search(c.Request.Context(), queryParams) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Observations", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/procedure_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/procedure_handler.go deleted file mode 100644 index a1fd911..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/procedure_handler.go +++ /dev/null @@ -1,102 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/procedure" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type ProcedureHandler struct { - service procedure.Service -} - -func NewProcedureHandler(service procedure.Service) *ProcedureHandler { - return &ProcedureHandler{ - service: service, - } -} - -func (h *ProcedureHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/procedure") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *ProcedureHandler) Create(c *gin.Context) { - var req procedure.ProcedureRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created Procedure", result.FullResponse) -} - -func (h *ProcedureHandler) Update(c *gin.Context) { - id := c.Param("id") - var req procedure.ProcedureRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated Procedure", result.FullResponse) -} - -func (h *ProcedureHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req procedure.ProcedurePatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", customErr) - return - } - - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched Procedure", result.FullResponse) -} - -func (h *ProcedureHandler) GetByID(c *gin.Context) { - id := c.Param("id") - result, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Procedure", result.FullResponse) -} - -func (h *ProcedureHandler) Search(c *gin.Context) { - queryParams := c.Request.URL.Query() - result, err := h.service.Search(c.Request.Context(), queryParams) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved Procedures", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/questionnaireresponse_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/questionnaireresponse_handler.go deleted file mode 100644 index 1bb187d..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/questionnaireresponse_handler.go +++ /dev/null @@ -1,91 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/questionnaireresponse" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type QuestionnaireResponseHandler struct { - service questionnaireresponse.Service -} - -func NewQuestionnaireResponseHandler(service questionnaireresponse.Service) *QuestionnaireResponseHandler { - return &QuestionnaireResponseHandler{service: service} -} - -func (h *QuestionnaireResponseHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/questionnaireresponse") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *QuestionnaireResponseHandler) Create(c *gin.Context) { - var req questionnaireresponse.QuestionnaireResponseRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created QuestionnaireResponse", result.FullResponse) -} - -func (h *QuestionnaireResponseHandler) Update(c *gin.Context) { - id := c.Param("id") - var req questionnaireresponse.QuestionnaireResponseRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated QuestionnaireResponse", result.FullResponse) -} - -func (h *QuestionnaireResponseHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req questionnaireresponse.QuestionnaireResponsePatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", validator.TranslateError(err)) - return - } - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched QuestionnaireResponse", result.FullResponse) -} - -func (h *QuestionnaireResponseHandler) GetByID(c *gin.Context) { - result, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved", result.FullResponse) -} -func (h *QuestionnaireResponseHandler) Search(c *gin.Context) { - result, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/servicerequest_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/servicerequest_handler.go deleted file mode 100644 index 8142d07..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/servicerequest_handler.go +++ /dev/null @@ -1,102 +0,0 @@ -package usecase - -import ( - "net/http" - - "service/internal/satusehat/usecase/servicerequest" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type ServiceRequestHandler struct { - service servicerequest.Service -} - -func NewServiceRequestHandler(service servicerequest.Service) *ServiceRequestHandler { - return &ServiceRequestHandler{ - service: service, - } -} - -func (h *ServiceRequestHandler) RegisterRoutes(router *gin.RouterGroup) { - group := router.Group("/satusehat/servicerequest") - { - group.POST("", h.Create) - group.GET("", h.Search) - group.GET("/:id", h.GetByID) - group.PUT("/:id", h.Update) - group.PATCH("/:id", h.Patch) - } -} - -func (h *ServiceRequestHandler) Create(c *gin.Context) { - var req servicerequest.ServiceRequestRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Successfully created ServiceRequest", result.FullResponse) -} - -func (h *ServiceRequestHandler) Update(c *gin.Context) { - id := c.Param("id") - var req servicerequest.ServiceRequestRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan tidak valid", customErr) - return - } - - result, err := h.service.Update(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully updated ServiceRequest", result.FullResponse) -} - -func (h *ServiceRequestHandler) Patch(c *gin.Context) { - id := c.Param("id") - var req servicerequest.ServiceRequestPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - customErr := validator.TranslateError(err) - response.ErrorWithLog(c, err, http.StatusBadRequest, "Format permintaan patch tidak valid", customErr) - return - } - - result, err := h.service.Patch(c.Request.Context(), id, req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully patched ServiceRequest", result.FullResponse) -} - -func (h *ServiceRequestHandler) GetByID(c *gin.Context) { - id := c.Param("id") - result, err := h.service.GetByID(c.Request.Context(), id) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved ServiceRequest", result.FullResponse) -} - -func (h *ServiceRequestHandler) Search(c *gin.Context) { - queryParams := c.Request.URL.Query() - result, err := h.service.Search(c.Request.Context(), queryParams) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Successfully retrieved ServiceRequests", result.FullResponse) -} diff --git a/internal/infrastructure/transport/http/handlers/satusehat/usecase/specimen_handler.go b/internal/infrastructure/transport/http/handlers/satusehat/usecase/specimen_handler.go deleted file mode 100644 index 6e3b359..0000000 --- a/internal/infrastructure/transport/http/handlers/satusehat/usecase/specimen_handler.go +++ /dev/null @@ -1,79 +0,0 @@ -package usecase - -import ( - "net/http" - "service/internal/satusehat/usecase/specimen" - "service/pkg/response" - "service/pkg/utils/validator" - - "github.com/gin-gonic/gin" -) - -type SpecimenHandler struct{ service specimen.Service } - -func NewSpecimenHandler(s specimen.Service) *SpecimenHandler { return &SpecimenHandler{service: s} } - -func (h *SpecimenHandler) RegisterRoutes(router *gin.RouterGroup) { - g := router.Group("/satusehat/specimen") - g.POST("", h.Create) - g.GET("", h.Search) - g.GET("/:id", h.GetByID) - g.PUT("/:id", h.Update) - g.PATCH("/:id", h.Patch) -} - -func (h *SpecimenHandler) Create(c *gin.Context) { - var req specimen.SpecimenRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Create(c.Request.Context(), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusCreated, "Success", res.FullResponse) -} -func (h *SpecimenHandler) Update(c *gin.Context) { - var req specimen.SpecimenRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid request", validator.TranslateError(err)) - return - } - res, err := h.service.Update(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *SpecimenHandler) Patch(c *gin.Context) { - var req specimen.SpecimenPatchRequest - if err := c.ShouldBindJSON(&req); err != nil { - response.ErrorWithLog(c, err, http.StatusBadRequest, "Invalid patch", validator.TranslateError(err)) - return - } - res, err := h.service.Patch(c.Request.Context(), c.Param("id"), req) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *SpecimenHandler) GetByID(c *gin.Context) { - res, err := h.service.GetByID(c.Request.Context(), c.Param("id")) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} -func (h *SpecimenHandler) Search(c *gin.Context) { - res, err := h.service.Search(c.Request.Context(), c.Request.URL.Query()) - if err != nil { - handleSatuSehatError(c, err) - return - } - response.Success(c, http.StatusOK, "Success", res.FullResponse) -} diff --git a/internal/infrastructure/transport/http/routes/routes.go b/internal/infrastructure/transport/http/routes/routes.go index 95c0334..a41007c 100644 --- a/internal/infrastructure/transport/http/routes/routes.go +++ b/internal/infrastructure/transport/http/routes/routes.go @@ -8,15 +8,9 @@ import ( "service/internal/infrastructure/config" "service/internal/infrastructure/transport/http/middleware" - antrolHttp "service/internal/infrastructure/transport/http/handlers/bpjs/antrol" - aplicareHttp "service/internal/infrastructure/transport/http/handlers/bpjs/aplicare" - apotekHttp "service/internal/infrastructure/transport/http/handlers/bpjs/apotek" - vclaimHttp "service/internal/infrastructure/transport/http/handlers/bpjs/vclaim" authHttp "service/internal/infrastructure/transport/http/handlers/main/auth" healthHttp "service/internal/infrastructure/transport/http/handlers/main/health" roleHttp "service/internal/infrastructure/transport/http/handlers/main/master/roles" - satuSehatRefHttp "service/internal/infrastructure/transport/http/handlers/satusehat/reference" - satuSehatUsecaseHttp "service/internal/infrastructure/transport/http/handlers/satusehat/usecase" "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" @@ -26,40 +20,10 @@ import ( // ModuleHandlers menampung seluruh HTTP handler opsional dari berbagai modul. // Jika sebuah handler bernilai nil, maka rutenya akan otomatis diabaikan (disabled). type ModuleHandlers struct { - Auth *authHttp.AuthHandler - RolePages *roleHttp.RolPagesHandler - RolePermission *roleHttp.RolPermissionHandler - RoleMaster *roleHttp.RoleMasterHandler - Sep *vclaimHttp.SepHandler - Peserta *vclaimHttp.PesertaHandler - Antrol *antrolHttp.AntrolHandler - AplicareBed *aplicareHttp.BedHandler - ApotekReference *apotekHttp.ReferenceHandler - SatuSehatAuth *satuSehatRefHttp.AuthHandler - SatuSehatPatient *satuSehatRefHttp.PatientHandler - SatuSehatPractitioner *satuSehatRefHttp.PractitionerHandler - SatuSehatOrganization *satuSehatRefHttp.OrganizationHandler - SatuSehatLocation *satuSehatRefHttp.LocationHandler - SatuSehatKFA *satuSehatRefHttp.KFAHandler - SSAllergyIntolerance *satuSehatUsecaseHttp.AllergyIntoleranceHandler - SSCarePlan *satuSehatUsecaseHttp.CarePlanHandler - SSClinicalImpression *satuSehatUsecaseHttp.ClinicalImpressionHandler - SSComposition *satuSehatUsecaseHttp.CompositionHandler - SSCondition *satuSehatUsecaseHttp.ConditionHandler - SSDiagnosticReport *satuSehatUsecaseHttp.DiagnosticReportHandler - SSEncounter *satuSehatUsecaseHttp.EncounterHandler - SSEpisodeOfCare *satuSehatUsecaseHttp.EpisodeOfCareHandler - SSImagingStudy *satuSehatUsecaseHttp.ImagingStudyHandler - SSImmunization *satuSehatUsecaseHttp.ImmunizationHandler - SSMedication *satuSehatUsecaseHttp.MedicationHandler - SSMedicationDispense *satuSehatUsecaseHttp.MedicationDispenseHandler - SSMedicationRequest *satuSehatUsecaseHttp.MedicationRequestHandler - SSMedicationStatement *satuSehatUsecaseHttp.MedicationStatementHandler - SSObservation *satuSehatUsecaseHttp.ObservationHandler - SSProcedure *satuSehatUsecaseHttp.ProcedureHandler - SSQuestionnaireResponse *satuSehatUsecaseHttp.QuestionnaireResponseHandler - SSServiceRequest *satuSehatUsecaseHttp.ServiceRequestHandler - SSSpecimen *satuSehatUsecaseHttp.SpecimenHandler + Auth *authHttp.AuthHandler + RolePages *roleHttp.RolPagesHandler + RolePermission *roleHttp.RolPermissionHandler + RoleMaster *roleHttp.RoleMasterHandler } // SetupRoutes mendaftarkan seluruh endpoint API secara dinamis berdasarkan @@ -153,111 +117,6 @@ func SetupRoutes( if h.RoleMaster != nil { h.RoleMaster.RegisterRoutes(protected) } - - // --- Routes Modul BPJS VClaim --- - if h.Sep != nil { - h.Sep.RegisterRoutes(protected) - } - if h.Peserta != nil { - h.Peserta.RegisterRoutes(protected) - } - - // --- Routes Modul BPJS Antrol --- - if h.Antrol != nil { - h.Antrol.RegisterRoutes(protected) - } - - // --- Routes Modul BPJS Aplicares --- - if h.AplicareBed != nil { - h.AplicareBed.RegisterRoutes(protected) - } - - // --- Routes Modul BPJS Apotek --- - if h.ApotekReference != nil { - h.ApotekReference.RegisterRoutes(protected) - } - - // --- Routes Modul Satu Sehat --- - // Buat grup khusus untuk membatasi traffic hit API ke Kemenkes - satuSehatGroup := protected.Group("") - satuSehatGroup.Use(middleware.MemoryRateLimitMiddleware(5.0, 10)) // Max 5 RPS, Burst capacity 10 - { - if h.SatuSehatAuth != nil { - h.SatuSehatAuth.RegisterRoutes(satuSehatGroup) - } - if h.SatuSehatPatient != nil { - h.SatuSehatPatient.RegisterRoutes(satuSehatGroup) - } - if h.SatuSehatPractitioner != nil { - h.SatuSehatPractitioner.RegisterRoutes(satuSehatGroup) - } - if h.SatuSehatOrganization != nil { - h.SatuSehatOrganization.RegisterRoutes(satuSehatGroup) - } - if h.SatuSehatLocation != nil { - h.SatuSehatLocation.RegisterRoutes(satuSehatGroup) - } - if h.SatuSehatKFA != nil { - h.SatuSehatKFA.RegisterRoutes(satuSehatGroup) - } - if h.SSAllergyIntolerance != nil { - h.SSAllergyIntolerance.RegisterRoutes(satuSehatGroup) - } - if h.SSCarePlan != nil { - h.SSCarePlan.RegisterRoutes(satuSehatGroup) - } - if h.SSClinicalImpression != nil { - h.SSClinicalImpression.RegisterRoutes(satuSehatGroup) - } - if h.SSComposition != nil { - h.SSComposition.RegisterRoutes(satuSehatGroup) - } - if h.SSCondition != nil { - h.SSCondition.RegisterRoutes(satuSehatGroup) - } - if h.SSDiagnosticReport != nil { - h.SSDiagnosticReport.RegisterRoutes(satuSehatGroup) - } - if h.SSEncounter != nil { - h.SSEncounter.RegisterRoutes(satuSehatGroup) - } - if h.SSEpisodeOfCare != nil { - h.SSEpisodeOfCare.RegisterRoutes(satuSehatGroup) - } - if h.SSImagingStudy != nil { - h.SSImagingStudy.RegisterRoutes(satuSehatGroup) - } - if h.SSImmunization != nil { - h.SSImmunization.RegisterRoutes(satuSehatGroup) - } - if h.SSMedication != nil { - h.SSMedication.RegisterRoutes(satuSehatGroup) - } - if h.SSMedicationDispense != nil { - h.SSMedicationDispense.RegisterRoutes(satuSehatGroup) - } - if h.SSMedicationRequest != nil { - h.SSMedicationRequest.RegisterRoutes(satuSehatGroup) - } - if h.SSMedicationStatement != nil { - h.SSMedicationStatement.RegisterRoutes(satuSehatGroup) - } - if h.SSObservation != nil { - h.SSObservation.RegisterRoutes(satuSehatGroup) - } - if h.SSProcedure != nil { - h.SSProcedure.RegisterRoutes(satuSehatGroup) - } - if h.SSQuestionnaireResponse != nil { - h.SSQuestionnaireResponse.RegisterRoutes(satuSehatGroup) - } - if h.SSServiceRequest != nil { - h.SSServiceRequest.RegisterRoutes(satuSehatGroup) - } - if h.SSSpecimen != nil { - h.SSSpecimen.RegisterRoutes(satuSehatGroup) - } - } } } } diff --git a/internal/infrastructure/transport/http/servers/registry.go b/internal/infrastructure/transport/http/servers/registry.go index a44eb3a..6fb9419 100644 --- a/internal/infrastructure/transport/http/servers/registry.go +++ b/internal/infrastructure/transport/http/servers/registry.go @@ -8,40 +8,9 @@ import ( "gorm.io/gorm" "service/internal/auth" - antrol "service/internal/bpjs/antrol/reference" - aplicareBed "service/internal/bpjs/aplicare/bed" - apotekDpho "service/internal/bpjs/apotek/reference/dpho" - apotekPoli "service/internal/bpjs/apotek/reference/poli" - peserta "service/internal/bpjs/vclaim/peserta" - sep "service/internal/bpjs/vclaim/sep" roleMaster "service/internal/master/role/master" rolePages "service/internal/master/role/pages" rolePermission "service/internal/master/role/permission" - satuSehatAuth "service/internal/satusehat/reference/auth" - satuSehatKfa "service/internal/satusehat/reference/kfa" - satuSehatLocation "service/internal/satusehat/reference/location" - satuSehatOrganization "service/internal/satusehat/reference/organization" - satuSehatPatient "service/internal/satusehat/reference/patient" - satuSehatPractitioner "service/internal/satusehat/reference/practitioner" - "service/internal/satusehat/usecase/allergyintolerance" - "service/internal/satusehat/usecase/careplan" - clinicalimpression "service/internal/satusehat/usecase/clinicalImpression" - "service/internal/satusehat/usecase/composition" - "service/internal/satusehat/usecase/condition" - "service/internal/satusehat/usecase/diagnosticreport" - "service/internal/satusehat/usecase/encounter" - "service/internal/satusehat/usecase/episodeofcare" - "service/internal/satusehat/usecase/imagingstudy" - "service/internal/satusehat/usecase/immunization" - "service/internal/satusehat/usecase/medication" - "service/internal/satusehat/usecase/medicationdispense" - "service/internal/satusehat/usecase/medicationrequest" - "service/internal/satusehat/usecase/medicationstatement" - "service/internal/satusehat/usecase/observation" - "service/internal/satusehat/usecase/procedure" - "service/internal/satusehat/usecase/questionnaireresponse" - "service/internal/satusehat/usecase/servicerequest" - "service/internal/satusehat/usecase/specimen" ) // MasterServices menampung kumpulan service untuk domain Master Data @@ -51,59 +20,6 @@ type MasterServices struct { RoleMaster roleMaster.Service } -// VClaimServices menampung kumpulan service untuk integrasi BPJS VClaim -type VClaimServices struct { - Sep sep.Service - Peserta peserta.Service -} - -// AntrolServices menampung kumpulan service untuk integrasi BPJS Antrean RS -type AntrolServices struct { - Reference antrol.Service -} - -// AplicaresServices menampung kumpulan service untuk integrasi BPJS Aplicares -type AplicaresServices struct { - Bed aplicareBed.Service -} - -// ApotekServices menampung kumpulan service untuk integrasi BPJS Apotek -type ApotekServices struct { - DPHO apotekDpho.Service - Poli apotekPoli.Service -} - -// SatuSehatServices menampung kumpulan service untuk integrasi Kemenkes Satu Sehat -type SatuSehatServices struct { - Auth satuSehatAuth.Service - Patient satuSehatPatient.Service - Practitioner satuSehatPractitioner.Service - Organization satuSehatOrganization.Service - Location satuSehatLocation.Service - KFA satuSehatKfa.Service - - // Usecase Services - AllergyIntolerance allergyintolerance.Service - CarePlan careplan.Service - ClinicalImpression clinicalimpression.Service - Composition composition.Service - Condition condition.Service - DiagnosticReport diagnosticreport.Service - Encounter encounter.Service - EpisodeOfCare episodeofcare.Service - ImagingStudy imagingstudy.Service - Immunization immunization.Service - Medication medication.Service - MedicationDispense medicationdispense.Service - MedicationRequest medicationrequest.Service - MedicationStatement medicationstatement.Service - Observation observation.Service - Procedure procedure.Service - QuestionnaireResponse questionnaireresponse.Service - ServiceRequest servicerequest.Service - Specimen specimen.Service -} - // ServiceRegistry berfungsi sebagai Dependency Injection Container untuk transport HTTP. // Struktur ini mencegah membengkaknya parameter pada saat inisialisasi API. type ServiceRegistry struct { @@ -115,9 +31,4 @@ type ServiceRegistry struct { // Modul Aplikasi (Pisahkan berdasarkan Bounded Context) AuthService auth.Service Master *MasterServices - VClaim *VClaimServices - Antrol *AntrolServices - Aplicare *AplicaresServices - Apotek *ApotekServices - SatuSehat *SatuSehatServices } diff --git a/internal/infrastructure/transport/http/servers/server.go b/internal/infrastructure/transport/http/servers/server.go index 1ebeed2..4bad18b 100644 --- a/internal/infrastructure/transport/http/servers/server.go +++ b/internal/infrastructure/transport/http/servers/server.go @@ -13,15 +13,9 @@ import ( "service/internal/infrastructure/transport/http/middleware" "service/internal/infrastructure/transport/http/routes" - antrolHttp "service/internal/infrastructure/transport/http/handlers/bpjs/antrol" - aplicareHttp "service/internal/infrastructure/transport/http/handlers/bpjs/aplicare" - apotekHttp "service/internal/infrastructure/transport/http/handlers/bpjs/apotek" - vclaimHttp "service/internal/infrastructure/transport/http/handlers/bpjs/vclaim" authHttp "service/internal/infrastructure/transport/http/handlers/main/auth" healthHttp "service/internal/infrastructure/transport/http/handlers/main/health" roleHttp "service/internal/infrastructure/transport/http/handlers/main/master/roles" - satuSehatRefHttp "service/internal/infrastructure/transport/http/handlers/satusehat/reference" - satuSehatUsecaseHttp "service/internal/infrastructure/transport/http/handlers/satusehat/usecase" // Inisialisasi pkg "service/pkg/errors" @@ -88,118 +82,6 @@ func NewHTTPServer( } } - // Inisialisasi Handlers Modul VClaim - if registry.VClaim != nil { - if registry.VClaim.Sep != nil { - appHandlers.Sep = vclaimHttp.NewSepHandler(registry.VClaim.Sep) - } - if registry.VClaim.Peserta != nil { - appHandlers.Peserta = vclaimHttp.NewPesertaHandler(registry.VClaim.Peserta) - } - } - - // Inisialisasi Handlers Modul Antrol - if registry.Antrol != nil { - if registry.Antrol.Reference != nil { - appHandlers.Antrol = antrolHttp.NewAntrolHandler(registry.Antrol.Reference) - } - } - - // Inisialisasi Handlers Modul Aplicares - if registry.Aplicare != nil { - if registry.Aplicare.Bed != nil { - appHandlers.AplicareBed = aplicareHttp.NewBedHandler(registry.Aplicare.Bed) - } - } - - // Inisialisasi Handlers Modul Apotek - if registry.Apotek != nil { - if registry.Apotek.DPHO != nil && registry.Apotek.Poli != nil { - appHandlers.ApotekReference = apotekHttp.NewReferenceHandler(registry.Apotek.DPHO, registry.Apotek.Poli) - } - } - - // Inisialisasi Handlers Modul Satu Sehat - if registry.SatuSehat != nil { - if registry.SatuSehat.Auth != nil { - appHandlers.SatuSehatAuth = satuSehatRefHttp.NewAuthHandler(registry.SatuSehat.Auth) - } - if registry.SatuSehat.Patient != nil { - appHandlers.SatuSehatPatient = satuSehatRefHttp.NewPatientHandler(registry.SatuSehat.Patient) - } - if registry.SatuSehat.Practitioner != nil { - appHandlers.SatuSehatPractitioner = satuSehatRefHttp.NewPractitionerHandler(registry.SatuSehat.Practitioner) - } - if registry.SatuSehat.Organization != nil { - appHandlers.SatuSehatOrganization = satuSehatRefHttp.NewOrganizationHandler(registry.SatuSehat.Organization) - } - if registry.SatuSehat.Location != nil { - appHandlers.SatuSehatLocation = satuSehatRefHttp.NewLocationHandler(registry.SatuSehat.Location) - } - if registry.SatuSehat.KFA != nil { - appHandlers.SatuSehatKFA = satuSehatRefHttp.NewKFAHandler(registry.SatuSehat.KFA) - } - - // Inisialisasi Handlers Modul Satu Sehat Usecase - if registry.SatuSehat.AllergyIntolerance != nil { - appHandlers.SSAllergyIntolerance = satuSehatUsecaseHttp.NewAllergyIntoleranceHandler(registry.SatuSehat.AllergyIntolerance) - } - if registry.SatuSehat.CarePlan != nil { - appHandlers.SSCarePlan = satuSehatUsecaseHttp.NewCarePlanHandler(registry.SatuSehat.CarePlan) - } - if registry.SatuSehat.ClinicalImpression != nil { - appHandlers.SSClinicalImpression = satuSehatUsecaseHttp.NewClinicalImpressionHandler(registry.SatuSehat.ClinicalImpression) - } - if registry.SatuSehat.Composition != nil { - appHandlers.SSComposition = satuSehatUsecaseHttp.NewCompositionHandler(registry.SatuSehat.Composition) - } - if registry.SatuSehat.Condition != nil { - appHandlers.SSCondition = satuSehatUsecaseHttp.NewConditionHandler(registry.SatuSehat.Condition) - } - if registry.SatuSehat.DiagnosticReport != nil { - appHandlers.SSDiagnosticReport = satuSehatUsecaseHttp.NewDiagnosticReportHandler(registry.SatuSehat.DiagnosticReport) - } - if registry.SatuSehat.Encounter != nil { - appHandlers.SSEncounter = satuSehatUsecaseHttp.NewEncounterHandler(registry.SatuSehat.Encounter) - } - if registry.SatuSehat.EpisodeOfCare != nil { - appHandlers.SSEpisodeOfCare = satuSehatUsecaseHttp.NewEpisodeOfCareHandler(registry.SatuSehat.EpisodeOfCare) - } - if registry.SatuSehat.ImagingStudy != nil { - appHandlers.SSImagingStudy = satuSehatUsecaseHttp.NewImagingStudyHandler(registry.SatuSehat.ImagingStudy) - } - if registry.SatuSehat.Immunization != nil { - appHandlers.SSImmunization = satuSehatUsecaseHttp.NewImmunizationHandler(registry.SatuSehat.Immunization) - } - if registry.SatuSehat.Medication != nil { - appHandlers.SSMedication = satuSehatUsecaseHttp.NewMedicationHandler(registry.SatuSehat.Medication) - } - if registry.SatuSehat.MedicationDispense != nil { - appHandlers.SSMedicationDispense = satuSehatUsecaseHttp.NewMedicationDispenseHandler(registry.SatuSehat.MedicationDispense) - } - if registry.SatuSehat.MedicationRequest != nil { - appHandlers.SSMedicationRequest = satuSehatUsecaseHttp.NewMedicationRequestHandler(registry.SatuSehat.MedicationRequest) - } - if registry.SatuSehat.MedicationStatement != nil { - appHandlers.SSMedicationStatement = satuSehatUsecaseHttp.NewMedicationStatementHandler(registry.SatuSehat.MedicationStatement) - } - if registry.SatuSehat.Observation != nil { - appHandlers.SSObservation = satuSehatUsecaseHttp.NewObservationHandler(registry.SatuSehat.Observation) - } - if registry.SatuSehat.Procedure != nil { - appHandlers.SSProcedure = satuSehatUsecaseHttp.NewProcedureHandler(registry.SatuSehat.Procedure) - } - if registry.SatuSehat.QuestionnaireResponse != nil { - appHandlers.SSQuestionnaireResponse = satuSehatUsecaseHttp.NewQuestionnaireResponseHandler(registry.SatuSehat.QuestionnaireResponse) - } - if registry.SatuSehat.ServiceRequest != nil { - appHandlers.SSServiceRequest = satuSehatUsecaseHttp.NewServiceRequestHandler(registry.SatuSehat.ServiceRequest) - } - if registry.SatuSehat.Specimen != nil { - appHandlers.SSSpecimen = satuSehatUsecaseHttp.NewSpecimenHandler(registry.SatuSehat.Specimen) - } - } - // Inisialisasi Health Handler dengan dependensi yang benar // Gunakan constructor baru yang menerima cache manager healthHandler := healthHttp.NewHealthHandlerWithCache(registry.PrimaryDB, registry.CacheManager, registry.Config, registry.DBManager) diff --git a/internal/satusehat/reference/auth/service.go b/internal/satusehat/reference/auth/service.go deleted file mode 100644 index 350bfe6..0000000 --- a/internal/satusehat/reference/auth/service.go +++ /dev/null @@ -1,83 +0,0 @@ -package auth - -import ( - "context" - "encoding/json" - "time" - - "service/internal/infrastructure/cache" - "service/internal/interfaces/satusehat" - "service/pkg/errors" - "service/pkg/logger" -) - -// Service mendefinisikan interface untuk manajemen Auth Satu Sehat di level aplikasi. -type Service interface { - GetToken(ctx context.Context) (map[string]interface{}, error) - RefreshToken(ctx context.Context) (map[string]interface{}, error) -} - -type service struct { - client satusehat.SatuSehatClient - cache *cache.Manager -} - -// NewService membuat instance baru dari auth service. -func NewService(client satusehat.SatuSehatClient, cacheManager *cache.Manager) Service { - return &service{ - client: client, - cache: cacheManager, - } -} - -func (s *service) GetToken(ctx context.Context) (map[string]interface{}, error) { - cacheKey := "satusehat:auth_data" - - // 1. Coba ambil dari Redis cache (sangat efisien untuk multi-instance/load balancer) - if s.cache != nil { - var cachedToken string - if err := s.cache.Get(ctx, cacheKey, &cachedToken); err == nil && cachedToken != "" { - var data map[string]interface{} - if err := json.Unmarshal([]byte(cachedToken), &data); err == nil { - logger.Default().Debug("🔑 Mendapatkan token Satu Sehat dari Redis Cache") - return data, nil - } - } - } - - // 2. Jika tidak ada di Redis (atau expired), ambil dari Klien Kemenkes - data, err := s.client.GetAccessToken(ctx) - if err != nil { - logger.Default().Error("Gagal mendapatkan token dari SatuSehat Client", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mendapatkan token Satu Sehat dari Kemenkes").Cause(err).Build() - } - - // 3. Simpan ke Redis cache (Diset 55 menit karena token Kemenkes biasanya expired dalam 60 menit) - if s.cache != nil { - if bytes, err := json.Marshal(data); err == nil { - _ = s.cache.Set(ctx, cacheKey, string(bytes), 55*time.Minute) - } - } - - return data, nil -} - -func (s *service) RefreshToken(ctx context.Context) (map[string]interface{}, error) { - // Refresh token secara paksa melewati cache in-memory HTTP Client - data, err := s.client.RefreshToken(ctx) - if err != nil { - logger.Default().Error("Gagal me-refresh token SatuSehat Client", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal melakukan refresh token Satu Sehat").Cause(err).Build() - } - - // Update sinkronisasi token terbaru ke Redis cache - if s.cache != nil { - cacheKey := "satusehat:auth_data" - if bytes, err := json.Marshal(data); err == nil { - _ = s.cache.Set(ctx, cacheKey, string(bytes), 55*time.Minute) - } - } - - logger.Default().Info("🔄 Token Satu Sehat berhasil di-refresh secara manual") - return data, nil -} diff --git a/internal/satusehat/reference/kfa/dto.go b/internal/satusehat/reference/kfa/dto.go deleted file mode 100644 index 74e7133..0000000 --- a/internal/satusehat/reference/kfa/dto.go +++ /dev/null @@ -1,10 +0,0 @@ -package kfa - -// KFASearchParams menampung parameter pencarian produk KFA -type KFASearchParams struct { - Page int `form:"page,default=1"` - Size int `form:"size,default=10"` - ProductType string `form:"product_type"` // Contoh: farmasi, alkes - Keyword string `form:"keyword"` // Kata kunci pencarian produk (jika didukung KFA) - From string `form:"from_"` // Query param from_ (digunakan untuk memfilter tanggal/waktu spesifik) -} diff --git a/internal/satusehat/reference/kfa/repository.go b/internal/satusehat/reference/kfa/repository.go deleted file mode 100644 index 43b2b5f..0000000 --- a/internal/satusehat/reference/kfa/repository.go +++ /dev/null @@ -1,67 +0,0 @@ -package kfa - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "strconv" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" - "service/pkg/logger" -) - -type Repository interface { - GetByCode(ctx context.Context, code string) (map[string]interface{}, error) - GetProducts(ctx context.Context, params KFASearchParams) (map[string]interface{}, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func parseResponse(body []byte) (map[string]interface{}, error) { - var res map[string]interface{} - if err := json.Unmarshal(body, &res); err != nil { - return nil, fmt.Errorf("failed to parse KFA response: %w", err) - } - return res, nil -} - -func (r *repository) GetByCode(ctx context.Context, code string) (map[string]interface{}, error) { - endpoint := fmt.Sprintf("/products?identifier=kfa&code=%s", url.QueryEscape(code)) - respBytes, err := r.client.DoKFA(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari produk KFA berdasarkan kode", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mencari produk KFA").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) GetProducts(ctx context.Context, params KFASearchParams) (map[string]interface{}, error) { - q := url.Values{} - q.Add("page", strconv.Itoa(params.Page)) - q.Add("size", strconv.Itoa(params.Size)) - if params.ProductType != "" { - q.Add("product_type", params.ProductType) - } - if params.Keyword != "" { - q.Add("keyword", params.Keyword) - } - if params.From != "" { - q.Add("from_", params.From) - } - - endpoint := "/products/all?" + q.Encode() - respBytes, err := r.client.DoKFA(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari daftar produk KFA", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mengambil daftar produk KFA").Cause(err).Build() - } - return parseResponse(respBytes) -} diff --git a/internal/satusehat/reference/kfa/service.go b/internal/satusehat/reference/kfa/service.go deleted file mode 100644 index 47fbf99..0000000 --- a/internal/satusehat/reference/kfa/service.go +++ /dev/null @@ -1,24 +0,0 @@ -package kfa - -import "context" - -type Service interface { - GetByCode(ctx context.Context, code string) (map[string]interface{}, error) - GetProducts(ctx context.Context, params KFASearchParams) (map[string]interface{}, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetByCode(ctx context.Context, code string) (map[string]interface{}, error) { - return s.repo.GetByCode(ctx, code) -} - -func (s *service) GetProducts(ctx context.Context, params KFASearchParams) (map[string]interface{}, error) { - return s.repo.GetProducts(ctx, params) -} diff --git a/internal/satusehat/reference/location/dto.go b/internal/satusehat/reference/location/dto.go deleted file mode 100644 index 8a35a88..0000000 --- a/internal/satusehat/reference/location/dto.go +++ /dev/null @@ -1,8 +0,0 @@ -package location - -// LocationSearchParams menampung kriteria pencarian Ruangan/Lokasi Satu Sehat -type LocationSearchParams struct { - Name string `form:"name"` - Organization string `form:"organization"` // ID Faskes pembuat - Identifier string `form:"identifier"` // Format {System}|{Value} -} diff --git a/internal/satusehat/reference/location/entity.go b/internal/satusehat/reference/location/entity.go deleted file mode 100644 index 9a48e00..0000000 --- a/internal/satusehat/reference/location/entity.go +++ /dev/null @@ -1,7 +0,0 @@ -package location - -// Konstanta standar untuk sistem identifier Location di Satu Sehat. -const ( - IdentifierSystemLocation = "http://sys-ids.kemkes.go.id/location" - PhysicalTypeSystem = "http://terminology.hl7.org/CodeSystem/location-physical-type" -) diff --git a/internal/satusehat/reference/location/repository.go b/internal/satusehat/reference/location/repository.go deleted file mode 100644 index dcebdb7..0000000 --- a/internal/satusehat/reference/location/repository.go +++ /dev/null @@ -1,90 +0,0 @@ -package location - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" - "service/pkg/logger" -) - -type Repository interface { - GetByID(ctx context.Context, id string) (map[string]interface{}, error) - Search(ctx context.Context, params LocationSearchParams) (map[string]interface{}, error) - Create(ctx context.Context, payload interface{}) (map[string]interface{}, error) - Update(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) - Patch(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func parseResponse(body []byte) (map[string]interface{}, error) { - var res map[string]interface{} - if err := json.Unmarshal(body, &res); err != nil { - return nil, fmt.Errorf("failed to parse SatuSehat response: %w", err) - } - return res, nil -} - -func (r *repository) GetByID(ctx context.Context, id string) (map[string]interface{}, error) { - endpoint := fmt.Sprintf("/Location/%s", id) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Location berdasarkan ID", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mencari Location").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) Search(ctx context.Context, params LocationSearchParams) (map[string]interface{}, error) { - q := url.Values{} - if params.Name != "" { - q.Add("name", params.Name) - } - if params.Organization != "" { - q.Add("organization", params.Organization) - } - if params.Identifier != "" { - q.Add("identifier", params.Identifier) - } - - endpoint := "/Location?" + q.Encode() - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Location", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal melakukan pencarian Location").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (map[string]interface{}, error) { - respBytes, err := r.client.DoRequest(ctx, "POST", "/Location", payload) - if err != nil { - return nil, err - } - return parseResponse(respBytes) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) { - respBytes, err := r.client.DoRequest(ctx, "PUT", fmt.Sprintf("/Location/%s", id), payload) - if err != nil { - return nil, err - } - return parseResponse(respBytes) -} -func (r *repository) Patch(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) { - respBytes, err := r.client.DoRequest(ctx, "PATCH", fmt.Sprintf("/Location/%s", id), payload) - if err != nil { - return nil, err - } - return parseResponse(respBytes) -} diff --git a/internal/satusehat/reference/location/service.go b/internal/satusehat/reference/location/service.go deleted file mode 100644 index bdb2b1d..0000000 --- a/internal/satusehat/reference/location/service.go +++ /dev/null @@ -1,37 +0,0 @@ -package location - -import "context" - -type Service interface { - GetByID(ctx context.Context, id string) (map[string]interface{}, error) - Search(ctx context.Context, params LocationSearchParams) (map[string]interface{}, error) - Create(ctx context.Context, payload interface{}) (map[string]interface{}, error) - Update(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) - Patch(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetByID(ctx context.Context, id string) (map[string]interface{}, error) { - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, params LocationSearchParams) (map[string]interface{}, error) { - return s.repo.Search(ctx, params) -} - -func (s *service) Create(ctx context.Context, payload interface{}) (map[string]interface{}, error) { - return s.repo.Create(ctx, payload) -} -func (s *service) Update(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) { - return s.repo.Update(ctx, id, payload) -} -func (s *service) Patch(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) { - return s.repo.Patch(ctx, id, payload) -} diff --git a/internal/satusehat/reference/organization/dto.go b/internal/satusehat/reference/organization/dto.go deleted file mode 100644 index 6b6db5c..0000000 --- a/internal/satusehat/reference/organization/dto.go +++ /dev/null @@ -1,8 +0,0 @@ -package organization - -// OrganizationSearchParams menampung parameter untuk pencarian Organisasi -type OrganizationSearchParams struct { - Name string `form:"name"` - PartOf string `form:"partof"` // ID Organisasi Parent - Identifier string `form:"identifier"` // Identifier Organisasi (contoh: http://sys-ids.kemkes.go.id/organization/10000004|R220001) -} diff --git a/internal/satusehat/reference/organization/entity.go b/internal/satusehat/reference/organization/entity.go deleted file mode 100644 index d4b07d9..0000000 --- a/internal/satusehat/reference/organization/entity.go +++ /dev/null @@ -1,7 +0,0 @@ -package organization - -// Konstanta standar untuk sistem identifier Organization di Satu Sehat. -const ( - IdentifierSystemOrg = "http://sys-ids.kemkes.go.id/organization" - TypeSystemOrg = "http://terminology.hl7.org/CodeSystem/organization-type" -) diff --git a/internal/satusehat/reference/organization/repository.go b/internal/satusehat/reference/organization/repository.go deleted file mode 100644 index 5850dd8..0000000 --- a/internal/satusehat/reference/organization/repository.go +++ /dev/null @@ -1,91 +0,0 @@ -package organization - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" - "service/pkg/logger" -) - -type Repository interface { - GetByID(ctx context.Context, id string) (map[string]interface{}, error) - Search(ctx context.Context, params OrganizationSearchParams) (map[string]interface{}, error) - Create(ctx context.Context, payload interface{}) (map[string]interface{}, error) - Update(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) - Patch(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func parseResponse(body []byte) (map[string]interface{}, error) { - var res map[string]interface{} - if err := json.Unmarshal(body, &res); err != nil { - return nil, fmt.Errorf("failed to parse SatuSehat response: %w", err) - } - return res, nil -} - -func (r *repository) GetByID(ctx context.Context, id string) (map[string]interface{}, error) { - endpoint := fmt.Sprintf("/Organization/%s", id) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Organization berdasarkan ID", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mencari Organization").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) Search(ctx context.Context, params OrganizationSearchParams) (map[string]interface{}, error) { - q := url.Values{} - if params.Name != "" { - q.Add("name", params.Name) - } - if params.PartOf != "" { - q.Add("partof", params.PartOf) - } - if params.Identifier != "" { - q.Add("identifier", params.Identifier) - } - - endpoint := "/Organization?" + q.Encode() - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Organization", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal melakukan pencarian Organization").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (map[string]interface{}, error) { - respBytes, err := r.client.DoRequest(ctx, "POST", "/Organization", payload) - if err != nil { - return nil, err - } - return parseResponse(respBytes) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) { - respBytes, err := r.client.DoRequest(ctx, "PUT", fmt.Sprintf("/Organization/%s", id), payload) - if err != nil { - return nil, err - } - return parseResponse(respBytes) -} - -func (r *repository) Patch(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) { - respBytes, err := r.client.DoRequest(ctx, "PATCH", fmt.Sprintf("/Organization/%s", id), payload) - if err != nil { - return nil, err - } - return parseResponse(respBytes) -} diff --git a/internal/satusehat/reference/organization/service.go b/internal/satusehat/reference/organization/service.go deleted file mode 100644 index d655374..0000000 --- a/internal/satusehat/reference/organization/service.go +++ /dev/null @@ -1,37 +0,0 @@ -package organization - -import "context" - -type Service interface { - GetByID(ctx context.Context, id string) (map[string]interface{}, error) - Search(ctx context.Context, params OrganizationSearchParams) (map[string]interface{}, error) - Create(ctx context.Context, payload interface{}) (map[string]interface{}, error) - Update(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) - Patch(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetByID(ctx context.Context, id string) (map[string]interface{}, error) { - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, params OrganizationSearchParams) (map[string]interface{}, error) { - return s.repo.Search(ctx, params) -} - -func (s *service) Create(ctx context.Context, payload interface{}) (map[string]interface{}, error) { - return s.repo.Create(ctx, payload) -} -func (s *service) Update(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) { - return s.repo.Update(ctx, id, payload) -} -func (s *service) Patch(ctx context.Context, id string, payload interface{}) (map[string]interface{}, error) { - return s.repo.Patch(ctx, id, payload) -} diff --git a/internal/satusehat/reference/patient/dto.go b/internal/satusehat/reference/patient/dto.go deleted file mode 100644 index 446bb92..0000000 --- a/internal/satusehat/reference/patient/dto.go +++ /dev/null @@ -1,20 +0,0 @@ -package patient - -// CreatePatientRequest adalah DTO internal yang lebih sederhana untuk diisi oleh Frontend. -type CreatePatientRequest struct { - NIK string `json:"nik" validate:"required"` - Name string `json:"name" validate:"required"` - Gender string `json:"gender" validate:"required"` // male, female, other, unknown - BirthDate string `json:"birth_date" validate:"required"` // Format: YYYY-MM-DD - Phone string `json:"phone"` // Opsional - Address string `json:"address"` // Opsional -} - -// PatientSearchParams menampung berbagai kriteria pencarian pasien Satu Sehat. -type PatientSearchParams struct { - Name string `form:"name"` - BirthDate string `form:"birthdate"` // Format: YYYY-MM-DD - Gender string `form:"gender"` // male, female, other, unknown - NIK string `form:"nik"` - NIKIbu string `form:"nik_ibu"` -} diff --git a/internal/satusehat/reference/patient/entity.go b/internal/satusehat/reference/patient/entity.go deleted file mode 100644 index 5fe4c3a..0000000 --- a/internal/satusehat/reference/patient/entity.go +++ /dev/null @@ -1,14 +0,0 @@ -package patient - -// PatientEntity mewakili konstanta dan aturan domain (business rules) untuk Pasien Satu Sehat. -const ( - // Standar Identifier System Kemenkes - IdentifierSystemNIK = "https://fhir.kemkes.go.id/id/nik" - IdentifierSystemNIKIbu = "https://fhir.kemkes.go.id/id/nik-ibu" - IdentifierSystemIHS = "https://fhir.kemkes.go.id/id/ihs-number" - - GenderMale = "male" - GenderFemale = "female" - GenderOther = "other" - GenderUnknown = "unknown" -) diff --git a/internal/satusehat/reference/patient/repository.go b/internal/satusehat/reference/patient/repository.go deleted file mode 100644 index c117ad9..0000000 --- a/internal/satusehat/reference/patient/repository.go +++ /dev/null @@ -1,123 +0,0 @@ -package patient - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" - "service/pkg/logger" -) - -// Repository mendefinisikan antarmuka komunikasi ke eksternal (Kemenkes API). -type Repository interface { - GetByNIK(ctx context.Context, nik string) (map[string]interface{}, error) - GetByID(ctx context.Context, id string) (map[string]interface{}, error) - Search(ctx context.Context, params PatientSearchParams) (map[string]interface{}, error) - Create(ctx context.Context, req CreatePatientRequest) (map[string]interface{}, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -// NewRepository membuat instance baru dari patient repository. -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -// helper untuk mem-parsing response body []byte menjadi Map JSON -func parseResponse(body []byte) (map[string]interface{}, error) { - var res map[string]interface{} - if err := json.Unmarshal(body, &res); err != nil { - return nil, fmt.Errorf("failed to parse SatuSehat response: %w", err) - } - return res, nil -} - -func (r *repository) GetByNIK(ctx context.Context, nik string) (map[string]interface{}, error) { - endpoint := fmt.Sprintf("/Patient?identifier=%s|%s", IdentifierSystemNIK, nik) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Pasien berdasarkan NIK", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mencari Pasien ke Satu Sehat").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) GetByID(ctx context.Context, id string) (map[string]interface{}, error) { - endpoint := fmt.Sprintf("/Patient/%s", id) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Pasien berdasarkan ID", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mencari Pasien ke Satu Sehat").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) Search(ctx context.Context, params PatientSearchParams) (map[string]interface{}, error) { - q := url.Values{} - - if params.Name != "" { - q.Add("name", params.Name) - } - if params.BirthDate != "" { - q.Add("birthdate", params.BirthDate) - } - if params.Gender != "" { - q.Add("gender", params.Gender) - } - if params.NIK != "" { - q.Add("identifier", IdentifierSystemNIK+"|"+params.NIK) - } else if params.NIKIbu != "" { - q.Add("identifier", IdentifierSystemNIKIbu+"|"+params.NIKIbu) - } - - endpoint := "/Patient?" + q.Encode() - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Pasien dengan parameter dinamis", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal melakukan pencarian Pasien ke Satu Sehat").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) Create(ctx context.Context, req CreatePatientRequest) (map[string]interface{}, error) { - payload := satusehat.NewFHIRPayload("Patient"). - Set("active", true). - Set("gender", req.Gender). - Set("birthDate", req.BirthDate). - Append("identifier", map[string]interface{}{ - "use": "official", - "system": IdentifierSystemNIK, - "value": req.NIK, - }). - Append("name", map[string]interface{}{ - "use": "official", - "text": req.Name, - }) - - if req.Phone != "" { - payload.Append("telecom", map[string]interface{}{ - "system": "phone", - "value": req.Phone, - "use": "mobile", - }) - } - if req.Address != "" { - payload.Append("address", map[string]interface{}{ - "use": "home", - "text": req.Address, - }) - } - - respBytes, err := r.client.DoRequest(ctx, "POST", "/Patient", payload) - if err != nil { - logger.Default().Error("Gagal mendaftarkan Pasien", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mendaftarkan Pasien ke Satu Sehat").Cause(err).Build() - } - - return parseResponse(respBytes) -} diff --git a/internal/satusehat/reference/patient/service.go b/internal/satusehat/reference/patient/service.go deleted file mode 100644 index d08fb92..0000000 --- a/internal/satusehat/reference/patient/service.go +++ /dev/null @@ -1,38 +0,0 @@ -package patient - -import ( - "context" -) - -// Service mendefinisikan interface untuk manajemen Pasien Satu Sehat -type Service interface { - GetByNIK(ctx context.Context, nik string) (map[string]interface{}, error) - GetByID(ctx context.Context, id string) (map[string]interface{}, error) - Search(ctx context.Context, params PatientSearchParams) (map[string]interface{}, error) - Create(ctx context.Context, req CreatePatientRequest) (map[string]interface{}, error) -} - -type service struct { - repo Repository -} - -// NewService membuat instance baru dari patient service. -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetByNIK(ctx context.Context, nik string) (map[string]interface{}, error) { - return s.repo.GetByNIK(ctx, nik) -} - -func (s *service) GetByID(ctx context.Context, id string) (map[string]interface{}, error) { - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, params PatientSearchParams) (map[string]interface{}, error) { - return s.repo.Search(ctx, params) -} - -func (s *service) Create(ctx context.Context, req CreatePatientRequest) (map[string]interface{}, error) { - return s.repo.Create(ctx, req) -} diff --git a/internal/satusehat/reference/practitioner/dto.go b/internal/satusehat/reference/practitioner/dto.go deleted file mode 100644 index ed16bbf..0000000 --- a/internal/satusehat/reference/practitioner/dto.go +++ /dev/null @@ -1,9 +0,0 @@ -package practitioner - -// PractitionerSearchParams menampung berbagai kriteria pencarian Tenaga Medis Satu Sehat. -type PractitionerSearchParams struct { - Name string `form:"name"` - NIK string `form:"nik"` - Gender string `form:"gender"` // male, female - BirthDate string `form:"birthdate"` // Format: YYYY-MM-DD -} diff --git a/internal/satusehat/reference/practitioner/entity.go b/internal/satusehat/reference/practitioner/entity.go deleted file mode 100644 index b127421..0000000 --- a/internal/satusehat/reference/practitioner/entity.go +++ /dev/null @@ -1,8 +0,0 @@ -package practitioner - -// Konstanta standar untuk sistem identifier Practitioner di Satu Sehat. -const ( - IdentifierSystemNIK = "https://fhir.kemkes.go.id/id/nik" - IdentifierSystemIHS = "https://fhir.kemkes.go.id/id/nakes-his-number" - IdentifierSystemSTR = "https://fhir.kemkes.go.id/id/str-kki-number" -) diff --git a/internal/satusehat/reference/practitioner/repository.go b/internal/satusehat/reference/practitioner/repository.go deleted file mode 100644 index 4856246..0000000 --- a/internal/satusehat/reference/practitioner/repository.go +++ /dev/null @@ -1,78 +0,0 @@ -package practitioner - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" - "service/pkg/logger" -) - -type Repository interface { - GetByNIK(ctx context.Context, nik string) (map[string]interface{}, error) - GetByID(ctx context.Context, id string) (map[string]interface{}, error) - Search(ctx context.Context, params PractitionerSearchParams) (map[string]interface{}, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func parseResponse(body []byte) (map[string]interface{}, error) { - var res map[string]interface{} - if err := json.Unmarshal(body, &res); err != nil { - return nil, fmt.Errorf("failed to parse SatuSehat response: %w", err) - } - return res, nil -} - -func (r *repository) GetByNIK(ctx context.Context, nik string) (map[string]interface{}, error) { - endpoint := fmt.Sprintf("/Practitioner?identifier=%s|%s", IdentifierSystemNIK, nik) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Practitioner berdasarkan NIK", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mencari Practitioner ke Satu Sehat").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) GetByID(ctx context.Context, id string) (map[string]interface{}, error) { - endpoint := fmt.Sprintf("/Practitioner/%s", id) - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Practitioner berdasarkan ID", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal mencari Practitioner ke Satu Sehat").Cause(err).Build() - } - return parseResponse(respBytes) -} - -func (r *repository) Search(ctx context.Context, params PractitionerSearchParams) (map[string]interface{}, error) { - q := url.Values{} - if params.Name != "" { - q.Add("name", params.Name) - } - if params.Gender != "" { - q.Add("gender", params.Gender) - } - if params.BirthDate != "" { - q.Add("birthdate", params.BirthDate) - } - if params.NIK != "" { - q.Add("identifier", IdentifierSystemNIK+"|"+params.NIK) - } - - endpoint := "/Practitioner?" + q.Encode() - respBytes, err := r.client.DoRequest(ctx, "GET", endpoint, nil) - if err != nil { - logger.Default().Error("Gagal mencari Practitioner", logger.ErrorField(err)) - return nil, errors.InternalError().Message("Gagal melakukan pencarian Practitioner").Cause(err).Build() - } - return parseResponse(respBytes) -} diff --git a/internal/satusehat/reference/practitioner/service.go b/internal/satusehat/reference/practitioner/service.go deleted file mode 100644 index 4667efd..0000000 --- a/internal/satusehat/reference/practitioner/service.go +++ /dev/null @@ -1,29 +0,0 @@ -package practitioner - -import "context" - -type Service interface { - GetByNIK(ctx context.Context, nik string) (map[string]interface{}, error) - GetByID(ctx context.Context, id string) (map[string]interface{}, error) - Search(ctx context.Context, params PractitionerSearchParams) (map[string]interface{}, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) GetByNIK(ctx context.Context, nik string) (map[string]interface{}, error) { - return s.repo.GetByNIK(ctx, nik) -} - -func (s *service) GetByID(ctx context.Context, id string) (map[string]interface{}, error) { - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, params PractitionerSearchParams) (map[string]interface{}, error) { - return s.repo.Search(ctx, params) -} diff --git a/internal/satusehat/usecase/allergyintolerance/dto.go b/internal/satusehat/usecase/allergyintolerance/dto.go deleted file mode 100644 index ba8278c..0000000 --- a/internal/satusehat/usecase/allergyintolerance/dto.go +++ /dev/null @@ -1,17 +0,0 @@ -package allergyintolerance - -import "time" - -type AllergyIntoleranceRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - ClinicalStatus string `json:"clinical_status" binding:"required,oneof=active inactive resolved"` - VerificationStatus string `json:"verification_status" binding:"required,oneof=unconfirmed presumed confirmed refuted entered-in-error"` - Category string `json:"category" binding:"required,oneof=food medication environment biologic"` - Code string `json:"code" binding:"required"` // SNOMED CT Code - Display string `json:"display" binding:"required"` // Display Name - RecordedDate time.Time `json:"recorded_date" binding:"required"` -} - -type AllergyIntolerancePatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/allergyintolerance/mapper.go b/internal/satusehat/usecase/allergyintolerance/mapper.go deleted file mode 100644 index 5041625..0000000 --- a/internal/satusehat/usecase/allergyintolerance/mapper.go +++ /dev/null @@ -1,42 +0,0 @@ -package allergyintolerance - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req AllergyIntoleranceRequest) satusehat.FHIRPayload { - return satusehat.NewFHIRPayload("AllergyIntolerance"). - Set("clinicalStatus", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", - "code": req.ClinicalStatus, - }, - }, - }). - Set("verificationStatus", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-verification", - "code": req.VerificationStatus, - }, - }, - }). - Set("category", []string{req.Category}). - Set("code", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://snomed.info/sct", - "code": req.Code, - "display": req.Display, - }, - }, - }). - Set("patient", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("recordedDate", req.RecordedDate.Format(time.RFC3339)) -} diff --git a/internal/satusehat/usecase/allergyintolerance/repository.go b/internal/satusehat/usecase/allergyintolerance/repository.go deleted file mode 100644 index 399144b..0000000 --- a/internal/satusehat/usecase/allergyintolerance/repository.go +++ /dev/null @@ -1,51 +0,0 @@ -package allergyintolerance - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req AllergyIntolerancePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type repository struct{ client satusehat.SatuSehatClient } - -func NewRepository(client satusehat.SatuSehatClient) Repository { return &repository{client: client} } - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/AllergyIntolerance", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/AllergyIntolerance/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req AllergyIntolerancePatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/AllergyIntolerance/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/AllergyIntolerance/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/AllergyIntolerance?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/allergyintolerance/service.go b/internal/satusehat/usecase/allergyintolerance/service.go deleted file mode 100644 index c1f3218..0000000 --- a/internal/satusehat/usecase/allergyintolerance/service.go +++ /dev/null @@ -1,38 +0,0 @@ -package allergyintolerance - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req AllergyIntoleranceRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req AllergyIntoleranceRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req AllergyIntolerancePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type service struct{ repo Repository } - -func NewService(repo Repository) Service { return &service{repo: repo} } - -func (s *service) Create(ctx context.Context, req AllergyIntoleranceRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req AllergyIntoleranceRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ID is required").Build() - } - return s.repo.Update(ctx, id, MapRequestToFHIR(req).Set("id", id)) -} -func (s *service) Patch(ctx context.Context, id string, req AllergyIntolerancePatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/careplan/dto.go b/internal/satusehat/usecase/careplan/dto.go deleted file mode 100644 index 4cde14f..0000000 --- a/internal/satusehat/usecase/careplan/dto.go +++ /dev/null @@ -1,18 +0,0 @@ -package careplan - -import "time" - -type CarePlanRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - PractitionerID string `json:"practitioner_id" binding:"required"` - PractitionerName string `json:"practitioner_name" binding:"required"` - Status string `json:"status" binding:"required,oneof=draft active on-hold revoked completed entered-in-error unknown"` - Intent string `json:"intent" binding:"required,oneof=proposal plan order option"` - Title string `json:"title" binding:"required"` - Description string `json:"description" binding:"required"` - CreatedDate time.Time `json:"created_date" binding:"required"` -} - -type CarePlanPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/careplan/mapper.go b/internal/satusehat/usecase/careplan/mapper.go deleted file mode 100644 index 53e825a..0000000 --- a/internal/satusehat/usecase/careplan/mapper.go +++ /dev/null @@ -1,24 +0,0 @@ -package careplan - -import ( - "service/internal/interfaces/satusehat" - "time" -) - -func MapRequestToFHIR(req CarePlanRequest) satusehat.FHIRPayload { - return satusehat.NewFHIRPayload("CarePlan"). - Set("status", req.Status). - Set("intent", req.Intent). - Set("title", req.Title). - Set("description", req.Description). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{"reference": "Encounter/" + req.EncounterID}). - Set("author", map[string]interface{}{ - "reference": "Practitioner/" + req.PractitionerID, - "display": req.PractitionerName, - }). - Set("created", req.CreatedDate.Format(time.RFC3339)) -} diff --git a/internal/satusehat/usecase/careplan/repository.go b/internal/satusehat/usecase/careplan/repository.go deleted file mode 100644 index 9cc83e6..0000000 --- a/internal/satusehat/usecase/careplan/repository.go +++ /dev/null @@ -1,51 +0,0 @@ -package careplan - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req CarePlanPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type repository struct{ client satusehat.SatuSehatClient } - -func NewRepository(client satusehat.SatuSehatClient) Repository { return &repository{client: client} } - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/CarePlan", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/CarePlan/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req CarePlanPatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/CarePlan/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/CarePlan/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/CarePlan?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/careplan/service.go b/internal/satusehat/usecase/careplan/service.go deleted file mode 100644 index 8db2fcf..0000000 --- a/internal/satusehat/usecase/careplan/service.go +++ /dev/null @@ -1,37 +0,0 @@ -package careplan - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req CarePlanRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req CarePlanRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req CarePlanPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type service struct{ repo Repository } - -func NewService(repo Repository) Service { return &service{repo: repo} } -func (s *service) Create(ctx context.Context, req CarePlanRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req CarePlanRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ID is required").Build() - } - return s.repo.Update(ctx, id, MapRequestToFHIR(req).Set("id", id)) -} -func (s *service) Patch(ctx context.Context, id string, req CarePlanPatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/clinicalImpression/dto.go b/internal/satusehat/usecase/clinicalImpression/dto.go deleted file mode 100644 index c3198b1..0000000 --- a/internal/satusehat/usecase/clinicalImpression/dto.go +++ /dev/null @@ -1,17 +0,0 @@ -package clinicalimpression - -import "time" - -type ClinicalImpressionRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - PractitionerID string `json:"practitioner_id" binding:"required"` - PractitionerName string `json:"practitioner_name" binding:"required"` - Status string `json:"status" binding:"required,oneof=in-progress completed entered-in-error"` - Date time.Time `json:"date" binding:"required"` - Summary string `json:"summary" binding:"required"` - Description string `json:"description" binding:"required"` -} - -type ClinicalImpressionPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/clinicalImpression/mapper.go b/internal/satusehat/usecase/clinicalImpression/mapper.go deleted file mode 100644 index efe013c..0000000 --- a/internal/satusehat/usecase/clinicalImpression/mapper.go +++ /dev/null @@ -1,23 +0,0 @@ -package clinicalimpression - -import ( - "service/internal/interfaces/satusehat" - "time" -) - -func MapRequestToFHIR(req ClinicalImpressionRequest) satusehat.FHIRPayload { - return satusehat.NewFHIRPayload("ClinicalImpression"). - Set("status", req.Status). - Set("description", req.Description). - Set("summary", req.Summary). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{"reference": "Encounter/" + req.EncounterID}). - Set("assessor", map[string]interface{}{ - "reference": "Practitioner/" + req.PractitionerID, - "display": req.PractitionerName, - }). - Set("date", req.Date.Format(time.RFC3339)) -} diff --git a/internal/satusehat/usecase/clinicalImpression/repository.go b/internal/satusehat/usecase/clinicalImpression/repository.go deleted file mode 100644 index 17320c1..0000000 --- a/internal/satusehat/usecase/clinicalImpression/repository.go +++ /dev/null @@ -1,51 +0,0 @@ -package clinicalimpression - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req ClinicalImpressionPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type repository struct{ client satusehat.SatuSehatClient } - -func NewRepository(client satusehat.SatuSehatClient) Repository { return &repository{client: client} } - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/ClinicalImpression", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/ClinicalImpression/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req ClinicalImpressionPatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/ClinicalImpression/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/ClinicalImpression/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/ClinicalImpression?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/clinicalImpression/service.go b/internal/satusehat/usecase/clinicalImpression/service.go deleted file mode 100644 index 65c9b32..0000000 --- a/internal/satusehat/usecase/clinicalImpression/service.go +++ /dev/null @@ -1,37 +0,0 @@ -package clinicalimpression - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req ClinicalImpressionRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req ClinicalImpressionRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req ClinicalImpressionPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type service struct{ repo Repository } - -func NewService(repo Repository) Service { return &service{repo: repo} } -func (s *service) Create(ctx context.Context, req ClinicalImpressionRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req ClinicalImpressionRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ID is required").Build() - } - return s.repo.Update(ctx, id, MapRequestToFHIR(req).Set("id", id)) -} -func (s *service) Patch(ctx context.Context, id string, req ClinicalImpressionPatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/composition/dto.go b/internal/satusehat/usecase/composition/dto.go deleted file mode 100644 index 8fe93cc..0000000 --- a/internal/satusehat/usecase/composition/dto.go +++ /dev/null @@ -1,17 +0,0 @@ -package composition - -import "time" - -type CompositionRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - PractitionerID string `json:"practitioner_id" binding:"required"` - PractitionerName string `json:"practitioner_name" binding:"required"` - Title string `json:"title" binding:"required"` - Status string `json:"status" binding:"required,oneof=preliminary final amended entered-in-error"` // preliminary, final, amended, entered-in-error - Date time.Time `json:"date" binding:"required"` -} - -// CompositionPatchRequest merepresentasikan payload operasi JSON Patch. -type CompositionPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/composition/mapper.go b/internal/satusehat/usecase/composition/mapper.go deleted file mode 100644 index 8f7e5aa..0000000 --- a/internal/satusehat/usecase/composition/mapper.go +++ /dev/null @@ -1,38 +0,0 @@ -package composition - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req CompositionRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("Composition"). - Set("status", req.Status). - Set("type", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://loinc.org", - "code": "11503-0", // Example: Medical records - "display": "Medical records", - }, - }, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("date", req.Date.Format(time.RFC3339)). - Set("title", req.Title) - - if req.PractitionerID != "" { - payload.Append("author", map[string]interface{}{ - "reference": "Practitioner/" + req.PractitionerID, - "display": req.PractitionerName, - }) - } - return payload -} diff --git a/internal/satusehat/usecase/composition/repository.go b/internal/satusehat/usecase/composition/repository.go deleted file mode 100644 index 5c72bed..0000000 --- a/internal/satusehat/usecase/composition/repository.go +++ /dev/null @@ -1,73 +0,0 @@ -package composition - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req CompositionPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - - return &satusehat.FHIRResponse{ - ID: resourceID, - FullResponse: result, - RawResponse: resp, - }, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/Composition", payload) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Composition/%s", id) - return r.executeRequest(ctx, "PUT", endpoint, payload) -} - -func (r *repository) Patch(ctx context.Context, id string, req CompositionPatchRequest) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Composition/%s", id) - return r.executeRequest(ctx, "PATCH", endpoint, req) -} - -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Composition/%s", id) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Composition?%s", queryParams.Encode()) - return r.executeRequest(ctx, "GET", endpoint, nil) -} diff --git a/internal/satusehat/usecase/composition/service.go b/internal/satusehat/usecase/composition/service.go deleted file mode 100644 index af67c1e..0000000 --- a/internal/satusehat/usecase/composition/service.go +++ /dev/null @@ -1,55 +0,0 @@ -package composition - -import ( - "context" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req CompositionRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req CompositionRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req CompositionPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req CompositionRequest) (*satusehat.FHIRResponse, error) { - fhirPayload := MapRequestToFHIR(req) - return s.repo.Create(ctx, fhirPayload) -} -func (s *service) Update(ctx context.Context, id string, req CompositionRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Composition ID is required").Build() - } - - fhirPayload := MapRequestToFHIR(req) - fhirPayload.Set("id", id) - - return s.repo.Update(ctx, id, fhirPayload) -} -func (s *service) Patch(ctx context.Context, id string, req CompositionPatchRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Composition ID is required").Build() - } - if len(req) == 0 { - return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build() - } - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/condition/dto.go b/internal/satusehat/usecase/condition/dto.go deleted file mode 100644 index 054064a..0000000 --- a/internal/satusehat/usecase/condition/dto.go +++ /dev/null @@ -1,18 +0,0 @@ -package condition - -import "time" - -type ConditionRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - ClinicalStatus string `json:"clinical_status" binding:"required,oneof=active recurrence relapse inactive remission resolved"` // active, recurrence, relapse, inactive, remission, resolved - CategoryCode string `json:"category_code" binding:"required"` // problem-list-item, encounter-diagnosis - CategoryDisplay string `json:"category_display" binding:"required"` - Code string `json:"code" binding:"required"` // SNOMED CT / ICD-10 code - Display string `json:"display" binding:"required"` // Diagnosis text - OnsetDateTime time.Time `json:"onset_date_time" binding:"required"` - RecordedDate time.Time `json:"recorded_date" binding:"required"` -} - -type ConditionPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/condition/mapper.go b/internal/satusehat/usecase/condition/mapper.go deleted file mode 100644 index cbb5c6f..0000000 --- a/internal/satusehat/usecase/condition/mapper.go +++ /dev/null @@ -1,50 +0,0 @@ -package condition - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req ConditionRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("Condition"). - Set("clinicalStatus", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", - "code": req.ClinicalStatus, - }, - }, - }). - Set("category", []map[string]interface{}{ - { - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/CodeSystem/condition-category", - "code": req.CategoryCode, - "display": req.CategoryDisplay, - }, - }, - }, - }). - Set("code", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://snomed.info/sct", - "code": req.Code, - "display": req.Display, - }, - }, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("onsetDateTime", req.OnsetDateTime.Format(time.RFC3339)). - Set("recordedDate", req.RecordedDate.Format(time.RFC3339)) - - return payload -} diff --git a/internal/satusehat/usecase/condition/repository.go b/internal/satusehat/usecase/condition/repository.go deleted file mode 100644 index 1ae9bf9..0000000 --- a/internal/satusehat/usecase/condition/repository.go +++ /dev/null @@ -1,72 +0,0 @@ -package condition - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, payload ConditionPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - - return &satusehat.FHIRResponse{ - ID: resourceID, - FullResponse: result, - RawResponse: resp, - }, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/Condition", payload) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Condition/%s", id) - return r.executeRequest(ctx, "PUT", endpoint, payload) -} - -func (r *repository) Patch(ctx context.Context, id string, payload ConditionPatchRequest) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Condition/%s", id) - return r.executeRequest(ctx, "PATCH", endpoint, payload) -} - -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Condition/%s", id) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Condition?%s", queryParams.Encode()) - return r.executeRequest(ctx, "GET", endpoint, nil) -} diff --git a/internal/satusehat/usecase/condition/service.go b/internal/satusehat/usecase/condition/service.go deleted file mode 100644 index ff07e78..0000000 --- a/internal/satusehat/usecase/condition/service.go +++ /dev/null @@ -1,62 +0,0 @@ -package condition - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req ConditionRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req ConditionRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req ConditionPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req ConditionRequest) (*satusehat.FHIRResponse, error) { - fhirPayload := MapRequestToFHIR(req) - return s.repo.Create(ctx, fhirPayload) -} - -func (s *service) Update(ctx context.Context, id string, req ConditionRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Condition ID is required").Build() - } - - fhirPayload := MapRequestToFHIR(req) - fhirPayload.Set("id", id) - - return s.repo.Update(ctx, id, fhirPayload) -} - -func (s *service) Patch(ctx context.Context, id string, req ConditionPatchRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Condition ID is required").Build() - } - if len(req) == 0 { - return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build() - } - return s.repo.Patch(ctx, id, req) -} - -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Condition ID is required").Build() - } - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - // Tambahkan validasi untuk query params jika diperlukan - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/diagnosticreport/dto.go b/internal/satusehat/usecase/diagnosticreport/dto.go deleted file mode 100644 index 87770b5..0000000 --- a/internal/satusehat/usecase/diagnosticreport/dto.go +++ /dev/null @@ -1,20 +0,0 @@ -package diagnosticreport - -import "time" - -type DiagnosticReportRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - PractitionerID string `json:"practitioner_id" binding:"required"` - PractitionerName string `json:"practitioner_name" binding:"required"` - Status string `json:"status" binding:"required,oneof=registered partial preliminary final amended corrected appended cancelled entered-in-error unknown"` - CategoryCode string `json:"category_code" binding:"required"` // e.g. LAB - CategoryDisplay string `json:"category_display" binding:"required"` - Code string `json:"code" binding:"required"` // LOINC code - Display string `json:"display" binding:"required"` - Issued time.Time `json:"issued" binding:"required"` - Conclusion string `json:"conclusion" binding:"required"` -} - -type DiagnosticReportPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/diagnosticreport/mapper.go b/internal/satusehat/usecase/diagnosticreport/mapper.go deleted file mode 100644 index b955972..0000000 --- a/internal/satusehat/usecase/diagnosticreport/mapper.go +++ /dev/null @@ -1,41 +0,0 @@ -package diagnosticreport - -import ( - "service/internal/interfaces/satusehat" - "time" -) - -func MapRequestToFHIR(req DiagnosticReportRequest) satusehat.FHIRPayload { - return satusehat.NewFHIRPayload("DiagnosticReport"). - Set("status", req.Status). - Set("category", []map[string]interface{}{ - { - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/CodeSystem/v2-0074", - "code": req.CategoryCode, - "display": req.CategoryDisplay, - }, - }, - }, - }). - Set("code", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://loinc.org", - "code": req.Code, - "display": req.Display, - }, - }, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{"reference": "Encounter/" + req.EncounterID}). - Set("performer", []map[string]interface{}{ - {"reference": "Practitioner/" + req.PractitionerID, "display": req.PractitionerName}, - }). - Set("issued", req.Issued.Format(time.RFC3339)). - Set("conclusion", req.Conclusion) -} diff --git a/internal/satusehat/usecase/diagnosticreport/repository.go b/internal/satusehat/usecase/diagnosticreport/repository.go deleted file mode 100644 index 1a3d596..0000000 --- a/internal/satusehat/usecase/diagnosticreport/repository.go +++ /dev/null @@ -1,51 +0,0 @@ -package diagnosticreport - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req DiagnosticReportPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type repository struct{ client satusehat.SatuSehatClient } - -func NewRepository(client satusehat.SatuSehatClient) Repository { return &repository{client: client} } - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/DiagnosticReport", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/DiagnosticReport/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req DiagnosticReportPatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/DiagnosticReport/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/DiagnosticReport/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/DiagnosticReport?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/diagnosticreport/service.go b/internal/satusehat/usecase/diagnosticreport/service.go deleted file mode 100644 index 5886a9d..0000000 --- a/internal/satusehat/usecase/diagnosticreport/service.go +++ /dev/null @@ -1,37 +0,0 @@ -package diagnosticreport - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req DiagnosticReportRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req DiagnosticReportRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req DiagnosticReportPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type service struct{ repo Repository } - -func NewService(repo Repository) Service { return &service{repo: repo} } -func (s *service) Create(ctx context.Context, req DiagnosticReportRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req DiagnosticReportRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ID is required").Build() - } - return s.repo.Update(ctx, id, MapRequestToFHIR(req).Set("id", id)) -} -func (s *service) Patch(ctx context.Context, id string, req DiagnosticReportPatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/encounter/dto.go b/internal/satusehat/usecase/encounter/dto.go deleted file mode 100644 index 5d8740e..0000000 --- a/internal/satusehat/usecase/encounter/dto.go +++ /dev/null @@ -1,44 +0,0 @@ -package encounter - -import ( - "database/sql" - "time" -) - -// EncounterRequest merepresentasikan data input untuk membuat atau memperbarui Encounter. -type EncounterRequest struct { - EncounterID string `json:"encounter_id" binding:"required"` - OrganizationID string `json:"organization_id" binding:"required"` - EpisodeOfCareID string `json:"episode_of_care_id,omitempty"` - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - PractitionerID string `json:"practitioner_id" binding:"required"` - PractitionerName string `json:"practitioner_name" binding:"required"` - LocationID string `json:"location_id" binding:"required"` - LocationName string `json:"location_name" binding:"required"` - Status string `json:"status" binding:"required,oneof=arrived in-progress finished cancelled"` // arrived, in-progress, finished, cancelled - Class string `json:"class" binding:"required,oneof=AMB IMP EMER"` // AMB (ambulatory), IMP (inpatient), EMER (emergency) - PeriodStart time.Time `json:"period_start" binding:"required"` - PeriodEnd *time.Time `json:"period_end,omitempty"` -} - -// EncounterPatchRequest merepresentasikan payload operasi JSON Patch. -type EncounterPatchRequest []map[string]interface{} - -// PendaftaranDB merepresentasikan baris data dari tabel t_pendaftaran -type PendaftaranDB struct { - IdxDaftar int64 `db:"idxdaftar"` - NoMR sql.NullString `db:"nomr"` - JamReg sql.NullTime `db:"jamreg"` - MasukPoly sql.NullTime `db:"masukpoly"` - KeluarPoly sql.NullTime `db:"keluarpoly"` - Batal sql.NullString `db:"batal"` - KdPoly sql.NullInt64 `db:"kdpoly"` - PoliNameHFIS sql.NullString `db:"poli_name_hfis"` - DokterIDHFIS sql.NullString `db:"dokter_id_hfis"` - DokterNameHFIS sql.NullString `db:"dokter_name_hfis"` - PasienNIK sql.NullString `db:"pasien_nik"` - DokterNIK sql.NullString `db:"dokter_nik"` - PatientIHS sql.NullString `db:"patient_ihs"` - PractitionerIHS sql.NullString `db:"practitioner_ihs"` -} diff --git a/internal/satusehat/usecase/encounter/mapper.go b/internal/satusehat/usecase/encounter/mapper.go deleted file mode 100644 index 778d21d..0000000 --- a/internal/satusehat/usecase/encounter/mapper.go +++ /dev/null @@ -1,141 +0,0 @@ -package encounter - -import ( - "fmt" - "time" - - "service/internal/interfaces/satusehat" -) - -// MapRequestToFHIR mengubah EncounterRequest (DTO internal) menjadi objek Payload FHIR. -// Penggunaan FHIRPayload (.Set dan .Append) akan memudahkan penulisan dan maintenance JSON yang kompleks. -func MapRequestToFHIR(req EncounterRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("Encounter"). - Set("status", req.Status). - Set("class", map[string]interface{}{ - "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", - "code": req.Class, - "display": getClassDisplay(req.Class), - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }) - - if req.OrganizationID != "" { - payload.Set("serviceProvider", map[string]interface{}{ - "reference": "Organization/" + req.OrganizationID, - }) - - if req.EncounterID != "" { - payload.Append("identifier", map[string]interface{}{ - "system": "http://sys-ids.kemkes.go.id/encounter/" + req.OrganizationID, - "value": req.EncounterID, - }) - } - } - - if req.EpisodeOfCareID != "" { - payload.Append("episodeOfCare", map[string]interface{}{ - "reference": "EpisodeOfCare/" + req.EpisodeOfCareID, - }) - } - - if req.PractitionerID != "" { - payload.Append("participant", map[string]interface{}{ - "type": []map[string]interface{}{ - { - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", - "code": "ATND", - "display": "attender", - }, - }, - }, - }, - "individual": map[string]interface{}{ - "reference": "Practitioner/" + req.PractitionerID, - "display": req.PractitionerName, - }, - }) - } - - if req.LocationID != "" { - payload.Append("location", map[string]interface{}{ - "location": map[string]interface{}{ - "reference": "Location/" + req.LocationID, - "display": req.LocationName, - }, - }) - } - - period := map[string]interface{}{ - "start": req.PeriodStart.Format(time.RFC3339), - } - if req.PeriodEnd != nil { - period["end"] = req.PeriodEnd.Format(time.RFC3339) - } - payload.Set("period", period) - - payload.Append("statusHistory", map[string]interface{}{ - "status": req.Status, - "period": period, - }) - - return payload -} - -// MapPendaftaranToRequest mengubah data database t_pendaftaran menjadi EncounterRequest -func MapPendaftaranToRequest(dbData PendaftaranDB, organizationID string, patientIHS string, practitionerIHS string) EncounterRequest { - // Penentuan status encounter - status := "arrived" - if dbData.Batal.Valid && dbData.Batal.String == "Y" { - status = "cancelled" - } else if dbData.KeluarPoly.Valid { - status = "finished" - } else if dbData.MasukPoly.Valid { - status = "in-progress" - } - - // Waktu mulai - periodStart := time.Now() - if dbData.MasukPoly.Valid { - periodStart = dbData.MasukPoly.Time - } else if dbData.JamReg.Valid { - periodStart = dbData.JamReg.Time - } - - var periodEnd *time.Time - if dbData.KeluarPoly.Valid { - periodEnd = &dbData.KeluarPoly.Time - } - - return EncounterRequest{ - EncounterID: fmt.Sprintf("%d", dbData.IdxDaftar), - OrganizationID: organizationID, - PatientID: patientIHS, // Hasil pemetaan/pencarian IHS - PatientName: "Pasien " + dbData.NoMR.String, // Fallback Name - PractitionerID: practitionerIHS, // Hasil pemetaan/pencarian IHS - PractitionerName: dbData.DokterNameHFIS.String, - LocationID: fmt.Sprintf("%d", dbData.KdPoly.Int64), // Catatan: Anda harus me-mapping ini ke IHS Location ID - LocationName: dbData.PoliNameHFIS.String, - Status: status, - Class: "AMB", // Default: Rawat Jalan (Ambulatory) - PeriodStart: periodStart, - PeriodEnd: periodEnd, - } -} - -func getClassDisplay(code string) string { - switch code { - case "AMB": - return "ambulatory" - case "IMP": - return "inpatient encounter" - case "EMER": - return "emergency" - default: - return "ambulatory" - } -} diff --git a/internal/satusehat/usecase/encounter/repository.go b/internal/satusehat/usecase/encounter/repository.go deleted file mode 100644 index afae8cc..0000000 --- a/internal/satusehat/usecase/encounter/repository.go +++ /dev/null @@ -1,130 +0,0 @@ -package encounter - -import ( - "context" - "database/sql" - "encoding/json" - "fmt" - "net/url" - "service/internal/infrastructure/database" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, payload EncounterPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) - GetPendaftaranByID(ctx context.Context, idxdaftar int64) (*PendaftaranDB, error) - SearchPatientByNIK(ctx context.Context, nik string) (*satusehat.FHIRResponse, error) - SearchPractitionerByNIK(ctx context.Context, nik string) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient - db database.Service -} - -func NewRepository(client satusehat.SatuSehatClient, db database.Service) Repository { - return &repository{client: client, db: db} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, payload interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, payload) - if err != nil { - return nil, err - } - return r.parseAndProcessResponse(resp) -} - -func (r *repository) parseAndProcessResponse(data []byte) (*satusehat.FHIRResponse, error) { - var result map[string]interface{} - if err := json.Unmarshal(data, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - // Ekstrak ID dari resource jika ada - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - - // Buat response terstruktur - fhirResponse := &satusehat.FHIRResponse{ - ID: resourceID, - FullResponse: result, - RawResponse: data, // Simpan data mentah untuk logging atau audit - } - - return fhirResponse, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/Encounter", payload) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Encounter/%s", id) - return r.executeRequest(ctx, "PUT", endpoint, payload) -} - -func (r *repository) Patch(ctx context.Context, id string, payload EncounterPatchRequest) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Encounter/%s", id) - return r.executeRequest(ctx, "PATCH", endpoint, payload) -} - -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Encounter/%s", id) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Encounter?%s", queryParams.Encode()) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) SearchPatientByNIK(ctx context.Context, nik string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Patient?identifier=https://fhir.kemkes.go.id/id/nik|%s", nik) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) SearchPractitionerByNIK(ctx context.Context, nik string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Practitioner?identifier=https://fhir.kemkes.go.id/id/nik|%s", nik) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) GetPendaftaranByID(ctx context.Context, idxdaftar int64) (*PendaftaranDB, error) { - // Ambil koneksi database internal - db, err := r.db.GetReadDB("default") - if err != nil { - return nil, err - } - - var p PendaftaranDB - query := ` - SELECT p.idxdaftar, p.nomr, p.jamreg, p.masukpoly, p.keluarpoly, p.batal, - p.kdpoly, p.poli_name_hfis, p.dokter_id_hfis, p.dokter_name_hfis, - COALESCE(NULLIF(mp.noktp_baru, ''), mp.noktp) AS pasien_nik, - dp.nik AS dokter_nik, - dpas."Nomor_satusehat" AS patient_ihs, - dp."Kode_satusehat" AS practitioner_ihs - FROM public.t_pendaftaran p - LEFT JOIN public.m_pasien mp ON p.nomr = mp.nomr - LEFT JOIN public.data_pasien dpas ON p.nomr = dpas."Nomor_rekamedik" - LEFT JOIN public.data_pegawai dp ON p.kddokter = dp."Kode_DPJP" - WHERE p.idxdaftar = $1` - - err = db.QueryRowContext(ctx, query, idxdaftar).Scan( - &p.IdxDaftar, &p.NoMR, &p.JamReg, &p.MasukPoly, &p.KeluarPoly, &p.Batal, - &p.KdPoly, &p.PoliNameHFIS, &p.DokterIDHFIS, &p.DokterNameHFIS, - &p.PasienNIK, &p.DokterNIK, &p.PatientIHS, &p.PractitionerIHS, - ) - if err != nil { - if err == sql.ErrNoRows { - return nil, fmt.Errorf("pendaftaran dengan idxdaftar %d tidak ditemukan", idxdaftar) - } - return nil, err - } - return &p, nil -} diff --git a/internal/satusehat/usecase/encounter/service.go b/internal/satusehat/usecase/encounter/service.go deleted file mode 100644 index 277f37b..0000000 --- a/internal/satusehat/usecase/encounter/service.go +++ /dev/null @@ -1,122 +0,0 @@ -package encounter - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "os" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req EncounterRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req EncounterRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req EncounterPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) - SyncFromSIMRS(ctx context.Context, idxdaftar int64) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req EncounterRequest) (*satusehat.FHIRResponse, error) { - fhirPayload := MapRequestToFHIR(req) - return s.repo.Create(ctx, fhirPayload) -} - -func (s *service) Update(ctx context.Context, id string, req EncounterRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Encounter ID is required").Build() - } - - fhirPayload := MapRequestToFHIR(req) - fhirPayload.Set("id", id) // Untuk Update (PUT), parameter ID di payload diwajibkan oleh standar API Kemenkes - - return s.repo.Update(ctx, id, fhirPayload) -} - -func (s *service) Patch(ctx context.Context, id string, req EncounterPatchRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Encounter ID is required").Build() - } - if len(req) == 0 { - return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build() - } - return s.repo.Patch(ctx, id, req) -} - -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Encounter ID is required").Build() - } - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - // Bisa ditambahkan validasi query params wajib di sini jika perlu - return s.repo.Search(ctx, queryParams) -} - -func (s *service) SyncFromSIMRS(ctx context.Context, idxdaftar int64) (*satusehat.FHIRResponse, error) { - // 1. Ambil data dari database SIMRS - pendaftaran, err := s.repo.GetPendaftaranByID(ctx, idxdaftar) - if err != nil { - return nil, fmt.Errorf("gagal mengambil data pendaftaran: %w", err) - } - - // 2. Ambil Organization ID RS Anda (Bisa dari environment variable atau parameter config) - orgID := os.Getenv("SATUSEHAT_ORGANIZATION_ID") // Sesuaikan bila ada package config terpisah - - // 3. Persiapkan Patient ID (IHS) dengan fallback pencarian ke NIK - patientIHS := pendaftaran.PatientIHS.String - if patientIHS == "" && pendaftaran.PasienNIK.Valid && pendaftaran.PasienNIK.String != "" { - resp, err := s.repo.SearchPatientByNIK(ctx, pendaftaran.PasienNIK.String) - if err == nil && resp != nil { - patientIHS = extractIDFromBundle(resp.RawResponse) - } - } - if patientIHS == "" { // Fallback terakhir (jaga-jaga agar mapping tak panic) - patientIHS = pendaftaran.NoMR.String - } - - // 4. Persiapkan Practitioner ID (IHS) dengan fallback pencarian ke NIK - practitionerIHS := pendaftaran.PractitionerIHS.String - if practitionerIHS == "" && pendaftaran.DokterNIK.Valid && pendaftaran.DokterNIK.String != "" { - resp, err := s.repo.SearchPractitionerByNIK(ctx, pendaftaran.DokterNIK.String) - if err == nil && resp != nil { - practitionerIHS = extractIDFromBundle(resp.RawResponse) - } - } - if practitionerIHS == "" { // Fallback terakhir - practitionerIHS = pendaftaran.DokterIDHFIS.String - } - - // 5. Mapping data database ke struktur Request Encounter API - req := MapPendaftaranToRequest(*pendaftaran, orgID, patientIHS, practitionerIHS) - - // 6. Proses Create/Kirim ke Satu Sehat menggunakan fungsi Create yang sudah ada - return s.Create(ctx, req) -} - -// extractIDFromBundle mem-parsing raw response FHIR Bundle untuk mengambil ID resource pertama -func extractIDFromBundle(data []byte) string { - var bundle struct { - Entry []struct { - Resource struct { - ID string `json:"id"` - } `json:"resource"` - } `json:"entry"` - } - if err := json.Unmarshal(data, &bundle); err == nil && len(bundle.Entry) > 0 { - return bundle.Entry[0].Resource.ID - } - return "" -} diff --git a/internal/satusehat/usecase/episodeofcare/dto.go b/internal/satusehat/usecase/episodeofcare/dto.go deleted file mode 100644 index 0adb19d..0000000 --- a/internal/satusehat/usecase/episodeofcare/dto.go +++ /dev/null @@ -1,14 +0,0 @@ -package episodeofcare - -import "time" - -type EpisodeOfCareRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - OrganizationID string `json:"organization_id" binding:"required"` - Status string `json:"status" binding:"required,oneof=planned waitlist active onhold finished cancelled entered-in-error"` // planned, waitlist, active, onhold, finished, cancelled, entered-in-error - PeriodStart time.Time `json:"period_start" binding:"required"` - PeriodEnd *time.Time `json:"period_end,omitempty"` -} - -type EpisodeOfCarePatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/episodeofcare/mapper.go b/internal/satusehat/usecase/episodeofcare/mapper.go deleted file mode 100644 index 67176f5..0000000 --- a/internal/satusehat/usecase/episodeofcare/mapper.go +++ /dev/null @@ -1,30 +0,0 @@ -package episodeofcare - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req EpisodeOfCareRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("EpisodeOfCare"). - Set("status", req.Status). - Set("patient", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }) - - if req.OrganizationID != "" { - payload.Set("managingOrganization", map[string]interface{}{ - "reference": "Organization/" + req.OrganizationID, - }) - } - - period := map[string]interface{}{"start": req.PeriodStart.Format(time.RFC3339)} - if req.PeriodEnd != nil { - period["end"] = req.PeriodEnd.Format(time.RFC3339) - } - payload.Set("period", period) - - return payload -} diff --git a/internal/satusehat/usecase/episodeofcare/repository.go b/internal/satusehat/usecase/episodeofcare/repository.go deleted file mode 100644 index 93de669..0000000 --- a/internal/satusehat/usecase/episodeofcare/repository.go +++ /dev/null @@ -1,74 +0,0 @@ -package episodeofcare - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -// Repository mendefinisikan kontrak untuk operasi penyimpanan data EpisodeOfCare. -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, payload EpisodeOfCarePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -// NewRepository membuat repositori EpisodeOfCare baru. -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - - return &satusehat.FHIRResponse{ - ID: resourceID, - FullResponse: result, - RawResponse: resp, - }, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/EpisodeOfCare", payload) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/EpisodeOfCare/%s", id) - return r.executeRequest(ctx, "PUT", endpoint, payload) -} - -func (r *repository) Patch(ctx context.Context, id string, payload EpisodeOfCarePatchRequest) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/EpisodeOfCare/%s", id) - return r.executeRequest(ctx, "PATCH", endpoint, payload) -} - -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/EpisodeOfCare/%s", id) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/EpisodeOfCare?%s", queryParams.Encode()) - return r.executeRequest(ctx, "GET", endpoint, nil) -} diff --git a/internal/satusehat/usecase/episodeofcare/service.go b/internal/satusehat/usecase/episodeofcare/service.go deleted file mode 100644 index fe1700c..0000000 --- a/internal/satusehat/usecase/episodeofcare/service.go +++ /dev/null @@ -1,63 +0,0 @@ -package episodeofcare - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -// Service mendefinisikan kontrak untuk logika bisnis EpisodeOfCare. -type Service interface { - Create(ctx context.Context, req EpisodeOfCareRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req EpisodeOfCareRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req EpisodeOfCarePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -// NewService membuat service EpisodeOfCare baru. -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req EpisodeOfCareRequest) (*satusehat.FHIRResponse, error) { - fhirPayload := MapRequestToFHIR(req) - return s.repo.Create(ctx, fhirPayload) -} - -func (s *service) Update(ctx context.Context, id string, req EpisodeOfCareRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("EpisodeOfCare ID is required").Build() - } - - fhirPayload := MapRequestToFHIR(req) - fhirPayload.Set("id", id) - - return s.repo.Update(ctx, id, fhirPayload) -} - -func (s *service) Patch(ctx context.Context, id string, req EpisodeOfCarePatchRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("EpisodeOfCare ID is required").Build() - } - if len(req) == 0 { - return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build() - } - return s.repo.Patch(ctx, id, req) -} - -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("EpisodeOfCare ID is required").Build() - } - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/imagingstudy/dto.go b/internal/satusehat/usecase/imagingstudy/dto.go deleted file mode 100644 index 7430c74..0000000 --- a/internal/satusehat/usecase/imagingstudy/dto.go +++ /dev/null @@ -1,20 +0,0 @@ -package imagingstudy - -import "time" - -type ImagingStudyRequest struct { - PatientID string `json:"patient_id"` - PatientName string `json:"patient_name"` - EncounterID string `json:"encounter_id"` - PractitionerID string `json:"practitioner_id"` - PractitionerName string `json:"practitioner_name"` - Status string `json:"status"` // registered, available, cancelled, entered-in-error, unknown - Started time.Time `json:"started"` - NumberOfSeries int `json:"number_of_series"` - NumberOfInstances int `json:"number_of_instances"` - ProcedureCode string `json:"procedure_code"` // SNOMED CT - ProcedureDisplay string `json:"procedure_display"` - Description string `json:"description"` -} - -type ImagingStudyPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/imagingstudy/mapper.go b/internal/satusehat/usecase/imagingstudy/mapper.go deleted file mode 100644 index 53a9bd3..0000000 --- a/internal/satusehat/usecase/imagingstudy/mapper.go +++ /dev/null @@ -1,39 +0,0 @@ -package imagingstudy - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req ImagingStudyRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("ImagingStudy"). - Set("status", req.Status). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("started", req.Started.Format(time.RFC3339)). - Set("numberOfSeries", req.NumberOfSeries). - Set("numberOfInstances", req.NumberOfInstances). - Set("description", req.Description) - - if req.ProcedureCode != "" { - payload.Set("procedureCode", []map[string]interface{}{ - { - "coding": []map[string]interface{}{ - { - "system": "http://snomed.info/sct", - "code": req.ProcedureCode, - "display": req.ProcedureDisplay, - }, - }, - }, - }) - } - - return payload -} diff --git a/internal/satusehat/usecase/imagingstudy/repository.go b/internal/satusehat/usecase/imagingstudy/repository.go deleted file mode 100644 index 62602e5..0000000 --- a/internal/satusehat/usecase/imagingstudy/repository.go +++ /dev/null @@ -1,74 +0,0 @@ -package imagingstudy - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -// Repository mendefinisikan kontrak untuk operasi penyimpanan data ImagingStudy. -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, payload ImagingStudyPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -// NewRepository membuat repositori ImagingStudy baru. -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - - return &satusehat.FHIRResponse{ - ID: resourceID, - FullResponse: result, - RawResponse: resp, - }, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/ImagingStudy", payload) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/ImagingStudy/%s", id) - return r.executeRequest(ctx, "PUT", endpoint, payload) -} - -func (r *repository) Patch(ctx context.Context, id string, payload ImagingStudyPatchRequest) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/ImagingStudy/%s", id) - return r.executeRequest(ctx, "PATCH", endpoint, payload) -} - -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/ImagingStudy/%s", id) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/ImagingStudy?%s", queryParams.Encode()) - return r.executeRequest(ctx, "GET", endpoint, nil) -} diff --git a/internal/satusehat/usecase/imagingstudy/service.go b/internal/satusehat/usecase/imagingstudy/service.go deleted file mode 100644 index 95bdb9f..0000000 --- a/internal/satusehat/usecase/imagingstudy/service.go +++ /dev/null @@ -1,63 +0,0 @@ -package imagingstudy - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -// Service mendefinisikan kontrak untuk logika bisnis ImagingStudy. -type Service interface { - Create(ctx context.Context, req ImagingStudyRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req ImagingStudyRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req ImagingStudyPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -// NewService membuat service ImagingStudy baru. -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req ImagingStudyRequest) (*satusehat.FHIRResponse, error) { - fhirPayload := MapRequestToFHIR(req) - return s.repo.Create(ctx, fhirPayload) -} - -func (s *service) Update(ctx context.Context, id string, req ImagingStudyRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ImagingStudy ID is required").Build() - } - - fhirPayload := MapRequestToFHIR(req) - fhirPayload.Set("id", id) - - return s.repo.Update(ctx, id, fhirPayload) -} - -func (s *service) Patch(ctx context.Context, id string, req ImagingStudyPatchRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ImagingStudy ID is required").Build() - } - if len(req) == 0 { - return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build() - } - return s.repo.Patch(ctx, id, req) -} - -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ImagingStudy ID is required").Build() - } - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/immunization/dto.go b/internal/satusehat/usecase/immunization/dto.go deleted file mode 100644 index 4b6d3fc..0000000 --- a/internal/satusehat/usecase/immunization/dto.go +++ /dev/null @@ -1,19 +0,0 @@ -package immunization - -import "time" - -type ImmunizationRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - Status string `json:"status" binding:"required,oneof=completed entered-in-error not-done"` - VaccineCode string `json:"vaccine_code" binding:"required"` // KFA Code for Vaccine - VaccineDisplay string `json:"vaccine_display" binding:"required"` - OccurrenceDateTime time.Time `json:"occurrence_date_time" binding:"required"` - PrimarySource bool `json:"primary_source"` - LotNumber string `json:"lot_number,omitempty"` - PractitionerID string `json:"practitioner_id" binding:"required"` - PractitionerName string `json:"practitioner_name" binding:"required"` -} - -type ImmunizationPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/immunization/mapper.go b/internal/satusehat/usecase/immunization/mapper.go deleted file mode 100644 index 51ff1b3..0000000 --- a/internal/satusehat/usecase/immunization/mapper.go +++ /dev/null @@ -1,33 +0,0 @@ -package immunization - -import ( - "service/internal/interfaces/satusehat" - "time" -) - -func MapRequestToFHIR(req ImmunizationRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("Immunization"). - Set("status", req.Status). - Set("vaccineCode", map[string]interface{}{ - "coding": []map[string]interface{}{ - {"system": "http://sys-ids.kemkes.go.id/kfa", "code": req.VaccineCode, "display": req.VaccineDisplay}, - }, - }). - Set("patient", map[string]interface{}{"reference": "Patient/" + req.PatientID, "display": req.PatientName}). - Set("encounter", map[string]interface{}{"reference": "Encounter/" + req.EncounterID}). - Set("occurrenceDateTime", req.OccurrenceDateTime.Format(time.RFC3339)). - Set("primarySource", req.PrimarySource). - Set("performer", []map[string]interface{}{ - { - "actor": map[string]interface{}{ - "reference": "Practitioner/" + req.PractitionerID, - "display": req.PractitionerName, - }, - }, - }) - - if req.LotNumber != "" { - payload.Set("lotNumber", req.LotNumber) - } - return payload -} diff --git a/internal/satusehat/usecase/immunization/repository.go b/internal/satusehat/usecase/immunization/repository.go deleted file mode 100644 index b78c034..0000000 --- a/internal/satusehat/usecase/immunization/repository.go +++ /dev/null @@ -1,51 +0,0 @@ -package immunization - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req ImmunizationPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type repository struct{ client satusehat.SatuSehatClient } - -func NewRepository(client satusehat.SatuSehatClient) Repository { return &repository{client: client} } - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/Immunization", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/Immunization/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req ImmunizationPatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/Immunization/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/Immunization/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/Immunization?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/immunization/service.go b/internal/satusehat/usecase/immunization/service.go deleted file mode 100644 index 0d625e0..0000000 --- a/internal/satusehat/usecase/immunization/service.go +++ /dev/null @@ -1,37 +0,0 @@ -package immunization - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req ImmunizationRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req ImmunizationRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req ImmunizationPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type service struct{ repo Repository } - -func NewService(repo Repository) Service { return &service{repo: repo} } -func (s *service) Create(ctx context.Context, req ImmunizationRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req ImmunizationRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ID is required").Build() - } - return s.repo.Update(ctx, id, MapRequestToFHIR(req).Set("id", id)) -} -func (s *service) Patch(ctx context.Context, id string, req ImmunizationPatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/medication/dto.go b/internal/satusehat/usecase/medication/dto.go deleted file mode 100644 index 3b12430..0000000 --- a/internal/satusehat/usecase/medication/dto.go +++ /dev/null @@ -1,16 +0,0 @@ -package medication - -import "time" - -type MedicationRequest struct { - StatusCode string `json:"status_code" binding:"required,oneof=active inactive entered-in-error"` - KfaCode string `json:"kfa_code" binding:"required"` - KfaDisplay string `json:"kfa_display" binding:"required"` - FormCode string `json:"form_code,omitempty"` - FormDisplay string `json:"form_display,omitempty"` - ManufacturerID string `json:"manufacturer_id,omitempty"` // Reference ke ID Organization (Pabrik/Distributor) - BatchNumber string `json:"batch_number,omitempty"` - ExpirationDate *time.Time `json:"expiration_date,omitempty"` -} - -type MedicationPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/medication/mapper.go b/internal/satusehat/usecase/medication/mapper.go deleted file mode 100644 index 3c9cf17..0000000 --- a/internal/satusehat/usecase/medication/mapper.go +++ /dev/null @@ -1,48 +0,0 @@ -package medication - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req MedicationRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("Medication"). - Set("status", req.StatusCode). - Set("code", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://sys-ids.kemkes.go.id/kfa", - "code": req.KfaCode, - "display": req.KfaDisplay, - }, - }, - }) - - if req.FormCode != "" { - payload.Set("form", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://terminology.kemkes.go.id/CodeSystem/medication-form", - "code": req.FormCode, - "display": req.FormDisplay, - }, - }, - }) - } - - if req.ManufacturerID != "" { - payload.Set("manufacturer", map[string]interface{}{ - "reference": "Organization/" + req.ManufacturerID, - }) - } - - if req.BatchNumber != "" && req.ExpirationDate != nil { - payload.Set("batch", map[string]interface{}{ - "lotNumber": req.BatchNumber, - "expirationDate": req.ExpirationDate.Format(time.RFC3339), - }) - } - - return payload -} diff --git a/internal/satusehat/usecase/medication/repository.go b/internal/satusehat/usecase/medication/repository.go deleted file mode 100644 index 3c7c039..0000000 --- a/internal/satusehat/usecase/medication/repository.go +++ /dev/null @@ -1,65 +0,0 @@ -package medication - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req MedicationPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - - return &satusehat.FHIRResponse{ - ID: resourceID, - FullResponse: result, - RawResponse: resp, - }, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/Medication", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/Medication/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req MedicationPatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/Medication/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/Medication/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/Medication?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/medication/service.go b/internal/satusehat/usecase/medication/service.go deleted file mode 100644 index 0428d2a..0000000 --- a/internal/satusehat/usecase/medication/service.go +++ /dev/null @@ -1,57 +0,0 @@ -package medication - -import ( - "context" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req MedicationRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req MedicationRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req MedicationPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req MedicationRequest) (*satusehat.FHIRResponse, error) { - fhirPayload := MapRequestToFHIR(req) - return s.repo.Create(ctx, fhirPayload) -} - -func (s *service) Update(ctx context.Context, id string, req MedicationRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Medication ID is required").Build() - } - fhirPayload := MapRequestToFHIR(req) - fhirPayload.Set("id", id) - return s.repo.Update(ctx, id, fhirPayload) -} - -func (s *service) Patch(ctx context.Context, id string, req MedicationPatchRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Medication ID is required").Build() - } - if len(req) == 0 { - return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build() - } - return s.repo.Patch(ctx, id, req) -} - -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/medicationdispense/dto.go b/internal/satusehat/usecase/medicationdispense/dto.go deleted file mode 100644 index 1349b53..0000000 --- a/internal/satusehat/usecase/medicationdispense/dto.go +++ /dev/null @@ -1,24 +0,0 @@ -package medicationdispense - -import "time" - -type MedicationDispenseRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - MedicationID string `json:"medication_id" binding:"required"` - MedicationDisplay string `json:"medication_display" binding:"required"` - PractitionerID string `json:"practitioner_id" binding:"required"` - PractitionerName string `json:"practitioner_name" binding:"required"` - LocationID string `json:"location_id" binding:"required"` - LocationName string `json:"location_name" binding:"required"` - PrescriptionID string `json:"prescription_id" binding:"required"` // Reference to MedicationRequest - Status string `json:"status" binding:"required,oneof=preparation in-progress cancelled on-hold completed entered-in-error stopped declined unknown"` - PreparedDate time.Time `json:"prepared_date" binding:"required"` - HandedOverDate time.Time `json:"handed_over_date" binding:"required"` - DispenseValue float64 `json:"dispense_value" binding:"required"` - DispenseUnit string `json:"dispense_unit" binding:"required"` - DosagePatientInstr string `json:"dosage_patient_instruction"` -} - -type MedicationDispensePatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/medicationdispense/mapper.go b/internal/satusehat/usecase/medicationdispense/mapper.go deleted file mode 100644 index 40ec143..0000000 --- a/internal/satusehat/usecase/medicationdispense/mapper.go +++ /dev/null @@ -1,51 +0,0 @@ -package medicationdispense - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req MedicationDispenseRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("MedicationDispense"). - Set("status", req.Status). - Set("category", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/fhir/CodeSystem/medicationdispense-category", - "code": "outpatient", - "display": "Outpatient", - }, - }, - }). - Set("medicationReference", map[string]interface{}{ - "reference": "Medication/" + req.MedicationID, - "display": req.MedicationDisplay, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("context", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("performer", []map[string]interface{}{ - { - "actor": map[string]interface{}{ - "reference": "Practitioner/" + req.PractitionerID, - "display": req.PractitionerName, - }, - }, - }). - Set("location", map[string]interface{}{ - "reference": "Location/" + req.LocationID, - "display": req.LocationName, - }). - Set("authorizingPrescription", []map[string]interface{}{ - {"reference": "MedicationRequest/" + req.PrescriptionID}, - }). - Set("whenPrepared", req.PreparedDate.Format(time.RFC3339)). - Set("whenHandedOver", req.HandedOverDate.Format(time.RFC3339)) - - return payload -} diff --git a/internal/satusehat/usecase/medicationdispense/repository.go b/internal/satusehat/usecase/medicationdispense/repository.go deleted file mode 100644 index 725b04b..0000000 --- a/internal/satusehat/usecase/medicationdispense/repository.go +++ /dev/null @@ -1,58 +0,0 @@ -package medicationdispense - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req MedicationDispensePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/MedicationDispense", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/MedicationDispense/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req MedicationDispensePatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/MedicationDispense/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/MedicationDispense/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/MedicationDispense?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/medicationdispense/service.go b/internal/satusehat/usecase/medicationdispense/service.go deleted file mode 100644 index 6ccd8ea..0000000 --- a/internal/satusehat/usecase/medicationdispense/service.go +++ /dev/null @@ -1,46 +0,0 @@ -package medicationdispense - -import ( - "context" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req MedicationDispenseRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req MedicationDispenseRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req MedicationDispensePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req MedicationDispenseRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req MedicationDispenseRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("MedicationDispense ID is required").Build() - } - payload := MapRequestToFHIR(req) - payload.Set("id", id) - return s.repo.Update(ctx, id, payload) -} -func (s *service) Patch(ctx context.Context, id string, req MedicationDispensePatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/medicationrequest/dto.go b/internal/satusehat/usecase/medicationrequest/dto.go deleted file mode 100644 index 34656e2..0000000 --- a/internal/satusehat/usecase/medicationrequest/dto.go +++ /dev/null @@ -1,23 +0,0 @@ -package medicationrequest - -import "time" - -type MedicationRequestRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - PractitionerID string `json:"practitioner_id" binding:"required"` - PractitionerName string `json:"practitioner_name" binding:"required"` - MedicationID string `json:"medication_id" binding:"required"` // Reference to Medication resource - MedicationDisplay string `json:"medication_display" binding:"required"` - Status string `json:"status" binding:"required,oneof=active on-hold cancelled completed entered-in-error stopped draft unknown"` - Intent string `json:"intent" binding:"required,oneof=proposal plan order original-order reflex-order filler-order instance-order option"` - AuthoredOn time.Time `json:"authored_on" binding:"required"` - DosageText string `json:"dosage_text" binding:"required"` - PatientInstr string `json:"patient_instruction"` - DispenseValue float64 `json:"dispense_value" binding:"required"` - DispenseUnit string `json:"dispense_unit" binding:"required"` - SupplyDuration int `json:"supply_duration" binding:"required"` // in days -} - -type MedicationRequestPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/medicationrequest/mapper.go b/internal/satusehat/usecase/medicationrequest/mapper.go deleted file mode 100644 index b4990ca..0000000 --- a/internal/satusehat/usecase/medicationrequest/mapper.go +++ /dev/null @@ -1,60 +0,0 @@ -package medicationrequest - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req MedicationRequestRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("MedicationRequest"). - Set("status", req.Status). - Set("intent", req.Intent). - Set("category", []map[string]interface{}{ - { - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-category", - "code": "outpatient", - "display": "Outpatient", - }, - }, - }, - }). - Set("medicationReference", map[string]interface{}{ - "reference": "Medication/" + req.MedicationID, - "display": req.MedicationDisplay, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("authoredOn", req.AuthoredOn.Format(time.RFC3339)). - Set("requester", map[string]interface{}{ - "reference": "Practitioner/" + req.PractitionerID, - "display": req.PractitionerName, - }). - Set("dosageInstruction", []map[string]interface{}{ - { - "sequence": 1, - "text": req.DosageText, - "patientInstruction": req.PatientInstr, - }, - }). - Set("dispenseRequest", map[string]interface{}{ - "quantity": map[string]interface{}{ - "value": req.DispenseValue, - "code": req.DispenseUnit, - }, - "expectedSupplyDuration": map[string]interface{}{ - "value": req.SupplyDuration, - "unit": "days", - "system": "http://unitsofmeasure.org", - "code": "d", - }, - }) - return payload -} diff --git a/internal/satusehat/usecase/medicationrequest/repository.go b/internal/satusehat/usecase/medicationrequest/repository.go deleted file mode 100644 index 392ba12..0000000 --- a/internal/satusehat/usecase/medicationrequest/repository.go +++ /dev/null @@ -1,58 +0,0 @@ -package medicationrequest - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req MedicationRequestPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/MedicationRequest", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/MedicationRequest/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req MedicationRequestPatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/MedicationRequest/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/MedicationRequest/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/MedicationRequest?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/medicationrequest/service.go b/internal/satusehat/usecase/medicationrequest/service.go deleted file mode 100644 index 8fba79e..0000000 --- a/internal/satusehat/usecase/medicationrequest/service.go +++ /dev/null @@ -1,46 +0,0 @@ -package medicationrequest - -import ( - "context" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req MedicationRequestRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req MedicationRequestRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req MedicationRequestPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req MedicationRequestRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req MedicationRequestRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("MedicationRequest ID is required").Build() - } - payload := MapRequestToFHIR(req) - payload.Set("id", id) - return s.repo.Update(ctx, id, payload) -} -func (s *service) Patch(ctx context.Context, id string, req MedicationRequestPatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/medicationstatement/dto.go b/internal/satusehat/usecase/medicationstatement/dto.go deleted file mode 100644 index 43cbec2..0000000 --- a/internal/satusehat/usecase/medicationstatement/dto.go +++ /dev/null @@ -1,18 +0,0 @@ -package medicationstatement - -import "time" - -type MedicationStatementRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - Status string `json:"status" binding:"required,oneof=active completed entered-in-error intended stopped on-hold unknown not-taken"` - CategoryCode string `json:"category_code" binding:"required,oneof=inpatient outpatient community"` - MedicationCode string `json:"medication_code" binding:"required"` // KFA Code - MedicationDisplay string `json:"medication_display" binding:"required"` // KFA Name - EffectiveDateTime time.Time `json:"effective_date_time" binding:"required"` - DateAsserted time.Time `json:"date_asserted" binding:"required"` - DosageText string `json:"dosage_text" binding:"required"` -} - -type MedicationStatementPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/medicationstatement/mapper.go b/internal/satusehat/usecase/medicationstatement/mapper.go deleted file mode 100644 index 02c15cb..0000000 --- a/internal/satusehat/usecase/medicationstatement/mapper.go +++ /dev/null @@ -1,50 +0,0 @@ -package medicationstatement - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req MedicationStatementRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("MedicationStatement"). - Set("status", req.Status). - Set("category", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/CodeSystem/medication-statement-category", - "code": req.CategoryCode, - "display": req.CategoryCode, - }, - }, - }). - Set("medicationCodeableConcept", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://sys-ids.kemkes.go.id/kfa", - "code": req.MedicationCode, - "display": req.MedicationDisplay, - }, - }, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("context", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("informationSource", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("effectiveDateTime", req.EffectiveDateTime.Format(time.RFC3339)). - Set("dateAsserted", req.DateAsserted.Format(time.RFC3339)). - Set("dosage", []map[string]interface{}{ - { - "text": req.DosageText, - }, - }) - - return payload -} diff --git a/internal/satusehat/usecase/medicationstatement/repository.go b/internal/satusehat/usecase/medicationstatement/repository.go deleted file mode 100644 index 2dae584..0000000 --- a/internal/satusehat/usecase/medicationstatement/repository.go +++ /dev/null @@ -1,58 +0,0 @@ -package medicationstatement - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req MedicationStatementPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/MedicationStatement", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/MedicationStatement/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req MedicationStatementPatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/MedicationStatement/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/MedicationStatement/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/MedicationStatement?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/medicationstatement/service.go b/internal/satusehat/usecase/medicationstatement/service.go deleted file mode 100644 index fa5aa44..0000000 --- a/internal/satusehat/usecase/medicationstatement/service.go +++ /dev/null @@ -1,46 +0,0 @@ -package medicationstatement - -import ( - "context" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req MedicationStatementRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req MedicationStatementRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req MedicationStatementPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req MedicationStatementRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req MedicationStatementRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("MedicationStatement ID is required").Build() - } - payload := MapRequestToFHIR(req) - payload.Set("id", id) - return s.repo.Update(ctx, id, payload) -} -func (s *service) Patch(ctx context.Context, id string, req MedicationStatementPatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/observation/dto.go b/internal/satusehat/usecase/observation/dto.go deleted file mode 100644 index 816fedb..0000000 --- a/internal/satusehat/usecase/observation/dto.go +++ /dev/null @@ -1,20 +0,0 @@ -package observation - -import "time" - -type ObservationRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - Status string `json:"status" binding:"required,oneof=registered preliminary final amended"` // registered, preliminary, final, amended - CategoryCode string `json:"category_code" binding:"required"` // vital-signs, laboratory - CategoryDisplay string `json:"category_display" binding:"required"` - Code string `json:"code" binding:"required"` // LOINC code (e.g., 8867-4 for Heart rate) - Display string `json:"display" binding:"required"` // Heart rate - Value float64 `json:"value" binding:"required"` - Unit string `json:"unit" binding:"required"` - UnitCode string `json:"unit_code" binding:"required"` // UCUM code (e.g., /min) - EffectiveDateTime time.Time `json:"effective_date_time" binding:"required"` -} - -type ObservationPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/observation/mapper.go b/internal/satusehat/usecase/observation/mapper.go deleted file mode 100644 index 62b6646..0000000 --- a/internal/satusehat/usecase/observation/mapper.go +++ /dev/null @@ -1,48 +0,0 @@ -package observation - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req ObservationRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("Observation"). - Set("status", req.Status). - Set("category", []map[string]interface{}{ - { - "coding": []map[string]interface{}{ - { - "system": "http://terminology.hl7.org/CodeSystem/observation-category", - "code": req.CategoryCode, - "display": req.CategoryDisplay, - }, - }, - }, - }). - Set("code", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://loinc.org", - "code": req.Code, - "display": req.Display, - }, - }, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("effectiveDateTime", req.EffectiveDateTime.Format(time.RFC3339)). - Set("valueQuantity", map[string]interface{}{ - "value": req.Value, - "unit": req.Unit, - "system": "http://unitsofmeasure.org", - "code": req.UnitCode, - }) - - return payload -} diff --git a/internal/satusehat/usecase/observation/repository.go b/internal/satusehat/usecase/observation/repository.go deleted file mode 100644 index 7d2e5f6..0000000 --- a/internal/satusehat/usecase/observation/repository.go +++ /dev/null @@ -1,72 +0,0 @@ -package observation - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, payload ObservationPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type repository struct { - client satusehat.SatuSehatClient -} - -// NewRepository membuat repositori observasi baru. -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - - return &satusehat.FHIRResponse{ - ID: resourceID, - FullResponse: result, - RawResponse: resp, - }, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/Observation", payload) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Observation/%s", id) - return r.executeRequest(ctx, "PUT", endpoint, payload) -} - -func (r *repository) Patch(ctx context.Context, id string, payload ObservationPatchRequest) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Observation/%s", id) - return r.executeRequest(ctx, "PATCH", endpoint, payload) -} - -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Observation/%s", id) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Observation?%s", queryParams.Encode()) - return r.executeRequest(ctx, "GET", endpoint, nil) -} diff --git a/internal/satusehat/usecase/observation/service.go b/internal/satusehat/usecase/observation/service.go deleted file mode 100644 index c877b67..0000000 --- a/internal/satusehat/usecase/observation/service.go +++ /dev/null @@ -1,62 +0,0 @@ -package observation - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req ObservationRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req ObservationRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req ObservationPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type service struct { - repo Repository -} - -// NewService membuat service observasi baru. -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req ObservationRequest) (*satusehat.FHIRResponse, error) { - fhirPayload := MapRequestToFHIR(req) - return s.repo.Create(ctx, fhirPayload) -} - -func (s *service) Update(ctx context.Context, id string, req ObservationRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Observation ID is required").Build() - } - - fhirPayload := MapRequestToFHIR(req) - fhirPayload.Set("id", id) - - return s.repo.Update(ctx, id, fhirPayload) -} - -func (s *service) Patch(ctx context.Context, id string, req ObservationPatchRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Observation ID is required").Build() - } - if len(req) == 0 { - return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build() - } - return s.repo.Patch(ctx, id, req) -} - -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Observation ID is required").Build() - } - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - // Tambahkan validasi untuk query params jika diperlukan - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/procedure/dto.go b/internal/satusehat/usecase/procedure/dto.go deleted file mode 100644 index 7a8b7e3..0000000 --- a/internal/satusehat/usecase/procedure/dto.go +++ /dev/null @@ -1,19 +0,0 @@ -package procedure - -import "time" - -type ProcedureRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - Status string `json:"status" binding:"required,oneof=preparation in-progress not-done on-hold stopped completed entered-in-error unknown"` // preparation, in-progress, not-done, on-hold, stopped, completed, entered-in-error, unknown - CategoryCode string `json:"category_code" binding:"required"` - CategoryDisplay string `json:"category_display" binding:"required"` - Code string `json:"code" binding:"required"` // SNOMED-CT or ICD9CM code - Display string `json:"display" binding:"required"` // Procedure name - PractitionerID string `json:"practitioner_id" binding:"required"` - PractitionerName string `json:"practitioner_name" binding:"required"` - PerformedDateTime time.Time `json:"performed_date_time" binding:"required"` -} - -type ProcedurePatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/procedure/mapper.go b/internal/satusehat/usecase/procedure/mapper.go deleted file mode 100644 index d6ba491..0000000 --- a/internal/satusehat/usecase/procedure/mapper.go +++ /dev/null @@ -1,49 +0,0 @@ -package procedure - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req ProcedureRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("Procedure"). - Set("status", req.Status). - Set("category", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://snomed.info/sct", - "code": req.CategoryCode, - "display": req.CategoryDisplay, - }, - }, - }). - Set("code", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://snomed.info/sct", - "code": req.Code, - "display": req.Display, - }, - }, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("performedDateTime", req.PerformedDateTime.Format(time.RFC3339)) - - if req.PractitionerID != "" { - payload.Append("performer", map[string]interface{}{ - "actor": map[string]interface{}{ - "reference": "Practitioner/" + req.PractitionerID, - "display": req.PractitionerName, - }, - }) - } - - return payload -} diff --git a/internal/satusehat/usecase/procedure/repository.go b/internal/satusehat/usecase/procedure/repository.go deleted file mode 100644 index 2615d43..0000000 --- a/internal/satusehat/usecase/procedure/repository.go +++ /dev/null @@ -1,72 +0,0 @@ -package procedure - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, payload ProcedurePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - - return &satusehat.FHIRResponse{ - ID: resourceID, - FullResponse: result, - RawResponse: resp, - }, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/Procedure", payload) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Procedure/%s", id) - return r.executeRequest(ctx, "PUT", endpoint, payload) -} - -func (r *repository) Patch(ctx context.Context, id string, payload ProcedurePatchRequest) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Procedure/%s", id) - return r.executeRequest(ctx, "PATCH", endpoint, payload) -} - -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Procedure/%s", id) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/Procedure?%s", queryParams.Encode()) - return r.executeRequest(ctx, "GET", endpoint, nil) -} diff --git a/internal/satusehat/usecase/procedure/service.go b/internal/satusehat/usecase/procedure/service.go deleted file mode 100644 index 8408993..0000000 --- a/internal/satusehat/usecase/procedure/service.go +++ /dev/null @@ -1,61 +0,0 @@ -package procedure - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req ProcedureRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req ProcedureRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req ProcedurePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req ProcedureRequest) (*satusehat.FHIRResponse, error) { - fhirPayload := MapRequestToFHIR(req) - return s.repo.Create(ctx, fhirPayload) -} - -func (s *service) Update(ctx context.Context, id string, req ProcedureRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Procedure ID is required").Build() - } - - fhirPayload := MapRequestToFHIR(req) - fhirPayload.Set("id", id) - - return s.repo.Update(ctx, id, fhirPayload) -} - -func (s *service) Patch(ctx context.Context, id string, req ProcedurePatchRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Procedure ID is required").Build() - } - if len(req) == 0 { - return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build() - } - return s.repo.Patch(ctx, id, req) -} - -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("Procedure ID is required").Build() - } - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/questionnaireresponse/dto.go b/internal/satusehat/usecase/questionnaireresponse/dto.go deleted file mode 100644 index e30b7e7..0000000 --- a/internal/satusehat/usecase/questionnaireresponse/dto.go +++ /dev/null @@ -1,17 +0,0 @@ -package questionnaireresponse - -import "time" - -type QuestionnaireResponseRequest struct { - QuestionnaireURL string `json:"questionnaire_url" binding:"required"` // e.g. "https://fhir.kemkes.go.id/Questionnaire/Q0007" - Status string `json:"status" binding:"required,oneof=in-progress completed amended entered-in-error stopped"` - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - AuthoredDate time.Time `json:"authored_date" binding:"required"` - AuthorID string `json:"author_id" binding:"required"` - AuthorName string `json:"author_name" binding:"required"` - Items []map[string]interface{} `json:"items" binding:"required"` // Raw FHIR formatted items to handle high nesting flexibility -} - -type QuestionnaireResponsePatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/questionnaireresponse/mapper.go b/internal/satusehat/usecase/questionnaireresponse/mapper.go deleted file mode 100644 index 16667ef..0000000 --- a/internal/satusehat/usecase/questionnaireresponse/mapper.go +++ /dev/null @@ -1,28 +0,0 @@ -package questionnaireresponse - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req QuestionnaireResponseRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("QuestionnaireResponse"). - Set("questionnaire", req.QuestionnaireURL). - Set("status", req.Status). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("authored", req.AuthoredDate.Format(time.RFC3339)). - Set("author", map[string]interface{}{ - "reference": "Practitioner/" + req.AuthorID, - "display": req.AuthorName, - }). - Set("item", req.Items) - - return payload -} diff --git a/internal/satusehat/usecase/questionnaireresponse/repository.go b/internal/satusehat/usecase/questionnaireresponse/repository.go deleted file mode 100644 index 4156809..0000000 --- a/internal/satusehat/usecase/questionnaireresponse/repository.go +++ /dev/null @@ -1,58 +0,0 @@ -package questionnaireresponse - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req QuestionnaireResponsePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/QuestionnaireResponse", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/QuestionnaireResponse/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req QuestionnaireResponsePatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/QuestionnaireResponse/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/QuestionnaireResponse/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/QuestionnaireResponse?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/questionnaireresponse/service.go b/internal/satusehat/usecase/questionnaireresponse/service.go deleted file mode 100644 index ecf88be..0000000 --- a/internal/satusehat/usecase/questionnaireresponse/service.go +++ /dev/null @@ -1,46 +0,0 @@ -package questionnaireresponse - -import ( - "context" - "net/url" - - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req QuestionnaireResponseRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req QuestionnaireResponseRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req QuestionnaireResponsePatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req QuestionnaireResponseRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req QuestionnaireResponseRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("QuestionnaireResponse ID is required").Build() - } - payload := MapRequestToFHIR(req) - payload.Set("id", id) - return s.repo.Update(ctx, id, payload) -} -func (s *service) Patch(ctx context.Context, id string, req QuestionnaireResponsePatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/servicerequest/dto.go b/internal/satusehat/usecase/servicerequest/dto.go deleted file mode 100644 index 5d55808..0000000 --- a/internal/satusehat/usecase/servicerequest/dto.go +++ /dev/null @@ -1,18 +0,0 @@ -package servicerequest - -import "time" - -type ServiceRequestRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - EncounterID string `json:"encounter_id" binding:"required"` - RequesterID string `json:"requester_id" binding:"required"` - RequesterName string `json:"requester_name" binding:"required"` - Status string `json:"status" binding:"required,oneof=draft active on-hold revoked completed entered-in-error unknown"` // draft, active, on-hold, revoked, completed, entered-in-error, unknown - Intent string `json:"intent" binding:"required,oneof=proposal plan directive order original-order reflex-order filler-order instance-order option"` // proposal, plan, directive, order, original-order, reflex-order, filler-order, instance-order, option - Code string `json:"code" binding:"required"` - Display string `json:"display" binding:"required"` - AuthoredOn time.Time `json:"authored_on" binding:"required"` -} - -type ServiceRequestPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/servicerequest/mapper.go b/internal/satusehat/usecase/servicerequest/mapper.go deleted file mode 100644 index 5dc48b7..0000000 --- a/internal/satusehat/usecase/servicerequest/mapper.go +++ /dev/null @@ -1,39 +0,0 @@ -package servicerequest - -import ( - "time" - - "service/internal/interfaces/satusehat" -) - -func MapRequestToFHIR(req ServiceRequestRequest) satusehat.FHIRPayload { - payload := satusehat.NewFHIRPayload("ServiceRequest"). - Set("status", req.Status). - Set("intent", req.Intent). - Set("code", map[string]interface{}{ - "coding": []map[string]interface{}{ - { - "system": "http://snomed.info/sct", - "code": req.Code, - "display": req.Display, - }, - }, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("encounter", map[string]interface{}{ - "reference": "Encounter/" + req.EncounterID, - }). - Set("authoredOn", req.AuthoredOn.Format(time.RFC3339)) - - if req.RequesterID != "" { - payload.Set("requester", map[string]interface{}{ - "reference": "Practitioner/" + req.RequesterID, - "display": req.RequesterName, - }) - } - - return payload -} diff --git a/internal/satusehat/usecase/servicerequest/repository.go b/internal/satusehat/usecase/servicerequest/repository.go deleted file mode 100644 index 3ec81e3..0000000 --- a/internal/satusehat/usecase/servicerequest/repository.go +++ /dev/null @@ -1,74 +0,0 @@ -package servicerequest - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -// Repository mendefinisikan kontrak untuk operasi penyimpanan data ServiceRequest. -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, payload ServiceRequestPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type repository struct { - client satusehat.SatuSehatClient -} - -// NewRepository membuat repositori ServiceRequest baru. -func NewRepository(client satusehat.SatuSehatClient) Repository { - return &repository{client: client} -} - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - - return &satusehat.FHIRResponse{ - ID: resourceID, - FullResponse: result, - RawResponse: resp, - }, nil -} - -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/ServiceRequest", payload) -} - -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/ServiceRequest/%s", id) - return r.executeRequest(ctx, "PUT", endpoint, payload) -} - -func (r *repository) Patch(ctx context.Context, id string, payload ServiceRequestPatchRequest) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/ServiceRequest/%s", id) - return r.executeRequest(ctx, "PATCH", endpoint, payload) -} - -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/ServiceRequest/%s", id) - return r.executeRequest(ctx, "GET", endpoint, nil) -} - -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - endpoint := fmt.Sprintf("/ServiceRequest?%s", queryParams.Encode()) - return r.executeRequest(ctx, "GET", endpoint, nil) -} diff --git a/internal/satusehat/usecase/servicerequest/service.go b/internal/satusehat/usecase/servicerequest/service.go deleted file mode 100644 index 9aff9b7..0000000 --- a/internal/satusehat/usecase/servicerequest/service.go +++ /dev/null @@ -1,63 +0,0 @@ -package servicerequest - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -// Service mendefinisikan kontrak untuk logika bisnis ServiceRequest. -type Service interface { - Create(ctx context.Context, req ServiceRequestRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req ServiceRequestRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req ServiceRequestPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} - -type service struct { - repo Repository -} - -// NewService membuat service ServiceRequest baru. -func NewService(repo Repository) Service { - return &service{repo: repo} -} - -func (s *service) Create(ctx context.Context, req ServiceRequestRequest) (*satusehat.FHIRResponse, error) { - fhirPayload := MapRequestToFHIR(req) - return s.repo.Create(ctx, fhirPayload) -} - -func (s *service) Update(ctx context.Context, id string, req ServiceRequestRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ServiceRequest ID is required").Build() - } - - fhirPayload := MapRequestToFHIR(req) - fhirPayload.Set("id", id) - - return s.repo.Update(ctx, id, fhirPayload) -} - -func (s *service) Patch(ctx context.Context, id string, req ServiceRequestPatchRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ServiceRequest ID is required").Build() - } - if len(req) == 0 { - return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build() - } - return s.repo.Patch(ctx, id, req) -} - -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ServiceRequest ID is required").Build() - } - return s.repo.GetByID(ctx, id) -} - -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/internal/satusehat/usecase/specimen/dto.go b/internal/satusehat/usecase/specimen/dto.go deleted file mode 100644 index b4de01f..0000000 --- a/internal/satusehat/usecase/specimen/dto.go +++ /dev/null @@ -1,16 +0,0 @@ -package specimen - -import "time" - -type SpecimenRequest struct { - PatientID string `json:"patient_id" binding:"required"` - PatientName string `json:"patient_name" binding:"required"` - Status string `json:"status" binding:"required,oneof=available unavailable unsatisfactory entered-in-error"` - TypeCode string `json:"type_code" binding:"required"` // SNOMED CT Code (e.g., 119297000 for Blood) - TypeDisplay string `json:"type_display" binding:"required"` - CollectedDateTime time.Time `json:"collected_date_time" binding:"required"` - CollectorID string `json:"collector_id" binding:"required"` - CollectorName string `json:"collector_name" binding:"required"` -} - -type SpecimenPatchRequest []map[string]interface{} diff --git a/internal/satusehat/usecase/specimen/mapper.go b/internal/satusehat/usecase/specimen/mapper.go deleted file mode 100644 index 8907716..0000000 --- a/internal/satusehat/usecase/specimen/mapper.go +++ /dev/null @@ -1,27 +0,0 @@ -package specimen - -import ( - "service/internal/interfaces/satusehat" - "time" -) - -func MapRequestToFHIR(req SpecimenRequest) satusehat.FHIRPayload { - return satusehat.NewFHIRPayload("Specimen"). - Set("status", req.Status). - Set("type", map[string]interface{}{ - "coding": []map[string]interface{}{ - {"system": "http://snomed.info/sct", "code": req.TypeCode, "display": req.TypeDisplay}, - }, - }). - Set("subject", map[string]interface{}{ - "reference": "Patient/" + req.PatientID, - "display": req.PatientName, - }). - Set("collection", map[string]interface{}{ - "collectedDateTime": req.CollectedDateTime.Format(time.RFC3339), - "collector": map[string]interface{}{ - "reference": "Practitioner/" + req.CollectorID, - "display": req.CollectorName, - }, - }) -} diff --git a/internal/satusehat/usecase/specimen/repository.go b/internal/satusehat/usecase/specimen/repository.go deleted file mode 100644 index ef2cb15..0000000 --- a/internal/satusehat/usecase/specimen/repository.go +++ /dev/null @@ -1,51 +0,0 @@ -package specimen - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "service/internal/interfaces/satusehat" -) - -type Repository interface { - Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req SpecimenPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type repository struct{ client satusehat.SatuSehatClient } - -func NewRepository(client satusehat.SatuSehatClient) Repository { return &repository{client: client} } - -func (r *repository) executeRequest(ctx context.Context, method, endpoint string, req interface{}) (*satusehat.FHIRResponse, error) { - resp, err := r.client.DoRequest(ctx, method, endpoint, req) - if err != nil { - return nil, err - } - var result map[string]interface{} - if err := json.Unmarshal(resp, &result); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - var resourceID string - if id, ok := result["id"].(string); ok { - resourceID = id - } - return &satusehat.FHIRResponse{ID: resourceID, FullResponse: result, RawResponse: resp}, nil -} -func (r *repository) Create(ctx context.Context, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "POST", "/Specimen", payload) -} -func (r *repository) Update(ctx context.Context, id string, payload interface{}) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PUT", fmt.Sprintf("/Specimen/%s", id), payload) -} -func (r *repository) Patch(ctx context.Context, id string, req SpecimenPatchRequest) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "PATCH", fmt.Sprintf("/Specimen/%s", id), req) -} -func (r *repository) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/Specimen/%s", id), nil) -} -func (r *repository) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return r.executeRequest(ctx, "GET", fmt.Sprintf("/Specimen?%s", queryParams.Encode()), nil) -} diff --git a/internal/satusehat/usecase/specimen/service.go b/internal/satusehat/usecase/specimen/service.go deleted file mode 100644 index 96fd827..0000000 --- a/internal/satusehat/usecase/specimen/service.go +++ /dev/null @@ -1,37 +0,0 @@ -package specimen - -import ( - "context" - "net/url" - "service/internal/interfaces/satusehat" - "service/pkg/errors" -) - -type Service interface { - Create(ctx context.Context, req SpecimenRequest) (*satusehat.FHIRResponse, error) - Update(ctx context.Context, id string, req SpecimenRequest) (*satusehat.FHIRResponse, error) - Patch(ctx context.Context, id string, req SpecimenPatchRequest) (*satusehat.FHIRResponse, error) - GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) - Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) -} -type service struct{ repo Repository } - -func NewService(repo Repository) Service { return &service{repo: repo} } -func (s *service) Create(ctx context.Context, req SpecimenRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Create(ctx, MapRequestToFHIR(req)) -} -func (s *service) Update(ctx context.Context, id string, req SpecimenRequest) (*satusehat.FHIRResponse, error) { - if id == "" { - return nil, errors.NewValidationError().Message("ID is required").Build() - } - return s.repo.Update(ctx, id, MapRequestToFHIR(req).Set("id", id)) -} -func (s *service) Patch(ctx context.Context, id string, req SpecimenPatchRequest) (*satusehat.FHIRResponse, error) { - return s.repo.Patch(ctx, id, req) -} -func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) { - return s.repo.GetByID(ctx, id) -} -func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) { - return s.repo.Search(ctx, queryParams) -} diff --git a/scripts/grpc.sh b/scripts/grpc.sh index 244d39e..f491e14 100755 --- a/scripts/grpc.sh +++ b/scripts/grpc.sh @@ -1,9 +1,528 @@ #!/bin/bash -echo "⚠️ scripts/grpc.sh is deprecated to avoid code duplication." -echo "To generate gRPC protobuf files, handlers, and mappers dynamically based on the database schema, please use scripts/context.sh instead." -echo "" -echo "Usage example:" -echo " ./scripts/context.sh -s path/to/sql -d your/module/dir -g grpc" -echo " ./scripts/context.sh -s path/to/sql -d your/module/dir -g all" -exit 1 \ No newline at end of file +# gRPC Layer Generator from Existing Context +# Usage: ./scripts/grpc.sh [OPTIONS] +# Options: +# -d, --dir PATH Custom directory structure of the existing context (e.g., master/reference/province) (required) +# -e, --entity-file PATH Optional path to the entity file if not named 'entity.go' +# -v, --verbose Verbose output +# -h, --help Show help + +set -uo pipefail + +# Colors for output +readonly RED='\033[0;31m' +readonly GREEN='\033[0;32m' +readonly YELLOW='\033[1;33m' +readonly BLUE='\033[0;34m' +readonly PURPLE='\033[0;35m' +readonly CYAN='\033[0;36m' +readonly WHITE='\033[1;37m' +readonly NC='\033[0m' # No Color + +# Configuration +readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +readonly PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +readonly INTERNAL_DIR="${PROJECT_ROOT}/internal" + +# Global variables +VERBOSE=false +CUSTOM_DIR="" +ENTITY_FILE_NAME="entity.go" + +# --- Helper Functions --- + +# Logging functions +log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } +log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } +log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1"; } +log_verbose() { [[ "$VERBOSE" == true ]] && echo -e "${CYAN}[VERBOSE]${NC} $1"; } +log_header() { echo -e "\n${PURPLE}==== $1 ====${NC}\n"; } + +# Help function +show_help() { + cat << EOF + ${WHITE}gRPC Layer Generator from Existing Context${NC} + + This script generates the gRPC layer (.proto, handler, mapper) + by parsing an existing Go entity file. + + ${YELLOW}Usage:${NC} + $(basename "$0") -d CONTEXT_DIR [OPTIONS] + + ${YELLOW}Required Options:${NC} + -d, --dir PATH Path to the existing context directory relative to 'internal/' + (e.g., master/reference/province) + + ${YELLOW}Optional Options:${NC} + -e, --entity-file NAME File name of the source entity (default: entity.go) + -v, --verbose Verbose output + -h, --help Show this help message + + ${YELLOW}Example:${NC} + # Generate gRPC layer for an existing 'province' context + $(basename "$0") -d master/reference/province +EOF +} + +# PascalCase from snake_case or kebab-case +to_pascal_case() { + echo "$1" | sed -E 's/(^|[-_.])([a-zA-Z])/\U\2/g' +} + +# snake_case from PascalCase +to_snake_case() { + echo "$1" | sed -E 's/([A-Z])/_\L\1/g' | sed 's/^_//' +} + +# camelCase from snake_case or kebab-case +to_camel_case() { + local pascal + pascal=$(to_pascal_case "$1") + echo "$(echo "${pascal:0:1}" | tr '[:upper:]' '[:lower:]')${pascal:1}" +} + +# Extract package name from custom directory structure +# For path master/reference/province, returns "province" +extract_package_name() { + basename "$1" +} + +# Convert Go type to Protobuf type +go_to_proto_type() { + local go_type="$1" + local is_pointer="${2:-false}" + + local proto_type="string" # Default + case "$go_type" in + "int"|"int32"|"int64") proto_type="int64" ;; + "string") proto_type="string" ;; + "bool") proto_type="bool" ;; + "time.Time") proto_type="google.protobuf.Timestamp" ;; + "float32"|"float64") proto_type="double" ;; + "uuid.UUID") proto_type="string" ;; + esac + + # Use optional for pointer fields (nullable) in proto3 + if [[ "$is_pointer" == "true" ]]; then + echo "optional $proto_type" + else + echo "$proto_type" + fi +} + +# --- Core Logic --- + +# Parse command line arguments +parse_args() { + if [[ "$#" -eq 0 ]]; then + show_help + exit 1 + fi + + while [[ $# -gt 0 ]]; do + case $1 in + -d|--dir) + CUSTOM_DIR="$2" + shift 2 + ;; + -e|--entity-file) + ENTITY_FILE_NAME="$2" + shift 2 + ;; + -v|--verbose) + VERBOSE=true + shift + ;; + -h|--help) + show_help + exit 0 + ;; + *) + log_error "Unknown option: $1" + show_help + exit 1 + ;; + esac + done + + # Validate required arguments + if [[ -z "$CUSTOM_DIR" ]]; then + log_error "Context directory is required. Use -d or --dir." + exit 1 + fi +} + +# Extract struct info from Go entity file +parse_go_context() { + local context_path="$1" + local entity_filename="$2" + local entity_file_path="${INTERNAL_DIR}/${context_path}/${entity_filename}" + + log_info "Parsing Go context from: $entity_file_path" + + if [[ ! -f "$entity_file_path" ]]; then + log_error "Entity file not found: $entity_file_path" + return 1 + fi + + # Extract struct name (e.g., Province) + local struct_name + struct_name=$(grep -m 1 -E "type .* struct" "$entity_file_path" | awk '{print $2}') + if [[ -z "$struct_name" ]]; then + log_error "Could not find a struct definition in $entity_file_path" + return 1 + fi + log_verbose "Found struct: $struct_name" + + # Reset arrays + PARSED_FIELDS=() + PARSED_PRIMARY_KEY_GO_NAME="" + PARSED_PRIMARY_KEY_GO_TYPE="" + + # Use awk to isolate the struct definition block + local fields_block + fields_block=$(awk -v struct_name="$struct_name" '$0 ~ "type " struct_name " struct \\{" {p=1; next} p && /}/ {p=0} p' "$entity_file_path") + + while IFS= read -r line; do + # Trim leading/trailing whitespace + local trimmed_line + trimmed_line=$(echo "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') + + # Skip empty, comment, or closing brace lines + if [[ -z "$trimmed_line" || "$trimmed_line" =~ ^// || "$trimmed_line" == "}" ]]; then + continue + fi + + local go_field_name go_type is_pointer db_name + go_field_name=$(echo "$trimmed_line" | awk '{print $1}') + go_type=$(echo "$trimmed_line" | awk '{print $2}') + is_pointer="false" + + if [[ "$go_type" == "*"* ]]; then + is_pointer="true" + go_type=${go_type#\*} # Remove the leading '*' + fi + + # Extract db tag for snake_case name, fallback to json tag, then to converting field name + db_name=$(echo "$trimmed_line" | grep -o 'db:"[^"]*"' | cut -d'"' -f2) + if [[ -z "$db_name" ]]; then + db_name=$(echo "$trimmed_line" | grep -o 'json:"[^"]*"' | cut -d'"' -f2) + fi + if [[ -z "$db_name" ]]; then + db_name=$(to_snake_case "$go_field_name") + fi + + PARSED_FIELDS+=("${go_field_name}|${go_type}|${is_pointer}|${db_name}") + log_verbose "Found field: $go_field_name ($go_type, pointer: $is_pointer, db_name: $db_name)" + + # Heuristic to find the Primary Key + if [[ -z "$PARSED_PRIMARY_KEY_GO_NAME" && ("$go_field_name" == "Id" || "$db_name" == "id") ]]; then + PARSED_PRIMARY_KEY_GO_NAME="$go_field_name" + PARSED_PRIMARY_KEY_GO_TYPE="$go_type" + fi + + done <<< "$fields_block" + + # If no PK found by heuristic, assume the first field is the PK + if [[ -z "$PARSED_PRIMARY_KEY_GO_NAME" && ${#PARSED_FIELDS[@]} -gt 0 ]]; then + IFS='|' read -r go_field_name go_type _ _ <<< "${PARSED_FIELDS[0]}" + PARSED_PRIMARY_KEY_GO_NAME="$go_field_name" + PARSED_PRIMARY_KEY_GO_TYPE="$go_type" + log_warning "Could not determine primary key, assuming first field '${go_field_name}' is the PK." + fi + + # Store in global variables for later use + export CLEAN_NAME="$struct_name" + export GO_PK_NAME="$PARSED_PRIMARY_KEY_GO_NAME" + export GO_PK_TYPE="$PARSED_PRIMARY_KEY_GO_TYPE" + export PROTO_PK_TYPE=$(go_to_proto_type "$PARSED_PRIMARY_KEY_GO_TYPE" "false") + + log_success "Successfully parsed context for: $struct_name" +} + +# Generate gRPC proto file +generate_proto_file() { + local package_name + package_name=$(extract_package_name "$CUSTOM_DIR") + + local proto_dir="${INTERNAL_DIR}/infrastructure/transport/grpc/proto/${CUSTOM_DIR}/v1" + log_info "Generating proto file in: $proto_dir" + mkdir -p "$proto_dir" + + local proto_file="${proto_dir}/${package_name}.proto" + + if [ -f "$proto_file" ]; then + log_warning "File already exists, skipping: $proto_file" + return + fi + + log_info "Generating file: $proto_file" + cat > "$proto_file" << EOF +syntax = "proto3"; + +package ${package_name}.v1; + +option go_package = "service/internal/infrastructure/transport/grpc/gen/${CUSTOM_DIR}/v1;${package_name}v1"; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/empty.proto"; + +// Service definition for ${CLEAN_NAME}. +service ${CLEAN_NAME}Service { + rpc Get${CLEAN_NAME}(Get${CLEAN_NAME}Request) returns (${CLEAN_NAME}Response); + rpc List${CLEAN_NAME}s(List${CLEAN_NAME}sRequest) returns (List${CLEAN_NAME}sResponse); + rpc Create${CLEAN_NAME}(Create${CLEAN_NAME}Request) returns (${CLEAN_NAME}Response); + rpc Update${CLEAN_NAME}(Update${CLEAN_NAME}Request) returns (${CLEAN_NAME}Response); + rpc Delete${CLEAN_NAME}(Delete${CLEAN_NAME}Request) returns (google.protobuf.Empty); +} + +// The main message representing a ${CLEAN_NAME}. +message ${CLEAN_NAME} { +EOF + + local field_index=1 + for field in "${PARSED_FIELDS[@]}"; do + IFS='|' read -r go_field_name go_type is_pointer db_name <<< "$field" + local proto_field_name="$db_name" + local proto_type + proto_type=$(go_to_proto_type "$go_type" "$is_pointer") + + echo " ${proto_type} ${proto_field_name} = ${field_index};" >> "$proto_file" + ((field_index++)) + done + + cat >> "$proto_file" << EOF +} + +// --- Request/Response Messages --- + +message Get${CLEAN_NAME}Request { + ${PROTO_PK_TYPE} id = 1; +} + +message ${CLEAN_NAME}Response { + ${CLEAN_NAME} data = 1; +} + +message List${CLEAN_NAME}sRequest { + int32 page = 1; + int32 page_size = 2; + // TODO: Add filter fields here if needed +} + +message List${CLEAN_NAME}sResponse { + repeated ${CLEAN_NAME} data = 1; + int64 total = 2; +} + +message Create${CLEAN_NAME}Request { +EOF + + local create_field_index=1 + for field in "${PARSED_FIELDS[@]}"; do + IFS='|' read -r go_field_name go_type is_pointer db_name <<< "$field" + # Skip PK, created_at, updated_at, deleted_at for create requests + if [[ "$db_name" == "id" || "$db_name" == "created_at" || "$db_name" == "updated_at" || "$db_name" == "deleted_at" ]]; then + continue + fi + local proto_field_name="$db_name" + local proto_type + proto_type=$(go_to_proto_type "$go_type" "false") # All fields are required for create + + echo " ${proto_type} ${proto_field_name} = ${create_field_index};" >> "$proto_file" + ((create_field_index++)) + done + + cat >> "$proto_file" << EOF +} + +message Update${CLEAN_NAME}Request { + ${PROTO_PK_TYPE} id = 1; +EOF + + local update_field_index=2 + for field in "${PARSED_FIELDS[@]}"; do + IFS='|' read -r go_field_name go_type is_pointer db_name <<< "$field" + if [[ "$db_name" == "id" || "$db_name" == "created_at" || "$db_name" == "updated_at" || "$db_name" == "deleted_at" ]]; then + continue + fi + local proto_field_name="$db_name" + # For update, all fields are optional + local proto_type + proto_type=$(go_to_proto_type "$go_type" "true") + + echo " ${proto_type} ${proto_field_name} = ${update_field_index};" >> "$proto_file" + ((update_field_index++)) + done + + cat >> "$proto_file" << EOF +} + +message Delete${CLEAN_NAME}Request { + ${PROTO_PK_TYPE} id = 1; +} +EOF + + log_success "Generated proto file: ${package_name}.proto" + + log_info "Running proto compiler to generate Go code from this new .proto file..." + # Assuming you have a script to compile protos, or you can do it directly. + # This is an example command. + if command -v protoc &> /dev/null; then + protoc --go_out=. --go_opt=paths=source_relative \ + --go-grpc_out=. --go-grpc_opt=paths=source_relative \ + "${proto_dir}/${package_name}.proto" + log_success "protoc compilation successful." + else + log_warning "protoc command not found. Please compile the .proto file manually." + fi +} + +# Generate gRPC handler and mapper file +generate_grpc_handler() { + local package_name + package_name=$(extract_package_name "$CUSTOM_DIR") + + local target_dir="${INTERNAL_DIR}/infrastructure/transport/grpc/handlers/${CUSTOM_DIR}" + log_info "Generating gRPC handler and mapper in: $target_dir" + mkdir -p "$target_dir" + + local handler_file_name="${target_dir}/${package_name}_grpc_handler.go" + local mapper_file_name="${target_dir}/${package_name}_grpc_mapper.go" + + if [ -f "$handler_file_name" ]; then + log_warning "File already exists, skipping: $handler_file_name" + else + log_info "Generating file: $handler_file_name" + cat > "$handler_file_name" << EOF +package handlers + +import ( + "context" + + "service/internal/infrastructure/transport/grpc/gen/${CUSTOM_DIR}/v1" + ${package_name}Service "service/internal/${CUSTOM_DIR}" + "service/pkg/errors" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/emptypb" +) + +type ${CLEAN_NAME}GrpcHandler struct { + ${package_name}v1.Unimplemented${CLEAN_NAME}ServiceServer + service ${package_name}Service.Service +} + +func New${CLEAN_NAME}GrpcHandler(service ${package_name}Service.Service) *${CLEAN_NAME}GrpcHandler { + return &${CLEAN_NAME}GrpcHandler{service: service} +} + +func (h *${CLEAN_NAME}GrpcHandler) Get${CLEAN_NAME}(ctx context.Context, req *${package_name}v1.Get${CLEAN_NAME}Request) (*${package_name}v1.${CLEAN_NAME}Response, error) { + res, err := h.service.GetDetail(ctx, req.GetId()) + if err != nil { + appErr := errors.FromError(err) + return nil, status.Error(appErr.GRPCStatus(), appErr.Error()) + } + return &${package_name}v1.${CLEAN_NAME}Response{Data: mapResponseToProto(res)}, nil +} + +// Add other handler methods (List, Create, Update, Delete) here... + +EOF + log_success "Generated gRPC handler file: ${package_name}_grpc_handler.go" + fi + + if [ -f "$mapper_file_name" ]; then + log_warning "File already exists, skipping: $mapper_file_name" + else + log_info "Generating file: $mapper_file_name" + cat > "$mapper_file_name" << EOF +package handlers + +import ( + "service/internal/infrastructure/transport/grpc/gen/${CUSTOM_DIR}/v1" + ${package_name}Service "service/internal/${CUSTOM_DIR}" + "google.golang.org/protobuf/types/known/timestamppb" +) + +// mapResponseToProto converts the service DTO to a Protobuf message. +func mapResponseToProto(dto *${package_name}Service.${CLEAN_NAME}Response) *${package_name}v1.${CLEAN_NAME} { + if dto == nil { + return nil + } + return &${package_name}v1.${CLEAN_NAME}{ +EOF + for field in "${PARSED_FIELDS[@]}"; do + IFS='|' read -r go_field_name go_type is_pointer db_name <<< "$field" + local proto_field_name="$db_name" + local go_pascal_field + go_pascal_field=$(to_pascal_case "$go_field_name") + + # Handle time.Time and *time.Time specifically + if [[ "$go_type" == "time.Time" ]]; then + if [[ "$is_pointer" == "true" ]]; then + echo " ${proto_field_name}: timestamppb.New(*dto.${go_pascal_field})," >> "$mapper_file_name" + else + echo " ${proto_field_name}: timestamppb.New(dto.${go_pascal_field})," >> "$mapper_file_name" + fi + else + echo " ${proto_field_name}: dto.${go_pascal_field}," >> "$mapper_file_name" + fi + done + cat >> "$mapper_file_name" << EOF + } +} + +// Add other mappers (e.g., mapCreateProtoToRequest) here... +EOF + log_success "Generated gRPC mapper file: ${package_name}_grpc_mapper.go" + fi +} + +# --- Main Execution --- + +main() { + log_header "gRPC Layer Generator" + parse_args "$@" + + if ! parse_go_context "$CUSTOM_DIR" "$ENTITY_FILE_NAME"; then + exit 1 + fi + + generate_proto_file + generate_grpc_handler + + local package_name + package_name=$(extract_package_name "$CUSTOM_DIR") + + echo -e "\n${PURPLE}================================================================${NC}" + echo -e "${GREEN}✨ gRPC LAYER FOR [${CLEAN_NAME}] GENERATED SUCCESSFULLY! ✨${NC}" + echo -e "${PURPLE}================================================================${NC}\n" + + echo -e "${YELLOW}🚀 NEXT STEPS TO ACTIVATE YOUR gRPC MODULE:${NC}\n" + + echo -e "${CYAN}1. Review Generated Files:${NC}" + echo -e " - ${WHITE}internal/infrastructure/transport/grpc/proto/${CUSTOM_DIR}/v1/${package_name}.proto${NC}" + echo -e " - ${WHITE}internal/infrastructure/transport/grpc/handlers/${CUSTOM_DIR}/${package_name}_grpc_handler.go${NC}" + echo -e " - ${WHITE}internal/infrastructure/transport/grpc/handlers/${CUSTOM_DIR}/${package_name}_grpc_mapper.go${NC}" + echo -e " Lengkapi implementasi untuk method List, Create, Update, Delete di handler dan mapper.\n" + + echo -e "${CYAN}2. Registrasi gRPC Handler (misal di cmd/grpc/server.go):${NC}" + echo -e " Import packages:" + echo -e " ${WHITE}gen${CLEAN_NAME} \"service/internal/infrastructure/transport/grpc/gen/${CUSTOM_DIR}/v1\"${NC}" + echo -e " ${WHITE}grpc${CLEAN_NAME}Handler \"service/internal/infrastructure/transport/grpc/handlers/${CUSTOM_DIR}\"${NC}\n" + echo -e " Inisialisasi dan registrasi handler:" + echo -e " ${WHITE}// (Asumsikan ${package_name}Svc sudah diinisialisasi)${NC}" + echo -e " ${WHITE}${package_name}GrpcHandler := grpc${CLEAN_NAME}Handler.New${CLEAN_NAME}GrpcHandler(${package_name}Svc)${NC}" + echo -e " ${WHITE}gen${CLEAN_NAME}.Register${CLEAN_NAME}ServiceServer(grpcServer, ${package_name}GrpcHandler)${NC}\n" + + echo -e "${CYAN}3. Rapihkan Dependencies:${NC}" + echo -e " ${WHITE}go mod tidy${NC}\n" +} + +# Run main function with all arguments +main "$@" + +