Merge pull request 'carts' (#25) from carts into main
Reviewed-on: #25 Reviewed-by: Marek Goc <goc_marek@ma-al.com>
This commit was merged in pull request #25.
This commit is contained in:
168
app/delivery/web/api/restricted/carts.go
Normal file
168
app/delivery/web/api/restricted/carts.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package restricted
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"git.ma-al.com/goc_daniel/b2b/app/service/cartsService"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
// CartsHandler handles endpoints that modify carts.
|
||||
type CartsHandler struct {
|
||||
cartsService *cartsService.CartsService
|
||||
}
|
||||
|
||||
// CartsHandler creates a new CartsHandler instance
|
||||
func NewCartsHandler() *CartsHandler {
|
||||
cartsService := cartsService.New()
|
||||
return &CartsHandler{
|
||||
cartsService: cartsService,
|
||||
}
|
||||
}
|
||||
|
||||
func CartsHandlerRoutes(r fiber.Router) fiber.Router {
|
||||
handler := NewCartsHandler()
|
||||
|
||||
r.Get("/add-new-cart", handler.AddNewCart)
|
||||
r.Get("/change-cart-name", handler.ChangeCartName)
|
||||
r.Get("/retrieve-carts-info", handler.RetrieveCartsInfo)
|
||||
r.Get("/retrieve-cart", handler.RetrieveCart)
|
||||
r.Get("/add-product-to-cart", handler.AddProduct)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (h *CartsHandler) AddNewCart(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("userID").(uint)
|
||||
if !ok {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||
}
|
||||
|
||||
new_cart, err := h.cartsService.CreateNewCart(userID)
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||
}
|
||||
|
||||
return c.JSON(response.Make(&new_cart, 0, i18n.T_(c, response.Message_OK)))
|
||||
}
|
||||
|
||||
func (h *CartsHandler) ChangeCartName(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("userID").(uint)
|
||||
if !ok {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||
}
|
||||
|
||||
new_name := c.Query("new_name")
|
||||
|
||||
cart_id_attribute := c.Query("cart_id")
|
||||
cart_id, err := strconv.Atoi(cart_id_attribute)
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||
}
|
||||
|
||||
err = h.cartsService.UpdateCartName(userID, uint(cart_id), new_name)
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||
}
|
||||
|
||||
return c.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(c, response.Message_OK)))
|
||||
}
|
||||
|
||||
func (h *CartsHandler) RetrieveCartsInfo(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("userID").(uint)
|
||||
if !ok {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||
}
|
||||
|
||||
carts_info, err := h.cartsService.RetrieveCartsInfo(userID)
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||
}
|
||||
|
||||
return c.JSON(response.Make(&carts_info, 0, i18n.T_(c, response.Message_OK)))
|
||||
}
|
||||
|
||||
func (h *CartsHandler) RetrieveCart(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("userID").(uint)
|
||||
if !ok {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||
}
|
||||
|
||||
cart_id_attribute := c.Query("cart_id")
|
||||
cart_id, err := strconv.Atoi(cart_id_attribute)
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||
}
|
||||
|
||||
cart, err := h.cartsService.RetrieveCart(userID, uint(cart_id))
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||
}
|
||||
|
||||
return c.JSON(response.Make(cart, 0, i18n.T_(c, response.Message_OK)))
|
||||
}
|
||||
|
||||
func (h *CartsHandler) AddProduct(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("userID").(uint)
|
||||
if !ok {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||
}
|
||||
|
||||
cart_id_attribute := c.Query("cart_id")
|
||||
cart_id, err := strconv.Atoi(cart_id_attribute)
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||
}
|
||||
|
||||
product_id_attribute := c.Query("product_id")
|
||||
product_id, err := strconv.Atoi(product_id_attribute)
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||
}
|
||||
|
||||
product_attribute_id_attribute := c.Query("product_attribute_id")
|
||||
var product_attribute_id *uint
|
||||
if product_attribute_id_attribute == "" {
|
||||
product_attribute_id = nil
|
||||
} else {
|
||||
val, err := strconv.Atoi(product_attribute_id_attribute)
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||
}
|
||||
uval := uint(val)
|
||||
product_attribute_id = &uval
|
||||
}
|
||||
|
||||
amount_attribute := c.Query("amount")
|
||||
amount, err := strconv.Atoi(amount_attribute)
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||
}
|
||||
|
||||
err = h.cartsService.AddProduct(userID, uint(cart_id), uint(product_id), product_attribute_id, uint(amount))
|
||||
if err != nil {
|
||||
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||
}
|
||||
|
||||
return c.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(c, response.Message_OK)))
|
||||
}
|
||||
@@ -110,6 +110,10 @@ func (s *Server) Setup() error {
|
||||
meiliSearch := s.restricted.Group("/meili-search")
|
||||
restricted.MeiliSearchHandlerRoutes(meiliSearch)
|
||||
|
||||
// carts (restricted)
|
||||
carts := s.restricted.Group("/carts")
|
||||
restricted.CartsHandlerRoutes(carts)
|
||||
|
||||
s.api.All("*", func(c fiber.Ctx) error {
|
||||
return c.SendStatus(fiber.StatusNotFound)
|
||||
})
|
||||
|
||||
24
app/model/cart.go
Normal file
24
app/model/cart.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package model
|
||||
|
||||
type CustomerCart struct {
|
||||
CartID uint `gorm:"column:cart_id;primaryKey;autoIncrement" json:"cart_id"`
|
||||
UserID uint `gorm:"column:user_id;not null;index" json:"-"`
|
||||
Name *string `gorm:"column:name;size:255" json:"name,omitempty"`
|
||||
Products []CartProduct `gorm:"foreignKey:CartID;references:CartID" json:"products,omitempty"`
|
||||
}
|
||||
|
||||
func (CustomerCart) TableName() string {
|
||||
return "b2b_customer_carts"
|
||||
}
|
||||
|
||||
type CartProduct struct {
|
||||
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"-"`
|
||||
CartID uint `gorm:"column:cart_id;not null;index" json:"-"`
|
||||
ProductID uint `gorm:"column:product_id;not null" json:"product_id"`
|
||||
ProductAttributeID *uint `gorm:"column:product_attribute_id" json:"product_attribute_id,omitempty"`
|
||||
Amount uint `gorm:"column:amount;not null" json:"amount"`
|
||||
}
|
||||
|
||||
func (CartProduct) TableName() string {
|
||||
return "b2b_carts_products"
|
||||
}
|
||||
133
app/repos/cartsRepo/cartsRepo.go
Normal file
133
app/repos/cartsRepo/cartsRepo.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package cartsRepo
|
||||
|
||||
import (
|
||||
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
||||
)
|
||||
|
||||
type UICartsRepo interface {
|
||||
CartsAmount(user_id uint) (uint, error)
|
||||
CreateNewCart(user_id uint) (model.CustomerCart, error)
|
||||
UserHasCart(user_id uint, cart_id uint) (uint, error)
|
||||
UpdateCartName(user_id uint, cart_id uint, new_name string) error
|
||||
RetrieveCartsInfo(user_id uint) ([]model.CustomerCart, error)
|
||||
RetrieveCart(user_id uint, cart_id uint) (*model.CustomerCart, error)
|
||||
CheckProductExists(product_id uint, product_attribute_id *uint) (uint, error)
|
||||
AddProduct(user_id uint, cart_id uint, product_id uint, product_attribute_id *uint, amount uint) error
|
||||
}
|
||||
|
||||
type CartsRepo struct{}
|
||||
|
||||
func New() UICartsRepo {
|
||||
return &CartsRepo{}
|
||||
}
|
||||
|
||||
func (repo *CartsRepo) CartsAmount(user_id uint) (uint, error) {
|
||||
var amt uint
|
||||
|
||||
err := db.DB.
|
||||
Table("b2b_customer_carts").
|
||||
Select("COUNT(*) AS amt").
|
||||
Where("user_id = ?", user_id).
|
||||
Scan(&amt).
|
||||
Error
|
||||
|
||||
return amt, err
|
||||
}
|
||||
|
||||
func (repo *CartsRepo) CreateNewCart(user_id uint) (model.CustomerCart, error) {
|
||||
var name string
|
||||
name = constdata.DEFAULT_NEW_CART_NAME
|
||||
|
||||
cart := model.CustomerCart{
|
||||
UserID: user_id,
|
||||
Name: &name,
|
||||
}
|
||||
err := db.DB.Create(&cart).Error
|
||||
|
||||
return cart, err
|
||||
}
|
||||
|
||||
func (repo *CartsRepo) UserHasCart(user_id uint, cart_id uint) (uint, error) {
|
||||
var amt uint
|
||||
|
||||
err := db.DB.
|
||||
Table("b2b_customer_carts").
|
||||
Select("COUNT(*) AS amt").
|
||||
Where("user_id = ? AND cart_id = ?", user_id, cart_id).
|
||||
Scan(&amt).
|
||||
Error
|
||||
|
||||
return amt, err
|
||||
}
|
||||
|
||||
func (repo *CartsRepo) UpdateCartName(user_id uint, cart_id uint, new_name string) error {
|
||||
err := db.DB.
|
||||
Table("b2b_customer_carts").
|
||||
Where("user_id = ? AND cart_id = ?", user_id, cart_id).
|
||||
Update("name", new_name).
|
||||
Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *CartsRepo) RetrieveCartsInfo(user_id uint) ([]model.CustomerCart, error) {
|
||||
var carts []model.CustomerCart
|
||||
|
||||
err := db.DB.
|
||||
Table("b2b_customer_carts").
|
||||
Where("user_id = ?", user_id).
|
||||
Scan(&carts).
|
||||
Error
|
||||
|
||||
return carts, err
|
||||
}
|
||||
|
||||
func (repo *CartsRepo) RetrieveCart(user_id uint, cart_id uint) (*model.CustomerCart, error) {
|
||||
var cart model.CustomerCart
|
||||
|
||||
err := db.DB.
|
||||
Preload("Products").
|
||||
Where("user_id = ? AND cart_id = ?", user_id, cart_id).
|
||||
First(&cart).
|
||||
Error
|
||||
|
||||
return &cart, err
|
||||
}
|
||||
|
||||
func (repo *CartsRepo) CheckProductExists(product_id uint, product_attribute_id *uint) (uint, error) {
|
||||
var amt uint
|
||||
|
||||
if product_attribute_id == nil {
|
||||
err := db.DB.
|
||||
Table("ps_product_shop").
|
||||
Select("COUNT(*) AS amt").
|
||||
Where("id_product = ?", product_id).
|
||||
Scan(&amt).
|
||||
Error
|
||||
return amt, err
|
||||
|
||||
} else {
|
||||
err := db.DB.
|
||||
Table("ps_product_shop AS ps").
|
||||
Joins("INNER JOIN ps_product_attribute_shop AS pas ON pas.id_product = ps.id_product").
|
||||
Select("COUNT(*) AS amt").
|
||||
Where("ps.id_product = ? AND pas.id_product_attribute = ?", product_id, *product_attribute_id).
|
||||
Scan(&amt).
|
||||
Error
|
||||
return amt, err
|
||||
}
|
||||
}
|
||||
|
||||
func (repo *CartsRepo) AddProduct(user_id uint, cart_id uint, product_id uint, product_attribute_id *uint, amount uint) error {
|
||||
product := model.CartProduct{
|
||||
CartID: cart_id,
|
||||
ProductID: product_id,
|
||||
ProductAttributeID: product_attribute_id,
|
||||
Amount: amount,
|
||||
}
|
||||
err := db.DB.Create(&product).Error
|
||||
|
||||
return err
|
||||
}
|
||||
83
app/service/cartsService/cartsService.go
Normal file
83
app/service/cartsService/cartsService.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package cartsService
|
||||
|
||||
import (
|
||||
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/repos/cartsRepo"
|
||||
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||
)
|
||||
|
||||
type CartsService struct {
|
||||
repo cartsRepo.UICartsRepo
|
||||
}
|
||||
|
||||
func New() *CartsService {
|
||||
return &CartsService{
|
||||
repo: cartsRepo.New(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CartsService) CreateNewCart(user_id uint) (model.CustomerCart, error) {
|
||||
var cart model.CustomerCart
|
||||
|
||||
customers_carts_amount, err := s.repo.CartsAmount(user_id)
|
||||
if err != nil {
|
||||
return cart, err
|
||||
}
|
||||
if customers_carts_amount >= constdata.MAX_AMOUNT_OF_CARTS_PER_USER {
|
||||
return cart, responseErrors.ErrMaxAmtOfCartsReached
|
||||
}
|
||||
|
||||
// create new cart for customer
|
||||
cart, err = s.repo.CreateNewCart(user_id)
|
||||
|
||||
return cart, nil
|
||||
}
|
||||
|
||||
func (s *CartsService) UpdateCartName(user_id uint, cart_id uint, new_name string) error {
|
||||
amt, err := s.repo.UserHasCart(user_id, cart_id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if amt != 1 {
|
||||
return responseErrors.ErrUserHasNoSuchCart
|
||||
}
|
||||
|
||||
return s.repo.UpdateCartName(user_id, cart_id, new_name)
|
||||
}
|
||||
|
||||
func (s *CartsService) RetrieveCartsInfo(user_id uint) ([]model.CustomerCart, error) {
|
||||
return s.repo.RetrieveCartsInfo(user_id)
|
||||
}
|
||||
|
||||
func (s *CartsService) RetrieveCart(user_id uint, cart_id uint) (*model.CustomerCart, error) {
|
||||
amt, err := s.repo.UserHasCart(user_id, cart_id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if amt != 1 {
|
||||
return nil, responseErrors.ErrUserHasNoSuchCart
|
||||
}
|
||||
|
||||
return s.repo.RetrieveCart(user_id, cart_id)
|
||||
}
|
||||
|
||||
func (s *CartsService) AddProduct(user_id uint, cart_id uint, product_id uint, product_attribute_id *uint, amount uint) error {
|
||||
amt, err := s.repo.UserHasCart(user_id, cart_id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if amt != 1 {
|
||||
return responseErrors.ErrUserHasNoSuchCart
|
||||
}
|
||||
|
||||
amt, err = s.repo.CheckProductExists(product_id, product_attribute_id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if amt != 1 {
|
||||
return responseErrors.ErrProductOrItsVariationDoesNotExist
|
||||
}
|
||||
|
||||
return s.repo.AddProduct(user_id, cart_id, product_id, product_attribute_id, amount)
|
||||
}
|
||||
@@ -3,3 +3,5 @@ package constdata
|
||||
// PASSWORD_VALIDATION_REGEX is used by the frontend (JavaScript supports lookaheads).
|
||||
const PASSWORD_VALIDATION_REGEX = `^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{10,}$`
|
||||
const SHOP_ID = 1
|
||||
const MAX_AMOUNT_OF_CARTS_PER_USER = 10
|
||||
const DEFAULT_NEW_CART_NAME = "new cart"
|
||||
|
||||
@@ -51,6 +51,11 @@ var (
|
||||
|
||||
// Typed errors for menu handler
|
||||
ErrNoRootFound = errors.New("no root found in categories table")
|
||||
|
||||
// Typed errors for carts handler
|
||||
ErrMaxAmtOfCartsReached = errors.New("maximal amount of carts reached")
|
||||
ErrUserHasNoSuchCart = errors.New("user does not have cart with given id")
|
||||
ErrProductOrItsVariationDoesNotExist = errors.New("product or its variation with given ids does not exist")
|
||||
)
|
||||
|
||||
// Error represents an error with HTTP status code
|
||||
@@ -141,6 +146,13 @@ func GetErrorCode(c fiber.Ctx, err error) string {
|
||||
case errors.Is(err, ErrNoRootFound):
|
||||
return i18n.T_(c, "error.no_root_found")
|
||||
|
||||
case errors.Is(err, ErrMaxAmtOfCartsReached):
|
||||
return i18n.T_(c, "error.max_amt_of_carts_reached")
|
||||
case errors.Is(err, ErrUserHasNoSuchCart):
|
||||
return i18n.T_(c, "error.user_has_no_such_cart")
|
||||
case errors.Is(err, ErrProductOrItsVariationDoesNotExist):
|
||||
return i18n.T_(c, "error.product_or_its_variation_does_not_exist")
|
||||
|
||||
default:
|
||||
return i18n.T_(c, "error.err_internal_server_error")
|
||||
}
|
||||
@@ -176,7 +188,10 @@ func GetErrorStatus(err error) int {
|
||||
errors.Is(err, ErrBadField),
|
||||
errors.Is(err, ErrInvalidXHTML),
|
||||
errors.Is(err, ErrBadPaging),
|
||||
errors.Is(err, ErrNoRootFound):
|
||||
errors.Is(err, ErrNoRootFound),
|
||||
errors.Is(err, ErrMaxAmtOfCartsReached),
|
||||
errors.Is(err, ErrUserHasNoSuchCart),
|
||||
errors.Is(err, ErrProductOrItsVariationDoesNotExist):
|
||||
return fiber.StatusBadRequest
|
||||
case errors.Is(err, ErrEmailExists):
|
||||
return fiber.StatusConflict
|
||||
|
||||
@@ -86,18 +86,27 @@ CREATE INDEX IF NOT EXISTS idx_customers_deleted_at
|
||||
ON b2b_customers (deleted_at);
|
||||
|
||||
|
||||
-- customer_repo_accesses
|
||||
-- CREATE TABLE IF NOT EXISTS b2b_customer_repo_accesses (
|
||||
-- user_id BIGINT NOT NULL,
|
||||
-- repo_id BIGINT NOT NULL,
|
||||
-- PRIMARY KEY (user_id, repo_id),
|
||||
-- CONSTRAINT fk_customer_repo_user
|
||||
-- FOREIGN KEY (user_id) REFERENCES b2b_customers(id)
|
||||
-- ON DELETE CASCADE,
|
||||
-- CONSTRAINT fk_customer_repo_repo
|
||||
-- FOREIGN KEY (repo_id) REFERENCES repository(id)
|
||||
-- ON DELETE CASCADE
|
||||
-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
-- customer_carts
|
||||
CREATE TABLE IF NOT EXISTS b2b_customer_carts (
|
||||
cart_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
name VARCHAR(255) NULL,
|
||||
CONSTRAINT fk_customer_carts_customers FOREIGN KEY (user_id) REFERENCES b2b_customers(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
|
||||
CREATE INDEX IF NOT EXISTS idx_customer_carts_user_id ON b2b_customer_carts (user_id);
|
||||
|
||||
|
||||
-- carts_products
|
||||
CREATE TABLE IF NOT EXISTS b2b_carts_products (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
cart_id BIGINT UNSIGNED NOT NULL,
|
||||
product_id INT UNSIGNED NOT NULL,
|
||||
product_attribute_id BIGINT NULL,
|
||||
amount INT UNSIGNED NOT NULL,
|
||||
CONSTRAINT fk_carts_products_customer_carts FOREIGN KEY (cart_id) REFERENCES b2b_customer_carts (cart_id) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_carts_products_product FOREIGN KEY (product_id) REFERENCES ps_product (id_product) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
|
||||
CREATE INDEX IF NOT EXISTS idx_carts_products_cart_id ON b2b_carts_products (cart_id);
|
||||
|
||||
|
||||
-- refresh_tokens
|
||||
|
||||
Reference in New Issue
Block a user