feat: creat main products query
This commit is contained in:
14
.vscode/launch.json
vendored
Normal file
14
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch Package",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "./app/cmd/main.go",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"envFile": "${workspaceFolder}/.env"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
97
app/delivery/web/api/restricted/currency.go
Normal file
97
app/delivery/web/api/restricted/currency.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
package restricted
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/config"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/service/currencyService"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CurrencyHandler struct {
|
||||||
|
CurrencyService *currencyService.CurrencyService
|
||||||
|
config *config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCurrencyHandler() *CurrencyHandler {
|
||||||
|
currencyService := currencyService.New()
|
||||||
|
return &CurrencyHandler{
|
||||||
|
CurrencyService: currencyService,
|
||||||
|
config: config.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CurrencyHandlerRoutes(r fiber.Router) fiber.Router {
|
||||||
|
handler := NewCurrencyHandler()
|
||||||
|
|
||||||
|
r.Post("/currency-rate", handler.PostCurrencyRate)
|
||||||
|
r.Get("/currency-rate/:id", handler.GetCurrencyRate)
|
||||||
|
// r.Get("/currencies", handler.GetCurrencyRates)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CurrencyHandler) PostCurrencyRate(c fiber.Ctx) error {
|
||||||
|
var currencyRate model.CurrencyRate
|
||||||
|
if err := c.Bind().Body(¤cyRate); err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrJSONBody)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrJSONBody)))
|
||||||
|
}
|
||||||
|
|
||||||
|
err := h.CurrencyService.CreateCurrencyRate(¤cyRate)
|
||||||
|
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(""), 1, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CurrencyHandler) GetCurrencyRate(c fiber.Ctx) error {
|
||||||
|
idStr := c.Params("id")
|
||||||
|
id, err := strconv.Atoi(idStr)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
currency, err := h.CurrencyService.GetCurrency(uint(id))
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// err = h.CurrencyService.GetCurrencyRate(userID, uint(productID), uint(productShopID), uint(productLangID), updates)
|
||||||
|
// if err != nil {
|
||||||
|
// return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
// JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
// }
|
||||||
|
|
||||||
|
return c.JSON(response.Make(currency, 0, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CurrencyHandler) GetCurrencyRates(c fiber.Ctx) error {
|
||||||
|
idStr := c.Params("id")
|
||||||
|
id, err := strconv.Atoi(idStr)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
currency, err := h.CurrencyService.GetCurrency(uint(id))
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// err = h.CurrencyService.GetCurrencyRate(userID, uint(productID), uint(productShopID), uint(productLangID), updates)
|
||||||
|
// if err != nil {
|
||||||
|
// return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
// JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
// }
|
||||||
|
|
||||||
|
return c.JSON(response.Make(currency, 0, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
82
app/delivery/web/api/restricted/product.go
Normal file
82
app/delivery/web/api/restricted/product.go
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package restricted
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/config"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/service/productService"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProductsHandler struct {
|
||||||
|
productService *productService.ProductService
|
||||||
|
config *config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewListProductsHandler creates a new ListProductsHandler instance
|
||||||
|
func NewProductsHandler() *ProductsHandler {
|
||||||
|
productService := productService.New()
|
||||||
|
return &ProductsHandler{
|
||||||
|
productService: productService,
|
||||||
|
config: config.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ProductsHandlerRoutes(r fiber.Router) fiber.Router {
|
||||||
|
handler := NewProductsHandler()
|
||||||
|
|
||||||
|
//TODO: WIP doesn't work yet
|
||||||
|
r.Get("/product/:id/:country_id/:quantity", handler.GetProductJson)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ProductsHandler) GetProductJson(c fiber.Ctx) error {
|
||||||
|
idStr := c.Params("id")
|
||||||
|
|
||||||
|
p_id_product, err := strconv.Atoi(idStr)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
country_idStr := c.Params("country_id")
|
||||||
|
|
||||||
|
b2b_id_country, err := strconv.Atoi(country_idStr)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
quantityStr := c.Params("quantity")
|
||||||
|
|
||||||
|
p_quantity, err := strconv.Atoi(quantityStr)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
id_lang, ok := c.Locals("lang_id").(int)
|
||||||
|
if !ok {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
|
}
|
||||||
|
|
||||||
|
p_id_customer, ok := c.Locals("user_id").(int)
|
||||||
|
if !ok {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
|
}
|
||||||
|
|
||||||
|
productJson, err := h.productService.GetJSON(p_id_product, id_lang, p_id_customer, b2b_id_country, p_quantity)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(response.Make(&productJson, 1, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
@@ -97,6 +97,8 @@ func (s *Server) Setup() error {
|
|||||||
listProducts := s.restricted.Group("/list-products")
|
listProducts := s.restricted.Group("/list-products")
|
||||||
restricted.ListProductsHandlerRoutes(listProducts)
|
restricted.ListProductsHandlerRoutes(listProducts)
|
||||||
|
|
||||||
|
restricted.ProductsHandlerRoutes(s.restricted)
|
||||||
|
|
||||||
// locale selector (restricted)
|
// locale selector (restricted)
|
||||||
// this is basically for changing user's selected language and country
|
// this is basically for changing user's selected language and country
|
||||||
localeSelector := s.restricted.Group("/langs-and-countries")
|
localeSelector := s.restricted.Group("/langs-and-countries")
|
||||||
@@ -118,6 +120,8 @@ func (s *Server) Setup() error {
|
|||||||
return c.SendStatus(fiber.StatusNotFound)
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
restricted.CurrencyHandlerRoutes(s.restricted)
|
||||||
|
|
||||||
// // Restricted routes example
|
// // Restricted routes example
|
||||||
// restricted := s.api.Group("/restricted")
|
// restricted := s.api.Group("/restricted")
|
||||||
// restricted.Use(middleware.AuthMiddleware())
|
// restricted.Use(middleware.AuthMiddleware())
|
||||||
|
|||||||
25
app/model/currency.go
Normal file
25
app/model/currency.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Currency struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
PsIDCurrency uint `json:"ps_id_currency"`
|
||||||
|
IsDefault bool `json:"is_default"`
|
||||||
|
IsActive bool `json:"is_active"`
|
||||||
|
ConversionRate *float64 `json:"conversion_rate,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Currency) TableName() string {
|
||||||
|
return "b2b_currencies"
|
||||||
|
}
|
||||||
|
|
||||||
|
type CurrencyRate struct {
|
||||||
|
B2bIdCurrency uint `json:"b2b_id_currency"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
ConversionRate *float64 `json:"conversion_rate,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (CurrencyRate) TableName() string {
|
||||||
|
return "b2b_currency_rates"
|
||||||
|
}
|
||||||
18
app/model/model.go
Normal file
18
app/model/model.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Model struct {
|
||||||
|
ID uint `gorm:"primarykey;autoIncrement" swaggerignore:"true" json:"id,omitempty" hidden:"true"`
|
||||||
|
CreatedAt time.Time `gorm:"not null;autoCreateTime" swaggerignore:"true" json:"-"`
|
||||||
|
UpdatedAt time.Time `gorm:"autoUpdateTime" swaggerignore:"true" json:"-"`
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index" swaggerignore:"true" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Makes all objects embedding db.Model implementators of ModelWithID interface
|
||||||
|
func (m Model) ModelWithID() {
|
||||||
|
}
|
||||||
53
app/repos/currencyRepo/currencyRepo.go
Normal file
53
app/repos/currencyRepo/currencyRepo.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package currencyRepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UICurrencyRepo interface {
|
||||||
|
CreateConversionRate(currencyRate *model.CurrencyRate) error
|
||||||
|
Get(id uint) (*model.Currency, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CurrencyRepo struct{}
|
||||||
|
|
||||||
|
func New() UICurrencyRepo {
|
||||||
|
return &CurrencyRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *CurrencyRepo) CreateConversionRate(currencyRate *model.CurrencyRate) error {
|
||||||
|
return db.DB.Debug().Create(currencyRate).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *CurrencyRepo) Get(id uint) (*model.Currency, error) {
|
||||||
|
var currency model.Currency
|
||||||
|
|
||||||
|
err := db.DB.Table("b2b_currencies c").
|
||||||
|
Select("c.*, r.conversion_rate").
|
||||||
|
Joins(`
|
||||||
|
LEFT JOIN b2b_currency_rates r
|
||||||
|
ON r.b2b_id_currency = c.id
|
||||||
|
AND r.created_at = (
|
||||||
|
SELECT MAX(created_at)
|
||||||
|
FROM b2b_currency_rates
|
||||||
|
WHERE b2b_id_currency = c.id
|
||||||
|
)
|
||||||
|
`).
|
||||||
|
Where("c.id = ?", id).
|
||||||
|
Scan(¤cy).Error
|
||||||
|
|
||||||
|
return ¤cy, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *CurrencyRepo) Find(langId uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.Currency], error) {
|
||||||
|
|
||||||
|
found, err := find.Paginate[model.Currency](langId, p, db.DB.
|
||||||
|
Model(&model.Currency{}).
|
||||||
|
Scopes(filt.All()...),
|
||||||
|
)
|
||||||
|
|
||||||
|
return &found, err
|
||||||
|
}
|
||||||
25
app/repos/productsRepo/productsRepo.go
Normal file
25
app/repos/productsRepo/productsRepo.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package productsRepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UIProductsRepo interface {
|
||||||
|
GetJSON(p_id_product, p_id_shop, p_id_lang, p_id_customer, b2b_id_country, p_quantity int) (*string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductsRepo struct{}
|
||||||
|
|
||||||
|
func New() UIProductsRepo {
|
||||||
|
return &ProductsRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *ProductsRepo) GetJSON(p_id_product, p_id_shop, p_id_lang, p_id_customer, b2b_id_country, p_quantity int) (*string, error) {
|
||||||
|
var product string
|
||||||
|
|
||||||
|
err := db.DB.Raw(`CALL get_full_product(?,?,?,?,?,?)`, p_id_product, p_id_shop, p_id_lang, p_id_customer, b2b_id_country, p_quantity).
|
||||||
|
Scan(&product).
|
||||||
|
Error
|
||||||
|
|
||||||
|
return &product, err
|
||||||
|
}
|
||||||
25
app/service/currencyService/currencyService.go
Normal file
25
app/service/currencyService/currencyService.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package currencyService
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/repos/currencyRepo"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CurrencyService struct {
|
||||||
|
repo currencyRepo.UICurrencyRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CurrencyService) GetCurrency(id uint) (*model.Currency, error) {
|
||||||
|
return s.repo.Get(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CurrencyService) CreateCurrencyRate(currency *model.CurrencyRate) error {
|
||||||
|
return s.repo.CreateConversionRate(currency)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *CurrencyService {
|
||||||
|
repo := currencyRepo.New()
|
||||||
|
return &CurrencyService{
|
||||||
|
repo: repo,
|
||||||
|
}
|
||||||
|
}
|
||||||
25
app/service/productService/productService.go
Normal file
25
app/service/productService/productService.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package productService
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/repos/productsRepo"
|
||||||
|
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProductService struct {
|
||||||
|
productsRepo productsRepo.UIProductsRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *ProductService {
|
||||||
|
return &ProductService{
|
||||||
|
productsRepo: productsRepo.New(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ProductService) GetJSON(p_id_product, p_id_lang, p_id_customer, b2b_id_country, p_quantity int) (*string, error) {
|
||||||
|
products, err := s.productsRepo.GetJSON(p_id_product, constdata.SHOP_ID, p_id_lang, p_id_customer, b2b_id_country, p_quantity)
|
||||||
|
if err != nil {
|
||||||
|
return products, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return products, nil
|
||||||
|
}
|
||||||
@@ -56,6 +56,9 @@ var (
|
|||||||
ErrMaxAmtOfCartsReached = errors.New("maximal amount of carts reached")
|
ErrMaxAmtOfCartsReached = errors.New("maximal amount of carts reached")
|
||||||
ErrUserHasNoSuchCart = errors.New("user does not have cart with given id")
|
ErrUserHasNoSuchCart = errors.New("user does not have cart with given id")
|
||||||
ErrProductOrItsVariationDoesNotExist = errors.New("product or its variation with given ids does not exist")
|
ErrProductOrItsVariationDoesNotExist = errors.New("product or its variation with given ids does not exist")
|
||||||
|
|
||||||
|
// Typed errors for data parsing
|
||||||
|
ErrJSONBody = errors.New("invalid JSON body")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error represents an error with HTTP status code
|
// Error represents an error with HTTP status code
|
||||||
@@ -153,6 +156,9 @@ func GetErrorCode(c fiber.Ctx, err error) string {
|
|||||||
case errors.Is(err, ErrProductOrItsVariationDoesNotExist):
|
case errors.Is(err, ErrProductOrItsVariationDoesNotExist):
|
||||||
return i18n.T_(c, "error.product_or_its_variation_does_not_exist")
|
return i18n.T_(c, "error.product_or_its_variation_does_not_exist")
|
||||||
|
|
||||||
|
case errors.Is(err, ErrJSONBody):
|
||||||
|
return i18n.T_(c, "error.err_json_body")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return i18n.T_(c, "error.err_internal_server_error")
|
return i18n.T_(c, "error.err_internal_server_error")
|
||||||
}
|
}
|
||||||
@@ -191,7 +197,8 @@ func GetErrorStatus(err error) int {
|
|||||||
errors.Is(err, ErrNoRootFound),
|
errors.Is(err, ErrNoRootFound),
|
||||||
errors.Is(err, ErrMaxAmtOfCartsReached),
|
errors.Is(err, ErrMaxAmtOfCartsReached),
|
||||||
errors.Is(err, ErrUserHasNoSuchCart),
|
errors.Is(err, ErrUserHasNoSuchCart),
|
||||||
errors.Is(err, ErrProductOrItsVariationDoesNotExist):
|
errors.Is(err, ErrProductOrItsVariationDoesNotExist),
|
||||||
|
errors.Is(err, ErrJSONBody):
|
||||||
return fiber.StatusBadRequest
|
return fiber.StatusBadRequest
|
||||||
case errors.Is(err, ErrEmailExists):
|
case errors.Is(err, ErrEmailExists):
|
||||||
return fiber.StatusConflict
|
return fiber.StatusConflict
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
-- +goose Up
|
-- +goose Up
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS b2b_language (
|
CREATE TABLE IF NOT EXISTS b2b_language (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||||
created_at DATETIME(6) NOT NULL,
|
created_at DATETIME(6) NOT NULL,
|
||||||
updated_at DATETIME(6) NULL,
|
updated_at DATETIME(6) NULL,
|
||||||
deleted_at DATETIME(6) NULL,
|
deleted_at DATETIME(6) NULL,
|
||||||
@@ -19,29 +19,22 @@ CREATE TABLE IF NOT EXISTS b2b_language (
|
|||||||
CREATE INDEX IF NOT EXISTS idx_language_deleted_at
|
CREATE INDEX IF NOT EXISTS idx_language_deleted_at
|
||||||
ON b2b_language (deleted_at);
|
ON b2b_language (deleted_at);
|
||||||
|
|
||||||
INSERT IGNORE INTO b2b_language
|
|
||||||
(id, created_at, updated_at, deleted_at, name, iso_code, lang_code, date_format, date_format_short, rtl, is_default, active, flag)
|
|
||||||
VALUES
|
|
||||||
(1, '2022-09-16 17:10:02.837', '2026-03-02 21:24:36.779730', NULL, 'Polski', 'pl', 'pl', '__-__-____', '__-__', 0, 0, 1, '🇵🇱'),
|
|
||||||
(2, '2022-09-16 17:10:02.852', '2026-03-02 21:24:36.779730', NULL, 'English', 'en', 'en', '__-__-____', '__-__', 0, 1, 1, '🇬🇧'),
|
|
||||||
(3, '2022-09-16 17:10:02.852', '2026-03-02 21:24:36.779730', NULL, 'Deutsch', 'de', 'de', '__-__-____', '__-__', 0, 0, 1, '🇩🇪');
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS b2b_components (
|
CREATE TABLE IF NOT EXISTS b2b_components (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||||
name VARCHAR(255) NOT NULL
|
name VARCHAR(255) NOT NULL
|
||||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
|
||||||
CREATE UNIQUE INDEX IF NOT EXISTS uk_components_name ON b2b_components (name, id);
|
CREATE UNIQUE INDEX IF NOT EXISTS uk_components_name ON b2b_components (name, id);
|
||||||
-- scopes
|
-- scopes
|
||||||
CREATE TABLE IF NOT EXISTS b2b_scopes (
|
CREATE TABLE IF NOT EXISTS b2b_scopes (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||||
name VARCHAR(255) NOT NULL
|
name VARCHAR(255) NOT NULL
|
||||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
|
||||||
CREATE UNIQUE INDEX IF NOT EXISTS uk_scopes_name ON b2b_scopes (name);
|
CREATE UNIQUE INDEX IF NOT EXISTS uk_scopes_name ON b2b_scopes (name);
|
||||||
-- translations
|
-- translations
|
||||||
CREATE TABLE IF NOT EXISTS b2b_translations (
|
CREATE TABLE IF NOT EXISTS b2b_translations (
|
||||||
lang_id INT NOT NULL,
|
lang_id INT UNSIGNED NOT NULL,
|
||||||
scope_id INT NOT NULL,
|
scope_id INT UNSIGNED NOT NULL,
|
||||||
component_id INT NOT NULL,
|
component_id INT UNSIGNED NOT NULL,
|
||||||
`key` VARCHAR(255) NOT NULL,
|
`key` VARCHAR(255) NOT NULL,
|
||||||
data TEXT NULL,
|
data TEXT NULL,
|
||||||
PRIMARY KEY (lang_id, scope_id, component_id, `key`),
|
PRIMARY KEY (lang_id, scope_id, component_id, `key`),
|
||||||
@@ -71,8 +64,8 @@ CREATE TABLE IF NOT EXISTS b2b_customers (
|
|||||||
password_reset_expires DATETIME(6) NULL,
|
password_reset_expires DATETIME(6) NULL,
|
||||||
last_password_reset_request DATETIME(6) NULL,
|
last_password_reset_request DATETIME(6) NULL,
|
||||||
last_login_at DATETIME(6) NULL,
|
last_login_at DATETIME(6) NULL,
|
||||||
lang_id BIGINT NULL DEFAULT 2,
|
lang_id INT NULL DEFAULT 2,
|
||||||
country_id BIGINT NULL DEFAULT 2,
|
country_id INT NULL DEFAULT 2,
|
||||||
created_at DATETIME(6) NULL,
|
created_at DATETIME(6) NULL,
|
||||||
updated_at DATETIME(6) NULL,
|
updated_at DATETIME(6) NULL,
|
||||||
deleted_at DATETIME(6) NULL
|
deleted_at DATETIME(6) NULL
|
||||||
@@ -87,7 +80,7 @@ ON b2b_customers (deleted_at);
|
|||||||
|
|
||||||
-- customer_carts
|
-- customer_carts
|
||||||
CREATE TABLE IF NOT EXISTS b2b_customer_carts (
|
CREATE TABLE IF NOT EXISTS b2b_customer_carts (
|
||||||
cart_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
cart_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
user_id BIGINT UNSIGNED NOT NULL,
|
user_id BIGINT UNSIGNED NOT NULL,
|
||||||
name VARCHAR(255) NULL,
|
name VARCHAR(255) NULL,
|
||||||
CONSTRAINT fk_customer_carts_customers FOREIGN KEY (user_id) REFERENCES b2b_customers(id) ON DELETE CASCADE ON UPDATE CASCADE
|
CONSTRAINT fk_customer_carts_customers FOREIGN KEY (user_id) REFERENCES b2b_customers(id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
@@ -97,10 +90,10 @@ CREATE INDEX IF NOT EXISTS idx_customer_carts_user_id ON b2b_customer_carts (use
|
|||||||
|
|
||||||
-- carts_products
|
-- carts_products
|
||||||
CREATE TABLE IF NOT EXISTS b2b_carts_products (
|
CREATE TABLE IF NOT EXISTS b2b_carts_products (
|
||||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
cart_id BIGINT UNSIGNED NOT NULL,
|
cart_id INT UNSIGNED NOT NULL,
|
||||||
product_id INT UNSIGNED NOT NULL,
|
product_id INT UNSIGNED NOT NULL,
|
||||||
product_attribute_id BIGINT NULL,
|
product_attribute_id INT NULL,
|
||||||
amount INT UNSIGNED NOT 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_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
|
CONSTRAINT fk_carts_products_product FOREIGN KEY (product_id) REFERENCES ps_product (id_product) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
@@ -110,7 +103,7 @@ CREATE INDEX IF NOT EXISTS idx_carts_products_cart_id ON b2b_carts_products (car
|
|||||||
|
|
||||||
-- refresh_tokens
|
-- refresh_tokens
|
||||||
CREATE TABLE IF NOT EXISTS b2b_refresh_tokens (
|
CREATE TABLE IF NOT EXISTS b2b_refresh_tokens (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||||
customer_id BIGINT UNSIGNED NOT NULL,
|
customer_id BIGINT UNSIGNED NOT NULL,
|
||||||
token_hash VARCHAR(64) NOT NULL,
|
token_hash VARCHAR(64) NOT NULL,
|
||||||
expires_at DATETIME(6) NOT NULL,
|
expires_at DATETIME(6) NOT NULL,
|
||||||
@@ -120,24 +113,146 @@ CREATE TABLE IF NOT EXISTS b2b_refresh_tokens (
|
|||||||
CREATE UNIQUE INDEX IF NOT EXISTS uk_refresh_tokens_token_hash ON b2b_refresh_tokens (token_hash);
|
CREATE UNIQUE INDEX IF NOT EXISTS uk_refresh_tokens_token_hash ON b2b_refresh_tokens (token_hash);
|
||||||
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_customer_id ON b2b_refresh_tokens (customer_id);
|
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_customer_id ON b2b_refresh_tokens (customer_id);
|
||||||
|
|
||||||
|
CREATE TABLE `b2b_currencies` (
|
||||||
|
`id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
|
||||||
|
`ps_id_currency` INT UNSIGNED NOT NULL,
|
||||||
|
`is_default` TINYINT NOT NULL,
|
||||||
|
`is_active` TINYINT NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
)
|
||||||
|
ENGINE = InnoDB;
|
||||||
|
|
||||||
|
ALTER TABLE `b2b_currencies` ADD CONSTRAINT `FK_b2b_currencies_ps_id_currency` FOREIGN KEY (`ps_id_currency`) REFERENCES `ps_currency` (`id_currency`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
CREATE INDEX `fk_b2b_currencies_ps_currency`
|
||||||
|
ON `b2b_currencies` (
|
||||||
|
`ps_id_currency` ASC
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `b2b_currency_rates` (
|
||||||
|
`id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
|
||||||
|
`b2b_id_currency` BIGINT UNSIGNED NOT NULL,
|
||||||
|
`created_at` DATETIME NOT NULL,
|
||||||
|
`conversion_rate` DECIMAL(13,6) NULL DEFAULT NULL ,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
)
|
||||||
|
ENGINE = InnoDB;
|
||||||
|
ALTER TABLE `b2b_currency_rates` ADD CONSTRAINT `FK_b2b_currency_rates_b2b_id_currency` FOREIGN KEY (`b2b_id_currency`) REFERENCES `b2b_currencies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
CREATE INDEX `fk_b2b_currency_rates_b2b_currencies`
|
||||||
|
ON `b2b_currency_rates` (
|
||||||
|
`b2b_id_currency` ASC
|
||||||
|
);
|
||||||
|
|
||||||
-- countries
|
-- countries
|
||||||
CREATE TABLE IF NOT EXISTS b2b_countries (
|
CREATE TABLE IF NOT EXISTS b2b_countries (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
`id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
|
||||||
name VARCHAR(128) NOT NULL,
|
`flag` VARCHAR(16) NOT NULL,
|
||||||
currency_id INT UNSIGNED NOT NULL,
|
`ps_id_country` INT UNSIGNED NOT NULL,
|
||||||
flag VARCHAR(16) NOT NULL,
|
`b2b_id_currency` BIGINT UNSIGNED NOT NULL,
|
||||||
CONSTRAINT fk_countries_currency FOREIGN KEY (currency_id) REFERENCES ps_currency(id_currency) ON DELETE RESTRICT ON UPDATE RESTRICT
|
PRIMARY KEY (`id`),
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
CONSTRAINT `fk_b2b_countries_ps_country` FOREIGN KEY (`ps_id_country`) REFERENCES `ps_country` (`id_country`) ON DELETE NO ACTION ON UPDATE NO ACTION,
|
||||||
|
CONSTRAINT `FK_b2b_countries_b2b_id_currency` FOREIGN KEY (`b2b_id_currency`) REFERENCES `b2b_currencies` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
|
||||||
|
)
|
||||||
|
ENGINE = InnoDB;
|
||||||
|
CREATE INDEX `fk_b2b_countries_ps_country`
|
||||||
|
ON `b2b_countries` (
|
||||||
|
`ps_id_country` ASC
|
||||||
|
);
|
||||||
|
|
||||||
INSERT IGNORE INTO b2b_countries
|
CREATE TABLE b2b_specific_price (
|
||||||
(id, name, currency_id, flag)
|
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||||
VALUES
|
name VARCHAR(255) NOT NULL,
|
||||||
(1, 'Polska', 1, '🇵🇱'),
|
created_at DATETIME NULL,
|
||||||
(2, 'England', 2, '🇬🇧'),
|
updated_at DATETIME NULL,
|
||||||
(3, 'Čeština', 2, '🇨🇿'),
|
deleted_at DATETIME NULL,
|
||||||
(4, 'Deutschland', 2, '🇩🇪');
|
scope ENUM('shop', 'category', 'product') NOT NULL,
|
||||||
|
valid_from DATETIME NULL,
|
||||||
|
valid_till DATETIME NULL,
|
||||||
|
has_expiration_date BOOLEAN DEFAULT FALSE,
|
||||||
|
reduction_type ENUM('amount', 'percentage') NOT NULL,
|
||||||
|
price DECIMAL(10, 2) NULL,
|
||||||
|
b2b_id_currency BIGINT UNSIGNED NULL, -- specifies which currency is used for the price
|
||||||
|
percentage_reduction DECIMAL(5, 2) NULL,
|
||||||
|
from_quantity INT UNSIGNED DEFAULT 1,
|
||||||
|
is_active BOOLEAN DEFAULT TRUE,
|
||||||
|
CONSTRAINT fk_b2b_specific_price_country FOREIGN KEY (b2b_id_country) REFERENCES b2b_countries(id) ON DELETE
|
||||||
|
SET
|
||||||
|
NULL ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT fk_b2b_specific_price_customer FOREIGN KEY (b2b_id_customer) REFERENCES b2b_customers(id) ON DELETE
|
||||||
|
SET
|
||||||
|
NULL ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT fk_b2b_specific_price_currency FOREIGN KEY (b2b_id_currency) REFERENCES b2b_currencies(id) ON DELETE
|
||||||
|
SET
|
||||||
|
NULL ON UPDATE CASCADE
|
||||||
|
) ENGINE = InnoDB;
|
||||||
|
CREATE INDEX idx_b2b_scope ON b2b_specific_price(scope);
|
||||||
|
CREATE INDEX idx_b2b_customer ON b2b_specific_price(b2b_id_customer);
|
||||||
|
CREATE INDEX idx_b2b_country ON b2b_specific_price(b2b_id_country);
|
||||||
|
CREATE INDEX idx_b2b_active_dates ON b2b_specific_price(is_active, valid_from, valid_till);
|
||||||
|
CREATE INDEX idx_b2b_lookup
|
||||||
|
ON b2b_specific_price (
|
||||||
|
scope,
|
||||||
|
is_active,
|
||||||
|
b2b_id_customer,
|
||||||
|
b2b_id_country,
|
||||||
|
from_quantity
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE b2b_specific_price_product (
|
||||||
|
b2b_specific_price_id BIGINT UNSIGNED,
|
||||||
|
id_product INT UNSIGNED,
|
||||||
|
PRIMARY KEY (b2b_specific_price_id, id_product),
|
||||||
|
FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (id_product) REFERENCES ps_product(id_product) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE b2b_specific_price_category (
|
||||||
|
b2b_specific_price_id BIGINT UNSIGNED,
|
||||||
|
id_category INT UNSIGNED,
|
||||||
|
PRIMARY KEY (b2b_specific_price_id, id_category),
|
||||||
|
FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (id_category) REFERENCES ps_category(id_category) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE b2b_specific_price_product_attribute (
|
||||||
|
b2b_specific_price_id BIGINT UNSIGNED,
|
||||||
|
id_product_attribute INT UNSIGNED,
|
||||||
|
PRIMARY KEY (b2b_specific_price_id, id_product_attribute),
|
||||||
|
FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (id_product_attribute) REFERENCES ps_product_attribute(id_product_attribute) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE b2b_specific_price_customer (
|
||||||
|
b2b_specific_price_id BIGINT UNSIGNED,
|
||||||
|
b2b_id_customer BIGINT UNSIGNED,
|
||||||
|
PRIMARY KEY (b2b_specific_price_id, b2b_id_customer),
|
||||||
|
FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (b2b_id_customer) REFERENCES b2b_customers(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE b2b_specific_price_country (
|
||||||
|
b2b_specific_price_id BIGINT UNSIGNED,
|
||||||
|
b2b_id_country BIGINT UNSIGNED,
|
||||||
|
PRIMARY KEY (b2b_specific_price_id, b2b_id_country),
|
||||||
|
FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (b2b_id_country) REFERENCES b2b_countries(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_b2b_product_rel
|
||||||
|
ON b2b_specific_price_product (id_product);
|
||||||
|
|
||||||
|
CREATE INDEX idx_b2b_category_rel
|
||||||
|
ON b2b_specific_price_category (id_category);
|
||||||
|
|
||||||
|
CREATE INDEX idx_b2b_product_attribute_rel
|
||||||
|
ON b2b_specific_price_product_attribute (id_product_attribute);
|
||||||
|
|
||||||
|
CREATE INDEX idx_bsp_customer
|
||||||
|
ON b2b_specific_price_customer (b2b_specific_price_id, b2b_id_customer);
|
||||||
|
|
||||||
|
CREATE INDEX idx_bsp_country
|
||||||
|
ON b2b_specific_price_country (b2b_specific_price_id, b2b_id_country);
|
||||||
-- +goose Down
|
-- +goose Down
|
||||||
|
|
||||||
DROP TABLE IF EXISTS b2b_countries;
|
DROP TABLE IF EXISTS b2b_countries;
|
||||||
@@ -147,3 +262,9 @@ DROP TABLE IF EXISTS b2b_scopes;
|
|||||||
DROP TABLE IF EXISTS b2b_translations;
|
DROP TABLE IF EXISTS b2b_translations;
|
||||||
DROP TABLE IF EXISTS b2b_customers;
|
DROP TABLE IF EXISTS b2b_customers;
|
||||||
DROP TABLE IF EXISTS b2b_refresh_tokens;
|
DROP TABLE IF EXISTS b2b_refresh_tokens;
|
||||||
|
DROP TABLE IF EXISTS b2b_currencies;
|
||||||
|
DROP TABLE IF EXISTS b2b_currency_rates;
|
||||||
|
DROP TABLE IF EXISTS b2b_specific_price;
|
||||||
|
DROP TABLE IF EXISTS b2b_specific_price_product;
|
||||||
|
DROP TABLE IF EXISTS b2b_specific_price_category;
|
||||||
|
DROP TABLE IF EXISTS b2b_specific_price_product_attribute;
|
||||||
|
|||||||
32
i18n/migrations/20260302163123_create_tables_data.sql
Normal file
32
i18n/migrations/20260302163123_create_tables_data.sql
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
-- +goose Up
|
||||||
|
|
||||||
|
INSERT IGNORE INTO b2b_language
|
||||||
|
(id, created_at, updated_at, deleted_at, name, iso_code, lang_code, date_format, date_format_short, rtl, is_default, active, flag)
|
||||||
|
VALUES
|
||||||
|
(1, '2022-09-16 17:10:02.837', '2026-03-02 21:24:36.779730', NULL, 'Polski', 'pl', 'pl', '__-__-____', '__-__', 0, 0, 1, '🇵🇱'),
|
||||||
|
(2, '2022-09-16 17:10:02.852', '2026-03-02 21:24:36.779730', NULL, 'English', 'en', 'en', '__-__-____', '__-__', 0, 1, 1, '🇬🇧'),
|
||||||
|
(3, '2022-09-16 17:10:02.852', '2026-03-02 21:24:36.779730', NULL, 'Deutsch', 'de', 'de', '__-__-____', '__-__', 0, 0, 1, '🇩🇪');
|
||||||
|
|
||||||
|
|
||||||
|
-- insert sample admin user admin@ma-al.com/Maal12345678
|
||||||
|
|
||||||
|
INSERT IGNORE INTO b2b_customers (id, email, password, first_name, last_name, role, provider, provider_id, avatar_url, is_active, email_verified, email_verification_token, email_verification_expires, password_reset_token, password_reset_expires, last_password_reset_request, last_login_at, lang_id, country_id, created_at, updated_at, deleted_at)
|
||||||
|
VALUES
|
||||||
|
(1, 'admin@ma-al.com', '$2a$10$Owy9DjrS0l3Fz4XoOvh5pulgmOMqdwXmb7hYE9BovnSuWS2plGr82', 'Super', 'Admin', 'admin', 'local', '', '', 1, 1, NULL, NULL, '', NULL, NULL, NULL, 1, 1, '2026-03-02 16:55:10.252740', '2026-03-02 16:55:10.252740', NULL);
|
||||||
|
ALTER TABLE b2b_customers AUTO_INCREMENT = 1;
|
||||||
|
|
||||||
|
INSERT INTO `b2b_currencies` (`ps_id_currency`, `is_default`, `is_active`) VALUES
|
||||||
|
('1','1','1'),
|
||||||
|
('2','0','1');
|
||||||
|
|
||||||
|
INSERT IGNORE INTO b2b_countries
|
||||||
|
(id, flag, ps_id_country, b2b_id_currency)
|
||||||
|
VALUES
|
||||||
|
(1, '🇵🇱', 14, 1),
|
||||||
|
(2, '🇬🇧', 17, 2),
|
||||||
|
(3, '🇨🇿', 16, 2),
|
||||||
|
(4, '🇩🇪', 1, 2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
@@ -1,223 +1,362 @@
|
|||||||
-- +goose Up
|
-- +goose Up
|
||||||
DELIMITER //
|
DELIMITER //
|
||||||
|
DROP PROCEDURE IF EXISTS get_full_product
|
||||||
DROP PROCEDURE IF EXISTS get_full_product //
|
//
|
||||||
|
|
||||||
CREATE PROCEDURE get_full_product(
|
CREATE PROCEDURE get_full_product(
|
||||||
IN p_id_product INT UNSIGNED,
|
IN p_id_product INT UNSIGNED,
|
||||||
IN p_id_shop INT UNSIGNED,
|
IN p_id_shop INT UNSIGNED,
|
||||||
IN p_id_lang INT UNSIGNED,
|
IN p_id_lang INT UNSIGNED,
|
||||||
IN p_id_customer INT UNSIGNED,
|
IN p_id_customer INT UNSIGNED,
|
||||||
IN p_id_group INT UNSIGNED,
|
IN b2b_id_country INT UNSIGNED,
|
||||||
IN p_id_currency INT UNSIGNED,
|
IN p_quantity INT UNSIGNED
|
||||||
IN p_id_country INT UNSIGNED,
|
)
|
||||||
IN p_quantity INT UNSIGNED
|
BEGIN
|
||||||
)
|
DECLARE v_tax_rate DECIMAL(10, 4) DEFAULT 0;
|
||||||
BEGIN
|
DECLARE p_id_currency DECIMAL(10, 4) DEFAULT 0;
|
||||||
|
SELECT
|
||||||
DECLARE v_tax_rate DECIMAL(10,4) DEFAULT 0;
|
COALESCE(t.rate, 0.0000) INTO v_tax_rate
|
||||||
|
FROM
|
||||||
SELECT COALESCE(t.rate, 0.0000) INTO v_tax_rate
|
ps_tax_rule tr
|
||||||
FROM ps_tax_rule tr
|
INNER JOIN ps_tax t ON t.id_tax = tr.id_tax
|
||||||
INNER JOIN ps_tax t
|
LEFT JOIN b2b_countries ON b2b_countries.id = b2b_id_country
|
||||||
ON t.id_tax = tr.id_tax
|
WHERE
|
||||||
WHERE tr.id_tax_rules_group = (
|
tr.id_tax_rules_group = (
|
||||||
SELECT ps.id_tax_rules_group
|
SELECT
|
||||||
FROM ps_product_shop ps
|
ps.id_tax_rules_group
|
||||||
WHERE ps.id_product = p_id_product
|
FROM
|
||||||
AND ps.id_shop = p_id_shop
|
ps_product_shop ps
|
||||||
LIMIT 1
|
WHERE
|
||||||
)
|
ps.id_product = p_id_product
|
||||||
AND tr.id_country = p_id_country
|
AND ps.id_shop = p_id_shop
|
||||||
ORDER BY
|
LIMIT
|
||||||
tr.id_state DESC,
|
1
|
||||||
tr.zipcode_from != '' DESC,
|
)
|
||||||
tr.id_tax_rule DESC
|
AND tr.id_country = b2b_countries.ps_id_country
|
||||||
|
ORDER BY
|
||||||
|
tr.id_state DESC,
|
||||||
|
tr.zipcode_from != '' DESC,
|
||||||
|
tr.id_tax_rule DESC
|
||||||
|
LIMIT
|
||||||
|
1;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
b2b_currencies.ps_id_currency INTO p_id_currency
|
||||||
|
FROM
|
||||||
|
b2b_currencies
|
||||||
|
LEFT JOIN b2b_countries ON b2b_countries.b2b_id_currency = b2b_currencies.id
|
||||||
|
WHERE
|
||||||
|
b2b_countries.id = b2b_id_country
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
|
/* FINAL JSON */
|
||||||
|
SELECT
|
||||||
|
JSON_OBJECT(
|
||||||
|
/* ================= PRODUCT ================= */
|
||||||
|
'id_product',
|
||||||
|
p.id_product,
|
||||||
|
'reference',
|
||||||
|
p.reference,
|
||||||
|
'name',
|
||||||
|
pl.name,
|
||||||
|
'description',
|
||||||
|
pl.description,
|
||||||
|
'short_description',
|
||||||
|
pl.description_short,
|
||||||
|
/* ================= PRICE ================= */
|
||||||
|
'price',
|
||||||
|
JSON_OBJECT(
|
||||||
|
'base',
|
||||||
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate),
|
||||||
|
|
||||||
/* FINAL JSON */
|
'final_tax_excl',
|
||||||
SELECT JSON_OBJECT(
|
(
|
||||||
|
CASE
|
||||||
/* ================= PRODUCT ================= */
|
WHEN bsp.id IS NOT NULL THEN
|
||||||
'id_product', p.id_product,
|
CASE
|
||||||
'reference', p.reference,
|
/* FIXED PRICE */
|
||||||
'name', pl.name,
|
WHEN bsp.reduction_type = 'amount' THEN
|
||||||
'description', pl.description,
|
|
||||||
'short_description', pl.description_short,
|
|
||||||
|
|
||||||
/* ================= PRICE ================= */
|
|
||||||
'price', JSON_OBJECT(
|
|
||||||
'base', COALESCE(ps.price, p.price),
|
|
||||||
|
|
||||||
'final_tax_excl',
|
|
||||||
(
|
(
|
||||||
COALESCE(ps.price, p.price)
|
CASE
|
||||||
- IFNULL(
|
WHEN bsp.b2b_id_currency IS NULL THEN bsp.price
|
||||||
CASE
|
ELSE bsp.price * br_bsp.conversion_rate
|
||||||
WHEN sp.reduction_type = 'amount' THEN sp.reduction
|
END
|
||||||
WHEN sp.reduction_type = 'percentage' THEN COALESCE(ps.price, p.price) * sp.reduction
|
|
||||||
ELSE 0
|
|
||||||
END, 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|
|
||||||
'final_tax_incl',
|
|
||||||
(
|
|
||||||
(
|
|
||||||
COALESCE(ps.price, p.price)
|
|
||||||
- IFNULL(
|
|
||||||
CASE
|
|
||||||
WHEN sp.reduction_type = 'amount' THEN sp.reduction
|
|
||||||
WHEN sp.reduction_type = 'percentage' THEN COALESCE(ps.price, p.price) * sp.reduction
|
|
||||||
ELSE 0
|
|
||||||
END, 0
|
|
||||||
)
|
|
||||||
) * (1 + v_tax_rate / 100)
|
|
||||||
)
|
)
|
||||||
),
|
|
||||||
|
|
||||||
/* ================= META ================= */
|
/* PERCENTAGE */
|
||||||
'active', COALESCE(ps.active, p.active),
|
WHEN bsp.reduction_type = 'percentage' THEN
|
||||||
'visibility', COALESCE(ps.visibility, p.visibility),
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
||||||
'manufacturer', m.name,
|
* (1 - bsp.percentage_reduction / 100)
|
||||||
'category', cl.name,
|
|
||||||
|
|
||||||
/* ================= IMAGE ================= */
|
ELSE
|
||||||
'cover_image', JSON_OBJECT(
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
||||||
'id', i.id_image,
|
END
|
||||||
'legend', il.legend
|
|
||||||
),
|
|
||||||
|
|
||||||
/* ================= FEATURES ================= */
|
ELSE
|
||||||
'features', (
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
||||||
SELECT JSON_ARRAYAGG(
|
END
|
||||||
JSON_OBJECT(
|
),
|
||||||
'name', fl.name,
|
|
||||||
'value', fvl.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
FROM ps_feature_product fp
|
|
||||||
JOIN ps_feature_lang fl
|
|
||||||
ON fl.id_feature = fp.id_feature AND fl.id_lang = p_id_lang
|
|
||||||
JOIN ps_feature_value_lang fvl
|
|
||||||
ON fvl.id_feature_value = fp.id_feature_value AND fvl.id_lang = p_id_lang
|
|
||||||
WHERE fp.id_product = p.id_product
|
|
||||||
),
|
|
||||||
|
|
||||||
/* ================= COMBINATIONS ================= */
|
'final_tax_incl',
|
||||||
'combinations', (
|
(
|
||||||
SELECT JSON_ARRAYAGG(
|
(
|
||||||
JSON_OBJECT(
|
CASE
|
||||||
'id_product_attribute', pa.id_product_attribute,
|
WHEN bsp.id IS NOT NULL THEN
|
||||||
'reference', pa.reference,
|
CASE
|
||||||
|
WHEN bsp.reduction_type = 'amount' THEN
|
||||||
|
(
|
||||||
|
CASE
|
||||||
|
WHEN bsp.b2b_id_currency IS NULL THEN bsp.price
|
||||||
|
ELSE bsp.price * br_bsp.conversion_rate
|
||||||
|
END
|
||||||
|
)
|
||||||
|
|
||||||
'price', JSON_OBJECT(
|
WHEN bsp.reduction_type = 'percentage' THEN
|
||||||
'impact', COALESCE(pas.price, pa.price),
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
||||||
|
* (1 - bsp.percentage_reduction / 100)
|
||||||
|
|
||||||
'final_tax_excl',
|
ELSE
|
||||||
(
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
||||||
COALESCE(ps.price, p.price)
|
END
|
||||||
+ COALESCE(pas.price, pa.price)
|
ELSE
|
||||||
),
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
||||||
|
END
|
||||||
'final_tax_incl',
|
) * (1 + v_tax_rate / 100)
|
||||||
(
|
)
|
||||||
(
|
),
|
||||||
COALESCE(ps.price, p.price)
|
/* ================= META ================= */
|
||||||
+ COALESCE(pas.price, pa.price)
|
'active',
|
||||||
) * (1 + v_tax_rate / 100)
|
COALESCE(ps.active, p.active),
|
||||||
)
|
'visibility',
|
||||||
),
|
COALESCE(ps.visibility, p.visibility),
|
||||||
|
'manufacturer',
|
||||||
'stock', IFNULL(sa.quantity, 0),
|
m.name,
|
||||||
|
'category',
|
||||||
'default_on', pas.default_on,
|
cl.name,
|
||||||
|
/* ================= IMAGE ================= */
|
||||||
/* ATTRIBUTES JSON */
|
'cover_image',
|
||||||
'attributes', (
|
JSON_OBJECT(
|
||||||
SELECT JSON_ARRAYAGG(
|
'id',
|
||||||
JSON_OBJECT(
|
i.id_image,
|
||||||
'group', agl.name,
|
'legend',
|
||||||
'attribute', al.name
|
il.legend
|
||||||
)
|
),
|
||||||
)
|
/* ================= FEATURES ================= */
|
||||||
FROM ps_product_attribute_combination pac
|
'features',
|
||||||
JOIN ps_attribute a ON a.id_attribute = pac.id_attribute
|
(
|
||||||
JOIN ps_attribute_lang al
|
SELECT
|
||||||
ON al.id_attribute = a.id_attribute AND al.id_lang = p_id_lang
|
JSON_ARRAYAGG(
|
||||||
JOIN ps_attribute_group_lang agl
|
JSON_OBJECT(
|
||||||
ON agl.id_attribute_group = a.id_attribute_group AND agl.id_lang = p_id_lang
|
'name',
|
||||||
WHERE pac.id_product_attribute = pa.id_product_attribute
|
fl.name,
|
||||||
),
|
'value',
|
||||||
|
fvl.value
|
||||||
/* IMAGES */
|
)
|
||||||
'images', (
|
|
||||||
SELECT JSON_ARRAYAGG(img.id_image)
|
|
||||||
FROM ps_product_attribute_image pai
|
|
||||||
JOIN ps_image img ON img.id_image = pai.id_image
|
|
||||||
WHERE pai.id_product_attribute = pa.id_product_attribute
|
|
||||||
)
|
|
||||||
|
|
||||||
)
|
|
||||||
)
|
|
||||||
FROM ps_product_attribute pa
|
|
||||||
JOIN ps_product_attribute_shop pas
|
|
||||||
ON pas.id_product_attribute = pa.id_product_attribute
|
|
||||||
AND pas.id_shop = p_id_shop
|
|
||||||
LEFT JOIN ps_stock_available sa
|
|
||||||
ON sa.id_product = pa.id_product
|
|
||||||
AND sa.id_product_attribute = pa.id_product_attribute
|
|
||||||
AND sa.id_shop = p_id_shop
|
|
||||||
WHERE pa.id_product = p.id_product
|
|
||||||
)
|
)
|
||||||
|
FROM
|
||||||
|
ps_feature_product fp
|
||||||
|
JOIN ps_feature_lang fl ON fl.id_feature = fp.id_feature
|
||||||
|
AND fl.id_lang = p_id_lang
|
||||||
|
JOIN ps_feature_value_lang fvl ON fvl.id_feature_value = fp.id_feature_value
|
||||||
|
AND fvl.id_lang = p_id_lang
|
||||||
|
WHERE
|
||||||
|
fp.id_product = p.id_product
|
||||||
|
),
|
||||||
|
/* ================= COMBINATIONS ================= */
|
||||||
|
'combinations',
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
JSON_ARRAYAGG(
|
||||||
|
JSON_OBJECT(
|
||||||
|
'id_product_attribute',
|
||||||
|
pa.id_product_attribute,
|
||||||
|
'reference',
|
||||||
|
pa.reference,
|
||||||
|
'price',
|
||||||
|
JSON_OBJECT(
|
||||||
|
'impact',
|
||||||
|
COALESCE(pas.price, pa.price),
|
||||||
|
'final_tax_excl',
|
||||||
|
(
|
||||||
|
COALESCE(ps.price, p.price) + COALESCE(pas.price, pa.price)
|
||||||
|
),
|
||||||
|
'final_tax_incl',
|
||||||
|
(
|
||||||
|
(
|
||||||
|
COALESCE(ps.price, p.price) + COALESCE(pas.price, pa.price)
|
||||||
|
) * (1 + v_tax_rate / 100)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'stock',
|
||||||
|
IFNULL(sa.quantity, 0),
|
||||||
|
'default_on',
|
||||||
|
pas.default_on,
|
||||||
|
/* ATTRIBUTES JSON */
|
||||||
|
'attributes',
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
JSON_ARRAYAGG(
|
||||||
|
JSON_OBJECT(
|
||||||
|
'group',
|
||||||
|
agl.name,
|
||||||
|
'attribute',
|
||||||
|
al.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
FROM
|
||||||
|
ps_product_attribute_combination pac
|
||||||
|
JOIN ps_attribute a ON a.id_attribute = pac.id_attribute
|
||||||
|
JOIN ps_attribute_lang al ON al.id_attribute = a.id_attribute
|
||||||
|
AND al.id_lang = p_id_lang
|
||||||
|
JOIN ps_attribute_group_lang agl ON agl.id_attribute_group = a.id_attribute_group
|
||||||
|
AND agl.id_lang = p_id_lang
|
||||||
|
WHERE
|
||||||
|
pac.id_product_attribute = pa.id_product_attribute
|
||||||
|
),
|
||||||
|
/* IMAGES */
|
||||||
|
'images',
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
JSON_ARRAYAGG(img.id_image)
|
||||||
|
FROM
|
||||||
|
ps_product_attribute_image pai
|
||||||
|
JOIN ps_image img ON img.id_image = pai.id_image
|
||||||
|
WHERE
|
||||||
|
pai.id_product_attribute = pa.id_product_attribute
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
FROM
|
||||||
|
ps_product_attribute pa
|
||||||
|
JOIN ps_product_attribute_shop pas ON pas.id_product_attribute = pa.id_product_attribute
|
||||||
|
AND pas.id_shop = p_id_shop
|
||||||
|
LEFT JOIN ps_stock_available sa ON sa.id_product = pa.id_product
|
||||||
|
AND sa.id_product_attribute = pa.id_product_attribute
|
||||||
|
AND sa.id_shop = p_id_shop
|
||||||
|
WHERE
|
||||||
|
pa.id_product = p.id_product
|
||||||
|
)
|
||||||
|
) AS product_json
|
||||||
|
FROM
|
||||||
|
ps_product p
|
||||||
|
LEFT JOIN ps_product_shop ps ON ps.id_product = p.id_product
|
||||||
|
AND ps.id_shop = p_id_shop
|
||||||
|
LEFT JOIN ps_product_lang pl ON pl.id_product = p.id_product
|
||||||
|
AND pl.id_lang = p_id_lang
|
||||||
|
AND pl.id_shop = p_id_shop
|
||||||
|
LEFT JOIN ps_category_lang cl ON cl.id_category = COALESCE(ps.id_category_default, p.id_category_default)
|
||||||
|
AND cl.id_lang = p_id_lang
|
||||||
|
AND cl.id_shop = p_id_shop
|
||||||
|
LEFT JOIN ps_manufacturer m ON m.id_manufacturer = p.id_manufacturer
|
||||||
|
LEFT JOIN ps_image i ON i.id_product = p.id_product
|
||||||
|
AND i.cover = 1
|
||||||
|
LEFT JOIN ps_image_lang il ON il.id_image = i.id_image
|
||||||
|
AND il.id_lang = p_id_lang
|
||||||
|
/* SPECIFIC PRICE */
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT bsp.*
|
||||||
|
FROM b2b_specific_price bsp
|
||||||
|
|
||||||
) AS product_json
|
/* RELATIONS */
|
||||||
|
LEFT JOIN b2b_specific_price_product bsp_p
|
||||||
|
ON bsp_p.b2b_specific_price_id = bsp.id
|
||||||
|
|
||||||
FROM ps_product p
|
LEFT JOIN b2b_specific_price_category bsp_c
|
||||||
|
ON bsp_c.b2b_specific_price_id = bsp.id
|
||||||
|
|
||||||
LEFT JOIN ps_product_shop ps
|
WHERE bsp.is_active = TRUE
|
||||||
ON ps.id_product = p.id_product AND ps.id_shop = p_id_shop
|
|
||||||
|
|
||||||
LEFT JOIN ps_product_lang pl
|
/* SCOPE MATCH */
|
||||||
ON pl.id_product = p.id_product
|
AND (
|
||||||
AND pl.id_lang = p_id_lang
|
/* PRODUCT */
|
||||||
AND pl.id_shop = p_id_shop
|
(bsp.scope = 'product' AND bsp_p.id_product = p_id_product)
|
||||||
|
|
||||||
LEFT JOIN ps_category_lang cl
|
/* CATEGORY */
|
||||||
ON cl.id_category = COALESCE(ps.id_category_default, p.id_category_default)
|
OR (
|
||||||
AND cl.id_lang = p_id_lang
|
bsp.scope = 'category'
|
||||||
AND cl.id_shop = p_id_shop
|
AND bsp_c.id_category IN (
|
||||||
|
SELECT cp.id_category
|
||||||
|
FROM ps_category_product cp
|
||||||
|
WHERE cp.id_product = p_id_product
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
LEFT JOIN ps_manufacturer m
|
/* SHOP (GLOBAL) */
|
||||||
ON m.id_manufacturer = p.id_manufacturer
|
OR (bsp.scope = 'shop')
|
||||||
|
)
|
||||||
|
|
||||||
LEFT JOIN ps_image i
|
/* CUSTOMER MATCH */
|
||||||
ON i.id_product = p.id_product AND i.cover = 1
|
AND (
|
||||||
|
NOT EXISTS (
|
||||||
|
SELECT 1 FROM b2b_specific_price_customer c
|
||||||
|
WHERE c.b2b_specific_price_id = bsp.id
|
||||||
|
)
|
||||||
|
OR EXISTS (
|
||||||
|
SELECT 1 FROM b2b_specific_price_customer c
|
||||||
|
WHERE c.b2b_specific_price_id = bsp.id
|
||||||
|
AND c.b2b_id_customer = p_id_customer
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
LEFT JOIN ps_image_lang il
|
/* COUNTRY MATCH */
|
||||||
ON il.id_image = i.id_image AND il.id_lang = p_id_lang
|
AND (
|
||||||
|
NOT EXISTS (
|
||||||
|
SELECT 1 FROM b2b_specific_price_country ctry
|
||||||
|
WHERE ctry.b2b_specific_price_id = bsp.id
|
||||||
|
)
|
||||||
|
OR EXISTS (
|
||||||
|
SELECT 1 FROM b2b_specific_price_country ctry
|
||||||
|
WHERE ctry.b2b_specific_price_id = bsp.id
|
||||||
|
AND ctry.b2b_id_country = b2b_id_country
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
/* SPECIFIC PRICE */
|
/* QUANTITY */
|
||||||
LEFT JOIN (
|
AND bsp.from_quantity <= p_quantity
|
||||||
SELECT sp1.*
|
|
||||||
FROM ps_specific_price sp1
|
|
||||||
WHERE sp1.id_product = p_id_product
|
|
||||||
AND (sp1.id_customer = 0 OR sp1.id_customer = p_id_customer)
|
|
||||||
AND (sp1.id_group = 0 OR sp1.id_group = p_id_group)
|
|
||||||
AND (sp1.id_currency = 0 OR sp1.id_currency = p_id_currency)
|
|
||||||
AND sp1.from_quantity <= p_quantity
|
|
||||||
ORDER BY
|
|
||||||
sp1.id_customer DESC,
|
|
||||||
sp1.id_group DESC,
|
|
||||||
sp1.from_quantity DESC,
|
|
||||||
sp1.id_specific_price DESC
|
|
||||||
LIMIT 1
|
|
||||||
) sp ON sp.id_product = p.id_product
|
|
||||||
|
|
||||||
WHERE p.id_product = p_id_product
|
/* DATE */
|
||||||
|
AND (
|
||||||
|
bsp.has_expiration_date = FALSE OR (
|
||||||
|
(bsp.valid_from IS NULL OR bsp.valid_from <= NOW())
|
||||||
|
AND (bsp.valid_till IS NULL OR bsp.valid_till >= NOW())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
LIMIT 1;
|
ORDER BY
|
||||||
|
/* 🔥 STRICT PRIORITY */
|
||||||
|
bsp.scope = 'product' DESC,
|
||||||
|
bsp.scope = 'category' DESC,
|
||||||
|
bsp.scope = 'shop' DESC,
|
||||||
|
|
||||||
|
bsp.b2b_id_customer DESC,
|
||||||
|
bsp.b2b_id_country DESC,
|
||||||
|
|
||||||
|
bsp.from_quantity DESC,
|
||||||
|
bsp.id DESC
|
||||||
|
|
||||||
|
LIMIT 1
|
||||||
|
) bsp ON 1=1
|
||||||
|
LEFT JOIN b2b_currency_rates br_bsp
|
||||||
|
ON br_bsp.b2b_id_currency = bsp.b2b_id_currency
|
||||||
|
AND br_bsp.created_at = (
|
||||||
|
SELECT MAX(created_at)
|
||||||
|
FROM b2b_currency_rates
|
||||||
|
WHERE b2b_id_currency = bsp.b2b_id_currency
|
||||||
|
)
|
||||||
|
LEFT JOIN b2b_countries ON b2b_countries.id = b2b_id_country
|
||||||
|
LEFT JOIN b2b_currencies ON b2b_currencies.id = p_id_currency
|
||||||
|
LEFT JOIN b2b_currency_rates r ON r.b2b_id_currency = b2b_currencies.id
|
||||||
|
AND r.created_at = (
|
||||||
|
SELECT
|
||||||
|
MAX(created_at)
|
||||||
|
FROM
|
||||||
|
b2b_currency_rates
|
||||||
|
WHERE
|
||||||
|
b2b_id_currency = b2b_currencies.id
|
||||||
|
)
|
||||||
|
WHERE
|
||||||
|
p.id_product = p_id_product
|
||||||
|
LIMIT
|
||||||
|
1;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|||||||
9
i18n/migrations/20260320113729_stuff.sql
Normal file
9
i18n/migrations/20260320113729_stuff.sql
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
SELECT 'up SQL query';
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- +goose StatementBegin
|
||||||
|
SELECT 'down SQL query';
|
||||||
|
-- +goose StatementEnd
|
||||||
53
repository/currencyRepo/currencyRepo.go
Normal file
53
repository/currencyRepo/currencyRepo.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package currencyRepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UICurrencyRepo interface {
|
||||||
|
CreateConversionRate(currencyRate *model.CurrencyRate) error
|
||||||
|
Get(id uint) (*model.Currency, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CurrencyRepo struct{}
|
||||||
|
|
||||||
|
func New() UICurrencyRepo {
|
||||||
|
return &CurrencyRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *CurrencyRepo) CreateConversionRate(currencyRate *model.CurrencyRate) error {
|
||||||
|
return db.DB.Debug().Create(currencyRate).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *CurrencyRepo) Get(id uint) (*model.Currency, error) {
|
||||||
|
var currency model.Currency
|
||||||
|
|
||||||
|
err := db.DB.Table("b2b_currencies c").
|
||||||
|
Select("c.*, r.conversion_rate").
|
||||||
|
Joins(`
|
||||||
|
LEFT JOIN b2b_currency_rates r
|
||||||
|
ON r.b2b_id_currency = c.id
|
||||||
|
AND r.created_at = (
|
||||||
|
SELECT MAX(created_at)
|
||||||
|
FROM b2b_currency_rates
|
||||||
|
WHERE b2b_id_currency = c.id
|
||||||
|
)
|
||||||
|
`).
|
||||||
|
Where("c.id = ?", id).
|
||||||
|
Scan(¤cy).Error
|
||||||
|
|
||||||
|
return ¤cy, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *CurrencyRepo) Find(langId uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.Currency], error) {
|
||||||
|
|
||||||
|
found, err := find.Paginate[model.Currency](langId, p, db.DB.
|
||||||
|
Model(&model.Currency{}).
|
||||||
|
Scopes(filt.All()...),
|
||||||
|
)
|
||||||
|
|
||||||
|
return &found, err
|
||||||
|
}
|
||||||
@@ -59,6 +59,7 @@ tasks:
|
|||||||
- |
|
- |
|
||||||
sed '/-- +goose Down/,$d' i18n/migrations/20260302163100_routes.sql | docker compose -p {{.PROJECT}} exec -T {{.LOCAL_DB_SERVICE}} mariadb -u {{.LOCAL_DB_USER}} --password={{.LOCAL_DB_PASSWORD}} {{.LOCAL_DB_NAME}}
|
sed '/-- +goose Down/,$d' i18n/migrations/20260302163100_routes.sql | docker compose -p {{.PROJECT}} exec -T {{.LOCAL_DB_SERVICE}} mariadb -u {{.LOCAL_DB_USER}} --password={{.LOCAL_DB_PASSWORD}} {{.LOCAL_DB_NAME}}
|
||||||
sed '/-- +goose Down/,$d' i18n/migrations/20260302163122_create_tables.sql | docker compose -p {{.PROJECT}} exec -T {{.LOCAL_DB_SERVICE}} mariadb -u {{.LOCAL_DB_USER}} --password={{.LOCAL_DB_PASSWORD}} {{.LOCAL_DB_NAME}}
|
sed '/-- +goose Down/,$d' i18n/migrations/20260302163122_create_tables.sql | docker compose -p {{.PROJECT}} exec -T {{.LOCAL_DB_SERVICE}} mariadb -u {{.LOCAL_DB_USER}} --password={{.LOCAL_DB_PASSWORD}} {{.LOCAL_DB_NAME}}
|
||||||
|
sed '/-- +goose Down/,$d' i18n/migrations/20260302163123_create_tables_data.sql | docker compose -p {{.PROJECT}} exec -T {{.LOCAL_DB_SERVICE}} mariadb -u {{.LOCAL_DB_USER}} --password={{.LOCAL_DB_PASSWORD}} {{.LOCAL_DB_NAME}}
|
||||||
sed '/-- +goose Down/,$d' i18n/migrations/20260302163152_translations_backoffice.sql | docker compose -p {{.PROJECT}} exec -T {{.LOCAL_DB_SERVICE}} mariadb -u {{.LOCAL_DB_USER}} --password={{.LOCAL_DB_PASSWORD}} {{.LOCAL_DB_NAME}}
|
sed '/-- +goose Down/,$d' i18n/migrations/20260302163152_translations_backoffice.sql | docker compose -p {{.PROJECT}} exec -T {{.LOCAL_DB_SERVICE}} mariadb -u {{.LOCAL_DB_USER}} --password={{.LOCAL_DB_PASSWORD}} {{.LOCAL_DB_NAME}}
|
||||||
sed '/-- +goose Down/,$d' i18n/migrations/20260302163157_translations_backend.sql | docker compose -p {{.PROJECT}} exec -T {{.LOCAL_DB_SERVICE}} mariadb -u {{.LOCAL_DB_USER}} --password={{.LOCAL_DB_PASSWORD}} {{.LOCAL_DB_NAME}}
|
sed '/-- +goose Down/,$d' i18n/migrations/20260302163157_translations_backend.sql | docker compose -p {{.PROJECT}} exec -T {{.LOCAL_DB_SERVICE}} mariadb -u {{.LOCAL_DB_USER}} --password={{.LOCAL_DB_PASSWORD}} {{.LOCAL_DB_NAME}}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user