diff --git a/README.md b/README.md index 287cad9..612df89 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,8 @@ Contoh payload pembuatan pasien HIS: "nik_karyawan": "TSB2026002", "dependant_id": "D001", "nama_karyawan": "BUDI SANTOS", - "channel": "CPONE" + "channel": "CPONE", + "login_buat": "Nama Pengguna" } ``` @@ -237,12 +238,16 @@ Content-Type: application/json "group_tarif_id": "0", "nomer_polis": "", "kelas_id": "Default", - "channel": "CPONE" + "channel": "CPONE", + "login_buat": "Nama Pengguna" } ``` Endpoint ini idempoten untuk pasien, tanggal, departemen, dan dokter yang sama; registrasi aktif yang sudah ada dikembalikan dengan status `already_registered_visit`. +Semua endpoint POST yang menulis data HIS mewajibkan `login_buat` berisi nama +pengguna CPONE yang sedang login (maksimal 30 karakter). Field `channel` tetap +menandai sumber integrasi dan tidak lagi dipakai untuk kolom `LoginBuat` HIS. Contoh payload registrasi laboratorium: @@ -260,7 +265,8 @@ Contoh payload registrasi laboratorium: "shift_harian_id": null, "diagnosa_kerja": "Pemeriksaan laboratorium", "catatan": null, - "channel": "CPONE" + "channel": "CPONE", + "login_buat": "Nama Pengguna" } ``` @@ -281,7 +287,8 @@ Contoh payload penambahan layanan: "catatan": null } ], - "channel": "CPONE" + "channel": "CPONE", + "login_buat": "Nama Pengguna" } ``` @@ -297,7 +304,8 @@ Contoh payload penambahan Paket Dispenser HIS: "cito": false, "markup_cito": 0, "catatan": "", - "channel": "CPONE" + "channel": "CPONE", + "login_buat": "Nama Pengguna" } ``` diff --git a/internal/http/lab_package.go b/internal/http/lab_package.go index 5c2d053..9c254d0 100644 --- a/internal/http/lab_package.go +++ b/internal/http/lab_package.go @@ -77,8 +77,12 @@ func validateAddLabPackage(payload map[string]any) (repository.AddLabPackagePara if !present { channel = "CPONE" } + loginBuat, message := requiredLoginBuat(payload) + if message != "" { + return repository.AddLabPackageParams{}, message + } return repository.AddLabPackageParams{ PackageID: packageID, Cito: cito, MarkupCito: markup, - Notes: strings.TrimSpace(notes), Channel: strings.ToUpper(strings.TrimSpace(channel)), + Notes: strings.TrimSpace(notes), Channel: strings.ToUpper(strings.TrimSpace(channel)), LoginBuat: loginBuat, }, "" } diff --git a/internal/http/lab_package_test.go b/internal/http/lab_package_test.go index ffb8a80..dd8d8d9 100644 --- a/internal/http/lab_package_test.go +++ b/internal/http/lab_package_test.go @@ -15,7 +15,7 @@ func TestAddLabPackageValidPayload(t *testing.T) { Message: "Paket dispenser berhasil ditambahkan ke registrasi laboratorium", }} handler := Handler{labRepo: repo} - request := httptest.NewRequest(http.MethodPost, "/packages", strings.NewReader(`{"paket_id":"disp-260800011","cito":true,"markup_cito":"10","catatan":" test ","channel":"cpone"}`)) + request := httptest.NewRequest(http.MethodPost, "/packages", strings.NewReader(`{"paket_id":"disp-260800011","cito":true,"markup_cito":"10","catatan":" test ","channel":"cpone","login_buat":"Joko Hudoro"}`)) request.SetPathValue("regId", "lab-2608210003") recorder := httptest.NewRecorder() handler.AddLabPackage(recorder, request) diff --git a/internal/http/lab_registration.go b/internal/http/lab_registration.go index 360710f..3004cde 100644 --- a/internal/http/lab_registration.go +++ b/internal/http/lab_registration.go @@ -233,6 +233,10 @@ func validateLabRegistration(payload map[string]any) (validatedLabRegistration, channel = "CPONE" } channel = strings.ToUpper(strings.TrimSpace(channel)) + loginBuat, message := requiredLoginBuat(payload) + if message != "" { + return validatedLabRegistration{}, message + } return validatedLabRegistration{Params: repository.LabRegistrationParams{ MedrecID: medrecID, @@ -255,6 +259,7 @@ func validateLabRegistration(payload map[string]any) (validatedLabRegistration, WorkingDiagnosis: workingDiagnosis, Notes: notes, Channel: channel, + LoginBuat: loginBuat, }}, "" } diff --git a/internal/http/lab_registration_test.go b/internal/http/lab_registration_test.go index b5cd55b..b906fb4 100644 --- a/internal/http/lab_registration_test.go +++ b/internal/http/lab_registration_test.go @@ -77,7 +77,8 @@ func TestRegisterLabValidPayloadAndResponseParity(t *testing.T) { "kelas_id":"", "diagnosa_kerja":"Pemeriksaan laboratorium", "catatan":" catatan ", - "channel":" cpone-api " + "channel":" cpone-api ", + "login_buat":"Joko Hudoro" }` request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/lab-registration", strings.NewReader(body)) @@ -95,7 +96,7 @@ func TestRegisterLabValidPayloadAndResponseParity(t *testing.T) { 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" { + if repo.params.TariffPeriodID != 10 || repo.params.ClassID != "Default" || repo.params.Channel != "CPONE-API" || repo.params.LoginBuat != "Joko Hudoro" { t.Fatalf("normalization mismatch: %+v", repo.params) } if repo.params.Referrer != " Klinik A " || repo.params.Notes != " catatan " { @@ -118,7 +119,8 @@ func TestRegisterLabUsesConfiguredDepartmentID(t *testing.T) { "dokter_pengirim_id":"DR02", "jenis_pasien_id":"0", "periode_tarif_id":10, - "diagnosa_kerja":"Pemeriksaan laboratorium" + "diagnosa_kerja":"Pemeriksaan laboratorium", + "login_buat":"Joko Hudoro" }` request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/lab-registration", strings.NewReader(body)) @@ -158,7 +160,8 @@ func TestRegisterLabCompanyPayload(t *testing.T) { "nama_karyawan":"INTAN SEPTIANI", "kelas_id":"Default", "shift_harian_id":48049, - "diagnosa_kerja":"Test diagnosa" + "diagnosa_kerja":"Test diagnosa", + "login_buat":"Joko Hudoro" }` request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/lab-registration", strings.NewReader(body)) @@ -186,6 +189,7 @@ func TestRegisterLabValidationParity(t *testing.T) { "jenis_pasien_id": "0", "periode_tarif_id": 10, "diagnosa_kerja": "Pemeriksaan laboratorium", + "login_buat": "Joko Hudoro", } tests := []struct { @@ -290,7 +294,7 @@ func TestRegisterLabRepositoryErrorsMatchLaravelEnvelope(t *testing.T) { }, } - 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"}` + 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","login_buat":"Joko Hudoro"}` for _, test := range tests { t.Run(test.name, func(t *testing.T) { handler := Handler{labRepo: &fakeLabRegistrationRepository{err: test.err}} diff --git a/internal/http/lab_services.go b/internal/http/lab_services.go index 3fb0215..212e016 100644 --- a/internal/http/lab_services.go +++ b/internal/http/lab_services.go @@ -128,8 +128,12 @@ func validateAddLabServices(payload map[string]any) (repository.AddLabServicesPa channel = "CPONE" } channel = strings.ToUpper(strings.TrimSpace(channel)) + loginBuat, message := requiredLoginBuat(payload) + if message != "" { + return repository.AddLabServicesParams{}, message + } - return repository.AddLabServicesParams{Layanan: services, Channel: channel}, "" + return repository.AddLabServicesParams{Layanan: services, Channel: channel, LoginBuat: loginBuat}, "" } func requiredNestedString(item map[string]any, key string, index int, maxLength int, requiredMessage string) (string, string) { diff --git a/internal/http/lab_services_test.go b/internal/http/lab_services_test.go index 0fc3491..e98a0f6 100644 --- a/internal/http/lab_services_test.go +++ b/internal/http/lab_services_test.go @@ -47,7 +47,8 @@ func TestAddLabServicesValidPayloadAndResponseParity(t *testing.T) { {"layanan_id":"6413","jumlah":"2","cito":true,"markup_cito":"10.5","catatan":" urgent "}, {"layanan_id":"6414","cito":"0"} ], - "channel":" cpone-api " + "channel":" cpone-api ", + "login_buat":"Joko Hudoro" }` request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/lab-registration/CPLAB2608180001/services", strings.NewReader(body)) request.SetPathValue("regId", "CPLAB2608180001") diff --git a/internal/http/login_buat.go b/internal/http/login_buat.go new file mode 100644 index 0000000..e3ad6f5 --- /dev/null +++ b/internal/http/login_buat.go @@ -0,0 +1,16 @@ +package http + +import "strings" + +// HIS package tables limit LoginBuat to 30 characters. +func requiredLoginBuat(payload map[string]any) (string, string) { + name, message := requiredString(payload, "login_buat", 30, "login_buat wajib diisi dengan nama pengguna CPONE") + if message != "" { + return "", message + } + name = strings.TrimSpace(name) + if name == "" { + return "", "login_buat wajib diisi dengan nama pengguna CPONE" + } + return name, "" +} diff --git a/internal/http/medrec.go b/internal/http/medrec.go index f19f851..ba53693 100644 --- a/internal/http/medrec.go +++ b/internal/http/medrec.go @@ -171,6 +171,10 @@ func validateMedrec(payload map[string]any) (repository.MedrecParams, string) { if !channelPresent || channel == "" { channel = "CPONE" } + loginBuat, message := requiredLoginBuat(payload) + if message != "" { + return repository.MedrecParams{}, message + } identityType = normalizeText(identityType) identityNumber = normalizeIdentity(identityNumber) @@ -208,6 +212,7 @@ func validateMedrec(payload map[string]any) (repository.MedrecParams, string) { DependantID: strings.TrimSpace(dependantID), EmployeeName: strings.TrimSpace(employeeName), Channel: normalizeText(channel), + LoginBuat: loginBuat, }, "" } diff --git a/internal/http/medrec_test.go b/internal/http/medrec_test.go index 7330c10..a261838 100644 --- a/internal/http/medrec_test.go +++ b/internal/http/medrec_test.go @@ -69,7 +69,8 @@ func TestStoreMedrecValidPayloadAndCreatedResponseParity(t *testing.T) { "nik_karyawan":" TSB2026002 ", "dependant_id":"D001", "nama_karyawan":" Budi Santos ", - "channel":" cpone " + "channel":" cpone ", + "login_buat":" Joko Hudoro " }` request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/medrec", strings.NewReader(body)) @@ -93,7 +94,7 @@ func TestStoreMedrecValidPayloadAndCreatedResponseParity(t *testing.T) { if repo.params.Phone != "081234567890" || repo.params.Mobile != "081234567890" { t.Fatalf("phone normalization mismatch: %+v", repo.params) } - if repo.params.Email != "budi@example.com" || repo.params.PlaceOfBirth != "JAKARTA" || repo.params.Channel != "CPONE" { + if repo.params.Email != "budi@example.com" || repo.params.PlaceOfBirth != "JAKARTA" || repo.params.Channel != "CPONE" || repo.params.LoginBuat != "Joko Hudoro" { t.Fatalf("text normalization mismatch: %+v", repo.params) } if repo.params.CompanyID != "PE260700001" || repo.params.EmployeeID != "TSB2026002" || repo.params.DependantID != "D001" || repo.params.EmployeeName != "Budi Santos" { @@ -112,6 +113,7 @@ func TestStoreMedrecValidationParity(t *testing.T) { "jenis_nomer_sosial": "KTP", "nomer_sosial": "3174011501900001", "telepon": "081234567890", + "login_buat": "Joko Hudoro", } tomorrow := time.Now().AddDate(0, 0, 1).Format("2006-01-02") @@ -168,7 +170,7 @@ func TestStoreMedrecNikFallbackAndOutcomeForwarding(t *testing.T) { Data: data, }} handler := Handler{patientRepo: repo} - body := `{"nama":"BUDI","jenis_kelamin":"P","tgl_lahir":"1990-01-15","nik":"3174011501900001","ponsel":"08123"}` + body := `{"nama":"BUDI","jenis_kelamin":"P","tgl_lahir":"1990-01-15","nik":"3174011501900001","ponsel":"08123","login_buat":"Joko Hudoro"}` request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/medrec", strings.NewReader(body)) recorder := httptest.NewRecorder() handler.StoreMedrec(recorder, request) @@ -180,7 +182,7 @@ func TestStoreMedrecNikFallbackAndOutcomeForwarding(t *testing.T) { func TestStoreMedrecRepositoryErrorParity(t *testing.T) { handler := Handler{patientRepo: &fakePatientRepository{err: errors.New("database unavailable")}} - body := `{"nama":"BUDI","jenis_kelamin":"L","tgl_lahir":"1990-01-15","nomer_sosial":"3174011501900001","telepon":"08123"}` + body := `{"nama":"BUDI","jenis_kelamin":"L","tgl_lahir":"1990-01-15","nomer_sosial":"3174011501900001","telepon":"08123","login_buat":"Joko Hudoro"}` request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/medrec", strings.NewReader(body)) recorder := httptest.NewRecorder() handler.StoreMedrec(recorder, request) diff --git a/internal/http/paket_create.go b/internal/http/paket_create.go index 9b2075d..20b84f8 100644 --- a/internal/http/paket_create.go +++ b/internal/http/paket_create.go @@ -123,6 +123,10 @@ func validateCreatePaket(payload map[string]any) (repository.CreatePaketParams, if !present || strings.TrimSpace(channel) == "" { channel = "CPONE" } + loginBuat, message := requiredLoginBuat(payload) + if message != "" { + return repository.CreatePaketParams{}, message + } days := int64(1) if value, present := nullableValue(payload, "jumlah_hari"); present { @@ -251,7 +255,7 @@ func validateCreatePaket(payload map[string]any) (repository.CreatePaketParams, RawatInap: rawatInap, RawatJalan: rawatJalan, MultiVisit: multiVisit, TanggalMulai: startDate, TanggalSelesai: endDate, KelasID: strings.TrimSpace(classID), HeaderPaketID: strings.TrimSpace(headerID), Keterangan: strings.TrimSpace(notes), JumlahHari: days, - Channel: strings.ToUpper(strings.TrimSpace(channel)), Layanan: result, + Channel: strings.ToUpper(strings.TrimSpace(channel)), LoginBuat: loginBuat, Layanan: result, }, "" } diff --git a/internal/http/paket_create_test.go b/internal/http/paket_create_test.go index ec493a2..7548ed8 100644 --- a/internal/http/paket_create_test.go +++ b/internal/http/paket_create_test.go @@ -18,6 +18,7 @@ const validCreatePaketJSON = `{ "tanggal_mulai":"2026-09-01", "tanggal_selesai":"2026-09-30", "kelas_id":"Default", + "login_buat":"Joko Hudoro", "layanan":[{ "layanan_id":"1200", "departemen_id":"MED-PNJ-LAB", diff --git a/internal/http/registration.go b/internal/http/registration.go index 83299a7..26ac81f 100644 --- a/internal/http/registration.go +++ b/internal/http/registration.go @@ -149,6 +149,10 @@ func validateRegistration(payload map[string]any, configuredDepartment string) ( if !present || strings.TrimSpace(channel) == "" { channel = "CPONE" } + loginBuat, message := requiredLoginBuat(payload) + if message != "" { + return repository.RegistrationParams{}, message + } referrer, _, message := optionalString(payload, "perujuk", 150) if message != "" { return repository.RegistrationParams{}, message @@ -183,7 +187,7 @@ func validateRegistration(payload map[string]any, configuredDepartment string) ( TariffPeriodID: tariffPeriod, CompanyID: strings.TrimSpace(companyID), InsuranceID: strings.TrimSpace(insuranceID), GroupTariffID: groupTariff, ProviderID: strings.TrimSpace(providerID), PolicyNumber: strings.TrimSpace(policyNumber), GuaranteeNumber: strings.TrimSpace(guaranteeNumber), EntryCode: strings.TrimSpace(entryCode), ClassID: strings.TrimSpace(classID), - Notes: strings.TrimSpace(notes), Referrer: strings.TrimSpace(referrer), EmployeeID: strings.TrimSpace(employeeID), EmployeeName: strings.TrimSpace(employeeName), Channel: normalizeText(channel), PackageID: packageID, + Notes: strings.TrimSpace(notes), Referrer: strings.TrimSpace(referrer), EmployeeID: strings.TrimSpace(employeeID), EmployeeName: strings.TrimSpace(employeeName), Channel: normalizeText(channel), LoginBuat: loginBuat, PackageID: packageID, }, "" } diff --git a/internal/http/registration_test.go b/internal/http/registration_test.go index 597bad7..1ad611d 100644 --- a/internal/http/registration_test.go +++ b/internal/http/registration_test.go @@ -42,7 +42,8 @@ func TestRegisterPatientUsesConfiguredDepartmentAndNormalizesPayload(t *testing. "group_tarif_id":18, "kode_paket":"PN2600036", "kelas_id":"Default", - "channel":"cpone" + "channel":"cpone", + "login_buat":"Joko Hudoro" }`)) recorder := httptest.NewRecorder() handler.RegisterPatient(recorder, request) @@ -53,7 +54,7 @@ func TestRegisterPatientUsesConfiguredDepartmentAndNormalizesPayload(t *testing. if repo.params.DepartmentID != "08_01" || repo.params.NIK != "3174011501900001" || repo.params.RegistrationType != 2 { t.Fatalf("unexpected normalized params: %+v", repo.params) } - if repo.params.PatientTypeID != 1 || repo.params.TariffPeriodID != 10 || repo.params.GroupTariffID != 18 || repo.params.Channel != "CPONE" { + if repo.params.PatientTypeID != 1 || repo.params.TariffPeriodID != 10 || repo.params.GroupTariffID != 18 || repo.params.Channel != "CPONE" || repo.params.LoginBuat != "Joko Hudoro" { t.Fatalf("unexpected numeric/text params: %+v", repo.params) } if repo.params.PackageID != "PN2600036" { @@ -72,9 +73,20 @@ func TestRegisterPatientRequiresIdentityWhenMedrecIsMissing(t *testing.T) { } } +func TestRegisterPatientRequiresLoggedInName(t *testing.T) { + handler := Handler{registrationRepo: &fakeRegistrationRepository{}, departmentID: "08_01"} + request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/registration", strings.NewReader(`{"medrec_id":"00001234","channel":"CPONE"}`)) + recorder := httptest.NewRecorder() + handler.RegisterPatient(recorder, request) + + if recorder.Code != http.StatusUnprocessableEntity || !strings.Contains(recorder.Body.String(), "login_buat wajib diisi") { + t.Fatalf("unexpected validation response: status=%d body=%s", recorder.Code, recorder.Body.String()) + } +} + func TestRegisterPatientForwardsRepositoryError(t *testing.T) { handler := Handler{registrationRepo: &fakeRegistrationRepository{err: errors.New("database unavailable")}, departmentID: "08_01"} - request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/registration", strings.NewReader(`{"medrec_id":"00001234"}`)) + request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/registration", strings.NewReader(`{"medrec_id":"00001234","login_buat":"Joko Hudoro"}`)) recorder := httptest.NewRecorder() handler.RegisterPatient(recorder, request) diff --git a/internal/repository/lab_package.go b/internal/repository/lab_package.go index 006bdd0..56e9f5b 100644 --- a/internal/repository/lab_package.go +++ b/internal/repository/lab_package.go @@ -16,6 +16,7 @@ type AddLabPackageParams struct { MarkupCito float64 Notes string Channel string + LoginBuat string } type labPackageHeader struct { @@ -161,7 +162,7 @@ func addLabPackageInTransaction(ctx context.Context, tx *sql.Tx, regID string, p return LabRegistrationOutcome{}, err } now := time.Now().In(jkt).Format("2006-01-02 15:04:05") - dispenserID, visitNumber, err := ensurePackageDispenser(ctx, tx, registration.Registration, packageHeader, params.Channel, now) + dispenserID, visitNumber, err := ensurePackageDispenser(ctx, tx, registration.Registration, packageHeader, params.LoginBuat, now) if err != nil { return LabRegistrationOutcome{}, err } @@ -194,7 +195,7 @@ func addLabPackageInTransaction(ctx context.Context, tx *sql.Tx, regID string, p if err != nil { return LabRegistrationOutcome{}, err } - dispenserServiceID, err := insertPackageDispenserService(ctx, tx, dispenserID, registration.Registration, packageHeader.ID, packageService, operationID, params.Channel, now) + dispenserServiceID, err := insertPackageDispenserService(ctx, tx, dispenserID, registration.Registration, packageHeader.ID, packageService, operationID, params.LoginBuat, now) if err != nil { return LabRegistrationOutcome{}, err } @@ -218,19 +219,19 @@ func addLabPackageInTransaction(ctx context.Context, tx *sql.Tx, regID string, p ShareExternal: parseNullableDecimal(packageService.ShareExternal), ShareLain: parseNullableDecimal(packageService.ShareOther), Catatan: params.Notes, } - trxServiceID, err := insertPackageTransactionService(ctx, tx, resolved, discountType, discount, patient, patient, guarantor, guarantor, packageHeader.ID, registration.Registration.RegID, transaction.Transaction.TrxDepartemenID, registration.Registration.MEDRECID, packageService.DepartmentID, doctorID, classID, params.Channel, now) + trxServiceID, err := insertPackageTransactionService(ctx, tx, resolved, discountType, discount, patient, patient, guarantor, guarantor, packageHeader.ID, registration.Registration.RegID, transaction.Transaction.TrxDepartemenID, registration.Registration.MEDRECID, packageService.DepartmentID, doctorID, classID, params.LoginBuat, now) if err != nil { return LabRegistrationOutcome{}, err } - if _, err := tx.ExecContext(ctx, `INSERT INTO trxlayanan_detail (TrxLayananID, PaketDispenserID, PaketDispenserLayananID, LoginBuat, TanggalBuat, NA) VALUES (?, ?, ?, ?, ?, 'N')`, trxServiceID, dispenserID, dispenserServiceID, params.Channel, now); err != nil { + if _, err := tx.ExecContext(ctx, `INSERT INTO trxlayanan_detail (TrxLayananID, PaketDispenserID, PaketDispenserLayananID, LoginBuat, TanggalBuat, NA) VALUES (?, ?, ?, ?, ?, 'N')`, trxServiceID, dispenserID, dispenserServiceID, params.LoginBuat, now); err != nil { return LabRegistrationOutcome{}, err } addedIDs = append(addedIDs, master.LayananID) } - if err := insertPackageAdministration(ctx, tx, dispenserID, registration.Registration.RegID, packageHeader.ID, params.Channel, now); err != nil { + if err := insertPackageAdministration(ctx, tx, dispenserID, registration.Registration.RegID, packageHeader.ID, params.LoginBuat, now); err != nil { return LabRegistrationOutcome{}, err } - if err := syncLabSpecimens(ctx, tx, transaction.Transaction.TrxDepartemenID, transaction.Transaction.TrxID, params.Channel, now); err != nil { + if err := syncLabSpecimens(ctx, tx, transaction.Transaction.TrxDepartemenID, transaction.Transaction.TrxID, params.LoginBuat, now); err != nil { return LabRegistrationOutcome{}, err } if err := updateLabTransactionTotal(ctx, tx, transaction.Transaction.TrxDepartemenID, registration.Registration.RegID, registration.Registration.DepartemenID); err != nil { diff --git a/internal/repository/lab_registration.go b/internal/repository/lab_registration.go index c5c05dd..1e9dbcd 100644 --- a/internal/repository/lab_registration.go +++ b/internal/repository/lab_registration.go @@ -35,6 +35,7 @@ type LabRegistrationParams struct { WorkingDiagnosis string Notes string Channel string + LoginBuat string } type LabRegistrationOutcome struct { @@ -290,7 +291,7 @@ func registerLabInTransaction(ctx context.Context, tx *sql.Tx, params LabRegistr params.ClassID, strings.TrimSpace(params.Notes), shiftID, - params.Channel, + params.LoginBuat, nowText, ) if err != nil { @@ -309,7 +310,7 @@ func registerLabInTransaction(ctx context.Context, tx *sql.Tx, params LabRegistr senderDoctorID, nowText, params.ClassID, - params.Channel, + params.LoginBuat, nowText, ) if err != nil { @@ -323,7 +324,7 @@ func registerLabInTransaction(ctx context.Context, tx *sql.Tx, params LabRegistr if err := upsertLabNominals(ctx, tx, regID, trxDepartmentID, params.DepartmentID); err != nil { return LabRegistrationOutcome{}, err } - if err := saveLabDiagnosis(ctx, tx, regID, patient.MEDRECID, strings.TrimSpace(params.WorkingDiagnosis), params.Channel, nowText); err != nil { + if err := saveLabDiagnosis(ctx, tx, regID, patient.MEDRECID, strings.TrimSpace(params.WorkingDiagnosis), params.LoginBuat, nowText); err != nil { return LabRegistrationOutcome{}, err } diff --git a/internal/repository/lab_services.go b/internal/repository/lab_services.go index e7105c9..b3bed6d 100644 --- a/internal/repository/lab_services.go +++ b/internal/repository/lab_services.go @@ -12,8 +12,9 @@ import ( ) type AddLabServicesParams struct { - Layanan []RequestedLabService - Channel string + Layanan []RequestedLabService + Channel string + LoginBuat string } type RequestedLabService struct { @@ -225,13 +226,13 @@ func addLabServicesInTransaction(ctx context.Context, tx *sql.Tx, regID string, registration.Registration.DepartemenID, doctorValue, classID, - params.Channel, + params.LoginBuat, now, ); err != nil { return LabRegistrationOutcome{}, err } } - if err := syncLabSpecimens(ctx, tx, transaction.Transaction.TrxDepartemenID, transaction.Transaction.TrxID, params.Channel, now); err != nil { + if err := syncLabSpecimens(ctx, tx, transaction.Transaction.TrxDepartemenID, transaction.Transaction.TrxID, params.LoginBuat, now); err != nil { return LabRegistrationOutcome{}, err } if err := updateLabTransactionTotal( diff --git a/internal/repository/medrec.go b/internal/repository/medrec.go index 681c1b1..d05d752 100644 --- a/internal/repository/medrec.go +++ b/internal/repository/medrec.go @@ -30,6 +30,7 @@ type MedrecParams struct { DependantID string EmployeeName string Channel string + LoginBuat string } type MedrecOutcome struct { @@ -263,7 +264,7 @@ func insertMedrec(ctx context.Context, tx *sql.Tx, medrecID string, params Medre params.IdentityType, params.IdentityNumber, params.EmployeeID, params.DependantID, params.EmployeeName, phone, mobile, params.Email, params.Address, params.Province, params.City, params.District, params.Village, - params.PostalCode, params.CompanyID, params.Channel, now, now) + params.PostalCode, params.CompanyID, params.LoginBuat, now, now) if err != nil { return MedrecPatient{}, err } diff --git a/internal/repository/paket.go b/internal/repository/paket.go index e56ba64..2b524e9 100644 --- a/internal/repository/paket.go +++ b/internal/repository/paket.go @@ -37,6 +37,7 @@ type CreatePaketParams struct { Keterangan string JumlahHari int64 Channel string + LoginBuat string Layanan []CreatePaketLayananParams } diff --git a/internal/repository/paket_create.go b/internal/repository/paket_create.go index 7538d6c..509ee1d 100644 --- a/internal/repository/paket_create.go +++ b/internal/repository/paket_create.go @@ -93,7 +93,7 @@ func (r MySQLLayananRepository) CreatePaket(ctx context.Context, params CreatePa ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 2, ?, ?, 'N')`, packageID, params.Nama, params.JenisPaket, boolInt(params.RawatJalan), boolInt(params.RawatInap), boolInt(params.MultiVisit), nullableDate(params.TanggalMulai), nullableDate(params.TanggalSelesai), - params.HeaderPaketID, params.KelasID, params.JumlahHari, "0.00", params.Keterangan, params.Channel, now) + params.HeaderPaketID, params.KelasID, params.JumlahHari, "0.00", params.Keterangan, params.LoginBuat, now) if err != nil { return CreatePaketResult{}, err } @@ -124,7 +124,7 @@ func (r MySQLLayananRepository) CreatePaket(ctx context.Context, params CreatePa packageID, departmentID, service.DepartemenID, service.LayananID, service.Jumlah, service.JumlahHari, decimalText(service.HargaCents), service.TipeDiskon, decimalText(service.DiskonCents), service.TipeShare, decimalText(service.ShareRSCents), decimalText(service.ShareDokterCents), decimalText(service.ShareExternalCents), - decimalText(service.ShareLainCents), decimalText(subtotal), params.Channel, now) + decimalText(service.ShareLainCents), decimalText(subtotal), params.LoginBuat, now) if err != nil { return CreatePaketResult{}, err } diff --git a/internal/repository/registration.go b/internal/repository/registration.go index f021fb5..a62f017 100644 --- a/internal/repository/registration.go +++ b/internal/repository/registration.go @@ -33,6 +33,7 @@ type RegistrationParams struct { EmployeeID string EmployeeName string Channel string + LoginBuat string PackageID string } @@ -129,7 +130,7 @@ func registerPatientInTransaction(ctx context.Context, tx *sql.Tx, params Regist if found { data := RegistrationData{Patient: patient, Registration: existing} if strings.TrimSpace(params.PackageID) != "" { - data.Package, err = addRegistrationPackage(ctx, tx, existing, patient.MEDRECID, params.PackageID, params.Channel, params.RegistrationDate) + data.Package, err = addRegistrationPackage(ctx, tx, existing, patient.MEDRECID, params.PackageID, params.LoginBuat, params.RegistrationDate) if err != nil { return RegistrationOutcome{}, err } @@ -196,7 +197,7 @@ func registerPatientInTransaction(ctx context.Context, tx *sql.Tx, params Regist params.ClassID, params.Notes, shiftID, - params.Channel, + params.LoginBuat, nowText, ) if err != nil { @@ -214,7 +215,7 @@ func registerPatientInTransaction(ctx context.Context, tx *sql.Tx, params Regist } data := RegistrationData{Patient: patient, Registration: registration} if strings.TrimSpace(params.PackageID) != "" { - data.Package, err = addRegistrationPackage(ctx, tx, registration, patient.MEDRECID, params.PackageID, params.Channel, params.RegistrationDate) + data.Package, err = addRegistrationPackage(ctx, tx, registration, patient.MEDRECID, params.PackageID, params.LoginBuat, params.RegistrationDate) if err != nil { return RegistrationOutcome{}, err } diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 96ea36f..ae4852a 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -63,10 +63,10 @@ if [[ "$requested_scope" == "user" ]]; then elif [[ "$requested_scope" == "system" ]]; then systemctl_cmd=(systemctl) resolved_scope=system -elif systemctl --user show "$service" >/dev/null 2>&1; then +elif [[ "$(systemctl --user show "$service" -p LoadState --value 2>/dev/null || true)" == loaded ]]; then systemctl_cmd=(systemctl --user) resolved_scope=user -elif systemctl show "$service" >/dev/null 2>&1; then +elif [[ "$(systemctl show "$service" -p LoadState --value 2>/dev/null || true)" == loaded ]]; then systemctl_cmd=(systemctl) resolved_scope=system else @@ -172,9 +172,13 @@ fi for attempt in {1..20}; do if "${systemctl_cmd[@]}" is-active --quiet "$service"; then new_pid="$("${systemctl_cmd[@]}" show "$service" -p MainPID --value 2>/dev/null || true)" - if [[ "$restart_mode" == "systemctl" || "$new_pid" != "$main_pid" ]]; then - echo "Service aktif: $service (MainPID=${new_pid:-unknown})" - exit 0 + if [[ "$new_pid" =~ ^[1-9][0-9]*$ && ( "$restart_mode" == "systemctl" || "$new_pid" != "$main_pid" ) ]]; then + sleep 2 + confirmed_pid="$("${systemctl_cmd[@]}" show "$service" -p MainPID --value 2>/dev/null || true)" + if [[ "$confirmed_pid" == "$new_pid" ]] && "${systemctl_cmd[@]}" is-active --quiet "$service"; then + echo "Service aktif: $service (MainPID=$confirmed_pid)" + exit 0 + fi fi fi sleep 1