first commit
This commit is contained in:
221
internal/models/models.go
Normal file
221
internal/models/models.go
Normal file
@@ -0,0 +1,221 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user