Initial CPONE middleware implementation
This commit is contained in:
240
internal/repository/mysql.go
Normal file
240
internal/repository/mysql.go
Normal file
@@ -0,0 +1,240 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user