package retribusi import ( "api-service/internal/models" "database/sql" "encoding/json" "time" "gorm.io/gorm" ) // Retribusi represents the data structure for the retribusi table // with proper null handling and optimized JSON marshaling type Retribusi struct { gorm.Model ID string `json:"id" gorm:"column:id;primaryKey;type:varchar(255)"` Status string `json:"status" gorm:"column:status;type:varchar(50);not null"` Sort sql.NullInt32 `json:"sort,omitempty" gorm:"column:sort"` UserCreated sql.NullString `json:"user_created,omitempty" gorm:"column:user_created"` DateCreated sql.NullTime `json:"date_created,omitempty" gorm:"column:date_created"` UserUpdated sql.NullString `json:"user_updated,omitempty" gorm:"column:user_updated"` DateUpdated sql.NullTime `json:"date_updated,omitempty" gorm:"column:date_updated"` Jenis sql.NullString `json:"jenis,omitempty" gorm:"column:Jenis"` Pelayanan sql.NullString `json:"pelayanan,omitempty" gorm:"column:Pelayanan"` Dinas sql.NullString `json:"dinas,omitempty" gorm:"column:Dinas"` KelompokObyek sql.NullString `json:"kelompok_obyek,omitempty" gorm:"column:Kelompok_obyek"` KodeTarif sql.NullString `json:"kode_tarif,omitempty" gorm:"column:Kode_tarif"` Tarif sql.NullString `json:"tarif,omitempty" gorm:"column:Tarif"` Satuan sql.NullString `json:"satuan,omitempty" gorm:"column:Satuan"` TarifOvertime sql.NullString `json:"tarif_overtime,omitempty" gorm:"column:Tarif_overtime"` SatuanOvertime sql.NullString `json:"satuan_overtime,omitempty" gorm:"column:Satuan_overtime"` RekeningPokok sql.NullString `json:"rekening_pokok,omitempty" gorm:"column:Rekening_pokok"` RekeningDenda sql.NullString `json:"rekening_denda,omitempty" gorm:"column:Rekening_denda"` Uraian1 sql.NullString `json:"uraian_1,omitempty" gorm:"column:Uraian_1"` Uraian2 sql.NullString `json:"uraian_2,omitempty" gorm:"column:Uraian_2"` Uraian3 sql.NullString `json:"uraian_3,omitempty" gorm:"column:Uraian_3"` } // Custom JSON marshaling untuk Retribusi agar NULL values tidak muncul di response func (r Retribusi) MarshalJSON() ([]byte, error) { type Alias Retribusi 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"` Jenis *string `json:"jenis,omitempty"` Pelayanan *string `json:"pelayanan,omitempty"` Dinas *string `json:"dinas,omitempty"` KelompokObyek *string `json:"kelompok_obyek,omitempty"` KodeTarif *string `json:"kode_tarif,omitempty"` Tarif *string `json:"tarif,omitempty"` Satuan *string `json:"satuan,omitempty"` TarifOvertime *string `json:"tarif_overtime,omitempty"` SatuanOvertime *string `json:"satuan_overtime,omitempty"` RekeningPokok *string `json:"rekening_pokok,omitempty"` RekeningDenda *string `json:"rekening_denda,omitempty"` Uraian1 *string `json:"uraian_1,omitempty"` Uraian2 *string `json:"uraian_2,omitempty"` Uraian3 *string `json:"uraian_3,omitempty"` *Alias }{ Alias: (*Alias)(&r), } // Convert NullableInt32 to pointer 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.Jenis.Valid { aux.Jenis = &r.Jenis.String } if r.Pelayanan.Valid { aux.Pelayanan = &r.Pelayanan.String } if r.Dinas.Valid { aux.Dinas = &r.Dinas.String } if r.KelompokObyek.Valid { aux.KelompokObyek = &r.KelompokObyek.String } if r.KodeTarif.Valid { aux.KodeTarif = &r.KodeTarif.String } if r.Tarif.Valid { aux.Tarif = &r.Tarif.String } if r.Satuan.Valid { aux.Satuan = &r.Satuan.String } if r.TarifOvertime.Valid { aux.TarifOvertime = &r.TarifOvertime.String } if r.SatuanOvertime.Valid { aux.SatuanOvertime = &r.SatuanOvertime.String } if r.RekeningPokok.Valid { aux.RekeningPokok = &r.RekeningPokok.String } if r.RekeningDenda.Valid { aux.RekeningDenda = &r.RekeningDenda.String } if r.Uraian1.Valid { aux.Uraian1 = &r.Uraian1.String } if r.Uraian2.Valid { aux.Uraian2 = &r.Uraian2.String } if r.Uraian3.Valid { aux.Uraian3 = &r.Uraian3.String } return json.Marshal(aux) } // Helper methods untuk mendapatkan nilai yang aman func (r *Retribusi) GetJenis() string { if r.Jenis.Valid { return r.Jenis.String } return "" } func (r *Retribusi) GetDinas() string { if r.Dinas.Valid { return r.Dinas.String } return "" } func (r *Retribusi) GetTarif() string { if r.Tarif.Valid { return r.Tarif.String } return "" } // Response struct untuk GET by ID - diperbaiki struktur type RetribusiGetByIDResponse struct { Message string `json:"message"` Data *Retribusi `json:"data"` } // Request struct untuk create - dioptimalkan dengan validasi type RetribusiCreateRequest struct { Status string `json:"status" validate:"required,oneof=draft active inactive"` Jenis *string `json:"jenis,omitempty" validate:"omitempty,min=1,max=255"` Pelayanan *string `json:"pelayanan,omitempty" validate:"omitempty,min=1,max=255"` Dinas *string `json:"dinas,omitempty" validate:"omitempty,min=1,max=255"` KelompokObyek *string `json:"kelompok_obyek,omitempty" validate:"omitempty,min=1,max=255"` KodeTarif *string `json:"kode_tarif,omitempty" validate:"omitempty,min=1,max=255"` Uraian1 *string `json:"uraian_1,omitempty"` Uraian2 *string `json:"uraian_2,omitempty"` Uraian3 *string `json:"uraian_3,omitempty"` Tarif *string `json:"tarif,omitempty" validate:"omitempty,numeric"` Satuan *string `json:"satuan,omitempty" validate:"omitempty,min=1,max=255"` TarifOvertime *string `json:"tarif_overtime,omitempty" validate:"omitempty,numeric"` SatuanOvertime *string `json:"satuan_overtime,omitempty" validate:"omitempty,min=1,max=255"` RekeningPokok *string `json:"rekening_pokok,omitempty" validate:"omitempty,min=1,max=255"` RekeningDenda *string `json:"rekening_denda,omitempty" validate:"omitempty,min=1,max=255"` } // Response struct untuk create type RetribusiCreateResponse struct { Message string `json:"message"` Data *Retribusi `json:"data"` } // Update request - sama seperti create tapi dengan ID type RetribusiUpdateRequest struct { ID string `json:"-" validate:"required,uuid4"` // ID dari URL path Status string `json:"status" validate:"required,oneof=draft active inactive"` Jenis *string `json:"jenis,omitempty" validate:"omitempty,min=1,max=255"` Pelayanan *string `json:"pelayanan,omitempty" validate:"omitempty,min=1,max=255"` Dinas *string `json:"dinas,omitempty" validate:"omitempty,min=1,max=255"` KelompokObyek *string `json:"kelompok_obyek,omitempty" validate:"omitempty,min=1,max=255"` KodeTarif *string `json:"kode_tarif,omitempty" validate:"omitempty,min=1,max=255"` Uraian1 *string `json:"uraian_1,omitempty"` Uraian2 *string `json:"uraian_2,omitempty"` Uraian3 *string `json:"uraian_3,omitempty"` Tarif *string `json:"tarif,omitempty" validate:"omitempty,numeric"` Satuan *string `json:"satuan,omitempty" validate:"omitempty,min=1,max=255"` TarifOvertime *string `json:"tarif_overtime,omitempty" validate:"omitempty,numeric"` SatuanOvertime *string `json:"satuan_overtime,omitempty" validate:"omitempty,min=1,max=255"` RekeningPokok *string `json:"rekening_pokok,omitempty" validate:"omitempty,min=1,max=255"` RekeningDenda *string `json:"rekening_denda,omitempty" validate:"omitempty,min=1,max=255"` } // Response struct untuk update type RetribusiUpdateResponse struct { Message string `json:"message"` Data *Retribusi `json:"data"` } // Response struct untuk delete type RetribusiDeleteResponse struct { Message string `json:"message"` ID string `json:"id"` } // Enhanced GET response dengan pagination dan aggregation type RetribusiGetResponse struct { Message string `json:"message"` Data []Retribusi `json:"data"` Meta models.MetaResponse `json:"meta"` Summary *models.AggregateData `json:"summary,omitempty"` } // Filter struct untuk query parameters type RetribusiFilter struct { Status *string `json:"status,omitempty" form:"status"` Jenis *string `json:"jenis,omitempty" form:"jenis"` Dinas *string `json:"dinas,omitempty" form:"dinas"` KelompokObyek *string `json:"kelompok_obyek,omitempty" form:"kelompok_obyek"` 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"` }