get tasks + insert result
This commit is contained in:
parent
47700dfd14
commit
718101ee67
6 changed files with 268 additions and 8 deletions
|
|
@ -1,8 +1,10 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
type MerchProvider interface {
|
type MerchProvider interface {
|
||||||
GetTasks(ctx context.Context) ([]Task, error)
|
GetTasks(ctx context.Context) ([]Task, error)
|
||||||
InsertRecords(ctx context.Context) error
|
InsertPrices(ctx context.Context, rawPrices []Result) error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ func New(deps Deps) *Handler {
|
||||||
r := newRepo(deps.DB)
|
r := newRepo(deps.DB)
|
||||||
s := newService(r, deps.Utils, deps.UserProvider)
|
s := newService(r, deps.Utils, deps.UserProvider)
|
||||||
c := newController(s, deps.Utils)
|
c := newController(s, deps.Utils)
|
||||||
p := newProvider()
|
p := newProvider(s, deps.Utils)
|
||||||
|
|
||||||
return &Handler{
|
return &Handler{
|
||||||
controller: c,
|
controller: c,
|
||||||
|
|
|
||||||
|
|
@ -44,3 +44,9 @@ type ExtraData struct {
|
||||||
OriginId int64
|
OriginId int64
|
||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type taskData struct {
|
||||||
|
MerchUuid string
|
||||||
|
OriginName string
|
||||||
|
Url string
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,93 @@ package merch
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"merch-api/internal/common"
|
"merch-api/internal/common"
|
||||||
|
"merch-api/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type provider struct{}
|
const providerLogHeader string = "[provider]"
|
||||||
|
|
||||||
func newProvider() *provider {
|
type provider struct {
|
||||||
return &provider{}
|
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) {
|
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
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
75
internal/merch/provider_test.go
Normal file
75
internal/merch/provider_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ type Repository interface {
|
||||||
getMany(ctx context.Context, userId int64) ([]merchDTO, error)
|
getMany(ctx context.Context, userId int64) ([]merchDTO, error)
|
||||||
|
|
||||||
getMerchIdByUuid(ctx context.Context, userId int64, uuid string) (int64, 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)
|
updateMerch(ctx context.Context, userId int64, merch *updateMerchDTO) (*merchDTO, error)
|
||||||
updateExtraData(ctx context.Context, merchId int64, insertData []ExtraData) ([]ExtraData, 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
|
deleteOneMerchRecord(ctx context.Context, userId int64, merchUuid string, delTime time.Time) error
|
||||||
|
|
||||||
Origins
|
Origins
|
||||||
|
Prices
|
||||||
|
Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
type Origins interface {
|
type Origins interface {
|
||||||
|
|
@ -34,6 +37,14 @@ type Origins interface {
|
||||||
deleteOriginByName(ctx context.Context, name string, deletedAt sql.NullTime) error
|
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 {
|
type repo struct {
|
||||||
db *pgxpool.Pool
|
db *pgxpool.Pool
|
||||||
}
|
}
|
||||||
|
|
@ -179,6 +190,35 @@ func (r *repo) getMerchIdByUuid(ctx context.Context, userId int64, uuid string)
|
||||||
return merchId, nil
|
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 {
|
func (r *repo) deleteOneMerchRecord(ctx context.Context, userId int64, merchUuid string, delTime time.Time) error {
|
||||||
tx, err := r.db.Begin(ctx)
|
tx, err := r.db.Begin(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -263,3 +303,65 @@ func (r *repo) updateExtraData(ctx context.Context, merchId int64, insertData []
|
||||||
|
|
||||||
return result, nil
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue