Subversion Repositories SmartDukaan

Rev

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

Rev 35757 Rev 35759
Line 9... Line 9...
9
import com.spice.profitmandi.dao.entity.auth.RbmCallSequenceLog;
9
import com.spice.profitmandi.dao.entity.auth.RbmCallSequenceLog;
10
import com.spice.profitmandi.dao.entity.cs.Position;
10
import com.spice.profitmandi.dao.entity.cs.Position;
11
import com.spice.profitmandi.dao.entity.cs.Ticket;
11
import com.spice.profitmandi.dao.entity.cs.Ticket;
12
import com.spice.profitmandi.dao.entity.fofo.FofoStore;
12
import com.spice.profitmandi.dao.entity.fofo.FofoStore;
13
import com.spice.profitmandi.dao.entity.fofo.MonthlyTarget;
13
import com.spice.profitmandi.dao.entity.fofo.MonthlyTarget;
-
 
14
import com.spice.profitmandi.dao.entity.fofo.RetailerContact;
14
import com.spice.profitmandi.dao.entity.inventory.RbmAchievements;
15
import com.spice.profitmandi.dao.entity.inventory.RbmAchievements;
15
import com.spice.profitmandi.dao.entity.inventory.RbmTargets;
16
import com.spice.profitmandi.dao.entity.inventory.RbmTargets;
-
 
17
import com.spice.profitmandi.dao.entity.user.Address;
16
import com.spice.profitmandi.dao.enumuration.auth.CollectionRemark;
18
import com.spice.profitmandi.dao.enumuration.auth.CollectionRemark;
17
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
19
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
18
import com.spice.profitmandi.dao.model.*;
20
import com.spice.profitmandi.dao.model.*;
19
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
21
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
20
import com.spice.profitmandi.dao.repository.auth.PartnerCollectionRemarkRepository;
22
import com.spice.profitmandi.dao.repository.auth.PartnerCollectionRemarkRepository;
Line 22... Line 24...
22
import com.spice.profitmandi.dao.repository.catalog.RbmAchievementsRepository;
24
import com.spice.profitmandi.dao.repository.catalog.RbmAchievementsRepository;
23
import com.spice.profitmandi.dao.repository.catalog.RbmTargetsRepository;
25
import com.spice.profitmandi.dao.repository.catalog.RbmTargetsRepository;
24
import com.spice.profitmandi.dao.repository.cs.CsService;
26
import com.spice.profitmandi.dao.repository.cs.CsService;
25
import com.spice.profitmandi.dao.repository.cs.PositionRepository;
27
import com.spice.profitmandi.dao.repository.cs.PositionRepository;
26
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
28
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
-
 
29
import com.spice.profitmandi.dao.repository.dtr.RetailerContactRepository;
27
import com.spice.profitmandi.dao.repository.fofo.MonthlyTargetRepository;
30
import com.spice.profitmandi.dao.repository.fofo.MonthlyTargetRepository;
28
import com.spice.profitmandi.dao.repository.logistics.PublicHolidaysRepository;
31
import com.spice.profitmandi.dao.repository.logistics.PublicHolidaysRepository;
29
import com.spice.profitmandi.dao.repository.transaction.LoanRepository;
32
import com.spice.profitmandi.dao.repository.transaction.LoanRepository;
30
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
33
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
-
 
34
import com.spice.profitmandi.dao.repository.user.AddressRepository;
31
import com.spice.profitmandi.service.user.RetailerService;
35
import com.spice.profitmandi.service.user.RetailerService;
32
import org.apache.logging.log4j.LogManager;
36
import org.apache.logging.log4j.LogManager;
33
import org.apache.logging.log4j.Logger;
37
import org.apache.logging.log4j.Logger;
34
import org.hibernate.Session;
38
import org.hibernate.Session;
35
import org.hibernate.SessionFactory;
39
import org.hibernate.SessionFactory;
Line 593... Line 597...
593
    com.spice.profitmandi.dao.repository.cs.TicketRepository ticketRepository;
597
    com.spice.profitmandi.dao.repository.cs.TicketRepository ticketRepository;
594
 
