package merch import ( "context" "database/sql" ) type Labels interface { createLabel(ctx context.Context, userId int64, label *Label) error getLabels(ctx context.Context, userId int64) ([]LabelsList, 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 *LabelLink) error detachLabel(ctx context.Context, userId int64, label *LabelLink) 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) ([]LabelsList, 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 []LabelsList for rows.Next() { var l LabelsList if err = rows.Scan(&l.LabelUuid, &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 := ` UPDATE labels SET updated_at = $1, name = COALESCE(NULLIF($2, ''), labels.name), color = COALESCE(NULLIF($3, ''), labels.color), bg_color = COALESCE(NULLIF($4, ''), labels.bg_color) WHERE uuid = $5 AND user_id = $6; ` _, err := r.db.Exec(ctx, q, l.UpdatedAt, l.Name, l.Color, l.BgColor, l.Uuid, userId) 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 *LabelLink) 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 *LabelLink) 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] = append(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 }