Files
2025-11-26 07:24:49 +00:00

222 lines
5.7 KiB
Go

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
}