Subversion Repositories SmartDukaan

Rev

Rev 36276 | Rev 36296 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 36276 Rev 36284
Line 813... Line 813...
813
        Map<Integer, Long> outOfSequenceCountByAuthId = outOfSequenceLogs.stream()
813
        Map<Integer, Long> outOfSequenceCountByAuthId = outOfSequenceLogs.stream()
814
                .collect(Collectors.groupingBy(RbmCallSequenceLog::getAuthId,
814
                .collect(Collectors.groupingBy(RbmCallSequenceLog::getAuthId,
815
                        Collectors.mapping(RbmCallSequenceLog::getFofoId, Collectors.collectingAndThen(Collectors.toSet(), s -> (long) s.size()))));
815
                        Collectors.mapping(RbmCallSequenceLog::getFofoId, Collectors.collectingAndThen(Collectors.toSet(), s -> (long) s.size()))));
816
        LOGGER.info("RBM Call Target - Out of Sequence fetch: {}ms", System.currentTimeMillis() - start);
816
        LOGGER.info("RBM Call Target - Out of Sequence fetch: {}ms", System.currentTimeMillis() - start);
817
 
817
 
-
 
818
        // BATCH FETCH: All call logs for all RBMs (L1 + L2 + L3) in a single query.
-
 
819
        // Replaces the previous N+1 pattern where getCallStats() was called per RBM.
-
 
820
        start = System.currentTimeMillis();
-
 
821
        List<AgentCallLog> allCallLogs = agentCallLogRepository.findByAuthIdsAndDate(rbmPositionsAuthIds, queryDate);
-
 
822
        Map<Long, List<AgentCallLog>> callLogsByAuthId = allCallLogs.stream()
-
 
823
                .collect(Collectors.groupingBy(AgentCallLog::getAuthId));
-
 
824
        LOGGER.info("RBM Call Target - Call logs batch fetch: {}ms ({} logs across {} RBMs)",
-
 
825
                System.currentTimeMillis() - start, allCallLogs.size(), callLogsByAuthId.size());
-
 
826
 
-
 
827
        // BATCH FETCH: Build a single mobile -> fofoId map from all unique customer numbers across all call logs.
-
 
828
        // Replaces the previous N+1 pattern where findFofoIdByMobile() was called per call log entry.
-
 
829
        start = System.currentTimeMillis();
-
 
830
        Set<String> allNormalizedMobiles = new HashSet<>();
-
 
831
        for (AgentCallLog callLog : allCallLogs) {
-
 
832
            String customerNumber = callLog.getCustomerNumber();
-
 
833
            if (customerNumber != null) {
-
 
834
                String normalized = customerNumber.startsWith("+91") ? customerNumber.substring(3) : customerNumber;
-
 
835
                allNormalizedMobiles.add(normalized);
-
 
836
            }
-
 
837
        }
-
 
838
        Map<String, Integer> mobileToFofoIdMap = buildMobileToFofoIdMap(allNormalizedMobiles);
-
 
839
        LOGGER.info("RBM Call Target - Mobile→FofoId batch fetch: {}ms ({} unique mobiles, {} mapped)",
-
 
840
                System.currentTimeMillis() - start, allNormalizedMobiles.size(), mobileToFofoIdMap.size());
-
 
841
 
818
        // Identify users who are both L1 and L2 — they will be shown only as L2
842
        // Identify users who are both L1 and L2 — they will be shown only as L2
819
        Set<Integer> l2AuthIdSet = new HashSet<>(l2AuthIds);
843
        Set<Integer> l2AuthIdSet = new HashSet<>(l2AuthIds);
820
 
844
 
821
        // Process L1 RBMs (skip users who are also L2 — their data will be merged into L2 model)
845
        // Process L1 RBMs (skip users who are also L2 — their data will be merged into L2 model)
