Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
37951 amit 1
package com.smartdukaan.cron.scheduled;
2
 
3
import com.spice.profitmandi.common.model.ProfitMandiConstants;
4
import com.spice.profitmandi.dao.entity.auth.AuthUser;
5
import com.spice.profitmandi.dao.repository.cs.CsService;
6
import org.apache.logging.log4j.LogManager;
7
import org.apache.logging.log4j.Logger;
8
import org.hibernate.SessionFactory;
9
import org.springframework.beans.factory.annotation.Autowired;
10
import org.springframework.beans.factory.annotation.Qualifier;
11
import org.springframework.core.io.ByteArrayResource;
12
import org.springframework.mail.javamail.JavaMailSender;
13
import org.springframework.mail.javamail.MimeMessageHelper;
14
import org.springframework.stereotype.Component;
15
import org.springframework.transaction.annotation.Transactional;
16
 
17
import javax.mail.internet.InternetAddress;
18
import javax.mail.internet.MimeMessage;
19
import java.nio.charset.StandardCharsets;
20
import java.time.LocalDate;
21
import java.util.Arrays;
22
import java.util.LinkedHashSet;
23
import java.util.List;
24
import java.util.Objects;
25
import java.util.Set;
26
import java.util.stream.Collectors;
27
 
28
/**
29
 * Daily list of smartphone items with no catalog.item.brand_identifier, for brands whose mobile
30
 * brand_category row (category_id 3) has brand_identifier_required set. Upload keeps the column optional;
31
 * this report is how the gaps get filled. Excludes feature phones (HSN 85171400), non-channel suppliers
32
 * ONEJMD 500 / Longlife 515 and "Any Colour" placeholders. Mail body = items listed or in stock with partners/us;
33
 * CSV = all. Goes to every level of the category team.
34
 */
