316 lines
11 KiB
Go
316 lines
11 KiB
Go
package http
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"primaya-api/cpone-middleware/internal/repository"
|
|
)
|
|
|
|
type fakeLabRegistrationRepository struct {
|
|
outcome repository.LabRegistrationOutcome
|
|
err error
|
|
params repository.LabRegistrationParams
|
|
addParams repository.AddLabServicesParams
|
|
packageParams repository.AddLabPackageParams
|
|
regID string
|
|
}
|
|
|
|
func (f *fakeLabRegistrationRepository) RegisterLab(_ context.Context, params repository.LabRegistrationParams) (repository.LabRegistrationOutcome, error) {
|
|
f.params = params
|
|
return f.outcome, f.err
|
|
}
|
|
|
|
func (f *fakeLabRegistrationRepository) AddLabServices(_ context.Context, regID string, params repository.AddLabServicesParams) (repository.LabRegistrationOutcome, error) {
|
|
f.regID = regID
|
|
f.addParams = params
|
|
return f.outcome, f.err
|
|
}
|
|
|
|
func (f *fakeLabRegistrationRepository) AddLabPackage(_ context.Context, regID string, params repository.AddLabPackageParams) (repository.LabRegistrationOutcome, error) {
|
|
f.regID = regID
|
|
f.packageParams = params
|
|
return f.outcome, f.err
|
|
}
|
|
|
|
func TestRegisterLabValidPayloadAndResponseParity(t *testing.T) {
|
|
doctorID := "DR01"
|
|
registrationType := int64(3)
|
|
repo := &fakeLabRegistrationRepository{outcome: repository.LabRegistrationOutcome{
|
|
HTTPStatus: http.StatusCreated,
|
|
Success: true,
|
|
Status: "registered",
|
|
Message: "Registrasi laboratorium berhasil disimpan",
|
|
Data: &repository.LabRegistrationData{
|
|
Registration: repository.LabRegistration{
|
|
RegID: "CPLAB2608180001",
|
|
MEDRECID: "00001234",
|
|
Tanggal: "2026-08-18 10:11:12",
|
|
DepartemenID: "LAB",
|
|
DokterID: &doctorID,
|
|
JenisPasienID: 0,
|
|
JenisRegID: ®istrationType,
|
|
PeriodeTarifID: 10,
|
|
},
|
|
Transaction: &repository.LabTransaction{
|
|
TrxDepartemenID: 99,
|
|
TrxID: "CPLAB2608180001",
|
|
GrandTotal: 0,
|
|
},
|
|
Layanan: []repository.LabService{},
|
|
},
|
|
}}
|
|
handler := Handler{labRepo: repo}
|
|
body := `{
|
|
"medrec_id":"00001234",
|
|
"tanggal":"2026-08-18",
|
|
"departemen_id":"LAB",
|
|
"dokter_id":"DR01",
|
|
"perujuk":" Klinik A ",
|
|
"jenis_pasien_id":"0",
|
|
"periode_tarif_id":"10",
|
|
"kelas_id":"",
|
|
"diagnosa_kerja":"Pemeriksaan laboratorium",
|
|
"catatan":" catatan ",
|
|
"channel":" cpone-api "
|
|
}`
|
|
|
|
request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/lab-registration", strings.NewReader(body))
|
|
recorder := httptest.NewRecorder()
|
|
handler.RegisterLab(recorder, request)
|
|
|
|
if recorder.Code != http.StatusCreated {
|
|
t.Fatalf("status = %d, want %d; body=%s", recorder.Code, http.StatusCreated, recorder.Body.String())
|
|
}
|
|
const expected = `{"success":true,"status":"registered","message":"Registrasi laboratorium berhasil disimpan","data":{"registration":{"RegID":"CPLAB2608180001","MEDRECID":"00001234","Tanggal":"2026-08-18 10:11:12","DepartemenID":"LAB","DokterID":"DR01","JenisPasienID":0,"JenisRegID":3,"PeriodeTarifID":10,"PerusahaanID":null,"AsuransiID":null,"ProviderID":null,"GroupTarifID":null,"NomerPolis":null},"transaction":{"TrxDepartemenID":99,"TrxID":"CPLAB2608180001","GrandTotal":0},"layanan":[]}}` + "\n"
|
|
if recorder.Body.String() != expected {
|
|
t.Fatalf("body mismatch\n got: %s\nwant: %s", recorder.Body.String(), expected)
|
|
}
|
|
|
|
if repo.params.MedrecID != "00001234" || repo.params.DepartmentID != "LAB" || repo.params.DoctorID != "DR01" {
|
|
t.Fatalf("unexpected repository params: %+v", repo.params)
|
|
}
|
|
if repo.params.TariffPeriodID != 10 || repo.params.ClassID != "Default" || repo.params.Channel != "CPONE-API" {
|
|
t.Fatalf("normalization mismatch: %+v", repo.params)
|
|
}
|
|
if repo.params.Referrer != " Klinik A " || repo.params.Notes != " catatan " {
|
|
t.Fatalf("handler must preserve values for repository trimming: %+v", repo.params)
|
|
}
|
|
}
|
|
|
|
func TestRegisterLabUsesConfiguredDepartmentID(t *testing.T) {
|
|
repo := &fakeLabRegistrationRepository{outcome: repository.LabRegistrationOutcome{
|
|
HTTPStatus: http.StatusCreated,
|
|
Success: true,
|
|
Status: "registered",
|
|
Message: "Registrasi laboratorium berhasil disimpan",
|
|
}}
|
|
handler := Handler{labRepo: repo, departmentID: "MED-PNJ-LAB"}
|
|
body := `{
|
|
"medrec_id":"00001234",
|
|
"departemen_id":"DIABAIKAN",
|
|
"dokter_id":"DR01",
|
|
"dokter_pengirim_id":"DR02",
|
|
"jenis_pasien_id":"0",
|
|
"periode_tarif_id":10,
|
|
"diagnosa_kerja":"Pemeriksaan laboratorium"
|
|
}`
|
|
|
|
request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/lab-registration", strings.NewReader(body))
|
|
recorder := httptest.NewRecorder()
|
|
handler.RegisterLab(recorder, request)
|
|
|
|
if recorder.Code != http.StatusCreated {
|
|
t.Fatalf("status = %d; body=%s", recorder.Code, recorder.Body.String())
|
|
}
|
|
if repo.params.DepartmentID != "MED-PNJ-LAB" {
|
|
t.Fatalf("department ID = %q, want %q", repo.params.DepartmentID, "MED-PNJ-LAB")
|
|
}
|
|
}
|
|
|
|
func TestRegisterLabCompanyPayload(t *testing.T) {
|
|
repo := &fakeLabRegistrationRepository{outcome: repository.LabRegistrationOutcome{
|
|
HTTPStatus: http.StatusCreated,
|
|
Success: true,
|
|
Status: "registered",
|
|
Message: "Registrasi laboratorium berhasil disimpan",
|
|
}}
|
|
handler := Handler{labRepo: repo}
|
|
body := `{
|
|
"medrec_id":"00409575",
|
|
"departemen_id":"MED-PNJ-LAB",
|
|
"dokter_id":"SPP01_003",
|
|
"dokter_pengirim_id":"Luar",
|
|
"perujuk":"DOKTER PERUJUK LUAR",
|
|
"jenis_pasien_id":"1",
|
|
"periode_tarif_id":7,
|
|
"perusahaan_id":"PE260700001",
|
|
"asuransi_id":"PE260700001",
|
|
"provider_id":"",
|
|
"group_tarif_id":1980,
|
|
"nomer_polis":"POLIS-001",
|
|
"nik_karyawan":"TSB2026002",
|
|
"nama_karyawan":"INTAN SEPTIANI",
|
|
"kelas_id":"Default",
|
|
"shift_harian_id":48049,
|
|
"diagnosa_kerja":"Test diagnosa"
|
|
}`
|
|
|
|
request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/lab-registration", strings.NewReader(body))
|
|
recorder := httptest.NewRecorder()
|
|
handler.RegisterLab(recorder, request)
|
|
|
|
if recorder.Code != http.StatusCreated {
|
|
t.Fatalf("status = %d, want %d; body=%s", recorder.Code, http.StatusCreated, recorder.Body.String())
|
|
}
|
|
params := repo.params
|
|
if params.PatientType != "1" || params.CompanyID != "PE260700001" || params.InsuranceID != "PE260700001" || params.GroupTariffID != 1980 {
|
|
t.Fatalf("company guarantor params mismatch: %+v", params)
|
|
}
|
|
if params.PolicyNumber != "POLIS-001" || params.EmployeeID != "TSB2026002" || params.EmployeeName != "INTAN SEPTIANI" {
|
|
t.Fatalf("company employee params mismatch: %+v", params)
|
|
}
|
|
}
|
|
|
|
func TestRegisterLabValidationParity(t *testing.T) {
|
|
baseline := map[string]any{
|
|
"medrec_id": "00001234",
|
|
"departemen_id": "LAB",
|
|
"dokter_id": "DR01",
|
|
"dokter_pengirim_id": "DR02",
|
|
"jenis_pasien_id": "0",
|
|
"periode_tarif_id": 10,
|
|
"diagnosa_kerja": "Pemeriksaan laboratorium",
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
mutate func(map[string]any)
|
|
message string
|
|
}{
|
|
{
|
|
name: "missing medrec",
|
|
mutate: func(payload map[string]any) { delete(payload, "medrec_id") },
|
|
message: "Medrec ID wajib diisi",
|
|
},
|
|
{
|
|
name: "invalid date",
|
|
mutate: func(payload map[string]any) { payload["tanggal"] = "18-08-2026" },
|
|
message: "Tanggal registrasi harus format Y-m-d",
|
|
},
|
|
{
|
|
name: "missing sender and referrer",
|
|
mutate: func(payload map[string]any) {
|
|
delete(payload, "dokter_pengirim_id")
|
|
delete(payload, "perujuk")
|
|
},
|
|
message: "Dokter pengirim atau perujuk wajib diisi",
|
|
},
|
|
{
|
|
name: "missing company for guarantor",
|
|
mutate: func(payload map[string]any) { payload["jenis_pasien_id"] = "1" },
|
|
message: "Perusahaan wajib diisi untuk pasien penjamin",
|
|
},
|
|
{
|
|
name: "missing patient type",
|
|
mutate: func(payload map[string]any) { delete(payload, "jenis_pasien_id") },
|
|
message: "Jenis pasien wajib diisi",
|
|
},
|
|
{
|
|
name: "invalid tariff period type",
|
|
mutate: func(payload map[string]any) { payload["periode_tarif_id"] = "1.5" },
|
|
message: "The periode tarif id must be an integer.",
|
|
},
|
|
{
|
|
name: "short diagnosis",
|
|
mutate: func(payload map[string]any) { payload["diagnosa_kerja"] = "AB" },
|
|
message: "Diagnosa kerja minimal 3 karakter",
|
|
},
|
|
{
|
|
name: "repeated diagnosis",
|
|
mutate: func(payload map[string]any) { payload["diagnosa_kerja"] = "---" },
|
|
message: "Diagnosa kerja tidak valid",
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
payload := make(map[string]any, len(baseline))
|
|
for key, value := range baseline {
|
|
payload[key] = value
|
|
}
|
|
test.mutate(payload)
|
|
body, err := json.Marshal(payload)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
handler := Handler{labRepo: &fakeLabRegistrationRepository{}}
|
|
request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/lab-registration", strings.NewReader(string(body)))
|
|
recorder := httptest.NewRecorder()
|
|
handler.RegisterLab(recorder, request)
|
|
|
|
if recorder.Code != http.StatusUnprocessableEntity {
|
|
t.Fatalf("status = %d; body=%s", recorder.Code, recorder.Body.String())
|
|
}
|
|
expected := `{"success":false,"status":"validation_error","message":` + strconvQuote(test.message) + `,"data":null}` + "\n"
|
|
if recorder.Body.String() != expected {
|
|
t.Fatalf("body mismatch\n got: %s\nwant: %s", recorder.Body.String(), expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRegisterLabRepositoryErrorsMatchLaravelEnvelope(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
err error
|
|
statusCode int
|
|
status string
|
|
message string
|
|
}{
|
|
{
|
|
name: "domain validation",
|
|
err: repository.ValidationError{Message: "Departemen tujuan bukan departemen laboratorium aktif"},
|
|
statusCode: http.StatusUnprocessableEntity,
|
|
status: "validation_error",
|
|
message: "Departemen tujuan bukan departemen laboratorium aktif",
|
|
},
|
|
{
|
|
name: "database error",
|
|
err: errors.New("database unavailable"),
|
|
statusCode: http.StatusInternalServerError,
|
|
status: "error",
|
|
message: "database unavailable",
|
|
},
|
|
}
|
|
|
|
const validBody = `{"medrec_id":"00001234","departemen_id":"LAB","dokter_id":"DR01","dokter_pengirim_id":"DR02","jenis_pasien_id":"0","periode_tarif_id":10,"diagnosa_kerja":"Pemeriksaan laboratorium"}`
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
handler := Handler{labRepo: &fakeLabRegistrationRepository{err: test.err}}
|
|
request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/lab-registration", strings.NewReader(validBody))
|
|
recorder := httptest.NewRecorder()
|
|
handler.RegisterLab(recorder, request)
|
|
|
|
if recorder.Code != test.statusCode {
|
|
t.Fatalf("status = %d; body=%s", recorder.Code, recorder.Body.String())
|
|
}
|
|
expected := `{"success":false,"status":` + strconvQuote(test.status) + `,"message":` + strconvQuote(test.message) + `,"data":null}` + "\n"
|
|
if recorder.Body.String() != expected {
|
|
t.Fatalf("body mismatch\n got: %s\nwant: %s", recorder.Body.String(), expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func strconvQuote(value string) string {
|
|
encoded, _ := json.Marshal(value)
|
|
return string(encoded)
|
|
}
|