822
        for (int rbmAuthId : l1AuthIds) {
846
        for (int rbmAuthId : l1AuthIds) {
Line 943... Line 967...
943
            todayTargetPartners.addAll(planTodayPartners);
967
            todayTargetPartners.addAll(planTodayPartners);
944
            todayTargetPartners.addAll(carryForwardPartners);
968
            todayTargetPartners.addAll(carryForwardPartners);
945
            todayTargetPartners.addAll(zeroBillingPartners);
969
            todayTargetPartners.addAll(zeroBillingPartners);
946
            todayTargetPartners.addAll(untouchedPartners);
970
            todayTargetPartners.addAll(untouchedPartners);
947
 
971
 
948
            // Value Achieved = All distinct partners called today (from call logs)
972
            // Value Achieved = All distinct partners called today (from pre-fetched call logs)
949
            long[] callStats = getCallStats(rbmAuthId, queryDate);
973
            long[] callStats = getCallStatsFromLogs(callLogsByAuthId.get((long) rbmAuthId), mobileToFofoIdMap);
950
            targetModel.setValueTargetAchieved(callStats[0]);
974
            targetModel.setValueTargetAchieved(callStats[0]);
951
            targetModel.setTotalRecordingCalls(callStats[1]);
975
            targetModel.setTotalRecordingCalls(callStats[1]);
952
            targetModel.setUniqueRecordingCalls(callStats[2]);
976
            targetModel.setUniqueRecordingCalls(callStats[2]);
953
 
977
 
954
            // Keep todayRemarks for movedToFuture calculation
978
            // Keep todayRemarks for movedToFuture calculation
Line 1098... Line 1122...
1098
            } else {
1122
            } else {
1099
                // Pure L2 (not also L1) — target is only L2 escalation
1123
                // Pure L2 (not also L1) — target is only L2 escalation
1100
                l2Model.setTodayTargetOfCall(l2TargetFofoIds.size());
1124
                l2Model.setTodayTargetOfCall(l2TargetFofoIds.size());
1101
            }
1125
            }
1102
 
1126
 
1103
            // Value Achieved = All distinct partners called today (from call logs)
1127
            // Value Achieved = All distinct partners called today (from pre-fetched call logs)
1104
            long[] l2CallStats = getCallStats(l2AuthId, queryDate);
1128
            long[] l2CallStats = getCallStatsFromLogs(callLogsByAuthId.get((long) l2AuthId), mobileToFofoIdMap);
1105
            l2Model.setValueTargetAchieved(l2CallStats[0]);
1129
            l2Model.setValueTargetAchieved(l2CallStats[0]);
1106
            l2Model.setTotalRecordingCalls(l2CallStats[1]);
1130
            l2Model.setTotalRecordingCalls(l2CallStats[1]);
1107
            l2Model.setUniqueRecordingCalls(l2CallStats[2]);
1131
            l2Model.setUniqueRecordingCalls(l2CallStats[2]);
1108
 
1132
 
1109
            l2Model.setOutOfSequenceCount(outOfSequenceCountByAuthId.getOrDefault(l2AuthId, 0L));
1133
            l2Model.setOutOfSequenceCount(outOfSequenceCountByAuthId.getOrDefault(l2AuthId, 0L));
Line 1132... Line 1156...
1132
            l3Model.setPartnerCount(l3AssignedFofoIds.size());
1156
            l3Model.setPartnerCount(l3AssignedFofoIds.size());
1133
 
1157
 
1134
            // L3 Target = partners with RBM_L3_ESCALATION as latest remark
1158
            // L3 Target = partners with RBM_L3_ESCALATION as latest remark
1135
            l3Model.setTodayTargetOfCall(l3TargetFofoIds.size());
1159
            l3Model.setTodayTargetOfCall(l3TargetFofoIds.size());
1136
 
1160
 
1137
            // Value Achieved = All distinct partners called today (from call logs)
1161
            // Value Achieved = All distinct partners called today (from pre-fetched call logs)
1138
            long[] l3CallStats = getCallStats(l3AuthId, queryDate);
1162
            long[] l3CallStats = getCallStatsFromLogs(callLogsByAuthId.get((long) l3AuthId), mobileToFofoIdMap);
1139
            l3Model.setValueTargetAchieved(l3CallStats[0]);
1163
            l3Model.setValueTargetAchieved(l3CallStats[0]);
1140
            l3Model.setTotalRecordingCalls(l3CallStats[1]);
1164
            l3Model.setTotalRecordingCalls(l3CallStats[1]);
1141
            l3Model.setUniqueRecordingCalls(l3CallStats[2]);
1165
            l3Model.setUniqueRecordingCalls(l3CallStats[2]);
1142
 
1166
 
1143
            l3Model.setOutOfSequenceCount(outOfSequenceCountByAuthId.getOrDefault(l3AuthId, 0L));
1167
            l3Model.setOutOfSequenceCount(outOfSequenceCountByAuthId.getOrDefault(l3AuthId, 0L));
Line 1721... Line 1745...
1721
    public long getCalledCountFromCallLogs(long authId, LocalDate date) {
1745
    public long getCalledCountFromCallLogs(long authId, LocalDate date) {
1722
        return getCallStats(authId, date)[0];
1746
        return getCallStats(authId, date)[0];
1723
    }
1747
    }
1724
 
1748
 
1725
    /**
1749
    /**
-
 
1750
     * Batch-builds a mobile (normalized, +91 stripped) -> fofoId mapping for all the given mobiles
-
 
1751
     * in just two queries (retailer_contact, then address fallback for unmapped numbers).
-
 
1752
     * Replaces the previous per-call-log findFofoIdByMobile() N+1 lookups.
-
 
1753
     */
