| Line 1785... |
Line 1785... |
| 1785 |
}
|
1785 |
}
|
| 1786 |
/** Test recipient(s) for the RBM ranking probe email. Kept here (not in a config)
|
1786 |
/** Test recipient(s) for the RBM ranking probe email. Kept here (not in a config)
|
| 1787 |
* because this whole flow is a Phase-1 probe — Phase 2 will move recipients into
|
1787 |
* because this whole flow is a Phase-1 probe — Phase 2 will move recipients into
|
| 1788 |
* the shipped monthly-email cron. */
|
1788 |
* the shipped monthly-email cron. */
|
| 1789 |
private static final String[] RBM_RANK_PROBE_RECIPIENTS = {
|
1789 |
private static final String[] RBM_RANK_PROBE_RECIPIENTS = {
|
| 1790 |
"gaurav.mathur@smartdukaan.com",
|
1790 |
// "gaurav.mathur@smartdukaan.com",
|
| 1791 |
"kangan.monga@smartdukaan.com",
|
1791 |
// "kangan.monga@smartdukaan.com",
|
| 1792 |
"siddharth.chaturvedi@smartdukaan.com",
|
1792 |
// "siddharth.chaturvedi@smartdukaan.com",
|
| 1793 |
// "aquil.ahmad@smartdukaan.com",
|
1793 |
// "aquil.ahmad@smartdukaan.com",
|
| 1794 |
"charu.sharma@smartdukaan.com",
|
1794 |
// "charu.sharma@smartdukaan.com",
|
| 1795 |
"ranu.rajput@smartdukaan.com"
|
1795 |
"ranu.rajput@smartdukaan.com"
|
| 1796 |
};
|
1796 |
};
|
| 1797 |
|
1797 |
|
| 1798 |
/**
|
1798 |
/**
|
| 1799 |
* Prints the composite RBM performance ranking for the given month to log
|
1799 |
* Prints the composite RBM performance ranking for the given month to log
|
| Line 1807... |
Line 1807... |
| 1807 |
LocalDate to = month.atEndOfMonth();
|
1807 |
LocalDate to = month.atEndOfMonth();
|
| 1808 |
LOGGER.info("[RBM-RANK] === Composite ranking for {} ({} → {}) ===",
|
1808 |
LOGGER.info("[RBM-RANK] === Composite ranking for {} ({} → {}) ===",
|
| 1809 |
month, from, to);
|
1809 |
month, from, to);
|
| 1810 |
List<RbmPerformanceDashboardModel> ranked =
|
1810 |
List<RbmPerformanceDashboardModel> ranked =
|
| 1811 |
rbmPerformanceRankingService.buildRanking(from, to);
|
1811 |
rbmPerformanceRankingService.buildRanking(from, to);
|
| - |
|
1812 |
|
| - |
|
1813 |
// Sep 2026: computed Aging% has a gap (warehouse close/reopen + stock
|
| - |
|
1814 |
// transfers skew the live snapshot). Inject the 15-day aging values
|
| - |
|
1815 |
// reported for 30-Sep for these RBMs, then re-score + re-rank with the
|
| - |
|
1816 |
// same weights the service uses. Other metrics stay query-driven.
|
| - |
|
1817 |
if (month.equals(java.time.YearMonth.of(2026, 9))) {
|
| - |
|
1818 |
Map<String, Double> agingOverrideSep26 = new LinkedHashMap<>();
|
| - |
|
1819 |
agingOverrideSep26.put("Akash", 146.7);
|
| - |
|
1820 |
agingOverrideSep26.put("Vinay", 284.1);
|
| - |
|
1821 |
agingOverrideSep26.put("Gurmeet", 242.0);
|
| - |
|
1822 |
agingOverrideSep26.put("Shikha", 121.7);
|
| - |
|
1823 |
agingOverrideSep26.put("Neha Dubey", 49.7);
|
| - |
|
1824 |
agingOverrideSep26.put("Hariom Sharma", 129.3);
|
| - |
|
1825 |
agingOverrideSep26.put("Sneha", 102.4);
|
| - |
|
1826 |
agingOverrideSep26.put("Nikita", 146.8);
|
| - |
|
1827 |
for (RbmPerformanceDashboardModel dm : ranked) {
|
| - |
|
1828 |
String name = dm.getRbmName() == null ? "" : dm.getRbmName().toLowerCase();
|
| - |
|
1829 |
for (Map.Entry<String, Double> e : agingOverrideSep26.entrySet()) {
|
| - |
|
1830 |
if (name.contains(e.getKey().toLowerCase())) {
|
| - |
|
1831 |
LOGGER.info("[RBM-RANK] Aging override for {}: {} -> {}",
|
| - |
|
1832 |
dm.getRbmName(),
|
| - |
|
1833 |
String.format("%.1f", dm.getAgingPct()), e.getValue());
|
| - |
|
1834 |
dm.setAgingPct(e.getValue());
|
| - |
|
1835 |
break;
|
| - |
|
1836 |
}
|
| - |
|
1837 |
}
|
| - |
|
1838 |
}
|
| - |
|
1839 |
for (RbmPerformanceDashboardModel dm : ranked) {
|
| - |
|
1840 |
double avgRatingScore = (dm.getPartnerRating() / 5.0) * 100;
|
| - |
|
1841 |
double partnersRatedScore = dm.getPartnerCount() > 0
|
| - |
|
1842 |
? (dm.getRatingPartnerCount() * 100.0 / dm.getPartnerCount()) : 0;
|
| - |
|
1843 |
double composite = (dm.getTalkPct() * 0.10)
|
| - |
|
1844 |
+ (dm.getDrrAchvPct() * 0.55)
|
| - |
|
1845 |
+ (dm.getAgingPct() * 0.02)
|
| - |
|
1846 |
+ (dm.getAbove1LPct() * 0.29)
|
| - |
|
1847 |
+ (avgRatingScore * 0.02)
|
| - |
|
1848 |
+ (partnersRatedScore * 0.02);
|
| - |
|
1849 |
dm.setCompositeScore(composite);
|
| - |
|
1850 |
}
|
| - |
|
1851 |
ranked.sort((a, b) -> Double.compare(b.getCompositeScore(), a.getCompositeScore()));
|
| - |
|
1852 |
int currentRank = 1;
|
| - |
|
1853 |
for (int i = 0; i < ranked.size(); i++) {
|
| - |
|
1854 |
if (i > 0 && ranked.get(i).getCompositeScore()
|
| - |
|
1855 |
< ranked.get(i - 1).getCompositeScore()) {
|
| - |
|
1856 |
currentRank = i + 1;
|
| - |
|
1857 |
}
|
| - |
|
1858 |
ranked.get(i).setRank(currentRank);
|
| - |
|
1859 |
}
|
| - |
|
1860 |
}
|
| - |
|
1861 |
|
| 1812 |
LOGGER.info("[RBM-RANK] {} RBMs ranked", ranked.size());
|
1862 |
LOGGER.info("[RBM-RANK] {} RBMs ranked", ranked.size());
|
| 1813 |
String header = String.format(
|
1863 |
String header = String.format(
|
| 1814 |
"%-4s %-25s %6s %8s %8s %10s %8s %6s %8s %8s",
|
1864 |
"%-4s %-25s %6s %8s %28s %10s %8s %6s %8s %8s",
|
| 1815 |
"RANK", "RBM NAME", "PART", "TALK%", "DRR%",
|
1865 |
"RANK", "RBM NAME", "PART", "TALK%", "DRR%(SEC/TGT)",
|
| 1816 |
"AGING%", ">1L%", "RATE", "RATED%", "SCORE");
|
1866 |
"AGING%", ">1L%", "RATE", "RATED%", "SCORE");
|
| 1817 |
LOGGER.info("[RBM-RANK] {}", header);
|
1867 |
LOGGER.info("[RBM-RANK] {}", header);
|
| 1818 |
for (RbmPerformanceDashboardModel dm : ranked) {
|
1868 |
for (RbmPerformanceDashboardModel dm : ranked) {
|
| 1819 |
double ratedPct = dm.getPartnerCount() > 0
|
1869 |
double ratedPct = dm.getPartnerCount() > 0
|
| 1820 |
? dm.getRatingPartnerCount() * 100.0 / dm.getPartnerCount() : 0;
|
1870 |
? dm.getRatingPartnerCount() * 100.0 / dm.getPartnerCount() : 0;
|
| 1821 |
String rbmName = dm.getRbmName() == null ? "-" : dm.getRbmName();
|
1871 |
String rbmName = dm.getRbmName() == null ? "-" : dm.getRbmName();
|
| 1822 |
if (rbmName.length() > 25) rbmName = rbmName.substring(0, 24) + "…";
|
1872 |
if (rbmName.length() > 25) rbmName = rbmName.substring(0, 24) + "…";
|
| - |
|
1873 |
String drrCell = String.format("%.1f(%.1fL/%.1fL)",
|
| - |
|
1874 |
dm.getDrrAchvPct(),
|
| - |
|
1875 |
dm.getMtdAchieved() / 100000.0,
|
| - |
|
1876 |
dm.getMonthlyTarget() / 100000.0);
|
| 1823 |
LOGGER.info("[RBM-RANK] {}", String.format(
|
1877 |
LOGGER.info("[RBM-RANK] {}", String.format(
|
| 1824 |
"%-4d %-25s %6d %8.1f %8.1f %10.1f %8.1f %6.2f %8.1f %8.2f",
|
1878 |
"%-4d %-25s %6d %8.1f %28s %10.1f %8.1f %6.2f %8.1f %8.2f",
|
| 1825 |
dm.getRank(), rbmName, dm.getPartnerCount(),
|
1879 |
dm.getRank(), rbmName, dm.getPartnerCount(),
|
| 1826 |
dm.getTalkPct(), dm.getDrrAchvPct(), dm.getAgingPct(),
|
1880 |
dm.getTalkPct(), drrCell, dm.getAgingPct(),
|
| 1827 |
dm.getAbove1LPct(), dm.getPartnerRating(), ratedPct,
|
1881 |
dm.getAbove1LPct(), dm.getPartnerRating(), ratedPct,
|
| 1828 |
dm.getCompositeScore()));
|
1882 |
dm.getCompositeScore()));
|
| 1829 |
}
|
1883 |
}
|
| 1830 |
LOGGER.info("[RBM-RANK] === End ranking for {} ===", month);
|
1884 |
LOGGER.info("[RBM-RANK] === End ranking for {} ===", month);
|
| 1831 |
|
1885 |
|
| 1832 |
// Email the same table so the user can eyeball without tailing logs.
|
1886 |
// Email disabled while verifying data gaps — check logs only.
|
| 1833 |
try {
|
1887 |
// try {
|
| 1834 |
sendRbmRankingProbeEmail(month, from, to, ranked);
|
1888 |
// sendRbmRankingProbeEmail(month, from, to, ranked);
|
| 1835 |
} catch (Exception e) {
|
1889 |
// } catch (Exception e) {
|
| 1836 |
LOGGER.error("[RBM-RANK] Email send FAILED (log-only fallback in place): {}", e.getMessage(), e);
|
1890 |
// LOGGER.error("[RBM-RANK] Email send FAILED (log-only fallback in place): {}", e.getMessage(), e);
|
| 1837 |
}
|
1891 |
// }
|
| 1838 |
}
|
1892 |
}
|
| 1839 |
|
1893 |
|
| 1840 |
/** Direct HTML send via googleMailSender — bypasses mail_outbox so dev delivers. */
|
1894 |
/** Direct HTML send via googleMailSender — bypasses mail_outbox so dev delivers. */
|
| 1841 |
private void sendRbmRankingProbeEmail(java.time.YearMonth month, LocalDate from, LocalDate to,
|
1895 |
private void sendRbmRankingProbeEmail(java.time.YearMonth month, LocalDate from, LocalDate to,
|
| 1842 |
List<RbmPerformanceDashboardModel> ranked) throws Exception {
|
1896 |
List<RbmPerformanceDashboardModel> ranked) throws Exception {
|