Subversion Repositories SmartDukaan

Rev

Rev 37287 | Rev 37355 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
25979 tejbeer 1
package com.spice.profitmandi.web.controller;
2
 
29266 manish 3
import com.google.gson.Gson;
31370 tejbeer 4
import com.mongodb.DBObject;
25988 tejbeer 5
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
33843 ranu 6
import com.spice.profitmandi.common.model.*;
29426 manish 7
import com.spice.profitmandi.common.util.FileUtil;
34627 aman.kumar 8
import com.spice.profitmandi.common.util.FormattingUtils;
31370 tejbeer 9
import com.spice.profitmandi.common.web.util.ResponseSender;
25979 tejbeer 10
import com.spice.profitmandi.dao.entity.auth.AuthUser;
32464 tejbeer 11
import com.spice.profitmandi.dao.entity.catalog.BrandCatalog;
30416 tejbeer 12
import com.spice.profitmandi.dao.entity.fofo.PartnerDailyInvestment;
33843 ranu 13
import com.spice.profitmandi.dao.entity.user.*;
30773 amit.gupta 14
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
31249 tejbeer 15
import com.spice.profitmandi.dao.enumuration.dtr.CommunicationType;
29598 tejbeer 16
import com.spice.profitmandi.dao.enumuration.dtr.LeadSource;
25979 tejbeer 17
import com.spice.profitmandi.dao.enumuration.dtr.LeadStatus;
33843 ranu 18
import com.spice.profitmandi.dao.model.*;
25979 tejbeer 19
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
30185 tejbeer 20
import com.spice.profitmandi.dao.repository.auth.PartnerCollectionPlanRepository;
30434 tejbeer 21
import com.spice.profitmandi.dao.repository.auth.PartnerCollectionRemarkRepository;
30416 tejbeer 22
import com.spice.profitmandi.dao.repository.cs.CsService;
29266 manish 23
import com.spice.profitmandi.dao.repository.cs.PositionRepository;
33843 ranu 24
import com.spice.profitmandi.dao.repository.dtr.*;
30416 tejbeer 25
import com.spice.profitmandi.dao.repository.fofo.PartnerDailyInvestmentRepository;
35223 ranu 26
import com.spice.profitmandi.dao.repository.fofo.RbmRatingRepository;
25979 tejbeer 27
import com.spice.profitmandi.dao.repository.inventory.StateRepository;
30445 tejbeer 28
import com.spice.profitmandi.dao.repository.transaction.UserWalletRepository;
29266 manish 29
import com.spice.profitmandi.service.AuthService;
30416 tejbeer 30
import com.spice.profitmandi.service.PartnerCollectionService;
33917 ranu 31
import com.spice.profitmandi.service.RbmTargetService;
32464 tejbeer 32
import com.spice.profitmandi.service.catalog.BrandsService;
34650 aman.kumar 33
import com.spice.profitmandi.service.order.OrderService;
30416 tejbeer 34
import com.spice.profitmandi.service.user.RetailerService;
25979 tejbeer 35
import com.spice.profitmandi.web.model.LoginDetails;
36
import com.spice.profitmandi.web.util.CookiesProcessor;
37
import com.spice.profitmandi.web.util.MVCResponseSender;
35548 aman 38
import org.apache.commons.csv.CSVFormat;
39
import org.apache.commons.csv.CSVParser;
33843 ranu 40
import org.apache.commons.csv.CSVRecord;
34707 aman.kumar 41
import org.apache.commons.io.output.ByteArrayOutputStream;
33843 ranu 42
import org.apache.logging.log4j.LogManager;
43
import org.apache.logging.log4j.Logger;
44
import org.springframework.beans.factory.annotation.Autowired;
37035 aman 45
import org.springframework.beans.factory.annotation.Value;
33843 ranu 46
import org.springframework.core.io.InputStreamResource;
47
import org.springframework.http.HttpHeaders;
48
import org.springframework.http.HttpStatus;
49
import org.springframework.http.MediaType;
50
import org.springframework.http.ResponseEntity;
51
import org.springframework.stereotype.Controller;
35507 ranu 52
import org.springframework.transaction.annotation.Transactional;
33843 ranu 53
import org.springframework.ui.Model;
54
import org.springframework.util.StringUtils;
55
import org.springframework.web.bind.annotation.*;
56
import org.springframework.web.multipart.MultipartFile;
25979 tejbeer 57
 
33843 ranu 58
import javax.servlet.http.HttpServletRequest;
59
import javax.servlet.http.HttpServletResponse;
60
import java.io.ByteArrayInputStream;
61
import java.io.InputStream;
35548 aman 62
import java.io.InputStreamReader;
63
import java.io.Reader;
35223 ranu 64
import java.text.DecimalFormat;
36101 ranu 65
import java.time.DayOfWeek;
33843 ranu 66
import java.time.LocalDate;
67
import java.time.LocalDateTime;
36101 ranu 68
import java.time.LocalTime;
33843 ranu 69
import java.time.format.DateTimeFormatter;
36101 ranu 70
import java.time.temporal.TemporalAdjusters;
33843 ranu 71
import java.util.*;
72
import java.util.Map.Entry;
73
import java.util.stream.Collectors;
74
 
25979 tejbeer 75
@Controller
35458 amit 76
@Transactional(rollbackFor = Throwable.class)
25979 tejbeer 77
public class LeadController {
32464 tejbeer 78
    private static final Logger LOGGER = LogManager.getLogger(LeadController.class);
25979 tejbeer 79
 
37035 aman 80
    /** Source / createdBy label for leads captured by the AI assistant (chat + voice). */
81
    private static final String AI_LEAD_SOURCE = "AI Assistant";
82
 
37036 aman 83
    // AI leads are auto-assigned round-robin (one by one) between these two auth users (was hardcoded 53 / Shankar Mushran).
84
    private static final int AI_ASSIGN_KHUSHBU = 134;  // Khushbu Saxena (khushbu@smartdukaan.com)
85
    private static final int AI_ASSIGN_ARCHANA = 126;  // Archana Ramola (archana@smartdukaan.com)
86
    private final java.util.concurrent.atomic.AtomicInteger aiAssignToggle = new java.util.concurrent.atomic.AtomicInteger(0);
87
 
37035 aman 88
    @Value("${ai.lead.intake.token:}")
89
    private String aiLeadIntakeToken;
90
 
91
    /**
92
     * AI-assistant lead intake, hosted in the fofo app so it deploys via {@code fofo_deploy}. Mirrors the
93
     * profitmandi-web /add/lead contract: shared-secret {@code Auth-Token}, source stamped server-side,
94
     * idempotent by mobile+source, NOT NULL columns coalesced (so a minimal name+number lead never
95
     * crashes), stores {@code state} + {@code recordingUrl}, status = pending (Open/New). This path is
96
     * excluded from fofo's authentication/role/post interceptors in WebConfig.
97
     */
98
    @RequestMapping(value = ProfitMandiConstants.URL_AI_LEAD_INTAKE, method = RequestMethod.POST)
99
    @ResponseBody
100
    public ResponseEntity<?> aiLead(HttpServletRequest request,
101
                                    @RequestHeader(name = "Auth-Token", required = false) String authToken,
102
                                    @RequestBody AiLeadRequest aiLeadRequest) {
103
        LOGGER.info("AI lead intake request: {}", aiLeadRequest);
104
 
105
        if (aiLeadIntakeToken == null || aiLeadIntakeToken.trim().isEmpty()
106
                || authToken == null || !aiLeadIntakeToken.equals(authToken)) {
107
            LOGGER.warn("AI lead intake rejected: invalid or missing Auth-Token");
108
            return aiLeadResponse(HttpStatus.UNAUTHORIZED, "401", "UNAUTHORIZED", "FAILURE", null);
109
        }
110
 
111
        String rawMobile = aiLeadRequest.getMobile();
112
        String mobile = rawMobile == null ? "" : rawMobile.replaceAll("\\D", "");
113
        if (mobile.length() > 10) {
114
            mobile = mobile.substring(mobile.length() - 10);
115
        }
116
        if (mobile.length() != 10) {
117
            return aiLeadResponse(HttpStatus.BAD_REQUEST, "400", "Mobile number must contain 10 digits", "FAILURE", null);
118
        }
119
 
120
        String firstName = aiLeadRequest.getFirstName();
121
        if (firstName == null || firstName.trim().isEmpty()) {
122
            return aiLeadResponse(HttpStatus.BAD_REQUEST, "400", "First name is required", "FAILURE", null);
123
        }
124
 
125
        // Idempotency scoped to AI leads only (the AI side retries fire-and-forget posts).
126
        Lead existing = leadRepository.selectByMobileNumberAndSource(mobile, AI_LEAD_SOURCE);
127
        if (existing != null) {
128
            LOGGER.info("AI lead intake: AI lead already exists for mobile {} (id={}), skipping create", mobile, existing.getId());
129
            return aiLeadResponse(HttpStatus.OK, "200", "OK", "SUCCESS", existing.getId());
130
        }
131
 
132
        Lead lead = new Lead();
133
        lead.setLeadMobile(mobile);
134
        lead.setFirstName(firstName.trim());
135
        // last_name / city / address / state are NOT NULL in user.lead; coalesce nulls to "" so a minimal lead never crashes.
136
        lead.setLastName(aiLeadRequest.getLastName() == null ? "" : aiLeadRequest.getLastName().trim());
137
        String city = aiLeadRequest.getCity() == null ? "" : aiLeadRequest.getCity().trim();
138
        lead.setCity(city);
139
        lead.setOutLetName(aiLeadRequest.getOutletName());
140
        // AI does not collect a separate address; mirror web capture and fall back to city.
141
        lead.setAddress(city);
142
        String state = aiLeadRequest.getState();
143
        lead.setState(state == null ? "" : state.trim());
144
 
145
        // Source stamped server-side; caller cannot override it.
146
        lead.setSource(AI_LEAD_SOURCE);
147
        lead.setCreatedBy(AI_LEAD_SOURCE);
148
        lead.setStatus(LeadStatus.pending);
149
        lead.setColor("yellow");
150
 
151
        // Optional call-recording URL (voice leads only); store null when absent.
152
        String recordingUrl = aiLeadRequest.getRecordingUrl();
153
        if (recordingUrl != null && !recordingUrl.trim().isEmpty()) {
154
            lead.setRecordingUrl(recordingUrl.trim());
155
        }
156
 
37036 aman 157
        // Round-robin between Khushbu and Archana, one lead at a time (toggle only advances on a real create, not dedup hits).
158
        int assignTo = (aiAssignToggle.getAndIncrement() % 2 == 0) ? AI_ASSIGN_KHUSHBU : AI_ASSIGN_ARCHANA;
159
        lead.setAssignTo(assignTo);
37035 aman 160
        lead.setAuthId(lead.getAssignTo());
161
        lead.setCreatedTimestamp(LocalDateTime.now());
162
        lead.setUpdatedTimestamp(LocalDateTime.now());
163
        leadRepository.persist(lead);
164
 
37036 aman 165
        LOGGER.info("AI lead intake: created lead id={} for mobile {}, assigned to authId={}", lead.getId(), mobile, assignTo);
37035 aman 166
        return aiLeadResponse(HttpStatus.OK, "200", "OK", "SUCCESS", lead.getId());
167
    }
168
 
169
    private ResponseEntity<Map<String, Object>> aiLeadResponse(HttpStatus status, String statusCode,
170
                                                               String statusMessage, String responseStatus, Object response) {
171
        Map<String, Object> body = new HashMap<>();
172
        body.put("statusCode", statusCode);
173
        body.put("statusMessage", statusMessage);
174
        body.put("response", response);
175
        body.put("responseStatus", responseStatus);
176
        return ResponseEntity.status(status).body(body);
177
    }
178
 
32464 tejbeer 179
    @Autowired
180
    private LeadRepository leadRepository;
25979 tejbeer 181
 
32464 tejbeer 182
    @Autowired
183
    private LeadActivityRepository leadActivityRepository;
25979 tejbeer 184
 
32464 tejbeer 185
    @Autowired
36787 ranu 186
    private com.spice.profitmandi.dao.repository.dtr.LeadVisitRequestRepository leadVisitRequestRepository;
187
 
188
    @Autowired
32464 tejbeer 189
    private StateRepository stateRepository;
25979 tejbeer 190
 
32464 tejbeer 191
    @Autowired
192
    private AuthService authService;
29266 manish 193
 
32464 tejbeer 194
    @Autowired
195
    private AuthRepository authRepository;
25979 tejbeer 196
 
32464 tejbeer 197
    @Autowired
198
    private Gson gson;
29266 manish 199
 
32464 tejbeer 200
    @Autowired
201
    private CookiesProcessor cookiesProcessor;
29426 manish 202
 
32464 tejbeer 203
    @Autowired
204
    PositionRepository positionRepository;
25979 tejbeer 205
 
32464 tejbeer 206
    @Autowired
207
    private MVCResponseSender mvcResponseSender;
25979 tejbeer 208
 
32464 tejbeer 209
    @Autowired
210
    private PartnerCollectionPlanRepository partnerCollectionPlanRepository;
30185 tejbeer 211
 
32464 tejbeer 212
    @Autowired
213
    private CsService csService;
30416 tejbeer 214
 
32464 tejbeer 215
    @Autowired
216
    private FofoStoreRepository fofoStoreRepository;
30416 tejbeer 217
 
32464 tejbeer 218
    @Autowired
219
    private PartnerCollectionService partnerCollectionService;
30416 tejbeer 220
 
32464 tejbeer 221
    @Autowired
222
    private RetailerService retailerService;
30416 tejbeer 223
 
32464 tejbeer 224
    @Autowired
225
    private PartnerCollectionRemarkRepository partnerCollectionRemarkRepository;
30434 tejbeer 226
 
32464 tejbeer 227
    @Autowired
228
    private PartnerDailyInvestmentRepository partnerDailyInvestmentRepository;
30445 tejbeer 229
 
32464 tejbeer 230
    @Autowired
231
    private UserWalletRepository userWalletRepository;
30445 tejbeer 232
 
32464 tejbeer 233
    @Autowired
234
    private FranchiseeVisitRepository franchiseeVisitRepository;
30522 tejbeer 235
 
32464 tejbeer 236
    @Autowired
237
    private FranchiseeActivityRepository franchiseeActivityRepository;
30522 tejbeer 238
 
32464 tejbeer 239
    @Autowired
240
    private VisitRequestRepository visitRequestRepository;
31249 tejbeer 241
 
32464 tejbeer 242
    @Autowired
243
    private LeadBrandRepository leadBrandRepository;
31370 tejbeer 244
 
32464 tejbeer 245
    @Autowired
246
    private LeadDetailRepository leadDetailRepository;
31370 tejbeer 247
 
32464 tejbeer 248
    @Autowired
36642 ranu 249
    private LeadLiveLocationRepository leadLiveLocationRepository;
250
 
251
    @Autowired
36644 ranu 252
    private BeatRouteRepository beatRouteRepository;
36642 ranu 253
 
254
    @Autowired
36644 ranu 255
    private LeadRouteRepository leadRouteRepository;
256
 
257
    @Autowired
258
    private BeatRepository beatRepository;
259
 
260
    @Autowired
36818 ranu 261
    private org.springframework.mail.javamail.JavaMailSender gmailRelaySender;
262
 
263
    @Autowired
32464 tejbeer 264
    private Mongo mongoClient;
31370 tejbeer 265
 
32464 tejbeer 266
    @Autowired
267
    private ResponseSender<?> responseSender;
31370 tejbeer 268
 
32464 tejbeer 269
    @Autowired
270
    private BrandsService brandsService;
34650 aman.kumar 271
    @Autowired
272
    OrderService orderService;
25988 tejbeer 273
 
35223 ranu 274
 
275
    @Autowired
276
    private RbmRatingRepository rbmRatingRepository;
277
 
32464 tejbeer 278
    List<LeadStatus> status = Arrays.asList(LeadStatus.notInterested, LeadStatus.finalized);
27609 tejbeer 279
 
37324 aman 280
    /**
281
     * Restricted lead view applies only to field-level sales positions (L1-L3: ASM/CM/DM).
282
     * L4+ sales (BM/RSM/NSM and above, incl. co-founder-level L7) keep the full lead list —
283
     * a senior head can hold a SALES position for approver/head flows without losing
284
     * Lead Management visibility.
285
     */
286
    private boolean isFieldSales(int authUserId) {
287
        return positionRepository.selectPositionByAuthId(authUserId).stream()
288
                .filter(p -> p.getCategoryId() == ProfitMandiConstants.TICKET_CATEGORY_SALES)
289
                .anyMatch(p -> p.getEscalationType() == null
290
                        || !p.getEscalationType().isGreaterThanEqualTo(EscalationType.L4));
291
    }
292
 
32464 tejbeer 293
    @RequestMapping(value = "/getOpenLead", method = RequestMethod.GET)
35769 amit 294
    public String getOpenLead(HttpServletRequest request, @RequestParam(name = "leadStatus", required = false, defaultValue = "All") List<LeadStatus> leadStatus, @RequestParam(name = "color", required = false, defaultValue = "All") List<String> color, @RequestParam(name = "startDate", required = false) LocalDate startDate, @RequestParam(name = "endDate", required = false) LocalDate endDate, Model model) throws Exception {
29445 manish 295
 
29426 manish 296
 
35769 amit 297
        LocalDateTime startDateTime = startDate != null ? startDate.atStartOfDay() : null;
298
        LocalDateTime endDateTime = endDate != null ? endDate.atTime(23, 59, 59) : null;
299
        LOGGER.info("startDateTime: " + startDateTime + ", endDateTime: " + endDateTime);
300
 
32464 tejbeer 301
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
302
        String emailId = loginDetails.getEmailId();
303
        AuthUser authUser = authRepository.selectByEmailOrMobile(emailId);
29426 manish 304
 
37324 aman 305
        boolean isPositionSales = this.isFieldSales(authUser.getId());
27610 tejbeer 306
 
32464 tejbeer 307
        if (leadStatus.contains(LeadStatus.All)) {
27615 tejbeer 308
 
32464 tejbeer 309
            leadStatus.add(LeadStatus.pending);
310
            leadStatus.add(LeadStatus.notInterested);
311
            leadStatus.add(LeadStatus.finalized);
312
        }
29744 tejbeer 313
 
32464 tejbeer 314
        if (color.contains("All")) {
315
            color.add("yellow");
316
            color.add("green");
317
        }
29445 manish 318
 
32464 tejbeer 319
        List<Lead> leads = new ArrayList<>();
29445 manish 320
 
32464 tejbeer 321
        model.addAttribute("colors", color);
29744 tejbeer 322
 
32464 tejbeer 323
        Map<Integer, List<LeadActivity>> leadActivityMap = new HashMap<>();
29445 manish 324
 
32464 tejbeer 325
        List<Integer> authUserIds = null;
29445 manish 326
 
32464 tejbeer 327
        LOGGER.info("color111" + color);
328
        List<Lead> leadFollowUp = new ArrayList<>();
34890 aman 329
        if (isPositionSales) {
32464 tejbeer 330
            authUserIds = authService.getAllReportees(authUser.getId());
331
            authUserIds.add(authUser.getId());
332
            LOGGER.info("authIds" + authUserIds);
29753 tejbeer 333
 
32464 tejbeer 334
            LOGGER.info("leadStatus" + leadStatus);
29445 manish 335
 
35769 amit 336
            if (startDateTime == null) {
29445 manish 337
 
32464 tejbeer 338
                if (!leadStatus.contains(LeadStatus.followUp)) {
29852 tejbeer 339
 
32464 tejbeer 340
                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestampAndAuthIds(leadStatus, authUserIds, color, LocalDateTime.now().minusMonths(1));
341
                }
29852 tejbeer 342
 
32464 tejbeer 343
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
344
                    leadFollowUp = leadRepository.selectByAssignAuthIdsAndStatus(authUserIds, LeadStatus.followUp);
345
                    leads.addAll(leadFollowUp);
346
                }
29445 manish 347
 
32464 tejbeer 348
            } else {
29852 tejbeer 349
 
32464 tejbeer 350
                if (!leadStatus.contains(LeadStatus.followUp)) {
35769 amit 351
                    leads = leadRepository.selectAllByColorStatusAndBetweenCreatedDateAndAuthIds(leadStatus, authUserIds, color, startDateTime, endDateTime);
32464 tejbeer 352
                }
29852 tejbeer 353
 
32464 tejbeer 354
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
30290 tejbeer 355
 
32464 tejbeer 356
                    leadFollowUp = leadRepository.selectByAssignAuthIdsAndStatus(authUserIds, LeadStatus.followUp);
29852 tejbeer 357
 
32464 tejbeer 358
                    leads.addAll(leadFollowUp);
29852 tejbeer 359
 
32464 tejbeer 360
                }
29445 manish 361
 
32464 tejbeer 362
            }
29445 manish 363
 
32464 tejbeer 364
        } else {
29445 manish 365
 
35769 amit 366
            if (startDateTime == null) {
32464 tejbeer 367
                if (!leadStatus.contains(LeadStatus.followUp)) {
29852 tejbeer 368
 
32464 tejbeer 369
                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestamp(leadStatus, color, LocalDateTime.now().minusMonths(1));
370
                }
371
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
30290 tejbeer 372
 
32464 tejbeer 373
                    leadFollowUp = leadRepository.selectAllByStatus(LeadStatus.followUp);
29445 manish 374
 
32464 tejbeer 375
                    leads.addAll(leadFollowUp);
376
                }
377
                LOGGER.info("leadlocalDateTime1" + leads);
29445 manish 378
 
32464 tejbeer 379
            } else {
380
                if (!leadStatus.contains(LeadStatus.followUp)) {
35769 amit 381
                    leads = leadRepository.selectAllByColorStatusAndBetweenCreatedDate(leadStatus, color, startDateTime, endDateTime);
32464 tejbeer 382
                }
29852 tejbeer 383
 
34890 aman 384
                if (leadStatus.contains(LeadStatus.followUp)) {
30290 tejbeer 385
 
32464 tejbeer 386
                    leadFollowUp = leadRepository.selectAllByStatus(LeadStatus.followUp);
29445 manish 387
 
32464 tejbeer 388
                    leads.addAll(leadFollowUp);
389
                }
390
                LOGGER.info("leadlocalDateTime2" + leads);
29426 manish 391
 
32464 tejbeer 392
            }
