Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -793,6 +793,11 @@ ORDER BY d.id, r.priority DESC, r.id
|
|||||||
}
|
}
|
||||||
|
|
||||||
func productSeriesSelectRules(v productSeriesAutoVariant, rules []productSeriesAutoRule) []productSeriesAutoRule {
|
func productSeriesSelectRules(v productSeriesAutoVariant, rules []productSeriesAutoRule) []productSeriesAutoRule {
|
||||||
|
selectionMode := strings.TrimSpace(strings.ToLower(os.Getenv("PRODUCT_SERIES_SELECTION_MODE")))
|
||||||
|
if selectionMode == "" {
|
||||||
|
selectionMode = "dfs"
|
||||||
|
}
|
||||||
|
|
||||||
candidates := make([]productSeriesAutoRule, 0, len(rules))
|
candidates := make([]productSeriesAutoRule, 0, len(rules))
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
if !productSeriesRuleFitsGroup(v.GroupKey, rule) {
|
if !productSeriesRuleFitsGroup(v.GroupKey, rule) {
|
||||||
@@ -805,6 +810,58 @@ func productSeriesSelectRules(v productSeriesAutoVariant, rules []productSeriesA
|
|||||||
if len(candidates) == 0 {
|
if len(candidates) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if selectionMode == "greedy" {
|
||||||
|
// Greedy: start from the widest series (most sizes), then narrower, until nothing fits.
|
||||||
|
// This matches the operational expectation: cover as much of the stock-size space as possible
|
||||||
|
// using broad series first, then progressively narrower series; fallback=1 only if nothing matches.
|
||||||
|
sort.Slice(candidates, func(i, j int) bool {
|
||||||
|
li := len(candidates[i].Ratio)
|
||||||
|
lj := len(candidates[j].Ratio)
|
||||||
|
if li != lj {
|
||||||
|
return li > lj
|
||||||
|
}
|
||||||
|
if candidates[i].Priority != candidates[j].Priority {
|
||||||
|
return candidates[i].Priority > candidates[j].Priority
|
||||||
|
}
|
||||||
|
// Prefer numeric codes ascending when comparable, otherwise lexicographic.
|
||||||
|
ai, ei := strconv.Atoi(strings.TrimSpace(candidates[i].Code))
|
||||||
|
aj, ej := strconv.Atoi(strings.TrimSpace(candidates[j].Code))
|
||||||
|
if ei == nil && ej == nil && ai != aj {
|
||||||
|
return ai < aj
|
||||||
|
}
|
||||||
|
return candidates[i].Code < candidates[j].Code
|
||||||
|
})
|
||||||
|
|
||||||
|
stock := copyProductSeriesStock(v.SizeQty)
|
||||||
|
picked := make([]productSeriesAutoRule, 0, 8)
|
||||||
|
used := make([]bool, len(candidates))
|
||||||
|
for {
|
||||||
|
pickedOne := false
|
||||||
|
for i := range candidates {
|
||||||
|
if used[i] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rule := candidates[i]
|
||||||
|
if productSeriesCanConsume(stock, rule) {
|
||||||
|
used[i] = true
|
||||||
|
picked = append(picked, rule)
|
||||||
|
productSeriesConsume(stock, rule, -1)
|
||||||
|
pickedOne = true
|
||||||
|
break // restart from widest again
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !pickedOne {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(picked) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
sort.Slice(picked, func(i, j int) bool { return picked[i].Code < picked[j].Code })
|
||||||
|
return picked
|
||||||
|
}
|
||||||
|
|
||||||
if len(candidates) > 24 {
|
if len(candidates) > 24 {
|
||||||
candidates = candidates[:24]
|
candidates = candidates[:24]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user