Files
inventory-plus-plus/server/api/accounts/router.go
T
2026-03-01 03:36:47 -07:00

894 lines
27 KiB
Go

package accounts
import (
"errors"
"fmt"
"strings"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"ruben/inventory2/consts"
"ruben/inventory2/domains/accounts"
"ruben/inventory2/logging"
"ruben/inventory2/server/auth"
"ruben/inventory2/server/param"
"ruben/inventory2/server/response"
"ruben/inventory2/server/sse"
)
type accountSubrouter struct {
log *logging.Logger
accts *accounts.Store
pub *sse.UpdateNotificationPublisher
}
func Routes(
r *gin.RouterGroup,
logger *logging.Logger,
accts *accounts.Store,
pub *sse.UpdateNotificationPublisher,
) {
as := &accountSubrouter{
log: logger,
accts: accts,
pub: pub,
}
r.POST("", response.Handler(as.createAccount))
platform := r.Group("/:acctID/platforms/:platform", pub.Publish("/:acctID/platforms"))
platform.PUT("/order-index", response.Handler(as.setOrderOfPlatformOnAccountPage))
platform.POST("/shops/mocks", response.Handler(as.createMockShop))
mockShops := r.Group("/:acctID/platforms/:platform/shops/mocks/:shop-id", pub.Publish("/:acctID/platforms/:platform/shops/mocks/:shop-id"))
mockShops.POST("/listings", response.Handler(as.addMockListing))
mockShops.PUT("/listings/:listing-id", response.Handler(as.updateMockListing))
mockShops.DELETE("/listings/:listing-id", response.Handler(as.deleteMockListing))
syncGroups := r.Group("/:acctID/inventory/sync-groups", pub.Publish("/:acctID/inventory/sync-groups"))
syncGroups.POST("", response.Handler(as.saveNewSyncGroup))
draftListings := r.Group("/:acctID/inventory/sync-groups/draft/listings", pub.Publish("/:acctID/inventory/sync-groups/draft/listings"))
draftListings.POST("", response.Handler(as.createSyncGroupListingDraft))
draftListings.PUT("/:orderIndex/shop", response.Handler(as.setShopInSyncGroupListingDraft))
draftListings.PUT("/:orderIndex/listing", response.Handler(as.setListingInSyncGroupListingDraft))
draftListings.DELETE("/:orderIndex", response.Handler(as.deleteSyncGroupListingDraft))
mockMode := r.Group("/:acctID/mock-mode", pub.Publish("/:acctID/mock-mode"))
mockMode.PUT("", response.Handler(as.setMockMode))
mockDraftListings := r.Group("/:acctID/inventory/sync-groups/mock/draft/listings", pub.Publish("/:acctID/inventory/sync-groups/mock/draft/listings"))
mockDraftListings.POST("", response.Handler(as.createMockSyncGroupListingDraft))
mockDraftListings.PUT("/:orderIndex/shop", response.Handler(as.setShopInMockSyncGroupListingDraft))
mockDraftListings.PUT("/:orderIndex/listing", response.Handler(as.setListingInMockSyncGroupListingDraft))
mockDraftListings.DELETE("/:orderIndex", response.Handler(as.deleteMockSyncGroupListingDraft))
mockSyncGroups := r.Group("/:acctID/inventory/sync-groups/mock", pub.Publish("/:acctID/inventory/sync-groups/mock"))
mockSyncGroups.POST("", response.Handler(as.saveNewMockSyncGroup))
mockSyncGroups.DELETE("/:syncGroupID", pub.Publish("/:acctID/inventory/sync-groups/mock"), response.Handler(as.deleteMockSyncGroup))
mockSyncGroupEditing := r.Group("/:acctID/inventory/sync-groups/mock/editing", pub.Publish("/:acctID/inventory/sync-groups/mock/editing"))
mockSyncGroupEditing.PUT("", response.Handler(as.selectMockSyncGroupForEditing))
mockSyncGroupEditing.POST("", response.Handler(as.saveMockSyncGroupBeingEdited))
mockSyncGroupEditing.DELETE("", response.Handler(as.cancelMockSyncGroupEdits))
mockSyncGroupEditing.POST("/listings", response.Handler(as.addListingToMockSyncGroupBeingEdited))
mockSyncGroupBeingEdited := r.Group("/:acctID/inventory/sync-groups/mock/:syncGroupID/editing", pub.Publish("/:acctID/inventory/sync-groups/mock/:syncGroupID/editing"))
mockSyncGroupBeingEdited.PUT("/listings/:orderIndex/shop", response.Handler(as.setShopInListingInMockSyncGroupBeingEdited))
mockSyncGroupBeingEdited.PUT("/listings/:orderIndex/listing", response.Handler(as.setListingInListingInMockSyncGroupBeingEdited))
mockSyncGroupBeingEdited.DELETE("/listings/:orderIndex", response.Handler(as.deleteListingInListingInMockSyncGroupBeingEdited))
simulations := r.Group("/:acctID/simulations", pub.Publish("/:acctID/simulations"))
simulations.PUT("/sale/form/shop", response.Handler(as.setShopInMockSaleForm))
simulations.POST("/sale", response.Handler(as.postNewMockSale))
simulations.PUT("/refund/form/shop", response.Handler(as.setShopInMockRefundForm))
simulations.POST("/refund", response.Handler(as.postNewMockRefund))
simulations.PUT("/count/form/shop", response.Handler(as.setShopInMockCountForm))
simulations.PUT("/shops/:shopID/listings/:listingID/count", response.Handler(as.setMockListingCount))
}
// POST /
func (s *accountSubrouter) createAccount(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
// TODO: get email from the user's account profile (how?) - will need to flesh out the account creation process later on
email := uuid.NewString() + "@example.com"
userID := auth.GetIdentity(ctx).User.UserID
_, err := s.accts.CreateAccount(ctx, userID, email)
if err != nil {
if errors.Is(err, consts.ErrConflict) {
return nil, response.Conflict().
Msg("user already has an account")
}
return nil, response.Errorf("failed to create account: %w", err)
}
return response.StatusCreated().
// force a reload to ensure an sse connection is made.
// user should automatically be redirected to the appropriate page based on their current location and/or login/account statuses.
HXRefresh("true"), nil
}
// POST /:acctID/inventory/sync-groups/draft/listings
func (s *accountSubrouter) createSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
if _, err := s.accts.CreateSyncGroupListingDraft(ctx, acctID); err != nil {
return nil, response.Errorf("failed to create new listing draft: %w", err)
}
return response.StatusCreated(), nil
}
// PUT /:acctID/inventory/sync-groups/draft/listings/:orderIndex/shop
// @platform string
// @shopID string
func (s *accountSubrouter) setShopInSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
orderIndex int
platform accounts.Platform
shopID string
)
err := param.Path("orderIndex", param.Int(&orderIndex)).
Form("platform", param.Platform(&platform)).
Form("shop-id", param.Text(&shopID)).
Unmarshal(c)
if err != nil {
return nil, err
}
if err := s.accts.SetShopInSyncGroupListingDraft(ctx, acctID, orderIndex, platform, shopID); err != nil {
return nil, response.Errorf("failed to set shop: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// PUT /:acctID/inventory/sync-groups/draft/listings/:orderIndex/listing
func (s *accountSubrouter) setListingInSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
orderIndex int
listingID string
)
err := param.Path("orderIndex", param.Int(&orderIndex)).
Form("listing-id", param.Text(&listingID)).
Unmarshal(c)
if err != nil {
return nil, err
}
if err := s.accts.SetListingInSyncGroupListingDraft(ctx, acctID, orderIndex, listingID); err != nil {
return nil, response.Errorf("failed to set listing: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// DELETE /:acctID/inventory/sync-groups/draft/listings/:orderIndex
func (s *accountSubrouter) deleteSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
orderIndex int
)
err := param.Path("orderIndex", param.Int(&orderIndex)).
Unmarshal(c)
if err != nil {
return nil, err
}
if _, err := s.accts.DeleteSyncGroupListingDraft(ctx, acctID, orderIndex); err != nil {
return nil, response.Errorf("failed to delete listing: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// POST /:acctID/inventory/sync-groups
func (s *accountSubrouter) saveNewSyncGroup(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
if _, err := s.accts.SaveNewSyncGroup(ctx, acctID); err != nil {
return nil, response.Errorf("failed to save new sync group: %w", response.ErrorFromConstant(err))
}
return response.StatusCreated(), nil
}
// PUT /:acctID/platforms/:platform/order-index"
// this endpoint is called when dragging a platform tab in the accounts page.
func (s *accountSubrouter) setOrderOfPlatformOnAccountPage(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
// validate parameters
var (
platform accounts.Platform
orderIndex int
)
err := param.Path("platform", param.Platform(&platform)).
Form("order-index", param.Int(&orderIndex)).
Unmarshal(c)
if err != nil {
return nil, err
}
// update the order
platforms, prevIndex, err := s.accts.SetOrderOfPlatformOnAccountPage(c, acctID, platform, orderIndex)
if err != nil {
return nil, fmt.Errorf("failed to save record: %w", err)
}
// emit events on all platforms updated, so the tabs can all refresh (including their logic)
platformEvents := make([]string, max(orderIndex, prevIndex)-min(orderIndex, prevIndex))
if orderIndex > prevIndex {
for i := range orderIndex - prevIndex {
p := platforms[prevIndex+i]
platformEvents[i] = fmt.Sprintf("accounts_%d_platforms_%s_order-index", acctID, lowerSnakeCase(p))
}
} else if orderIndex < prevIndex {
for i := range prevIndex - orderIndex {
p := platforms[orderIndex+1+i]
platformEvents[i] = fmt.Sprintf("accounts_%d_platforms_%s_order-index", acctID, lowerSnakeCase(p))
}
}
if err := s.pub.Push(c, acctID, platformEvents...); err != nil {
s.log.Errorf("failed to publish platform order-index events: %v", err)
}
return response.StatusNoContent(), nil
}
// POST /:acctID/platforms/:platform/shops/mocks
func (s *accountSubrouter) createMockShop(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
// validate parameters
var (
platform accounts.Platform
name string
)
err := param.Path("platform", param.Platform(&platform)).
Form("name", param.Text(&name)).
Unmarshal(c)
if err != nil {
return nil, err
}
s.log.Warnf("not implemented: mock store created: account_id = %d; platform = %s; name = %s", acctID, platform, name)
// create the mock account
id, err := s.accts.CreateMockShop(c, acctID, platform, name)
if err != nil {
return nil, fmt.Errorf("failed to save record: %w", err)
}
location := fmt.Sprintf("/ui/accounts/%d/platforms/%s/mock-shops/%s", acctID, lowerSnakeCase(platform), id)
var res response.Response
if c.GetHeader("HX-Request") == "true" {
res = response.StatusCreated()
} else {
res = response.SeeOther(location)
}
return res.HXLocation(location), nil
}
// POST /:acctID/platforms/:platform/shops/mocks/:shop-id/listings
func (s *accountSubrouter) addMockListing(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
platform accounts.Platform
shopID string
name string
sku string
description string
count int
)
err := param.Path("platform", param.Platform(&platform)).
Path("shop-id", param.Text(&shopID)).
Form("name", param.Text(&name)).
Form("sku", param.Text(&sku)).
Form("description", param.Text(&description)).
Form("count", param.Int(&count)).
Unmarshal(c)
if err != nil {
return nil, err
}
_, err = s.accts.CreateMockListing(
c,
accounts.MockListing{
AccountShopListingIDs: accounts.NewAccountIDs(acctID).
ShopID(platform, shopID).
ListingID(""),
Name: name,
SKU: sku,
Description: description,
Count: int64(count),
},
)
if err != nil {
return nil, fmt.Errorf("failed to create new listing: %w", err)
}
return response.StatusCreated(), nil
}
// PUT /:acctID/platforms/:platform/shops/mocks/:shop-id/listings/:listing-id
func (s *accountSubrouter) updateMockListing(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
platform accounts.Platform
shopID string
listingID string
name string
sku string
description string
count int
)
err := param.Path("platform", param.Platform(&platform)).
Path("shop-id", param.Text(&shopID)).
Path("listing-id", param.Text(&listingID)).
Form("name", param.Text(&name)).
Form("sku", param.Text(&sku)).
Form("description", param.Text(&description)).
Form("count", param.Int(&count)).
Unmarshal(c)
if err != nil {
return nil, err
}
err = s.accts.UpdateMockListing(
c,
accounts.MockListing{
AccountShopListingIDs: accounts.NewAccountIDs(acctID).
ShopID(platform, shopID).
ListingID(listingID),
Name: name,
SKU: sku,
Description: description,
Count: int64(count),
},
)
if err != nil {
return nil, fmt.Errorf("failed to update listing: %w", err)
}
return response.StatusOK(), nil
}
// DELETE /:acctID/platforms/:platform/shops/mocks/:shop-id/listings/:listing-id
func (s *accountSubrouter) deleteMockListing(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
platform accounts.Platform
shopID string
listingID string
)
err := param.Path("platform", param.Platform(&platform)).
Path("shop-id", param.Text(&shopID)).
Path("listing-id", param.Text(&listingID)).
Unmarshal(c)
if err != nil {
return nil, err
}
err = s.accts.DeleteMockListing(
c,
accounts.NewAccountIDs(acctID).
ShopID(platform, shopID).
ListingID(listingID),
)
if err != nil {
return nil, fmt.Errorf("failed to delete listing: %w", err)
}
return response.StatusNoContent(), nil
}
// POST /:acctID/inventory/sync-groups/mock/draft/listings
func (s *accountSubrouter) createMockSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
if _, err := s.accts.CreateMockSyncGroupListingDraft(ctx, acctID); err != nil {
return nil, response.Errorf("failed to create new listing draft: %w", err)
}
return response.StatusCreated(), nil
}
// PUT /:acctID/inventory/sync-groups/mock/draft/listings/:orderIndex/shop
// @platform string
// @shopID string
func (s *accountSubrouter) setShopInMockSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
orderIndex int
platform accounts.Platform
shopID string
)
err := param.Path("orderIndex", param.Int(&orderIndex)).
Form("platform", param.Platform(&platform)).
Form("shop-id", param.Text(&shopID)).
Unmarshal(c)
if err != nil {
return nil, err
}
if err := s.accts.SetShopInMockSyncGroupListingDraft(ctx, acctID, orderIndex, platform, shopID); err != nil {
return nil, response.Errorf("failed to set shop: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// PUT /:acctID/inventory/sync-groups/mock/draft/listings/:orderIndex/listing
func (s *accountSubrouter) setListingInMockSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
orderIndex int
listingID string
)
err := param.Path("orderIndex", param.Int(&orderIndex)).
Form("listing-id", param.Text(&listingID)).
Unmarshal(c)
if err != nil {
return nil, err
}
if err := s.accts.SetListingInMockSyncGroupListingDraft(ctx, acctID, orderIndex, listingID); err != nil {
return nil, response.Errorf("failed to set listing: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// DELETE /:acctID/inventory/sync-groups/mock/draft/listings/:orderIndex
func (s *accountSubrouter) deleteMockSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
orderIndex int
)
err := param.Path("orderIndex", param.Int(&orderIndex)).
Unmarshal(c)
if err != nil {
return nil, err
}
if err := s.accts.DeleteMockSyncGroupListingDraft(ctx, acctID, orderIndex); err != nil {
return nil, response.Errorf("failed to delete listing: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// PUT /:acctID/mock-mode
func (s *accountSubrouter) setMockMode(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
on bool
)
err := param.Form("on", param.Bool(&on)).
Unmarshal(c)
if err != nil {
return nil, err
}
if err := s.accts.SetMockMode(ctx, acctID, on); err != nil {
return nil, response.Errorf("failed to set mock mode: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// POST /:acctID/inventory/sync-groups/mock
func (s *accountSubrouter) saveNewMockSyncGroup(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
name string
)
err := param.Form("name", param.Text(&name)).
Unmarshal(c)
if err != nil {
return nil, err
}
if _, err := s.accts.SaveNewMockSyncGroup(ctx, acctID, name); err != nil {
return nil, response.Errorf("failed to save new mock sync group: %w", response.ErrorFromConstant(err))
}
return response.StatusCreated(), nil
}
// DELETE /:acctID/inventory/sync-groups/mock/:syncGroupID
func (s *accountSubrouter) deleteMockSyncGroup(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
syncGroupID int64
)
if err := param.Path("syncGroupID", param.Int64(&syncGroupID)).
Unmarshal(c); err != nil {
return nil, err
}
if err := s.accts.DeleteMockSyncGroup(ctx, acctID, syncGroupID); err != nil {
return nil, response.Errorf("failed to save new mock sync group: %w", response.ErrorFromConstant(err))
}
return response.StatusCreated(), nil
}
// PUT /:acctID/inventory/sync-groups/mock/editing
func (s *accountSubrouter) selectMockSyncGroupForEditing(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
var (
syncGroupID int64
)
if err := param.Form("syncGroupID", param.Int64(&syncGroupID)).
Unmarshal(c); err != nil {
return nil, err
}
prevSyncGroupID, ok, err := s.accts.StartEditingMockSyncGroup(ctx, acctID, syncGroupID)
if err != nil {
return nil, response.Errorf("failed to start editing mock sync group: %w", response.ErrorFromConstant(err))
}
// emit events indicating sync groups being edited and no longer being edited
evts := make([]string, 1, 2)
evts[0] = fmt.Sprintf("accounts_%d_inventory_sync-groups_mock_%d", acctID, syncGroupID)
if ok {
evts = append(evts, fmt.Sprintf("accounts_%d_inventory_sync-groups_mock_%d", acctID, prevSyncGroupID))
}
if err := s.pub.Push(c, acctID, evts...); err != nil {
s.log.Errorf("failed to publish mock sync group editing events: %v", err)
}
return response.StatusOK(), nil
}
// POST /:acctID/inventory/sync-groups/mock/editing
func (s *accountSubrouter) saveMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
syncGroupID, err := s.accts.SaveMockSyncGroupBeingEdited(ctx, acctID)
if err != nil {
return nil, response.Errorf("failed to save mock sync group being edited: %w", response.ErrorFromConstant(err))
}
// emit events indicating sync groups being edited and no longer being edited
if err := s.pub.Push(
c,
acctID,
fmt.Sprintf("accounts_%d_inventory_sync-groups_mock_%d", acctID, syncGroupID),
fmt.Sprintf("accounts_%d_inventory_sync-groups_mock_%d_editing", acctID, syncGroupID),
); err != nil {
s.log.Errorf("failed to publish mock sync group editing events: %v", err)
}
return response.StatusOK(), nil
}
// DELETE /:acctID/inventory/sync-groups/mock/editing
func (s *accountSubrouter) cancelMockSyncGroupEdits(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
prevSyncGroupID, deleted, err := s.accts.CancelEditingOfMockSyncGroupForAccount(ctx, acctID)
if err != nil {
return nil, response.Errorf("failed to stop editing mock sync group: %w", response.ErrorFromConstant(err))
}
// emit events indicating sync groups being edited and no longer being edited
if deleted {
evt := fmt.Sprintf("accounts_%d_inventory_sync-groups_mock_%d", acctID, prevSyncGroupID)
if err := s.pub.Push(c, acctID, evt); err != nil {
s.log.Errorf("failed to publish mock sync group editing events: %v", err)
}
}
return response.StatusOK(), nil
}
// POST /:acctID/inventory/sync-groups/mock/editing/listings
func (s *accountSubrouter) addListingToMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
r := c.Request
ctx := r.Context()
acctID := auth.GetIdentity(ctx).Account.AccountID
if _, _, err := s.accts.AddListingToMockSyncGroupBeingEdited(ctx, acctID); err != nil {
return nil, response.Errorf("failed to add listing to mock sync group being edited: %w", response.ErrorFromConstant(err))
}
return response.StatusCreated(), nil
}
// PUT /:acctID/inventory/sync-groups/mock/editing/listings/:orderIndex/shop
func (s *accountSubrouter) setShopInListingInMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
syncGroupID int64
orderIndex int
platform accounts.Platform
shopID string
)
if err := param.Path("syncGroupID", param.Int64(&syncGroupID)).
Path("orderIndex", param.Int(&orderIndex)).
Form("platform", param.Platform(&platform)).
Form("shop-id", param.Text(&shopID)).
Unmarshal(c); err != nil {
return nil, err
}
if err := s.accts.SetShopInListingInMockSyncGroupBeingEdited(c, acctID, syncGroupID, orderIndex, platform, shopID); err != nil {
return nil, response.Errorf("failed to set shop in listing in mock sync group being edited: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// PUT /:acctID/inventory/sync-groups/mock/editing/listings/:orderIndex/listing
func (s *accountSubrouter) setListingInListingInMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
syncGroupID int64
orderIndex int
listingID string
)
if err := param.Path("syncGroupID", param.Int64(&syncGroupID)).
Path("orderIndex", param.Int(&orderIndex)).
Form("listing-id", param.Text(&listingID)).
Unmarshal(c); err != nil {
return nil, err
}
if err := s.accts.SetListingInListingInMockSyncGroupBeingEdited(c, acctID, syncGroupID, orderIndex, listingID); err != nil {
return nil, response.Errorf("failed to set listing in listing in mock sync group being edited: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// DELETE /:acctID/inventory/sync-groups/mock/editing/listings/:orderIndex
func (s *accountSubrouter) deleteListingInListingInMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
orderIndex int
)
if err := param.Path("orderIndex", param.Int(&orderIndex)).
Unmarshal(c); err != nil {
return nil, err
}
if err := s.accts.DeleteListingInListingInMockSyncGroupBeingEdited(c, acctID, orderIndex); err != nil {
return nil, response.Errorf("failed to delete listing in mock sync group being edited: %w", response.ErrorFromConstant(err))
}
return response.StatusOK(), nil
}
// PUT /:acctID/simulations/sale/form/shop
func (s *accountSubrouter) setShopInMockSaleForm(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
platform accounts.Platform
shopID string
)
if err := param.Form("platform", param.Platform(&platform)).
Form("shop-id", param.Text(&shopID)).
Unmarshal(c); err != nil {
return nil, err
}
if err := s.accts.SetShopInMockSaleForm(c, acctID, platform, shopID); err != nil {
return nil, fmt.Errorf("failed to set shop in mock sale form: %w", err)
}
return response.StatusOK(), nil
}
// POST /:acctID/simulations/sale
func (s *accountSubrouter) postNewMockSale(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
platform accounts.Platform
shopID string
listingID string
count int
)
if err := param.Form("platform", param.Platform(&platform)).
Form("shop-id", param.Text(&shopID)).
Form("listing-id", param.Text(&listingID)).
Form("count", param.Int(&count)).
Unmarshal(c); err != nil {
return nil, err
}
if _, err := s.accts.SaveNewMockSale(c, acctID, platform, shopID, listingID, count); err != nil {
return nil, fmt.Errorf("failed to save new mock sale: %w", err)
}
return response.StatusCreated(), nil
}
// PUT /:acctID/simulations/refund/form/shop
func (s *accountSubrouter) setShopInMockRefundForm(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
platform accounts.Platform
shopID string
)
if err := param.Form("platform", param.Platform(&platform)).
Form("shop-id", param.Text(&shopID)).
Unmarshal(c); err != nil {
return nil, err
}
if err := s.accts.SetShopInMockRefundForm(c, acctID, platform, shopID); err != nil {
return nil, fmt.Errorf("failed to set shop in mock refund form: %w", err)
}
return response.StatusOK(), nil
}
// POST /:acctID/simulations/refund
func (s *accountSubrouter) postNewMockRefund(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
platform accounts.Platform
shopID string
listingID string
count int
)
if err := param.Form("platform", param.Platform(&platform)).
Form("shop-id", param.Text(&shopID)).
Form("listing-id", param.Text(&listingID)).
Form("count", param.Int(&count)).
Unmarshal(c); err != nil {
return nil, err
}
if _, err := s.accts.SaveNewMockRefund(c, acctID, platform, shopID, listingID, count); err != nil {
return nil, fmt.Errorf("failed to save new mock refund: %w", err)
}
return response.StatusCreated(), nil
}
// PUT /:acctID/simulations/count/form/shop
func (s *accountSubrouter) setShopInMockCountForm(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
platform accounts.Platform
shopID string
)
if err := param.Form("platform", param.Platform(&platform)).
Form("shop-id", param.Text(&shopID)).
Unmarshal(c); err != nil {
return nil, err
}
if err := s.accts.SetShopInMockCountForm(c, acctID, platform, shopID); err != nil {
return nil, fmt.Errorf("failed to set shop in mock count form: %w", err)
}
return response.StatusOK(), nil
}
// PUT /:acctID/simulations/shops/:shopID/listings/:listingID/count
func (s *accountSubrouter) setMockListingCount(c *gin.Context) (response.Response, error) {
acctID := auth.GetIdentity(c).Account.AccountID
var (
platform accounts.Platform
shopID string
listingID string
count int
)
if err := param.Form("platform", param.Platform(&platform)).
Path("shopID", param.Text(&shopID)).
Path("listingID", param.Text(&listingID)).
Form("count", param.Int(&count)).
Unmarshal(c); err != nil {
return nil, err
}
if _, err := s.accts.SaveNewMockInventoryReset(c, acctID, platform, shopID, listingID, count); err != nil {
return nil, fmt.Errorf("failed to save new mock inventory reset: %w", err)
}
return response.StatusOK(), nil
}
func lowerSnakeCase(s accounts.Platform) string {
return strings.ToLower(strings.Join(strings.Split(string(s), " "), "_"))
}