29445 manish 393
 
32464 tejbeer 394
        }
27642 tejbeer 395
 
34890 aman 396
        if (isPositionSales && authUserIds.size() > 0) {
32464 tejbeer 397
            List<String> leadCreators = new ArrayList<>();
398
            leadCreators.add("daily-sync");
34032 amit.gupta 399
            leadCreators.addAll(csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_SALES, Arrays.asList(EscalationType.L1, EscalationType.L2)).stream().map(x -> x.getFullName()).collect(Collectors.toList()));
400
            leadCreators.addAll(csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_BGC, Arrays.asList(EscalationType.L1, EscalationType.L2, EscalationType.L3)).stream().map(x -> x.getFullName()).collect(Collectors.toList()));
32464 tejbeer 401
            model.addAttribute("leadCreators", leadCreators);
402
        }
403
        List<Lead> weekLast = new ArrayList<>();
404
        List<Lead> weekThird = new ArrayList<>();
405
        List<Lead> weekSecond = new ArrayList<>();
406
        List<Lead> weekFirst = new ArrayList<>();
407
        LocalDateTime curDate = LocalDate.now().atStartOfDay();
408
        List<LeadWeakWiseModel> lwDays = new ArrayList<>();
29266 manish 409
 
32464 tejbeer 410
        for (int i = 7; i >= 1; i--) {
411
            LocalDateTime startOfDay = curDate.minusDays(i);
29266 manish 412
 
32464 tejbeer 413
            LeadWeakWiseModel lm = new LeadWeakWiseModel();
414
            lm.setMonth(startOfDay.toLocalDate());
415
            lwDays.add(lm);
416
        }
417
        if (!leads.isEmpty()) {
29266 manish 418
 
32464 tejbeer 419
            weekLast.addAll(
420
                    leads.stream().filter(x -> x.getCreatedTimestamp().isAfter(curDate.minusDays(28)) && x.getCreatedTimestamp().isBefore(curDate.minusDays(21))).collect(Collectors.toList()));
29266 manish 421
 
32464 tejbeer 422
            weekThird.addAll(leads.stream().filter(x -> x.getCreatedTimestamp().isAfter(curDate.minusDays(21)) && x.getCreatedTimestamp().isBefore(curDate.minusDays(14))).collect(Collectors.toList()));
29426 manish 423
 
32464 tejbeer 424
            weekSecond.addAll(leads.stream().filter(x -> x.getCreatedTimestamp().isAfter(curDate.minusDays(14)) && x.getCreatedTimestamp().isBefore(curDate.minusDays(7))).collect(Collectors.toList()));
29744 tejbeer 425
 
32464 tejbeer 426
            weekFirst.addAll(leads.stream().filter(x -> x.getCreatedTimestamp().isAfter(curDate.minusDays(7))).collect(Collectors.toList()));
29266 manish 427
 
32464 tejbeer 428
        }
429
        LOGGER.info("weekLast" + weekLast);
430
        LOGGER.info("weekThird" + weekThird);
431
        LOGGER.info("weekSecond" + weekSecond);
432
        Map<String, Long> leadLasts = weekLast.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy(), Collectors.counting()));
433
        Map<String, Long> leadThirds = weekThird.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy(), Collectors.counting()));
434
        Map<String, Long> leadSeconds = weekSecond.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy(), Collectors.mapping(Lead::getCreatedBy, Collectors.counting())));
29266 manish 435
 
32464 tejbeer 436
        Map<String, Map<LocalDate, Long>> leadFirsts = weekFirst.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy(), Collectors.groupingBy(x -> x.getCreatedTimestamp().toLocalDate(), Collectors.counting())));
29266 manish 437
 
32464 tejbeer 438
        LOGGER.info("leadFirsts" + leadFirsts);
25979 tejbeer 439
 
32464 tejbeer 440
        List<Integer> authIds = new ArrayList<>();
441
        if (!leads.isEmpty()) {
27610 tejbeer 442
 
32464 tejbeer 443
            authIds.addAll(leads.stream().map(x -> x.getAssignTo()).collect(Collectors.toList()));
29744 tejbeer 444
 
32464 tejbeer 445
            leadActivityMap = leadActivityRepository.selectAllByleadIds(leads.stream().map(x -> x.getId()).collect(Collectors.toList())).stream().collect(Collectors.groupingBy(LeadActivity::getLeadId, Collectors.toList()));
27723 tejbeer 446
 
35395 amit 447
            Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
32464 tejbeer 448
            model.addAttribute("leadActivityMap", leadActivityMap);
449
            model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
36787 ranu 450
 
451
            // Pending visit requests per lead — drives the "Visit request pending"
452
            // badge on the row template. Best-effort: never blocks the list render.
453
            try {
454
                List<Integer> leadIds = leads.stream().map(Lead::getId).collect(Collectors.toList());
455
                List<com.spice.profitmandi.dao.entity.user.LeadVisitRequest> pending =
456
                        leadVisitRequestRepository.selectByLeadIdsAndStatus(leadIds, "PENDING");
457
                Set<Integer> pendingSet = pending.stream()
458
                        .map(com.spice.profitmandi.dao.entity.user.LeadVisitRequest::getLeadId)
459
                        .collect(Collectors.toSet());
460
                model.addAttribute("pendingVisitRequestLeadIds", pendingSet);
461
            } catch (Exception e) {
462
                LOGGER.warn("pending visit-request lookup failed: {}", e.getMessage());
463
                model.addAttribute("pendingVisitRequestLeadIds", new HashSet<Integer>());
464
            }
32464 tejbeer 465
        }
29266 manish 466
 
32464 tejbeer 467
        ChartLeadModel cm = this.getLeadChart(leads);
468
        model.addAttribute("chartLead", gson.toJson(cm));
29266 manish 469
 
32464 tejbeer 470
        LOGGER.info("ChartLeadModel" + gson.toJson(cm));
471
        LOGGER.info("lwDays" + lwDays);
29426 manish 472
 
32464 tejbeer 473
        LOGGER.info("leads" + leads);
474
        List<String> stateNames = stateRepository.selectAll().stream().map(x -> x.getName()).collect(Collectors.toList());
34127 tejus.loha 475
//        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
35098 ranu 476
        List<AuthUser> authUsers = new ArrayList<>();
37287 ranu 477
        List<AuthUser> salesUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_SALES, Arrays.asList(EscalationType.L1, EscalationType.L2, EscalationType.L3, EscalationType.L4));
35098 ranu 478
        List<AuthUser> abmUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_ABM, Arrays.asList(EscalationType.L1, EscalationType.L2, EscalationType.L3));
35252 aman 479
        List<AuthUser> bgcUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_BGC, Arrays.asList(EscalationType.L1, EscalationType.L2, EscalationType.L3));
35098 ranu 480
        authUsers.addAll(salesUsers);
481
        authUsers.addAll(abmUsers);
35252 aman 482
        authUsers.addAll(bgcUsers);
32464 tejbeer 483
        LocalDate lastDate = curDate.minusDays(1).toLocalDate();
29426 manish 484
 
32464 tejbeer 485
        List<LocalDate> weekDates = new ArrayList<>();
29426 manish 486
 
32464 tejbeer 487
        weekDates.add(curDate.minusDays(28).toLocalDate());
488
        weekDates.add(curDate.minusDays(22).toLocalDate());
489
        weekDates.add(curDate.minusDays(21).toLocalDate());
490
        weekDates.add(curDate.minusDays(15).toLocalDate());
491
        weekDates.add(curDate.minusDays(14).toLocalDate());
492
        weekDates.add(curDate.minusDays(8).toLocalDate());
493
        weekDates.add(curDate.minusDays(7).toLocalDate());
494
        LOGGER.info("lastDate" + lastDate);
29426 manish 495
 
32464 tejbeer 496
        model.addAttribute("weekDates", weekDates);
31249 tejbeer 497
 
35769 amit 498
        model.addAttribute("startDate", startDate);
499
        model.addAttribute("endDate", endDate);
32464 tejbeer 500
        model.addAttribute("lastDate", lastDate);
501
        model.addAttribute("stateNames", stateNames);
31249 tejbeer 502
 
32464 tejbeer 503
        model.addAttribute("communicationTypes", CommunicationType.values());
25979 tejbeer 504
 
32464 tejbeer 505
        model.addAttribute("authUsers", authUsers);
33223 amit.gupta 506
        model.addAttribute("leads", leads);
32464 tejbeer 507
        model.addAttribute("leadStatus", LeadStatus.values());
508
        model.addAttribute("leadLasts", leadLasts);
509
        model.addAttribute("leadThirds", leadThirds);
510
        model.addAttribute("leadSeconds", leadSeconds);
511
        model.addAttribute("leadFirsts", leadFirsts);
512
        model.addAttribute("lwDays", lwDays);
31370 tejbeer 513
 
32464 tejbeer 514
        model.addAttribute("selectedLeadStatus", leadStatus.get(0));
31370 tejbeer 515
 
35548 aman 516
        boolean showBulkUploader =
517
                "sm@smartdukaan.com".equalsIgnoreCase(emailId);
31370 tejbeer 518
 
35548 aman 519
        model.addAttribute("showBulkUploader", showBulkUploader);
520
 
32464 tejbeer 521
        List<BrandCatalog> brandsDisplays = brandsService.getBrandsToDisplay(3);
522
        brandsDisplays.addAll(brandsService.getBrandsToDisplay(6));
523
        model.addAttribute("brandsDisplays", brandsDisplays.stream().distinct().collect(Collectors.toList()));
31370 tejbeer 524
 
32464 tejbeer 525
        LOGGER.info("brandsDisplays" + brandsDisplays);
27642 tejbeer 526
 
36642 ranu 527
        // Geo location status map for all leads
528
        if (!leads.isEmpty()) {
529
            List<Integer> allLeadIds = leads.stream().map(Lead::getId).collect(Collectors.toList());
530
            Map<Integer, LeadLiveLocation> geoLocationMap = leadLiveLocationRepository.selectByLeadIds(allLeadIds).stream()
531
                    .collect(Collectors.toMap(LeadLiveLocation::getLeadId, x -> x, (a, b) -> a));
532
            model.addAttribute("geoLocationMap", geoLocationMap);
533
        } else {
534
            model.addAttribute("geoLocationMap", new HashMap<>());
535
        }
536
        model.addAttribute("salesUsers", salesUsers);
537
        model.addAttribute("bgcUsers", bgcUsers);
25979 tejbeer 538
 
32464 tejbeer 539
        return "lead";
29266 manish 540
 
32464 tejbeer 541
    }
29266 manish 542
 
