diff --git a/internal/merch/repository.go b/internal/merch/repository.go index e5d10ab..9121540 100644 --- a/internal/merch/repository.go +++ b/internal/merch/repository.go @@ -9,6 +9,7 @@ type Repository interface { Origins Prices Tasks + Labels } type repo struct { diff --git a/internal/merch/repository_labels.go b/internal/merch/repository_labels.go new file mode 100644 index 0000000..13752ce --- /dev/null +++ b/internal/merch/repository_labels.go @@ -0,0 +1,182 @@ +package merch + +import ( + "context" + "database/sql" +) + +type Labels interface { + createLabel(ctx context.Context, userId int64, label *Label) error + getLabels(ctx context.Context, userId int64) ([]Label, error) + updateLabel(ctx context.Context, userId int64, label *Label) error + deleteLabel(ctx context.Context, userId int64, labelUuid string, now sql.NullTime) error + + attachLabel(ctx context.Context, userId int64, label *CardLabel) error + detachLabel(ctx context.Context, userId int64, label *CardLabel) error + + getManyAttachedLabelsByList(ctx context.Context, userId int64, list []int64) (map[int64]string, error) + getAttachedLabelsByUuid(ctx context.Context, userId int64, merchUuid string) ([]string, error) +} + +func (r *repo) createLabel(ctx context.Context, userId int64, l *Label) error { + q := ` + INSERT INTO labels (created_at, updated_at, deleted_at, user_id, uuid, name, color, bg_color) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ` + _, err := r.db.Exec(ctx, q, l.CreatedAt, l.UpdatedAt, l.DeletedAt, userId, l.Uuid, l.Name, l.Color, l.BgColor) + if err != nil { + return err + } + + return nil +} + +func (r *repo) getLabels(ctx context.Context, userId int64) ([]Label, error) { + q := ` + SELECT uuid, name, color, bg_color + FROM labels + WHERE user_id = $1 + AND deleted_at IS NULL + ` + + rows, err := r.db.Query(ctx, q, userId) + if err != nil { + return nil, err + } + + var labels []Label + for rows.Next() { + var l Label + if err = rows.Scan(&l.Uuid, &l.Name, &l.Color, &l.BgColor); err != nil { + rows.Close() + return nil, err + } + labels = append(labels, l) + } + + rows.Close() + if err = rows.Err(); err != nil { + return nil, err + } + + return labels, nil +} + +func (r *repo) updateLabel(ctx context.Context, userId int64, l *Label) error { + q := ` + INSERT INTO labels (created_at, updated_at, deleted_at, user_id, uuid, name, color, bg_color) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (uuid) DO UPDATE SET + updated_at = $2, + name = COALESCE(NULLIF(EXCLUDED.name, ''), labels.name), + color = COALESCE(NULLIF(EXCLUDED.color, ''), labels.color), + bg_color = COALESCE(NULLIF(EXCLUDED.bg_color, ''), labels.bg_color) + ` + + _, err := r.db.Exec(ctx, q, l.CreatedAt, l.UpdatedAt, l.DeletedAt, userId, l.Uuid, l.Name, l.Color, l.BgColor) + if err != nil { + return err + } + + return nil +} + +func (r *repo) deleteLabel(ctx context.Context, userId int64, labelUuid string, now sql.NullTime) error { + q := `UPDATE labels SET deleted_at = &1 WHERE user_id = $2 AND uuid = $3` + _, err := r.db.Exec(ctx, q, now, userId, labelUuid) + if err != nil { + return err + } + return nil +} + +func (r *repo) attachLabel(ctx context.Context, userId int64, label *CardLabel) error { + q := ` + INSERT INTO card_labels (user_id, label_id, merch_id) + VALUES ($1, (SELECT id FROM labels WHERE uuid = $2), (SELECT id FROM merch WHERE merch_uuid = $3 AND user_id = $1)) + ` + _, err := r.db.Exec(ctx, q, userId, label.LabelUuid, label.MerchUuid) + if err != nil { + return err + } + return nil +} + +func (r *repo) detachLabel(ctx context.Context, userId int64, label *CardLabel) error { + q := ` + DELETE FROM card_labels + WHERE user_id = $1 + AND label_id = (SELECT id FROM labels WHERE uuid = $2) + AND merch_id = (SELECT id FROM merch WHERE merch_uuid = $3 AND user_id = $1) + ` + _, err := r.db.Exec(ctx, q, userId, label.LabelUuid, label.MerchUuid) + if err != nil { + return err + } + return nil +} + +func (r *repo) getManyAttachedLabelsByList(ctx context.Context, userId int64, list []int64) (map[int64]string, error) { + q := ` + SELECT l.uuid, cl.merch_id + FROM card_labels AS cl + JOIN labels AS l ON cl.label_id = l.id + WHERE cl.user_id = $1 + AND cl.merch_id = ANY($2) + AND l.deleted_at IS NULL + ` + rows, err := r.db.Query(ctx, q, userId, list) + if err != nil { + return nil, err + } + + cardLabelsMap := make(map[int64]string) + + for rows.Next() { + var ( + merchId int64 + labelUuid string + ) + + if err = rows.Scan(&labelUuid, &merchId); err != nil { + rows.Close() + return nil, err + } + cardLabelsMap[merchId] = labelUuid + } + + rows.Close() + if err = rows.Err(); err != nil { + return nil, err + } + + return cardLabelsMap, nil +} + +func (r *repo) getAttachedLabelsByUuid(ctx context.Context, userId int64, merchUuid string) ([]string, error) { + q := ` + SELECT l.uuid + FROM card_labels AS cl + JOIN labels AS l ON cl.label_id = l.id + WHERE cl.merch_id = (SELECT id FROM merch WHERE merch_uuid = $2 AND user_id = $1 AND deleted_at IS NULL) + AND cl.user_id = $1 + AND l.deleted_at IS NULL + ` + + rows, err := r.db.Query(ctx, q, userId, merchUuid) + if err != nil { + return nil, err + } + + var labels []string + for rows.Next() { + var label string + if err = rows.Scan(&label); err != nil { + rows.Close() + return nil, err + } + labels = append(labels, label) + } + + return labels, nil +}