Subversion Repositories SmartDukaan

Rev

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