32464 tejbeer 543
    public ChartLeadModel getLeadChart(List<Lead> leads) throws ProfitMandiBusinessException {
29426 manish 544
 
32464 tejbeer 545
        Map<LeadStatus, Long> leadStatusMap = leads.stream().collect(
546
                Collectors.groupingBy(x -> x.getStatus(), Collectors.mapping(Lead::getStatus, Collectors.counting())));
29266 manish 547
 
32464 tejbeer 548
        Map<String, Long> hotLeadsMap = leads.stream().collect(
549
                Collectors.groupingBy(x -> x.getColor(), Collectors.mapping(Lead::getColor, Collectors.counting())));
29445 manish 550
 
32464 tejbeer 551
        LOGGER.info("hotLeadsMap" + hotLeadsMap);
552
        ChartLeadModel cm = new ChartLeadModel();
29445 manish 553
 
32464 tejbeer 554
        HashSet<LeadStatus> labels = new HashSet<LeadStatus>();
555
        labels.addAll(leadStatusMap.keySet());
29445 manish 556
 
32464 tejbeer 557
        List<String> hotLeads = new ArrayList<>();
558
        hotLeads.addAll(leadStatusMap.keySet().stream().map(x -> x.toString()).collect(Collectors.toSet()));
559
        hotLeads.add("HotLead");
29598 tejbeer 560
 
32464 tejbeer 561
        List<String> hotLeadKeys = new ArrayList<>();
29445 manish 562
 
32464 tejbeer 563
        hotLeadKeys.add("HotLead");
564
        List<String> hotLeadGreen = new ArrayList<>(hotLeadKeys);
29266 manish 565
 
32464 tejbeer 566
        LOGGER.info("hotLeads" + hotLeads);
29266 manish 567
 
32464 tejbeer 568
        List<LeadStatus> labelList = new ArrayList<>(labels);
569
        List<String> backgroundColor = new ArrayList<>();
570
        LOGGER.info("hotLeadKeys" + hotLeadKeys);
571
        List<Long> values = new ArrayList<>();
29598 tejbeer 572
 
32464 tejbeer 573
        for (String hotLead : hotLeads) {
29445 manish 574
 
32464 tejbeer 575
            if (hotLead.equals("pending")) {
576
                backgroundColor.add("pink");
577
                values.add(leadStatusMap.get(LeadStatus.pending));
578
            }
579
            if (hotLead.equals("notInterested")) {
580
                backgroundColor.add("red");
581
                values.add(leadStatusMap.get(LeadStatus.notInterested));
582
            }
583
            if (hotLead.equals("followUp")) {
584
                backgroundColor.add("#9ACD32");
585
                values.add(leadStatusMap.get(LeadStatus.followUp));
586
            }
587
            if (hotLead.equals("finalized")) {
588
                backgroundColor.add("blue");
589
                values.add(leadStatusMap.get(LeadStatus.finalized));
590
            }
29445 manish 591
 
32464 tejbeer 592
            if (hotLead.equals("HotLead")) {
593
                backgroundColor.add("green");
594
                values.add(hotLeadsMap.get("Green"));
29266 manish 595
 
32464 tejbeer 596
            }
29266 manish 597
 
32464 tejbeer 598
        }
599
        LOGGER.info("labelList" + labelList);
29266 manish 600
 
32464 tejbeer 601
        LOGGER.info("backgroundColor" + backgroundColor);
602
        LOGGER.info("labelsChartLead" + labels);
603
        LeadStatusData data = new LeadStatusData();
604
        data.setData(values);
605
        data.setBackgroundColor(backgroundColor);
606
        data.setLabel("DataSet 1");
29266 manish 607
 
32464 tejbeer 608
        PieLables label = new PieLables();
609
        label.setFontColor("black");
610
        label.setFontSize(15);
29266 manish 611
 
32464 tejbeer 612
        Legend legend = new Legend();
613
        legend.setLabels(label);
614
        legend.setPosition("left");
29266 manish 615
 
32464 tejbeer 616
        List<LeadStatusData> dataList = new ArrayList<>();
617
        dataList.add(data);
29266 manish 618
 
32464 tejbeer 619
        DataLeadModel datasets = new DataLeadModel();
620
        datasets.setDatasets(dataList);
621
        datasets.setLabels(hotLeads);
29266 manish 622
 
32464 tejbeer 623
        OptionModel om = new OptionModel();
624
        om.setLegend(legend);
29266 manish 625
 
32464 tejbeer 626
        cm.setType("pie");
627
        cm.setData(datasets);
628
        cm.setOptions(om);
25988 tejbeer 629
 
32464 tejbeer 630
        return cm;
631
    }
25988 tejbeer 632
 
34650 aman.kumar 633
    @RequestMapping(value = "/downloadDateWiseLead", method = RequestMethod.GET)
34707 aman.kumar 634
    public ResponseEntity<?> getdownloadLeadDataByDate(HttpServletRequest request,
635
                                                       @RequestParam(name = "leadStatus", required = false, defaultValue = "All") List<LeadStatus> leadStatus,
636
                                                       @RequestParam(name = "color", required = false, defaultValue = "All") List<String> color,
35769 amit 637
                                                       @RequestParam(name = "startDate", required = false) LocalDate startDate,
638
                                                       @RequestParam(name = "endDate", required = false) LocalDate endDate) throws Exception {
25988 tejbeer 639
 
34650 aman.kumar 640
        LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
641
        String emailId = fofoDetails.getEmailId();
35769 amit 642
        LocalDateTime startDateTime = startDate != null ? startDate.atStartOfDay() : null;
643
        LocalDateTime endDateTime = endDate != null ? endDate.atTime(23, 59, 59) : null;
34650 aman.kumar 644
        List<Lead> leads = new ArrayList<>();
645
        AuthUser authUser = authRepository.selectByEmailOrMobile(emailId);
646
 
34707 aman.kumar 647
        if (leadStatus.contains(LeadStatus.All)) {
648
            leadStatus.add(LeadStatus.pending);
649
            leadStatus.add(LeadStatus.notInterested);
650
            leadStatus.add(LeadStatus.finalized);
36984 aman 651
            // NOTE: do NOT add followUp here. Follow-ups are pulled separately (undated) below,
652
            // mirroring the on-screen view. Adding it here made the date query get skipped so the
653
            // download collapsed to follow-ups only (original bug).
34707 aman.kumar 654
        }
655
        if (color.contains("All")) {
656
            color.add("yellow");
657
            color.add("green");
658
        }
34650 aman.kumar 659
 
660
        Map<Integer, List<LeadActivity>> leadActivityMap = new HashMap<>();
37324 aman 661
        boolean authPositon = this.isFieldSales(authUser.getId());
34650 aman.kumar 662
        List<Integer> authUserIds = null;
663
        List<Lead> leadFollowUp = new ArrayList<>();
664
 
665
        if (authPositon) {
666
            authUserIds = authService.getAllReportees(authUser.getId());
667
            authUserIds.add(authUser.getId());
35769 amit 668
            if (startDateTime == null) {
34650 aman.kumar 669
                if (!leadStatus.contains(LeadStatus.followUp)) {
670
                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestampAndAuthIds(leadStatus, authUserIds, color, LocalDateTime.now().minusMonths(1));
671
                }
672
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
673
                    leadFollowUp = leadRepository.selectByAssignAuthIdsAndStatus(authUserIds, LeadStatus.followUp);
674
                    leads.addAll(leadFollowUp);
675
                }
676
            } else {
36984 aman 677
                // Date range: non-follow-up statuses created within [start, end], PLUS all follow-ups
678
                // (undated) — mirrors the on-screen view so the CSV matches what the user sees.
679
                if (!leadStatus.contains(LeadStatus.followUp)) {
680
                    leads = leadRepository.selectAllByColorStatusAndBetweenCreatedDateAndAuthIds(leadStatus, authUserIds, color, startDateTime, endDateTime);
681
                }
682
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
683
                    leadFollowUp = leadRepository.selectByAssignAuthIdsAndStatus(authUserIds, LeadStatus.followUp);
684
                    leads.addAll(leadFollowUp);
685
                }
34650 aman.kumar 686
            }
687
        } else {
35769 amit 688
            if (startDateTime == null) {
34650 aman.kumar 689
                if (!leadStatus.contains(LeadStatus.followUp)) {
690
                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestamp(leadStatus, color, LocalDateTime.now().minusMonths(1));
691
                }
692
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
693
                    leadFollowUp = leadRepository.selectAllByStatus(LeadStatus.followUp);
694
                    leads.addAll(leadFollowUp);
695
                }
696
            } else {
36984 aman 697
                // Date range: non-follow-up statuses created within [start, end], PLUS all follow-ups
698
                // (undated) — mirrors the on-screen view.
699
                if (!leadStatus.contains(LeadStatus.followUp)) {
700
                    leads = leadRepository.selectAllByColorStatusAndBetweenCreatedDate(leadStatus, color, startDateTime, endDateTime);
701
                }
702
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
703
                    leadFollowUp = leadRepository.selectAllByStatus(LeadStatus.followUp);
704
                    leads.addAll(leadFollowUp);
705
                }
34650 aman.kumar 706
            }
34707 aman.kumar 707
        }
34650 aman.kumar 708
 
34707 aman.kumar 709
        // Build activity map and auth map (SAME AS VIEW ENDPOINT)
36984 aman 710
        // Guard both lookups on a non-empty result: an empty list would generate an invalid
711
        // "IN ()" and 500 (e.g. a date range with no leads), so an empty range yields an empty CSV.
712
        Map<Integer, AuthUser> authIdAndAuthUserMap = new HashMap<>();
34650 aman.kumar 713
        if (!leads.isEmpty()) {
34707 aman.kumar 714
            List<Integer> leadIds = leads.stream().map(Lead::getId).collect(Collectors.toList());
715
            leadActivityMap = leadActivityRepository.selectAllByleadIds(leadIds).stream()
716
                    .collect(Collectors.groupingBy(LeadActivity::getLeadId));
36984 aman 717
            List<Integer> authIds = leads.stream().map(Lead::getAssignTo).collect(Collectors.toList());
718
            authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream()
719
                    .collect(Collectors.toMap(AuthUser::getId, x -> x));
34650 aman.kumar 720
        }
34707 aman.kumar 721
 
722
        // Build CSV rows (USE DIRECT LEAD PROPERTIES - NO ACTIVITY FALLBACK)
34650 aman.kumar 723
        List<List<?>> rows = new ArrayList<>();
724
        for (Lead lead : leads) {
725
            List<LeadActivity> activities = leadActivityMap.get(lead.getId());
34707 aman.kumar 726
 
727
            // Use FIRST activity's schedule timestamp if exists
34650 aman.kumar 728
            String scheduleTimestamp = (activities != null && !activities.isEmpty())
729
                    ? FormattingUtils.format(activities.get(0).getSchelduleTimestamp())
34707 aman.kumar 730
                    : "";
34650 aman.kumar 731
 
34707 aman.kumar 732
            // DIRECTLY use Lead properties (NO fallback to activity)
733
            Double potential = lead.getPotential();
734
            String outLetName = lead.getOutLetName() != null ? lead.getOutLetName() : "";
34650 aman.kumar 735
 
34707 aman.kumar 736
            // Assignee name (blank if missing)
737
            String assignTo = "";
738
            if (authIdAndAuthUserMap.containsKey(lead.getAssignTo())) {
739
                AuthUser user = authIdAndAuthUserMap.get(lead.getAssignTo());
740
                assignTo = (user.getFirstName() + " " + user.getLastName()).trim();
741
            }
34650 aman.kumar 742
 
34707 aman.kumar 743
            rows.add(Arrays.asList(
35579 aman 744
                    lead.getId(),
34707 aman.kumar 745
                    lead.getSource(),
746
                    lead.getFullName(),
747
                    outLetName,
748
                    potential,
749
                    lead.getLeadMobile(),
750
                    lead.getAddress() != null ? lead.getAddress() : "",
751
                    lead.getCity() != null ? lead.getCity() : "",
752
                    lead.getState() != null ? lead.getState() : "",
753
                    lead.getCreatedBy() != null ? lead.getCreatedBy() : "",
754
                    lead.getStatus().toString(),
755
                    FormattingUtils.format(lead.getCreatedTimestamp()),
756
                    FormattingUtils.format(lead.getUpdatedTimestamp()),
757
                    scheduleTimestamp,
758
                    lead.getClosureTimestamp() != null
759
                            ? FormattingUtils.format(lead.getClosureTimestamp())
760
                            : "",  // Handle null closure
761
                    assignTo,
762
                    lead.getColor() != null ? lead.getColor() : ""
763
            ));
764
        }
34650 aman.kumar 765
 
34707 aman.kumar 766
        // Generate CSV response
767
        ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
35579 aman 768
                Arrays.asList("Id", "Source", "Partner Name", "Outlet Name", "Potential", "Mobile", "Address", "City", "State",
34707 aman.kumar 769
                        "Created By", "Status", "Created On", "Updated On", "Scheduled Timestamp",
770
                        "Closure Timestamp", "Assign To", "Color"),
771
                rows
772
        );
773
        return orderService.downloadReportInCsv(baos, rows, "LeadDetails_");
34650 aman.kumar 774
    }
775
 
32464 tejbeer 776
    @RequestMapping(value = "/getClosedLead", method = RequestMethod.GET)
777
    public String getClosedLead(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, @RequestParam(name = "searchTerm", required = false, defaultValue = "") String searchTerm, Model model) throws Exception {
778
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
779
        List<Lead> leads = null;
780
        long size = 0;
781
        leads = leadRepository.selectAllByStatus(status, offset, limit);
782
        size = leadRepository.selectCountByStatus(status);
25988 tejbeer 783
 
32464 tejbeer 784
        if (!leads.isEmpty()) {
785
            List<Integer> authIds = new ArrayList<>();
786
            for (Lead lead : leads) {
787
                authIds.add(lead.getAssignTo());
788
            }
35395 amit 789
            Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
25988 tejbeer 790
 
32464 tejbeer 791
            model.addAttribute("leads", leads);
792
            model.addAttribute("start", offset + 1);
793
            model.addAttribute("size", size);
794
            model.addAttribute("searchTerm", searchTerm);
795
            model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
796
            model.addAttribute("url", "/getPaginatedClosedLeads");
25988 tejbeer 797
 
32464 tejbeer 798
            if (leads.size() < limit) {
799
                model.addAttribute("end", offset + leads.size());
800
            } else {
801
                model.addAttribute("end", offset + limit);
802
            }
25988 tejbeer 803
 
32464 tejbeer 804
        } else {
805
            model.addAttribute("lead", leads);
25988 tejbeer 806
 
32464 tejbeer 807
            model.addAttribute("size", size);
808
        }
25988 tejbeer 809
 
32464 tejbeer 810
        model.addAttribute("authUsers", authUsers);
811
        return "lead-close";
812
    }
25988 tejbeer 813
 
32464 tejbeer 814
    @RequestMapping(value = "/getPaginatedClosedLeads", method = RequestMethod.GET)
815
    public String getPaginatedClosedLeads(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, Model model) throws ProfitMandiBusinessException {
816
        List<Lead> leads = null;
817
        leads = leadRepository.selectAllByStatus(status, offset, limit);
25988 tejbeer 818
 
32464 tejbeer 819
        if (!leads.isEmpty()) {
820
            List<Integer> authIds = new ArrayList<>();
821
            for (Lead lead : leads) {
822
                authIds.add(lead.getAssignTo());
823
            }
35395 amit 824
            Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
32464 tejbeer 825
            model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
826
            model.addAttribute("leads", leads);
827
            model.addAttribute("url", "/getPaginatedClosedLeads");
25988 tejbeer 828
 
37047 ranu 829
            List<Integer> allLeadIds = leads.stream().map(Lead::getId).collect(Collectors.toList());
830
            Map<Integer, LeadLiveLocation> geoLocationMap = leadLiveLocationRepository.selectByLeadIds(allLeadIds).stream()
831
                    .collect(Collectors.toMap(LeadLiveLocation::getLeadId, x -> x, (a, b) -> a));
832
            model.addAttribute("geoLocationMap", geoLocationMap);
32464 tejbeer 833
        } else {
834
            model.addAttribute("leads", leads);
37047 ranu 835
            model.addAttribute("geoLocationMap", new HashMap<>());
32464 tejbeer 836
        }
837
        return "lead-close-paginated";
838
    }
25988 tejbeer 839
 
32464 tejbeer 840
    @RequestMapping(value = "/searchLeads")
841
    public String getClosedLeads(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, @RequestParam(name = "searchTerm", required = false, defaultValue = "") String searchTerm, Model model) throws ProfitMandiBusinessException {
842
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
843
        List<Lead> leads = null;
844
        long size = 0;
845
        if (!(searchTerm.equals(""))) {
846
            leads = leadRepository.selectBySearchTerm(status, searchTerm, offset, limit);
34155 tejus.loha 847
            size = leadRepository.selectCountByStatus(status);
848
            Map<Integer, AuthUser> authIdAndAuthUserMap = new HashMap<>();
849
            List<Integer> authIds = new ArrayList<>();
32464 tejbeer 850
            if (!(leads.size() == 0)) {
851
                for (Lead lead : leads) {
852
                    authIds.add(lead.getAssignTo());
853
                }
35395 amit 854
                authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
32464 tejbeer 855
                if (leads.size() < limit) {
856
                    model.addAttribute("end", offset + leads.size());
857
                } else {
858
                    model.addAttribute("end", offset + limit);
859
                }
860
            } else {
34155 tejus.loha 861
                model.addAttribute("end", offset + limit);
32464 tejbeer 862
            }
34155 tejus.loha 863
            model.addAttribute("leads", leads);
864
            model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
865
            model.addAttribute("start", offset + 1);
866
            model.addAttribute("size", size);
867
            model.addAttribute("searchTerm", searchTerm);
32464 tejbeer 868
        } else {
869
            leads = leadRepository.selectAllByStatus(status, offset, limit);
870
            size = leadRepository.selectCountByStatus(status);
25988 tejbeer 871
 
32464 tejbeer 872
            if (!leads.isEmpty()) {
873
                List<Integer> authIds = new ArrayList<>();
874
                for (Lead lead : leads) {
875
                    authIds.add(lead.getAssignTo());
876
                }
35395 amit 877
                Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
25988 tejbeer 878
 
32464 tejbeer 879
                model.addAttribute("leads", leads);
880
                model.addAttribute("start", offset + 1);
881
                model.addAttribute("size", size);
882
                model.addAttribute("searchTerm", searchTerm);
883
                model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
25988 tejbeer 884
 
32464 tejbeer 885
                if (leads.size() < limit) {
886
                    model.addAttribute("end", offset + leads.size());
887
                } else {
888
                    model.addAttribute("end", offset + limit);
889
                }
25988 tejbeer 890
 
32464 tejbeer 891
            }
892
        }
25988 tejbeer 893
 
32464 tejbeer 894
        model.addAttribute("authUsers", authUsers);
895
        return "lead-close";
896
    }
