From e5b1b407dee0da6a2c004728d9db4a7b75516e90 Mon Sep 17 00:00:00 2001 From: nquidox Date: Wed, 11 Mar 2026 19:32:14 +0300 Subject: [PATCH] zero prices methods --- internal/merch/dto.go | 13 ++++++ internal/merch/repository.go | 83 ++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/internal/merch/dto.go b/internal/merch/dto.go index 89e0218..2d95fe6 100644 --- a/internal/merch/dto.go +++ b/internal/merch/dto.go @@ -62,3 +62,16 @@ type PricesResponse struct { MerchUuid string `json:"merch_uuid"` Origins []OriginWithPrices `json:"origins"` } + +type ZeroPrice struct { + Id int64 `json:"id,omitempty"` + CreatedAt time.Time `json:"created_at,omitempty"` + MerchUuid string `json:"merch_uuid"` + Name string `json:"name"` + Origin string `json:"origin"` +} + +type DeleteZeroPrices struct { + Id int64 `json:"id"` + MerchUuid string `json:"merch_uuid"` +} diff --git a/internal/merch/repository.go b/internal/merch/repository.go index 5e93631..8940d86 100644 --- a/internal/merch/repository.go +++ b/internal/merch/repository.go @@ -42,6 +42,10 @@ type Prices interface { insertPrices(ctx context.Context, prices []Price) error getPricesWithDays(ctx context.Context, userId int64, days time.Time) ([]Price, error) getDistinctPrices(ctx context.Context, userId int64, merchUuid string, days time.Time) ([]Price, error) + + getZeroPrices(ctx context.Context, userId int64) ([]ZeroPrice, error) + deleteZeroPricesPeriod(ctx context.Context, userId int64, start, end time.Time, now sql.NullTime) error + deleteZeroPrices(ctx context.Context, now sql.NullTime, list []int64) error } type Tasks interface { @@ -469,3 +473,82 @@ func (r *repo) getDistinctPrices(ctx context.Context, userId int64, merchUuid st } return result, nil } + +func (r *repo) getZeroPrices(ctx context.Context, userId int64) ([]ZeroPrice, error) { + q := ` + WITH price_with_neighbors AS ( + SELECT + p.id, p.created_at, p.merch_id, p.price, p.origin_id, m.name, + LAG(price) OVER (PARTITION BY p.merch_id, p.origin_id ORDER BY p.created_at, p.id) AS prev_price, + LEAD(price) OVER (PARTITION BY p.merch_id, p.origin_id ORDER BY p.created_at, p.id) AS next_price + FROM merch_prices AS p + JOIN merch as m ON m.id = p.merch_id + WHERE p.deleted_at IS NULL + AND m.deleted_at IS NULL + AND m.user_id = 3) + + SELECT + pwn.id, pwn.created_at, pwn.merch_uuid, pwn.name, mo.name + FROM price_with_neighbors AS pwn + JOIN merch_origins AS mo ON mo.id = pwn.origin_id + WHERE + pwn.price = 0 + AND pwn.prev_price IS NOT NULL + AND pwn.prev_price > 0 + AND pwn.next_price IS NOT NULL + AND pwn.next_price > 0 + ORDER BY pwn.created_at DESC + ` + + rows, err := r.db.Query(ctx, q, userId) + if err != nil { + return nil, err + } + + var zeroPrices []ZeroPrice + for rows.Next() { + var p ZeroPrice + if err = rows.Scan(&p.Id, &p.CreatedAt, &p.MerchUuid, &p.Name, &p.Origin); err != nil { + rows.Close() + return nil, err + } + zeroPrices = append(zeroPrices, p) + } + + rows.Close() + if err = rows.Err(); err != nil { + return nil, err + } + + return zeroPrices, nil +} + +func (r *repo) deleteZeroPricesPeriod(ctx context.Context, userId int64, start, end time.Time, now sql.NullTime) error { + q := ` + UPDATE merch_prices + SET deleted_at = $1 + FROM merch + WHERE merch_prices.merch_id = merch.id + AND merch.user_id = $2 + AND merch_prices.price = 0 + AND merch_prices.deleted_at IS NULL + AND merch_prices.created_at BETWEEN $3 AND $4; + ` + + _, err := r.db.Exec(ctx, q, now, userId, start, end) + if err != nil { + return err + } + + return nil +} + +func (r *repo) deleteZeroPrices(ctx context.Context, now sql.NullTime, list []int64) error { + q := `UPDATE merch_prices SET deleted_at = $1 WHERE id IN $2` + + _, err := r.db.Exec(ctx, q, now, list) + if err != nil { + return err + } + return nil +}