package datatable import ( "cargo-erp-backend/internal/handlers/dto" "fmt" "strings" "gorm.io/gorm" ) type DatatableInterface interface { Render(coldef []dto.DataTableColDef) dto.DataTableResponse } type Datatable struct { DB *gorm.DB Req dto.DataTableRequest } func NewDatatable(db *gorm.DB, table_request dto.DataTableRequest) DatatableInterface { return &Datatable{ DB: db, Req: table_request, } } func (d *Datatable) SetTable(db *gorm.DB) { d.DB = db } func (d *Datatable) Render(coldef []dto.DataTableColDef) dto.DataTableResponse { var totaldata int64 = 0 d.DB.Count(&totaldata) //select selectAlias := make([]string, 0) for _, v := range coldef { selectAlias = append(selectAlias, fmt.Sprintf("%v AS %v", v.Field, v.Alias)) } d.DB.Select(selectAlias) //global filter if len(d.Req.Search.Value) > 0 { for _, vcol := range d.Req.Columns { if vcol.Searchable { for _, v := range coldef { if v.Alias == vcol.Data { d.DB.Or(fmt.Sprintf("%v::TEXT ILIKE '%%%v%%'", v.Field, d.Req.Search.Value)) } } } } } //order if len(d.Req.Order) > 0 { for _, vOrder := range d.Req.Order { for _, vcol := range d.Req.Columns { if vcol.Orderable && vOrder.Column == vcol.Data { for _, v := range coldef { if v.Alias == vcol.Data { d.DB.Order(fmt.Sprintf("%v %v", v.Field, strings.ToUpper(vOrder.Dir))) } } } } } } var totalFiltered int64 = 0 d.DB.Count(&totalFiltered) start := d.Req.Start if start == 0 { start = 1 } limit := d.Req.Length d.DB.Limit(limit).Offset(start*limit - limit) output := make([]map[string]interface{}, 0) d.DB.Scan(&output) for _, voutput := range output { for kv, vv := range voutput { for _, v := range coldef { if v.Alias == kv { if v.Formatter != nil { voutput[kv] = v.Formatter(voutput, vv) } } } } } result := dto.DataTableResponse{ Draw: 1, RecordsTotal: totaldata, RecordsFiltered: totalFiltered, Data: output, } return result }