210 lines
5.1 KiB
Go
210 lines
5.1 KiB
Go
package merch
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
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, userId int64, now sql.NullTime, list []int64) error
|
|
}
|
|
|
|
func (r *repo) insertPrices(ctx context.Context, prices []Price) error {
|
|
q := `
|
|
INSERT INTO merch_prices (created_at, updated_at, merch_id, origin_id, price)
|
|
SELECT $1, $2, src.merch_id, src.origin_id, src.price
|
|
FROM UNNEST(
|
|
$3::bigint[],
|
|
$4::bigint[],
|
|
$5::int[]
|
|
) AS src (merch_id, origin_id, price)
|
|
`
|
|
|
|
var (
|
|
merchIds []int64
|
|
originIds []int64
|
|
priceValues []int
|
|
)
|
|
|
|
for _, price := range prices {
|
|
merchIds = append(merchIds, price.MerchId)
|
|
originIds = append(originIds, price.OriginId)
|
|
priceValues = append(priceValues, price.Price)
|
|
}
|
|
|
|
_, err := r.db.Exec(ctx, q, merchIds, originIds, priceValues)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *repo) getPricesWithDays(ctx context.Context, userId int64, days time.Time) ([]Price, error) {
|
|
q := `
|
|
SELECT mp.created_at, mp.merch_id, mp.price, mp.origin_id
|
|
FROM merch_prices AS mp
|
|
JOIN merch AS m ON m.id = mp.merch_id
|
|
WHERE m.user_id = $1
|
|
AND mp.created_at > $2
|
|
AND mp.deleted_at IS NULL
|
|
AND m.deleted_at IS NULL
|
|
`
|
|
|
|
rows, err := r.db.Query(ctx, q, userId, days)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var result []Price
|
|
for rows.Next() {
|
|
var p Price
|
|
if err = rows.Scan(&p.CreatedAt, &p.MerchId, &p.Price, &p.OriginId); err != nil {
|
|
rows.Close()
|
|
return nil, err
|
|
}
|
|
result = append(result, p)
|
|
}
|
|
rows.Close()
|
|
|
|
if err = rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (r *repo) getDistinctPrices(ctx context.Context, userId int64, merchUuid string, days time.Time) ([]Price, error) {
|
|
q := `
|
|
SELECT price, created_at, origin_id
|
|
FROM (
|
|
SELECT DISTINCT ON (price) price, created_at, origin_id
|
|
FROM merch_prices
|
|
WHERE merch_id = (
|
|
SELECT id
|
|
FROM merch
|
|
WHERE merch_uuid = $1
|
|
AND user_id = $2
|
|
AND deleted_at IS NULL
|
|
)
|
|
AND deleted_at IS NULL
|
|
AND created_at > $3
|
|
)
|
|
ORDER BY created_at;
|
|
`
|
|
fmt.Println(merchUuid, userId, days)
|
|
rows, err := r.db.Query(ctx, q, merchUuid, userId, days)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var result []Price
|
|
for rows.Next() {
|
|
var p Price
|
|
if err = rows.Scan(&p.Price, &p.CreatedAt, &p.OriginId); err != nil {
|
|
rows.Close()
|
|
return nil, err
|
|
}
|
|
result = append(result, p)
|
|
}
|
|
|
|
rows.Close()
|
|
if err = rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
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, userId int64, now sql.NullTime, list []int64) error {
|
|
q := `
|
|
UPDATE merch_prices mp
|
|
SET deleted_at = $1
|
|
FROM merch m
|
|
WHERE mp.id = ANY($2)
|
|
AND mp.merch_id = m.id
|
|
AND m.user_id = $3
|
|
`
|
|
|
|
_, err := r.db.Exec(ctx, q, now, list, userId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|