504 lines
18 KiB
Go
504 lines
18 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type RegistrationParams struct {
|
|
MedrecID string
|
|
NIK string
|
|
BirthDate time.Time
|
|
RegistrationDate time.Time
|
|
DepartmentID string
|
|
DoctorID string
|
|
PatientTypeID int64
|
|
RegistrationType int64
|
|
TariffPeriodID int64
|
|
CompanyID string
|
|
InsuranceID string
|
|
GroupTariffID int64
|
|
ProviderID string
|
|
PolicyNumber string
|
|
GuaranteeNumber string
|
|
EntryCode string
|
|
ClassID string
|
|
Notes string
|
|
Referrer string
|
|
EmployeeID string
|
|
EmployeeName string
|
|
Channel string
|
|
PackageID string
|
|
}
|
|
|
|
type RegistrationOutcome struct {
|
|
HTTPStatus int
|
|
Success bool
|
|
Status string
|
|
Message string
|
|
Data any
|
|
}
|
|
|
|
type RegistrationData struct {
|
|
Patient MedrecPatient `json:"patient"`
|
|
Registration RegistrationRecord `json:"registration"`
|
|
Package *RegistrationPackage `json:"package,omitempty"`
|
|
}
|
|
|
|
type RegistrationPackage struct {
|
|
PaketDispenserID int64 `json:"PaketDispenserID"`
|
|
PaketID string `json:"PaketID"`
|
|
Nama string `json:"Nama"`
|
|
KunjunganKe int64 `json:"KunjunganKe"`
|
|
}
|
|
|
|
type RegistrationRecord struct {
|
|
RegID string `json:"RegID"`
|
|
MEDRECID string `json:"MEDRECID"`
|
|
Tanggal string `json:"Tanggal"`
|
|
DepartmentID string `json:"DepartemenID"`
|
|
DoctorID string `json:"DokterID"`
|
|
PatientTypeID int64 `json:"JenisPasienID"`
|
|
RegistrationID int64 `json:"JenisRegID"`
|
|
TariffPeriodID int64 `json:"PeriodeTarifID"`
|
|
CompanyID string `json:"PerusahaanID"`
|
|
InsuranceID string `json:"AsuransiID"`
|
|
ProviderID string `json:"ProviderID"`
|
|
GroupTariffID int64 `json:"GroupTarifID"`
|
|
PolicyNumber string `json:"NomerPolis"`
|
|
Pulang string `json:"Pulang"`
|
|
BatalDaftar string `json:"BatalDaftar"`
|
|
}
|
|
|
|
func (r MySQLLayananRepository) RegisterPatient(ctx context.Context, params RegistrationParams) (RegistrationOutcome, error) {
|
|
for attempt := 0; attempt < 3; attempt++ {
|
|
outcome, err := r.registerPatientAttempt(ctx, params)
|
|
if err == nil {
|
|
return outcome, nil
|
|
}
|
|
if !isConcurrencyError(err) || ctx.Err() != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
}
|
|
return RegistrationOutcome{}, fmt.Errorf("registrasi pasien gagal karena konflik transaksi")
|
|
}
|
|
|
|
func (r MySQLLayananRepository) registerPatientAttempt(ctx context.Context, params RegistrationParams) (outcome RegistrationOutcome, err error) {
|
|
tx, err := r.db.BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
defer func() {
|
|
if recovered := recover(); recovered != nil {
|
|
_ = tx.Rollback()
|
|
panic(recovered)
|
|
}
|
|
if err != nil {
|
|
_ = tx.Rollback()
|
|
}
|
|
}()
|
|
|
|
outcome, err = registerPatientInTransaction(ctx, tx, params)
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
if err = tx.Commit(); err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
return outcome, nil
|
|
}
|
|
|
|
func registerPatientInTransaction(ctx context.Context, tx *sql.Tx, params RegistrationParams) (RegistrationOutcome, error) {
|
|
patient, found, err := findRegistrationPatient(ctx, tx, params)
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
if !found {
|
|
return registrationOutcome(404, false, "patient_not_found", "Pasien tidak ditemukan", nil), nil
|
|
}
|
|
|
|
existing, found, err := findExistingRegistration(ctx, tx, patient.MEDRECID, params)
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
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)
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
}
|
|
return registrationOutcome(200, true, "already_registered_visit", "Pasien sudah memiliki registrasi aktif pada tujuan yang sama", data), nil
|
|
}
|
|
|
|
jakarta, err := time.LoadLocation("Asia/Jakarta")
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
now := time.Now().In(jakarta)
|
|
nowText := now.Format("2006-01-02 15:04:05")
|
|
regDate := params.RegistrationDate.Format("2006-01-02")
|
|
prefix := "P" + params.RegistrationDate.Format("0601")
|
|
regID, err := nextRegistrationID(ctx, tx, prefix)
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
shiftID, err := resolveDailyShiftID(ctx, tx, nil, params.RegistrationDate)
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
|
|
var previousVisits int64
|
|
if err := tx.QueryRowContext(ctx, `SELECT COUNT(*) FROM regpas WHERE MEDRECID = ? AND NA = 'N'`, patient.MEDRECID).Scan(&previousVisits); err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
|
|
_, err = tx.ExecContext(ctx, `
|
|
INSERT INTO regpas SET
|
|
RegID = ?, MEDRECID = ?, Nama = ?, ALAMATEXTPAS = ?, TELPEXTPAS = ?, TglLahir = ?, JnsKelamin = ?,
|
|
KunjunganKe = ?, Tanggal = ?, JenisPasienID = ?, PeriodeTarifID = ?, PerusahaanID = ?,
|
|
GroupTarifID = ?, AsuransiID = ?, ProviderID = ?, NomerPolis = ?, NIK = ?, NamaKaryawan = ?,
|
|
NomerJaminan = ?, KodeMasukID = ?, DepartemenID = ?, DepartemenID2 = ?, JenisRegID = ?,
|
|
Perujuk = ?, DokterID = ?, DokterID2 = '', KelasID = ?, MataUang = 'IDR', Rate = 1,
|
|
Pulang = 'N', BolehPulang = 'N', Lunas = 'N', BatalDaftar = 'N', Catatan = '',
|
|
CatatanMasuk = ?, ShiftHarianIDDaftar = ?, LoginBuat = ?, TanggalBuat = ?, NA = 'N'`,
|
|
regID,
|
|
patient.MEDRECID,
|
|
patient.Nama,
|
|
"",
|
|
firstNonEmpty(pointerValue(patient.Ponsel), pointerValue(patient.Telepon)),
|
|
pointerValue(patient.TanggalLahir),
|
|
firstNonEmpty(pointerValue(patient.Kelamin), "L"),
|
|
previousVisits+1,
|
|
regDate,
|
|
params.PatientTypeID,
|
|
params.TariffPeriodID,
|
|
params.CompanyID,
|
|
params.GroupTariffID,
|
|
params.InsuranceID,
|
|
params.ProviderID,
|
|
params.PolicyNumber,
|
|
firstNonEmpty(params.EmployeeID, params.NIK, pointerValue(patient.NomerSosial)),
|
|
params.EmployeeName,
|
|
params.GuaranteeNumber,
|
|
params.EntryCode,
|
|
params.DepartmentID,
|
|
params.DepartmentID,
|
|
params.RegistrationType,
|
|
params.Referrer,
|
|
params.DoctorID,
|
|
params.ClassID,
|
|
params.Notes,
|
|
shiftID,
|
|
params.Channel,
|
|
nowText,
|
|
)
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
|
|
registration := RegistrationRecord{
|
|
RegID: regID, MEDRECID: patient.MEDRECID, Tanggal: regDate,
|
|
DepartmentID: params.DepartmentID, DoctorID: params.DoctorID,
|
|
PatientTypeID: params.PatientTypeID, RegistrationID: params.RegistrationType,
|
|
TariffPeriodID: params.TariffPeriodID, CompanyID: params.CompanyID,
|
|
InsuranceID: params.InsuranceID, ProviderID: params.ProviderID,
|
|
GroupTariffID: params.GroupTariffID, PolicyNumber: params.PolicyNumber,
|
|
Pulang: "N", BatalDaftar: "N",
|
|
}
|
|
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)
|
|
if err != nil {
|
|
return RegistrationOutcome{}, err
|
|
}
|
|
}
|
|
return registrationOutcome(201, true, "registered", "Registrasi berhasil disimpan", data), nil
|
|
}
|
|
|
|
func addRegistrationPackage(ctx context.Context, tx *sql.Tx, registration RegistrationRecord, medrecID, packageID, channel string, registrationDate time.Time) (*RegistrationPackage, error) {
|
|
packageID = strings.ToUpper(strings.TrimSpace(packageID))
|
|
header, found, err := findActiveOutpatientPackage(ctx, tx, packageID, registrationDate)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !found {
|
|
return nil, ValidationError{Message: "Paket dispenser MCU tidak ditemukan, belum disetujui, atau sudah tidak berlaku"}
|
|
}
|
|
|
|
jakarta, err := time.LoadLocation("Asia/Jakarta")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
now := time.Now().In(jakarta).Format("2006-01-02 15:04:05")
|
|
if registration.RegistrationID == 2 {
|
|
if _, err := ensureMCUTransaction(ctx, tx, registration, channel, now); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
dbRegistration := dbLabRegistration{RegID: registration.RegID, MEDRECID: medrecID}
|
|
dispenserID, visitNumber, err := ensurePackageDispenser(ctx, tx, dbRegistration, header, channel, now)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if registration.RegistrationID == 2 {
|
|
if err := ensureMCUPackageDetails(ctx, tx, dispenserID, registration.RegID, medrecID, header.ID, channel, now); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return &RegistrationPackage{
|
|
PaketDispenserID: dispenserID,
|
|
PaketID: header.ID,
|
|
Nama: header.Name,
|
|
KunjunganKe: visitNumber,
|
|
}, nil
|
|
}
|
|
|
|
func ensureMCUTransaction(ctx context.Context, tx *sql.Tx, registration RegistrationRecord, channel, now string) (int64, error) {
|
|
var transactionID int64
|
|
err := tx.QueryRowContext(ctx, `
|
|
SELECT TrxDepartemenID
|
|
FROM trxdepartemen
|
|
WHERE RegID = ? AND DepartemenID = ? AND DokterID = ? AND NA = 'N'
|
|
ORDER BY TrxDepartemenID DESC LIMIT 1 FOR UPDATE`, registration.RegID, registration.DepartmentID, registration.DoctorID).Scan(&transactionID)
|
|
if err == nil {
|
|
return transactionID, nil
|
|
}
|
|
if !errors.Is(err, sql.ErrNoRows) {
|
|
return 0, err
|
|
}
|
|
|
|
result, err := tx.ExecContext(ctx, `
|
|
INSERT INTO trxdepartemen (
|
|
RegID, TrxID, DepartemenID, DokterID, Dokter2, AntrianID, Tanggal,
|
|
KelasID, MataUang, StatusID, LogID, LoginBuat, TanggalBuat, NA
|
|
) VALUES (?, ?, ?, ?, '', 0, ?, ?, 'IDR', 0, 0, ?, ?, 'N')`,
|
|
registration.RegID, registration.RegID, registration.DepartmentID, registration.DoctorID,
|
|
now, "Default", channel, now,
|
|
)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.LastInsertId()
|
|
}
|
|
|
|
type registrationPackageItem struct {
|
|
PackageDepartmentID sql.NullInt64
|
|
ItemDepartmentID sql.NullInt64
|
|
ItemWarehouseID sql.NullInt64
|
|
ItemID sql.NullString
|
|
HeaderID sql.NullInt64
|
|
DepartmentID sql.NullString
|
|
UnitID sql.NullString
|
|
BaseUnitID sql.NullString
|
|
Quantity sql.NullString
|
|
Price sql.NullString
|
|
DiscountType sql.NullString
|
|
Discount sql.NullString
|
|
}
|
|
|
|
func ensureMCUPackageDetails(ctx context.Context, tx *sql.Tx, dispenserID int64, regID, medrecID, packageID, channel, now string) error {
|
|
services, err := findActivePackageServices(ctx, tx, packageID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, service := range services {
|
|
var present int
|
|
err := tx.QueryRowContext(ctx, `
|
|
SELECT EXISTS(
|
|
SELECT 1 FROM paket_dispenser_layanan
|
|
WHERE PaketDispenserID = ? AND LayananID = ? AND NA = 'N'
|
|
)`, dispenserID, service.ServiceID).Scan(&present)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if present != 0 {
|
|
continue
|
|
}
|
|
operationID, err := resolvePackageOperationIDForMCU(ctx, tx, service.HeaderService)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = tx.ExecContext(ctx, `
|
|
INSERT INTO paket_dispenser_layanan (
|
|
PaketDispenserID, PaketDispenserOperasiID, RegID, MEDRECID, PaketID,
|
|
DepartemenID, LayananID, HeaderLayanan, JumlahAwal, Jumlah, JumlahHari,
|
|
Harga, TipeDiskon, Diskon, ShareTipe, ShareRS, ShareDokter, ShareExternal,
|
|
ShareLain, LoginBuat, TanggalBuat, NA
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'N')`,
|
|
dispenserID, operationID, regID, medrecID, packageID, service.DepartmentID, service.ServiceID,
|
|
nullStringValue(service.HeaderService), nullStringValue(service.Quantity), nullStringValue(service.Quantity),
|
|
nullInt64Value(service.Days), nullStringValue(service.Price), nullStringValue(service.DiscountType),
|
|
nullStringValue(service.Discount), nullStringValue(service.ShareType), nullStringValue(service.ShareHospital),
|
|
nullStringValue(service.ShareDoctor), nullStringValue(service.ShareExternal), nullStringValue(service.ShareOther),
|
|
channel, now,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
rows, err := tx.QueryContext(ctx, `
|
|
SELECT PaketDepartemenID, ItemDepartemenID, ItemGudangID, ItemID, HeaderID,
|
|
DepartemenID, SatuanID, SatuanDasarID, Jumlah, Harga, TipeDiskon, Diskon
|
|
FROM paket_item WHERE PaketID = ? AND NA = 'N' ORDER BY PaketItemID`, packageID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
items := make([]registrationPackageItem, 0)
|
|
for rows.Next() {
|
|
var item registrationPackageItem
|
|
if err := rows.Scan(&item.PackageDepartmentID, &item.ItemDepartmentID, &item.ItemWarehouseID, &item.ItemID, &item.HeaderID, &item.DepartmentID, &item.UnitID, &item.BaseUnitID, &item.Quantity, &item.Price, &item.DiscountType, &item.Discount); err != nil {
|
|
rows.Close()
|
|
return err
|
|
}
|
|
items = append(items, item)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
rows.Close()
|
|
return err
|
|
}
|
|
rows.Close()
|
|
for _, item := range items {
|
|
var present int
|
|
if err := tx.QueryRowContext(ctx, `SELECT EXISTS(SELECT 1 FROM paket_dispenser_item WHERE PaketDispenserID = ? AND ItemID = ? AND HeaderID = ? AND NA = 'N')`, dispenserID, nullStringValue(item.ItemID), nullInt64Value(item.HeaderID)).Scan(&present); err != nil {
|
|
return err
|
|
}
|
|
if present != 0 {
|
|
continue
|
|
}
|
|
operationID, err := resolvePackageOperationIDForMCU(ctx, tx, nullStringFromInt(item.HeaderID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := tx.ExecContext(ctx, `
|
|
INSERT INTO paket_dispenser_item (
|
|
PaketDispenserID, PaketDispenserOperasiID, RegID, MEDRECID, PaketID,
|
|
PaketDepartemenID, ItemDepartemenID, ItemGudangID, ItemID, DepartemenID,
|
|
HeaderID, SatuanID, SatuanDasarID, JumlahAwal, Jumlah, Harga, TipeDiskon,
|
|
Diskon, LoginBuat, TanggalBuat, NA
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'N')`,
|
|
dispenserID, operationID, regID, medrecID, packageID, nullInt64Value(item.PackageDepartmentID),
|
|
nullInt64Value(item.ItemDepartmentID), nullInt64Value(item.ItemWarehouseID), nullStringValue(item.ItemID),
|
|
nullStringValue(item.DepartmentID), nullInt64Value(item.HeaderID), nullStringValue(item.UnitID),
|
|
nullStringValue(item.BaseUnitID), nullStringValue(item.Quantity), nullStringValue(item.Quantity),
|
|
nullStringValue(item.Price), nullStringValue(item.DiscountType), nullStringValue(item.Discount), channel, now,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
_, err = tx.ExecContext(ctx, `
|
|
INSERT INTO paket_dispenser_adm (
|
|
PaketAdmID, PaketDispenserID, RegID, PaketID, TipeRI, Hitung, AdmRI,
|
|
AdmRIBaru, TipeDiskonRI, DiskonRI, LoginBuat, TanggalBuat, NA
|
|
)
|
|
SELECT pa.PaketAdmID, ?, ?, pa.PaketID, pa.TipeRI, 'Y', pa.AdmRI,
|
|
pa.AdmRIBaru, pa.TipeDiskonRI, pa.DiskonRI, ?, ?, 'N'
|
|
FROM paket_adm pa
|
|
WHERE pa.PaketID = ? AND pa.NA = 'N'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM paket_dispenser_adm da
|
|
WHERE da.PaketDispenserID = ? AND da.PaketAdmID = pa.PaketAdmID AND da.NA = 'N'
|
|
)
|
|
LIMIT 1`, dispenserID, regID, channel, now, packageID, dispenserID)
|
|
return err
|
|
}
|
|
|
|
func resolvePackageOperationIDForMCU(ctx context.Context, tx *sql.Tx, header sql.NullString) (int64, error) {
|
|
if !header.Valid || strings.TrimSpace(header.String) == "" {
|
|
return 0, nil
|
|
}
|
|
var operationID sql.NullInt64
|
|
err := tx.QueryRowContext(ctx, `SELECT PaketDispenserOperasiID FROM paket_dispenser_operasi_header WHERE PaketOperasiHeaderID = ? LIMIT 1`, header.String).Scan(&operationID)
|
|
if errors.Is(err, sql.ErrNoRows) || !operationID.Valid {
|
|
return 0, nil
|
|
}
|
|
return operationID.Int64, err
|
|
}
|
|
|
|
func nullStringFromInt(value sql.NullInt64) sql.NullString {
|
|
if !value.Valid {
|
|
return sql.NullString{}
|
|
}
|
|
return sql.NullString{String: strconv.FormatInt(value.Int64, 10), Valid: true}
|
|
}
|
|
|
|
func findRegistrationPatient(ctx context.Context, tx *sql.Tx, params RegistrationParams) (MedrecPatient, bool, error) {
|
|
query := medrecPatientSelect + ` WHERE NA = 'N' AND MEDRECID = ? LIMIT 1 FOR UPDATE`
|
|
args := []any{params.MedrecID}
|
|
if strings.TrimSpace(params.MedrecID) == "" {
|
|
query = medrecPatientSelect + ` WHERE NA = 'N' AND JenisNomerSosial = 'KTP' AND NomerSosial = ? AND DATE(TanggalLahir) = ? LIMIT 1 FOR UPDATE`
|
|
args = []any{params.NIK, params.BirthDate.Format("2006-01-02")}
|
|
}
|
|
patient, err := scanMedrecPatient(tx.QueryRowContext(ctx, query, args...))
|
|
if err == sql.ErrNoRows {
|
|
return MedrecPatient{}, false, nil
|
|
}
|
|
return patient, err == nil, err
|
|
}
|
|
|
|
func findExistingRegistration(ctx context.Context, tx *sql.Tx, medrecID string, params RegistrationParams) (RegistrationRecord, bool, error) {
|
|
query := `
|
|
SELECT RegID, MEDRECID, DATE_FORMAT(Tanggal, '%Y-%m-%d'), DepartemenID, DokterID,
|
|
JenisPasienID, JenisRegID, PeriodeTarifID, PerusahaanID, AsuransiID,
|
|
ProviderID, GroupTarifID, NomerPolis, Pulang, BatalDaftar
|
|
FROM regpas
|
|
WHERE MEDRECID = ? AND DATE(Tanggal) = ? AND DepartemenID = ?
|
|
AND Pulang = 'N' AND (BatalDaftar IS NULL OR BatalDaftar IN ('N', '')) AND NA = 'N'`
|
|
args := []any{medrecID, params.RegistrationDate.Format("2006-01-02"), params.DepartmentID}
|
|
if params.DoctorID != "" {
|
|
query += ` AND DokterID = ?`
|
|
args = append(args, params.DoctorID)
|
|
}
|
|
query += ` ORDER BY RegID DESC LIMIT 1 FOR UPDATE`
|
|
|
|
var registration RegistrationRecord
|
|
err := tx.QueryRowContext(ctx, query, args...).Scan(
|
|
®istration.RegID, ®istration.MEDRECID, ®istration.Tanggal, ®istration.DepartmentID,
|
|
®istration.DoctorID, ®istration.PatientTypeID, ®istration.RegistrationID,
|
|
®istration.TariffPeriodID, ®istration.CompanyID, ®istration.InsuranceID,
|
|
®istration.ProviderID, ®istration.GroupTariffID, ®istration.PolicyNumber,
|
|
®istration.Pulang, ®istration.BatalDaftar,
|
|
)
|
|
if err == sql.ErrNoRows {
|
|
return RegistrationRecord{}, false, nil
|
|
}
|
|
return registration, err == nil, err
|
|
}
|
|
|
|
func nextRegistrationID(ctx context.Context, tx *sql.Tx, prefix string) (string, error) {
|
|
var lastID string
|
|
err := tx.QueryRowContext(ctx, `SELECT RegID FROM regpas WHERE RegID LIKE ? ORDER BY RegID DESC LIMIT 1 FOR UPDATE`, prefix+"%").Scan(&lastID)
|
|
if err == sql.ErrNoRows {
|
|
return prefix + "00001", nil
|
|
}
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
number, err := strconv.Atoi(strings.TrimPrefix(lastID, prefix))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return fmt.Sprintf("%s%05d", prefix, number+1), nil
|
|
}
|
|
|
|
func registrationOutcome(statusCode int, success bool, status, message string, data any) RegistrationOutcome {
|
|
return RegistrationOutcome{HTTPStatus: statusCode, Success: success, Status: status, Message: message, Data: data}
|
|
}
|
|
|
|
func firstNonEmpty(values ...string) string {
|
|
for _, value := range values {
|
|
if strings.TrimSpace(value) != "" {
|
|
return value
|
|
}
|
|
}
|
|
return ""
|
|
}
|