package integration import ( "encoding/json" "errors" "net/http" "os" "satusehat-rssa/internal/constant" "satusehat-rssa/internal/model" "satusehat-rssa/pkg/httputil" "strconv" ) type MedicineIntegrationInterface interface { GetMedicineKfa(req model.MedicineKfaRequest) ([]model.MedicineKfaResponse, error) MedicationCreate(req model.MedicationRequest) (map[string]interface{}, error) GetMedicineByKfaCode(kfaCode string) (map[string]interface{}, error) } type MedicineKfaRepository struct { akses *model.Akses } // GetMedicineByKfaCode implements MedicineIntegrationInterface. func (m *MedicineKfaRepository) GetMedicineByKfaCode(kfaCode string) (map[string]interface{}, error) { var data map[string]interface{} url := m.akses.KfaUrl + "/products" method := "GET" client := &http.Client{} request, err := http.NewRequest(method, url, nil) // Assuming the access token is stored in a field of the akses struct oauth := model.OauthRequest{ ClientId: m.akses.ClientId, ClientSecret: m.akses.ClientSecret, } OauthInterface := NewOauthRequestRepo(m.akses) token, err := OauthInterface.GenerateToken(oauth) if err != nil { return nil, err } if token != nil { request.Header.Add("Authorization", "Bearer "+token.AccessToken) } else { return nil, errors.New(constant.ErrGenerateToken) } request.Header.Set("Content-Type", "application/json") q := request.URL.Query() q.Add("code", kfaCode) q.Add("identifier", "kfa") request.URL.RawQuery = q.Encode() res, err := client.Do(request) if err != nil { return nil, err } defer res.Body.Close() if err := json.NewDecoder(res.Body).Decode(&data); err != nil { return nil, err } return data, nil } // MedicationCreate implements MedicineIntegrationInterface. func (m *MedicineKfaRepository) MedicationCreate(req model.MedicationRequest) (map[string]interface{}, error) { req.ResourceType = "Medication" req.Meta = model.Meta{ Profile: []string{constant.FHIRMedicationProfile}, } req.Identifier = []model.Identifier{ { System: "http://sys-ids.kemkes.go.id/medication/" + os.Getenv("ORGANIZATION_ID"), Value: os.Getenv("ORGANIZATION_ID"), Use: "official", }, } req.Manufacturer = model.Reference{ Reference: "Organization/" + os.Getenv("ORGANIZATION_ID"), } req.Extension = []model.ExtensionMedication{ { URL: "https://fhir.kemkes.go.id/r4/StructureDefinition/MedicationType", ValueCodeableConcept: model.CodeableConcept{ Coding: []model.Coding{ { System: "http://terminology.kemkes.go.id/CodeSystem/medication-type", Code: "NC", Display: "Non-compound", }, }, }, }, } url := m.akses.BaseUrl + "/Medication" oauth := model.OauthRequest{ ClientId: m.akses.ClientId, ClientSecret: m.akses.ClientSecret, } OauthInterface := NewOauthRequestRepo(m.akses) token, err := OauthInterface.GenerateToken(oauth) if err != nil { return nil, err } data, err := httputil.DoRequest(httputil.RequestOption{ Method: "POST", URL: url, Body: req, BearerToken: token.AccessToken, Headers: httputil.DefaultFHIRHeaders(), }) if err != nil { return nil, err } return data, nil } // GetMedicineKfa implements MedicineIntegrationInterface. func (m *MedicineKfaRepository) GetMedicineKfa(req model.MedicineKfaRequest) ([]model.MedicineKfaResponse, error) { var ( data map[string]interface{} ) url := m.akses.KfaUrl + "/products/all" method := "GET" client := &http.Client{} request, err := http.NewRequest(method, url, nil) // Assuming the access token is stored in a field of the akses struct oauth := model.OauthRequest{ ClientId: m.akses.ClientId, ClientSecret: m.akses.ClientSecret, } OauthInterface := NewOauthRequestRepo(m.akses) token, err := OauthInterface.GenerateToken(oauth) if err != nil { return nil, err } if token != nil { request.Header.Add("Authorization", "Bearer "+token.AccessToken) } else { return nil, errors.New(constant.ErrGenerateToken) } request.Header.Set("Content-Type", "application/json") q := request.URL.Query() q.Add("page", strconv.Itoa(req.Page)) q.Add("size", strconv.Itoa(req.Size)) q.Add("product_type", req.ProdustType) q.Add("keyword", req.Keyword) request.URL.RawQuery = q.Encode() res, err := client.Do(request) if err != nil { return nil, err } defer res.Body.Close() if res.StatusCode != http.StatusOK { return nil, errors.New("failed to fetch data: " + res.Status) } var response []model.MedicineKfaResponse if err := json.NewDecoder(res.Body).Decode(&data); err != nil { return nil, err } if items, ok := data["items"].(map[string]interface{}); ok { for _, item := range items { if itemMap, ok := item.([]interface{}); ok { for _, med := range itemMap { if medMap, ok := med.(map[string]interface{}); ok { medicine := model.MedicineKfaResponse{ Name: medMap["name"].(string), KfaCode: medMap["kfa_code"].(string), } response = append(response, medicine) } else { return nil, errors.New("invalid item format") } } } } } else { return nil, errors.New("invalid response format") } return response, nil } func NewMedicineKfaRepo(akses *model.Akses) MedicineIntegrationInterface { return &MedicineKfaRepository{ akses: akses, } }