All checks were successful
Deploy Smart Search Backend Test / deploy (push) Successful in 1m44s
244 lines
7.4 KiB
Go
244 lines
7.4 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
|
|
"git.techease.ru/Smart-search/smart-search-back/internal/model"
|
|
errs "git.techease.ru/Smart-search/smart-search-back/pkg/errors"
|
|
sq "github.com/Masterminds/squirrel"
|
|
"github.com/google/uuid"
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
type requestRepository struct {
|
|
pool *pgxpool.Pool
|
|
qb sq.StatementBuilderType
|
|
}
|
|
|
|
func NewRequestRepository(pool *pgxpool.Pool) RequestRepository {
|
|
return &requestRepository{
|
|
pool: pool,
|
|
qb: sq.StatementBuilder.PlaceholderFormat(sq.Dollar),
|
|
}
|
|
}
|
|
|
|
func (r *requestRepository) Create(ctx context.Context, req *model.Request) error {
|
|
query := r.qb.Insert("requests_for_suppliers").Columns(
|
|
"user_id", "request_txt",
|
|
).Values(
|
|
req.UserID, req.RequestTxt,
|
|
).Suffix("RETURNING id, created_at")
|
|
|
|
sqlQuery, args, err := query.ToSql()
|
|
if err != nil {
|
|
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
|
}
|
|
|
|
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&req.ID, &req.CreatedAt)
|
|
if err != nil {
|
|
return errs.NewInternalError(errs.DatabaseError, "failed to create request", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *requestRepository) UpdateWithTZ(ctx context.Context, id uuid.UUID, tz string, generated bool) error {
|
|
return r.updateWithTZExecutor(ctx, r.pool, id, tz, generated)
|
|
}
|
|
|
|
func (r *requestRepository) UpdateWithTZTx(ctx context.Context, tx pgx.Tx, id uuid.UUID, tz string, generated bool) error {
|
|
return r.updateWithTZExecutor(ctx, tx, id, tz, generated)
|
|
}
|
|
|
|
func (r *requestRepository) updateWithTZExecutor(ctx context.Context, exec DBTX, id uuid.UUID, tz string, generated bool) error {
|
|
query := r.qb.Update("requests_for_suppliers").
|
|
Set("final_tz", tz).
|
|
Set("generated_tz", generated).
|
|
Set("generated_final_tz", generated).
|
|
Where(sq.Eq{"id": id})
|
|
|
|
sqlQuery, args, err := query.ToSql()
|
|
if err != nil {
|
|
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
|
}
|
|
|
|
_, err = exec.Exec(ctx, sqlQuery, args...)
|
|
if err != nil {
|
|
return errs.NewInternalError(errs.DatabaseError, "failed to update request", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *requestRepository) UpdateFinalTZ(ctx context.Context, id uuid.UUID, finalTZ string) error {
|
|
query := r.qb.Update("requests_for_suppliers").
|
|
Set("final_update_tz", finalTZ).
|
|
Where(sq.Eq{"id": id})
|
|
|
|
sqlQuery, args, err := query.ToSql()
|
|
if err != nil {
|
|
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
|
}
|
|
|
|
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
|
if err != nil {
|
|
return errs.NewInternalError(errs.DatabaseError, "failed to update final TZ", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *requestRepository) GetByUserID(ctx context.Context, userID int) ([]*model.Request, error) {
|
|
query := r.qb.Select(
|
|
"r.id", "r.request_txt", "ms.status_name as mailing_status",
|
|
).From("requests_for_suppliers r").
|
|
Join("mailling_status ms ON r.mailling_status_id = ms.id").
|
|
Where(sq.Eq{"r.user_id": userID}).
|
|
OrderBy("r.created_at DESC")
|
|
|
|
sqlQuery, args, err := query.ToSql()
|
|
if err != nil {
|
|
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
|
}
|
|
|
|
rows, err := r.pool.Query(ctx, sqlQuery, args...)
|
|
if err != nil {
|
|
return nil, errs.NewInternalError(errs.DatabaseError, "failed to get requests", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var requests []*model.Request
|
|
for rows.Next() {
|
|
req := &model.Request{}
|
|
var statusName string
|
|
err := rows.Scan(&req.ID, &req.RequestTxt, &statusName)
|
|
if err != nil {
|
|
return nil, errs.NewInternalError(errs.DatabaseError, "failed to scan request", err)
|
|
}
|
|
requests = append(requests, req)
|
|
}
|
|
|
|
return requests, nil
|
|
}
|
|
|
|
func (r *requestRepository) GetByID(ctx context.Context, id uuid.UUID) (*model.Request, error) {
|
|
query := r.qb.Select(
|
|
"id", "user_id", "request_txt", "generated_tz", "final_tz",
|
|
"generated_final_tz", "final_update_tz", "mailling_status_id", "created_at",
|
|
).From("requests_for_suppliers").Where(sq.Eq{"id": id})
|
|
|
|
sqlQuery, args, err := query.ToSql()
|
|
if err != nil {
|
|
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
|
}
|
|
|
|
req := &model.Request{}
|
|
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(
|
|
&req.ID, &req.UserID, &req.RequestTxt, &req.GeneratedTZ,
|
|
&req.FinalTZ, &req.GeneratedFinalTZ, &req.FinalUpdateTZ,
|
|
&req.MailingStatusID, &req.CreatedAt,
|
|
)
|
|
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return nil, errs.NewBusinessError(errs.RequestNotFound, "request not found")
|
|
}
|
|
if err != nil {
|
|
return nil, errs.NewInternalError(errs.DatabaseError, "failed to get request", err)
|
|
}
|
|
|
|
return req, nil
|
|
}
|
|
|
|
func (r *requestRepository) GetDetailByID(ctx context.Context, id uuid.UUID) (*model.RequestDetail, error) {
|
|
query := r.qb.Select(
|
|
"r.id AS request_id",
|
|
"r.request_txt AS title",
|
|
"r.final_update_tz AS mail_text",
|
|
`COALESCE(json_agg(
|
|
json_build_object(
|
|
'email', COALESCE(s.email, ''),
|
|
'phone', COALESCE(s.phone, ''),
|
|
'company_name', COALESCE(s.name, ''),
|
|
'company_id', s.id,
|
|
'url', COALESCE(s.url, '')
|
|
)
|
|
) FILTER (WHERE s.id IS NOT NULL), '[]') AS suppliers`,
|
|
).From("requests_for_suppliers r").
|
|
LeftJoin("suppliers s ON s.request_id = r.id").
|
|
Where(sq.Eq{"r.id": id}).
|
|
GroupBy("r.id", "r.request_txt", "r.final_update_tz")
|
|
|
|
sqlQuery, args, err := query.ToSql()
|
|
if err != nil {
|
|
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
|
}
|
|
|
|
detail := &model.RequestDetail{}
|
|
var suppliersJSON []byte
|
|
|
|
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(
|
|
&detail.RequestID, &detail.Title, &detail.MailText, &suppliersJSON,
|
|
)
|
|
|
|
if err == pgx.ErrNoRows {
|
|
return nil, errs.NewBusinessError(errs.RequestNotFound, "request not found")
|
|
}
|
|
if err != nil {
|
|
return nil, errs.NewInternalError(errs.DatabaseError, "failed to get request detail", err)
|
|
}
|
|
|
|
if len(suppliersJSON) > 0 && string(suppliersJSON) != "[]" {
|
|
if err := json.Unmarshal(suppliersJSON, &detail.Suppliers); err != nil {
|
|
return nil, errs.NewInternalError(errs.DatabaseError, "failed to parse suppliers", err)
|
|
}
|
|
}
|
|
|
|
return detail, nil
|
|
}
|
|
|
|
func (r *requestRepository) GetUserStatistics(ctx context.Context, userID int) (requestsCount, suppliersCount, createdTZ int, err error) {
|
|
query := r.qb.Select(
|
|
"COUNT(DISTINCT r.id) AS requests_count",
|
|
"COUNT(s.id) AS suppliers_count",
|
|
"COUNT(DISTINCT CASE WHEN r.request_txt IS NOT NULL THEN r.id END) AS created_tz",
|
|
).From("requests_for_suppliers r").
|
|
LeftJoin("suppliers s ON s.request_id = r.id").
|
|
Where(sq.Eq{"r.user_id": userID})
|
|
|
|
sqlQuery, args, err := query.ToSql()
|
|
if err != nil {
|
|
return 0, 0, 0, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
|
}
|
|
|
|
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&requestsCount, &suppliersCount, &createdTZ)
|
|
if err != nil {
|
|
return 0, 0, 0, errs.NewInternalError(errs.DatabaseError, "failed to get statistics", err)
|
|
}
|
|
|
|
return requestsCount, suppliersCount, createdTZ, nil
|
|
}
|
|
|
|
func (r *requestRepository) CheckOwnership(ctx context.Context, requestID uuid.UUID, userID int) (bool, error) {
|
|
query := r.qb.Select("1").From("requests_for_suppliers").
|
|
Where(sq.Eq{"id": requestID, "user_id": userID})
|
|
|
|
sqlQuery, args, err := query.ToSql()
|
|
if err != nil {
|
|
return false, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
|
}
|
|
|
|
var exists int
|
|
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&exists)
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return false, nil
|
|
}
|
|
if err != nil {
|
|
return false, errs.NewInternalError(errs.DatabaseError, "failed to check ownership", err)
|
|
}
|
|
|
|
return true, nil
|
|
}
|