25988 tejbeer 897
 
32464 tejbeer 898
    @RequestMapping(value = "/searchLeadPaginated")
899
    public String searchLeadPaginated(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, @RequestParam(name = "searchTerm", required = false, defaultValue = "") String searchTerm, Model model) throws ProfitMandiBusinessException {
900
        LOGGER.info("In search Item....");
901
        List<Lead> leads = null;
902
        if (!searchTerm.equals("")) {
903
            leads = leadRepository.selectBySearchTerm(status, searchTerm, offset, limit);
904
            if (!(leads.size() == 0)) {
25988 tejbeer 905
 
32464 tejbeer 906
                List<Integer> authIds = new ArrayList<>();
907
                for (Lead lead : leads) {
908
                    authIds.add(lead.getAssignTo());
909
                }
35395 amit 910
                Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
32464 tejbeer 911
                model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
912
                model.addAttribute("leads", leads);
37047 ranu 913
 
914
                List<Integer> allLeadIds = leads.stream().map(Lead::getId).collect(Collectors.toList());
915
                Map<Integer, LeadLiveLocation> geoLocationMap = leadLiveLocationRepository.selectByLeadIds(allLeadIds).stream()
916
                        .collect(Collectors.toMap(LeadLiveLocation::getLeadId, x -> x, (a, b) -> a));
917
                model.addAttribute("geoLocationMap", geoLocationMap);
32464 tejbeer 918
            }
919
        }
37047 ranu 920
        if (!model.containsAttribute("geoLocationMap")) {
921
            model.addAttribute("geoLocationMap", new HashMap<>());
922
        }
31249 tejbeer 923
 
32464 tejbeer 924
        return "lead-close-paginated";
31249 tejbeer 925
 
32464 tejbeer 926
    }
31249 tejbeer 927
 
36984 aman 928
    // Global lead search box: find ANY lead by name / mobile / outlet / city, no date filter needed.
929
    @RequestMapping(value = "/globalLeadSearch")
930
    public String globalLeadSearch(HttpServletRequest request,
931
                                   @RequestParam(name = "searchTerm", required = false, defaultValue = "") String searchTerm,
932
                                   Model model) {
933
        List<Lead> leads = new ArrayList<>();
934
        if (!searchTerm.trim().isEmpty()) {
935
            leads = leadRepository.selectByGlobalSearch(searchTerm.trim(), 200);
936
            if (!leads.isEmpty()) {
37048 ranu 937
                List<Integer> allLeadIds = leads.stream().map(Lead::getId).collect(Collectors.toList());
36984 aman 938
                List<Integer> authIds = leads.stream().map(Lead::getAssignTo).collect(Collectors.toList());
939
                Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream()
940
                        .collect(Collectors.toMap(AuthUser::getId, x -> x));
941
                model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
37047 ranu 942
 
943
                Map<Integer, LeadLiveLocation> geoLocationMap = leadLiveLocationRepository.selectByLeadIds(allLeadIds).stream()
944
                        .collect(Collectors.toMap(LeadLiveLocation::getLeadId, x -> x, (a, b) -> a));
945
                model.addAttribute("geoLocationMap", geoLocationMap);
37048 ranu 946
 
947
                Map<Integer, List<LeadActivity>> leadActivityMap = leadActivityRepository.selectAllByleadIds(allLeadIds).stream()
948
                        .collect(Collectors.groupingBy(LeadActivity::getLeadId, Collectors.toList()));
949
                model.addAttribute("leadActivityMap", leadActivityMap);
950
 
951
                try {
952
                    Set<Integer> pendingSet = leadVisitRequestRepository.selectByLeadIdsAndStatus(allLeadIds, "PENDING").stream()
953
                            .map(com.spice.profitmandi.dao.entity.user.LeadVisitRequest::getLeadId)
954
                            .collect(Collectors.toSet());
955
                    model.addAttribute("pendingVisitRequestLeadIds", pendingSet);
956
                } catch (Exception e) {
957
                    model.addAttribute("pendingVisitRequestLeadIds", new HashSet<Integer>());
958
                }
36984 aman 959
            }
960
        }
37047 ranu 961
        if (!model.containsAttribute("geoLocationMap")) {
962
            model.addAttribute("geoLocationMap", new HashMap<>());
963
        }
37048 ranu 964
        if (!model.containsAttribute("leadActivityMap")) {
965
            model.addAttribute("leadActivityMap", new HashMap<>());
966
        }
967
        if (!model.containsAttribute("pendingVisitRequestLeadIds")) {
968
            model.addAttribute("pendingVisitRequestLeadIds", new HashSet<Integer>());
969
        }
36984 aman 970
        model.addAttribute("leads", leads);
971
        model.addAttribute("searchTerm", searchTerm);
37048 ranu 972
        return "lead-global-search";
36984 aman 973
    }
974
 
32464 tejbeer 975
    @RequestMapping(value = "/getLeadActivity", method = RequestMethod.GET)
976
    public String getLeadActivity(HttpServletRequest request, @RequestParam int leadId, Model model) throws Exception {
977
        List<LeadActivity> leadActivity = leadActivityRepository.selectBYLeadId(leadId);
25979 tejbeer 978
 
32464 tejbeer 979
        LOGGER.info("leadActivity" + leadActivity);
31370 tejbeer 980
 
32464 tejbeer 981
        model.addAttribute("leadActivity", leadActivity);
982
        model.addAttribute("authUserMap", authRepository.selectAllActiveUser().stream().collect(Collectors.toMap(x -> x.getId(), x -> x)));
31370 tejbeer 983
 
32464 tejbeer 984
        return "lead_activity_modal";
985
    }
31370 tejbeer 986
 
32464 tejbeer 987
    @RequestMapping(value = "/getLead", method = RequestMethod.GET)
988
    public ResponseEntity<?> getLead(HttpServletRequest request, @RequestParam int leadId) throws Exception {
989
        Lead lead = leadRepository.selectById(leadId);
31370 tejbeer 990
 
32464 tejbeer 991
        LeadDetail leadDetail = leadDetailRepository.selectByLeadId(lead.getId());
992
        if (leadDetail != null) {
993
            lead.setOutLetName(leadDetail.getOutletName());
994
        }
31249 tejbeer 995
 
32464 tejbeer 996
        return responseSender.ok(lead);
25979 tejbeer 997
 
32464 tejbeer 998
    }
31249 tejbeer 999
 
32464 tejbeer 1000
    @RequestMapping(value = "/createLead", method = RequestMethod.POST)
1001
    public String CreateLead(HttpServletRequest request, @RequestBody CreateRefferalRequest createRefferalRequest, Model model) throws Exception {
1002
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
35083 vikas 1003
        Lead leadDetails = leadRepository.selectByMobileNumber(createRefferalRequest.getMobile());
1004
        LOGGER.info("Lead Details {}", leadDetails);
31249 tejbeer 1005
 
35083 vikas 1006
        if (leadDetails != null && leadDetails.getStatus() != LeadStatus.notInterested) {
1007
            AuthUser authUser1 = authRepository.selectById(leadDetails.getAssignTo());
1008
            model.addAttribute("response1", "Lead already exists, created by " + leadDetails.getCreatedBy() +
1009
                    " on " + FormattingUtils.format(leadDetails.getCreatedTimestamp()) +
34671 aman.kumar 1010
                    ", assigned to " + authUser1.getFullName());
1011
            return "response";
34627 aman.kumar 1012
 
34671 aman.kumar 1013
 
34627 aman.kumar 1014
        }
1015
 
32464 tejbeer 1016
        LOGGER.info("createRefferalRequest" + createRefferalRequest.getSchelduleTimestamp());
1017
        Lead lead = new Lead();
1018
        lead.setFirstName(createRefferalRequest.getFirstName());
1019
        lead.setLastName(createRefferalRequest.getLastName());
1020
        lead.setLeadMobile(createRefferalRequest.getMobile());
1021
        lead.setState(createRefferalRequest.getState());
1022
        lead.setCity(createRefferalRequest.getCity());
1023
        lead.setAddress(createRefferalRequest.getAddress());
1024
        lead.setCreatedTimestamp(LocalDateTime.now());
1025
        lead.setUpdatedTimestamp(LocalDateTime.now());
1026
        lead.setStatus(createRefferalRequest.getStatus());
1027
        lead.setAssignTo(createRefferalRequest.getAssignTo());
1028
        lead.setSource(createRefferalRequest.getSource());
36741 ranu 1029
        if (Boolean.TRUE.equals(createRefferalRequest.getColorCheck())) {
32471 tejbeer 1030
            lead.setColor("Green");
1031
        } else {
1032
            lead.setColor("Yellow");
1033
        }
32464 tejbeer 1034
        // change
1035
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1036
        String authUserName = authUser.getFirstName() + " " + authUser.getLastName();
1037
        lead.setCreatedBy(authUserName);
1038
        lead.setAuthId(authUser.getId());
1039
        LOGGER.info("lead --- {}", lead);
1040
        leadRepository.persist(lead);
1041
        LeadActivity leadActivity = new LeadActivity();
1042
        leadActivity.setLeadId(lead.getId());
1043
        leadActivity.setRemark(createRefferalRequest.getRemark());
1044
        leadActivity.setAuthId(authUser.getId());
32471 tejbeer 1045
 
32464 tejbeer 1046
        LOGGER.info("createRefferalRequest" + createRefferalRequest.getCommunicationType());
25979 tejbeer 1047
 
32464 tejbeer 1048
        if (createRefferalRequest.getStatus() == LeadStatus.followUp) {
1049
            leadActivity.setSchelduleTimestamp(createRefferalRequest.getSchelduleTimestamp());
1050
            leadActivity.setCommunicationType(createRefferalRequest.getCommunicationType());
25979 tejbeer 1051
 
32464 tejbeer 1052
            if (leadActivity.getCommunicationType().equals(CommunicationType.VISIT)) {
1053
                visitRequestRepository.createVisitRequest(lead.getId(), "lead", lead.getAssignTo(), createRefferalRequest.getSchelduleTimestamp());
1054
            }
1055
        } else {
1056
            leadActivity.setSchelduleTimestamp(null);
1057
        }
1058
        leadActivity.setCreatedTimestamp(LocalDateTime.now());
1059
        leadActivityRepository.persist(leadActivity);
34127 tejus.loha 1060
        if (!lead.getStatus().equals(LeadStatus.notInterested)) {
1061
            LeadDetailModel leadDetail = new LeadDetailModel();
1062
            leadDetail.setLeadId(lead.getId());
1063
            leadDetail.setOutletName(createRefferalRequest.getOutletName());
1064
            leadDetail.setCounterSize(createRefferalRequest.getCounterSize());
25979 tejbeer 1065
 
31249 tejbeer 1066
 
34127 tejus.loha 1067
            leadDetail.setFrontp(createRefferalRequest.getFrontp());
1068
            leadDetail.setFrontWithMarket(createRefferalRequest.getFrontWithMarket());
31370 tejbeer 1069
 
1070
 
34127 tejus.loha 1071
            leadDetail.setInternalLongShot(createRefferalRequest.getInternalLongShot());
31370 tejbeer 1072
 
34127 tejus.loha 1073
            leadDetail.setInternalLeftWall(createRefferalRequest.getInternalLeftWall());
29598 tejbeer 1074
 
34127 tejus.loha 1075
            leadDetail.setInternalRightWall(createRefferalRequest.getInternalRightWall());
1076
            List<LeadBrandModel> brandModels = new ArrayList<LeadBrandModel>();
27605 tejbeer 1077
 
34127 tejus.loha 1078
            for (LeadBrandModel leadBrandModel : createRefferalRequest.getLeadBrands()) {
25979 tejbeer 1079
 
34127 tejus.loha 1080
                LeadBrandModel leadBrand = new LeadBrandModel();
1081
                leadBrand.setBrand(leadBrandModel.getBrand());
1082
                leadBrand.setValue(leadBrandModel.getValue());
29598 tejbeer 1083
 
34127 tejus.loha 1084
                brandModels.add(leadBrand);
25979 tejbeer 1085
 
34127 tejus.loha 1086
            }
29598 tejbeer 1087
 
34127 tejus.loha 1088
            leadDetail.setLeadBrands(brandModels);
29598 tejbeer 1089
 
32471 tejbeer 1090
            leadRepository.persistLeadDetail(leadDetail, authUser);
1091
        }
32464 tejbeer 1092
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
29598 tejbeer 1093
 
32464 tejbeer 1094
        return "response";
29598 tejbeer 1095
 
32464 tejbeer 1096
    }
29476 manish 1097
 
29473 manish 1098
 
32464 tejbeer 1099
    @RequestMapping(value = "/editLead", method = RequestMethod.POST)
