Subversion Repositories SmartDukaan

Rev

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

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