diff --git a/app/model/category.go b/app/model/category.go index 50e6ce9..8ba7ee1 100644 --- a/app/model/category.go +++ b/app/model/category.go @@ -10,7 +10,8 @@ type ScannedCategory struct { LinkRewrite string `gorm:"column:link_rewrite"` IsoCode string `gorm:"column:iso_code"` - Visited bool //this is for internal backend use only + Visited bool // this is for internal backend use only + Filter string // filter applicable to this category } type Category struct { @@ -25,6 +26,7 @@ type CategoryParams struct { CategoryID uint `json:"category_id" form:"category_id"` LinkRewrite string `json:"link_rewrite" form:"link_rewrite"` Locale string `json:"locale" form:"locale"` + Filter string `json:"filter" form:"filter"` } type CategoryInBreadcrumb struct { diff --git a/app/repos/categoriesRepo/categoriesRepo.go b/app/repos/categoriesRepo/categoriesRepo.go deleted file mode 100644 index 955292a..0000000 --- a/app/repos/categoriesRepo/categoriesRepo.go +++ /dev/null @@ -1,48 +0,0 @@ -package categoriesRepo - -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/model/dbmodel" - constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data" -) - -type UICategoriesRepo interface { - GetAllCategories(idLang uint) ([]model.ScannedCategory, error) -} - -type CategoriesRepo struct{} - -func New() UICategoriesRepo { - return &CategoriesRepo{} -} - -func (r *CategoriesRepo) GetAllCategories(idLang uint) ([]model.ScannedCategory, error) { - var allCategories []model.ScannedCategory - - categoryTbl := (&dbmodel.PsCategory{}).TableName() - categoryLangTbl := (&dbmodel.PsCategoryLang{}).TableName() - categoryShopTbl := (&dbmodel.PsCategoryShop{}).TableName() - langTbl := (&dbmodel.PsLang{}).TableName() - - err := db.Get(). - Model(dbmodel.PsCategory{}). - Select(` - ps_category.id_category AS category_id, - ps_category_lang.name AS name, - ps_category.active AS active, - ps_category_shop.position AS position, - ps_category.id_parent AS id_parent, - ps_category.is_root_category AS is_root_category, - ps_category_lang.link_rewrite AS link_rewrite, - ps_lang.iso_code AS iso_code - `). - Joins(`LEFT JOIN `+categoryLangTbl+` ON `+categoryLangTbl+`.id_category = `+categoryTbl+`.id_category AND `+categoryLangTbl+`.id_shop = ? AND `+categoryLangTbl+`.id_lang = ?`, - constdata.SHOP_ID, idLang). - Joins(`LEFT JOIN `+categoryShopTbl+` ON `+categoryShopTbl+`.id_category = `+categoryTbl+`.id_category AND `+categoryShopTbl+`.id_shop = ?`, - constdata.SHOP_ID). - Joins(`JOIN ` + langTbl + ` ON ` + langTbl + `.id_lang = ` + categoryLangTbl + `.id_lang`). - Scan(&allCategories).Error - - return allCategories, err -} diff --git a/app/repos/categoryRepo/categoryRepo.go b/app/repos/categoryRepo/categoryRepo.go index dd31f39..086cfcf 100644 --- a/app/repos/categoryRepo/categoryRepo.go +++ b/app/repos/categoryRepo/categoryRepo.go @@ -2,11 +2,14 @@ package categoryrepo 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/model/dbmodel" + constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data" ) type UICategoryRepo interface { GetCategoryTranslations(ids []uint, idLang uint) (map[uint]string, error) + RetrieveMenuCategories(idLang uint) ([]model.ScannedCategory, error) } type CategoryRepo struct{} @@ -42,3 +45,33 @@ func (r *CategoryRepo) GetCategoryTranslations(ids []uint, idLang uint) (map[uin return translations, nil } + +func (r *CategoryRepo) RetrieveMenuCategories(idLang uint) ([]model.ScannedCategory, error) { + var allCategories []model.ScannedCategory + + categoryTbl := (&dbmodel.PsCategory{}).TableName() + categoryLangTbl := (&dbmodel.PsCategoryLang{}).TableName() + categoryShopTbl := (&dbmodel.PsCategoryShop{}).TableName() + langTbl := (&dbmodel.PsLang{}).TableName() + + err := db.Get(). + Model(dbmodel.PsCategory{}). + Select(` + ps_category.id_category AS category_id, + ps_category_lang.name AS name, + ps_category.active AS active, + ps_category_shop.position AS position, + ps_category.id_parent AS id_parent, + ps_category.is_root_category AS is_root_category, + ps_category_lang.link_rewrite AS link_rewrite, + ps_lang.iso_code AS iso_code + `). + Joins(`LEFT JOIN `+categoryLangTbl+` ON `+categoryLangTbl+`.id_category = `+categoryTbl+`.id_category AND `+categoryLangTbl+`.id_shop = ? AND `+categoryLangTbl+`.id_lang = ?`, + constdata.SHOP_ID, idLang). + Joins(`LEFT JOIN `+categoryShopTbl+` ON `+categoryShopTbl+`.id_category = `+categoryTbl+`.id_category AND `+categoryShopTbl+`.id_shop = ?`, + constdata.SHOP_ID). + Joins(`JOIN ` + langTbl + ` ON ` + langTbl + `.id_lang = ` + categoryLangTbl + `.id_lang`). + Scan(&allCategories).Error + + return allCategories, err +} diff --git a/app/service/menuService/menuService.go b/app/service/menuService/menuService.go index de2498d..e63b6b5 100644 --- a/app/service/menuService/menuService.go +++ b/app/service/menuService/menuService.go @@ -3,31 +3,45 @@ package menuService import ( "slices" "sort" + "strconv" "git.ma-al.com/goc_daniel/b2b/app/model" - "git.ma-al.com/goc_daniel/b2b/app/repos/categoriesRepo" + categoryrepo "git.ma-al.com/goc_daniel/b2b/app/repos/categoryRepo" routesRepo "git.ma-al.com/goc_daniel/b2b/app/repos/routesRepo" + constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data" + "git.ma-al.com/goc_daniel/b2b/app/utils/i18n" "git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors" ) type MenuService struct { - categoriesRepo categoriesRepo.UICategoriesRepo - routesRepo routesRepo.UIRoutesRepo + categoryRepo categoryrepo.UICategoryRepo + routesRepo routesRepo.UIRoutesRepo } func New() *MenuService { return &MenuService{ - categoriesRepo: categoriesRepo.New(), - routesRepo: routesRepo.New(), + categoryRepo: categoryrepo.New(), + routesRepo: routesRepo.New(), } } func (s *MenuService) GetCategoryTree(root_category_id uint, id_lang uint) (*model.Category, error) { - all_categories, err := s.categoriesRepo.GetAllCategories(id_lang) + all_categories, err := s.categoryRepo.RetrieveMenuCategories(id_lang) if err != nil { return &model.Category{}, err } + // remove blacklisted categories + // to do so, we detach them from the main tree + for i := 0; i < len(all_categories); i++ { + if slices.Contains(constdata.CATEGORY_BLACKLIST, all_categories[i].CategoryID) { + all_categories[i].ParentID = all_categories[i].CategoryID + } + } + + iso_code := all_categories[0].IsoCode + s.appendAdditional(&all_categories, id_lang, iso_code) + // find the root root_index := 0 root_found := false @@ -98,7 +112,7 @@ func (s *MenuService) scannedToNormalCategory(scanned model.ScannedCategory) mod normal.CategoryID = scanned.CategoryID normal.Label = scanned.Name // normal.Active = scanned.Active == 1 - normal.Params = model.CategoryParams{CategoryID: normal.CategoryID, LinkRewrite: scanned.LinkRewrite, Locale: scanned.IsoCode} + normal.Params = model.CategoryParams{CategoryID: normal.CategoryID, LinkRewrite: scanned.LinkRewrite, Locale: scanned.IsoCode, Filter: scanned.Filter} normal.Children = []model.Category{} return normal } @@ -114,11 +128,14 @@ func (a ByPosition) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByPosition) Less(i, j int) bool { return a[i].Position < a[j].Position } func (s *MenuService) GetBreadcrumb(root_category_id uint, start_category_id uint, id_lang uint) ([]model.CategoryInBreadcrumb, error) { - all_categories, err := s.categoriesRepo.GetAllCategories(id_lang) + all_categories, err := s.categoryRepo.RetrieveMenuCategories(id_lang) if err != nil { return []model.CategoryInBreadcrumb{}, err } + iso_code := all_categories[0].IsoCode + s.appendAdditional(&all_categories, id_lang, iso_code) + breadcrumb := []model.CategoryInBreadcrumb{} start_index := 0 @@ -211,3 +228,24 @@ func (s *MenuService) GetTopMenu(languageId uint, roleId uint) ([]*model.B2BTopM return roots, nil } + +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)) + } + + 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 + + additional.Visited = false + additional.Filter = "is_new_in=true" + + *all_categories = append(*all_categories, additional) +} diff --git a/app/service/productTranslationService/sanitizeURLSlug.go b/app/service/productTranslationService/sanitizeURLSlug.go index ea69d7c..2d0ddbf 100644 --- a/app/service/productTranslationService/sanitizeURLSlug.go +++ b/app/service/productTranslationService/sanitizeURLSlug.go @@ -4,6 +4,7 @@ import ( "strings" "unicode" + "git.ma-al.com/goc_daniel/b2b/app/db" constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data" "github.com/dlclark/regexp2" "golang.org/x/text/runes" @@ -22,7 +23,7 @@ func SanitizeSlug(s string) string { s = strings.TrimSpace(strings.ToLower(s)) // First apply explicit transliteration for language-specific letters. - s = transliterateWithTable(s) + s = transliterateSlug(s) // Then normalize and strip any remaining combining marks. s = removeDiacritics(s) @@ -40,19 +41,17 @@ func SanitizeSlug(s string) string { return s } -func transliterateWithTable(s string) string { - var b strings.Builder - b.Grow(len(s)) +func transliterateSlug(s string) string { + var cleared string - for _, r := range s { - if repl, ok := constdata.TRANSLITERATION_TABLE[r]; ok { - b.WriteString(repl) - } else { - b.WriteRune(r) - } + err := db.DB.Raw("SELECT slugify_eu(?)", s).Scan(&cleared).Error + if err != nil { + // log error + _ = err + return s } - return b.String() + return cleared } func removeDiacritics(s string) string { diff --git a/app/utils/const_data/consts.go b/app/utils/const_data/consts.go index aa62f27..2d760bc 100644 --- a/app/utils/const_data/consts.go +++ b/app/utils/const_data/consts.go @@ -9,6 +9,9 @@ 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 +// since arrays can not be const +var CATEGORY_BLACKLIST = []uint{250} + const MAX_AMOUNT_OF_CARTS_PER_USER = 10 const DEFAULT_NEW_CART_NAME = "new cart" @@ -25,23 +28,3 @@ const WEBDAV_TRIMMED_ROOT = "localhost:3000/api/v1/webdav/storage" const NON_ALNUM_REGEX = `[^a-z0-9]+` const MULTI_DASH_REGEX = `-+` const SLUG_REGEX = `^[a-z0-9]+(?:-[a-z0-9]+)*$` - -// Currently supports only German+Polish specific cases -var TRANSLITERATION_TABLE = map[rune]string{ - // German - 'ä': "ae", - 'ö': "oe", - 'ü': "ue", - 'ß': "ss", - - // Polish - 'ą': "a", - 'ć': "c", - 'ę': "e", - 'ł': "l", - 'ń': "n", - 'ó': "o", - 'ś': "s", - 'ż': "z", - 'ź': "z", -} diff --git a/bruno/b2b_daniel/menu/get-breadcrumb.yml b/bruno/b2b_daniel/menu/get-breadcrumb.yml index a805790..5870773 100644 --- a/bruno/b2b_daniel/menu/get-breadcrumb.yml +++ b/bruno/b2b_daniel/menu/get-breadcrumb.yml @@ -5,10 +5,10 @@ info: http: method: GET - url: http://localhost:3000/api/v1/restricted/menu/get-breadcrumb?root_category_id=10&category_id=13 + url: http://localhost:3000/api/v1/restricted/menu/get-breadcrumb?root_category_id=2&category_id=13 params: - name: root_category_id - value: "10" + value: "2" type: query - name: category_id value: "13" diff --git a/bruno/b2b_daniel/menu/get-category-tree.yml b/bruno/b2b_daniel/menu/get-category-tree.yml index 6e9d875..a1b6714 100644 --- a/bruno/b2b_daniel/menu/get-category-tree.yml +++ b/bruno/b2b_daniel/menu/get-category-tree.yml @@ -5,10 +5,10 @@ info: http: method: GET - url: http://localhost:3000/api/v1/restricted/menu/get-category-tree?root_category_id=10 + url: http://localhost:3000/api/v1/restricted/menu/get-category-tree?root_category_id=2 params: - name: root_category_id - value: "10" + value: "2" type: query auth: inherit diff --git a/i18n/migrations/20260302163122_create_tables.sql b/i18n/migrations/20260302163122_create_tables.sql index ba4469a..0ec6408 100644 --- a/i18n/migrations/20260302163122_create_tables.sql +++ b/i18n/migrations/20260302163122_create_tables.sql @@ -405,16 +405,26 @@ DELIMITER ; -- +goose Down -DROP TABLE IF EXISTS b2b_countries; -DROP TABLE IF EXISTS b2b_language; -DROP TABLE IF EXISTS b2b_components; -DROP TABLE IF EXISTS b2b_scopes; -DROP TABLE IF EXISTS b2b_translations; -DROP TABLE IF EXISTS b2b_customers; -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_addresses; +DROP TABLE IF EXISTS b2b_top_menu_roles; +DROP TABLE IF EXISTS b2b_favorites; +DROP TABLE IF EXISTS b2b_carts_products; +DROP TABLE IF EXISTS b2b_customer_carts; +DROP TABLE IF EXISTS b2b_specific_price_country; +DROP TABLE IF EXISTS b2b_specific_price_customer; DROP TABLE IF EXISTS b2b_specific_price_product_attribute; +DROP TABLE IF EXISTS b2b_specific_price_category; +DROP TABLE IF EXISTS b2b_specific_price_product; +DROP TABLE IF EXISTS b2b_specific_price; +DROP TABLE IF EXISTS b2b_role_permissions; +DROP TABLE IF EXISTS b2b_permissions; +DROP TABLE IF EXISTS b2b_roles; +DROP TABLE IF EXISTS b2b_countries; +DROP TABLE IF EXISTS b2b_currency_rates; +DROP TABLE IF EXISTS b2b_currencies; +DROP TABLE IF EXISTS b2b_refresh_tokens; +DROP TABLE IF EXISTS b2b_customers; +DROP TABLE IF EXISTS b2b_translations; +DROP TABLE IF EXISTS b2b_scopes; +DROP TABLE IF EXISTS b2b_components; +DROP TABLE IF EXISTS b2b_language;