1100
    public String EditLead(HttpServletRequest request, @RequestBody CreateLeacdActivityRequest createLeadActivityRequest, Model model) throws Exception {
1101
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
29426 manish 1102
 
32464 tejbeer 1103
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
29426 manish 1104
 
34113 tejus.loha 1105
        Lead lead = leadRepository.selectById(createLeadActivityRequest.getId());
1106
        AuthUser leadAuthUser = authRepository.selectById(lead.getAuthId());
32464 tejbeer 1107
        LeadDetail leadDetail = leadDetailRepository.selectByLeadId(createLeadActivityRequest.getId());
29426 manish 1108
 
36789 ranu 1109
        // Geo gate: required for follow-up / finalized (anything that schedules
1110
        // a visit or beat slot). For notInterested (close-out) no geo / no beat
1111
        // is needed — only the activity (status + reason + remark) is saved.
36792 ranu 1112
        // Non-sales assignees (BGC / other internal hand-offs) also bypass the
1113
        // gate — those are just routing the lead to another department's queue
1114
        // and don't carry a beat-day attachment.
1115
        int assignToId = createLeadActivityRequest.getAssignTo();
1116
        boolean assigneeIsSales = assignToId > 0
1117
                && positionRepository.hasCategory(assignToId, ProfitMandiConstants.TICKET_CATEGORY_SALES);
1118
        if (createLeadActivityRequest.getStatus() != LeadStatus.notInterested && assigneeIsSales) {
36789 ranu 1119
            LeadLiveLocation approvedGeo = leadLiveLocationRepository.selectApprovedByLeadId(createLeadActivityRequest.getId());
1120
            if (approvedGeo == null) {
1121
                throw new ProfitMandiBusinessException("Lead", "", "Live geo-location for this lead has not been approved yet. Please approve the geo-location before editing.");
1122
            }
36761 ranu 1123
        }
1124
 
34113 tejus.loha 1125
        if (leadDetail == null && !createLeadActivityRequest.getStatus().equals(LeadStatus.notInterested) && leadAuthUser.isActive()) {
29426 manish 1126
 
32464 tejbeer 1127
            throw new ProfitMandiBusinessException("LeadDetail", "", "Please fill lead detail");
1128
        }
29445 manish 1129
 
32464 tejbeer 1130
        LeadActivity leadActivity = new LeadActivity();
1131
        leadActivity.setLeadId(createLeadActivityRequest.getId());
1132
        leadActivity.setRemark(createLeadActivityRequest.getRemark());
29598 tejbeer 1133
 
32464 tejbeer 1134
        LOGGER.info("createRefferalRequest" + createLeadActivityRequest);
29598 tejbeer 1135
 
32464 tejbeer 1136
        if (createLeadActivityRequest.getStatus() == LeadStatus.followUp) {
1137
            leadActivity.setSchelduleTimestamp(createLeadActivityRequest.getScheldule());
1138
            leadActivity.setCommunicationType(createLeadActivityRequest.getCommunicationType());
36741 ranu 1139
            // A beat-day pick wires the lead onto that beat's route regardless of
1140
            // communication type (TELEPHONIC = call on that beat day).
1141
            String beatSelection = createLeadActivityRequest.getBeatSelection();
1142
            if (beatSelection != null && beatSelection.contains("|")) {
36644 ranu 1143
                int beatId = 0;
1144
                LocalDate beatDate = createLeadActivityRequest.getScheldule() != null
1145
                        ? createLeadActivityRequest.getScheldule().toLocalDate() : LocalDate.now();
1146
                String beatName = "Beat";
36642 ranu 1147
 
36741 ranu 1148
                String[] parts = beatSelection.split("\\|", 3);
1149
                beatDate = LocalDate.parse(parts[0]);
1150
                beatName = parts.length > 1 ? parts[1] : "Beat";
1151
                if (parts.length > 2) {
1152
                    try {
1153
                        beatId = Integer.parseInt(parts[2]);
1154
                    } catch (NumberFormatException ignored) {
36642 ranu 1155
                    }
1156
                }
1157
 
36644 ranu 1158
                // Find optimal insert position using lead geolocation
1159
                int insertAt = 0;
1160
                LeadLiveLocation leadGeo = leadLiveLocationRepository.selectApprovedByLeadId(createLeadActivityRequest.getId());
1161
                List<BeatRoute> existingStops = beatId > 0
1162
                        ? beatRouteRepository.selectByBeatId(beatId).stream()
1163
                        .sorted(Comparator.comparingInt(BeatRoute::getSequenceOrder))
1164
                        .collect(Collectors.toList())
1165
                        : new ArrayList<>();
36642 ranu 1166
 
36644 ranu 1167
                insertAt = existingStops.size(); // default: append at end
1168
 
1169
                if (!existingStops.isEmpty() && leadGeo != null) {
1170
                    // Use nearest neighbor to find optimal position
1171
                    // (simplified — append at end for now, full geocoding done in LeadGeoLocationController)
1172
                    insertAt = existingStops.size();
1173
                }
1174
 
1175
                // Shift existing stops
1176
                for (BeatRoute stop : existingStops) {
1177
                    if (stop.getSequenceOrder() >= insertAt) {
1178
                        stop.setSequenceOrder(stop.getSequenceOrder() + 1);
1179
                    }
1180
                }
1181
 
1182
                // Create lead_route entry (directly APPROVED)
1183
                LeadRoute leadRoute = new LeadRoute();
1184
                leadRoute.setBeatId(beatId);
1185
                leadRoute.setLeadId(createLeadActivityRequest.getId());
1186
                leadRoute.setScheduleDate(beatDate);
1187
                leadRoute.setSequenceOrder(insertAt);
1188
                leadRoute.setStatus("APPROVED");
1189
                leadRoute.setRequestedBy(authUser.getId());
1190
                leadRoute.setApprovedBy(authUser.getId());
1191
                leadRoute.setApprovedTimestamp(LocalDateTime.now());
1192
                leadRoute.setCreatedTimestamp(LocalDateTime.now());
1193
                leadRoute.setUpdatedTimestamp(LocalDateTime.now());
1194
 
1195
                // Set nearest store
1196
                if (!existingStops.isEmpty()) {
1197
                    leadRoute.setNearestStoreId(existingStops.get(Math.min(insertAt, existingStops.size() - 1)).getFofoId());
1198
                }
1199
                leadRouteRepository.persist(leadRoute);
1200
 
1201
                // Create visit request
1202
                visitRequestRepository.createVisitRequest(
1203
                        createLeadActivityRequest.getId(), "lead",
1204
                        createLeadActivityRequest.getAssignTo(),
1205
                        beatDate.atTime(10, 0));
1206
 
36642 ranu 1207
                // Log activity
36644 ranu 1208
                LeadActivity visitActivity = new LeadActivity();
1209
                visitActivity.setLeadId(createLeadActivityRequest.getId());
1210
                visitActivity.setRemark("Lead scheduled for visit on beat: " + beatName
1211
                        + " (" + beatDate + ") at stop #" + (insertAt + 1));
1212
                visitActivity.setAuthId(authUser.getId());
1213
                visitActivity.setCreatedTimestamp(LocalDateTime.now());
1214
                leadActivityRepository.persist(visitActivity);
32464 tejbeer 1215
            }
1216
        } else {
1217
            leadActivity.setSchelduleTimestamp(null);
1218
        }
1219
        leadActivity.setCreatedTimestamp(LocalDateTime.now());
1220
        leadActivity.setAuthId(authUser.getId());
1221
        leadActivityRepository.persist(leadActivity);
1222
        lead.setAssignTo(createLeadActivityRequest.getAssignTo());
1223
        lead.setStatus(createLeadActivityRequest.getStatus());
35548 aman 1224
        lead.setState(createLeadActivityRequest.getState());
1225
        lead.setCity(createLeadActivityRequest.getCity());
35769 amit 1226
        if (createLeadActivityRequest.getSource() != null && !createLeadActivityRequest.getSource().isEmpty()) {
1227
            lead.setSource(createLeadActivityRequest.getSource());
1228
        }
36741 ranu 1229
        if (Boolean.TRUE.equals(createLeadActivityRequest.getColorCheck())) {
32471 tejbeer 1230
            lead.setColor("Green");
1231
        } else {
1232
            lead.setColor("Yellow");
1233
        }
32464 tejbeer 1234
        lead.setNotinterestedReason(createLeadActivityRequest.getReason());
1235
        lead.setUpdatedTimestamp(LocalDateTime.now());
37003 ranu 1236
        // Persist the mutated Lead row. Without this the audit activity is written but
1237
        // the main lead table keeps the old status/assignTo — the list view shows the
1238
        // stale row while the activity dialog shows the new state.
1239
        leadRepository.persist(lead);
29426 manish 1240
 
32464 tejbeer 1241
        int authId = 0;
34127 tejus.loha 1242
        authId = lead.getAssignTo();
1243
        Map<Integer, LeadActivity> leadActivityMap = new HashMap<>();
29426 manish 1244
 
34127 tejus.loha 1245
        List<LeadActivity> leadActivitys = leadActivityRepository.selectBYLeadId(lead.getId());
29426 manish 1246
 
34127 tejus.loha 1247
        if (!leadActivitys.isEmpty()) {
1248
            leadActivityMap.put(lead.getId(), leadActivitys.get(0));
1249
        }
29426 manish 1250
 
34127 tejus.loha 1251
        Map<Integer, AuthUser> authIdAndAuthUserMap = new HashMap<>();
1252
        AuthUser AuthUser = authRepository.selectById(authId);
29426 manish 1253
 
34127 tejus.loha 1254
        authIdAndAuthUserMap.put(AuthUser.getId(), AuthUser);
29426 manish 1255
 
34127 tejus.loha 1256
        model.addAttribute("leadActivityMap", leadActivityMap);
1257
        model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
29426 manish 1258
 
30185 tejbeer 1259
 
33223 amit.gupta 1260
        model.addAttribute("lead", lead);
30185 tejbeer 1261
 
36818 ranu 1262
        // Best-effort hierarchy email — fired after the lead+activity are persisted
1263
        // so a mail failure never blocks the assignment. Covers every editLead path
1264
        // (followUp, notInterested, etc.) so every assignment is announced upward.
1265
        try {
1266
            sendLeadAssignmentEmail(lead, AuthUser, authUser,
1267
                    createLeadActivityRequest.getStatus() != null ? createLeadActivityRequest.getStatus().toString() : null);
1268
        } catch (Exception e) {
1269
            LOGGER.warn("Lead-assignment email fan-out failed (lead id {}): {}", lead.getId(), e.getMessage());
1270
        }
1271
 
32464 tejbeer 1272
        return "edit-lead";
30185 tejbeer 1273
 
32464 tejbeer 1274
    }
31370 tejbeer 1275
 
36818 ranu 1276
    // Hierarchy-wide email when a lead is assigned. Recipients:
1277
    //   - the assignee themselves (L1)
1278
    //   - every manager above the assignee, capped at L4
1279
    // L5 / Final / super-admins are intentionally NOT copied on lead-management mails.
1280
    private void sendLeadAssignmentEmail(Lead lead, AuthUser assignee, AuthUser requestedBy, String status) {
1281
        if (gmailRelaySender == null || lead == null || assignee == null) return;
1282
 
1283
        java.util.LinkedHashSet<String> recipients = new java.util.LinkedHashSet<>();
1284
        if (assignee.getEmailId() != null && !assignee.getEmailId().isEmpty()) {
1285
            recipients.add(assignee.getEmailId());
1286
        }
1287
        try {
1288
            for (AuthUser m : authService.getAllManagers(assignee.getId())) {
1289
                if (m.getEmailId() == null || m.getEmailId().isEmpty()) continue;
1290
                // Cap chain at L4 — L5 / Final never receive lead-management mails.
1291
                com.spice.profitmandi.dao.enumuration.cs.EscalationType lvl = highestEscalation(m.getId());
1292
                if (lvl != null
1293
                        && com.spice.profitmandi.dao.enumuration.cs.EscalationType.L4.isGreaterThanEqualTo(lvl)) {
1294
                    recipients.add(m.getEmailId());
1295
                }
1296
            }
1297
        } catch (Exception ignored) {
1298
        }
1299
        if (recipients.isEmpty()) return;
1300
 
1301
        // TEST OVERRIDE — uncomment to route all lead-assignment mail to one inbox.
1302
        // recipients.clear();
1303
        // recipients.add("ranu.rajput@smartdukaan.com");
1304
 
1305
        String leadName = ((lead.getFirstName() != null ? lead.getFirstName() : "")
1306
                + " " + (lead.getLastName() != null ? lead.getLastName() : "")).trim();
1307
        if (leadName.isEmpty()) leadName = "Lead #" + lead.getId();
1308
        String assigneeName = ((assignee.getFirstName() != null ? assignee.getFirstName() : "")
1309
                + " " + (assignee.getLastName() != null ? assignee.getLastName() : "")).trim();
1310
 
1311
        String subject = "Lead assigned — " + leadName + " → " + assigneeName;
1312
        StringBuilder text = new StringBuilder();
1313
        text.append("A lead has been assigned.\n\n");
1314
        text.append("Lead:        ").append(leadName).append("\n");
1315
        if (lead.getLeadMobile() != null) text.append("Mobile:      ").append(lead.getLeadMobile()).append("\n");
1316
        if (lead.getOutLetName() != null) text.append("Outlet:      ").append(lead.getOutLetName()).append("\n");
1317
        if (lead.getCity() != null || lead.getState() != null) {
1318
            text.append("Location:    ")
1319
                    .append(lead.getCity() != null ? lead.getCity() : "")
1320
                    .append(lead.getCity() != null && lead.getState() != null ? ", " : "")
1321
                    .append(lead.getState() != null ? lead.getState() : "")
1322
                    .append("\n");
1323
        }
1324
        text.append("Assignee:    ").append(assigneeName).append("\n");
1325
        if (status != null) text.append("Status:      ").append(status).append("\n");
1326
        if (requestedBy != null) {
1327
            String rbName = ((requestedBy.getFirstName() != null ? requestedBy.getFirstName() : "")
1328
                    + " " + (requestedBy.getLastName() != null ? requestedBy.getLastName() : "")).trim();
1329
            text.append("Assigned by: ").append(rbName.isEmpty() ? ("#" + requestedBy.getId()) : rbName).append("\n");
1330
        }
1331
 
1332
        try {
1333
            javax.mail.internet.MimeMessage message = gmailRelaySender.createMimeMessage();
1334
            org.springframework.mail.javamail.MimeMessageHelper helper = new org.springframework.mail.javamail.MimeMessageHelper(message, true);
1335
            helper.setSubject(subject);
1336
            helper.setText(text.toString());
1337
            helper.setTo(recipients.toArray(new String[0]));
1338
            helper.setFrom(new javax.mail.internet.InternetAddress("sdtech@smartdukaan.com", "SD Tech"));
1339
            gmailRelaySender.send(message);
1340
        } catch (Exception e) {
1341
            LOGGER.warn("Lead-assignment mail send failed: {}", e.getMessage());
1342
        }
1343
    }
1344
 
1345
    // Returns the user's highest escalation across all positions (or null).
1346
    // Used to gate the chain-mail cap.
1347
    private com.spice.profitmandi.dao.enumuration.cs.EscalationType highestEscalation(int authUserId) {
1348
        com.spice.profitmandi.dao.enumuration.cs.EscalationType highest = null;
1349
        try {
1350
            for (com.spice.profitmandi.dao.entity.cs.Position p : positionRepository.selectPositionByAuthId(authUserId)) {
1351
                if (highest == null || p.getEscalationType().isGreaterThanEqualTo(highest)) {
1352
                    highest = p.getEscalationType();
1353
                }
1354
            }
1355
        } catch (Exception ignored) {
1356
        }
1357
        return highest;
1358
    }
1359
 
32464 tejbeer 1360
    @RequestMapping(value = "/downloadIvoryLead", method = RequestMethod.GET)
1361
    public ResponseEntity<?> downloadDelayDayTemplate(HttpServletRequest request) throws Exception {
1362
        List<String> stateNames = stateRepository.selectAll().stream().map(x -> x.getName()).collect(Collectors.toList());
31370 tejbeer 1363
 
32464 tejbeer 1364
        List<List<?>> rows = new ArrayList<>();
31496 tejbeer 1365
 
32464 tejbeer 1366
        List<LeadSource> lss = LeadSource.enumValues;
31370 tejbeer 1367
 
32464 tejbeer 1368
        for (LeadSource ls : lss) {
1369
            rows.add(Arrays.asList("-", "-", "-", "-", "-", "-", "-", ls));
31478 tejbeer 1370
 
32464 tejbeer 1371
        }
1372
        for (String stateName : stateNames) {
1373
            rows.add(Arrays.asList("-", "-", "-", "-", stateName, "-", "-", "-"));
31478 tejbeer 1374
 
32464 tejbeer 1375
        }
31478 tejbeer 1376
 
32464 tejbeer 1377
        org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(Arrays.asList("First Name", "Last Name", "Address", "City", "State", "Mobile", "Assign To(email)", "Source"), rows);
31478 tejbeer 1378
 
32464 tejbeer 1379
        final HttpHeaders headers = new HttpHeaders();
1380
        headers.set("Content-Type", "text/csv");
1381
        headers.set("Content-disposition", "inline; filename=leads.format.csv");
1382
        headers.setContentLength(baos.toByteArray().length);
31478 tejbeer 1383
 
32464 tejbeer 1384
        final InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
1385
        final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
1386
        return new ResponseEntity<InputStreamResource>(inputStreamResource, headers, HttpStatus.OK);
31478 tejbeer 1387
 
32464 tejbeer 1388
    }
31478 tejbeer 1389
 
32464 tejbeer 1390
    @RequestMapping(value = "/csvFileAndSetLead", method = RequestMethod.POST)
1391
    public String readCsvFileAndSetLead(HttpServletRequest request, Model model, HttpServletResponse response, @RequestPart MultipartFile file) throws Throwable {
31478 tejbeer 1392
 
32464 tejbeer 1393
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1394
        String email = loginDetails.getEmailId();
31478 tejbeer 1395
 
32464 tejbeer 1396
        AuthUser createdBy = authRepository.selectByEmailOrMobile(email);
31478 tejbeer 1397
 
32464 tejbeer 1398
        LOGGER.info("file" + file.toString());
31478 tejbeer 1399
 
32464 tejbeer 1400
        String fileName = file.getName();
31370 tejbeer 1401
 
32464 tejbeer 1402
        String fileNames = file.getOriginalFilename();
31370 tejbeer 1403
 
32464 tejbeer 1404
        LOGGER.info("fileName" + fileName);
1405
        LOGGER.info("fileNames" + fileNames);
31370 tejbeer 1406
 
32464 tejbeer 1407
        List<CSVRecord> records = FileUtil.readFile(file);
31370 tejbeer 1408
 
32464 tejbeer 1409
        for (CSVRecord record : records) {
31370 tejbeer 1410
 
32464 tejbeer 1411
            Lead lead = new Lead();
1412
            lead.setFirstName(record.get(0));
1413
            lead.setLastName(record.get(1));
1414
            lead.setAddress(record.get(2));
1415
            lead.setCity(record.get(3));
1416
            lead.setState(record.get(4));
1417
            lead.setLeadMobile(record.get(5));
1418
            LOGGER.info("record" + record.get(6));
31370 tejbeer 1419
 
32464 tejbeer 1420
            AuthUser assignTo = authRepository.selectByEmailOrMobile(record.get(6));
31370 tejbeer 1421
 
32464 tejbeer 1422
            if (assignTo == null) {
1423
                throw new ProfitMandiBusinessException("Assign To ", record.get(6), "email id not exist");
1424
            }
31370 tejbeer 1425
 
32464 tejbeer 1426
            lead.setAssignTo(assignTo.getId());
1427
            lead.setSource(record.get(7));
31370 tejbeer 1428
 
32464 tejbeer 1429
            lead.setCreatedTimestamp(LocalDateTime.now());
31370 tejbeer 1430
 
32464 tejbeer 1431
            lead.setUpdatedTimestamp(LocalDateTime.now());
1432
            lead.setStatus(LeadStatus.pending);
1433
            lead.setColor("yellow");
1434
            // change
1435
            lead.setCreatedBy(createdBy.getFullName());
1436
            lead.setAuthId(createdBy.getId());
31370 tejbeer 1437
 
32464 tejbeer 1438
            leadRepository.persist(lead);
31370 tejbeer 1439
 
32464 tejbeer 1440
            LeadActivity leadActivity = new LeadActivity();
1441
            leadActivity.setLeadId(lead.getId());
1442
            leadActivity.setRemark("New Lead");
1443
            leadActivity.setSchelduleTimestamp(null);
31370 tejbeer 1444
 
32464 tejbeer 1445
            leadActivity.setCreatedTimestamp(LocalDateTime.now());
1446
            leadActivityRepository.persist(leadActivity);
1447
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));
31370 tejbeer 1448
 
