diff --git a/app/delivery/web/api/restricted/carts.go b/app/delivery/web/api/restricted/carts.go index 34600be..6118af2 100644 --- a/app/delivery/web/api/restricted/carts.go +++ b/app/delivery/web/api/restricted/carts.go @@ -46,7 +46,8 @@ func (h *CartsHandler) AddNewCart(c fiber.Ctx) error { JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody))) } - new_cart, err := h.cartsService.CreateNewCart(userID) + name := c.Query("name") + new_cart, err := h.cartsService.CreateNewCart(userID, name) if err != nil { return c.Status(responseErrors.GetErrorStatus(err)). JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) diff --git a/app/delivery/web/api/restricted/product.go b/app/delivery/web/api/restricted/product.go index ba6b99d..9e58550 100644 --- a/app/delivery/web/api/restricted/product.go +++ b/app/delivery/web/api/restricted/product.go @@ -112,6 +112,7 @@ var columnMappingListProducts map[string]string = map[string]string{ "quantity": "bp.quantity", "is_favorite": "bp.is_favorite", "is_new": "bp.is_new", + "is_oem": "bp.is_oem", } func (h *ProductsHandler) AddToFavorites(c fiber.Ctx) error { diff --git a/app/model/product.go b/app/model/product.go index 6595f79..1432f1e 100644 --- a/app/model/product.go +++ b/app/model/product.go @@ -12,7 +12,8 @@ type ProductInList struct { PriceTaxExcl float64 `gorm:"column:price_tax_excl" json:"price_tax_excl"` PriceTaxIncl float64 `gorm:"column:price_tax_incl" json:"price_tax_incl"` IsFavorite bool `gorm:"column:is_favorite" json:"is_favorite"` - IsNew uint `gorm:"column:is_new" json:"is_new"` + IsNew bool `gorm:"column:is_new" json:"is_new"` + IsOEM bool `gorm:"column:is_oem" json:"is_oem"` } type ProductFilters struct { diff --git a/app/repos/cartsRepo/cartsRepo.go b/app/repos/cartsRepo/cartsRepo.go index 0f4c5ab..87c5932 100644 --- a/app/repos/cartsRepo/cartsRepo.go +++ b/app/repos/cartsRepo/cartsRepo.go @@ -12,7 +12,7 @@ import ( type UICartsRepo interface { CartsAmount(user_id uint) (uint, error) - CreateNewCart(user_id uint) (model.CustomerCart, error) + CreateNewCart(user_id uint, name string) (model.CustomerCart, error) RemoveCart(user_id uint, cart_id uint) error UserHasCart(user_id uint, cart_id uint) (bool, error) UpdateCartName(user_id uint, cart_id uint, new_name string) error @@ -42,10 +42,7 @@ func (repo *CartsRepo) CartsAmount(user_id uint) (uint, error) { return amt, err } -func (repo *CartsRepo) CreateNewCart(user_id uint) (model.CustomerCart, error) { - var name string - name = constdata.DEFAULT_NEW_CART_NAME - +func (repo *CartsRepo) CreateNewCart(user_id uint, name string) (model.CustomerCart, error) { cart := model.CustomerCart{ UserID: user_id, Name: &name, diff --git a/app/repos/productsRepo/productsRepo.go b/app/repos/productsRepo/productsRepo.go index a6d850d..fb139a5 100644 --- a/app/repos/productsRepo/productsRepo.go +++ b/app/repos/productsRepo/productsRepo.go @@ -122,6 +122,19 @@ func (repo *ProductsRepo) Find(langID uint, userID uint, p find.Paging, filt *fi Group("product_id"), }, }, + { + Name: "oems", + Subquery: exclause.Subquery{ + DB: db.DB. + Table("b2b_oems"). + Select(` + product_id AS product_id, + COUNT(*) > 0 AS is_customers_oem + `). + Where("user_id = ?", userID). + Group("product_id"), + }, + }, { Name: "new_product_days", Subquery: exclause.Subquery{ @@ -150,6 +163,7 @@ func (repo *ProductsRepo) Find(langID uint, userID uint, p find.Paging, filt *fi pl.name AS name, ps.id_category_default AS category_id, p.reference AS reference, + p.is_oem AS is_oem, sa.quantity AS quantity, COALESCE(f.is_favorite, 0) AS is_favorite, CASE @@ -166,7 +180,9 @@ func (repo *ProductsRepo) Find(langID uint, userID uint, p find.Paging, filt *fi Joins("LEFT JOIN favorites f ON f.product_id = ps.id_product"). Joins("LEFT JOIN ps_stock_available sa ON sa.id_product = ps.id_product AND sa.id_product_attribute = 0"). Joins("LEFT JOIN new_product_days npd ON 1 = 1"). + Joins("LEFT JOIN oems ON oems.product_id = ps.id_product"). Where("ps.active = ?", 1). + Where("(p.is_oem = 0 OR oems.is_customers_oem > 0)"). Group("ps.id_product"), }, }, @@ -182,7 +198,8 @@ func (repo *ProductsRepo) Find(langID uint, userID uint, p find.Paging, filt *fi COALESCE(v.variants_number, 0) AS variants_number, bp.quantity AS quantity, bp.is_favorite AS is_favorite, - bp.is_new AS is_new + bp.is_new AS is_new, + bp.is_oem AS is_oem `, config.Get().Image.ImagePrefix). Joins("JOIN ps_product_lang pl ON pl.id_product = bp.product_id AND pl.id_lang = ?", langID). Joins("JOIN ps_image_shop ims ON ims.id_product = bp.product_id AND ims.cover = 1"). diff --git a/app/service/cartsService/cartsService.go b/app/service/cartsService/cartsService.go index 6d75b3c..4d5378a 100644 --- a/app/service/cartsService/cartsService.go +++ b/app/service/cartsService/cartsService.go @@ -17,7 +17,7 @@ func New() *CartsService { } } -func (s *CartsService) CreateNewCart(user_id uint) (model.CustomerCart, error) { +func (s *CartsService) CreateNewCart(user_id uint, name string) (model.CustomerCart, error) { var cart model.CustomerCart customers_carts_amount, err := s.repo.CartsAmount(user_id) @@ -28,8 +28,12 @@ func (s *CartsService) CreateNewCart(user_id uint) (model.CustomerCart, error) { return cart, responseErrors.ErrMaxAmtOfCartsReached } + if name == "" { + name = constdata.DEFAULT_NEW_CART_NAME + } + // create new cart for customer - cart, err = s.repo.CreateNewCart(user_id) + cart, err = s.repo.CreateNewCart(user_id, name) return cart, nil } diff --git a/app/service/menuService/menuService.go b/app/service/menuService/menuService.go index cc98450..595303a 100644 --- a/app/service/menuService/menuService.go +++ b/app/service/menuService/menuService.go @@ -231,21 +231,54 @@ func (s *MenuService) GetTopMenu(languageId uint, roleId uint) ([]*model.B2BTopM func (s *MenuService) appendAdditional(all_categories *[]model.ScannedCategory, id_lang uint, iso_code string) { for i := 0; i < len(*all_categories); i++ { - (*all_categories)[i].Filter = "category_id_in=" + strconv.Itoa(int((*all_categories)[i].CategoryID)) + (*all_categories)[i].Filter = "category_id_eq=" + strconv.Itoa(int((*all_categories)[i].CategoryID)) } - var additional model.ScannedCategory - additional.CategoryID = 10001 - additional.Name = "New Products" - additional.Active = 1 - additional.Position = 10 - additional.ParentID = 2 - additional.IsRoot = 0 - additional.LinkRewrite = i18n.T___(id_lang, "category.new_products") - additional.IsoCode = iso_code + // the new products category + var new_products_category model.ScannedCategory + new_products_category.CategoryID = constdata.ADDITIONAL_CATEGORIES_INDEX + 1 + new_products_category.Name = "New Products" + new_products_category.Active = 1 + new_products_category.Position = 10 + new_products_category.ParentID = 2 + new_products_category.IsRoot = 0 + new_products_category.LinkRewrite = i18n.T___(id_lang, "category.new_products") + new_products_category.IsoCode = iso_code - additional.Visited = false - additional.Filter = "is_new_in=true" + new_products_category.Visited = false + new_products_category.Filter = "is_new_eq=true" - *all_categories = append(*all_categories, additional) + *all_categories = append(*all_categories, new_products_category) + + // the oem products category + var oem_products_category model.ScannedCategory + oem_products_category.CategoryID = constdata.ADDITIONAL_CATEGORIES_INDEX + 2 + oem_products_category.Name = "OEM Products" + oem_products_category.Active = 1 + oem_products_category.Position = 11 + oem_products_category.ParentID = 2 + oem_products_category.IsRoot = 0 + oem_products_category.LinkRewrite = i18n.T___(id_lang, "category.oem_products") + oem_products_category.IsoCode = iso_code + + oem_products_category.Visited = false + oem_products_category.Filter = "is_oem_eq=true" + + *all_categories = append(*all_categories, oem_products_category) + + // the favorite products category + var favorite_products_category model.ScannedCategory + favorite_products_category.CategoryID = constdata.ADDITIONAL_CATEGORIES_INDEX + 3 + favorite_products_category.Name = "Favourite Products" // British English version. + favorite_products_category.Active = 1 + favorite_products_category.Position = 12 + favorite_products_category.ParentID = 2 + favorite_products_category.IsRoot = 0 + favorite_products_category.LinkRewrite = i18n.T___(id_lang, "category.favorite_products") + favorite_products_category.IsoCode = iso_code + + favorite_products_category.Visited = false + favorite_products_category.Filter = "is_favorite_eq=true" + + *all_categories = append(*all_categories, favorite_products_category) } diff --git a/app/utils/const_data/consts.go b/app/utils/const_data/consts.go index 5860000..080bf7e 100644 --- a/app/utils/const_data/consts.go +++ b/app/utils/const_data/consts.go @@ -9,6 +9,7 @@ const ADMIN_NOTIFICATION_LANGUAGE = 2 // CATEGORY_TREE_ROOT_ID corresponds to id_category in ps_category which has is_root_category=1 const CATEGORY_TREE_ROOT_ID = 2 +const ADDITIONAL_CATEGORIES_INDEX = 10000 // since arrays can not be const var CATEGORY_BLACKLIST = []uint{250} diff --git a/app/view/product.go b/app/view/product.go index 9dba8d1..a505477 100644 --- a/app/view/product.go +++ b/app/view/product.go @@ -95,4 +95,6 @@ type Product struct { Category string `gorm:"column:category" json:"category"` IsFavorite bool `gorm:"column:is_favorite" json:"is_favorite"` + IsOEM bool `gorm:"column:is_oem" json:"is_oem"` + IsNew bool `gorm:"column:is_new" json:"is_new"` } diff --git a/bruno/api_v1/product/Products List.yml b/bruno/api_v1/product/Products List.yml index c099b28..31a415f 100644 --- a/bruno/api_v1/product/Products List.yml +++ b/bruno/api_v1/product/Products List.yml @@ -5,7 +5,7 @@ info: http: method: GET - url: "{{bas_url}}/restricted/product/list?p=1&elems=30&reference=~NC100" + url: "{{bas_url}}/restricted/product/list?p=1&elems=30&reference=~NC100&is_new_eq=0&is_favorite_eq=false&is_oem_eq=FALSE" params: - name: p value: "1" @@ -27,11 +27,12 @@ http: - name: is_new_eq value: "0" type: query - disabled: true - name: is_favorite_eq value: "false" type: query - disabled: true + - name: is_oem_eq + value: "FALSE" + type: query body: type: json data: "" diff --git a/bruno/b2b_daniel/addresses/folder.yml b/bruno/b2b_daniel/addresses/folder.yml index aaa37e8..bc8e1c4 100644 --- a/bruno/b2b_daniel/addresses/folder.yml +++ b/bruno/b2b_daniel/addresses/folder.yml @@ -1,7 +1,7 @@ info: name: addresses type: folder - seq: 10 + seq: 9 request: auth: inherit diff --git a/bruno/b2b_daniel/carts/add-new-cart.yml b/bruno/b2b_daniel/carts/add-new-cart.yml index 20199cf..de2bba7 100644 --- a/bruno/b2b_daniel/carts/add-new-cart.yml +++ b/bruno/b2b_daniel/carts/add-new-cart.yml @@ -5,7 +5,11 @@ info: http: method: GET - url: http://localhost:3000/api/v1/restricted/carts/add-new-cart + url: http://localhost:3000/api/v1/restricted/carts/add-new-cart?name=carttt + params: + - name: name + value: carttt + type: query auth: inherit settings: diff --git a/bruno/b2b_daniel/list/folder.yml b/bruno/b2b_daniel/list/folder.yml deleted file mode 100644 index 52fa517..0000000 --- a/bruno/b2b_daniel/list/folder.yml +++ /dev/null @@ -1,7 +0,0 @@ -info: - name: list - type: folder - seq: 3 - -request: - auth: inherit diff --git a/bruno/b2b_daniel/list/list-products.yml b/bruno/b2b_daniel/list/list-products.yml deleted file mode 100644 index 20e6cac..0000000 --- a/bruno/b2b_daniel/list/list-products.yml +++ /dev/null @@ -1,24 +0,0 @@ -info: - name: list-products - type: http - seq: 1 - -http: - method: GET - url: http://localhost:3000/api/v1/restricted/list/list-products?p=1&elems=10&target_user_id=2 - params: - - name: p - value: "1" - type: query - - name: elems - value: "10" - type: query - - name: target_user_id - value: "2" - type: query - -settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 diff --git a/bruno/b2b_daniel/list/list-users.yml b/bruno/b2b_daniel/list/list-users.yml deleted file mode 100644 index 85d70fa..0000000 --- a/bruno/b2b_daniel/list/list-users.yml +++ /dev/null @@ -1,21 +0,0 @@ -info: - name: list-users - type: http - seq: 1 - -http: - method: GET - url: http://localhost:3000/api/v1/restricted/list/list-users?p=1&elems=10 - params: - - name: p - value: "1" - type: query - - name: elems - value: "10" - type: query - -settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 diff --git a/bruno/b2b_daniel/orders/folder.yml b/bruno/b2b_daniel/orders/folder.yml index f542e59..262ee49 100644 --- a/bruno/b2b_daniel/orders/folder.yml +++ b/bruno/b2b_daniel/orders/folder.yml @@ -1,7 +1,7 @@ info: name: orders type: folder - seq: 11 + seq: 10 request: auth: inherit diff --git a/bruno/b2b_daniel/product-translation/folder.yml b/bruno/b2b_daniel/product-translation/folder.yml index cda7116..71c5004 100644 --- a/bruno/b2b_daniel/product-translation/folder.yml +++ b/bruno/b2b_daniel/product-translation/folder.yml @@ -1,7 +1,7 @@ info: name: product-translation type: folder - seq: 2 + seq: 3 request: auth: inherit diff --git a/bruno/b2b_daniel/storage-old/folder.yml b/bruno/b2b_daniel/storage-old/folder.yml index 852efec..9dc0684 100644 --- a/bruno/b2b_daniel/storage-old/folder.yml +++ b/bruno/b2b_daniel/storage-old/folder.yml @@ -1,7 +1,7 @@ info: name: storage-old type: folder - seq: 1 + seq: 2 request: auth: inherit diff --git a/bruno/b2b_daniel/storage-restricted/folder.yml b/bruno/b2b_daniel/storage-restricted/folder.yml index ec9eca7..940bde2 100644 --- a/bruno/b2b_daniel/storage-restricted/folder.yml +++ b/bruno/b2b_daniel/storage-restricted/folder.yml @@ -1,7 +1,7 @@ info: name: storage-restricted type: folder - seq: 9 + seq: 8 request: auth: inherit diff --git a/i18n/migrations/20260302163122_create_tables.sql b/i18n/migrations/20260302163122_create_tables.sql index 6226f32..0c68535 100644 --- a/i18n/migrations/20260302163122_create_tables.sql +++ b/i18n/migrations/20260302163122_create_tables.sql @@ -162,6 +162,16 @@ CREATE TABLE IF NOT EXISTS b2b_favorites ( ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; +-- oems +CREATE TABLE IF NOT EXISTS b2b_oems ( + user_id BIGINT UNSIGNED NOT NULL, + product_id INT UNSIGNED NOT NULL, + PRIMARY KEY (user_id, product_id), + CONSTRAINT fk_oems_customer FOREIGN KEY (user_id) REFERENCES b2b_customers(id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT fk_oems_product FOREIGN KEY (product_id) REFERENCES ps_product(id_product) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; + + -- refresh_tokens CREATE TABLE IF NOT EXISTS b2b_refresh_tokens ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, diff --git a/i18n/migrations/20260319163200_procedures.sql b/i18n/migrations/20260319163200_procedures.sql index b823a3a..651f897 100644 --- a/i18n/migrations/20260319163200_procedures.sql +++ b/i18n/migrations/20260319163200_procedures.sql @@ -384,10 +384,19 @@ BEGIN m.name AS manufacturer, cl.name AS category, + p.is_oem, EXISTS( SELECT 1 FROM b2b_favorites f WHERE f.user_id = p_id_customer AND f.product_id = p_id_product - ) AS is_favorite + ) AS is_favorite, + CASE + WHEN ps.date_add >= DATE_SUB( + NOW(), + INTERVAL COALESCE(CAST(ps_configuration.value AS SIGNED), 20) DAY + ) AND ps.active = 1 + THEN 1 + ELSE 0 + END AS is_new @@ -405,6 +414,8 @@ BEGIN AND cl.id_shop = p_id_shop LEFT JOIN ps_manufacturer m ON m.id_manufacturer = p.id_manufacturer + LEFT JOIN ps_configuration + ON ps_configuration.name = PS_NB_DAYS_NEW_PRODUCT WHERE p.id_product = p_id_product LIMIT 1;