package models import ( "database/sql" "database/sql/driver" "net/http" "strconv" "time" ) // NullableInt32 - your existing implementation type NullableInt32 struct { Int32 int32 `json:"int32,omitempty"` Valid bool `json:"valid"` } // Scan implements the sql.Scanner interface for NullableInt32 func (n *NullableInt32) Scan(value interface{}) error { var ni sql.NullInt32 if err := ni.Scan(value); err != nil { return err } n.Int32 = ni.Int32 n.Valid = ni.Valid return nil } // Value implements the driver.Valuer interface for NullableInt32 func (n NullableInt32) Value() (driver.Value, error) { if !n.Valid { return nil, nil } return n.Int32, nil } // NullableString provides consistent nullable string handling type NullableString struct { String string `json:"string,omitempty"` Valid bool `json:"valid"` } // Scan implements the sql.Scanner interface for NullableString func (n *NullableString) Scan(value interface{}) error { var ns sql.NullString if err := ns.Scan(value); err != nil { return err } n.String = ns.String n.Valid = ns.Valid return nil } // Value implements the driver.Valuer interface for NullableString func (n NullableString) Value() (driver.Value, error) { if !n.Valid { return nil, nil } return n.String, nil } // NullableTime provides consistent nullable time handling type NullableTime struct { Time time.Time `json:"time,omitempty"` Valid bool `json:"valid"` } // Scan implements the sql.Scanner interface for NullableTime func (n *NullableTime) Scan(value interface{}) error { var nt sql.NullTime if err := nt.Scan(value); err != nil { return err } n.Time = nt.Time n.Valid = nt.Valid return nil } // Value implements the driver.Valuer interface for NullableTime func (n NullableTime) Value() (driver.Value, error) { if !n.Valid { return nil, nil } return n.Time, nil } // Metadata untuk pagination - dioptimalkan type MetaResponse struct { Limit int `json:"limit"` Offset int `json:"offset"` Total int `json:"total"` TotalPages int `json:"total_pages"` CurrentPage int `json:"current_page"` HasNext bool `json:"has_next"` HasPrev bool `json:"has_prev"` } // Aggregate data untuk summary type AggregateData struct { TotalActive int `json:"total_active"` TotalDraft int `json:"total_draft"` TotalInactive int `json:"total_inactive"` ByStatus map[string]int `json:"by_status"` ByDinas map[string]int `json:"by_dinas,omitempty"` ByJenis map[string]int `json:"by_jenis,omitempty"` LastUpdated *time.Time `json:"last_updated,omitempty"` CreatedToday int `json:"created_today"` UpdatedToday int `json:"updated_today"` } // Error response yang konsisten type ErrorResponse struct { Error string `json:"error"` Code int `json:"code"` Message string `json:"message"` Timestamp time.Time `json:"timestamp"` } // BaseRequest contains common fields for all BPJS requests type BaseRequest struct { RequestID string `json:"request_id,omitempty"` Timestamp time.Time `json:"timestamp,omitempty"` } // BaseResponse contains common response fields type BaseResponse struct { Status string `json:"status"` Message string `json:"message,omitempty"` RequestID string `json:"request_id,omitempty"` Timestamp string `json:"timestamp,omitempty"` } // ErrorResponse represents error response structure type ErrorResponseBpjs struct { Status string `json:"status"` Message string `json:"message"` RequestID string `json:"request_id,omitempty"` Errors map[string]interface{} `json:"errors,omitempty"` Code string `json:"code,omitempty"` } // PaginationRequest contains pagination parameters type PaginationRequest struct { Page int `json:"page" validate:"min=1"` Limit int `json:"limit" validate:"min=1,max=100"` SortBy string `json:"sort_by,omitempty"` SortDir string `json:"sort_dir,omitempty" validate:"omitempty,oneof=asc desc"` } // PaginationResponse contains pagination metadata type PaginationResponse struct { CurrentPage int `json:"current_page"` TotalPages int `json:"total_pages"` TotalItems int64 `json:"total_items"` ItemsPerPage int `json:"items_per_page"` HasNext bool `json:"has_next"` HasPrev bool `json:"has_previous"` } // MetaInfo contains additional metadata type MetaInfo struct { Version string `json:"version"` Environment string `json:"environment"` ServerTime string `json:"server_time"` } func GetStatusCodeFromMeta(metaCode interface{}) int { statusCode := http.StatusOK if metaCode != nil { switch v := metaCode.(type) { case string: if code, err := strconv.Atoi(v); err == nil { if code >= 100 && code <= 599 { statusCode = code } else { statusCode = http.StatusInternalServerError } } else { statusCode = http.StatusInternalServerError } case int: if v >= 100 && v <= 599 { statusCode = v } else { statusCode = http.StatusInternalServerError } case float64: code := int(v) if code >= 100 && code <= 599 { statusCode = code } else { statusCode = http.StatusInternalServerError } default: statusCode = http.StatusInternalServerError } } return statusCode } // Validation constants const ( StatusDraft = "draft" StatusActive = "active" StatusInactive = "inactive" StatusDeleted = "deleted" ) // ValidStatuses untuk validasi var ValidStatuses = []string{StatusDraft, StatusActive, StatusInactive} // IsValidStatus helper function func IsValidStatus(status string) bool { for _, validStatus := range ValidStatuses { if status == validStatus { return true } } return false }