32464 tejbeer 1449
        }
31370 tejbeer 1450
 
32464 tejbeer 1451
        model.addAttribute("responseSTG", mvcResponseSender.createResponseString(true));
31370 tejbeer 1452
 
32464 tejbeer 1453
        return "response";
31370 tejbeer 1454
 
32464 tejbeer 1455
    }
31370 tejbeer 1456
 
32464 tejbeer 1457
    @RequestMapping(value = "/teamCommitment", method = RequestMethod.GET)
1458
    public String teamCommitments(HttpServletRequest request, Model model) throws Exception {
31370 tejbeer 1459
 
32464 tejbeer 1460
        return "team-commitment";
31370 tejbeer 1461
 
32464 tejbeer 1462
    }
31370 tejbeer 1463
 
32464 tejbeer 1464
    @RequestMapping(value = "/leadDetail", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
1465
    public String leadDetail(HttpServletRequest request, @RequestBody LeadDetailModel leadDetailModel, Model model) throws Exception {
31370 tejbeer 1466
 
32464 tejbeer 1467
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1468
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
31370 tejbeer 1469
 
32471 tejbeer 1470
        leadRepository.persistLeadDetail(leadDetailModel, authUser);
32464 tejbeer 1471
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
31370 tejbeer 1472
 
32464 tejbeer 1473
        return "response";
31370 tejbeer 1474
 
32464 tejbeer 1475
    }
31370 tejbeer 1476
 
32464 tejbeer 1477
    @RequestMapping(value = "/getLeadDetail", method = RequestMethod.GET)
1478
    public String getLeadDetail(HttpServletRequest request, Model model) throws Exception {
1479
        List<Integer> followUpleadIds = leadRepository.selectAllByStatus(LeadStatus.followUp).stream().map(x -> x.getId()).collect(Collectors.toList());
1480
        List<LeadDetail> leadDetails = leadDetailRepository.selectByLeadIds(followUpleadIds);
31370 tejbeer 1481
 
32464 tejbeer 1482
        List<DBObject> mobileBrands = mongoClient.getAllBrandsToDisplay(3);
31370 tejbeer 1483
 
32464 tejbeer 1484
        List<String> brands = mobileBrands.stream().map(x -> (String) x.get("name")).collect(Collectors.toList());
31370 tejbeer 1485
 
32464 tejbeer 1486
        model.addAttribute("brands", brands);
1487
        if (!leadDetails.isEmpty()) {
31370 tejbeer 1488
 
32464 tejbeer 1489
            List<Integer> detailsIds = leadDetails.stream().map(x -> x.getId()).collect(Collectors.toList());
31370 tejbeer 1490
 
32464 tejbeer 1491
            List<Integer> leadIds = leadDetails.stream().map(x -> x.getLeadId()).collect(Collectors.toList());
31370 tejbeer 1492
 
32464 tejbeer 1493
            Map<Integer, Lead> leadMap = leadRepository.selectAllByIds(leadIds).stream().filter(x -> x.getStatus().equals(LeadStatus.followUp)).collect(Collectors.toMap(x -> x.getId(), x -> x));
31370 tejbeer 1494
 
32464 tejbeer 1495
            Map<Integer, Optional<LeadActivity>> leadActivityMap = leadActivityRepository.selectAllByleadIds(leadIds).stream().collect(Collectors.groupingBy(x -> x.getLeadId(), Collectors.maxBy(Comparator.comparing(LeadActivity::getId))));
31370 tejbeer 1496
 
32464 tejbeer 1497
            model.addAttribute("leadActivityMap", leadActivityMap);
30185 tejbeer 1498
 
32464 tejbeer 1499
            List<LeadBrand> leadBrands = leadBrandRepository.selectByLeadDetailId(detailsIds);
30185 tejbeer 1500
 
32464 tejbeer 1501
            LOGGER.info("leadBrands {}" + leadBrands);
30185 tejbeer 1502
 
32464 tejbeer 1503
            Map<Integer, Map<String, Integer>> leadDetailBrandValue = new HashMap<>();
30416 tejbeer 1504
 
32464 tejbeer 1505
            Map<Integer, List<LeadBrand>> leadDetail = leadBrands.stream().collect(Collectors.groupingBy(x -> x.getLeadDetailId(), Collectors.toList()));
30416 tejbeer 1506
 
32464 tejbeer 1507
            for (Entry<Integer, List<LeadBrand>> leadDetailEntry : leadDetail.entrySet()) {
30416 tejbeer 1508
 
32464 tejbeer 1509
                Map<String, Integer> brandValue = new HashMap<>();
30416 tejbeer 1510
 
32464 tejbeer 1511
                for (LeadBrand leadBrand : leadDetailEntry.getValue()) {
1512
                    brandValue.put(leadBrand.getBrand(), leadBrand.getValue());
30416 tejbeer 1513
 
32464 tejbeer 1514
                }
1515
                leadDetailBrandValue.put(leadDetailEntry.getKey(), brandValue);
1516
            }
30416 tejbeer 1517
 
32464 tejbeer 1518
            LOGGER.info("leadDetailBrandValue {}" + leadDetailBrandValue);
30416 tejbeer 1519
 
32464 tejbeer 1520
            model.addAttribute("leadDetailBrandValue", leadDetailBrandValue);
30416 tejbeer 1521
 
32464 tejbeer 1522
            model.addAttribute("leadMap", leadMap);
1523
        }
30434 tejbeer 1524
 
32464 tejbeer 1525
        model.addAttribute("leadDetails", leadDetails);
30434 tejbeer 1526
 
32464 tejbeer 1527
        Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectAllActiveUser().stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
1528
        model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
30434 tejbeer 1529
 
32464 tejbeer 1530
        return "lead-detail";
30458 tejbeer 1531
 
32464 tejbeer 1532
    }
30458 tejbeer 1533
 
32464 tejbeer 1534
    @RequestMapping(value = "/getLeadDetailByLeadId", method = RequestMethod.GET)
35548 aman 1535
    public ResponseEntity<?> getLeadDetailByLeadId(@RequestParam int leadId) {
30458 tejbeer 1536
 
35548 aman 1537
        Lead lead = leadRepository.selectById(leadId);
32464 tejbeer 1538
        LeadDetail leadDetail = leadDetailRepository.selectByLeadId(leadId);
35548 aman 1539
        Map<String, Object> response = new HashMap<>();
1540
        response.put("city", lead.getCity());
1541
        response.put("state", lead.getState());
1542
        if (leadDetail != null) {
1543
            response.put("outletName", leadDetail.getOutletName());
1544
            response.put("counterSize", leadDetail.getCounterSize());
1545
        }
1546
        return responseSender.ok(response);
1547
    }
30458 tejbeer 1548
 
35548 aman 1549
    @PostMapping("/upload-assign-id")
1550
    public ResponseEntity<?> uploadAssignIdCsv(
1551
            @RequestParam("file") MultipartFile file)
1552
            throws Exception {
1553
 
1554
        try (Reader reader = new InputStreamReader(file.getInputStream());
1555
             CSVParser parser = new CSVParser(reader, CSVFormat.DEFAULT)) {
1556
 
1557
            List<CSVRecord> records = parser.getRecords();
1558
 
1559
            if (records.size() < 2) {
1560
                throw new ProfitMandiBusinessException(
1561
                        "Uploaded File", "", "No records Found");
1562
            }
1563
 
1564
            records.remove(0);
1565
 
1566
            for (CSVRecord record : records) {
1567
 
1568
                int leadId = Integer.parseInt(record.get(0));
1569
                int assignId = Integer.parseInt(record.get(1));
1570
 
1571
                Lead lead = leadRepository.selectById(leadId);
1572
 
1573
                if (lead == null) {
1574
                    LOGGER.warn("Lead not found for id {}", leadId);
1575
                    continue;
1576
                }
1577
 
1578
                lead.setAssignTo(assignId);
1579
            }
1580
        }
1581
 
1582
        return responseSender.ok("CSV processed successfully");
32464 tejbeer 1583
    }
30434 tejbeer 1584
 
35548 aman 1585
 
1586
 
32464 tejbeer 1587
    @RequestMapping(value = "/getTeamCommitment", method = RequestMethod.GET)
1588
    public String getTeamCommitments(HttpServletRequest request, @RequestParam LocalDateTime date, Model model) throws Exception {
30781 tejbeer 1589
 
32464 tejbeer 1590
        List<TeamCommitmentModel> commitments = partnerCollectionPlanRepository.selectTeamCommitmentByDate(date.toLocalDate());
30416 tejbeer 1591
 
32464 tejbeer 1592
        model.addAttribute("commitments", commitments);
1593
        return "team-commitment-table";
30416 tejbeer 1594
 
32464 tejbeer 1595
    }
30416 tejbeer 1596
 
33917 ranu 1597
    @Autowired
1598
    RbmTargetService rbmTargetService;
1599
 
1600
    @RequestMapping(value = "/rbmTodayArr", method = RequestMethod.GET)
1601
    public String getRbmTodayArr(HttpServletRequest request, Model model, @RequestParam(value = "startDate", required = false) LocalDate startDate) throws Exception {
1602
        List<RbmArrViewModel> rbmArrViewModels;
35223 ranu 1603
        DecimalFormat decimalFormat = new DecimalFormat("#"); // No decimal places
33917 ranu 1604
        if (startDate != null) {
1605
            rbmArrViewModels = rbmTargetService.getRbmTodayArr(startDate);
1606
        } else {
1607
            rbmArrViewModels = rbmTargetService.getRbmTodayArr();
1608
        }
1609
 
35223 ranu 1610
        Set<AuthUser> authUsers = new HashSet<>();
1611
        Set<AuthUser> rbmAuthUsers = csService.getAuthUserByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_RBM, EscalationType.L1).stream().filter(x -> x.isActive()).collect(Collectors.toSet());
1612
        Set<AuthUser> salesAuthUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_RBM, Arrays.asList(EscalationType.L1, EscalationType.L2)).stream().filter(x -> x.isActive()).collect(Collectors.toSet());
33953 ranu 1613
 
35223 ranu 1614
        authUsers.addAll(rbmAuthUsers);
1615
        authUsers.addAll(salesAuthUsers);
33953 ranu 1616
 
35223 ranu 1617
        double totalAchieved = rbmArrViewModels.stream().mapToDouble(RbmArrViewModel::getTotalAchievedTarget).sum();
1618
        double totalTargetSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayTarget).sum();
1619
 
1620
        double totalHidSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayHidTarget).sum();
1621
        double totalHidAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedHidTarget).sum();
1622
 
1623
        double totalFastSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayFastMovingTarget).sum();
1624
        double totalFastAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedFastMovingTarget).sum();
1625
 
1626
        double totalSlowSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodaySlowMovingTarget).sum();
1627
        double totalSlowAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedSlowMovingTarget).sum();
1628
 
1629
        double totalRunningSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayRunningTarget).sum();
1630
        double totalRunningAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedRunningTarget).sum();
1631
 
1632
        double totalOtherSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayOtherMovingTarget).sum();
1633
        double totalOtherAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedOtherMovingTarget).sum();
1634
 
34055 ranu 1635
        List<Sold15daysOldAgingModel> sold15daysOldAgingModels = rbmTargetService.getAgingSale(LocalDate.now(), LocalDate.now().plusDays(1));
1636
        List<Our15DaysOldAgingStock> our15DaysOldAgingStocks = rbmTargetService.our15DaysAgingStock();
1637
 
35223 ranu 1638
        long totalSoldSlow = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getSlowmovingBilled).sum();
1639
        long totalSoldRun = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getRunningBilled).sum();
1640
        long totalSoldFast = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getFastmovingBilled).sum();
1641
        long totalSoldHid = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getHidBilled).sum();
1642
        long totalSoldOther = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getOthersBilled).sum();
1643
        long totalSoldAging = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getTotalBilled).sum();
34103 ranu 1644
 
35223 ranu 1645
 
34103 ranu 1646
//        first week count of rbm partner billing
1647
        LocalDate firstOfCurrentMonth = LocalDate.now().withDayOfMonth(1);
1648
        LocalDate seventhOfCurrentMonth = LocalDate.now().withDayOfMonth(7);
1649
 
1650
        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsFirstWeek = rbmTargetService.getDateWiseBilledFofoIdByRbm(firstOfCurrentMonth, seventhOfCurrentMonth);
1651
 
1652
        Map<String, Long> rbmBilledCountMapFirstWeek = rbmBilledFofoIdsModelsFirstWeek.stream()
1653
                .filter(x -> x.getStatus().equals("Billed"))
1654
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));
1655
 
34119 ranu 1656
        long totalFirstWeekCount = rbmBilledCountMapFirstWeek.values().stream()
1657
                .mapToLong(Long::longValue)
1658
                .sum();
1659
 
34114 ranu 1660
        Map<String, Long> rbmTargetedFofoIdCountMap = rbmBilledFofoIdsModelsFirstWeek.stream()
1661
                .collect(Collectors.groupingBy(
1662
                        RbmBilledFofoIdsModel::getRbmName, // Group by RBM Name
1663
                        Collectors.counting() // Count all fofoId entries for each RBM
1664
                ));
34103 ranu 1665
 
34119 ranu 1666
        long totalTargetedCount = rbmTargetedFofoIdCountMap.values().stream().mapToLong(x -> x.longValue()).sum();
34114 ranu 1667
 
1668
 
34103 ranu 1669
//        second week count of rbm partner billing
1670
 
1671
        LocalDate eightOfCurrentMonth = LocalDate.now().withDayOfMonth(8);
1672
        LocalDate fifteenOfCurrentMonth = LocalDate.now().withDayOfMonth(15);
1673
 
1674
        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsSecondWeek = rbmTargetService.getDateWiseBilledFofoIdByRbm(eightOfCurrentMonth, fifteenOfCurrentMonth);
1675
 
1676
        Map<String, Long> rbmBilledCountMapSecondWeek = rbmBilledFofoIdsModelsSecondWeek.stream()
1677
                .filter(x -> x.getStatus().equals("Billed"))
1678
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));
1679
 
34119 ranu 1680
        long totalSecondWeekCount = rbmBilledCountMapSecondWeek.values().stream().mapToLong(Long::longValue).sum();
34103 ranu 1681
 
1682
//      third week count of rbm partner billing
1683
 
1684
        LocalDate sixteenOfCurrentMonth = LocalDate.now().withDayOfMonth(16);
34144 ranu 1685
        LocalDate twentySecondOfCurrentMonth = LocalDate.now().withDayOfMonth(22);
34103 ranu 1686
 
34144 ranu 1687
        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsThirdWeek = rbmTargetService.getDateWiseBilledFofoIdByRbm(sixteenOfCurrentMonth, twentySecondOfCurrentMonth);
34103 ranu 1688
 
1689
        Map<String, Long> rbmBilledCountMapThirdWeek = rbmBilledFofoIdsModelsThirdWeek.stream()
1690
                .filter(x -> x.getStatus().equals("Billed"))
1691
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));
1692
 
34119 ranu 1693
        long totalThirdWeekCount = rbmBilledCountMapThirdWeek.values().stream().mapToLong(Long::longValue).sum();
34103 ranu 1694
 
34119 ranu 1695
 
34103 ranu 1696
        //      fourth week count of rbm partner billing
1697
 
34144 ranu 1698
        LocalDate twentyThirdOfCurrentMonth = LocalDate.now().withDayOfMonth(23);
34103 ranu 1699
        LocalDate lastDayOfCurrentMonth = LocalDate.now().withDayOfMonth(LocalDate.now().lengthOfMonth());
1700
 
34144 ranu 1701
        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsFourthWeek = rbmTargetService.getDateWiseBilledFofoIdByRbm(twentyThirdOfCurrentMonth, lastDayOfCurrentMonth);
34103 ranu 1702
 
1703
        Map<String, Long> rbmBilledCountMapFourthWeek = rbmBilledFofoIdsModelsFourthWeek.stream()
1704
                .filter(x -> x.getStatus().equals("Billed"))
1705
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));
1706
 
34119 ranu 1707
        long totalFourthWeekCount = rbmBilledCountMapFourthWeek.values().stream().mapToLong(x -> x.longValue()).sum();
34103 ranu 1708
 
34119 ranu 1709
 
34103 ranu 1710
//      mtd rbm partner billing
1711
 
1712
        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsMtd = rbmTargetService.getDateWiseBilledFofoIdByRbm(firstOfCurrentMonth, LocalDate.now());
1713
 
1714
        Map<String, Long> rbmBilledCountMapMtd = rbmBilledFofoIdsModelsMtd.stream()
1715
                .filter(x -> x.getStatus().equals("Billed"))
1716
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));
1717
 
34119 ranu 1718
        long totalMtdCount = rbmBilledCountMapMtd.values().stream().mapToLong(Long::longValue).sum();
1719
 
1720
        Map<String, Long> zeroBilledCountMap = rbmTargetedFofoIdCountMap.entrySet().stream()
1721
                .collect(Collectors.toMap(
1722
                        Map.Entry::getKey,
1723
                        entry -> entry.getValue() - rbmBilledCountMapMtd.getOrDefault(entry.getKey(), 0L)
1724
                ));
