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 var g *gorm.DB is_filtering := false 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 { g.Or(fmt.Sprintf("%v::TEXT ILIKE '%%%v%%'", v.Field, d.Req.Search.Value)) is_filtering = true } } } } } if is_filtering { d.DB.Where(g) } //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))) } } } } } } //order if len(d.Req.AdditionalFilter) > 0 { for k, vFilter := range d.Req.AdditionalFilter { for _, v := range coldef { if v.Alias == k { d.DB.Where(fmt.Sprintf("%v=?", v.Field), vFilter) } } } } 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 }