Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a860a791e | ||
|
|
55fb837379 |
No files matched your search
@@ -6,6 +6,7 @@ import (
|
||||
models "api-service/internal/models"
|
||||
referenceModels "api-service/internal/models/reference"
|
||||
queryUtils "api-service/internal/utils/query"
|
||||
"api-service/internal/utils/validation"
|
||||
"api-service/pkg/logger"
|
||||
"context"
|
||||
"database/sql"
|
||||
@@ -118,10 +119,37 @@ func (c *InMemoryCache) DeleteByPrefix(prefix string) {
|
||||
type ReferenceHandler struct {
|
||||
db database.Service
|
||||
queryBuilder *queryUtils.QueryBuilder
|
||||
validator *validation.DynamicValidator
|
||||
cache *InMemoryCache
|
||||
}
|
||||
|
||||
|
||||
func NewReferenceHandler() *ReferenceHandler {
|
||||
queryBuilder := queryUtils.NewQueryBuilder(queryUtils.DBTypePostgreSQL).
|
||||
SetAllowedColumns([]string{
|
||||
// tabel ref_service_type -> Penjamin
|
||||
"id","name","active",
|
||||
// tabel ref_payment_type
|
||||
"id","name","active",
|
||||
// tabel visit_type
|
||||
"id","name","description","active","fk_ref_healthcare_status_id",
|
||||
|
||||
// tabel D
|
||||
"id", "status", "sort", "user_created", "date_created",
|
||||
"user_updated", "date_updated", "Jenis", "Pelayanan",
|
||||
"Dinas", "Kelompok_obyek", "Kode_tarif", "Tarif", "Satuan",
|
||||
"Tarif_overtime", "Satuan_overtime", "Rekening_pokok",
|
||||
"Rekening_denda", "Uraian_1", "Uraian_2", "Uraian_3",
|
||||
})
|
||||
|
||||
return &ReferenceHandler{
|
||||
db: referencedb,
|
||||
queryBuilder: queryBuilder,
|
||||
validator: validation.NewDynamicValidator(queryBuilder),
|
||||
cache: NewInMemoryCache(), // Initialize in-memory cache
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// HANDLER ENDPOINTS (READ-ONLY)
|
||||
// =============================================================================
|
||||
@@ -152,7 +180,7 @@ func (h *ReferenceHandler) GetRefServiceType(c *gin.Context) {
|
||||
Fields: []queryUtils.SelectField{
|
||||
{Expression: "rst.id", Alias: "id"},
|
||||
{Expression: "rst.name", Alias: "name"},
|
||||
{Expression: "rst.active", Alias: "medical_record_number"},
|
||||
{Expression: "rst.active", Alias: "status"},
|
||||
},
|
||||
Sort: []queryUtils.SortField{
|
||||
{Column: "rst.name", Order: "ASC"},
|
||||
@@ -200,7 +228,7 @@ func (h *ReferenceHandler) GetRefServiceType(c *gin.Context) {
|
||||
if cachedData, found := h.cache.Get(cacheKey); found {
|
||||
logger.Info("Cache hit for search", map[string]interface{}{"search": search})
|
||||
|
||||
if patients, ok := cachedData.([]referenceModels.RefServiceType); ok {
|
||||
if serviceTypeData, ok := cachedData.([]referenceModels.RefServiceType); ok {
|
||||
var aggregateData *models.AggregateData
|
||||
if c.Query("include_summary") == "true" {
|
||||
fullFilterGroups := []queryUtils.FilterGroup{
|
||||
@@ -216,11 +244,11 @@ func (h *ReferenceHandler) GetRefServiceType(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
meta := h.calculateMeta(query.Limit, query.Offset, len(patients))
|
||||
// meta := h.calculateMeta(query.Limit, query.Offset, len(serviceTypeData))
|
||||
response := referenceModels.RefServiceTypeGetResponse{
|
||||
Message: "Data patient berhasil diambil (dari cache)",
|
||||
Data: patients,
|
||||
Meta: meta,
|
||||
Message: "Data Jenis Layanan berhasil diambil",
|
||||
Data: serviceTypeData,
|
||||
// Meta: meta,
|
||||
}
|
||||
|
||||
if aggregateData != nil {
|
||||
@@ -249,19 +277,19 @@ func (h *ReferenceHandler) GetRefServiceType(c *gin.Context) {
|
||||
}
|
||||
|
||||
// Process results into structured format
|
||||
patients := h.processQueryResultsRST(results)
|
||||
serviceTypeData := h.processQueryResultsRST(results)
|
||||
|
||||
// Get total count for pagination metadata
|
||||
total, err := h.getTotalCount(ctx, dbConn, query)
|
||||
// total, err := h.getTotalCount(ctx, dbConn, query)
|
||||
if err != nil {
|
||||
h.logAndRespondError(c, "Failed to get total count", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Cache results if this was a search query
|
||||
if useCache && len(patients) > 0 {
|
||||
h.cache.Set(cacheKey, patients, 15*time.Minute)
|
||||
logger.Info("Cached search results", map[string]interface{}{"search": search, "count": len(patients)})
|
||||
if useCache && len(serviceTypeData) > 0 {
|
||||
h.cache.Set(cacheKey, serviceTypeData, 15*time.Minute)
|
||||
logger.Info("Cached search results", map[string]interface{}{"search": search, "count": len(serviceTypeData)})
|
||||
}
|
||||
|
||||
// Get aggregate data if requested
|
||||
@@ -275,11 +303,11 @@ func (h *ReferenceHandler) GetRefServiceType(c *gin.Context) {
|
||||
}
|
||||
|
||||
// Build and send response
|
||||
meta := h.calculateMeta(query.Limit, query.Offset, total)
|
||||
// meta := h.calculateMeta(query.Limit, query.Offset, total)
|
||||
response := referenceModels.RefServiceTypeGetResponse{
|
||||
Message: "Data patient berhasil diambil",
|
||||
Data: patients,
|
||||
Meta: meta,
|
||||
Message: "Data Jenis Layanan berhasil diambil",
|
||||
Data: serviceTypeData,
|
||||
// Meta: meta,
|
||||
}
|
||||
|
||||
if aggregateData != nil {
|
||||
@@ -412,7 +440,7 @@ func (h *ReferenceHandler) GetRefPaymentType(c *gin.Context) {
|
||||
}
|
||||
|
||||
// Process results into structured format
|
||||
patients := h.processQueryResultsRST(results)
|
||||
patients := h.processQueryResultsRPT(results)
|
||||
|
||||
// Get total count for pagination metadata
|
||||
total, err := h.getTotalCount(ctx, dbConn, query)
|
||||
@@ -439,7 +467,7 @@ func (h *ReferenceHandler) GetRefPaymentType(c *gin.Context) {
|
||||
|
||||
// Build and send response
|
||||
meta := h.calculateMeta(query.Limit, query.Offset, total)
|
||||
response := referenceModels.RefServiceTypeGetResponse{
|
||||
response := referenceModels.RefPaymentTypeGetResponse{
|
||||
Message: "Data patient berhasil diambil",
|
||||
Data: patients,
|
||||
Meta: meta,
|
||||
|
||||
@@ -6,6 +6,17 @@ import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
|
||||
// tabel reference.ref_visit_status
|
||||
type RefVisitStatus struct {
|
||||
ID int64 `json:"id" db:"id"`
|
||||
Name sql.NullString `json:"name,omitempty" db:"name"`
|
||||
Description sql.NullString `json:"description,omitempty" db:"description"`
|
||||
Active sql.NullBool `json:"active,omitempty" db:"active"`
|
||||
FkRefHealthcareStatusID sql.NullInt64 `json:"fk_ref_healthcare_status_id,omitempty" db:"fk_ref_healthcare_status_id"`
|
||||
}
|
||||
|
||||
|
||||
// table ref_service_type table
|
||||
type RefServiceType struct {
|
||||
ID int64 `json:"id" db:"id"`
|
||||
@@ -178,6 +189,48 @@ func (r *RefHealthcareType) GetActive() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// table ref_healtcare_status table
|
||||
type RefHealthcareStatus struct {
|
||||
ID int64 `json:"id" db:"id"`
|
||||
Name sql.NullString `json:"name,omitempty" db:"name"`
|
||||
Active sql.NullBool `json:"active,omitempty" db:"active"`
|
||||
}
|
||||
|
||||
// Custom JSON marshaling untuk RefHealthcareStatus agar NULL values tidak muncul di response
|
||||
func (r RefHealthcareStatus) MarshalJSON() ([]byte, error) {
|
||||
type Alias RefHealthcareStatus
|
||||
aux := &struct {
|
||||
*Alias
|
||||
Name *string `json:"name,omitempty"`
|
||||
Active *bool `json:"active,omitempty"`
|
||||
}{
|
||||
Alias: (*Alias)(&r),
|
||||
}
|
||||
|
||||
if r.Name.Valid {
|
||||
aux.Name = &r.Name.String
|
||||
}
|
||||
if r.Active.Valid {
|
||||
aux.Active = &r.Active.Bool
|
||||
}
|
||||
|
||||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
func (r *RefHealthcareStatus) GetName() string {
|
||||
if r.Name.Valid {
|
||||
return r.Name.String
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *RefHealthcareStatus) GetActive() bool {
|
||||
if r.Active.Valid {
|
||||
return r.Active.Bool
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Response structs for RefServiceType
|
||||
type RefServiceTypeGetByIDResponse struct {
|
||||
Message string `json:"message"`
|
||||
@@ -187,7 +240,7 @@ type RefServiceTypeGetByIDResponse struct {
|
||||
type RefServiceTypeGetResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data []RefServiceType `json:"data"`
|
||||
Meta models.MetaResponse `json:"meta"`
|
||||
// Meta models.MetaResponse `json:"meta"`
|
||||
Summary *models.AggregateData `json:"summary,omitempty"`
|
||||
}
|
||||
|
||||
@@ -352,4 +405,49 @@ type RefHealthcareTypeDeleteResponse struct {
|
||||
type RefHealthcareTypeFilter struct {
|
||||
Status *string `json:"status,omitempty" form:"status"`
|
||||
Search *string `json:"search,omitempty" form:"search"`
|
||||
}
|
||||
|
||||
|
||||
// Response structs for RefHealthcareStatus
|
||||
type RefHealthcareStatusGetByIDResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data *RefHealthcareStatus `json:"data"`
|
||||
}
|
||||
|
||||
type RefHealthcareStatusGetResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data []RefHealthcareStatus `json:"data"`
|
||||
Meta models.MetaResponse `json:"meta"`
|
||||
Summary *models.AggregateData `json:"summary,omitempty"`
|
||||
}
|
||||
|
||||
type RefHealthcareStatusCreateRequest struct {
|
||||
Name *string `json:"name" validate:"required,min=1,max=20"`
|
||||
Active *bool `json:"active"`
|
||||
}
|
||||
|
||||
type RefHealthcareStatusCreateResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data *RefHealthcareStatus `json:"data"`
|
||||
}
|
||||
|
||||
type RefHealthcareStatusUpdateRequest struct {
|
||||
ID *int `json:"-" validate:"required,min=1"` // Menggunakan *int64 agar selaras dengan tipe ID di model
|
||||
Name *string `json:"name" validate:"required,min=1,max=20"`
|
||||
Active *bool `json:"active"`
|
||||
}
|
||||
|
||||
type RefHealthcareStatusUpdateResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data *RefHealthcareStatus `json:"data"`
|
||||
}
|
||||
|
||||
type RefHealthcareStatusDeleteResponse struct {
|
||||
Message string `json:"message"`
|
||||
ID string `json:"id"` // Format string, biasanya dari path param
|
||||
}
|
||||
|
||||
type RefHealthcareStatusFilter struct {
|
||||
Status *string `json:"status,omitempty" form:"status"`
|
||||
Search *string `json:"search,omitempty" form:"search"`
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
pagesRolpagesHandlers "api-service/internal/handlers/pages"
|
||||
pasienPasienHandlers "api-service/internal/handlers/pasien"
|
||||
patientMspatientHandlers "api-service/internal/handlers/patient"
|
||||
referenceReferenceHandler "api-service/internal/handlers/reference"
|
||||
websocketHandlers "api-service/internal/handlers/websocket"
|
||||
"api-service/internal/middleware"
|
||||
services "api-service/internal/services/auth"
|
||||
@@ -141,6 +142,14 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine {
|
||||
pasienPasienGroup.GET("/by-location", pasienPasienHandler.GetPasienByLocation)
|
||||
}
|
||||
|
||||
referenceReferenceHandler := referenceReferenceHandler.NewReferenceHandler()
|
||||
referenceGroup := v1.Group("/ref")
|
||||
{
|
||||
referenceGroup.GET("/jenisPenjamin", referenceReferenceHandler.GetRefPaymentType)
|
||||
referenceGroup.GET("/jenisPelayanan", referenceReferenceHandler.GetRefServiceType)
|
||||
referenceGroup.GET("/statusReservasi", referenceReferenceHandler.GetRefVisitType)
|
||||
}
|
||||
|
||||
// Rol_pages endpoints
|
||||
pagesRolpagesHandler := pagesRolpagesHandlers.NewRol_pagesHandler()
|
||||
pagesRolpagesGroup := v1.Group("/pages")
|
||||
|
||||
Reference in New Issue
Block a user