1725
 
1726
        long totalZeroBilledCount = zeroBilledCountMap.values().stream().mapToLong(Long::longValue).sum();
1727
 
36101 ranu 1728
        //        rbmRating by franchisee visits (weekly: Monday to Sunday)
35223 ranu 1729
 
1730
        Map<Integer, String> rbmIdToNameMap = authUsers.stream()
1731
                .collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));
1732
 
36101 ranu 1733
        // Calculate current week: Monday (start) to Sunday (end)
1734
        LocalDate today = LocalDate.now();
1735
        LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
1736
        LocalDate sunday = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
1737
        LocalDateTime weekStart = monday.atStartOfDay();
1738
        LocalDateTime weekEnd = sunday.atTime(LocalTime.MAX);
1739
 
35223 ranu 1740
        Map<String, RbMRatingModel> rbmNameToRatingMap = rbmRatingRepository
36101 ranu 1741
                .findAverageRatingByRbmIdAndDateRange(new ArrayList<>(rbmIdToNameMap.keySet()), weekStart, weekEnd)
1742
                .stream().collect(Collectors.toMap(
35223 ranu 1743
                        x -> rbmIdToNameMap.get(x.getRbmId()),
1744
                        x -> x
1745
                ));
1746
 
1747
 
33917 ranu 1748
        LOGGER.info("rbmArrViewModels {}", rbmArrViewModels);
1749
        model.addAttribute("rbmArrViewModels", rbmArrViewModels);
35223 ranu 1750
        model.addAttribute("rbmNameToRatingMap", rbmNameToRatingMap);
1751
 
1752
        model.addAttribute("totalTargetSum", decimalFormat.format(totalTargetSum));
1753
        model.addAttribute("totalAchieved", decimalFormat.format(totalAchieved));
1754
 
1755
        model.addAttribute("totalHidSum", decimalFormat.format(totalHidSum));
1756
        model.addAttribute("totalHidAchievedSum", decimalFormat.format(totalHidAchievedSum));
1757
 
1758
        model.addAttribute("totalFastSum", decimalFormat.format(totalFastSum));
1759
        model.addAttribute("totalFastAchievedSum", decimalFormat.format(totalFastAchievedSum));
1760
 
1761
        model.addAttribute("totalSlowSum", decimalFormat.format(totalSlowSum));
1762
        model.addAttribute("totalSlowAchievedSum", decimalFormat.format(totalSlowAchievedSum));
1763
 
1764
        model.addAttribute("totalRunningSum", decimalFormat.format(totalRunningSum));
1765
        model.addAttribute("totalRunningAchievedSum", decimalFormat.format(totalRunningAchievedSum));
1766
 
1767
        model.addAttribute("totalOtherSum", decimalFormat.format(totalOtherSum));
1768
        model.addAttribute("totalOtherAchievedSum", decimalFormat.format(totalOtherAchievedSum));
1769
 
1770
        model.addAttribute("our15DaysOldAgingStocks", our15DaysOldAgingStocks);
34055 ranu 1771
        model.addAttribute("sold15daysOldAgingModels", sold15daysOldAgingModels);
35223 ranu 1772
        model.addAttribute("totalSoldSlow", totalSoldSlow);
1773
        model.addAttribute("totalSoldRun", totalSoldRun);
1774
        model.addAttribute("totalSoldFast", totalSoldFast);
1775
        model.addAttribute("totalSoldHid", totalSoldHid);
1776
        model.addAttribute("totalSoldOther", totalSoldOther);
1777
        model.addAttribute("totalSoldAging", totalSoldAging);
33917 ranu 1778
 
34114 ranu 1779
        model.addAttribute("rbmTargetedFofoIdCountMap", rbmTargetedFofoIdCountMap);
34103 ranu 1780
        model.addAttribute("rbmBilledCountMapFirstWeek", rbmBilledCountMapFirstWeek);
1781
        model.addAttribute("rbmBilledCountMapSecondWeek", rbmBilledCountMapSecondWeek);
1782
        model.addAttribute("rbmBilledCountMapThirdWeek", rbmBilledCountMapThirdWeek);
1783
        model.addAttribute("rbmBilledCountMapFourthWeek", rbmBilledCountMapFourthWeek);
1784
        model.addAttribute("rbmBilledCountMapMtd", rbmBilledCountMapMtd);
34119 ranu 1785
        model.addAttribute("zeroBilledCountMap", zeroBilledCountMap);
1786
        model.addAttribute("totalFirstWeekCount", totalFirstWeekCount);
1787
        model.addAttribute("totalTargetedCount", totalTargetedCount);
1788
        model.addAttribute("totalSecondWeekCount", totalSecondWeekCount);
1789
        model.addAttribute("totalThirdWeekCount", totalThirdWeekCount);
1790
        model.addAttribute("totalFourthWeekCount", totalFourthWeekCount);
1791
        model.addAttribute("totalMtdCount", totalMtdCount);
1792
        model.addAttribute("totalZeroBilledCount", totalZeroBilledCount);
34103 ranu 1793
 
33917 ranu 1794
        return "rbm-today-arr";
1795
    }
1796
 
1797
 
32464 tejbeer 1798
    @RequestMapping(value = "/partnerHealth", method = RequestMethod.GET)
1799
    public String partnerHealth(HttpServletRequest request, @RequestParam(name = "email", required = false) String email, Model model) throws Exception {
1800
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
30416 tejbeer 1801
 
32464 tejbeer 1802
        if (StringUtils.isEmpty(email)) {
1803
            email = loginDetails.getEmailId();
1804
        } else {
1805
            AuthUser selectedUser = authRepository.selectByEmailOrMobile(email);
30416 tejbeer 1806
 
32464 tejbeer 1807
            model.addAttribute("selectedUser", selectedUser);
30445 tejbeer 1808
 
32464 tejbeer 1809
        }
30445 tejbeer 1810
 
32464 tejbeer 1811
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
30445 tejbeer 1812
 
32464 tejbeer 1813
        Map<String, Set<Integer>> storeGuyMap = csService.getAuthUserPartnerIdMapping();
1814
        List<Integer> fofoIds = new ArrayList<>(storeGuyMap.get(email));
1815
        LocalDateTime startDate = LocalDate.now().atStartOfDay();
1816
        if (fofoIds != null && fofoIds.size() > 0) {
1817
            List<Integer> fofoIdList = fofoStoreRepository.selectByRetailerIds(fofoIds).stream().filter(x -> !x.isInternal()).map(x -> x.getId()).collect(Collectors.toList());
30420 tejbeer 1818
 
32464 tejbeer 1819
            Map<Integer, PartnerCollectionPlanModel> foundCollectionMap = partnerCollectionService.getCollectionMap(fofoIdList, startDate);
30416 tejbeer 1820
 
32464 tejbeer 1821
            List<Integer> remarkIds = partnerCollectionRemarkRepository.selectMaxRemarkId(fofoIdList);
30416 tejbeer 1822
 
32464 tejbeer 1823
            LOGGER.info("remarkIds {}", remarkIds);
30416 tejbeer 1824
 
32464 tejbeer 1825
            long todayOverallCall = 0;
1826
            if (!remarkIds.isEmpty()) {
30416 tejbeer 1827
 
32464 tejbeer 1828
                if (authUser.getEmailId().equals(email)) {
30441 tejbeer 1829
 
32464 tejbeer 1830
                    todayOverallCall = partnerCollectionRemarkRepository.selectByIds(remarkIds).stream().filter(x -> x.getCreateTimestamp().toLocalDate().equals(LocalDate.now())).collect(Collectors.counting());
1831
                } else {
30441 tejbeer 1832
 
32464 tejbeer 1833
                    todayOverallCall = partnerCollectionRemarkRepository.selectByAuthIdAndIds(authRepository.selectByEmailOrMobile(email).getId(), remarkIds).stream().filter(x -> x.getCreateTimestamp().toLocalDate().equals(LocalDate.now())).collect(Collectors.counting());
30416 tejbeer 1834
 
32464 tejbeer 1835
                }
30416 tejbeer 1836
 
32464 tejbeer 1837
            }
1838
            ChartLeadModel cm = new ChartLeadModel();
30416 tejbeer 1839
 
32464 tejbeer 1840
            if (!foundCollectionMap.isEmpty()) {
1841
                cm = this.getCollectionCount(foundCollectionMap.values().stream().collect(Collectors.toList()));
30416 tejbeer 1842
 
32464 tejbeer 1843
            }
1844
            model.addAttribute("chartPartnerHealth", gson.toJson(cm));
1845
            Map<Integer, PartnerDailyInvestment> partnerDailyInvestmentMap = new HashMap<>();
30416 tejbeer 1846
 
32464 tejbeer 1847
            List<PartnerDailyInvestment> partnerDailyInvestments = partnerDailyInvestmentRepository.selectAll(fofoIdList, startDate.toLocalDate().minusDays(1));
1848
            if (!partnerDailyInvestments.isEmpty()) {
1849
                partnerDailyInvestmentMap = partnerDailyInvestments.stream().collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
1850
            }
30416 tejbeer 1851
 
32464 tejbeer 1852
            Map<LocalDate, Map<Integer, PartnerCollectionPlanModel>> pcpmMap = new TreeMap<>();
1853
            for (int i = 0; i <= 6; i++) {
30416 tejbeer 1854
 
32464 tejbeer 1855
                Map<Integer, PartnerCollectionPlanModel> collectionMap = partnerCollectionService.getCollectionMap(fofoIdList, startDate.minusDays(i));
30416 tejbeer 1856
 
32464 tejbeer 1857
                pcpmMap.put(startDate.minusDays(i).toLocalDate(), collectionMap);
1858
            }
30416 tejbeer 1859
 
32464 tejbeer 1860
            Map<Integer, PartnerCollectionPlanModel> todayPcpmMap = pcpmMap.get(startDate.toLocalDate());
1861
            model.addAttribute("todayPcpmMap", todayPcpmMap);
30416 tejbeer 1862
 
32464 tejbeer 1863
            TotalTargetColectionModel totalTargetCollection = partnerCollectionService.getTotalTargetCollection(todayPcpmMap, startDate);
1864
            model.addAttribute("totalPartnerTargetCollection", totalTargetCollection.getTotalTarget());
30416 tejbeer 1865
 
32464 tejbeer 1866
            model.addAttribute("totalPartnerAchievement", totalTargetCollection.getTotalAchievement());
30416 tejbeer 1867
 
32464 tejbeer 1868
            Map<Integer, CustomRetailer> customRetailerMap = retailerService.getAllFofoRetailers();
1869
            Map<Integer, CustomRetailer> customRetailers = fofoIdList.stream().distinct().map(x -> customRetailerMap.get(x)).filter(x -> x != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(x -> x.getPartnerId(), x -> x));
1870
            List<Integer> allReportees = authService.getAllReportees(authUser.getId());
30416 tejbeer 1871
 
32464 tejbeer 1872
            List<Integer> salesPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_SALES).stream().map(x -> x.getAuthUserId()).collect(Collectors.toList());
1873
            List<Integer> rbmPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_RBM).stream().map(x -> x.getAuthUserId()).collect(Collectors.toList());
30416 tejbeer 1874
 
32464 tejbeer 1875
            salesPositionsAuthIds.addAll(rbmPositionsAuthIds);
30416 tejbeer 1876
 
32464 tejbeer 1877
            Set<Integer> empHierarchy = allReportees.stream().filter(x -> salesPositionsAuthIds.contains(x)).collect(Collectors.toSet());
34027 ranu 1878
            List<AuthUser> authUsers = new ArrayList<>();
1879
            if (!empHierarchy.isEmpty()) {
35395 amit 1880
                authUsers = authRepository.selectByIds(new ArrayList<>(empHierarchy));
34027 ranu 1881
            }
30416 tejbeer 1882
 
1883
 
32464 tejbeer 1884
            Map<Integer, AuthUser> authUserMap = authRepository.selectAll().stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
30416 tejbeer 1885
 
32464 tejbeer 1886
            LOGGER.info("todayPcpmMap {}", todayPcpmMap);
30416 tejbeer 1887
 
32464 tejbeer 1888
            model.addAttribute("authUsers", authUsers);
1889
            model.addAttribute("authUserMap", authUserMap);
1890
            model.addAttribute("partnerCollectionPlanMap", pcpmMap);
1891
            model.addAttribute("partnerDailyInvestmentMap", partnerDailyInvestmentMap);
1892
            model.addAttribute("customRetailers", customRetailers);
1893
            model.addAttribute("rankColorMap", ProfitMandiConstants.Rank_Color_Map);
1894
            model.addAttribute("todayOverallCall", todayOverallCall);
30522 tejbeer 1895
 
32464 tejbeer 1896
        }
1897
        return "partner-health";
30522 tejbeer 1898
 
32464 tejbeer 1899
    }
30522 tejbeer 1900
 
32464 tejbeer 1901
    public ChartLeadModel getCollectionCount(List<PartnerCollectionPlanModel> pcpm) throws ProfitMandiBusinessException {
30522 tejbeer 1902
 
32464 tejbeer 1903
        Map<Integer, Long> rankCount = pcpm.stream().collect(Collectors.groupingBy(x -> x.getRank(), Collectors.mapping(PartnerCollectionPlanModel::getRank, Collectors.counting())));
30522 tejbeer 1904
 
32464 tejbeer 1905
        ChartLeadModel cm = new ChartLeadModel();
30522 tejbeer 1906
 
32464 tejbeer 1907
        List<String> labels = new ArrayList<>();
1908
        labels.add("Plan for Today");
1909
        labels.add("Carry Forward");
1910
        labels.add("Untouched");
1911
        labels.add("Plan for Future");
1912
        labels.add("Normal");
30522 tejbeer 1913
 
32464 tejbeer 1914
        List<String> backgroundColor = new ArrayList<>();
1915
        List<Long> values = new ArrayList<>();
30522 tejbeer 1916
 
32464 tejbeer 1917
        for (String label : labels) {
30522 tejbeer 1918
 
32464 tejbeer 1919
            if (label.equals("Plan for Today")) {
1920
                backgroundColor.add("#007bff");
1921
                values.add(rankCount.get(1));
1922
            }
1923
            if (label.equals("Carry Forward")) {
1924
                backgroundColor.add("#ffc107");
1925
                values.add(rankCount.get(2));
1926
            }
1927
            if (label.equals("Untouched")) {
1928
                backgroundColor.add("#dc3545");
1929
                values.add(rankCount.get(3));
1930
            }
1931
            if (label.equals("Plan for Future")) {
1932
                backgroundColor.add("#6c757d");
1933
                values.add(rankCount.get(4));
1934
            }
1935
            if (label.equals("Normal")) {
1936
                backgroundColor.add("White");
1937
                values.add(rankCount.get(5));
1938
            }
30522 tejbeer 1939
 
32464 tejbeer 1940
        }
30522 tejbeer 1941
 
32464 tejbeer 1942
        LOGGER.info("backgroundColor" + backgroundColor);
1943
        LOGGER.info("labelsChartLead" + labels);
1944
        LeadStatusData data = new LeadStatusData();
1945
        data.setData(values);
1946
        data.setBackgroundColor(backgroundColor);
1947
        data.setLabel("DataSet 1");
30522 tejbeer 1948
 
32464 tejbeer 1949
        PieLables label = new PieLables();
1950
        label.setFontColor("black");
1951
        label.setFontSize(15);
30522 tejbeer 1952
 
32464 tejbeer 1953
        Legend legend = new Legend();
1954
        legend.setLabels(label);
1955
        legend.setPosition("left");
30522 tejbeer 1956
 
32464 tejbeer 1957
        List<LeadStatusData> dataList = new ArrayList<>();
1958
        dataList.add(data);
30522 tejbeer 1959
 
32464 tejbeer 1960
        DataLeadModel datasets = new DataLeadModel();
1961
        datasets.setDatasets(dataList);
1962
        datasets.setLabels(labels);
30522 tejbeer 1963
 
32464 tejbeer 1964
        OptionModel om = new OptionModel();
1965
        om.setLegend(legend);
30522 tejbeer 1966
 
32464 tejbeer 1967
        cm.setType("pie");
1968
        cm.setData(datasets);
1969
        cm.setOptions(om);
30522 tejbeer 1970
 
32464 tejbeer 1971
        return cm;
1972
    }
30522 tejbeer 1973
 
32464 tejbeer 1974
    @RequestMapping(value = "/franchiseVisit", method = RequestMethod.GET)
1975
    public String franchiseVisit(HttpServletRequest request, @RequestParam(name = "email", required = false) String email, Model model) throws Exception {
1976
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
30522 tejbeer 1977
 
32464 tejbeer 1978
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
30522 tejbeer 1979
 
32464 tejbeer 1980
        List<Integer> salesPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_SALES).stream().map(x -> x.getAuthUserId()).collect(Collectors.toList());
1981
        List<Integer> rbmPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_RBM).stream().map(x -> x.getAuthUserId()).collect(Collectors.toList());
30522 tejbeer 1982
 
32464 tejbeer 1983
        salesPositionsAuthIds.addAll(rbmPositionsAuthIds);
