package models import ( "database/sql" "database/sql/driver" "encoding/json" "time" ) // NullableInt32 is a custom type to replace sql.NullInt32 for swagger compatibility 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 } // Product represents the data structure for the product table type Product struct { ID string `json:"id" db:"id"` Status string `json:"status" db:"status"` Sort NullableInt32 `json:"sort,omitempty" db:"sort"` UserCreated sql.NullString `json:"user_created,omitempty" db:"user_created"` DateCreated sql.NullTime `json:"date_created,omitempty" db:"date_created"` UserUpdated sql.NullString `json:"user_updated,omitempty" db:"user_updated"` DateUpdated sql.NullTime `json:"date_updated,omitempty" db:"date_updated"` Name sql.NullString `json:"name,omitempty" db:"name"` } // Custom JSON marshaling for Product func (r Product) MarshalJSON() ([]byte, error) { type Alias Product aux := &struct { Sort *int `json:"sort,omitempty"` UserCreated *string `json:"user_created,omitempty"` DateCreated *time.Time `json:"date_created,omitempty"` UserUpdated *string `json:"user_updated,omitempty"` DateUpdated *time.Time `json:"date_updated,omitempty"` Name *string `json:"name,omitempty"` *Alias }{ Alias: (*Alias)(&r), } if r.Sort.Valid { sort := int(r.Sort.Int32) aux.Sort = &sort } if r.UserCreated.Valid { aux.UserCreated = &r.UserCreated.String } if r.DateCreated.Valid { aux.DateCreated = &r.DateCreated.Time } if r.UserUpdated.Valid { aux.UserUpdated = &r.UserUpdated.String } if r.DateUpdated.Valid { aux.DateUpdated = &r.DateUpdated.Time } if r.Name.Valid { aux.Name = &r.Name.String } return json.Marshal(aux) } // Helper methods func (r *Product) GetName() string { if r.Name.Valid { return r.Name.String } return "" } // Response struct for GET by ID type ProductGetByIDResponse struct { Message string `json:"message"` Data *Product `json:"data"` } // Enhanced GET response with pagination and aggregation type ProductGetResponse struct { Message string `json:"message"` Data []Product `json:"data"` Meta MetaResponse `json:"meta"` Summary *AggregateData `json:"summary,omitempty"` } // Request struct for create type ProductCreateRequest struct { Status string `json:"status" validate:"required,oneof=draft active inactive"` Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"` } // Response struct for create type ProductCreateResponse struct { Message string `json:"message"` Data *Product `json:"data"` } // Update request type ProductUpdateRequest struct { ID string `json:"-" validate:"required,uuid4"` // ID dari URL path Status string `json:"status" validate:"required,oneof=draft active inactive"` Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"` } // Response struct for update type ProductUpdateResponse struct { Message string `json:"message"` Data *Product `json:"data"` } // Response struct for delete type ProductDeleteResponse struct { Message string `json:"message"` ID string `json:"id"` } // Metadata for pagination 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 for 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"` LastUpdated *time.Time `json:"last_updated,omitempty"` CreatedToday int `json:"created_today"` UpdatedToday int `json:"updated_today"` } // Error response type ErrorResponse struct { Error string `json:"error"` Code int `json:"code"` Message string `json:"message"` Timestamp time.Time `json:"timestamp"` } // Filter struct for query parameters type ProductFilter struct { Status *string `json:"status,omitempty" form:"status"` Search *string `json:"search,omitempty" form:"search"` DateFrom *time.Time `json:"date_from,omitempty" form:"date_from"` DateTo *time.Time `json:"date_to,omitempty" form:"date_to"` } // Validation constants const ( StatusDraft = "draft" StatusActive = "active" StatusInactive = "inactive" StatusDeleted = "deleted" ) // ValidStatuses for validation 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 }