241 lines
5.7 KiB
Go
241 lines
5.7 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
var ErrTarifTableNotFound = errors.New("tarif table not found")
|
|
|
|
type MappingHargaParams struct {
|
|
PeriodeTarifID string
|
|
LayananIDs []string
|
|
Search string
|
|
}
|
|
|
|
type TarifLayanan struct {
|
|
TarifLayananID int64 `json:"TarifLayananID"`
|
|
LayananID *string `json:"LayananID"`
|
|
NamaLayanan *string `json:"NamaLayanan"`
|
|
JenisLayananID *int64 `json:"JenisLayananID"`
|
|
NamaJenisLayanan *string `json:"NamaJenisLayanan"`
|
|
Kelas string `json:"Kelas"`
|
|
NamaKelas string `json:"NamaKelas"`
|
|
Harga *string `json:"Harga"`
|
|
TipeDiskonRJ string `json:"TipeDiskonRJ"`
|
|
DiskonRJ string `json:"DiskonRJ"`
|
|
TipeDiskonRI string `json:"TipeDiskonRI"`
|
|
DiskonRI string `json:"DiskonRI"`
|
|
TipeShare *string `json:"TipeShare"`
|
|
ShareDokter *string `json:"ShareDokter"`
|
|
ShareRS *string `json:"ShareRS"`
|
|
ShareExt *string `json:"ShareExt"`
|
|
ShareLain *string `json:"ShareLain"`
|
|
AsalTarif string `json:"AsalTarif"`
|
|
}
|
|
|
|
type MySQLLayananRepository struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
func NewMySQLLayananRepository(db *sql.DB) MySQLLayananRepository {
|
|
return MySQLLayananRepository{db: db}
|
|
}
|
|
|
|
func (r MySQLLayananRepository) MappingHarga(ctx context.Context, params MappingHargaParams) ([]TarifLayanan, error) {
|
|
tableName := "harga_layanan_" + params.PeriodeTarifID
|
|
|
|
exists, err := r.tableExists(ctx, tableName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !exists {
|
|
return nil, ErrTarifTableNotFound
|
|
}
|
|
|
|
query, args := mappingHargaQuery(tableName, params.LayananIDs, params.Search)
|
|
rows, err := r.db.QueryContext(ctx, query, args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
result := make([]TarifLayanan, 0)
|
|
seenLayananID := map[string]struct{}{}
|
|
|
|
for rows.Next() {
|
|
row, err := scanTarifLayanan(rows)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
layananID := stringValue(row.LayananID)
|
|
if layananID != "" {
|
|
if _, exists := seenLayananID[layananID]; exists {
|
|
continue
|
|
}
|
|
seenLayananID[layananID] = struct{}{}
|
|
}
|
|
|
|
result = append(result, row)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (r MySQLLayananRepository) tableExists(ctx context.Context, tableName string) (bool, error) {
|
|
var count int
|
|
err := r.db.QueryRowContext(ctx, `
|
|
SELECT COUNT(*)
|
|
FROM information_schema.tables
|
|
WHERE table_schema = DATABASE()
|
|
AND table_name = ?
|
|
`, tableName).Scan(&count)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return count > 0, nil
|
|
}
|
|
|
|
func mappingHargaQuery(tableName string, layananIDs []string, search string) (string, []any) {
|
|
args := make([]any, 0, len(layananIDs)+2)
|
|
placeholders := make([]string, 0, len(layananIDs))
|
|
for _, id := range layananIDs {
|
|
placeholders = append(placeholders, "?")
|
|
args = append(args, id)
|
|
}
|
|
|
|
var builder strings.Builder
|
|
builder.WriteString(`
|
|
SELECT
|
|
tarif.HargaLayananID AS TarifLayananID,
|
|
layanan_dept.LayananID,
|
|
layanan.Nama AS NamaLayanan,
|
|
layanan.JenisLayananID,
|
|
jenis.Nama AS NamaJenisLayanan,
|
|
'Default' AS Kelas,
|
|
'Default' AS NamaKelas,
|
|
tarif.Harga,
|
|
'Percentage' AS TipeDiskonRJ,
|
|
'0.00' AS DiskonRJ,
|
|
'Percentage' AS TipeDiskonRI,
|
|
'0.00' AS DiskonRI,
|
|
tarif.ShareTipe AS TipeShare,
|
|
tarif.ShareDokter,
|
|
tarif.ShareRS,
|
|
tarif.ShareExternal AS ShareExt,
|
|
tarif.ShareLain,
|
|
'+Layanan' AS AsalTarif
|
|
FROM layanandepartemen AS layanan_dept
|
|
INNER JOIN `)
|
|
builder.WriteString(tableName)
|
|
builder.WriteString(` AS tarif
|
|
ON tarif.LayananDepartemenID = layanan_dept.LayananDepartemenID
|
|
AND tarif.KelasID = 'Default'
|
|
AND tarif.NA = 'N'
|
|
LEFT JOIN masterlayanan AS layanan
|
|
ON layanan.LayananID = layanan_dept.LayananID
|
|
LEFT JOIN jenislayanan AS jenis
|
|
ON jenis.JenisLayananID = layanan.JenisLayananID
|
|
WHERE layanan_dept.NA = 'N'
|
|
AND layanan_dept.LayananID IN (` + strings.Join(placeholders, ",") + `)
|
|
`)
|
|
|
|
if search != "" {
|
|
like := "%" + search + "%"
|
|
builder.WriteString(`
|
|
AND (
|
|
layanan_dept.LayananID LIKE ?
|
|
OR layanan.Nama LIKE ?
|
|
)
|
|
`)
|
|
args = append(args, like, like)
|
|
}
|
|
|
|
builder.WriteString(`
|
|
ORDER BY layanan.Nama, layanan.JenisLayananID
|
|
`)
|
|
|
|
return builder.String(), args
|
|
}
|
|
|
|
func scanTarifLayanan(rows *sql.Rows) (TarifLayanan, error) {
|
|
var row TarifLayanan
|
|
var layananID sql.NullString
|
|
var namaLayanan sql.NullString
|
|
var jenisLayananID sql.NullInt64
|
|
var namaJenisLayanan sql.NullString
|
|
var harga sql.NullString
|
|
var tipeShare sql.NullString
|
|
var shareDokter sql.NullString
|
|
var shareRS sql.NullString
|
|
var shareExt sql.NullString
|
|
var shareLain sql.NullString
|
|
|
|
err := rows.Scan(
|
|
&row.TarifLayananID,
|
|
&layananID,
|
|
&namaLayanan,
|
|
&jenisLayananID,
|
|
&namaJenisLayanan,
|
|
&row.Kelas,
|
|
&row.NamaKelas,
|
|
&harga,
|
|
&row.TipeDiskonRJ,
|
|
&row.DiskonRJ,
|
|
&row.TipeDiskonRI,
|
|
&row.DiskonRI,
|
|
&tipeShare,
|
|
&shareDokter,
|
|
&shareRS,
|
|
&shareExt,
|
|
&shareLain,
|
|
&row.AsalTarif,
|
|
)
|
|
if err != nil {
|
|
return TarifLayanan{}, fmt.Errorf("scan tarif layanan: %w", err)
|
|
}
|
|
|
|
row.LayananID = nullStringPtr(layananID)
|
|
row.NamaLayanan = nullStringPtr(namaLayanan)
|
|
row.JenisLayananID = nullInt64Ptr(jenisLayananID)
|
|
row.NamaJenisLayanan = nullStringPtr(namaJenisLayanan)
|
|
row.Harga = nullStringPtr(harga)
|
|
row.TipeShare = nullStringPtr(tipeShare)
|
|
row.ShareDokter = nullStringPtr(shareDokter)
|
|
row.ShareRS = nullStringPtr(shareRS)
|
|
row.ShareExt = nullStringPtr(shareExt)
|
|
row.ShareLain = nullStringPtr(shareLain)
|
|
|
|
return row, nil
|
|
}
|
|
|
|
func nullStringPtr(value sql.NullString) *string {
|
|
if !value.Valid {
|
|
return nil
|
|
}
|
|
return &value.String
|
|
}
|
|
|
|
func nullInt64Ptr(value sql.NullInt64) *int64 {
|
|
if !value.Valid {
|
|
return nil
|
|
}
|
|
return &value.Int64
|
|
}
|
|
|
|
func stringValue(value *string) string {
|
|
if value == nil {
|
|
return ""
|
|
}
|
|
return *value
|
|
}
|