feat(cpone): support company lab registrations

This commit is contained in:
2026-08-23 19:53:39 +07:00
parent 7bd62cc65c
commit b497012de3
4 changed files with 275 additions and 13 deletions

View File

@@ -21,7 +21,15 @@ type LabRegistrationParams struct {
DoctorID string
SenderDoctorID string
Referrer string
PatientType string
TariffPeriodID int64
CompanyID string
InsuranceID string
ProviderID string
GroupTariffID int64
PolicyNumber string
EmployeeID string
EmployeeName string
ClassID string
DailyShiftID *int64
WorkingDiagnosis string
@@ -54,6 +62,11 @@ type LabRegistration struct {
JenisPasienID int64 `json:"JenisPasienID"`
JenisRegID *int64 `json:"JenisRegID"`
PeriodeTarifID int64 `json:"PeriodeTarifID"`
PerusahaanID *string `json:"PerusahaanID"`
AsuransiID *string `json:"AsuransiID"`
ProviderID *string `json:"ProviderID"`
GroupTarifID *int64 `json:"GroupTarifID"`
NomerPolis *string `json:"NomerPolis"`
}
type LabTransaction struct {
@@ -91,6 +104,11 @@ type dbLabRegistration struct {
JenisPasienID int64
JenisRegID sql.NullInt64
PeriodeTarifID int64
PerusahaanID sql.NullString
AsuransiID sql.NullString
ProviderID sql.NullString
GroupTarifID sql.NullInt64
NomerPolis sql.NullString
}
type dbLabTransaction struct {
@@ -161,6 +179,9 @@ func registerLabInTransaction(ctx context.Context, tx *sql.Tx, params LabRegistr
if !departmentActive {
return LabRegistrationOutcome{}, ValidationError{Message: "Departemen tujuan bukan departemen laboratorium aktif"}
}
if err := validateLabGuarantor(ctx, tx, params); err != nil {
return LabRegistrationOutcome{}, err
}
patient, found, err := findLabPatientForUpdate(ctx, tx, params.MedrecID)
if err != nil {
@@ -175,6 +196,15 @@ func registerLabInTransaction(ctx context.Context, tx *sql.Tx, params LabRegistr
return LabRegistrationOutcome{}, err
}
if found {
if !sameLabGuarantor(existing, params) {
return labOutcome(
409,
false,
"registration_guarantor_conflict",
"Pasien sudah memiliki registrasi laboratorium pada hari yang sama dengan penjamin berbeda",
nil,
), nil
}
trx, trxFound, err := findLabTransaction(ctx, tx, existing.RegID, params.DepartmentID)
if err != nil {
return LabRegistrationOutcome{}, err
@@ -223,10 +253,11 @@ func registerLabInTransaction(ctx context.Context, tx *sql.Tx, params LabRegistr
INSERT INTO regpas (
RegID, MEDRECID, Nama, ALAMATEXTPAS, TELPEXTPAS, TglLahir, JnsKelamin,
KunjunganKe, Tanggal, JenisPasienID, PeriodeTarifID, PerusahaanID,
GroupTarifID, AsuransiID, ProviderID, DepartemenID, Perujuk, JenisRegID,
GroupTarifID, AsuransiID, ProviderID, NomerPolis, NIK, NamaKaryawan,
DepartemenID, Perujuk, JenisRegID,
DokterID, DokterID2, KelasID, MataUang, Rate, Pulang, BolehPulang, Lunas,
BatalDaftar, Catatan, ShiftHarianIDDaftar, LoginBuat, TanggalBuat, NA
) VALUES (?, ?, ?, '', '', ?, ?, ?, ?, '0', ?, '', '0', '', '', ?, ?, '3', ?, ?, ?, 'IDR', 1, 'N', 'N', 'N', 'N', ?, ?, ?, ?, 'N')`,
) VALUES (?, ?, ?, '', '', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '3', ?, ?, ?, 'IDR', 1, 'N', 'N', 'N', 'N', ?, ?, ?, ?, 'N')`,
regID,
patient.MEDRECID,
patient.Nama,
@@ -234,7 +265,15 @@ func registerLabInTransaction(ctx context.Context, tx *sql.Tx, params LabRegistr
nullStringValue(patient.Kelamin),
previousVisits+1,
nowText,
params.PatientType,
params.TariffPeriodID,
params.CompanyID,
params.GroupTariffID,
params.InsuranceID,
params.ProviderID,
params.PolicyNumber,
params.EmployeeID,
params.EmployeeName,
params.DepartmentID,
strings.TrimSpace(params.Referrer),
params.DoctorID,
@@ -295,11 +334,108 @@ func registerLabInTransaction(ctx context.Context, tx *sql.Tx, params LabRegistr
return labOutcome(201, true, "registered", "Registrasi laboratorium berhasil disimpan", &data), nil
}
func validateLabGuarantor(ctx context.Context, tx *sql.Tx, params LabRegistrationParams) error {
if params.PatientType == "0" {
return nil
}
active, err := exists(ctx, tx, `
SELECT EXISTS(
SELECT 1 FROM jenispasien
WHERE JenisPasienID = ? AND NA = 'N'
)`, params.PatientType)
if err != nil {
return err
}
if !active {
return ValidationError{Message: "Jenis pasien penjamin tidak ditemukan atau sudah tidak aktif"}
}
guarantors := []struct {
label string
id string
}{
{label: "Perusahaan", id: params.CompanyID},
{label: "Asuransi/penanggung", id: params.InsuranceID},
{label: "Provider", id: params.ProviderID},
}
for _, guarantor := range guarantors {
if guarantor.id == "" {
continue
}
active, err = exists(ctx, tx, `
SELECT EXISTS(
SELECT 1 FROM perusahaan
WHERE PerusahaanID = ? AND NA = 'N'
)`, guarantor.id)
if err != nil {
return err
}
if !active {
return ValidationError{Message: guarantor.label + " tidak ditemukan atau sudah tidak aktif"}
}
}
var tariffPeriodID int64
err = tx.QueryRowContext(ctx, `
SELECT pg.PeriodeTarifID
FROM perusahaan_grouptarif AS pg
INNER JOIN perusahaan_tarif AS pt
ON pt.Perusahaan_TarifID = pg.Perusahaan_TarifID
WHERE pg.GroupTarifID = ?
AND pt.PerusahaanID = ?
AND pg.NA = 'N'
AND DATE(pg.TanggalBerlaku) <= ?
AND DATE(pg.TanggalBerakhir) >= ?
LIMIT 1`,
params.GroupTariffID,
params.CompanyID,
params.RegistrationDate.Format("2006-01-02"),
params.RegistrationDate.Format("2006-01-02"),
).Scan(&tariffPeriodID)
if errors.Is(err, sql.ErrNoRows) {
return ValidationError{Message: "Group tarif tidak aktif, tidak berlaku pada tanggal registrasi, atau bukan milik perusahaan yang dipilih"}
}
if err != nil {
return err
}
if tariffPeriodID != params.TariffPeriodID {
return ValidationError{Message: fmt.Sprintf("Periode tarif harus %d sesuai group tarif yang dipilih", tariffPeriodID)}
}
return nil
}
func sameLabGuarantor(existing dbLabRegistration, params LabRegistrationParams) bool {
return strconv.FormatInt(existing.JenisPasienID, 10) == params.PatientType &&
existing.PeriodeTarifID == params.TariffPeriodID &&
nullInt64(existing.GroupTarifID) == params.GroupTariffID &&
strings.TrimSpace(nullableString(existing.PerusahaanID)) == params.CompanyID &&
strings.TrimSpace(nullableString(existing.AsuransiID)) == params.InsuranceID &&
strings.TrimSpace(nullableString(existing.ProviderID)) == params.ProviderID &&
strings.TrimSpace(nullableString(existing.NomerPolis)) == params.PolicyNumber
}
func nullInt64(value sql.NullInt64) int64 {
if !value.Valid {
return 0
}
return value.Int64
}
func nullableString(value sql.NullString) string {
if !value.Valid {
return ""
}
return value.String
}
func findLabRegistrationByID(ctx context.Context, tx *sql.Tx, regID string) (dbLabRegistration, error) {
var registration dbLabRegistration
err := tx.QueryRowContext(ctx, `
SELECT RegID, MEDRECID, Tanggal, DepartemenID, DokterID,
JenisPasienID, JenisRegID, PeriodeTarifID
JenisPasienID, JenisRegID, PeriodeTarifID, PerusahaanID,
AsuransiID, ProviderID, GroupTarifID, NomerPolis
FROM regpas WHERE RegID = ? LIMIT 1`, regID).Scan(
&registration.RegID,
&registration.MEDRECID,
@@ -309,6 +445,11 @@ func findLabRegistrationByID(ctx context.Context, tx *sql.Tx, regID string) (dbL
&registration.JenisPasienID,
&registration.JenisRegID,
&registration.PeriodeTarifID,
&registration.PerusahaanID,
&registration.AsuransiID,
&registration.ProviderID,
&registration.GroupTarifID,
&registration.NomerPolis,
)
return registration, err
}
@@ -355,7 +496,8 @@ func findExistingLabRegistrationForUpdate(
var registration dbLabRegistration
err := tx.QueryRowContext(ctx, `
SELECT RegID, MEDRECID, Tanggal, DepartemenID, DokterID,
JenisPasienID, JenisRegID, PeriodeTarifID
JenisPasienID, JenisRegID, PeriodeTarifID, PerusahaanID,
AsuransiID, ProviderID, GroupTarifID, NomerPolis
FROM regpas
WHERE MEDRECID = ?
AND DepartemenID = ?
@@ -371,6 +513,11 @@ func findExistingLabRegistrationForUpdate(
&registration.JenisPasienID,
&registration.JenisRegID,
&registration.PeriodeTarifID,
&registration.PerusahaanID,
&registration.AsuransiID,
&registration.ProviderID,
&registration.GroupTarifID,
&registration.NomerPolis,
)
if errors.Is(err, sql.ErrNoRows) {
return dbLabRegistration{}, false, nil
@@ -544,6 +691,11 @@ func buildLabRegistrationData(ctx context.Context, tx *sql.Tx, registration dbLa
JenisPasienID: registration.JenisPasienID,
JenisRegID: nullInt64Ptr(registration.JenisRegID),
PeriodeTarifID: registration.PeriodeTarifID,
PerusahaanID: nullStringPtr(registration.PerusahaanID),
AsuransiID: nullStringPtr(registration.AsuransiID),
ProviderID: nullStringPtr(registration.ProviderID),
GroupTarifID: nullInt64Ptr(registration.GroupTarifID),
NomerPolis: nullStringPtr(registration.NomerPolis),
},
Layanan: make([]LabService, 0),
}