request_list.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package rest_gorm
  2. import (
  3. "fmt"
  4. "reflect"
  5. "git.ali33.ru/fcg-xvii/rest"
  6. "gorm.io/gorm"
  7. "gorm.io/gorm/clause"
  8. )
  9. type List struct {
  10. Conditions rest.ConditionList `json:"Conditions" swagger:"items=$ref:rest.Condition"`
  11. Orders []*rest.Order `json:"Orders" swagger:"items=$ref:rest.Order"`
  12. Offset int `json:"Offset"`
  13. Limit int `json:"Limit"`
  14. }
  15. func (s *List) Prepare() {
  16. if s.Limit <= 0 || s.Limit > 20 {
  17. s.Limit = 20
  18. }
  19. }
  20. func (s *List) Result(pg *gorm.DB, fields rest.FieldNamesList, res any) (count int64, err rest.IErrorArgs) {
  21. s.Prepare()
  22. for i, cond := range s.Conditions {
  23. if !cond.Logic.IsValid() {
  24. err = rest.ErrorFiled(cond.Field, "Unexpected logic")
  25. return
  26. }
  27. if !cond.Operator.IsValid() {
  28. err = rest.ErrorFiled(cond.Field, "Unexpected operator")
  29. return
  30. }
  31. if !fields.Exists(cond.Field) {
  32. err = rest.ErrorFiled(cond.Field, "Unexpected field")
  33. return
  34. }
  35. if cond.Value != nil {
  36. q := fmt.Sprintf("%s %s ?", CamelToSnake(cond.Field), cond.Operator)
  37. if i == 0 || cond.Logic == rest.LogicAND {
  38. pg = pg.Where(q, cond.Value)
  39. } else {
  40. pg = pg.Or(q, cond.Value)
  41. }
  42. } else {
  43. if cond.Operator != "" && cond.Operator != rest.OperatorNot {
  44. err = rest.ErrorFiled(cond.Field, "Expected empty operator or not")
  45. }
  46. q := fmt.Sprintf("%s is %s null", CamelToSnake(cond.Field), cond.Operator)
  47. if i == 0 || cond.Logic == rest.LogicAND {
  48. pg = pg.Where(q)
  49. } else {
  50. pg = pg.Or(q)
  51. }
  52. }
  53. }
  54. // count
  55. if dbRes := pg.Count(&count); dbRes.Error != nil {
  56. err = rest.ErrorFiled("ErrDB", dbRes.Error.Error())
  57. return
  58. }
  59. // offset limit
  60. pg = pg.Offset(s.Offset).Limit(s.Limit)
  61. // orders
  62. for _, order := range s.Orders {
  63. pg = pg.Order(
  64. clause.OrderByColumn{
  65. Column: clause.Column{
  66. Name: CamelToSnake(order.Name),
  67. },
  68. Desc: !order.IsAsc,
  69. },
  70. )
  71. }
  72. if pg = pg.Find(res); pg.Error != nil {
  73. err = rest.ErrorFiled("ErrDB", pg.Error.Error())
  74. return
  75. }
  76. return
  77. }
  78. func toAnySlice(slice any) []any {
  79. v := reflect.ValueOf(slice)
  80. // Check if the input is a slice
  81. if v.Kind() != reflect.Slice {
  82. return nil
  83. }
  84. result := make([]any, v.Len())
  85. for i := 0; i < v.Len(); i++ {
  86. result[i] = v.Index(i).Interface()
  87. }
  88. return result
  89. }
  90. type ResultList struct {
  91. Items []any `json:"Items" rest:"fixed"`
  92. Offset int `json:"Offset" rest:"fixed"`
  93. Limit int `json:"Limit" rest:"fixed"`
  94. Count int64 `json:"Count" rest:"fixed"`
  95. }
  96. func (s *List) ResultAnswer(pg *gorm.DB, fields rest.FieldNamesList, res any, offset, limit int) (*ResultList, rest.IErrorArgs) {
  97. count, err := s.Result(pg, fields, res)
  98. if err != nil {
  99. return nil, err
  100. }
  101. rList := &ResultList{
  102. Items: toAnySlice(res),
  103. Offset: offset,
  104. Limit: limit,
  105. Count: count,
  106. }
  107. return rList, nil
  108. }