598
 
595
    @Autowired
599
    @Autowired
596
    com.spice.profitmandi.dao.repository.cs.AgentCallLogRepository agentCallLogRepository;
600
    com.spice.profitmandi.dao.repository.cs.AgentCallLogRepository agentCallLogRepository;
597
 
601
 
-
 
602
    @Autowired
-
 
603
    RetailerContactRepository retailerContactRepository;
-
 
604
 
-
 
605
    @Autowired
-
 
606
    AddressRepository addressRepository;
-
 
607
 
598
    @Override
608
    @Override
599
    public List<RbmCallTargetModel> getRbmCallTargetModels() throws Exception {
609
    public List<RbmCallTargetModel> getRbmCallTargetModels() throws Exception {
600
        long methodStart = System.currentTimeMillis();
610
        long methodStart = System.currentTimeMillis();
601
        List<RbmCallTargetModel> rbmCallTargetModels = new ArrayList<>();
611
        List<RbmCallTargetModel> rbmCallTargetModels = new ArrayList<>();
602
 
612
 
Line 1029... Line 1039...
1029
        return getCalledPartnerDetails(authId, LocalDate.now());
1039
        return getCalledPartnerDetails(authId, LocalDate.now());
1030
    }
1040
    }
1031
 
1041
 
1032
    @Override
1042
    @Override
