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.

216 lines
5.4 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
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package postgres
  2. import (
  3. "context"
  4. "database/sql"
  5. "github.com/Masterminds/squirrel"
  6. "github.com/gissleh/stufflog/internal/slerrors"
  7. "github.com/gissleh/stufflog/models"
  8. "github.com/jmoiron/sqlx"
  9. )
  10. type taskRepository struct {
  11. db *sqlx.DB
  12. }
  13. func (r *taskRepository) Find(ctx context.Context, id string) (*models.Task, error) {
  14. res := models.Task{}
  15. err := r.db.GetContext(ctx, &res, "SELECT task.*, p.icon FROM task INNER JOIN project AS p ON task.project_id = p.project_id WHERE task_id=$1", id)
  16. if err != nil {
  17. if err == sql.ErrNoRows {
  18. return nil, slerrors.NotFound("Task")
  19. }
  20. return nil, err
  21. }
  22. return &res, nil
  23. }
  24. func (r *taskRepository) List(ctx context.Context, filter models.TaskFilter) ([]*models.Task, error) {
  25. tasks, _, err := r.ListWithLinks(ctx, filter)
  26. return tasks, err
  27. }
  28. func (r *taskRepository) ListWithLinks(ctx context.Context, filter models.TaskFilter) ([]*models.Task, []*models.TaskLink, error) {
  29. type tasksWithLinks struct {
  30. models.Task
  31. LinkedProjectID *string `db:"tl_project_id"`
  32. }
  33. sq := squirrel.Select("task.*", "tl.project_id as tl_project_id", "p.icon").From("task").PlaceholderFormat(squirrel.Dollar)
  34. sq = sq.Where(squirrel.Eq{"task.user_id": filter.UserID})
  35. if filter.Active != nil {
  36. if *filter.Active {
  37. sq = sq.Where(squirrel.Or{
  38. squirrel.Eq{"task.active": true},
  39. squirrel.Eq{"task.status_tag": []string{
  40. "on hold", "to do",
  41. }},
  42. })
  43. } else {
  44. sq = sq.Where(squirrel.And{
  45. squirrel.Eq{"task.active": false},
  46. squirrel.Eq{"task.status_tag": []string{
  47. "failed", "completed", "declined",
  48. }},
  49. })
  50. }
  51. }
  52. if filter.Expiring != nil {
  53. if *filter.Expiring {
  54. sq = sq.Where("task.end_time IS NOT NULL")
  55. } else {
  56. sq = sq.Where("task.end_time IS NULL")
  57. }
  58. }
  59. if filter.IDs != nil {
  60. sq = sq.Where(squirrel.Eq{"task.task_id": filter.IDs})
  61. }
  62. if filter.ItemIDs != nil {
  63. sq = sq.Where(squirrel.Eq{"task.item_id": filter.ItemIDs})
  64. }
  65. if filter.ProjectIDs != nil {
  66. sq = sq.Where(squirrel.Or{
  67. squirrel.Eq{"task.project_id": filter.ProjectIDs},
  68. squirrel.Eq{"tl.project_id": filter.ProjectIDs},
  69. })
  70. }
  71. sq = sq.LeftJoin("task_link AS tl ON task.task_id = tl.task_id")
  72. sq = sq.InnerJoin("project AS p ON task.project_id = p.project_id")
  73. sq = sq.OrderBy("active DESC", "status_tag ASC", "created_time")
  74. query, args, err := sq.ToSql()
  75. if err != nil {
  76. return nil, nil, err
  77. }
  78. rows := make([]tasksWithLinks, 0, 8)
  79. err = r.db.SelectContext(ctx, &rows, query, args...)
  80. if err != nil {
  81. if err == sql.ErrNoRows {
  82. return []*models.Task{}, []*models.TaskLink{}, nil
  83. }
  84. return nil, nil, err
  85. }
  86. added := make(map[string]bool)
  87. tasks := make([]*models.Task, 0, len(rows))
  88. links := make([]*models.TaskLink, 0, len(rows))
  89. for _, row := range rows {
  90. if row.LinkedProjectID != nil {
  91. links = append(links, &models.TaskLink{
  92. TaskID: row.Task.ID,
  93. ProjectID: *row.LinkedProjectID,
  94. })
  95. }
  96. if !added[row.Task.ID] {
  97. task := row.Task
  98. tasks = append(tasks, &task)
  99. added[row.Task.ID] = true
  100. }
  101. }
  102. return tasks, links, nil
  103. }
  104. func (r *taskRepository) Insert(ctx context.Context, task models.Task) error {
  105. _, err := r.db.NamedExecContext(ctx, `
  106. INSERT INTO task (
  107. task_id, user_id, item_id, project_id, item_amount, name, description, active, created_time, end_time, status_tag
  108. ) VALUES (
  109. :task_id, :user_id, :item_id, :project_id, :item_amount, :name, :description, :active, :created_time, :end_time, :status_tag
  110. )
  111. `, &task)
  112. if err != nil {
  113. return err
  114. }
  115. return nil
  116. }
  117. func (r *taskRepository) Update(ctx context.Context, task models.Task) error {
  118. _, err := r.db.NamedExecContext(ctx, `
  119. UPDATE task SET
  120. item_id = :item_id,
  121. item_amount = :item_amount,
  122. name = :name,
  123. description = :description,
  124. active = :active,
  125. end_time = :end_time,
  126. status_tag = :status_tag,
  127. project_id = :project_id
  128. WHERE task_id=:task_id
  129. `, &task)
  130. if err != nil {
  131. return err
  132. }
  133. _, err = r.db.NamedExecContext(ctx, `UPDATE log SET item_id = :item_id WHERE task_id=:task_id`, &task)
  134. if err != nil {
  135. return err
  136. }
  137. return nil
  138. }
  139. func (r *taskRepository) CreateLink(ctx context.Context, link models.TaskLink) error {
  140. _, err := r.db.NamedExecContext(ctx, `
  141. INSERT INTO task_link (project_id, task_id) VALUES (:project_id, :task_id)
  142. ON CONFLICT DO NOTHING
  143. `, &link)
  144. return err
  145. }
  146. func (r *taskRepository) DeleteLink(ctx context.Context, link models.TaskLink) error {
  147. _, err := r.db.NamedExecContext(ctx, `
  148. DELETE FROM task_link WHERE task_id=:task_id AND project_id=:project_id
  149. `, &link)
  150. if err == sql.ErrNoRows {
  151. err = slerrors.NotFound("Link")
  152. }
  153. return err
  154. }
  155. func (r *taskRepository) UnlinkTask(ctx context.Context, task models.Task) error {
  156. _, err := r.db.ExecContext(ctx, `
  157. DELETE FROM task_link WHERE task_id=$1;
  158. `, task.ID)
  159. if err == sql.ErrNoRows {
  160. err = nil
  161. }
  162. return err
  163. }
  164. func (r *taskRepository) UnlinkProject(ctx context.Context, project models.Project) error {
  165. _, err := r.db.ExecContext(ctx, `
  166. DELETE FROM task_link WHERE task_id=$1;
  167. `, project.ID)
  168. if err == sql.ErrNoRows {
  169. err = nil
  170. }
  171. return err
  172. }
  173. func (r *taskRepository) Delete(ctx context.Context, task models.Task) error {
  174. _, err := r.db.ExecContext(ctx, `DELETE FROM task WHERE task_id=$1`, task.ID)
  175. if err != nil {
  176. if err == sql.ErrNoRows {
  177. return slerrors.NotFound("Task")
  178. }
  179. return err
  180. }
  181. _, err = r.db.ExecContext(ctx, `DELETE FROM task_link WHERE task_id=$1`, task.ID)
  182. if err != nil && err != sql.ErrNoRows {
  183. return err
  184. }
  185. return nil
  186. }