Subversion Repositories SmartDukaan

Rev

Rev 37862 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 37862 Rev 37892
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 {