package repository import ( "context" "database/sql" "fmt" ) type PerusahaanListParams struct { Search string Page int PerPage int } type PerusahaanPage struct { Items []PerusahaanSummary Total int } type PerusahaanSummary struct { PerusahaanID string `json:"PerusahaanID"` KodePerusahaan string `json:"KodePerusahaan"` Nama string `json:"Nama"` } type PerusahaanDetail struct { PerusahaanID string `json:"PerusahaanID"` KodePerusahaan string `json:"KodePerusahaan"` Nama string `json:"Nama"` JenisPerusahaanID int64 `json:"JenisPerusahaanID"` Penjamin string `json:"Penjamin"` Asuransi string `json:"Asuransi"` Provider string `json:"Provider"` COB string `json:"COB"` MataUangID string `json:"MataUangID"` Penanggungjawab *string `json:"Penanggungjawab"` TeleponPenanggungjawab *string `json:"TeleponPenanggungjawab"` EmailPenanggungjawab *string `json:"EmailPenanggungjawab"` Alamat *string `json:"Alamat"` Kota *string `json:"Kota"` KodePos *string `json:"KodePos"` Propinsi *string `json:"Propinsi"` Negara *string `json:"Negara"` Telepon *string `json:"Telepon"` Fax *string `json:"Fax"` Email *string `json:"Email"` Website *string `json:"Website"` NamaBank *string `json:"NamaBank"` NamaRekening *string `json:"NamaRekening"` NomerRekening *string `json:"nomerRekening"` DefaultLamaPembayaran int64 `json:"DefaultLamaPembayaran"` DefaultDiskon string `json:"DefaultDiskon"` PPN string `json:"ppn"` Catatan *string `json:"Catatan"` NPWP *string `json:"NPWP"` FlagDiskon string `json:"FlagDiskon"` VerifikasiBilling string `json:"VerifikasiBilling"` PICMarketing *string `json:"PIC_Marketing"` NA string `json:"NA"` } type PerusahaanGroupTarifDetail struct { PerusahaanID string `json:"PerusahaanID"` KodePerusahaan string `json:"KodePerusahaan"` NamaPerusahaan string `json:"NamaPerusahaan"` GroupTarif []PerusahaanGroupTarif `json:"GroupTarif"` } type PerusahaanGroupTarif struct { GroupTarifID int64 `json:"GroupTarifID"` NamaGroupTarif string `json:"NamaGroupTarif"` TanggalBerlaku string `json:"TanggalBerlaku"` TanggalBerakhir string `json:"TanggalBerakhir"` PeriodeTarifID int64 `json:"PeriodeTarifID"` Keterangan string `json:"Keterangan"` DetailLayanan []PerusahaanGroupTarifLayanan `json:"DetailLayanan"` } type PerusahaanGroupTarifLayanan 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"` } func (r MySQLLayananRepository) ListPerusahaan(ctx context.Context, params PerusahaanListParams) (PerusahaanPage, error) { where := "WHERE NA = 'N'" args := make([]any, 0, 5) if params.Search != "" { where += " AND (Nama LIKE ? OR KodePerusahaan LIKE ? OR PerusahaanID LIKE ?)" like := "%" + params.Search + "%" args = append(args, like, like, like) } var total int if err := r.db.QueryRowContext(ctx, "SELECT COUNT(*) FROM perusahaan "+where, args...).Scan(&total); err != nil { return PerusahaanPage{}, err } queryArgs := append(append([]any{}, args...), params.PerPage, (params.Page-1)*params.PerPage) rows, err := r.db.QueryContext(ctx, `SELECT PerusahaanID, KodePerusahaan, Nama FROM perusahaan `+where+` ORDER BY Nama LIMIT ? OFFSET ?`, queryArgs...) if err != nil { return PerusahaanPage{}, err } defer rows.Close() items := make([]PerusahaanSummary, 0) for rows.Next() { var item PerusahaanSummary if err := rows.Scan(&item.PerusahaanID, &item.KodePerusahaan, &item.Nama); err != nil { return PerusahaanPage{}, err } items = append(items, item) } if err := rows.Err(); err != nil { return PerusahaanPage{}, err } return PerusahaanPage{Items: items, Total: total}, nil } func (r MySQLLayananRepository) GetPerusahaan(ctx context.Context, id string) (*PerusahaanDetail, error) { row := r.db.QueryRowContext(ctx, `SELECT PerusahaanID, KodePerusahaan, Nama, JenisPerusahaanID, Penjamin, Asuransi, Provider, COB, MataUangID, Penanggungjawab, TeleponPenanggungjawab, EmailPenanggungjawab, Alamat, Kota, KodePos, Propinsi, Negara, Telepon, Fax, Email, Website, NamaBank, NamaRekening, NomerRekening, DefaultLamaPembayaran, CAST(DefaultDiskon AS CHAR), CAST(ppn AS CHAR), Catatan, NPWP, FlagDiskon, VerifikasiBilling, PIC_Marketing, NA FROM perusahaan WHERE NA = 'N' AND (PerusahaanID = ? OR KodePerusahaan = ?) LIMIT 1`, id, id) detail, err := scanPerusahaanDetail(row) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, err } return &detail, nil } func (r MySQLLayananRepository) GetPerusahaanGroupTarif(ctx context.Context, id, groupTarifID string) (*PerusahaanGroupTarifDetail, error) { var result PerusahaanGroupTarifDetail err := r.db.QueryRowContext(ctx, `SELECT PerusahaanID, KodePerusahaan, Nama FROM perusahaan WHERE PerusahaanID = ? OR KodePerusahaan = ? LIMIT 1`, id, id). Scan(&result.PerusahaanID, &result.KodePerusahaan, &result.NamaPerusahaan) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, err } query := `SELECT pg.GroupTarifID, CAST(pg.TanggalBerlaku AS CHAR), CAST(pg.TanggalBerakhir AS CHAR), pg.PeriodeTarifID, pg.Keterangan FROM perusahaan_grouptarif pg INNER JOIN perusahaan_tarif pt ON pt.Perusahaan_TarifID = pg.Perusahaan_TarifID WHERE pt.PerusahaanID = ? AND pg.NA = 'N' AND CURDATE() BETWEEN pg.TanggalBerlaku AND pg.TanggalBerakhir` args := []any{result.PerusahaanID} if groupTarifID != "" { query += " AND pg.GroupTarifID = ?" args = append(args, groupTarifID) } query += " ORDER BY pg.Keterangan" rows, err := r.db.QueryContext(ctx, query, args...) if err != nil { return nil, err } defer rows.Close() result.GroupTarif = make([]PerusahaanGroupTarif, 0) for rows.Next() { var group PerusahaanGroupTarif if err := rows.Scan(&group.GroupTarifID, &group.TanggalBerlaku, &group.TanggalBerakhir, &group.PeriodeTarifID, &group.Keterangan); err != nil { return nil, err } if group.Keterangan != "" { group.NamaGroupTarif = group.Keterangan } else { group.NamaGroupTarif = fmt.Sprintf("Group Tarif %d", group.GroupTarifID) } group.DetailLayanan, err = r.perusahaanGroupTarifLayanan(ctx, group.GroupTarifID) if err != nil { return nil, err } result.GroupTarif = append(result.GroupTarif, group) } if err := rows.Err(); err != nil { return nil, err } return &result, nil } func (r MySQLLayananRepository) perusahaanGroupTarifLayanan(ctx context.Context, groupTarifID int64) ([]PerusahaanGroupTarifLayanan, error) { tableName := fmt.Sprintf("perusahaan_tarif_layanan_%d", groupTarifID) exists, err := r.tableExists(ctx, tableName) if err != nil { return nil, err } if !exists { return []PerusahaanGroupTarifLayanan{}, nil } query := fmt.Sprintf(`SELECT tarif.TarifLayananID, tarif.LayananID, layanan.Nama, tarif.JenisLayananID, jenis.Nama, tarif.KelasID, kelas.Nama, CAST(tarif.Harga AS CHAR), tarif.TipeDiskon, CAST(tarif.Diskon AS CHAR), '' AS TipeDiskonRI, '0' AS DiskonRI, tarif.TipeShare, CAST(tarif.ShareDokter AS CHAR), CAST(tarif.ShareRS AS CHAR), CAST(tarif.ShareExternal AS CHAR), CAST(tarif.ShareLain AS CHAR), tarif.AsalTarif FROM %s tarif LEFT JOIN masterlayanan layanan ON layanan.LayananID = tarif.LayananID LEFT JOIN jenislayanan jenis ON jenis.JenisLayananID = tarif.JenisLayananID LEFT JOIN kelas kelas ON kelas.KelasID = tarif.KelasID WHERE tarif.NA = 'N' ORDER BY layanan.Nama, tarif.KelasID`, tableName) rows, err := r.db.QueryContext(ctx, query) if err != nil { return nil, err } defer rows.Close() result := make([]PerusahaanGroupTarifLayanan, 0) for rows.Next() { var item PerusahaanGroupTarifLayanan var namaLayanan, namaJenisLayanan, namaKelas sql.NullString if err := rows.Scan(&item.TarifLayananID, &item.LayananID, &namaLayanan, &item.JenisLayananID, &namaJenisLayanan, &item.Kelas, &namaKelas, &item.Harga, &item.TipeDiskonRJ, &item.DiskonRJ, &item.TipeDiskonRI, &item.DiskonRI, &item.TipeShare, &item.ShareDokter, &item.ShareRS, &item.ShareExt, &item.ShareLain, &item.AsalTarif); err != nil { return nil, err } item.NamaLayanan = nullStringPtr(namaLayanan) item.NamaJenisLayanan = nullStringPtr(namaJenisLayanan) if namaKelas.Valid && namaKelas.String != "" { item.NamaKelas = namaKelas.String } else { item.NamaKelas = item.Kelas } result = append(result, item) } if err := rows.Err(); err != nil { return nil, err } return result, nil } func scanPerusahaanDetail(row interface{ Scan(...any) error }) (PerusahaanDetail, error) { var result PerusahaanDetail var penanggungjawab, teleponPJ, emailPJ, alamat, kota, kodePos, propinsi, negara sql.NullString var telepon, fax, email, website, namaBank, namaRekening, nomerRekening sql.NullString var catatan, npwp, picMarketing sql.NullString err := row.Scan(&result.PerusahaanID, &result.KodePerusahaan, &result.Nama, &result.JenisPerusahaanID, &result.Penjamin, &result.Asuransi, &result.Provider, &result.COB, &result.MataUangID, &penanggungjawab, &teleponPJ, &emailPJ, &alamat, &kota, &kodePos, &propinsi, &negara, &telepon, &fax, &email, &website, &namaBank, &namaRekening, &nomerRekening, &result.DefaultLamaPembayaran, &result.DefaultDiskon, &result.PPN, &catatan, &npwp, &result.FlagDiskon, &result.VerifikasiBilling, &picMarketing, &result.NA) if err != nil { return PerusahaanDetail{}, err } result.Penanggungjawab = nullStringPtr(penanggungjawab) result.TeleponPenanggungjawab = nullStringPtr(teleponPJ) result.EmailPenanggungjawab = nullStringPtr(emailPJ) result.Alamat = nullStringPtr(alamat) result.Kota = nullStringPtr(kota) result.KodePos = nullStringPtr(kodePos) result.Propinsi = nullStringPtr(propinsi) result.Negara = nullStringPtr(negara) result.Telepon = nullStringPtr(telepon) result.Fax = nullStringPtr(fax) result.Email = nullStringPtr(email) result.Website = nullStringPtr(website) result.NamaBank = nullStringPtr(namaBank) result.NamaRekening = nullStringPtr(namaRekening) result.NomerRekening = nullStringPtr(nomerRekening) result.Catatan = nullStringPtr(catatan) result.NPWP = nullStringPtr(npwp) result.PICMarketing = nullStringPtr(picMarketing) return result, nil }