server/types/productSearch.go

116 lines
2.3 KiB
Go

/**
* file: types/productSearch.go
* author: Theo Technicguy
* license: Apache 2.0
*
* product searching type and functions
*/
package types
import (
"errors"
"fmt"
"strings"
)
var (
ErrInvalidSearch = errors.New("invalid search")
)
type ProductSearch struct {
Ean string
Names []string
TagIds []uint
Oprators ProductSearchOperators
}
type ProductSearchOperators struct {
Master string
Names string
TagIds string
}
/* *** Validators *** */
func (pso *ProductSearchOperators) ValidOperators() bool {
return ((pso.Master == "AND" || pso.Master == "OR") &&
(pso.Names == "AND" || pso.Names == "OR") &&
(pso.TagIds == "AND" || pso.TagIds == "OR"))
}
func (pso *ProductSearchOperators) Valid() bool {
return pso.ValidOperators()
}
func (ps *ProductSearch) Valid() bool {
return ps.Oprators.Valid()
}
/* *** Type functions *** */
func (pso *ProductSearchOperators) FillDefaults() {
if pso.Master == "" {
pso.Master = "AND"
}
if pso.Names == "" {
pso.Names = "AND"
}
if pso.TagIds == "" {
pso.TagIds = "AND"
}
}
func (ps *ProductSearch) BuildNamesSearch() string {
nameSearch := []string{}
for _, name := range ps.Names {
nameSearch = append(nameSearch, fmt.Sprintf("p.name LIKE '%%%s%%'", name))
}
return "(" + strings.Join(nameSearch, " "+ps.Oprators.Names+" ") + ")"
}
func (ps *ProductSearch) BuildTagSearch() string {
tagSearch := []string{}
for _, tag := range ps.TagIds {
tagSearch = append(tagSearch, fmt.Sprintf("%d", tag))
}
return "ptg.tid IN (" + strings.Join(tagSearch, ", ") + ")"
}
func (ps *ProductSearch) BuildSearch() string {
sql := `SELECT DISTINCT p.*
FROM Product p
LEFT OUTER JOIN ProductTagging ptg ON p.ProductID = ptg.ProductID
LEFT OUTER JOIN ProductTag pt ON ptg.TagID = pt.TagID
`
filters := []string{}
if ps.Ean != "" {
filters = append(filters, fmt.Sprintf("p.ean LIKE '%%%s%%'", ps.Ean))
}
if len(ps.Names) > 0 {
filters = append(filters, ps.BuildNamesSearch())
}
if len(ps.TagIds) > 0 {
filters = append(filters, ps.BuildTagSearch())
}
if len(filters) > 0 {
sql = sql + "WHERE (" + strings.Join(filters, " "+ps.Oprators.Master+" ") + ")\n"
}
if len(ps.TagIds) > 0 {
sql = sql + "GROUP BY p.id"
if ps.Oprators.TagIds == "AND" {
sql = sql + fmt.Sprintf("\nHAVING COUNT(p.id) = %d", len(ps.TagIds))
}
}
sql = sql + ";"
return sql
}