| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736 | package fetdataimport (	"math"	"sort"	"strings"	"golang-fave/engine/utils"	"golang-fave/engine/wrapper")type ShopPagination struct {	Num     string	Link    string	Current bool	Dots    bool}type Shop struct {	wrap     *wrapper.Wrapper	category *ShopCategory	product  *ShopProduct	products         []*ShopProduct	productsCount    int	productsPerPage  int	productsMaxPage  int	productsCurrPage int	pagination       []*ShopPagination	paginationPrev   *ShopPagination	paginationNext   *ShopPagination	bufferCats map[int]*utils.MySql_shop_category}func (this *Shop) load() *Shop {	if this == nil {		return this	}	if (*this.wrap.Config).Modules.Enabled.Shop == 0 {		return this	}	sql_nums := `		SELECT			COUNT(*)		FROM			fave_shop_products		WHERE			active = 1 AND			parent_id IS NULL		;	`	sql_rows := `		SELECT			fave_shop_products.id,			fave_shop_products.user,			fave_shop_products.currency,			fave_shop_products.price,			fave_shop_products.price_old,			fave_shop_products.gname,			fave_shop_products.name,			fave_shop_products.alias,			fave_shop_products.vendor,			fave_shop_products.quantity,			fave_shop_products.category,			fave_shop_products.briefly,			fave_shop_products.content,			UNIX_TIMESTAMP(fave_shop_products.datetime) as datetime,			fave_shop_products.active,			fave_users.id,			fave_users.first_name,			fave_users.last_name,			fave_users.email,			fave_users.admin,			fave_users.active,			fave_shop_currencies.id,			fave_shop_currencies.name,			fave_shop_currencies.coefficient,			fave_shop_currencies.code,			fave_shop_currencies.symbol,			cats.id,			cats.user,			cats.name,			cats.alias,			cats.lft,			cats.rgt,			cats.depth,			cats.parent_id		FROM			fave_shop_products			LEFT JOIN fave_users ON fave_users.id = fave_shop_products.user			LEFT JOIN fave_shop_currencies ON fave_shop_currencies.id = fave_shop_products.currency			LEFT JOIN (				SELECT					main.id,					main.user,					main.name,					main.alias,					main.lft,					main.rgt,					main.depth,					parent.id AS parent_id				FROM					(						SELECT							node.id,							node.user,							node.name,							node.alias,							node.lft,							node.rgt,							(COUNT(parent.id) - 1) AS depth						FROM							fave_shop_cats AS node,							fave_shop_cats AS parent						WHERE							node.lft BETWEEN parent.lft AND parent.rgt						GROUP BY							node.id						ORDER BY							node.lft ASC					) AS main					LEFT JOIN (						SELECT							node.id,							node.user,							node.name,							node.alias,							node.lft,							node.rgt,							(COUNT(parent.id) - 0) AS depth						FROM							fave_shop_cats AS node,							fave_shop_cats AS parent						WHERE							node.lft BETWEEN parent.lft AND parent.rgt						GROUP BY							node.id						ORDER BY							node.lft ASC					) AS parent ON					parent.depth = main.depth AND					main.lft > parent.lft AND					main.rgt < parent.rgt				WHERE					main.id > 1				ORDER BY					main.lft ASC			) AS cats ON cats.id = fave_shop_products.category		WHERE			fave_shop_products.active = 1 AND			fave_shop_products.parent_id IS NULL		ORDER BY			fave_shop_products.quantity DESC,			fave_shop_products.id DESC		LIMIT ?, ?;	`	// Category selected	if this.category != nil {		var cat_ids []string		if rows, err := this.wrap.DB.Query(			this.wrap.R.Context(),			`SELECT				node.id			FROM				fave_shop_cats AS node,				fave_shop_cats AS parent			WHERE				node.lft BETWEEN parent.lft AND parent.rgt AND				node.id > 1 AND				parent.id = ?			GROUP BY				node.id			ORDER BY				node.lft ASC			;`,			this.category.Id(),		); err == nil {			defer rows.Close()			for rows.Next() {				var cat_id string				if err := rows.Scan(&cat_id); *this.wrap.LogCpError(&err) == nil {					cat_ids = append(cat_ids, cat_id)				}			}		}		sql_nums = `			SELECT				COUNT(*)			FROM				(					SELECT						COUNT(*)					FROM						fave_shop_products						LEFT JOIN fave_shop_cat_product_rel ON fave_shop_cat_product_rel.product_id = fave_shop_products.id					WHERE						fave_shop_products.active = 1 AND						fave_shop_products.parent_id IS NULL AND						fave_shop_cat_product_rel.category_id IN (` + strings.Join(cat_ids, ", ") + `)					GROUP BY						fave_shop_products.id				) AS tbl			;		`		sql_rows = `			SELECT				fave_shop_products.id,				fave_shop_products.user,				fave_shop_products.currency,				fave_shop_products.price,				fave_shop_products.price_old,				fave_shop_products.gname,				fave_shop_products.name,				fave_shop_products.alias,				fave_shop_products.vendor,				fave_shop_products.quantity,				fave_shop_products.category,				fave_shop_products.briefly,				fave_shop_products.content,				UNIX_TIMESTAMP(fave_shop_products.datetime) AS datetime,				fave_shop_products.active,				fave_users.id,				fave_users.first_name,				fave_users.last_name,				fave_users.email,				fave_users.admin,				fave_users.active,				fave_shop_currencies.id,				fave_shop_currencies.name,				fave_shop_currencies.coefficient,				fave_shop_currencies.code,				fave_shop_currencies.symbol,				cats.id,				cats.user,				cats.name,				cats.alias,				cats.lft,				cats.rgt,				cats.depth,				cats.parent_id			FROM				fave_shop_products				LEFT JOIN fave_shop_cat_product_rel ON fave_shop_cat_product_rel.product_id = fave_shop_products.id				LEFT JOIN fave_users ON fave_users.id = fave_shop_products.user				LEFT JOIN fave_shop_currencies ON fave_shop_currencies.id = fave_shop_products.currency				LEFT JOIN (					SELECT						main.id,						main.user,						main.name,						main.alias,						main.lft,						main.rgt,						main.depth,						parent.id AS parent_id					FROM						(							SELECT								node.id,								node.user,								node.name,								node.alias,								node.lft,								node.rgt,								(COUNT(parent.id) - 1) AS depth							FROM								fave_shop_cats AS node,								fave_shop_cats AS parent							WHERE								node.lft BETWEEN parent.lft AND parent.rgt							GROUP BY								node.id							ORDER BY								node.lft ASC						) AS main						LEFT JOIN (							SELECT								node.id,								node.user,								node.name,								node.alias,								node.lft,								node.rgt,								(COUNT(parent.id) - 0) AS depth							FROM								fave_shop_cats AS node,								fave_shop_cats AS parent							WHERE								node.lft BETWEEN parent.lft AND parent.rgt							GROUP BY								node.id							ORDER BY								node.lft ASC						) AS parent ON						parent.depth = main.depth AND						main.lft > parent.lft AND						main.rgt < parent.rgt					WHERE						main.id > 1					ORDER BY						main.lft ASC				) AS cats ON cats.id = fave_shop_products.category			WHERE				fave_shop_products.active = 1 AND				fave_shop_products.parent_id IS NULL AND				fave_shop_cat_product_rel.category_id IN (` + strings.Join(cat_ids, ", ") + `)			GROUP BY				fave_shop_products.id,				cats.parent_id			ORDER BY				fave_shop_products.quantity DESC,				fave_shop_products.id DESC			LIMIT ?, ?;		`	}	product_ids := []string{}	if err := this.wrap.DB.QueryRow(this.wrap.R.Context(), sql_nums).Scan(&this.productsCount); *this.wrap.LogCpError(&err) == nil {		if this.category == nil {			this.productsPerPage = (*this.wrap.Config).Shop.Pagination.Index		} else {			this.productsPerPage = (*this.wrap.Config).Shop.Pagination.Category		}		this.productsMaxPage = int(math.Ceil(float64(this.productsCount) / float64(this.productsPerPage)))		this.productsCurrPage = this.wrap.GetCurrentPage(this.productsMaxPage)		offset := this.productsCurrPage*this.productsPerPage - this.productsPerPage		if rows, err := this.wrap.DB.Query(this.wrap.R.Context(), sql_rows, offset, this.productsPerPage); err == nil {			defer rows.Close()			for rows.Next() {				rp := utils.MySql_shop_product{}				ru := utils.MySql_user{}				rc := utils.MySql_shop_currency{}				ro := utils.MySql_shop_category{}				if err := rows.Scan(					&rp.A_id,					&rp.A_user,					&rp.A_currency,					&rp.A_price,					&rp.A_price_old,					&rp.A_gname,					&rp.A_name,					&rp.A_alias,					&rp.A_vendor,					&rp.A_quantity,					&rp.A_category,					&rp.A_briefly,					&rp.A_content,					&rp.A_datetime,					&rp.A_active,					&ru.A_id,					&ru.A_first_name,					&ru.A_last_name,					&ru.A_email,					&ru.A_admin,					&ru.A_active,					&rc.A_id,					&rc.A_name,					&rc.A_coefficient,					&rc.A_code,					&rc.A_symbol,					&ro.A_id,					&ro.A_user,					&ro.A_name,					&ro.A_alias,					&ro.A_lft,					&ro.A_rgt,					&ro.A_depth,					&ro.A_parent,				); *this.wrap.LogCpError(&err) == nil {					product_ids = append(product_ids, utils.IntToStr(rp.A_id))					this.products = append(this.products, &ShopProduct{						wrap:     this.wrap,						object:   &rp,						user:     &User{wrap: this.wrap, object: &ru},						currency: &ShopCurrency{wrap: this.wrap, object: &rc},						category: &ShopCategory{wrap: this.wrap, object: &ro},					})				}			}		}	}	// Product images	product_images := map[int][]*ShopProductImage{}	if len(product_ids) > 0 {		if rows, err := this.wrap.DB.Query(			this.wrap.R.Context(),			`SELECT				fave_shop_product_images.product_id,				fave_shop_product_images.filename			FROM				fave_shop_product_images			WHERE				fave_shop_product_images.product_id IN (`+strings.Join(product_ids, ", ")+`)			ORDER BY				fave_shop_product_images.ord ASC			;`,		); err == nil {			defer rows.Close()			for rows.Next() {				img := utils.MySql_shop_product_image{}				if err := rows.Scan(					&img.A_product_id,					&img.A_filename,				); *this.wrap.LogCpError(&err) == nil {					product_images[img.A_product_id] = append(product_images[img.A_product_id], &ShopProductImage{wrap: this.wrap, object: &img})				}			}		}	}	for index, product := range this.products {		if pimgs, ok := product_images[product.Id()]; ok {			this.products[index].images = pimgs		}	}	// Build pagination	if true {		for i := 1; i < this.productsCurrPage; i++ {			if this.productsCurrPage >= 5 && i > 1 && i < this.productsCurrPage-1 {				continue			}			if this.productsCurrPage >= 5 && i > 1 && i < this.productsCurrPage {				this.pagination = append(this.pagination, &ShopPagination{					Dots: true,				})			}			link := this.wrap.R.URL.Path			if i > 1 {				link = link + "?p=" + utils.IntToStr(i)			}			this.pagination = append(this.pagination, &ShopPagination{				Num:     utils.IntToStr(i),				Link:    link,				Current: false,			})		}		// Current page		link := this.wrap.R.URL.Path		if this.productsCurrPage > 1 {			link = link + "?p=" + utils.IntToStr(this.productsCurrPage)		}		this.pagination = append(this.pagination, &ShopPagination{			Num:     utils.IntToStr(this.productsCurrPage),			Link:    link,			Current: true,		})		for i := this.productsCurrPage + 1; i <= this.productsMaxPage; i++ {			if this.productsCurrPage < this.productsMaxPage-3 && i == this.productsCurrPage+3 {				this.pagination = append(this.pagination, &ShopPagination{					Dots: true,				})			}			if this.productsCurrPage < this.productsMaxPage-3 && i > this.productsCurrPage+1 && i <= this.productsMaxPage-1 {				continue			}			link := this.wrap.R.URL.Path			if i > 1 {				link = link + "?p=" + utils.IntToStr(i)			}			this.pagination = append(this.pagination, &ShopPagination{				Num:     utils.IntToStr(i),				Link:    link,				Current: false,			})		}	} else {		for i := 1; i <= this.productsMaxPage; i++ {			link := this.wrap.R.URL.Path			if i > 1 {				link = link + "?p=" + utils.IntToStr(i)			}			this.pagination = append(this.pagination, &ShopPagination{				Num:     utils.IntToStr(i),				Link:    link,				Current: i == this.productsCurrPage,			})		}	}	// Pagination prev/next	if this.productsMaxPage > 1 {		link := this.wrap.R.URL.Path		if this.productsCurrPage-1 > 1 {			link = this.wrap.R.URL.Path + "?p=" + utils.IntToStr(this.productsCurrPage-1)		}		this.paginationPrev = &ShopPagination{			Num:     utils.IntToStr(this.productsCurrPage - 1),			Link:    link,			Current: this.productsCurrPage <= 1,		}		if this.productsCurrPage >= 1 && this.productsCurrPage < this.productsMaxPage {			link = this.wrap.R.URL.Path + "?p=" + utils.IntToStr(this.productsCurrPage+1)		} else {			link = this.wrap.R.URL.Path + "?p=" + utils.IntToStr(this.productsMaxPage)		}		this.paginationNext = &ShopPagination{			Num:     utils.IntToStr(this.productsCurrPage + 1),			Link:    link,			Current: this.productsCurrPage >= this.productsMaxPage,		}	}	return this}func (this *Shop) preload_cats() {	if (*this.wrap.Config).Modules.Enabled.Shop == 0 {		return	}	if this.bufferCats == nil {		this.bufferCats = map[int]*utils.MySql_shop_category{}		if rows, err := this.wrap.DB.Query(			this.wrap.R.Context(),			`SELECT				main.id,				main.user,				main.name,				main.alias,				main.lft,				main.rgt,				main.depth,				parent.id AS parent_id			FROM				(					SELECT						node.id,						node.user,						node.name,						node.alias,						node.lft,						node.rgt,						(COUNT(parent.id) - 1) AS depth					FROM						fave_shop_cats AS node,						fave_shop_cats AS parent					WHERE						node.lft BETWEEN parent.lft AND parent.rgt					GROUP BY						node.id					ORDER BY						node.lft ASC				) AS main				LEFT JOIN (					SELECT						node.id,						node.user,						node.name,						node.alias,						node.lft,						node.rgt,						(COUNT(parent.id) - 0) AS depth					FROM						fave_shop_cats AS node,						fave_shop_cats AS parent					WHERE						node.lft BETWEEN parent.lft AND parent.rgt					GROUP BY						node.id					ORDER BY						node.lft ASC				) AS parent ON				parent.depth = main.depth AND				main.lft > parent.lft AND				main.rgt < parent.rgt			WHERE				main.id > 1			ORDER BY				main.lft ASC			;		`); err == nil {			defer rows.Close()			for rows.Next() {				row := utils.MySql_shop_category{}				if err := rows.Scan(					&row.A_id,					&row.A_user,					&row.A_name,					&row.A_alias,					&row.A_lft,					&row.A_rgt,					&row.A_depth,					&row.A_parent,				); *this.wrap.LogCpError(&err) == nil {					this.bufferCats[row.A_id] = &row					if _, ok := this.bufferCats[row.A_parent]; ok {						this.bufferCats[row.A_parent].A_childs = true					}				}			}		}	}}func (this *Shop) Category() *ShopCategory {	if this == nil {		return nil	}	return this.category}func (this *Shop) Product() *ShopProduct {	if this == nil {		return nil	}	return this.product}func (this *Shop) HaveProducts() bool {	if this == nil {		return false	}	if len(this.products) <= 0 {		return false	}	return true}func (this *Shop) Products() []*ShopProduct {	if this == nil {		return []*ShopProduct{}	}	return this.products}func (this *Shop) ProductsCount() int {	if this == nil {		return 0	}	return this.productsCount}func (this *Shop) ProductsPerPage() int {	if this == nil {		return 0	}	return this.productsPerPage}func (this *Shop) ProductsMaxPage() int {	if this == nil {		return 0	}	return this.productsMaxPage}func (this *Shop) ProductsCurrPage() int {	if this == nil {		return 0	}	return this.productsCurrPage}func (this *Shop) Pagination() []*ShopPagination {	if this == nil {		return []*ShopPagination{}	}	return this.pagination}func (this *Shop) PaginationPrev() *ShopPagination {	if this == nil {		return nil	}	return this.paginationPrev}func (this *Shop) PaginationNext() *ShopPagination {	if this == nil {		return nil	}	return this.paginationNext}func (this *Shop) Currencies() []*ShopCurrency {	result := []*ShopCurrency{}	if (*this.wrap.Config).Modules.Enabled.Shop != 0 {		for _, currency := range *this.wrap.ShopGetAllCurrencies() {			obj := currency			result = append(result, (&ShopCurrency{wrap: this.wrap, object: &obj}).load())		}		sort.Slice(result, func(i, j int) bool { return result[i].Id() < result[j].Id() })	}	return result}func (this *Shop) CurrentCurrency() *ShopCurrency {	obj := *this.wrap.ShopGetCurrentCurrency()	return (&ShopCurrency{wrap: this.wrap, object: &obj}).load()}func (this *Shop) Categories(parent, depth int) []*ShopCategory {	this.preload_cats()	depth_tmp := 0	result := []*ShopCategory{}	if (*this.wrap.Config).Modules.Enabled.Shop != 0 {		for _, cat := range this.bufferCats {			if parent <= 1 {				if depth <= 0 {					result = append(result, (&ShopCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats))				} else {					if cat.A_depth <= depth {						result = append(result, (&ShopCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats))					}				}			} else {				if cat.A_parent == parent {					if depth_tmp == 0 {						depth_tmp = cat.A_depth					}					if depth <= 0 {						result = append(result, (&ShopCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats))					} else {						if (cat.A_depth - depth_tmp + 1) <= depth {							result = append(result, (&ShopCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats))						}					}				}			}		}		sort.Slice(result, func(i, j int) bool { return result[i].Left() < result[j].Left() })	}	return result}
 |