| 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 |
}
|