You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
4.7 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package models
  2. import (
  3. "context"
  4. "time"
  5. )
  6. type Task struct {
  7. ID string `json:"id" db:"task_id"`
  8. UserID string `json:"-" db:"user_id"`
  9. ItemID string `json:"itemId" db:"item_id"`
  10. ProjectID string `json:"projectId" db:"project_id"`
  11. ItemAmount int `json:"itemAmount" db:"item_amount"`
  12. Name string `json:"name" db:"name"`
  13. Description string `json:"description" db:"description"`
  14. Icon string `json:"icon" db:"icon"`
  15. Active bool `json:"active" db:"active"`
  16. CreatedTime time.Time `json:"createdTime" db:"created_time"`
  17. EndTime *time.Time `json:"endTime" db:"end_time"`
  18. StatusTag *string `json:"statusTag" db:"status_tag"`
  19. }
  20. func (task *Task) Update(update TaskUpdate) {
  21. if update.ItemID != nil {
  22. task.ItemID = *update.ItemID
  23. }
  24. if update.ItemAmount != nil {
  25. task.ItemAmount = *update.ItemAmount
  26. }
  27. if update.Name != nil {
  28. task.Name = *update.Name
  29. }
  30. if update.Description != nil {
  31. task.Description = *update.Description
  32. }
  33. if update.Active != nil {
  34. task.Active = *update.Active
  35. }
  36. if update.EndTime != nil {
  37. endTimeCopy := update.EndTime.UTC()
  38. task.EndTime = &endTimeCopy
  39. }
  40. if update.ClearEndTime {
  41. task.EndTime = nil
  42. }
  43. if update.StatusTag != nil {
  44. task.StatusTag = update.StatusTag
  45. }
  46. if update.ClearStatusTag {
  47. task.StatusTag = nil
  48. }
  49. if update.ProjectID != nil {
  50. task.ProjectID = *update.ProjectID
  51. }
  52. }
  53. type TaskUpdate struct {
  54. ItemID *string `json:"itemId"`
  55. ItemAmount *int `json:"itemAmount"`
  56. Name *string `json:"name"`
  57. Description *string `json:"description"`
  58. Active *bool `json:"active"`
  59. EndTime *time.Time `json:"endTime"`
  60. ClearEndTime bool `json:"clearEndTime"`
  61. StatusTag *string `json:"statusTag"`
  62. ClearStatusTag bool `json:"clearStatusTag"`
  63. ProjectID *string `json:"projectId"`
  64. }
  65. type TaskLink struct {
  66. TaskID string `json:"taskId" db:"task_id"`
  67. ProjectID string `json:"projectId" db:"project_id"`
  68. }
  69. type TaskWithProject struct {
  70. Task
  71. Project *Project `json:"project,omitempty"`
  72. }
  73. type TaskResult struct {
  74. Task
  75. Item *Item `json:"item"`
  76. Logs []*LogWithSecondaryItem `json:"logs"`
  77. CompletedAmount int `json:"completedAmount"`
  78. Project *Project `json:"project,omitempty"`
  79. }
  80. type TaskFilter struct {
  81. UserID string
  82. Active *bool
  83. Expiring *bool
  84. IDs []string
  85. ItemIDs []string
  86. ProjectIDs []string
  87. }
  88. var taskStatusOrder = []string{"", "to do", "on hold", "completed", "failed", "declined"}
  89. type TaskSorter struct {
  90. Data []*TaskResult
  91. Fields []string
  92. }
  93. func (s *TaskSorter) Valid() bool {
  94. for _, field := range s.Fields {
  95. switch field {
  96. case "name", "-name", "createdTime", "-createdTime", "amount", "-amount", "status", "-status":
  97. default:
  98. return false
  99. }
  100. }
  101. return true
  102. }
  103. func (s TaskSorter) Len() int {
  104. return len(s.Data)
  105. }
  106. func (s TaskSorter) Less(i, j int) bool {
  107. a := s.Data[i]
  108. b := s.Data[j]
  109. for _, field := range s.Fields {
  110. switch field {
  111. case "status", "-status":
  112. as := ""
  113. if a.StatusTag != nil {
  114. as = *a.StatusTag
  115. }
  116. bs := ""
  117. if b.StatusTag != nil {
  118. bs = *b.StatusTag
  119. }
  120. if as != bs {
  121. asi := 1000
  122. bsi := 1000
  123. for i, sn := range taskStatusOrder {
  124. if sn == as {
  125. asi = i
  126. }
  127. if sn == bs {
  128. bsi = i
  129. }
  130. }
  131. if field == "-status" {
  132. return asi > bsi
  133. } else {
  134. return asi < bsi
  135. }
  136. }
  137. case "amount":
  138. if a.ItemAmount != b.ItemAmount {
  139. return a.ItemAmount < b.ItemAmount
  140. }
  141. case "-amount":
  142. if a.ItemAmount != b.ItemAmount {
  143. return a.ItemAmount > b.ItemAmount
  144. }
  145. case "name":
  146. if a.Name != b.Name {
  147. return a.Name < b.Name
  148. }
  149. case "-name":
  150. if a.Name != b.Name {
  151. return a.Name > b.Name
  152. }
  153. case "-time":
  154. return a.CreatedTime.After(b.CreatedTime)
  155. case "time":
  156. return a.CreatedTime.Before(b.CreatedTime)
  157. }
  158. }
  159. return a.CreatedTime.Before(b.CreatedTime)
  160. }
  161. func (s TaskSorter) Swap(i, j int) {
  162. s.Data[i], s.Data[j] = s.Data[j], s.Data[i]
  163. }
  164. type TaskRepository interface {
  165. Find(ctx context.Context, id string) (*Task, error)
  166. List(ctx context.Context, filter TaskFilter) ([]*Task, error)
  167. ListWithLinks(ctx context.Context, filter TaskFilter) ([]*Task, []*TaskLink, error)
  168. Insert(ctx context.Context, task Task) error
  169. Update(ctx context.Context, task Task) error
  170. CreateLink(ctx context.Context, link TaskLink) error
  171. DeleteLink(ctx context.Context, link TaskLink) error
  172. UnlinkTask(ctx context.Context, task Task) error
  173. UnlinkProject(ctx context.Context, project Project) error
  174. Delete(ctx context.Context, task Task) error
  175. }