30522 tejbeer 1984
 
32464 tejbeer 1985
        List<Integer> allReportees = authService.getAllReportees(authUser.getId());
30522 tejbeer 1986
 
32464 tejbeer 1987
        Set<Integer> empHierarchy = allReportees.stream().filter(x -> salesPositionsAuthIds.contains(x)).collect(Collectors.toSet());
30522 tejbeer 1988
 
35395 amit 1989
        List<AuthUser> authUsers = authRepository.selectByIds(new ArrayList<>(empHierarchy));
30522 tejbeer 1990
 
32464 tejbeer 1991
        Map<Integer, String> monthValueMap = new HashMap<>();
1992
        for (int i = 0; i <= 5; i++) {
1993
            LocalDateTime startOfMonth = LocalDateTime.now().withDayOfMonth(1).minusMonths(i);
1994
            monthValueMap.put(i, startOfMonth.format(DateTimeFormatter.ofPattern("MMM''uu")));
1995
        }
30522 tejbeer 1996
 
32464 tejbeer 1997
        model.addAttribute("authUsers", authUsers);
1998
        model.addAttribute("monthValueMap", monthValueMap);
30522 tejbeer 1999
 
32464 tejbeer 2000
        return "franchise-visit";
30522 tejbeer 2001
 
32464 tejbeer 2002
    }
30522 tejbeer 2003
 
32464 tejbeer 2004
    @RequestMapping(value = "/getFranchiseVisit", method = RequestMethod.GET)
2005
    public String getFranchiseVisit(HttpServletRequest request, @RequestParam(name = "authId", required = false) int authId, int yearMonth, Model model) throws Exception {
30522 tejbeer 2006
 
32464 tejbeer 2007
        LocalDateTime startDate = LocalDate.now().minusMonths(8).withDayOfMonth(1).atStartOfDay();
2008
        LocalDateTime endDate = startDate.plusMonths(1).withDayOfMonth(1).toLocalDate().atStartOfDay();
30522 tejbeer 2009
 
32464 tejbeer 2010
        DateRangeModel drm = DateRangeModel.of(startDate, endDate);
30522 tejbeer 2011
 
32464 tejbeer 2012
        List<FranchiseeVisit> visits = franchiseeVisitRepository.selectByAuthUserAndDateRange(drm, authId);
30522 tejbeer 2013
 
32464 tejbeer 2014
        if (!visits.isEmpty()) {
30522 tejbeer 2015
 
32464 tejbeer 2016
            Map<Integer, List<FranchiseeVisit>> franchiseeVisitMap = visits.stream().collect(Collectors.groupingBy(x -> x.getScheduleTimestamp().getDayOfMonth()));
30522 tejbeer 2017
 
32464 tejbeer 2018
            model.addAttribute("franchiseeVisitMap", franchiseeVisitMap);
30522 tejbeer 2019
 
32464 tejbeer 2020
        }
30771 amit.gupta 2021
 
32464 tejbeer 2022
        model.addAttribute("visits", visits);
2023
        model.addAttribute("monthLength", startDate.toLocalDate().lengthOfMonth());
30771 amit.gupta 2024
 
32464 tejbeer 2025
        // Calender
30771 amit.gupta 2026
 
32464 tejbeer 2027
        int Year = startDate.getYear(); // year
2028
        int startDayOfMonth = 5;
2029
        int spaces = startDayOfMonth;
30771 amit.gupta 2030
 
32464 tejbeer 2031
        int month = startDate.getMonthValue();
30771 amit.gupta 2032
 
32464 tejbeer 2033
        int[] days = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
30771 amit.gupta 2034
 
32464 tejbeer 2035
        LOGGER.info("visits {} ", visits);
30771 amit.gupta 2036
 
32464 tejbeer 2037
        if ((((Year % 4 == 0) && (Year % 100 != 0)) || (Year % 400 == 0)) && month == 2) {
2038
            days[month] = 29;
2039
        }
30771 amit.gupta 2040
 
32464 tejbeer 2041
        spaces = (days[month - 1] + spaces) % 7;
30771 amit.gupta 2042
 
32464 tejbeer 2043
        model.addAttribute("month", month);
2044
        model.addAttribute("spaces", spaces);
2045
        model.addAttribute("days", days);
30771 amit.gupta 2046
 
32464 tejbeer 2047
        return "franchise-visit-container";
30771 amit.gupta 2048
 
32464 tejbeer 2049
    }
31249 tejbeer 2050
 
32464 tejbeer 2051
    @RequestMapping(value = "/getFranchiseeActivity", method = RequestMethod.GET)
2052
    public String getFranchiseeActivity(HttpServletRequest request, int visitId, Model model) throws Exception {
31249 tejbeer 2053
 
32464 tejbeer 2054
        List<FranchiseeActivity> franchiseeActivities = franchiseeActivityRepository.selectByFranchiseeVisitId(visitId);
31249 tejbeer 2055
 
32464 tejbeer 2056
        FranchiseeVisit franchiseeVisit = franchiseeVisitRepository.selectById(visitId);
31249 tejbeer 2057
 
32464 tejbeer 2058
        Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectAll().stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
2059
        model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
31249 tejbeer 2060
 
32464 tejbeer 2061
        model.addAttribute("franchiseeVisit", franchiseeVisit);
2062
        model.addAttribute("franchiseeActivity", franchiseeActivities.get(0));
31249 tejbeer 2063
 
32464 tejbeer 2064
        return "franchie-visit-detail";
31249 tejbeer 2065
 
32464 tejbeer 2066
    }
31249 tejbeer 2067
 
32464 tejbeer 2068
    @RequestMapping(value = "/indent/today_target", method = RequestMethod.GET)
2069
    public String todayTarget(HttpServletRequest request, Model model) throws Exception {
2070
        List<RBMPerformanceSummaryModel> summaryModels = new ArrayList<>();
2071
        List<Integer> rbmPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_RBM).stream().filter(x -> Arrays.asList(EscalationType.L1, EscalationType.L2).contains(x.getEscalationType())).map(x -> x.getAuthUserId()).distinct().collect(Collectors.toList());
2072
        Map<String, Set<Integer>> storeGuyMap = csService.getAuthUserPartnerIdMapping();
2073
        List<TeamCommitmentModel> teamCommitmentModels = partnerCollectionPlanRepository.selectTeamCommitmentByDate(LocalDate.now());
2074
        Map<Integer, Double> rbmSecondaryTargetMap = teamCommitmentModels.stream().filter(x -> rbmPositionsAuthIds.contains(x.getAuthId())).collect(Collectors.groupingBy(x -> x.getAuthId(), Collectors.summingDouble(x -> x.getTotalTarget() == null ? 0 : x.getTotalTarget())));
2075
        Map<Integer, Double> rbmSecondaryMap = teamCommitmentModels.stream().filter(x -> rbmPositionsAuthIds.contains(x.getAuthId())).collect(Collectors.groupingBy(x -> x.getAuthId(), Collectors.summingDouble(x -> x.getTotalAchievement() == null ? 0 : x.getTotalAchievement())));
2076
        LocalDateTime startDate = LocalDate.now().atStartOfDay();
2077
        for (int rbmAuthId : rbmPositionsAuthIds) {
2078
            RBMPerformanceSummaryModel rbmPerformanceSummaryModel = new RBMPerformanceSummaryModel();
2079
            rbmPerformanceSummaryModel.setAuthId(rbmAuthId);
2080
            AuthUser authUser = authRepository.selectById(rbmAuthId);
2081
            rbmPerformanceSummaryModel.setAuthName(authUser.getFullName());
33844 ranu 2082
            List<Integer> fofoIds = new ArrayList<>(storeGuyMap.get(authUser.getEmailId()));
31249 tejbeer 2083
 
32464 tejbeer 2084
            if (fofoIds.size() > 0) {
2085
                fofoIds = fofoStoreRepository.selectByRetailerIds(fofoIds).stream().filter(x -> !x.isInternal()).map(x -> x.getId()).collect(Collectors.toList());
31249 tejbeer 2086
 
32464 tejbeer 2087
                /*
2088
                 * Map<Integer, PartnerCollectionPlanModel> foundCollectionMap =
2089
                 * partnerCollectionService .getCollectionMap(fofoIds, startDate);
2090
                 */
31249 tejbeer 2091
 
33844 ranu 2092
                List<Integer> remarkIds = partnerCollectionRemarkRepository.selectMaxRemarkId(fofoIds);
2093
 
32464 tejbeer 2094
                LOGGER.info("remarkIds {}", remarkIds);
31249 tejbeer 2095
 
32464 tejbeer 2096
                long todayOverallCall = 0;
2097
                if (!remarkIds.isEmpty()) {
2098
                    todayOverallCall = partnerCollectionRemarkRepository.selectByIds(remarkIds).stream().filter(x -> x.getCreateTimestamp().toLocalDate().equals(LocalDate.now())).collect(Collectors.counting());
31249 tejbeer 2099
 
32464 tejbeer 2100
                }
31249 tejbeer 2101
 
32464 tejbeer 2102
                Map<Integer, PartnerCollectionPlanModel> collectionMap = partnerCollectionService.getCollectionMap(fofoIds, startDate);
31249 tejbeer 2103
 
32464 tejbeer 2104
                ChartLeadModel cm = this.getCollectionCount(collectionMap.values().stream().collect(Collectors.toList()));
31249 tejbeer 2105
 
32464 tejbeer 2106
                long collectionTarget = collectionMap.values().stream().filter(x -> x.getTargetPlan() != null).collect(Collectors.summingLong(x -> x.getTargetPlan()));
2107
                long collection = collectionMap.values().stream().filter(
2108
                        x -> x.getTargetPlan() != null && x.getTargetPlan() != 0 && x.getAchievementPlan() != null).collect(Collectors.summingLong(x -> x.getAchievementPlan()));
2109
                rbmPerformanceSummaryModel.setChartLeadModel(cm);
2110
                rbmPerformanceSummaryModel.setPartnersCommunicated(todayOverallCall);
2111
                rbmPerformanceSummaryModel.setCollectionTarget(collectionTarget);
2112
                rbmPerformanceSummaryModel.setCollection(collection);
2113
                rbmPerformanceSummaryModel.setSecondaryTarget(rbmSecondaryTargetMap.get(rbmAuthId) == null ? 0 : rbmSecondaryTargetMap.get(rbmAuthId).floatValue());
2114
                rbmPerformanceSummaryModel.setSecondary(
2115
                        rbmSecondaryMap.get(rbmAuthId) == null ? 0 : rbmSecondaryMap.get(rbmAuthId).floatValue());
2116
                summaryModels.add(rbmPerformanceSummaryModel);
2117
                // cm.getData().getDatasets().get(0).getData().;
2118
                // cm.getData().getDatasets().get(0).getBackgroundColor();
2119
                // cm.getData().getLabels()
31249 tejbeer 2120
 
32464 tejbeer 2121
            }
2122
        }
2123
        model.addAttribute("summaryModels", summaryModels);
2124
        return "today_target";
2125
    }
31249 tejbeer 2126
 
32464 tejbeer 2127
    @RequestMapping(value = "/visitPlan", method = RequestMethod.GET)
2128
    public String visitPlan(HttpServletRequest request, Model model) throws Exception {
31249 tejbeer 2129
 
32464 tejbeer 2130
        return "visit-request-plan";
2131
    }
31249 tejbeer 2132
 
32464 tejbeer 2133
    @RequestMapping(value = "/visit/getVisitPlan", method = RequestMethod.GET)
2134
    public String getVisitPlan(HttpServletRequest request, @RequestParam LocalDate date, Model model) throws Exception {
2135
        List<VisitRequest> visitRequests = visitRequestRepository.selectByAuthIdAndDate(date);
31249 tejbeer 2136
 
32464 tejbeer 2137
        List<Integer> leadIds = visitRequests.stream().filter(x -> x.getVisitType().equals("lead")).map(x -> x.getVisitId()).collect(Collectors.toList());
2138
        Map<Integer, Lead> leadMap = new HashMap<>();
2139
        if (!leadIds.isEmpty()) {
2140
            List<Lead> leads = leadRepository.selectAllByIds(leadIds);
31249 tejbeer 2141
 
32464 tejbeer 2142
            for (Lead lead : leads) {
2143
                List<LeadActivity> leadActivities = leadActivityRepository.selectBYLeadId(lead.getId());
2144
                lead.setScheduledTimestamp(leadActivities.get(0).getSchelduleTimestamp());
2145
                lead.setLeadActivity(leadActivities.get(0));
31249 tejbeer 2146
 
32464 tejbeer 2147
                leadMap.put(lead.getId(), lead);
2148
            }
31249 tejbeer 2149
 
32464 tejbeer 2150
        }
2151
        List<Integer> franchiseeIds = visitRequests.stream().filter(x -> x.getVisitType().equals("franchiseeVisit")).map(x -> x.getVisitId()).collect(Collectors.toList());
2152
        Map<Integer, FranchiseeVisit> franchiseeVisitsMap = new HashMap<>();
2153
        if (!franchiseeIds.isEmpty()) {
2154
            List<FranchiseeVisit> franchiseeVisits = franchiseeVisitRepository.selectAllByIds(franchiseeIds);
2155
            LOGGER.info("franchiseeVisits {}", franchiseeVisits);
31249 tejbeer 2156
 
32464 tejbeer 2157
            for (FranchiseeVisit franchiseeVisit : franchiseeVisits) {
2158
                List<FranchiseeActivity> franchiseeActivities = franchiseeActivityRepository.selectByFranchiseeVisitId(franchiseeVisit.getId());
2159
                LOGGER.info("franchiseeActivities {}", franchiseeActivities);
2160
 
2161
                franchiseeVisit.setScheduleTimestamp(franchiseeActivities.get(0).getSchelduleTimestamp());
2162
                franchiseeVisit.setFranchiseeActivity(franchiseeActivities.get(0));
2163
 
2164
                franchiseeVisitsMap.put(franchiseeVisit.getId(), franchiseeVisit);
2165
            }
2166
 
2167
        }
2168
 
2169
        Map<Integer, List<VisitRequest>> visitRequestMap = visitRequests.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy()));
2170
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
2171
        List<UserVisitModel> userVisits = new ArrayList<>();
2172
 
2173
        for (AuthUser authUser : authUsers) {
2174
 
2175
            List<VisitRequest> authVisitRequests = visitRequestMap.get(authUser.getId());
2176
 
2177
            if (authVisitRequests != null) {
2178
                UserVisitModel userVisitModel = new UserVisitModel();
2179
                userVisitModel.setAuthUser(authUser.getFullName());
2180
                List<VisitDescriptionModel> visitDescriptions = new ArrayList<>();
2181
 
2182
                for (VisitRequest authVisitRequest : authVisitRequests) {
2183
                    VisitDescriptionModel visitDescriptionModel = new VisitDescriptionModel();
2184
                    visitDescriptionModel.setVisitId(authVisitRequest.getVisitId());
2185
 
2186
                    if (authVisitRequest.getVisitType().equals("lead")) {
2187
                        Lead lead = leadMap.get(authVisitRequest.getVisitId());
2188
 
2189
                        visitDescriptionModel.setVisitName(lead.getFirstName());
2190
                        visitDescriptionModel.setCity(lead.getCity());
2191
                        visitDescriptionModel.setState(lead.getState());
2192
                        visitDescriptionModel.setScheduleTime(lead.getScheduledTimestamp());
2193
                        visitDescriptionModel.setRemarks(lead.getLeadActivity().getRemark());
2194
 
2195
                    } else {
2196
                        FranchiseeVisit franchiseeVisit = franchiseeVisitsMap.get(authVisitRequest.getVisitId());
2197
                        CustomRetailer customRetailer = retailerService.getFofoRetailer(franchiseeVisit.getFofoId());
2198
 
2199
                        visitDescriptionModel.setVisitName(franchiseeVisit.getPartnerName());
2200
                        visitDescriptionModel.setCity(customRetailer.getAddress().getCity());
2201
                        visitDescriptionModel.setState(customRetailer.getAddress().getState());
2202
                        visitDescriptionModel.setScheduleTime(franchiseeVisit.getFranchiseeActivity().getSchelduleTimestamp());
2203
                        visitDescriptionModel.setRemarks(franchiseeVisit.getAgenda());
2204
 
2205
                    }
2206
 
2207
                    if (authVisitRequest.getActionedBy() != 0) {
2208
                        AuthUser au = authRepository.selectById(authVisitRequest.getActionedBy());
2209
 
2210
                        visitDescriptionModel.setActionBy(au.getFullName());
2211
                    }
2212
                    visitDescriptionModel.setStatus(authVisitRequest.getStatus());
2213
                    visitDescriptionModel.setVisitType(authVisitRequest.getVisitType());
2214
                    visitDescriptions.add(visitDescriptionModel);
2215
                }
2216
 
2217
                userVisitModel.setVisitDescriptions(visitDescriptions);
2218
                userVisits.add(userVisitModel);
2219
            }
2220
 
2221
        }
2222
 
2223
        model.addAttribute("userVisits", userVisits);
2224
 
2225
        return "visit-request-plan";
2226
    }
25979 tejbeer 2227
}