35
@Component
36
@Transactional(rollbackFor = Throwable.class)
37
public class BrandIdentifierGapMonitor {
38
 
39
    private static final Logger LOGGER = LogManager.getLogger(BrandIdentifierGapMonitor.class);
40
 
41
    private static final String[] HEADERS = {"Item Id", "Catalog Id", "Brand", "Model", "Color", "Created On", "Live Since", "Listed",
42
            "Partner Stock", "Our Stock"};
43
 
44
    private static final String GAP_QUERY =
45
            "SELECT i.id, i.catalog_item_id, b.name, " +
46
            "TRIM(CONCAT_WS(' ', NULLIF(i.model_name, ''), i.model_number)) model, " +
47
            "TRIM(REPLACE(REPLACE(i.color, 'f_', ''), 'F_', '')) color, DATE(i.addedOn) created_on, " +
48
            "(SELECT DATE(MIN(COALESCE(tl.start_date, tl.create_timestamp))) FROM catalog.tag_listing tl WHERE tl.item_id = i.id AND tl.tag_id = 4) live_since, " +
49
            "IF(EXISTS(SELECT 1 FROM catalog.tag_listing tl WHERE tl.item_id = i.id AND tl.tag_id = 4 AND tl.active = 1), 'Y', 'N') listed, " +
50
            "COALESCE((SELECT SUM(cis.availability) FROM fofo.current_inventory_snapshot cis WHERE cis.item_id = i.id AND cis.availability > 0), 0) partner_stock, " +
51
            "COALESCE((SELECT SUM(ii.currentQuantity) FROM warehouse.inventoryItem ii WHERE ii.itemId = i.id AND ii.currentQuantity > 0), 0) our_stock " +
52
            "FROM catalog.item i " +
53
            "JOIN catalog.catalog c ON c.id = i.catalog_item_id " +
54
            "JOIN catalog.brand b ON b.id = c.brand_id " +
55
            "JOIN catalog.brand_category bc ON bc.brand_id = b.id AND bc.category_id = 3 AND bc.brand_identifier_required = 1 " +
56
            "WHERE i.category = 10006 AND i.hsnCode IN ('85171300', '85171290') " +
57
            "AND (i.brand_identifier IS NULL OR TRIM(i.brand_identifier) = '') " +
58
            "AND i.preferredVendor NOT IN (500, 515) " +
59
            "AND LOWER(TRIM(REPLACE(REPLACE(i.color, 'f_', ''), 'F_', ''))) <> 'any colour' " +
60
            "ORDER BY listed DESC, partner_stock + our_stock DESC, i.addedOn DESC, i.id DESC";
61
 
62
    private static final String[] EXTRA_RECIPIENTS = {"alok.divedi@smartdukaan.com", "gaurav.sharma@smartdukaan.com"};
63
 
64
    @Autowired
65
    private SessionFactory sessionFactory;
66
 
67
    @Autowired
68
    private CsService csService;
69
 
70
    @Autowired
71
    @Qualifier(value = "googleMailSender")
72
    private JavaMailSender googleMailSender;
73
 
74
    @SuppressWarnings("unchecked")
75
    public void monitor() throws Exception {
76
        List<Object[]> rows = sessionFactory.getCurrentSession().createNativeQuery(GAP_QUERY).list();
77
        List<Object[]> liveRows = rows.stream().filter(x -> "Y".equals(String.valueOf(x[7]))
78
                || ((Number) x[8]).intValue() > 0 || ((Number) x[9]).intValue() > 0).collect(Collectors.toList());
79
        LOGGER.info("Brand identifier gaps: {} items, {} listed or in stock", rows.size(), liveRows.size());
80
        if (!rows.isEmpty()) {
81
            this.sendReport(rows, liveRows);
82
        }
83
    }
84
 
85
    private void sendReport(List<Object[]> rows, List<Object[]> liveRows) {
86
        try {
87
            StringBuilder sb = new StringBuilder();
88
            sb.append("<html><body>");
89
            sb.append("<h3>Missing Brand Identifier</h3>");
90
            sb.append("<p>Smartphones of flagged brands without a brand identifier: <b>").append(rows.size())
91
              .append("</b>, of which listed or in stock with partners/us: <b>").append(liveRows.size()).append("</b>.</p>");
92
            sb.append("<p>All items are in the attached CSV. Listed or in-stock items:</p>");
93
            sb.append("<table border='1' cellpadding='5' cellspacing='0'><tr>");
94
            for (String header : HEADERS) {
95
                sb.append("<th>").append(header).append("</th>");
96
            }
97
            sb.append("</tr>");
98
            for (Object[] row : liveRows) {
99
                sb.append("<tr>");
100
                for (Object cell : row) {
101
                    sb.append("<td>").append(cell != null ? cell.toString() : "").append("</td>");
102
                }
103
                sb.append("</tr>");
104
            }
105
            sb.append("</table></body></html>");
106
 
107
            MimeMessage message = googleMailSender.createMimeMessage();
108
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
109
            helper.setSubject("Missing Brand Identifier - " + LocalDate.now());
110
            helper.setText(sb.toString(), true);
111
            helper.addAttachment("missing-brand-identifier-" + LocalDate.now() + ".csv",
112
                    new ByteArrayResource(this.toCsv(rows).getBytes(StandardCharsets.UTF_8)));
113
            Set<String> to = csService.getAuthUserByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_CATEGORY).stream()
114
                    .map(AuthUser::getEmailId).filter(Objects::nonNull).collect(Collectors.toCollection(LinkedHashSet::new));
115
            to.addAll(Arrays.asList(EXTRA_RECIPIENTS));
116
            helper.setTo(to.toArray(new String[0]));
117
            helper.setCc(new String[]{"sdtech@smartdukaan.com", "amit.gupta@smartdukaan.com"});
118
            helper.setFrom(new InternetAddress("sdtech@smartdukaan.com", "Smart Dukaan"));
119
            googleMailSender.send(message);
120
            LOGGER.info("Brand identifier gap report emailed");
121
        } catch (Exception e) {
122
            LOGGER.error("Failed to send brand identifier gap report", e);
123
        }
124
    }
125
 
126
    private String toCsv(List<Object[]> rows) {
127
        StringBuilder sb = new StringBuilder(String.join(",", HEADERS)).append("\n");
128
        for (Object[] row : rows) {
129
            for (int i = 0; i < row.length; i++) {
130
                String cell = row[i] != null ? row[i].toString() : "";
131
                sb.append(i > 0 ? "," : "").append('"').append(cell.replace("\"", "\"\"")).append('"');
132
            }
133
            sb.append("\n");
134
        }
135
        return sb.toString();
136
    }
137
}