package http import ( "net/http" "net/http/httptest" "strings" "testing" "primaya-api/cpone-middleware/internal/repository" ) const validCreatePaketJSON = `{ "nama":"PAKET MCU CPONE TES 2", "jenis_paket":"MCU", "rawat_inap":false, "rawat_jalan":true, "multi_visit":false, "tanggal_mulai":"2026-09-01", "tanggal_selesai":"2026-09-30", "kelas_id":"Default", "layanan":[{ "layanan_id":"1200", "departemen_id":"MED-PNJ-LAB", "jumlah":1, "jumlah_hari":1, "harga":"130000.00", "tipe_diskon":"Percentage", "diskon":"0.00", "tipe_share":"Absolute", "share_rs":"65000.00", "share_dokter":"0.00", "share_external":"65000.00", "share_lain":"0.00" }] }` func TestCreatePaketResponseAndDecimalParsing(t *testing.T) { repo := &fakePaketRepository{create: repository.CreatePaketResult{ PaketID: "DISP-260900022", Nama: "PAKET MCU CPONE TES 2", TotalHarga: "130000.00", TotalDiskon: "0.00", JumlahLayanan: 1, }} handler := Handler{paketRepo: repo} request := httptest.NewRequest(http.MethodPost, "/api/cpone/paket", strings.NewReader(validCreatePaketJSON)) recorder := httptest.NewRecorder() handler.CreatePaket(recorder, request) if recorder.Code != http.StatusCreated { t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String()) } if len(repo.createParams.Layanan) != 1 || repo.createParams.Layanan[0].HargaCents != 13000000 || repo.createParams.Layanan[0].ShareExternalCents != 6500000 { t.Fatalf("unexpected parsed params: %+v", repo.createParams) } const expected = `{"success":true,"status":"created","message":"Paket berhasil dibuat","data":{"paket_id":"DISP-260900022","nama":"PAKET MCU CPONE TES 2","total_harga":"130000.00","total_diskon":"0.00","jumlah_layanan":1}}` + "\n" if recorder.Body.String() != expected { t.Fatalf("body mismatch\n got: %s\nwant: %s", recorder.Body.String(), expected) } } func TestCreatePaketValidation(t *testing.T) { tests := []struct { name string mutate func(map[string]any) message string valid bool }{ { name: "requires care type", mutate: func(payload map[string]any) { payload["rawat_jalan"] = false }, message: "Rawat inap atau rawat jalan minimal salah satu harus aktif", }, { name: "rejects percentage discount above 100", mutate: func(payload map[string]any) { service := payload["layanan"].([]any)[0].(map[string]any) service["diskon"] = "100.01" }, message: "The layanan.0 diskon percentage tidak boleh lebih dari 100.", }, { name: "rejects absolute share mismatch", mutate: func(payload map[string]any) { service := payload["layanan"].([]any)[0].(map[string]any) service["share_external"] = "64000.00" }, message: "The layanan.0 total share absolute harus sama dengan harga.", }, { name: "allows one cent absolute share rounding difference", mutate: func(payload map[string]any) { service := payload["layanan"].([]any)[0].(map[string]any) service["share_external"] = "64999.99" }, message: "", valid: true, }, { name: "rejects duplicate service", mutate: func(payload map[string]any) { services := payload["layanan"].([]any) services = append(services, services[0]) payload["layanan"] = services }, message: "The layanan.1 layanan_id tidak boleh duplikat dalam satu paket.", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { var payload map[string]any request := httptest.NewRequest(http.MethodPost, "/api/cpone/paket", strings.NewReader(validCreatePaketJSON)) payload, _ = decodeJSONObject(request) test.mutate(payload) params, message := validateCreatePaket(payload) if test.valid { if params.Nama == "" || message != "" { t.Fatalf("params=%+v message=%q want valid payload", params, message) } return } if params.Nama != "" || message != test.message { t.Fatalf("params=%+v message=%q want=%q", params, message, test.message) } }) } }