1033
    public List<CalledPartnerDetailModel> getCalledPartnerDetails(int authId, LocalDate date) throws ProfitMandiBusinessException {
1043
    public List<CalledPartnerDetailModel> getCalledPartnerDetails(int authId, LocalDate date) throws ProfitMandiBusinessException {
1034
        LocalDate today = date;
-
 
1035
        LocalDateTime startDate = today.atStartOfDay();
-
 
1036
        LocalDate firstOfMonth = today.withDayOfMonth(1);
-
 
1037
        LocalDate endOfMonth = today.withDayOfMonth(today.lengthOfMonth()).plusDays(1);
-
 
1038
 
-
 
1039
        // Get auth user
-
 
1040
        List<AuthUser> authUsers = authRepository.selectByIds(Collections.singletonList(authId));
-
 
1041
        if (authUsers.isEmpty()) {
-
 
1042
            return Collections.emptyList();
-
 
1043
        }
-
 
1044
        AuthUser authUser = authUsers.get(0);
-
 
1045
 
-
 
1046
        // Check if L1 or L2
-
 
1047
        List<Position> positions = positionRepository.selectPositionByAuthIds(Collections.singletonList(authId));
-
 
1048
        boolean isL2 = positions.stream()
-
 
1049
                .anyMatch(p -> ProfitMandiConstants.TICKET_CATEGORY_RBM == p.getCategoryId()
-
 
1050
                        && EscalationType.L2.equals(p.getEscalationType()));
-
 
1051
 
-
 
1052
        // Get fofo IDs for this RBM
1044
        // Get all call logs for this auth user on this date
1053
        List<Integer> fofoIdList;
-
 
1054
        if (isL2) {
-
 
1055
            // L2: get fofo IDs from escalated tickets (all escalated tickets are target)
-
 
1056
            List<Ticket> escalatedTickets = ticketRepository.selectOpenEscalatedTicketsByAuthIds(Collections.singletonList(authId));
1045
        List<com.spice.profitmandi.dao.entity.cs.AgentCallLog> callLogs = agentCallLogRepository.findByAuthIdAndDate(authId, date);
1057
            fofoIdList = escalatedTickets.stream()
-
 
1058
                    .filter(t -> t.getL2AuthUser() == authId
-
 
1059
                            || t.getL3AuthUser() == authId
-
 
1060
                            || t.getL4AuthUser() == authId
-
 
1061
                            || t.getL5AuthUser() == authId)
-
 
1062
                    .map(Ticket::getFofoId)
-
 
1063
                    .distinct()
-
 
1064
                    .collect(Collectors.toList());
-
 
1065
 
-
 
1066
            // Get today's remarks created by L2 (all remarks, not deduplicated)
-
 
1067
            List<PartnerCollectionRemark> todayRemarks = partnerCollectionRemarkRepository
-
 
1068
                    .selectAllByAuthIdsOnDate(Collections.singletonList(authId), today);
-
 
1069
 
-
 
1070
            return buildCalledPartnerResult(todayRemarks);
-
 
1071
        }
-
 
1072
 
1046
 
1073
        // L1 Logic
-
 
1074
        Map<String, Set<Integer>> storeGuyMap;
-
 
1075
        try {
-
 
1076
            storeGuyMap = csService.getAuthUserPartnerIdMapping();
-
 
1077
        } catch (ProfitMandiBusinessException e) {
1047
        if (callLogs.isEmpty()) {
1078
            LOGGER.error("Error fetching store guy map", e);
-
 
1079
            return Collections.emptyList();
1048
            return Collections.emptyList();
1080
        }
1049
        }
1081
 
1050
 
1082
        if (!storeGuyMap.containsKey(authUser.getEmailId())) {
1051
        // Build a map of normalized customer number -> fofoId
-
 
1052
        Map<String, Integer> customerToFofoIdMap = new HashMap<>();
-
 
1053
        Set<String> normalizedNumbers = new HashSet<>();
-
 
1054
 
-
 
1055
        for (com.spice.profitmandi.dao.entity.cs.AgentCallLog callLog : callLogs) {
-
 
1056
            String customerNumber = callLog.getCustomerNumber();
1083
            return Collections.emptyList();
1057
            if (customerNumber != null) {
-
 
1058
                String normalized = customerNumber.startsWith("+91") ? customerNumber.substring(3) : customerNumber;
-
 
1059
                normalizedNumbers.add(normalized);
-
 
1060
            }
1084
        }
1061
        }
1085
        fofoIdList = new ArrayList<>(storeGuyMap.get(authUser.getEmailId()));
-
 
1086
 
1062
 
-
 
1063
        // For each normalized number, find fofoId from retailer_contact first, then address
-
 
1064
        for (String mobile : normalizedNumbers) {
-
 
1065
            Integer fofoId = findFofoIdByMobile(mobile);
1087
        if (fofoIdList.isEmpty()) {
1066
            if (fofoId != null) {
1088
            return Collections.emptyList();
1067
                customerToFofoIdMap.put(mobile, fofoId);
-
 
1068
            }
1089
        }
1069
        }
1090
 
1070
 
1091
        // Get fofo stores for filtering
1071
        // Get unique fofoIds for retailer lookup
-
 
1072
        Set<Integer> fofoIds = new HashSet<>(customerToFofoIdMap.values());
1092
        Map<Integer, FofoStore> fofoStoresMap;
1073
        Map<Integer, CustomRetailer> retailerMap = Collections.emptyMap();
-
 
1074
        if (!fofoIds.isEmpty()) {
1093
        try {
1075
            try {
1094
            fofoStoresMap = fofoStoreRepository.selectByRetailerIds(fofoIdList).stream()
1076
                retailerMap = retailerService.getFofoRetailers(new ArrayList<>(fofoIds));
1095
                    .collect(Collectors.toMap(FofoStore::getId, x -> x, (a, b) -> a));
-
 
1096
        } catch (ProfitMandiBusinessException e) {
1077
            } catch (ProfitMandiBusinessException e) {
1097
            LOGGER.error("Error fetching fofo stores", e);
1078
                LOGGER.error("Error fetching fofo stores", e);
1098
            return Collections.emptyList();
1079
            }
1099
        }
1080
        }
1100
 
1081
 
1101
        // Filter escalated partners for L1
1082
        // Get today's remarks for these fofoIds
1102
        List<Integer> allRemarkIds = partnerCollectionRemarkRepository.selectMaxRemarkId(fofoIdList);
1083
        Map<Integer, List<PartnerCollectionRemark>> fofoRemarkMap = new HashMap<>();
1103
        if (!allRemarkIds.isEmpty()) {
1084
        if (!fofoIds.isEmpty()) {
1104
            Map<Integer, PartnerCollectionRemark> partnerCollectionRemarks = partnerCollectionRemarkRepository.selectByIds(allRemarkIds).stream()
1085
            List<PartnerCollectionRemark> todayRemarks = partnerCollectionRemarkRepository
1105
                    .collect(Collectors.toMap(PartnerCollectionRemark::getFofoId, x -> x, (a, b) -> a));
1086
                    .selectAllByFofoIdsOnDate(new ArrayList<>(fofoIds), date);
1106
            fofoIdList = partnerCollectionRemarks.entrySet().stream()
-
 
1107
                    .filter(entry -> {
-
 
1108
                        PartnerCollectionRemark pcrMap = entry.getValue();
1087
            for (PartnerCollectionRemark remark : todayRemarks) {
1109
                        return !(CollectionRemark.RBM_L2_ESCALATION.equals(pcrMap.getRemark())
1088
                fofoRemarkMap.computeIfAbsent(remark.getFofoId(), k -> new ArrayList<>()).add(remark);
1110
                                || CollectionRemark.SALES_ESCALATION.equals(pcrMap.getRemark()));
-
 
1111
                    })
1089
            }
1112
                    .map(Map.Entry::getKey)
-
 
1113
                    .collect(Collectors.toList());
-
 
1114
        }
1090
        }
1115
 
1091
 
1116
        // Filter to only external, ACTIVE stores
-
 
1117
        List<Integer> validFofoIds = fofoIdList.stream()
-
 
1118
                .filter(fofoId -> {
-
 
1119
                    FofoStore store = fofoStoresMap.get(fofoId);
1092
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a");
1120
                    if (store == null || store.isInternal()) {
-
 
1121
                        return false;
-
 
1122
                    }
-
 
1123
                    return ActivationType.ACTIVE.equals(store.getActivationType());
1093
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy hh:mm a");
1124
                })
-
 
1125
                .collect(Collectors.toList());
1094
        List<CalledPartnerDetailModel> result = new ArrayList<>();
1126
 
1095
 
-
 
1096
        for (com.spice.profitmandi.dao.entity.cs.AgentCallLog callLog : callLogs) {
-
 
1097
            String customerNumber = callLog.getCustomerNumber();
1127
        if (validFofoIds.isEmpty()) {
1098
            if (customerNumber == null) {
1128
            return Collections.emptyList();
1099
                continue;
1129
        }
1100
            }
1130
 
1101
 
1131
        // Get collection rank map
-
 
1132
        Map<Integer, Integer> collectionRankMap;
-
 
1133
        try {
-
 
1134
            collectionRankMap = partnerCollectionService.getCollectionRankMap(validFofoIds, startDate);
1102
            String normalized = customerNumber.startsWith("+91") ? customerNumber.substring(3) : customerNumber;
1135
        } catch (ProfitMandiBusinessException e) {
-
 
1136
            LOGGER.error("Error fetching collection rank map", e);
1103
            Integer fofoId = customerToFofoIdMap.get(normalized);
1137
            collectionRankMap = new HashMap<>();
-
 
1138
        }
-
 
1139
 
1104
 
1140
        // Get MTD billing data for zero billing check
1105
            String partyName = "Unknown";
-
 
1106
            String code = "-";
-
 
1107
 
-
 
1108
            if (fofoId != null) {
1141
        List<RbmWeeklyBillingModel> mtdBillingData = getWeeklyBillingDataForMonth(firstOfMonth, endOfMonth);
1109
                CustomRetailer retailer = retailerMap.get(fofoId);
-
 
1110
                if (retailer != null) {
1142
        Set<Integer> mtdBilledFofoIds = mtdBillingData.stream()
1111
                    partyName = retailer.getBusinessName();
1143
                .filter(RbmWeeklyBillingModel::isMtdBilled)
1112
                    code = retailer.getCode();
-
 
1113
                } else {
1144
                .map(RbmWeeklyBillingModel::getFofoId)
1114
                    partyName = "Unknown (" + fofoId + ")";
-
 
1115
                }
-
 
1116
            } else {
1145
                .collect(Collectors.toSet());
1117
                partyName = "Unknown (" + normalized + ")";
-
 
1118
            }
1146
 
1119
 
-
 
1120
            // Get remark if available
-
 
1121
            String remarkValue = "-";
-
 
1122
            String messageValue = "-";
-
 
1123
            String remarkTime = "-";
-
 
1124
 
1147
        // Build target partner set (PlanToday + CarryForward + ZeroBilling + Untouched)
1125
            if (fofoId != null && fofoRemarkMap.containsKey(fofoId)) {
1148
        Set<Integer> targetFofoIds = new HashSet<>();
1126
                List<PartnerCollectionRemark> remarks = fofoRemarkMap.get(fofoId);
1149
        for (Integer fofoId : validFofoIds) {
1127
                if (!remarks.isEmpty()) {
1150
            int rank = collectionRankMap.getOrDefault(fofoId, 5);
1128
                    PartnerCollectionRemark remark = remarks.get(0);
-
 
1129
                    remarkValue = remark.getRemark() != null ? remark.getRemark().getValue() : "-";
1151
            boolean hasZeroBilling = !mtdBilledFofoIds.contains(fofoId);
1130
                    messageValue = remark.getMessage() != null ? remark.getMessage() : "-";
-
 
1131
                    remarkTime = remark.getCreateTimestamp() != null ? remark.getCreateTimestamp().format(timeFormatter) : "-";
-
 
1132
                }
-
 
1133
            }
1152
 
1134
 
-
 
1135
            // Build call log data
1153
            // Same priority logic as in getRbmCallTargetModels
1136
            String recordingUrl = callLog.getRecordingUrl();
-
 
1137
            String callStatus = callLog.getCallStatus();
1154
            if (rank == 1 || rank == 2 || hasZeroBilling || rank == 3) {
1138
            String callDuration = callLog.getCallDuration();
1155
                targetFofoIds.add(fofoId);
1139
            String callDateTime = null;
-
 
1140
            if (callLog.getCallDate() != null && callLog.getCallTime() != null) {
-
 
1141
                LocalDateTime callDateTimeObj = LocalDateTime.of(callLog.getCallDate(), callLog.getCallTime());
-
 
1142
                callDateTime = callDateTimeObj.format(dateTimeFormatter);
1156
            }
1143
            }
-
 
1144
 
-
 
1145
            result.add(new CalledPartnerDetailModel(partyName, code, remarkValue, messageValue, remarkTime,
1157
            // rank 4 (FuturePlan) and rank 5 (Normal) are NOT in target
1146
                    recordingUrl, callStatus, callDuration, callDateTime));
1158
        }
1147
        }
1159
 
1148
 
-
 
1149
        return result;
-
 
1150
    }
-
 
1151
 
-
 
1152
    private Integer findFofoIdByMobile(String mobile) {
1160
        // Get today's remarks created by L1 (all remarks, not deduplicated)
1153
        // First check retailer_contact
1161
        List<PartnerCollectionRemark> todayRemarks = partnerCollectionRemarkRepository
1154
        List<RetailerContact> contacts = retailerContactRepository.selectByMobile(mobile);
-
 
1155
        if (contacts != null && !contacts.isEmpty()) {
-
 
1156
            return contacts.get(0).getFofoId();
-
 
1157
        }
-
 
1158
 
-
 
1159
        // Fallback to user.address
1162
                .selectAllByAuthIdsOnDate(Collections.singletonList(authId), today);
1160
        Address address = addressRepository.selectByPhoneNumber(mobile);
-
 
1161
        if (address != null) {
-
 
1162
            return address.getRetaierId();
-
 
1163
        }
1163
 
1164
 
1164
        return buildCalledPartnerResult(todayRemarks);
1165
        return null;
1165
    }
1166
    }
1166
 
1167
 
1167
    private List<CalledPartnerDetailModel> buildCalledPartnerResult(List<PartnerCollectionRemark> allRemarks) {
1168
    private List<CalledPartnerDetailModel> buildCalledPartnerResult(List<PartnerCollectionRemark> allRemarks) {
1168
        if (allRemarks.isEmpty()) {
1169
        if (allRemarks.isEmpty()) {
1169
            return Collections.emptyList();
1170
            return Collections.emptyList();