Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
37337 amit 1
package com.spice.profitmandi.web.offercircular;
2
 
3
import java.util.HashMap;
4
import java.util.Map;
5
import java.util.regex.Matcher;
6
import java.util.regex.Pattern;
7
 
8
import com.spice.profitmandi.dao.repository.offers.CircularIngestRepository;
9
 
10
/**
11
 * Human-confirmed exceptions from offers.product_alias, consulted BEFORE any matching.
12
 *
13
 * These exist because the circular and our catalog sometimes name the same product
14
 * differently - Apple ship "iPhone Air" while our catalog rows read "iPhone 17 Air" -
15
 * and because some products are genuinely not ours (no Pixel SKUs are stocked). A
16
 * confirmation recorded once keeps applying every following month, which is the whole
17
 * point: without it the same review queue regenerates identically.
18
 */
19
public final class ProductAliases {
20
 
21
    private static final Pattern VARIANT_SPEC = Pattern.compile(
22
            "\\(?\\s*\\d+\\s*[+/]\\s*\\d+\\s*(?:GB|TB|G|T)?\\s*\\)?|\\d+\\s*(?:GB|TB)",
23
            Pattern.CASE_INSENSITIVE);
24
 
25
    public static final class Alias {
26
        private final String action;
27
        private final String canonicalText;
28
        private final Integer catalogId;
29
        private final Integer superCatalogId;
30
 
31
        Alias(String action, String canonicalText, Integer catalogId, Integer superCatalogId) {
32
            this.action = action;
33
            this.canonicalText = canonicalText;
34
            this.catalogId = catalogId;
35
            this.superCatalogId = superCatalogId;
36
        }
37
        public boolean isIgnore() { return "IGNORE".equals(action); }
38
        public boolean isPin() { return "PIN".equals(action) && (catalogId != null || superCatalogId != null); }
39
        public boolean isRewrite() { return "REWRITE".equals(action) && canonicalText != null; }
40
        public Integer getCatalogId() { return catalogId; }
41
        public Integer getSuperCatalogId() { return superCatalogId; }
42
 
43
        /**
44
         * Substitutes the catalog's spelling while preserving whatever variant spec
45
         * the circular gave, so "iPhone Air" becomes "iPhone 17 Air" and
46
         * "RENO16C 12+256GB" would become "<canonical> 12+256GB".
47
         */
48
        public String rewrite(String rawText) {
49
            StringBuilder sb = new StringBuilder(canonicalText);
50
            Matcher m = VARIANT_SPEC.matcher(rawText);
51
            while (m.find()) {
52
                sb.append(' ').append(m.group());
53
            }
54
            return sb.toString().trim();
55
        }
56
    }
57
 
58
    private final Map<String, Alias> byLabelAndText = new HashMap<>();
59
 
60
    private ProductAliases() { }
61
 
62
    public static ProductAliases load(CircularIngestRepository repository) {
63
        ProductAliases aliases = new ProductAliases();
64
        for (Object[] row : repository.selectProductAliases()) {
65
            String label = (String) row[0];
66
            String rawText = (String) row[1];
67
            String action = (String) row[2];
68
            String canonical = (String) row[3];
69
            int catalogId = ((Number) row[4]).intValue();
70
            int superCatalogId = ((Number) row[5]).intValue();
71
            aliases.byLabelAndText.put(key(label, rawText),
72
                    new Alias(action,
73
                            canonical == null || canonical.isEmpty() ? null : canonical,
74
                            catalogId == 0 ? null : catalogId,
75
                            superCatalogId == 0 ? null : superCatalogId));
76
        }
77
        return aliases;
78
    }
79
 
80
    /** Keyed on the normalised product text so trivial spacing differences still hit. */
81
    private static String key(String divisionLabel, String rawText) {
82
        return divisionLabel + "" + ProductNames.norm(rawText);
83
    }
84
 
85
    public Alias find(String divisionLabel, String rawText) {
86
        return byLabelAndText.get(key(divisionLabel, rawText));
87
    }
88
 
89
    public int size() { return byLabelAndText.size(); }
90
}