ability to delete mock sync groups
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
type (
|
||||
SyncGroup struct {
|
||||
SyncGroupIDs
|
||||
Name string
|
||||
Listings []SyncGroupListing
|
||||
}
|
||||
|
||||
@@ -811,6 +812,372 @@ func (db *Store) SaveNewSyncGroup(ctx context.Context, acctID int64) (SyncGroup,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (db *Store) SaveNewMockSyncGroup(ctx context.Context, acctID int64, name string) (SyncGroup, error) {
|
||||
tx, err := db.db.Begin(ctx)
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to start transaction: %w", err)
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
// verify there are enough listings
|
||||
|
||||
rows, err := tx.Query(
|
||||
ctx,
|
||||
`
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
mock.sync_group_listing_draft_order_indexes
|
||||
WHERE
|
||||
account_id = @account_id
|
||||
`,
|
||||
pgx.NamedArgs{
|
||||
"account_id": acctID,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to perform query: %w", err)
|
||||
}
|
||||
|
||||
numDrafts, err := pgx.CollectExactlyOneRow(rows, pgx.RowTo[int])
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to scan rows: %w", err)
|
||||
}
|
||||
|
||||
if numDrafts < 2 {
|
||||
return SyncGroup{}, fmt.Errorf("%w: insufficient listings: must be at least 2: %d", consts.ErrConflict, numDrafts)
|
||||
}
|
||||
|
||||
// create the new sync group row
|
||||
|
||||
rows, err = tx.Query(
|
||||
ctx,
|
||||
`
|
||||
INSERT INTO
|
||||
mock.sync_groups (
|
||||
account_id,
|
||||
name
|
||||
)
|
||||
VALUES (
|
||||
@account_id,
|
||||
@name
|
||||
)
|
||||
RETURNING
|
||||
sync_group_id
|
||||
`,
|
||||
pgx.NamedArgs{
|
||||
"account_id": acctID,
|
||||
"name": name,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to perform query to insert new mock sync group: %w", err)
|
||||
}
|
||||
|
||||
syncGroupID, err := pgx.CollectExactlyOneRow(rows, pgx.RowTo[int64])
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to scan row from inserting new mock sync group: %w", err)
|
||||
}
|
||||
|
||||
// read and delete the draft listings
|
||||
|
||||
type DraftListingRow struct {
|
||||
Order_index int
|
||||
Shop_id pgtype.Text
|
||||
Listing_id pgtype.Text
|
||||
}
|
||||
infos := getAllMockShopSchemaInfos()
|
||||
newListingsPerPlatform := make(map[Platform][]SyncGroupListing, len(infos))
|
||||
var numListings int
|
||||
for _, info := range infos {
|
||||
rows, err := tx.Query(
|
||||
ctx,
|
||||
fmt.Sprintf(
|
||||
`
|
||||
DELETE FROM
|
||||
%s
|
||||
WHERE
|
||||
account_id = @account_id
|
||||
RETURNING
|
||||
order_index,
|
||||
shop_id,
|
||||
listing_id
|
||||
`,
|
||||
info.syncGroupListingDraftsTable,
|
||||
),
|
||||
pgx.NamedArgs{
|
||||
"account_id": acctID,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to perform query deleting mock sync group listing draft order indexes for platform %s: %w", info.platform, err)
|
||||
}
|
||||
|
||||
vs, err := pgx.CollectRows(rows, pgx.RowToStructByNameLax[DraftListingRow])
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to scan rows: %w", err)
|
||||
}
|
||||
|
||||
ls := make([]SyncGroupListing, len(vs))
|
||||
for i, v := range vs {
|
||||
if !v.Shop_id.Valid {
|
||||
return SyncGroup{}, fmt.Errorf("%w: shop_id not specified on listing of order index %d", consts.ErrConflict, v.Order_index)
|
||||
}
|
||||
if !v.Listing_id.Valid {
|
||||
return SyncGroup{}, fmt.Errorf("%w: listing_id not specified on listing of order index %d", consts.ErrConflict, v.Order_index)
|
||||
}
|
||||
|
||||
ls[i] = SyncGroupListing{
|
||||
SyncGroupIDs: SyncGroupIDs{
|
||||
AccountIDs: AccountIDs{
|
||||
AccountID: acctID,
|
||||
},
|
||||
SyncGroupID: syncGroupID,
|
||||
},
|
||||
AccountShopIDs: AccountShopIDs{
|
||||
AccountIDs: AccountIDs{
|
||||
AccountID: acctID,
|
||||
},
|
||||
Platform: info.platform,
|
||||
ShopID: v.Shop_id.String,
|
||||
},
|
||||
ListingID: v.Listing_id.String,
|
||||
OrderIndex: v.Order_index,
|
||||
}
|
||||
}
|
||||
|
||||
newListingsPerPlatform[info.platform] = ls
|
||||
numListings += len(ls)
|
||||
}
|
||||
|
||||
_, err = tx.Exec(
|
||||
ctx,
|
||||
`
|
||||
DELETE FROM
|
||||
mock.sync_group_listing_draft_order_indexes
|
||||
`,
|
||||
)
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to perform query deleting mock sync group listing draft order indexes: %w", err)
|
||||
}
|
||||
|
||||
// create new sync listing rows
|
||||
|
||||
listings := make([]SyncGroupListing, 0, numListings)
|
||||
for _, info := range infos {
|
||||
for _, l := range newListingsPerPlatform[info.platform] {
|
||||
_, err := tx.Exec(
|
||||
ctx,
|
||||
`
|
||||
INSERT INTO
|
||||
mock.sync_group_listing_order_indexes (
|
||||
sync_group_id,
|
||||
order_index
|
||||
)
|
||||
VALUES (
|
||||
@sync_group_id,
|
||||
@order_index
|
||||
)
|
||||
`,
|
||||
pgx.NamedArgs{
|
||||
"sync_group_id": syncGroupID,
|
||||
"order_index": l.OrderIndex,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to perform query to insert row into mock.sync_group_listing_order_indexes: %w", err)
|
||||
}
|
||||
|
||||
_, err = tx.Exec(
|
||||
ctx,
|
||||
fmt.Sprintf(
|
||||
`
|
||||
INSERT INTO
|
||||
%s (
|
||||
account_id,
|
||||
sync_group_id,
|
||||
shop_id,
|
||||
listing_id,
|
||||
order_index
|
||||
)
|
||||
VALUES (
|
||||
@account_id,
|
||||
@sync_group_id,
|
||||
@shop_id,
|
||||
@listing_id,
|
||||
@order_index
|
||||
)
|
||||
`,
|
||||
info.syncGroupListingsTable,
|
||||
),
|
||||
pgx.NamedArgs{
|
||||
"account_id": acctID,
|
||||
"sync_group_id": syncGroupID,
|
||||
"order_index": l.OrderIndex,
|
||||
"shop_id": l.ShopID,
|
||||
"listing_id": l.ListingID,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to perform query to insert row into %s: %w", info.syncGroupListingsTable, err)
|
||||
}
|
||||
|
||||
listings = append(listings, l)
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return SyncGroup{}, fmt.Errorf("failed to commit transaction: %w", err)
|
||||
}
|
||||
|
||||
// prepare return value
|
||||
|
||||
slices.SortFunc(listings, func(a, b SyncGroupListing) int {
|
||||
return a.OrderIndex - b.OrderIndex
|
||||
})
|
||||
|
||||
return SyncGroup{
|
||||
SyncGroupIDs: SyncGroupIDs{
|
||||
AccountIDs: AccountIDs{
|
||||
AccountID: acctID,
|
||||
},
|
||||
SyncGroupID: syncGroupID,
|
||||
},
|
||||
Name: name,
|
||||
Listings: listings,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (db *Store) ListMockSyncGroups(ctx context.Context, acctID int64) ([]SyncGroup, error) {
|
||||
tx, err := db.db.BeginTx(ctx, pgx.TxOptions{
|
||||
AccessMode: pgx.ReadOnly,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to begin transaction: %w", err)
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
rows, err := tx.Query(
|
||||
ctx,
|
||||
`
|
||||
SELECT
|
||||
sync_group_id,
|
||||
name
|
||||
FROM
|
||||
mock.sync_groups
|
||||
WHERE
|
||||
account_id = @account_id
|
||||
`,
|
||||
pgx.NamedArgs{
|
||||
"account_id": acctID,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to perform query: %w", err)
|
||||
}
|
||||
|
||||
vs, err := pgx.CollectRows(rows, pgx.RowToStructByNameLax[struct {
|
||||
Sync_group_id int64
|
||||
Name string
|
||||
}])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan rows: %w", err)
|
||||
}
|
||||
|
||||
grps := make([]SyncGroup, len(vs))
|
||||
for i, v := range vs {
|
||||
listings, err := db.listMockSyncGroupListings(ctx, tx, acctID, v.Sync_group_id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load listings: %w", err)
|
||||
}
|
||||
|
||||
grps[i] = SyncGroup{
|
||||
SyncGroupIDs: SyncGroupIDs{
|
||||
AccountIDs: AccountIDs{
|
||||
AccountID: acctID,
|
||||
},
|
||||
SyncGroupID: v.Sync_group_id,
|
||||
},
|
||||
Name: v.Name,
|
||||
Listings: listings,
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to commit transaction: %w", err)
|
||||
}
|
||||
|
||||
return grps, nil
|
||||
}
|
||||
|
||||
// listMockSyncGroupListings will sort the returned listings by order_index.
|
||||
func (db *Store) listMockSyncGroupListings(ctx context.Context, tx pgx.Tx, acctID, syncGroupID int64) ([]SyncGroupListing, error) {
|
||||
var listings []SyncGroupListing
|
||||
for _, info := range getAllMockShopSchemaInfos() {
|
||||
rows, err := tx.Query(
|
||||
ctx,
|
||||
fmt.Sprintf(
|
||||
`
|
||||
SELECT
|
||||
account_id,
|
||||
shop_id,
|
||||
listing_id,
|
||||
order_index
|
||||
FROM
|
||||
%s
|
||||
WHERE
|
||||
account_id = @account_id
|
||||
AND sync_group_id = @sync_group_id
|
||||
`,
|
||||
info.syncGroupListingsTable,
|
||||
),
|
||||
pgx.NamedArgs{
|
||||
"account_id": acctID,
|
||||
"sync_group_id": syncGroupID,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to perform query on %s: %w", info.syncGroupListingsTable, err)
|
||||
}
|
||||
|
||||
vs, err := pgx.CollectRows(rows, pgx.RowToStructByNameLax[struct {
|
||||
Account_id int64
|
||||
Shop_id string
|
||||
Listing_id string
|
||||
Order_index int
|
||||
}])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan rows from %s: %w", info.syncGroupListingsTable, err)
|
||||
}
|
||||
|
||||
for _, v := range vs {
|
||||
listings = append(listings, SyncGroupListing{
|
||||
SyncGroupIDs: SyncGroupIDs{
|
||||
AccountIDs: AccountIDs{
|
||||
AccountID: acctID,
|
||||
},
|
||||
SyncGroupID: syncGroupID,
|
||||
},
|
||||
AccountShopIDs: AccountShopIDs{
|
||||
AccountIDs: AccountIDs{
|
||||
AccountID: acctID,
|
||||
},
|
||||
Platform: info.platform,
|
||||
ShopID: v.Shop_id,
|
||||
},
|
||||
ListingID: v.Listing_id,
|
||||
OrderIndex: v.Order_index,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
slices.SortFunc(listings, func(a, b SyncGroupListing) int {
|
||||
return a.OrderIndex - b.OrderIndex
|
||||
})
|
||||
|
||||
return listings, nil
|
||||
}
|
||||
|
||||
func deref[T any](ptr *T) T {
|
||||
if ptr == nil {
|
||||
var zero T
|
||||
|
||||
Reference in New Issue
Block a user