get tasks + insert result

This commit is contained in:
nquidox 2026-03-08 16:42:37 +03:00
parent 47700dfd14
commit 718101ee67
6 changed files with 268 additions and 8 deletions

View file

@ -21,7 +21,7 @@ func New(deps Deps) *Handler {
r := newRepo(deps.DB)
s := newService(r, deps.Utils, deps.UserProvider)
c := newController(s, deps.Utils)
p := newProvider()
p := newProvider(s, deps.Utils)
return &Handler{
controller: c,

View file

@ -44,3 +44,9 @@ type ExtraData struct {
OriginId int64
URL string
}
type taskData struct {
MerchUuid string
OriginName string
Url string
}

View file

@ -3,18 +3,93 @@ package merch
import (
"context"
"merch-api/internal/common"
"merch-api/pkg/utils"
)
type provider struct{}
const providerLogHeader string = "[provider]"
func newProvider() *provider {
return &provider{}
type provider struct {
service *service
utils utils.Utils
}
func newProvider(s *service, u utils.Utils) *provider {
return &provider{
service: s,
utils: u,
}
}
func (p *provider) GetTasks(ctx context.Context) ([]common.Task, error) {
return nil, nil
rawTasks, err := p.service.repo.getTaskData(ctx)
if err != nil {
logErr(providerLogHeader, err)
return nil, err
}
return p.convertTasks(rawTasks), nil
}
func (p *provider) InsertRecords(ctx context.Context) error {
func (p *provider) InsertPrices(ctx context.Context, rawPrices []common.Result) error {
if rawPrices == nil || len(rawPrices) == 0 {
logDebug(providerLogHeader, "no prices given")
return nil
}
var uuids []string
for _, rawPrice := range rawPrices {
uuids = append(uuids, rawPrice.MerchUuid)
}
uuidMap, err := p.service.getMerchUuidMap(ctx, uuids)
if err != nil {
logErr(serviceLogHeader, err)
return err
}
originIds, _, err := p.service.getOriginsMaps(ctx)
if err != nil {
logErr(serviceLogHeader, err)
return err
}
now := p.utils.TimeNowUTC()
var insertPrices []Price
for _, rawPrice := range rawPrices {
insertPrices = append(insertPrices, Price{
CreatedAt: now,
UpdatedAt: p.utils.NullTimeFromNow(now),
MerchId: uuidMap[rawPrice.MerchUuid],
OriginId: originIds[rawPrice.OriginName],
Price: int(rawPrice.Price),
})
}
if err = p.service.repo.insertPrices(ctx, insertPrices); err != nil {
logErr(serviceLogHeader, err)
return err
}
return nil
}
func (p *provider) convertTasks(rawTasks []taskData) []common.Task {
convert := make(map[string]*common.Task, len(rawTasks))
for _, item := range rawTasks {
task, ok := convert[item.MerchUuid]
if !ok {
task = &common.Task{
MerchUuid: item.MerchUuid,
Origins: make(map[string]string),
}
convert[item.MerchUuid] = task
}
task.Origins[item.OriginName] = item.Url
}
result := make([]common.Task, 0, len(convert))
for _, task := range convert {
result = append(result, *task)
}
return result
}

View file

@ -0,0 +1,75 @@
package merch
import (
"merch-api/internal/common"
"merch-api/pkg/utils"
"reflect"
"testing"
)
func Test_provider_convertTasks(t *testing.T) {
type fields struct {
service *service
utils utils.Utils
}
type args struct {
rawTasks []taskData
}
tests := []struct {
name string
fields fields
args args
want []common.Task
}{
{
name: "Success convert tasks",
fields: fields{
service: nil,
utils: nil,
},
args: args{[]taskData{
{"1", "surugaya", "url"},
{"1", "mandarake", "url"},
{"1", "amiami", "url"},
{"2", "surugaya", "url"},
{"2", "mandarake", "url"},
{"2", "amiami", "url"},
{"3", "surugaya", "url"},
{"3", "amiami", "url"},
{"4", "amiami", "url"},
}},
want: []common.Task{
{"1", map[string]string{"surugaya": "url", "mandarake": "url", "amiami": "url"}},
{"2", map[string]string{"surugaya": "url", "mandarake": "url", "amiami": "url"}},
{"3", map[string]string{"surugaya": "url", "amiami": "url"}},
{"4", map[string]string{"amiami": "url"}},
},
},
{
name: "Success convert tasks",
fields: fields{
service: nil,
utils: nil,
},
args: args{[]taskData{
{"1", "surugaya", "url"},
{"1", "mandarake", "url"},
{"1", "amiami", "url"},
}},
want: []common.Task{
{"1", map[string]string{"surugaya": "url", "mandarake": "url", "amiami": "url"}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &provider{
service: tt.fields.service,
utils: tt.fields.utils,
}
if got := p.convertTasks(tt.args.rawTasks); !reflect.DeepEqual(got, tt.want) {
t.Errorf("convertTasks() = %v, want %v", got, tt.want)
}
})
}
}

View file

@ -18,6 +18,7 @@ type Repository interface {
getMany(ctx context.Context, userId int64) ([]merchDTO, error)
getMerchIdByUuid(ctx context.Context, userId int64, uuid string) (int64, error)
getMerchUuidMap(ctx context.Context, merchUuids []string) (map[string]int64, error)
updateMerch(ctx context.Context, userId int64, merch *updateMerchDTO) (*merchDTO, error)
updateExtraData(ctx context.Context, merchId int64, insertData []ExtraData) ([]ExtraData, error)
@ -26,6 +27,8 @@ type Repository interface {
deleteOneMerchRecord(ctx context.Context, userId int64, merchUuid string, delTime time.Time) error
Origins
Prices
Tasks
}
type Origins interface {
@ -34,6 +37,14 @@ type Origins interface {
deleteOriginByName(ctx context.Context, name string, deletedAt sql.NullTime) error
}
type Prices interface {
insertPrices(ctx context.Context, prices []Price) error
}
type Tasks interface {
getTaskData(ctx context.Context) ([]taskData, error)
}
type repo struct {
db *pgxpool.Pool
}
@ -179,6 +190,35 @@ func (r *repo) getMerchIdByUuid(ctx context.Context, userId int64, uuid string)
return merchId, nil
}
func (r *repo) getMerchUuidMap(ctx context.Context, merchUuids []string) (map[string]int64, error) {
q := `SELECT merch_uuid, id FROM merch WHERE deleted_at IS NULL AND merch_uuid = ANY($1)`
rows, err := r.db.Query(ctx, q, merchUuids)
if err != nil {
return nil, err
}
var merchUuidMap map[string]int64
for rows.Next() {
var (
uuid string
id int64
)
if err = rows.Scan(&uuid, &id); err != nil {
rows.Close()
return nil, err
}
merchUuidMap[uuid] = id
}
rows.Close()
if err = rows.Err(); err != nil {
return nil, err
}
return merchUuidMap, nil
}
func (r *repo) deleteOneMerchRecord(ctx context.Context, userId int64, merchUuid string, delTime time.Time) error {
tx, err := r.db.Begin(ctx)
if err != nil {
@ -263,3 +303,65 @@ func (r *repo) updateExtraData(ctx context.Context, merchId int64, insertData []
return result, nil
}
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) getTaskData(ctx context.Context) ([]taskData, error) {
q := `SELECT m.merch_uuid, med.url, mo.name
FROM merch AS m
JOIN merch_extra_data AS med ON m.id = med.merch_id
JOIN merch_origins AS mo ON mo.id = med.origin_id
WHERE m.deleted_at IS NULL
AND med.deleted_at IS NULL
AND mo.deleted_at IS NULL
`
rows, err := r.db.Query(ctx, q)
if err != nil {
return nil, err
}
var result []taskData
for rows.Next() {
var t taskData
if err = rows.Scan(&t.MerchUuid, &t.Url, &t.OriginName); err != nil {
return nil, err
}
result = append(result, t)
}
rows.Close()
if err = rows.Err(); err != nil {
return nil, err
}
return result, nil
}