-
 
1754
    private Map<String, Integer> buildMobileToFofoIdMap(Set<String> normalizedMobiles) {
-
 
1755
        Map<String, Integer> result = new HashMap<>();
-
 
1756
        if (normalizedMobiles == null || normalizedMobiles.isEmpty()) {
-
 
1757
            return result;
-
 
1758
        }
-
 
1759
        List<String> mobilesList = new ArrayList<>(normalizedMobiles);
-
 
1760
 
-
 
1761
        // First pass: retailer_contact
-
 
1762
        List<RetailerContact> contacts = retailerContactRepository.selectByMobiles(mobilesList);
-
 
1763
        for (RetailerContact rc : contacts) {
-
 
1764
            // Keep the first fofoId we see per mobile (matches old single-mobile behavior of get(0))
-
 
1765
            result.putIfAbsent(rc.getMobile(), rc.getFofoId());
-
 
1766
        }
-
 
1767
 
-
 
1768
        // Second pass: address fallback for mobiles not yet mapped
-
 
1769
        List<String> unmapped = mobilesList.stream()
-
 
1770
                .filter(m -> !result.containsKey(m))
-
 
1771
                .collect(Collectors.toList());
-
 
1772
        if (!unmapped.isEmpty()) {
-
 
1773
            List<Address> addresses = addressRepository.selectAllByPhoneNumbers(unmapped);
-
 
1774
            for (Address addr : addresses) {
-
 
1775
                result.putIfAbsent(addr.getPhoneNumber(), addr.getRetaierId());
-
 
1776
            }
-
 
1777
        }
-
 
1778
        return result;
-
 
1779
    }
-
 
1780
 
-
 
1781
    /**
-
 
1782
     * In-memory variant of getCallStats() that uses pre-fetched call logs and mobile→fofoId mapping.
-
 
1783
     * Used by the batch-fetched RBM Call Target loop to avoid N+1 query patterns.
-
 
1784
     */
-
 
1785
    private long[] getCallStatsFromLogs(List<AgentCallLog> callLogs, Map<String, Integer> mobileToFofoIdMap) {
-
 
1786
        if (callLogs == null || callLogs.isEmpty()) {
-
 
1787
            return new long[]{0, 0, 0};
-
 
1788
        }
-
 
1789
 
-
 
1790
        Set<Integer> calledFofoIds = new HashSet<>();
-
 
1791
        Set<String> calledNumbersWithoutFofoId = new HashSet<>();
-
 
1792
        long totalRecordingCalls = 0;
-
 
1793
        Set<String> uniqueRecordingNumbers = new HashSet<>();
-
 
1794
 
-
 
1795
        for (AgentCallLog callLog : callLogs) {
-
 
1796
            String customerNumber = callLog.getCustomerNumber();
-
 
1797
            if (customerNumber != null) {
-
 
1798
                String normalized = customerNumber.startsWith("+91") ? customerNumber.substring(3) : customerNumber;
-
 
1799
                Integer fofoId = mobileToFofoIdMap.get(normalized);
-
 
1800
                if (fofoId != null) {
-
 
1801
                    calledFofoIds.add(fofoId);
-
 
1802
                } else {
-
 
1803
                    calledNumbersWithoutFofoId.add(normalized);
-
 
1804
                }
-
 
1805
 
-
 
1806
                if (callLog.getRecordingUrl() != null && !callLog.getRecordingUrl().isEmpty()
-
 
1807
                        && !"None".equalsIgnoreCase(callLog.getRecordingUrl())) {
-
 
1808
                    totalRecordingCalls++;
-
 
1809
                    uniqueRecordingNumbers.add(normalized);
-
 
1810
                }
-
 
1811
            }
-
 
1812
        }
-
 
1813
 
-
 
1814
        long calledCount = calledFofoIds.size() + calledNumbersWithoutFofoId.size();
-
 
1815
        return new long[]{calledCount, totalRecordingCalls, uniqueRecordingNumbers.size()};
-
 
1816
    }
-
 
1817
 
-
 
1818
    /**
1726
     * Returns call stats: [0] = called count, [1] = total recording calls, [2] = unique recording calls
1819
     * Returns call stats: [0] = called count, [1] = total recording calls, [2] = unique recording calls
1727
     */
1820
     */
1728
    public long[] getCallStats(long authId, LocalDate date) {
1821
    public long[] getCallStats(long authId, LocalDate date) {
1729
        List<AgentCallLog> callLogs = agentCallLogRepository.findByAuthIdAndDate(authId, date);
1822
        List<AgentCallLog> callLogs = agentCallLogRepository.findByAuthIdAndDate(authId, date);
1730
 
1823