Subversion Repositories SmartDukaan

Rev

Rev 36401 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
24417 govind 1
package com.spice.profitmandi.web.controller;
2
 
3
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
4
import com.spice.profitmandi.common.model.CustomRetailer;
32812 shampa 5
import com.spice.profitmandi.common.model.ProfitMandiConstants;
24417 govind 6
import com.spice.profitmandi.dao.entity.auth.AuthUser;
27690 amit.gupta 7
import com.spice.profitmandi.dao.entity.cs.*;
36040 ranu 8
import com.spice.profitmandi.dao.entity.cs.TicketReadStatus.UserType;
27270 tejbeer 9
import com.spice.profitmandi.dao.entity.dtr.Document;
24417 govind 10
import com.spice.profitmandi.dao.entity.fofo.ActivityType;
11
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
24699 govind 12
import com.spice.profitmandi.dao.enumuration.cs.TicketStatus;
25570 tejbeer 13
import com.spice.profitmandi.dao.model.CreatePositionModel;
24417 govind 14
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
27690 amit.gupta 15
import com.spice.profitmandi.dao.repository.cs.*;
27270 tejbeer 16
import com.spice.profitmandi.dao.repository.dtr.DocumentRepository;
25570 tejbeer 17
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
24417 govind 18
import com.spice.profitmandi.service.authentication.RoleManager;
36040 ranu 19
import com.spice.profitmandi.service.mail.MailOutboxService;
24417 govind 20
import com.spice.profitmandi.service.user.RetailerService;
21
import com.spice.profitmandi.web.model.LoginDetails;
22
import com.spice.profitmandi.web.util.CookiesProcessor;
23
import com.spice.profitmandi.web.util.MVCResponseSender;
27690 amit.gupta 24
import org.apache.logging.log4j.LogManager;
25
import org.apache.logging.log4j.Logger;
26
import org.springframework.beans.factory.annotation.Autowired;
27
import org.springframework.mail.javamail.JavaMailSender;
28
import org.springframework.stereotype.Controller;
29
import org.springframework.transaction.annotation.Transactional;
30
import org.springframework.ui.Model;
31
import org.springframework.web.bind.annotation.*;
24417 govind 32
 
27690 amit.gupta 33
import javax.servlet.http.HttpServletRequest;
36040 ranu 34
import javax.swing.*;
27690 amit.gupta 35
import java.time.LocalDateTime;
36
import java.util.*;
37
import java.util.stream.Collectors;
38
 
24417 govind 39
@Controller
40
@Transactional(rollbackFor = Throwable.class)
41
public class CsController {
42
 
31762 tejbeer 43
    private static final Logger LOGGER = LogManager.getLogger(CsController.class);
44
    private static final String ACTIVITY_SUBJECT = "Message related ticketId#%s";
45
    private static final String PARTNER_RESOLVED_TICKET_MAIL = "Dear Partner , we have resolved your ticket # %s , request to kindly accept the same. In case you still have any concerns regarding the same pls click on %s so that we can help you.Regards\nSmartdukaan";
46
    private static final String PARTNER_REOPEN = "Dear Partner , Your ticket # %s has been re-opened as per your confirmation & we are committed to resolve it on priority.Regards\nSmartdukaan";
47
    private static final String INTERNAL_REOPEN_MAIL = "Team, Pls note that the Ticket Id %s has been re-opened by %s , pls respond on priority";
48
    private static final String INTERNAL_REOPEN_ACTIVITY_MESSAGE = "Hi,My ticket is not resolved yet,so I have reopened it";
24699 govind 49
 
31762 tejbeer 50
    @Autowired
36401 amit 51
    JavaMailSender gmailRelaySender;
24620 govind 52
 
31762 tejbeer 53
    @Autowired
35957 amit 54
    MailOutboxService mailOutboxService;
55
 
56
    @Autowired
31762 tejbeer 57
    private CsService csService;
24417 govind 58
 
31762 tejbeer 59
    @Autowired
60
    private CookiesProcessor cookiesProcessor;
24417 govind 61
 
31762 tejbeer 62
    @Autowired
63
    private TicketCategoryRepository ticketCategoryRepository;
24417 govind 64
 
31762 tejbeer 65
    @Autowired
66
    private TicketSubCategoryRepository ticketSubCategoryRepository;
24417 govind 67
 
31762 tejbeer 68
    @Autowired
69
    private RegionRepository regionRepository;
24417 govind 70
 
31762 tejbeer 71
    @Autowired
72
    private RetailerService retailerService;
24417 govind 73
 
31762 tejbeer 74
    @Autowired
75
    private MVCResponseSender mvcResponseSender;
24417 govind 76
 
31762 tejbeer 77
    @Autowired
78
    private AuthRepository authRepository;
24417 govind 79
 
31762 tejbeer 80
    @Autowired
81
    private PositionRepository positionRepository;
24417 govind 82
 
31762 tejbeer 83
    @Autowired
84
    private TicketRepository ticketRepository;
24417 govind 85
 
31762 tejbeer 86
    @Autowired
87
    private RoleManager roleManager;
24417 govind 88
 
31762 tejbeer 89
    @Autowired
90
    private ActivityRepository activityRepository;
24417 govind 91
 
31762 tejbeer 92
    @Autowired
93
    private ActivityAttachmentRepository activityAttachmentRepository;
27270 tejbeer 94
 
31762 tejbeer 95
    @Autowired
96
    private TicketAssignedRepository ticketAssignedRepository;
24569 govind 97
 
31762 tejbeer 98
    @Autowired
99
    private PartnerRegionRepository partnerRegionRepository;
24500 govind 100
 
31762 tejbeer 101
    @Autowired
32493 amit.gupta 102
    PartnerPositionRepository partnerPositionRepository;
25570 tejbeer 103
 
31762 tejbeer 104
    @Autowired
105
    FofoStoreRepository fofoStoreRepository;
25570 tejbeer 106
 
31762 tejbeer 107
    @Autowired
108
    DocumentRepository documentRepository;
27270 tejbeer 109
 
31762 tejbeer 110
    @GetMapping(value = "/cs/createCategory")
111
    public String getCreateCategory(HttpServletRequest request, Model model) {
112
        List<TicketCategory> ticketCategories = ticketCategoryRepository.selectAll();
113
        model.addAttribute("ticketCategories", ticketCategories);
114
        return "create-ticket-category";
115
    }
24417 govind 116
 
31762 tejbeer 117
    @PostMapping(value = "/cs/createCategory")
33081 ranu 118
    public String createCategory(HttpServletRequest request,
119
                                 @RequestParam(name = "name") String name,
120
                                 @RequestParam(name = "categoryType") int categoryType,
121
                                 @RequestParam(name = "description") String description,
122
                                 Model model) throws ProfitMandiBusinessException {
31762 tejbeer 123
        TicketCategory ticketCategory = ticketCategoryRepository.selectByName(name);
124
        if (ticketCategory != null) {
125
            throw new ProfitMandiBusinessException("name", name, "already exists!");
126
        }
33081 ranu 127
 
31762 tejbeer 128
        ticketCategory = new TicketCategory();
129
        ticketCategory.setName(name);
130
        ticketCategory.setDescription(description);
33081 ranu 131
 
132
        ticketCategory.setCategoryType(categoryType == 1);
31762 tejbeer 133
        ticketCategoryRepository.persist(ticketCategory);
134
        return "create-ticket-category";
135
    }
24417 govind 136
 
33081 ranu 137
 
31762 tejbeer 138
    @GetMapping(value = "/cs/createSubCategory")
139
    public String getCreateSubCategory(HttpServletRequest request, Model model) {
140
        List<TicketCategory> ticketCategories = ticketCategoryRepository.selectAll();
141
        model.addAttribute("ticketCategories", ticketCategories);
142
        return "create-ticket-sub-category";
143
    }
24417 govind 144
 
31762 tejbeer 145
    @GetMapping(value = "/cs/getSubCategoryByCategoryId")
146
    public String getSubCategoryByCategoryId(HttpServletRequest request, @RequestParam(name = "ticketCategoryId", defaultValue = "") int ticketCategoryId, Model model) {
147
        List<TicketSubCategory> ticketSubCategories = ticketSubCategoryRepository.selectAll(ticketCategoryId);
148
        TicketCategory ticketCategory = ticketCategoryRepository.selectById(ticketCategoryId);
33081 ranu 149
        LOGGER.info("ticketSubCategories {}", ticketSubCategories);
150
        LOGGER.info("ticketCategory {}", ticketCategory);
31762 tejbeer 151
        model.addAttribute("ticketSubCategories", ticketSubCategories);
152
        model.addAttribute("ticketCategory", ticketCategory);
153
        return "ticket-sub-category";
154
    }
24417 govind 155
 
31762 tejbeer 156
    @PostMapping(value = "/cs/createSubCategory")
157
    public String createSubCategory(HttpServletRequest request, @RequestParam(name = "categoryId", defaultValue = "0") int categoryId, @RequestParam(name = "name") String name, @RequestParam(name = "description") String description, Model model) throws ProfitMandiBusinessException {
24417 govind 158
 
31762 tejbeer 159
        TicketSubCategory ticketSubCategory = ticketSubCategoryRepository.selectTicketSubCategory(categoryId, name);
160
        if (ticketSubCategory != null) {
161
            throw new ProfitMandiBusinessException("name & categoryId", name + "  " + categoryId, "already exists!");
162
        }
24417 govind 163
 
31762 tejbeer 164
        ticketSubCategory = new TicketSubCategory();
165
        ticketSubCategory.setCategoryId(categoryId);
166
        ticketSubCategory.setName(name);
167
        ticketSubCategory.setDescription(description);
168
        ticketSubCategoryRepository.persist(ticketSubCategory);
169
        return "create-ticket-sub-category";
170
    }
24417 govind 171
 
31762 tejbeer 172
    @GetMapping(value = "/cs/createRegion")
173
    public String createRegion(HttpServletRequest request, Model model) {
174
        List<Region> regions = regionRepository.selectAll();
175
        model.addAttribute("regions", regions);
176
        return "create-region";
177
    }
24417 govind 178
 
31762 tejbeer 179
    @PostMapping(value = "/cs/createRegion")
180
    public String createRegion(HttpServletRequest request, @RequestParam(name = "name") String name, @RequestParam(name = "description") String description, Model model) throws Exception {
181
        Region region = regionRepository.selectByName(name);
182
        if (region != null) {
183
            throw new ProfitMandiBusinessException("name", name, "already exists!");
184
        }
185
        region = new Region();
186
        region.setName(name);
187
        region.setDescription(description);
188
        regionRepository.persist(region);
189
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
190
        return "response";
191
    }
24417 govind 192
 
31762 tejbeer 193
    @GetMapping(value = "/cs/getPartners")
33244 ranu 194
    public String getPartners(HttpServletRequest request, @RequestParam(name = "regionId", defaultValue = "0") int regionId, Model model) throws ProfitMandiBusinessException {
31762 tejbeer 195
        List<Integer> fofoIds = fofoStoreRepository.selectAll().stream().map(x -> x.getId()).collect(Collectors.toList());
196
        List<Integer> addedfofoIds = partnerRegionRepository.selectByRegionId(regionId).stream().map(x -> x.getFofoId()).collect(Collectors.toList());
30426 tejbeer 197
 
31762 tejbeer 198
        Map<Integer, CustomRetailer> customRetailerMap = retailerService.getAllFofoRetailers();
199
        Map<Integer, CustomRetailer> fofoRetailers = fofoIds.stream().map(x -> customRetailerMap.get(x)).filter(x -> x != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(x -> x.getPartnerId(), x -> x));
200
        model.addAttribute("fofoRetailers", fofoRetailers);
201
        model.addAttribute("addedfofoIds", addedfofoIds);
202
        return "added-region-partners";
203
    }
24569 govind 204
 
31762 tejbeer 205
    @GetMapping(value = "/cs/getPartnersByRegion")
33244 ranu 206
    public String getPartnersByRegion(HttpServletRequest request, @RequestParam(name = "regionId", defaultValue = "0") int regionId, Model model) throws ProfitMandiBusinessException {
31762 tejbeer 207
        List<Integer> fofoIds = null;
208
        fofoIds = partnerRegionRepository.selectByRegionId(regionId).stream().map(x -> x.getFofoId()).collect(Collectors.toList());
25570 tejbeer 209
 
31762 tejbeer 210
        if (fofoIds.contains(0)) {
211
            fofoIds = fofoStoreRepository.selectAll().stream().filter(x -> x.isActive()).collect(Collectors.toList()).stream().map(x -> x.getId()).collect(Collectors.toList());
25570 tejbeer 212
 
31762 tejbeer 213
        }
214
        Map<Integer, CustomRetailer> customRetailerMap = retailerService.getAllFofoRetailers();
25570 tejbeer 215
 
31762 tejbeer 216
        Map<Integer, CustomRetailer> fofoRetailers = fofoIds.stream().map(x -> customRetailerMap.get(x)).filter(x -> x != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(x -> x.getPartnerId(), x -> x));
217
        model.addAttribute("fofoRetailers", fofoRetailers);
218
        return "added-subregion-partners";
219
    }
25570 tejbeer 220
 
31762 tejbeer 221
    @GetMapping(value = "/cs/createPartnerRegion")
222
    public String createPartnerRegion(HttpServletRequest request, Model model) {
223
        List<Region> regions = regionRepository.selectAll();
224
        model.addAttribute("regions", regions);
225
        return "create-partner-region";
226
    }
24417 govind 227
 
31762 tejbeer 228
    @PostMapping(value = "/cs/createPartnerRegion")
229
    public String createPartnerRegion(HttpServletRequest request, @RequestParam(name = "regionId") int regionId, @RequestBody List<Integer> selectedFofoIds, Model model) throws Exception {
230
        partnerRegionRepository.delete(regionId);
231
        LOGGER.info("successfully removed");
232
        LOGGER.info(selectedFofoIds.size());
233
        csService.addPartnerToRegion(regionId, selectedFofoIds);
234
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
235
        return "response";
236
    }
24417 govind 237
 
31762 tejbeer 238
    @GetMapping(value = "/cs/getPosition")
33244 ranu 239
    public String getPosition(HttpServletRequest request, @RequestParam int positionId, Model model) throws ProfitMandiBusinessException {
27410 tejbeer 240
 
31762 tejbeer 241
        Position position = positionRepository.selectById(positionId);
27410 tejbeer 242
 
31762 tejbeer 243
        List<CustomRetailer> positionIdCustomRetailer = csService.getPositionCustomRetailerMap(Arrays.asList(position)).get(position.getId());
27410 tejbeer 244
 
31762 tejbeer 245
        Map<Integer, CustomRetailer> regionRetailerMap = csService.getRegionPartners(Arrays.asList(position)).get(position.getRegionId()).stream().collect(Collectors.toMap(x -> x.getPartnerId(), x -> x));
27410 tejbeer 246
 
31762 tejbeer 247
        model.addAttribute("position", position);
248
        model.addAttribute("regionRetailerMap", regionRetailerMap);
249
        model.addAttribute("positionIdCustomRetailer", positionIdCustomRetailer);
27410 tejbeer 250
 
31762 tejbeer 251
        return "position-partner";
252
    }
27410 tejbeer 253
 
31762 tejbeer 254
    @GetMapping(value = "/cs/createPosition")
255
    public String createPosition(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, Model model) {
256
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
257
        List<TicketCategory> ticketCategories = ticketCategoryRepository.selectAll();
258
        List<Region> regions = regionRepository.selectAll();
259
        model.addAttribute("escalationTypes", EscalationType.values());
260
        model.addAttribute("authUsers", authUsers);
261
        model.addAttribute("ticketCategories", ticketCategories);
262
        model.addAttribute("regions", regions);
24500 govind 263
 
31762 tejbeer 264
        List<Position> positions = positionRepository.selectAllPosition();
265
        LOGGER.info("positions" + positions);
30426 tejbeer 266
 
31762 tejbeer 267
        Map<Integer, AuthUser> authUserIdAndAuthUserMap = csService.getAuthUserIdAndAuthUserMapUsingPositions(positions);
268
        Map<Integer, TicketCategory> categoryIdAndCategoryMap = csService.getCategoryIdAndCategoryUsingPositions(positions);
269
        Map<Integer, Region> regionIdAndRegionMap = csService.getRegionIdAndRegionMap(positions);
25570 tejbeer 270
 
27410 tejbeer 271
//	    Map<Integer, List<CustomRetailer>> positionIdAndpartnerRegionMap = csService
272
//			.getpositionIdAndpartnerRegionMap(positions);
25570 tejbeer 273
 
27410 tejbeer 274
//	     Map<Integer, List<CustomRetailer>> addedpositionIdAndCustomRetailerMap = csService
275
//				.getPositionCustomRetailerMap(positions);
276
//		LOGGER.info("fofoIdAndCustomRetailerMap" + addedpositionIdAndCustomRetailerMap);
24500 govind 277
 
31762 tejbeer 278
        model.addAttribute("start", offset + 1);
30426 tejbeer 279
 
31762 tejbeer 280
        model.addAttribute("positions", positions);
281
        model.addAttribute("authUserIdAndAuthUserMap", authUserIdAndAuthUserMap);
282
        model.addAttribute("categoryIdAndCategoryMap", categoryIdAndCategoryMap);
283
        model.addAttribute("regionIdAndRegionMap", regionIdAndRegionMap);
284
        // model.addAttribute("positionIdAndCustomRetailerMap",
285
        // addedpositionIdAndCustomRetailerMap);
286
        // model.addAttribute("positionIdAndpartnerRegionMap",
27410 tejbeer 287
// positionIdAndpartnerRegionMap);
25570 tejbeer 288
 
31762 tejbeer 289
        return "create-position";
290
    }
24500 govind 291
 
31762 tejbeer 292
    @GetMapping(value = "/cs/position-paginated")
293
    public String positionPaginated(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, Model model) {
24500 govind 294
 
31762 tejbeer 295
        List<Position> positions = positionRepository.selectAll(offset, limit);
296
        Map<Integer, AuthUser> authUserIdAndAuthUserMap = csService.getAuthUserIdAndAuthUserMapUsingPositions(positions);
297
        Map<Integer, TicketCategory> categoryIdAndCategoryMap = csService.getCategoryIdAndCategoryUsingPositions(positions);
298
        Map<Integer, Region> regionIdAndRegionMap = csService.getRegionIdAndRegionMap(positions);
299
        /*
300
         * Map<Integer, List<CustomRetailer>> positionIdAndpartnerRegionMap = csService
301
         * .getpositionIdAndpartnerRegionMap(positions);
302
         * 
303
         * Map<Integer, List<CustomRetailer>> addedpositionIdAndCustomRetailerMap =
304
         * csService .getPositionCustomRetailerMap(positions);
305
         */
25570 tejbeer 306
 
31762 tejbeer 307
        model.addAttribute("positions", positions);
308
        model.addAttribute("authUserIdAndAuthUserMap", authUserIdAndAuthUserMap);
309
        model.addAttribute("categoryIdAndCategoryMap", categoryIdAndCategoryMap);
310
        model.addAttribute("regionIdAndRegionMap", regionIdAndRegionMap);
311
        // model.addAttribute("positionIdAndCustomRetailerMap",
312
        // addedpositionIdAndCustomRetailerMap);
313
        // model.addAttribute("positionIdAndpartnerRegionMap",
314
        // positionIdAndpartnerRegionMap);
25570 tejbeer 315
 
31762 tejbeer 316
        return "position-paginated";
317
    }
24417 govind 318
 
31762 tejbeer 319
    @PostMapping(value = "/cs/createPosition")
320
    public String createPosition(HttpServletRequest request, @RequestBody CreatePositionModel createPositionModel, Model model) throws Exception {
24417 govind 321
 
35570 amit 322
        LOGGER.info("partnerPosition" + createPositionModel.isTicketAssigned());
25570 tejbeer 323
 
35570 amit 324
        // Validate authUserId exists
325
        int authUserId = createPositionModel.getAuthUserId();
326
        if (authUserId <= 0 || authRepository.selectById(authUserId) == null) {
327
            throw new ProfitMandiBusinessException("Position", authUserId, "Invalid authUserId");
328
        }
329
 
330
        // Validate categoryId exists (0 means "All Categories")
331
        int categoryId = createPositionModel.getCategoryId();
332
        if (categoryId > 0 && ticketCategoryRepository.selectById(categoryId) == null) {
333
            throw new ProfitMandiBusinessException("Position", categoryId, "Invalid categoryId");
334
        }
335
 
336
        // Validate regionId exists (0 or 5 typically means "All Partners/Regions")
337
        int regionId = createPositionModel.getRegionId();
338
        if (regionId > 0 && regionId != 5 && regionRepository.selectById(regionId) == null) {
339
            throw new ProfitMandiBusinessException("Position", regionId, "Invalid regionId");
340
        }
341
 
37003 ranu 342
        // Partners are optional — a position can be created for a region that doesn't have
343
        // partners yet (e.g., a newly opened region). Partners can be added later via
344
        // /cs/updatePartnerPosition. When provided, validate the list; when empty, skip.
35570 amit 345
        List<Integer> fofoIds = createPositionModel.getFofoIds();
37003 ranu 346
        boolean hasAllPartners = fofoIds != null && fofoIds.contains(0);
35590 amit 347
        if (hasAllPartners && fofoIds.size() > 1) {
348
            throw new ProfitMandiBusinessException("Position", 0, "Cannot mix 'All Partners' (0) with specific partner IDs");
349
        }
37003 ranu 350
        if (fofoIds != null && !fofoIds.isEmpty() && !hasAllPartners) {
35590 amit 351
            Map<Integer, CustomRetailer> validRetailers = retailerService.getFofoRetailers(false);
352
            for (int fofoId : fofoIds) {
353
                if (!validRetailers.containsKey(fofoId)) {
354
                    throw new ProfitMandiBusinessException("Position", fofoId, "Invalid fofoId");
35570 amit 355
                }
356
            }
357
        }
358
 
359
        Position position = positionRepository.selectPosition(authUserId, categoryId, regionId, createPositionModel.getEscalationType());
31762 tejbeer 360
        if (position == null) {
361
            position = new Position();
35570 amit 362
            position.setAuthUserId(authUserId);
363
            position.setCategoryId(categoryId);
31762 tejbeer 364
            position.setEscalationType(createPositionModel.getEscalationType());
35570 amit 365
            position.setRegionId(regionId);
31762 tejbeer 366
            position.setCreateTimestamp(LocalDateTime.now());
367
            position.setTicketAssignee(createPositionModel.isTicketAssigned());
368
            positionRepository.persist(position);
25570 tejbeer 369
 
35570 amit 370
            if (fofoIds != null) {
371
                for (int fofoId : fofoIds) {
372
                    PartnerPosition partnerPosition = new PartnerPosition();
373
                    partnerPosition.setFofoId(fofoId);
374
                    partnerPosition.setRegionId(regionId);
375
                    partnerPosition.setPositionId(position.getId());
376
                    partnerPositionRepository.persist(partnerPosition);
377
                    LOGGER.info("partnerPosition" + partnerPosition);
378
                }
31762 tejbeer 379
            }
24417 govind 380
 
31762 tejbeer 381
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));
382
        } else {
35570 amit 383
            throw new ProfitMandiBusinessException("Position", authUserId, "already exists!");
31762 tejbeer 384
        }
385
        return "response";
386
    }
25570 tejbeer 387
 
31762 tejbeer 388
    @PostMapping(value = "/cs/updatePartnerPosition")
389
    public String updatePartnerPosition(HttpServletRequest request, @RequestParam(name = "regionId") int regionId, @RequestBody List<Integer> selectedFofoIds, @RequestParam(name = "positionId") int positionId, Model model) throws Exception {
25570 tejbeer 390
 
35571 amit 391
        // Validate positionId exists
392
        Position position = positionRepository.selectById(positionId);
393
        if (position == null) {
394
            throw new ProfitMandiBusinessException("Position", positionId, "Position not found");
395
        }
396
 
397
        // Validate regionId exists (0 or 5 typically means "All Partners/Regions")
398
        if (regionId > 0 && regionId != 5 && regionRepository.selectById(regionId) == null) {
399
            throw new ProfitMandiBusinessException("Position", regionId, "Invalid regionId");
400
        }
401
 
35589 amit 402
        // Validate fofoIds exist (0 means "All Partners")
35590 amit 403
        if (selectedFofoIds == null || selectedFofoIds.isEmpty()) {
404
            throw new ProfitMandiBusinessException("Position", 0, "At least one partner must be specified");
405
        }
406
        boolean hasAllPartners = selectedFofoIds.contains(0);
407
        if (hasAllPartners && selectedFofoIds.size() > 1) {
408
            throw new ProfitMandiBusinessException("Position", 0, "Cannot mix 'All Partners' (0) with specific partner IDs");
409
        }
410
        if (!hasAllPartners) {
35607 amit 411
            // Use direct database query instead of cached retailerService to include newly added partners
412
            Set<Integer> validFofoIds = fofoStoreRepository.selectAll().stream()
413
                    .map(fs -> fs.getId())
414
                    .collect(Collectors.toSet());
35590 amit 415
            for (int fofoId : selectedFofoIds) {
35607 amit 416
                if (!validFofoIds.contains(fofoId)) {
35590 amit 417
                    throw new ProfitMandiBusinessException("Position", fofoId, "Invalid fofoId");
35571 amit 418
                }
419
            }
420
        }
421
 
32493 amit.gupta 422
        partnerPositionRepository.delete(positionId);
35571 amit 423
        if (selectedFofoIds != null) {
424
            for (int fofoId : selectedFofoIds) {
425
                PartnerPosition partnerPosition = new PartnerPosition();
426
                partnerPosition.setFofoId(fofoId);
427
                partnerPosition.setRegionId(regionId);
428
                partnerPosition.setPositionId(positionId);
429
                partnerPositionRepository.persist(partnerPosition);
430
            }
31762 tejbeer 431
        }
25570 tejbeer 432
 
31762 tejbeer 433
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
25570 tejbeer 434
 
31762 tejbeer 435
        return "response";
436
    }
24417 govind 437
 
31762 tejbeer 438
    @GetMapping(value = "/cs/createTicket")
439
    public String createTicket(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
440
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
35594 amit 441
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
442
        boolean isCrmUser = false;
443
 
31762 tejbeer 444
        List<TicketCategory> ticketCategories = csService.getAllTicketCategotyFromSubCategory();
35594 amit 445
 
446
        if (isAdmin) {
447
            AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
448
            isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
449
 
450
            // CRM users should not see Sales and RBM categories
451
            if (isCrmUser) {
452
                ticketCategories = ticketCategories.stream()
453
                        .filter(tc -> tc.getId() != ProfitMandiConstants.TICKET_CATEGORY_SALES
454
                                && tc.getId() != ProfitMandiConstants.TICKET_CATEGORY_RBM)
455
                        .collect(Collectors.toList());
456
            }
35626 amit 457
        } else {
458
            // For partners/customers: hide categories where ALL subcategories are invisible
459
            ticketCategories = ticketCategories.stream()
460
                    .filter(category -> {
461
                        List<TicketSubCategory> subs = ticketSubCategoryRepository.selectAll(category.getId());
462
                        // Keep category if at least one subcategory is visible
463
                        return subs.stream().anyMatch(TicketSubCategory::isVisibility);
464
                    })
465
                    .collect(Collectors.toList());
35594 amit 466
        }
467
 
468
        model.addAttribute("roleType", isAdmin);
31762 tejbeer 469
        model.addAttribute("ticketCategories", ticketCategories);
35594 amit 470
        model.addAttribute("isCrmUser", isCrmUser);
31762 tejbeer 471
        return "create-ticket";
472
    }
24417 govind 473
 
31762 tejbeer 474
    @GetMapping(value = "/cs/getSubCategoriesByCategoryId")
35594 amit 475
    public String getSubCategoriesByCategoryId(HttpServletRequest request, @RequestParam(name = "categoryId", defaultValue = "0") int categoryId, Model model) throws ProfitMandiBusinessException {
476
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
477
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
478
        boolean isCrmUser = false;
479
 
480
        if (isAdmin) {
481
            AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
482
            isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
483
        }
484
 
31830 amit.gupta 485
        List<TicketSubCategory> ticketSubCategories = ticketSubCategoryRepository.selectAllVisible(categoryId);
35594 amit 486
 
35617 amit 487
        // CRM users should not see invisible subcategories
35594 amit 488
        if (isCrmUser) {
489
            ticketSubCategories = ticketSubCategories.stream()
35617 amit 490
                    .filter(TicketSubCategory::isVisibility)
35594 amit 491
                    .collect(Collectors.toList());
492
        }
493
 
31762 tejbeer 494
        LOGGER.info(ticketSubCategories);
495
        model.addAttribute("ticketSubCategories", ticketSubCategories);
496
        return "ticket-sub-categories";
497
    }
24417 govind 498
 
24791 govind 499
 
31762 tejbeer 500
    @GetMapping(value = "/cs/getEscalationTypeByCategoryId")
501
    public String getEscalationTypeByCategoryId(HttpServletRequest request, @RequestParam(name = "categoryId", defaultValue = "0") int categoryId, @RequestParam(name = "authId", defaultValue = "0") int authId, Model model) {
502
        List<Position> positions = positionRepository.selectPositionbyCategoryIdAndAuthId(categoryId, authId);
503
        List<EscalationType> escalationTypes = new ArrayList<>();
24791 govind 504
 
31762 tejbeer 505
        if (!positions.isEmpty()) {
506
            escalationTypes = positions.stream().map(x -> x.getEscalationType()).distinct().collect(Collectors.toList());
507
        }
24620 govind 508
 
31762 tejbeer 509
        LOGGER.info("escalationTypes {}", escalationTypes);
24500 govind 510
 
31762 tejbeer 511
        model.addAttribute("escalationTypes", escalationTypes);
512
        return "ticket-escalationtype";
513
    }
24500 govind 514
 
24824 govind 515
 
31762 tejbeer 516
    @GetMapping(value = "/cs/getCategoriesByAuthId")
517
    public String getCategoriesByAuthId(HttpServletRequest request, @RequestParam(name = "authId", defaultValue = "0") int authId, Model model) {
24824 govind 518
 
24787 govind 519
 
31762 tejbeer 520
        List<Position> positions = positionRepository.selectPositionByAuthId(authId);
24791 govind 521
 
31762 tejbeer 522
        LOGGER.info("positions {}", positions);
24417 govind 523
 
31762 tejbeer 524
        List<TicketCategory> ticketCategories = new ArrayList<TicketCategory>();
24417 govind 525
 
31762 tejbeer 526
        if (!positions.isEmpty()) {
24417 govind 527
 
31762 tejbeer 528
            List<Integer> categoryIds = positions.stream().map(x -> x.getCategoryId()).collect(Collectors.toList());
529
            ticketCategories = ticketCategoryRepository.selectAll(categoryIds);
530
        }
531
        LOGGER.info("ticketCategories {}", ticketCategories);
532
        model.addAttribute("ticketCategories", ticketCategories);
533
        return "ticket-categories";
534
    }
27270 tejbeer 535
 
31762 tejbeer 536
    @PostMapping(value = "/cs/createTicket")
537
    public String createTicket(HttpServletRequest request, @RequestParam(name = "categoryId") int categoryId, @RequestParam(name = "subCategoryId") int subCategoryId, @RequestParam(name = "message") String message, Model model) throws Exception {
538
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
539
        List<Ticket> tickets = ticketRepository.selectAllResolvedMarkedTicketByCreator(loginDetails.getFofoId());
540
        if (tickets.size() > 3 || tickets.size() == 3) {
541
            model.addAttribute("response1", mvcResponseSender.createResponseString(false));
542
        } else {
543
            csService.createTicket(loginDetails.getFofoId(), categoryId, subCategoryId, message);
544
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));
545
        }
546
        return "response";
547
    }
27270 tejbeer 548
 
31762 tejbeer 549
    @GetMapping(value = "/cs/myticket")
35626 amit 550
    public String getTicket(HttpServletRequest request,
551
                            @RequestParam(name = "orderby", defaultValue = "DESCENDING") SortOrder sortOrder,
552
                            @RequestParam(name = "ticketStatus", defaultValue = "OPENED") TicketStatus ticketStatus,
553
                            @RequestParam(name = "ticketSearchType", defaultValue = "") TicketSearchType ticketSearchType,
554
                            @RequestParam(name = "searchTerm", defaultValue = "0") int searchTerm,
555
                            @RequestParam(name = "page", defaultValue = "0") int page,
556
                            @RequestParam(name = "pageSize", defaultValue = "25") int pageSize,
557
                            @RequestParam(name = "search", required = false) String searchText,
558
                            Model model) throws ProfitMandiBusinessException {
559
        populateMyTicketModel(request, sortOrder, ticketStatus, ticketSearchType, searchTerm, page, pageSize, searchText, model);
560
        return "ticket";
561
    }
562
 
563
    @GetMapping(value = "/cs/myticket-content")
564
    public String getTicketContent(HttpServletRequest request,
565
                                   @RequestParam(name = "orderby", defaultValue = "DESCENDING") SortOrder sortOrder,
566
                                   @RequestParam(name = "ticketStatus", defaultValue = "OPENED") TicketStatus ticketStatus,
567
                                   @RequestParam(name = "ticketSearchType", defaultValue = "") TicketSearchType ticketSearchType,
568
                                   @RequestParam(name = "searchTerm", defaultValue = "0") int searchTerm,
569
                                   @RequestParam(name = "page", defaultValue = "0") int page,
570
                                   @RequestParam(name = "pageSize", defaultValue = "25") int pageSize,
571
                                   @RequestParam(name = "search", required = false) String searchText,
572
                                   Model model) throws ProfitMandiBusinessException {
573
        populateMyTicketModel(request, sortOrder, ticketStatus, ticketSearchType, searchTerm, page, pageSize, searchText, model);
574
        return "ticket-content";
575
    }
576
 
577
    private void populateMyTicketModel(HttpServletRequest request, SortOrder sortOrder, TicketStatus ticketStatus,
578
                                       TicketSearchType ticketSearchType, int searchTerm, int page, int pageSize,
579
                                       String searchText, Model model) throws ProfitMandiBusinessException {
31762 tejbeer 580
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
581
        List<Ticket> tickets = null;
582
        List<TicketAssigned> ticketAssigneds = null;
35626 amit 583
        long totalRecords = 0;
31762 tejbeer 584
        Map<Integer, AuthUser> authUserIdAndAuthUserMap = null;
35569 amit 585
        boolean isAdmin = roleManager.isAdmin(new HashSet<>(loginDetails.getRoleIds()));
586
        AuthUser currentAuthUser = isAdmin ? authRepository.selectByEmailOrMobile(loginDetails.getEmailId()) : null;
587
 
35592 amit 588
        boolean isCrmUser = isAdmin && currentAuthUser != null && positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
35603 amit 589
        boolean isSalesUser = isAdmin && currentAuthUser != null && positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_SALES);
590
        boolean isRbmUser = isAdmin && currentAuthUser != null && positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_RBM);
35592 amit 591
 
35626 amit 592
        List<Integer> userCategoryIds = isAdmin && currentAuthUser != null
593
                ? positionRepository.selectCategoryIdsByAuthUserId(currentAuthUser.getId())
594
                : Collections.emptyList();
595
 
596
        int offset = page * pageSize;
597
 
35569 amit 598
        if (isAdmin) {
599
            int authUserId = currentAuthUser.getId();
35592 amit 600
 
601
            if (isCrmUser) {
35626 amit 602
                Optional<Boolean> resolvedOpt = ticketStatus.equals(TicketStatus.RESOLVED) ? Optional.empty() : Optional.of(TicketStatus.CLOSED.equals(ticketStatus));
603
                tickets = ticketRepository.selectAllTicketsPaginated(
604
                        resolvedOpt, sortOrder, ticketSearchType, searchTerm, searchText,
605
                        userCategoryIds, offset, pageSize);
606
                totalRecords = ticketRepository.selectAllTicketsPaginatedCount(
607
                        resolvedOpt, ticketSearchType, searchTerm, searchText, userCategoryIds);
31762 tejbeer 608
            } else {
35626 amit 609
                Optional<Boolean> resolvedOpt = ticketStatus.equals(TicketStatus.RESOLVED) ? Optional.empty() : Optional.of(TicketStatus.CLOSED.equals(ticketStatus));
610
                tickets = ticketRepository.selectAllByAssigneePaginated(
611
                        authUserId, resolvedOpt, sortOrder, ticketSearchType, searchTerm, searchText,
612
                        offset, pageSize);
613
                totalRecords = ticketRepository.selectAllByAssigneePaginatedCount(
614
                        authUserId, resolvedOpt, ticketSearchType, searchTerm, searchText);
31762 tejbeer 615
            }
35626 amit 616
 
31762 tejbeer 617
            if (tickets.size() > 0) {
618
                ticketAssigneds = ticketAssignedRepository.selectByTicketIds(tickets.stream().map(x -> x.getId()).collect(Collectors.toList()));
619
                authUserIdAndAuthUserMap = csService.getAuthUserIdAndAuthUserMap(ticketAssigneds);
620
                Map<Integer, CustomRetailer> fofoIdsAndCustomRetailer = csService.getPartnerByFofoIds(tickets);
621
                model.addAttribute("fofoIdsAndCustomRetailer", fofoIdsAndCustomRetailer);
622
            }
24500 govind 623
 
31762 tejbeer 624
        } else {
625
            tickets = ticketRepository.selectAllByCreator(loginDetails.getFofoId(), Optional.of(TicketStatus.OPENED.equals(ticketStatus)), sortOrder);
35626 amit 626
            totalRecords = ticketRepository.selectAllCountByCreator(loginDetails.getFofoId(), Optional.of(TicketStatus.OPENED.equals(ticketStatus)));
31762 tejbeer 627
        }
628
        authUserIdAndAuthUserMap = csService.getTicketIdAndAuthUserMapUsingTickets(tickets);
35571 amit 629
        if (authUserIdAndAuthUserMap == null) {
630
            authUserIdAndAuthUserMap = new HashMap<>();
631
        }
24620 govind 632
 
36040 ranu 633
        Map<Integer, List<AuthUser>> authUserListMap = csService.getAssignedAuthList(tickets);
634
        if (authUserListMap == null) {
635
            authUserListMap = new HashMap<>();
636
        }
637
 
35626 amit 638
        int totalPages = (int) Math.ceil((double) totalRecords / pageSize);
639
        if (totalPages == 0) totalPages = 1;
640
        int startRecord = totalRecords > 0 ? offset + 1 : 0;
641
        int endRecord = (int) Math.min(offset + pageSize, totalRecords);
642
 
643
        model.addAttribute("size", totalRecords);
644
        model.addAttribute("totalRecords", totalRecords);
645
        model.addAttribute("currentPage", page);
646
        model.addAttribute("pageSize", pageSize);
647
        model.addAttribute("totalPages", totalPages);
648
        model.addAttribute("startRecord", startRecord);
649
        model.addAttribute("endRecord", endRecord);
650
        model.addAttribute("searchText", searchText != null ? searchText : "");
651
        model.addAttribute("currentPageDisplay", page + 1);
652
        model.addAttribute("prevPage", page - 1);
653
        model.addAttribute("nextPage", page + 1);
654
        model.addAttribute("lastPage", totalPages - 1);
655
 
35569 amit 656
        model.addAttribute("roleType", isAdmin);
657
        model.addAttribute("isCrmUser", isCrmUser);
35603 amit 658
        model.addAttribute("isSalesUser", isSalesUser);
659
        model.addAttribute("salesCategoryId", ProfitMandiConstants.TICKET_CATEGORY_SALES);
660
        model.addAttribute("isRbmUser", isRbmUser);
661
        model.addAttribute("rbmCategoryId", ProfitMandiConstants.TICKET_CATEGORY_RBM);
35626 amit 662
        model.addAttribute("userCategoryIds", userCategoryIds);
24500 govind 663
 
31762 tejbeer 664
        List<Integer> subCategoryIds = tickets.stream().map(x -> x.getSubCategoryId()).collect(Collectors.toList());
665
        Map<Integer, TicketSubCategory> subCategoryIdAndSubCategoryMap = csService.getSubCategoryIdAndSubCategoryMap(subCategoryIds);
35571 amit 666
        if (subCategoryIdAndSubCategoryMap == null) {
667
            subCategoryIdAndSubCategoryMap = new HashMap<>();
668
        }
24747 govind 669
 
31762 tejbeer 670
        Map<Integer, TicketCategory> subCategoryIdAndCategoryMap = csService.getSubCategoryIdAndCategoryMap(subCategoryIds);
35571 amit 671
        if (subCategoryIdAndCategoryMap == null) {
672
            subCategoryIdAndCategoryMap = new HashMap<>();
673
        }
27318 amit.gupta 674
 
31762 tejbeer 675
        List<Integer> ticketIds = tickets.stream().map(x -> x.getId()).collect(Collectors.toList());
24500 govind 676
 
35569 amit 677
        Map<Integer, List<Activity>> activityMap = new HashMap<>();
33864 ranu 678
        Map<Integer, List<Activity>> activityMapWithActivityId = new HashMap<>();
35569 amit 679
        Map<Integer, AuthUser> authUserMap = new HashMap<>();
24500 govind 680
 
31762 tejbeer 681
        if (!ticketIds.isEmpty()) {
35569 amit 682
            List<Activity> allActivities = activityRepository.selectAll(ticketIds);
683
            activityMap = allActivities.stream().collect(Collectors.groupingBy(Activity::getTicketId));
684
            activityMapWithActivityId = allActivities.stream().collect(Collectors.groupingBy(Activity::getId));
24787 govind 685
 
35569 amit 686
            Set<Integer> activityCreatorIds = allActivities.stream()
687
                    .map(Activity::getCreatedBy)
688
                    .filter(id -> id > 0)
689
                    .collect(Collectors.toSet());
690
            if (!activityCreatorIds.isEmpty()) {
691
                authUserMap = authRepository.selectByIds(new ArrayList<>(activityCreatorIds))
692
                        .stream().collect(Collectors.toMap(AuthUser::getId, x -> x));
693
            }
31762 tejbeer 694
        }
24787 govind 695
 
35626 amit 696
        int currentUserId;
697
        UserType currentUserType;
698
        if (isAdmin) {
699
            currentUserId = currentAuthUser.getId();
700
            currentUserType = UserType.AUTH_USER;
701
        } else {
702
            currentUserId = loginDetails.getFofoId();
703
            currentUserType = UserType.PARTNER;
704
        }
705
        Map<Integer, Boolean> unreadMap = csService.getUnreadStatusForTickets(tickets, currentUserId, currentUserType);
706
        Map<Integer, Activity> lastActivityMap = csService.getLastActivitiesForTickets(ticketIds);
35640 amit 707
        Map<Integer, Activity> lastMessageMap = csService.getLastMessageActivitiesForTickets(ticketIds);
35626 amit 708
        model.addAttribute("unreadMap", unreadMap);
709
        model.addAttribute("lastActivityMap", lastActivityMap);
35640 amit 710
        model.addAttribute("lastMessageMap", lastMessageMap);
35626 amit 711
 
31762 tejbeer 712
        model.addAttribute("tickets", tickets);
713
        model.addAttribute("resolved", ActivityType.RESOLVED);
714
        model.addAttribute("resolved-accepted", ActivityType.RESOLVED_ACCEPTED);
715
        model.addAttribute("resolved-rejected", ActivityType.RESOLVED_REJECTED);
716
        model.addAttribute("authUserIdAndAuthUserMap", authUserIdAndAuthUserMap);
36040 ranu 717
        model.addAttribute("authUserListMap", authUserListMap);
31762 tejbeer 718
        model.addAttribute("subCategoryIdAndSubCategoryMap", subCategoryIdAndSubCategoryMap);
27318 amit.gupta 719
 
31762 tejbeer 720
        model.addAttribute("subCategoryIdAndCategoryMap", subCategoryIdAndCategoryMap);
721
        model.addAttribute("activityMap", activityMap);
33864 ranu 722
        model.addAttribute("authUserMap", authUserMap);
723
        model.addAttribute("activityMapWithActivityId", activityMapWithActivityId);
24500 govind 724
 
31762 tejbeer 725
        model.addAttribute("ticketStatusValues", TicketStatus.values());
726
        model.addAttribute("orderByValues", SortOrder.values());
727
        model.addAttribute("selectedticketStatus", ticketStatus);
728
        model.addAttribute("selectedorderby", sortOrder);
729
        model.addAttribute("ticketSearchTypes", TicketSearchType.values());
730
        model.addAttribute("ticketSearchType", ticketSearchType);
731
        model.addAttribute("searchTerm", searchTerm);
732
    }
24500 govind 733
 
27124 amit.gupta 734
 
31762 tejbeer 735
    @GetMapping(value = "/cs/getActivities")
736
    public String getActivity(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, Model model) throws Exception {
35592 amit 737
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
738
        Ticket ticket = ticketRepository.selectById(ticketId);
739
 
740
        if (ticket == null) {
741
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
742
        }
743
 
744
        // Authorization check: verify user has access to this ticket
745
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
746
        if (!isAdmin) {
747
            // Partners can only view their own tickets
748
            if (ticket.getFofoId() != loginDetails.getFofoId()) {
749
                throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to view this ticket");
750
            }
751
        } else {
752
            // Admins must be assigned to the ticket OR be CRM user OR be in the escalation chain
753
            AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
754
            boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
755
 
756
            if (!isCrmUser) {
757
                // Check if user is assigned or in escalation chain
758
                List<TicketAssigned> assignments = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
759
                boolean isAssigned = assignments.stream().anyMatch(ta -> ta.getAssineeId() == currentAuthUser.getId() || ta.getManagerId() == currentAuthUser.getId());
760
                boolean isInEscalationChain = ticket.getL1AuthUser() == currentAuthUser.getId() ||
761
                        ticket.getL2AuthUser() == currentAuthUser.getId() ||
762
                        ticket.getL3AuthUser() == currentAuthUser.getId() ||
763
                        ticket.getL4AuthUser() == currentAuthUser.getId() ||
764
                        ticket.getL5AuthUser() == currentAuthUser.getId();
765
 
36231 ranu 766
                // Check if user is related to this partner (RBM, ASM, BM etc.)
767
                boolean isRelatedToPartner = false;
35592 amit 768
                if (!isAssigned && !isInEscalationChain) {
36231 ranu 769
                    List<AuthUser> relatedUsers = csService.getAuthUserIdByPartnerId(ticket.getFofoId());
770
                    isRelatedToPartner = relatedUsers.stream()
771
                            .anyMatch(au -> au.getId() == currentAuthUser.getId());
772
                    if (!isRelatedToPartner) {
773
                        throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to view this ticket");
774
                    }
35592 amit 775
                }
36231 ranu 776
 
777
                // User can view but cannot take action if only related to partner (not assigned/escalation)
778
                model.addAttribute("canTakeAction", isAssigned || isInEscalationChain);
35592 amit 779
            }
780
        }
781
 
31762 tejbeer 782
        List<Activity> allactivities = activityRepository.selectAll(ticketId);
35570 amit 783
 
784
        // Batch fetch all documents for attachments (fix N+1 query)
785
        List<Integer> documentIds = allactivities.stream()
786
                .flatMap(a -> a.getActivityAttachment().stream())
787
                .map(ActivityAttachment::getDocumentId)
788
                .distinct()
789
                .collect(Collectors.toList());
790
 
791
        Map<Integer, Document> documentMap = Collections.emptyMap();
792
        if (!documentIds.isEmpty()) {
793
            documentMap = documentRepository.selectByIds(documentIds).stream()
794
                    .collect(Collectors.toMap(Document::getId, d -> d));
795
        }
796
 
797
        // Set document names transiently (do not persist during GET)
798
        for (Activity activity : allactivities) {
799
            for (ActivityAttachment attachment : activity.getActivityAttachment()) {
800
                Document document = documentMap.get(attachment.getDocumentId());
801
                if (document != null) {
802
                    attachment.setDocumentName(document.getDisplayName());
803
                }
31762 tejbeer 804
            }
805
        }
806
        List<Activity> activities = null;
35592 amit 807
        if (isAdmin) {
31762 tejbeer 808
            Set<Integer> authUserIds = allactivities.stream().map(x -> x.getCreatedBy()).collect(Collectors.toSet());
36040 ranu 809
 
810
            // Fetch current assignees for this ticket to show in ASSIGNED/ESCALATED activities
811
            List<TicketAssigned> ticketAssignments = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
812
            Set<Integer> assigneeIds = ticketAssignments.stream()
813
                    .map(TicketAssigned::getAssineeId)
814
                    .collect(Collectors.toSet());
815
            authUserIds.addAll(assigneeIds);
816
 
35395 amit 817
            List<AuthUser> users = authRepository.selectByIds(new ArrayList<>(authUserIds));
31762 tejbeer 818
            Map<Integer, String> authUserNameMap = users.stream().collect(Collectors.toMap(AuthUser::getId, x -> x.getFirstName() + " " + x.getLastName()));
36040 ranu 819
 
820
            // Get current assignee name (most recent assignment)
821
            String currentAssigneeName = null;
822
            if (!ticketAssignments.isEmpty()) {
823
                int latestAssigneeId = ticketAssignments.get(ticketAssignments.size() - 1).getAssineeId();
824
                currentAssigneeName = authUserNameMap.get(latestAssigneeId);
825
            }
826
            final String assigneeName = currentAssigneeName;
827
 
828
            allactivities.stream().forEach(x -> {
829
                x.setName(authUserNameMap.get(x.getCreatedBy()));
830
                // For ASSIGNED/ESCALATED activities, use name field to show assignee
831
                ActivityType actType = x.getType();
832
                if (assigneeName != null && (actType == ActivityType.ASSIGNED || actType == ActivityType.ESCALATED || actType == ActivityType.ESCALATED_FINAL)) {
833
                    x.setName(assigneeName);
834
                }
835
            });
31762 tejbeer 836
            activities = allactivities;
837
        } else {
838
            activities = allactivities.stream().filter(x -> ActivityType.PARTNER_ACTIVITIES.contains(x.getType())).collect(Collectors.toList());
839
        }
840
        if (activities == null) {
841
            throw new ProfitMandiBusinessException("Activity", ticketId, "No Activity Found");
842
        }
843
        model.addAttribute("response1", mvcResponseSender.createResponseString(activities));
844
        return "response";
24500 govind 845
 
31762 tejbeer 846
    }
24620 govind 847
 
31762 tejbeer 848
    @PostMapping(value = "/cs/createActivity")
849
    public String createActivity(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, @RequestParam(name = "assigneeId", defaultValue = "0") int assigneeId, @RequestParam(name = "internal", defaultValue = "true") boolean internal, @RequestParam(name = "message", defaultValue = "") String message, @RequestBody List<Integer> documentIds,
24620 govind 850
 
31762 tejbeer 851
                                 Model model) throws Exception {
24620 govind 852
 
31762 tejbeer 853
        LOGGER.info("documentIds" + documentIds);
854
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
855
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 856
 
857
        if (ticket == null) {
858
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
859
        }
860
 
861
        // Authorization check: verify user has access to add activity to this ticket
862
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
863
        if (!isAdmin) {
864
            // Partners can only add activity to their own tickets
865
            if (ticket.getFofoId() != loginDetails.getFofoId()) {
866
                throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to add activity to this ticket");
867
            }
868
        } else {
869
            // Admins must be assigned to the ticket OR be CRM user OR be in the escalation chain
870
            AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
871
            boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
872
 
873
            if (!isCrmUser) {
874
                List<TicketAssigned> assignments = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
875
                boolean isAssigned = assignments.stream().anyMatch(ta -> ta.getAssineeId() == currentAuthUser.getId() || ta.getManagerId() == currentAuthUser.getId());
876
                boolean isInEscalationChain = ticket.getL1AuthUser() == currentAuthUser.getId() ||
877
                        ticket.getL2AuthUser() == currentAuthUser.getId() ||
878
                        ticket.getL3AuthUser() == currentAuthUser.getId() ||
879
                        ticket.getL4AuthUser() == currentAuthUser.getId() ||
880
                        ticket.getL5AuthUser() == currentAuthUser.getId();
881
 
882
                if (!isAssigned && !isInEscalationChain) {
883
                    throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to add activity to this ticket");
884
                }
885
            }
886
        }
31762 tejbeer 887
        List<TicketAssigned> ticketAssignedList = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
888
        List<Integer> authUserIds = ticketAssignedList.stream().map(x -> x.getAssineeId()).collect(Collectors.toList());
889
        authUserIds.add(ticketAssignedList.get(ticketAssignedList.size() - 1).getManagerId());
35395 amit 890
        Map<Integer, AuthUser> authUsersMap = authRepository.selectByIds(authUserIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
31762 tejbeer 891
        if (ticket.getCloseTimestamp() == null) {
892
            Activity activity = new Activity();
893
            activity.setCreatedBy(0);
894
            activity.setCreateTimestamp(LocalDateTime.now());
895
            String subject = null;
896
            String mailMessage = null;
897
            activity.setMessage(message);
898
            if (!roleManager.isAdmin(new HashSet<>(loginDetails.getRoleIds()))) {
899
                CustomRetailer customRetailer = retailerService.getFofoRetailers(true).get(loginDetails.getFofoId());
900
                activity.setType(ActivityType.COMMUNICATION_IN);
901
                subject = String.format("Ticket Update #%s by franchisee %s", ticket.getId(), customRetailer.getBusinessName() + "(" + customRetailer.getCode() + ")");
902
                mailMessage = String.format("Franchisee message - %s", message);
903
            } else {
904
                AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
905
                activity.setCreatedBy(authUser.getId());
906
                authUsersMap.remove(authUser.getId());
907
                subject = String.format("Ticket Update #%s by %s", ticket.getId(), authUser.getName());
908
                mailMessage = String.format("%s's message - %s", authUser.getFirstName(), message);
35569 amit 909
                // Only CRM users can send external communications
910
                boolean isCrmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
911
                if (internal || !isCrmUser) {
31762 tejbeer 912
                    activity.setType(ActivityType.COMMUNICATION_INTERNAL);
913
                } else {
914
                    String updatedBy = "SD Team";
31854 amit.gupta 915
                    CustomRetailer customRetailer = retailerService.getFofoRetailers(false).get(ticket.getFofoId());
31762 tejbeer 916
                    subject = String.format("Ticket Update #%s by %s", ticket.getId(), updatedBy);
917
                    String partnerMessage = String.format("%s's message - %s", updatedBy, message);
918
                    this.activityRelatedMail(customRetailer.getEmail(), null, "subject", partnerMessage);
919
                    activity.setType(ActivityType.COMMUNICATION_OUT);
920
                }
921
            }
922
            activityRepository.persist(activity);
923
 
924
            for (Integer documentId : documentIds) {
925
                ActivityAttachment activityAttachment = new ActivityAttachment();
926
                activityAttachment.setActivityId(activity.getId());
927
                activityAttachment.setDocumentId(documentId);
928
                activityAttachmentRepository.persist(activityAttachment);
929
            }
930
 
931
            csService.addActivity(ticket, activity);
932
            AuthUser authUser = authUsersMap.remove(authUserIds.get(0));
933
            if (authUser == null) {
934
                authUser = authUsersMap.remove(authUserIds.get(1));
935
            }
936
            model.addAttribute("response1", mvcResponseSender.createResponseString(authUser));
937
            String[] cc = authUsersMap.entrySet().stream().map(x -> x.getValue().getEmailId()).toArray(String[]::new);
938
            this.activityRelatedMail(authUser.getEmailId(), cc, subject, mailMessage);
939
        } else {
940
            throw new ProfitMandiBusinessException("Ticket", ticket.getId(), "Already closed ticket");
941
        }
942
        return "response";
943
    }
944
 
945
    private void activityRelatedMail(String to, String[] cc, String subject, String message) throws ProfitMandiBusinessException {
946
        try {
35957 amit 947
            mailOutboxService.queueMail(to, cc, subject, message, "CsController.activityRelatedMail");
31762 tejbeer 948
        } catch (Exception e) {
949
            throw new ProfitMandiBusinessException("Ticket Activity", to, "Could not send ticket activity mail");
950
        }
951
    }
952
 
953
    @PostMapping(value = "/cs/closeTicket")
954
    public String closeTicket(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, @RequestParam(name = "happyCode") String happyCode, Model model) throws Exception {
35592 amit 955
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
31762 tejbeer 956
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 957
 
958
        if (ticket == null) {
959
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
960
        }
961
 
962
        // Authorization check: only the ticket owner (partner) can close the ticket
963
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
964
        if (isAdmin) {
965
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Only partners can close tickets using happy code");
966
        }
967
 
968
        // Verify the partner owns this ticket
969
        if (ticket.getFofoId() != loginDetails.getFofoId()) {
970
            throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to close this ticket");
971
        }
972
 
31762 tejbeer 973
        if (ticket.getHappyCode().equals(happyCode)) {
974
            ticket.setCloseTimestamp(LocalDateTime.now());
975
            ticketRepository.persist(ticket);
976
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));
977
        } else {
978
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Happy Code can't match");
979
        }
980
        return "response";
981
    }
982
 
34913 ranu 983
    @GetMapping(value = "/cs/myPartyTicketTicket")
984
    public String getMyPartyTicketTicket(HttpServletRequest request, @RequestParam(name = "orderby", defaultValue = "DESCENDING") SortOrder sortOrder, @RequestParam(name = "ticketStatus", defaultValue = "OPENED") TicketStatus ticketStatus, @RequestParam(name = "ticketSearchType", defaultValue = "") TicketSearchType ticketSearchType, @RequestParam(name = "searchTerm", defaultValue = "0") int searchTerm, Model model) throws ProfitMandiBusinessException {
35626 amit 985
        populateMyPartnerTicketModel(request, sortOrder, ticketStatus, ticketSearchType, searchTerm, model);
986
        return "my-partner-tickets";
987
    }
988
 
989
    @GetMapping(value = "/cs/myPartyTicket-content")
990
    public String getMyPartyTicketContent(HttpServletRequest request,
991
                                          @RequestParam(name = "orderby", defaultValue = "DESCENDING") SortOrder sortOrder,
992
                                          @RequestParam(name = "ticketStatus", defaultValue = "OPENED") TicketStatus ticketStatus,
993
                                          @RequestParam(name = "ticketSearchType", defaultValue = "") TicketSearchType ticketSearchType,
994
                                          @RequestParam(name = "searchTerm", defaultValue = "0") int searchTerm,
995
                                          Model model) throws ProfitMandiBusinessException {
996
        populateMyPartnerTicketModel(request, sortOrder, ticketStatus, ticketSearchType, searchTerm, model);
997
        return "my-partner-tickets-content";
998
    }
999
 
1000
    private void populateMyPartnerTicketModel(HttpServletRequest request, SortOrder sortOrder, TicketStatus ticketStatus,
1001
                                              TicketSearchType ticketSearchType, int searchTerm, Model model) throws ProfitMandiBusinessException {
34913 ranu 1002
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1003
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1004
        List<Ticket> tickets = new ArrayList<>();
1005
        Map<String, Set<Integer>> storeGuyMap = csService.getAuthUserPartnerIdMapping();
1006
        Set<Integer> fofoIds = storeGuyMap.get(authUser.getEmailId());
1007
 
1008
        Map<Integer, List<AuthUser>> authUserListMap = null;
1009
        if (fofoIds != null && !fofoIds.isEmpty()) {
35571 amit 1010
            List<Ticket> allPartnerTickets = ticketRepository.selectAllOpenTickets(new ArrayList<>(fofoIds));
1011
            if (allPartnerTickets != null && !allPartnerTickets.isEmpty()) {
1012
                tickets = allPartnerTickets.stream()
1013
                        .filter(ticket -> ticket.getLastActivity() == null ||
1014
                                ticket.getLastActivity() != ActivityType.RESOLVED)
1015
                        .collect(Collectors.toList());
34913 ranu 1016
            }
1017
        }
1018
 
1019
        authUserListMap = csService.getAssignedAuthList(tickets);
1020
 
36231 ranu 1021
        // Find which tickets are assigned to or escalated to this user (can take action)
1022
        Set<Integer> actionableTicketIds = new HashSet<>();
34913 ranu 1023
        if (tickets.size() > 0) {
36231 ranu 1024
            List<TicketAssigned> allAssignments = ticketAssignedRepository.selectByTicketIds(
1025
                    tickets.stream().map(Ticket::getId).collect(Collectors.toList()));
1026
            for (TicketAssigned ta : allAssignments) {
1027
                if (ta.getAssineeId() == authUser.getId() || ta.getManagerId() == authUser.getId()) {
1028
                    actionableTicketIds.add(ta.getTicketId());
1029
                }
1030
            }
1031
            // Also check escalation chain
1032
            for (Ticket t : tickets) {
1033
                if (t.getL1AuthUser() == authUser.getId() || t.getL2AuthUser() == authUser.getId()
1034
                        || t.getL3AuthUser() == authUser.getId() || t.getL4AuthUser() == authUser.getId()
1035
                        || t.getL5AuthUser() == authUser.getId()) {
1036
                    actionableTicketIds.add(t.getId());
1037
                }
1038
            }
34913 ranu 1039
            Map<Integer, CustomRetailer> fofoIdsAndCustomRetailer = csService.getPartnerByFofoIds(tickets);
1040
            model.addAttribute("fofoIdsAndCustomRetailer", fofoIdsAndCustomRetailer);
1041
        }
36231 ranu 1042
        model.addAttribute("actionableTicketIds", actionableTicketIds);
34913 ranu 1043
 
35626 amit 1044
        // Pagination for partner tickets (in-memory since selectAllOpenTickets doesn't support DB-level pagination)
1045
        long totalRecords = tickets.size();
1046
        int totalPages = totalRecords > 0 ? (int) Math.ceil((double) totalRecords / 25) : 1;
1047
        model.addAttribute("totalRecords", totalRecords);
1048
        model.addAttribute("currentPage", 0);
1049
        model.addAttribute("pageSize", 25);
1050
        model.addAttribute("totalPages", totalPages);
1051
        model.addAttribute("startRecord", totalRecords > 0 ? 1 : 0);
1052
        model.addAttribute("endRecord", totalRecords);
1053
        model.addAttribute("currentPageDisplay", 1);
1054
        model.addAttribute("prevPage", 0);
1055
        model.addAttribute("nextPage", 1);
1056
        model.addAttribute("lastPage", totalPages - 1);
1057
 
34913 ranu 1058
        model.addAttribute("size", tickets.size());
1059
        model.addAttribute("tickets", tickets);
1060
 
1061
        List<Integer> subCategoryIds = tickets.stream().map(x -> x.getSubCategoryId()).collect(Collectors.toList());
1062
        Map<Integer, TicketSubCategory> subCategoryIdAndSubCategoryMap = csService.getSubCategoryIdAndSubCategoryMap(subCategoryIds);
35571 amit 1063
        if (subCategoryIdAndSubCategoryMap == null) {
1064
            subCategoryIdAndSubCategoryMap = new HashMap<>();
1065
        }
34913 ranu 1066
 
1067
        Map<Integer, TicketCategory> subCategoryIdAndCategoryMap = csService.getSubCategoryIdAndCategoryMap(subCategoryIds);
35571 amit 1068
        if (subCategoryIdAndCategoryMap == null) {
1069
            subCategoryIdAndCategoryMap = new HashMap<>();
1070
        }
34913 ranu 1071
 
1072
        List<Integer> ticketIds = tickets.stream().map(x -> x.getId()).collect(Collectors.toList());
1073
        Map<Integer, List<Activity>> activityMap = new HashMap<>();
1074
        Map<Integer, List<Activity>> activityMapWithActivityId = new HashMap<>();
35569 amit 1075
        Map<Integer, AuthUser> authUserMap = new HashMap<>();
34913 ranu 1076
 
1077
        if (!ticketIds.isEmpty()) {
35569 amit 1078
            List<Activity> allActivities = activityRepository.selectAll(ticketIds);
1079
            activityMap = allActivities.stream().collect(Collectors.groupingBy(Activity::getTicketId));
1080
            activityMapWithActivityId = allActivities.stream().collect(Collectors.groupingBy(Activity::getId));
34913 ranu 1081
 
35569 amit 1082
            Set<Integer> activityCreatorIds = allActivities.stream()
1083
                    .map(Activity::getCreatedBy)
1084
                    .filter(id -> id > 0)
1085
                    .collect(Collectors.toSet());
1086
            if (!activityCreatorIds.isEmpty()) {
1087
                authUserMap = authRepository.selectByIds(new ArrayList<>(activityCreatorIds))
1088
                        .stream().collect(Collectors.toMap(AuthUser::getId, x -> x));
1089
            }
34913 ranu 1090
        }
1091
 
35626 amit 1092
        Map<Integer, Boolean> unreadMap = csService.getUnreadStatusForTickets(tickets, authUser.getId(), UserType.AUTH_USER);
35640 amit 1093
        List<Integer> partnerTicketIds = tickets.stream().map(Ticket::getId).collect(Collectors.toList());
1094
        Map<Integer, Activity> lastActivityMap = csService.getLastActivitiesForTickets(partnerTicketIds);
1095
        Map<Integer, Activity> lastMessageMap = csService.getLastMessageActivitiesForTickets(partnerTicketIds);
35626 amit 1096
        model.addAttribute("unreadMap", unreadMap);
1097
        model.addAttribute("lastActivityMap", lastActivityMap);
35640 amit 1098
        model.addAttribute("lastMessageMap", lastMessageMap);
35626 amit 1099
 
34913 ranu 1100
        model.addAttribute("ticketStatusValues", TicketStatus.values());
1101
        model.addAttribute("orderByValues", SortOrder.values());
1102
        model.addAttribute("selectedticketStatus", ticketStatus);
1103
        model.addAttribute("selectedorderby", sortOrder);
1104
        model.addAttribute("ticketSearchTypes", TicketSearchType.values());
1105
        model.addAttribute("ticketSearchType", ticketSearchType);
1106
        model.addAttribute("searchTerm", searchTerm);
35571 amit 1107
        model.addAttribute("authUserListMap", authUserListMap != null ? authUserListMap : new HashMap<>());
34913 ranu 1108
        model.addAttribute("subCategoryIdAndSubCategoryMap", subCategoryIdAndSubCategoryMap);
1109
 
1110
        model.addAttribute("subCategoryIdAndCategoryMap", subCategoryIdAndCategoryMap);
1111
 
1112
        model.addAttribute("activityMap", activityMap);
1113
        model.addAttribute("authUserMap", authUserMap);
1114
        model.addAttribute("activityMapWithActivityId", activityMapWithActivityId);
35569 amit 1115
        boolean isCrmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1116
        model.addAttribute("isCrmUser", isCrmUser);
35626 amit 1117
    }
34913 ranu 1118
 
35626 amit 1119
    @GetMapping(value = "/cs/managerTicket")
1120
    public String getManagerTickets(HttpServletRequest request,
1121
                                    @RequestParam(name = "orderby", defaultValue = "DESCENDING") SortOrder sortOrder,
1122
                                    @RequestParam(name = "ticketStatus", defaultValue = "OPENED") TicketStatus ticketStatus,
1123
                                    @RequestParam(name = "ticketSearchType", defaultValue = "") TicketSearchType ticketSearchType,
1124
                                    @RequestParam(name = "searchTerm", defaultValue = "0") int searchTerm,
1125
                                    @RequestParam(name = "page", defaultValue = "0") int page,
1126
                                    @RequestParam(name = "pageSize", defaultValue = "25") int pageSize,
1127
                                    @RequestParam(name = "search", required = false) String searchText,
1128
                                    Model model) throws ProfitMandiBusinessException {
1129
        populateManagerTicketModel(request, sortOrder, ticketStatus, ticketSearchType, searchTerm, page, pageSize, searchText, model);
1130
        return "managerTicket";
34913 ranu 1131
    }
1132
 
35626 amit 1133
    @GetMapping(value = "/cs/managerTicket-content")
1134
    public String getManagerTicketContent(HttpServletRequest request,
1135
                                          @RequestParam(name = "orderby", defaultValue = "DESCENDING") SortOrder sortOrder,
1136
                                          @RequestParam(name = "ticketStatus", defaultValue = "OPENED") TicketStatus ticketStatus,
1137
                                          @RequestParam(name = "ticketSearchType", defaultValue = "") TicketSearchType ticketSearchType,
1138
                                          @RequestParam(name = "searchTerm", defaultValue = "0") int searchTerm,
1139
                                          @RequestParam(name = "page", defaultValue = "0") int page,
1140
                                          @RequestParam(name = "pageSize", defaultValue = "25") int pageSize,
1141
                                          @RequestParam(name = "search", required = false) String searchText,
1142
                                          Model model) throws ProfitMandiBusinessException {
1143
        populateManagerTicketModel(request, sortOrder, ticketStatus, ticketSearchType, searchTerm, page, pageSize, searchText, model);
1144
        return "managerTicket-content";
1145
    }
1146
 
1147
    private void populateManagerTicketModel(HttpServletRequest request, SortOrder sortOrder, TicketStatus ticketStatus,
1148
                                            TicketSearchType ticketSearchType, int searchTerm, int page, int pageSize,
1149
                                            String searchText, Model model) throws ProfitMandiBusinessException {
31762 tejbeer 1150
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
35626 amit 1151
        long totalRecords = 0;
31762 tejbeer 1152
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
35626 amit 1153
 
1154
        // Block L1-only users from accessing manager tickets
1155
        List<Position> positions = positionRepository.selectAllByAuthUserId(authUser.getId());
1156
        boolean isAboveL1 = positions.stream().anyMatch(pos -> pos.getEscalationType() != EscalationType.L1);
1157
        if (!isAboveL1) {
1158
            throw new ProfitMandiBusinessException("ManagerTicket", 0, "Access denied: requires at least L2 position");
1159
        }
1160
 
35594 amit 1161
        boolean isCrmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1162
 
35626 amit 1163
        List<Integer> userCategoryIds = positionRepository.selectCategoryIdsByAuthUserId(authUser.getId());
1164
 
31762 tejbeer 1165
        List<Ticket> tickets = null;
1166
        Map<Integer, List<AuthUser>> authUserListMap = null;
35594 amit 1167
 
35626 amit 1168
        int offset = page * pageSize;
1169
        Optional<Boolean> resolvedOpt = ticketStatus.equals(TicketStatus.RESOLVED) ? Optional.empty() : Optional.of(TicketStatus.CLOSED.equals(ticketStatus));
1170
 
35594 amit 1171
        if (isCrmUser) {
35626 amit 1172
            tickets = ticketRepository.selectAllTicketsPaginated(
1173
                    resolvedOpt, sortOrder, ticketSearchType, searchTerm, searchText,
1174
                    userCategoryIds, offset, pageSize);
1175
            totalRecords = ticketRepository.selectAllTicketsPaginatedCount(
1176
                    resolvedOpt, ticketSearchType, searchTerm, searchText, userCategoryIds);
31762 tejbeer 1177
        } else {
35626 amit 1178
            tickets = ticketRepository.selectAllManagerTicketPaginated(
1179
                    authUser.getId(), sortOrder, resolvedOpt, ticketSearchType, searchTerm, searchText,
1180
                    offset, pageSize);
1181
            totalRecords = ticketRepository.selectAllCountByManagerTicketPaginated(
1182
                    authUser.getId(), resolvedOpt, ticketSearchType, searchTerm, searchText);
31762 tejbeer 1183
        }
1184
        authUserListMap = csService.getAssignedAuthList(tickets);
1185
 
1186
        if (tickets.size() > 0) {
1187
            Map<Integer, CustomRetailer> fofoIdsAndCustomRetailer = csService.getPartnerByFofoIds(tickets);
1188
            model.addAttribute("fofoIdsAndCustomRetailer", fofoIdsAndCustomRetailer);
1189
        }
1190
 
35626 amit 1191
        int totalPages = (int) Math.ceil((double) totalRecords / pageSize);
1192
        if (totalPages == 0) totalPages = 1;
1193
        int startRecord = totalRecords > 0 ? offset + 1 : 0;
1194
        int endRecord = (int) Math.min(offset + pageSize, totalRecords);
1195
 
1196
        model.addAttribute("size", totalRecords);
1197
        model.addAttribute("totalRecords", totalRecords);
1198
        model.addAttribute("currentPage", page);
1199
        model.addAttribute("pageSize", pageSize);
1200
        model.addAttribute("totalPages", totalPages);
1201
        model.addAttribute("startRecord", startRecord);
1202
        model.addAttribute("endRecord", endRecord);
1203
        model.addAttribute("searchText", searchText != null ? searchText : "");
1204
        model.addAttribute("currentPageDisplay", page + 1);
1205
        model.addAttribute("prevPage", page - 1);
1206
        model.addAttribute("nextPage", page + 1);
1207
        model.addAttribute("lastPage", totalPages - 1);
31762 tejbeer 1208
        model.addAttribute("tickets", tickets);
1209
 
1210
        List<Integer> subCategoryIds = tickets.stream().map(x -> x.getSubCategoryId()).collect(Collectors.toList());
1211
        Map<Integer, TicketSubCategory> subCategoryIdAndSubCategoryMap = csService.getSubCategoryIdAndSubCategoryMap(subCategoryIds);
35571 amit 1212
        if (subCategoryIdAndSubCategoryMap == null) {
1213
            subCategoryIdAndSubCategoryMap = new HashMap<>();
1214
        }
31762 tejbeer 1215
 
1216
        Map<Integer, TicketCategory> subCategoryIdAndCategoryMap = csService.getSubCategoryIdAndCategoryMap(subCategoryIds);
35571 amit 1217
        if (subCategoryIdAndCategoryMap == null) {
1218
            subCategoryIdAndCategoryMap = new HashMap<>();
1219
        }
31762 tejbeer 1220
 
1221
        List<Integer> ticketIds = tickets.stream().map(x -> x.getId()).collect(Collectors.toList());
1222
        Map<Integer, List<Activity>> activityMap = new HashMap<>();
33778 ranu 1223
        Map<Integer, List<Activity>> activityMapWithActivityId = new HashMap<>();
35570 amit 1224
        Map<Integer, AuthUser> authUserMap = new HashMap<>();
31762 tejbeer 1225
 
1226
        if (!ticketIds.isEmpty()) {
35570 amit 1227
            List<Activity> allActivities = activityRepository.selectAll(ticketIds);
1228
            activityMap = allActivities.stream().collect(Collectors.groupingBy(Activity::getTicketId));
1229
            activityMapWithActivityId = allActivities.stream().collect(Collectors.groupingBy(Activity::getId));
31762 tejbeer 1230
 
35570 amit 1231
            Set<Integer> activityCreatorIds = allActivities.stream()
1232
                    .map(Activity::getCreatedBy)
1233
                    .filter(id -> id > 0)
1234
                    .collect(Collectors.toSet());
1235
            if (!activityCreatorIds.isEmpty()) {
1236
                authUserMap = authRepository.selectByIds(new ArrayList<>(activityCreatorIds))
1237
                        .stream().collect(Collectors.toMap(AuthUser::getId, x -> x));
1238
            }
31762 tejbeer 1239
        }
33778 ranu 1240
 
35626 amit 1241
        Map<Integer, Boolean> unreadMap = csService.getUnreadStatusForTickets(tickets, authUser.getId(), UserType.AUTH_USER);
35640 amit 1242
        List<Integer> managerTicketIds = tickets.stream().map(Ticket::getId).collect(Collectors.toList());
1243
        Map<Integer, Activity> lastActivityMap = csService.getLastActivitiesForTickets(managerTicketIds);
1244
        Map<Integer, Activity> lastMessageMap = csService.getLastMessageActivitiesForTickets(managerTicketIds);
35626 amit 1245
        model.addAttribute("unreadMap", unreadMap);
1246
        model.addAttribute("lastActivityMap", lastActivityMap);
35640 amit 1247
        model.addAttribute("lastMessageMap", lastMessageMap);
35626 amit 1248
 
31762 tejbeer 1249
        model.addAttribute("ticketStatusValues", TicketStatus.values());
1250
        model.addAttribute("orderByValues", SortOrder.values());
1251
        model.addAttribute("selectedticketStatus", ticketStatus);
1252
        model.addAttribute("selectedorderby", sortOrder);
1253
        model.addAttribute("ticketSearchTypes", TicketSearchType.values());
1254
        model.addAttribute("ticketSearchType", ticketSearchType);
1255
        model.addAttribute("searchTerm", searchTerm);
1256
        model.addAttribute("authUserListMap", authUserListMap);
1257
        model.addAttribute("subCategoryIdAndSubCategoryMap", subCategoryIdAndSubCategoryMap);
1258
 
1259
        model.addAttribute("subCategoryIdAndCategoryMap", subCategoryIdAndCategoryMap);
1260
 
1261
        model.addAttribute("activityMap", activityMap);
33778 ranu 1262
        model.addAttribute("authUserMap", authUserMap);
1263
        model.addAttribute("activityMapWithActivityId", activityMapWithActivityId);
35594 amit 1264
        model.addAttribute("isCrmUser", isCrmUser);
31762 tejbeer 1265
    }
1266
 
1267
 
1268
    @GetMapping(value = "/cs/edit-ticket")
35594 amit 1269
    public String getEditTicket(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, Model model) throws ProfitMandiBusinessException {
1270
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1271
        AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1272
        boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1273
 
31762 tejbeer 1274
        Ticket ticket = ticketRepository.selectById(ticketId);
35626 amit 1275
        if (ticket == null) {
1276
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
1277
        }
1278
 
1279
        TicketSubCategory ticketSubCategory = ticketSubCategoryRepository.selectById(ticket.getSubCategoryId());
1280
        int ticketCategoryId = ticketSubCategory.getCategoryId();
1281
        boolean isVisibleSubCategory = ticketSubCategory.isVisibility();
1282
 
1283
        // Check permissions
1284
        boolean hasPositionInCategory = positionRepository.hasCategory(currentAuthUser.getId(), ticketCategoryId);
1285
        List<TicketAssigned> assignments = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
1286
        boolean isAssigned = assignments.stream().anyMatch(ta -> ta.getAssineeId() == currentAuthUser.getId() || ta.getManagerId() == currentAuthUser.getId());
1287
        boolean isInEscalationChain = ticket.getL1AuthUser() == currentAuthUser.getId() ||
1288
                ticket.getL2AuthUser() == currentAuthUser.getId() ||
1289
                ticket.getL3AuthUser() == currentAuthUser.getId() ||
1290
                ticket.getL4AuthUser() == currentAuthUser.getId() ||
1291
                ticket.getL5AuthUser() == currentAuthUser.getId();
1292
 
1293
        boolean canEdit = (isCrmUser && isVisibleSubCategory)
1294
                || hasPositionInCategory
1295
                || isAssigned
1296
                || isInEscalationChain;
1297
 
1298
        if (!canEdit) {
1299
            throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to edit this ticket");
1300
        }
1301
 
31762 tejbeer 1302
        List<TicketCategory> ticketCategories = csService.getAllTicketCategotyFromSubCategory();
1303
        List<TicketSubCategory> ticketSubCategories = ticketSubCategoryRepository.selectAll(ticketSubCategory.getCategoryId());
1304
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
35594 amit 1305
 
35617 amit 1306
        // CRM users should not see invisible subcategories
35594 amit 1307
        if (isCrmUser) {
1308
            ticketSubCategories = ticketSubCategories.stream()
35617 amit 1309
                    .filter(TicketSubCategory::isVisibility)
35594 amit 1310
                    .collect(Collectors.toList());
1311
        }
1312
 
1313
        // Get partner name for modal title
1314
        String partnerName = retailerService.getFofoRetailer(ticket.getFofoId()).getBusinessName();
1315
 
31762 tejbeer 1316
        model.addAttribute("ticket", ticket);
1317
        model.addAttribute("ticketCategories", ticketCategories);
1318
        model.addAttribute("ticketSubCategories", ticketSubCategories);
1319
        model.addAttribute("ticketSubCategory", ticketSubCategory);
1320
        model.addAttribute("authUsers", authUsers);
35594 amit 1321
        model.addAttribute("isCrmUser", isCrmUser);
1322
        model.addAttribute("partnerName", partnerName);
31762 tejbeer 1323
        return "edit-ticket-modal";
1324
    }
1325
 
34913 ranu 1326
    @GetMapping(value = "/cs/edit-partner-ticket")
35594 amit 1327
    public String getEditPartnerTicket(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, Model model) throws ProfitMandiBusinessException {
1328
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1329
        AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1330
        boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1331
 
34913 ranu 1332
        Ticket ticket = ticketRepository.selectById(ticketId);
1333
        List<TicketCategory> ticketCategories = csService.getAllTicketCategotyFromSubCategory();
1334
        TicketSubCategory ticketSubCategory = ticketSubCategoryRepository.selectById(ticket.getSubCategoryId());
1335
        List<TicketSubCategory> ticketSubCategories = ticketSubCategoryRepository.selectAll(ticketSubCategory.getCategoryId());
1336
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
35594 amit 1337
 
35617 amit 1338
        // CRM users should not see invisible subcategories
35594 amit 1339
        if (isCrmUser) {
1340
            ticketSubCategories = ticketSubCategories.stream()
35617 amit 1341
                    .filter(TicketSubCategory::isVisibility)
35594 amit 1342
                    .collect(Collectors.toList());
1343
        }
1344
 
1345
        // Get partner name for modal title
1346
        String partnerName = retailerService.getFofoRetailer(ticket.getFofoId()).getBusinessName();
1347
 
34913 ranu 1348
        model.addAttribute("ticket", ticket);
1349
        model.addAttribute("ticketCategories", ticketCategories);
1350
        model.addAttribute("ticketSubCategories", ticketSubCategories);
1351
        model.addAttribute("ticketSubCategory", ticketSubCategory);
1352
        model.addAttribute("authUsers", authUsers);
35594 amit 1353
        model.addAttribute("isCrmUser", isCrmUser);
1354
        model.addAttribute("partnerName", partnerName);
34913 ranu 1355
        return "edit-ticket-partner-modal";
1356
    }
1357
 
31762 tejbeer 1358
    @PostMapping(value = "/cs/edit-ticket")
1359
    public String editTicket(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, @RequestParam(name = "subCategoryId", defaultValue = "0") int subCategoryId, @RequestParam(name = "categoryId", defaultValue = "0") int categoryId, @RequestParam(name = "authUserId", defaultValue = "0") int authUserId, @RequestParam(name = "escalationType", defaultValue = "L1") EscalationType escalationType, Model model) throws Exception {
1360
        LOGGER.info("Ticket Id {}, CategoryId {}, SubCategory Id {} authUserId {}", ticketId, categoryId, subCategoryId, authUserId);
35592 amit 1361
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1362
 
1363
        // Only admins can edit tickets
1364
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
1365
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Only admins can edit tickets");
1366
        }
1367
 
31762 tejbeer 1368
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 1369
        if (ticket == null) {
1370
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
1371
        }
1372
 
35626 amit 1373
        // Verify admin has access to this ticket
35592 amit 1374
        AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1375
        boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1376
 
35626 amit 1377
        // Get ticket's subcategory to check visibility
1378
        TicketSubCategory ticketSubCategory = ticketSubCategoryRepository.selectById(ticket.getSubCategoryId());
1379
        int ticketCategoryId = ticketSubCategory.getCategoryId();
1380
        boolean isVisibleSubCategory = ticketSubCategory.isVisibility();
35592 amit 1381
 
35626 amit 1382
        // Check if user has position in ticket's category
1383
        boolean hasPositionInCategory = positionRepository.hasCategory(currentAuthUser.getId(), ticketCategoryId);
1384
 
1385
        // Check if assigned or in escalation chain
1386
        List<TicketAssigned> assignments = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
1387
        boolean isAssigned = assignments.stream().anyMatch(ta -> ta.getAssineeId() == currentAuthUser.getId() || ta.getManagerId() == currentAuthUser.getId());
1388
        boolean isInEscalationChain = ticket.getL1AuthUser() == currentAuthUser.getId() ||
1389
                ticket.getL2AuthUser() == currentAuthUser.getId() ||
1390
                ticket.getL3AuthUser() == currentAuthUser.getId() ||
1391
                ticket.getL4AuthUser() == currentAuthUser.getId() ||
1392
                ticket.getL5AuthUser() == currentAuthUser.getId();
1393
 
1394
        // Permission rules:
1395
        // 1. CRM user AND ticket has visible subcategory, OR
1396
        // 2. Has position in ticket's category (can edit even invisible), OR
1397
        // 3. Is assigned to ticket, OR
1398
        // 4. Is in escalation chain
1399
        boolean canEdit = (isCrmUser && isVisibleSubCategory)
1400
                || hasPositionInCategory
1401
                || isAssigned
1402
                || isInEscalationChain;
1403
 
1404
        if (!canEdit) {
1405
            throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to edit this ticket");
35592 amit 1406
        }
1407
 
31762 tejbeer 1408
        csService.updateTicket(categoryId, subCategoryId, ticket, authUserId, escalationType);
1409
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1410
        return "response";
1411
 
1412
    }
1413
 
34913 ranu 1414
    @PostMapping(value = "/cs/edit-partner-ticket")
1415
    public String editPartnerTicket(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, @RequestParam(name = "subCategoryId", defaultValue = "0") int subCategoryId, @RequestParam(name = "categoryId", defaultValue = "0") int categoryId, @RequestParam(name = "authUserId", defaultValue = "0") int authUserId, @RequestParam(name = "escalationType", defaultValue = "L1") EscalationType escalationType, Model model) throws Exception {
1416
        LOGGER.info("Ticket Id {}, CategoryId {}, SubCategory Id {} authUserId {}", ticketId, categoryId, subCategoryId, authUserId);
35592 amit 1417
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1418
 
1419
        // Only admins can edit partner tickets
1420
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
1421
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Only admins can edit partner tickets");
1422
        }
1423
 
34913 ranu 1424
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 1425
        if (ticket == null) {
1426
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
1427
        }
1428
 
1429
        // Verify admin has access (must be in Sales, ABM, or RBM position for the partner)
1430
        AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1431
        Map<String, Set<Integer>> authUserPartnerMap = csService.getAuthUserPartnerIdMapping();
1432
        Set<Integer> allowedPartnerIds = authUserPartnerMap.get(currentAuthUser.getEmailId());
1433
 
1434
        if (allowedPartnerIds == null || !allowedPartnerIds.contains(ticket.getFofoId())) {
1435
            // Also allow CRM users
1436
            boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1437
            if (!isCrmUser) {
1438
                throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to edit this partner's ticket");
1439
            }
1440
        }
1441
 
34913 ranu 1442
        csService.updateTicket(categoryId, subCategoryId, ticket, authUserId, escalationType);
1443
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1444
        return "response";
1445
 
1446
    }
1447
 
31762 tejbeer 1448
    @PostMapping(value = "/cs/changeTicketAssignee")
1449
    public String changeTicketAssignee(HttpServletRequest request, @RequestParam(name = "positionId", defaultValue = "0") int positionId, Model model) throws Exception {
1450
        Position position = positionRepository.selectById(positionId);
1451
        if (position.isTicketAssignee()) {
1452
            position.setTicketAssignee(false);
1453
        } else {
1454
            position.setTicketAssignee(true);
1455
        }
1456
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1457
        return "response";
1458
    }
1459
 
1460
 
1461
    @DeleteMapping(value = "/cs/removePosition")
1462
    public String removePosition(HttpServletRequest request, @RequestParam(name = "positionId", defaultValue = "0") int positionId, Model model) throws Exception {
1463
        positionRepository.delete(positionId);
1464
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1465
        return "response";
1466
    }
1467
 
1468
    @PostMapping(value = "/cs/create-last-activity")
1469
    public String createlastActivity(HttpServletRequest request, @RequestParam(name = "ticketId") int ticketId, @RequestParam(name = "lastactivity") ActivityType lastActivity, Model model) throws Exception {
1470
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1471
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 1472
 
1473
        if (ticket == null) {
1474
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
1475
        }
1476
 
1477
        // Authorization check for partners: can only update their own tickets
1478
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
1479
        if (!isAdmin && ticket.getFofoId() != loginDetails.getFofoId()) {
1480
            throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to update this ticket");
1481
        }
1482
 
31762 tejbeer 1483
        Activity activity = new Activity();
1484
        String subject = String.format(ACTIVITY_SUBJECT, ticket.getId());
35592 amit 1485
        if (isAdmin) {
35603 amit 1486
            // CRM team members can resolve any ticket
1487
            // Sales team members can resolve their own Sales category tickets
1488
            // RBM team members can resolve their own RBM category tickets
35592 amit 1489
            AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1490
            boolean isCrmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
35603 amit 1491
            boolean isSalesUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_SALES);
1492
            boolean isRbmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_RBM);
1493
 
1494
            // Check if ticket belongs to Sales or RBM category
1495
            TicketSubCategory ticketSubCategory = ticketSubCategoryRepository.selectById(ticket.getSubCategoryId());
1496
            boolean isSalesTicket = ticketSubCategory != null && ticketSubCategory.getCategoryId() == ProfitMandiConstants.TICKET_CATEGORY_SALES;
1497
            boolean isRbmTicket = ticketSubCategory != null && ticketSubCategory.getCategoryId() == ProfitMandiConstants.TICKET_CATEGORY_RBM;
1498
 
1499
            // Allow if CRM user OR (Sales user AND Sales ticket) OR (RBM user AND RBM ticket)
1500
            if (!isCrmUser && !(isSalesUser && isSalesTicket) && !(isRbmUser && isRbmTicket)) {
1501
                throw new ProfitMandiBusinessException("Ticket", ticketId, "Only CRM, Sales (for Sales tickets), or RBM (for RBM tickets) team can mark tickets as resolved");
35592 amit 1502
            }
31762 tejbeer 1503
            ticket.setLastActivity(lastActivity);
1504
            String to = retailerService.getFofoRetailer(ticket.getFofoId()).getEmail();
1505
            String message = String.format(PARTNER_RESOLVED_TICKET_MAIL, ticketId, "REOPEN");
1506
            activity.setMessage(message);
35592 amit 1507
            activity.setCreatedBy(authUser.getId());
31762 tejbeer 1508
            activity.setTicketId(ticketId);
1509
            activity.setCreateTimestamp(LocalDateTime.now());
1510
            activity.setType(ActivityType.COMMUNICATION_OUT);
1511
            this.activityRelatedMail(to, null, subject, message);
1512
        } else {
1513
            if (ActivityType.RESOLVED_ACCEPTED == lastActivity) {
1514
                ticket.setLastActivity(lastActivity);
1515
                ticket.setCloseTimestamp(LocalDateTime.now());
1516
                activity.setMessage(ActivityType.RESOLVED_ACCEPTED.toString());
1517
                activity.setCreatedBy(0);
1518
                activity.setTicketId(ticketId);
1519
                activity.setType(ActivityType.COMMUNICATION_IN);
1520
                activity.setCreateTimestamp(LocalDateTime.now());
1521
            } else {
1522
                String message = String.format(INTERNAL_REOPEN_MAIL, ticketId, retailerService.getFofoRetailer(loginDetails.getFofoId()).getBusinessName());
1523
                String to = authRepository.selectById(ticket.getL1AuthUser()).getEmailId();
35395 amit 1524
                String[] ccTo = authRepository.selectByIds(Arrays.asList(ticket.getL2AuthUser(), ticket.getL3AuthUser(), ticket.getL4AuthUser(), ticket.getL5AuthUser())).stream().map(x -> x.getEmailId()).toArray(String[]::new);
31762 tejbeer 1525
                ticket.setLastActivity(lastActivity);
1526
                ticket.setUpdateTimestamp(LocalDateTime.now());
1527
                ticketAssignedRepository.deleteByTicketId(ticketId);
1528
                TicketAssigned ticketAssigned = new TicketAssigned();
1529
                ticketAssigned.setAssineeId(ticket.getL1AuthUser());
1530
                ticketAssigned.setTicketId(ticketId);
1531
                ticketAssignedRepository.persist(ticketAssigned);
1532
                activity.setMessage(INTERNAL_REOPEN_ACTIVITY_MESSAGE);
1533
                activity.setCreatedBy(0);
1534
                activity.setTicketId(ticketId);
1535
                activity.setType(ActivityType.COMMUNICATION_IN);
1536
                activity.setCreateTimestamp(LocalDateTime.now());
1537
                this.activityRelatedMail(to, ccTo, subject, message);
1538
                this.activityRelatedMail(retailerService.getFofoRetailer(loginDetails.getFofoId()).getEmail(), null, subject, String.format(PARTNER_REOPEN, ticketId));
1539
            }
1540
 
1541
        }
1542
        activityRepository.persist(activity);
1543
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1544
        return "response";
1545
    }
1546
 
32812 shampa 1547
 
1548
 
1549
 
1550
 
1551
    @PostMapping(value = "/partner-position/update")
1552
    public String positionUpdated(Model model, @RequestBody List<PartnerPositonUpdateModel> partnerPositionUpdateModels)
1553
            throws Exception {
1554
 
32821 shampa 1555
        Map<Integer, List<String>> positionIdsToAddMap = partnerPositionUpdateModels.stream().filter(x->x.getPositionIdTo()!=0).collect(Collectors.groupingBy(x->x.getPositionIdTo(),
32812 shampa 1556
                Collectors.mapping(x->x.getStoreCode(), Collectors.toList())));
1557
 
32821 shampa 1558
        Map<Integer, List<String>> positionIdsToRemoveMap = partnerPositionUpdateModels.stream().filter(x->x.getPositionIdFrom()!=0).collect(Collectors.groupingBy(x->x.getPositionIdFrom(),
32812 shampa 1559
                Collectors.mapping(x->x.getStoreCode(), Collectors.toList())));
1560
 
1561
        List<Integer> positionIdsToUpdate = new ArrayList<>();
1562
        positionIdsToUpdate.addAll(positionIdsToAddMap.keySet());
1563
        positionIdsToUpdate.addAll(positionIdsToRemoveMap.keySet());
1564
 
35395 amit 1565
        Map<Integer, Position> positionsToUpdateMap =  positionRepository.selectByIds(positionIdsToUpdate).stream().collect(Collectors.toMap(x->x.getId(), x->x));
32812 shampa 1566
        List<Integer> invalidPositionIds = positionsToUpdateMap.values().stream().filter(x-> x.getCategoryId()!= ProfitMandiConstants.TICKET_CATEGORY_RBM
34908 ranu 1567
                && x.getCategoryId() != ProfitMandiConstants.TICKET_CATEGORY_SALES && x.getCategoryId() != ProfitMandiConstants.TICKET_CATEGORY_ABM).map(x -> x.getId()).collect(Collectors.toList());
32812 shampa 1568
        if(invalidPositionIds.size() > 0) {
34908 ranu 1569
            String message = "Non RBM/Sales/ABM are not allowed - " + invalidPositionIds;
32812 shampa 1570
            throw new ProfitMandiBusinessException(message, message, message);
1571
        }
1572
 
1573
        for (Map.Entry<Integer, List<String>> positionIdStoreMapEntry : positionIdsToAddMap.entrySet()) {
1574
            int positionId = positionIdStoreMapEntry.getKey();
1575
            Position position = positionsToUpdateMap.get(positionId);
32821 shampa 1576
            LOGGER.info("positionId - {}, Position - {}", positionId, position);
32812 shampa 1577
            List<String> storeCodesToAdd = positionIdStoreMapEntry.getValue();
1578
            List<Integer> retailerIdsToAdd = fofoStoreRepository.selectByStoreCodes(storeCodesToAdd).stream().map(x->x.getId()).collect(Collectors.toList());
1579
            Map<Integer, PartnerPosition> partnerPositionsMapByFofoId  = partnerPositionRepository
32821 shampa 1580
                    .selectByRegionIdAndPostionId(Arrays.asList(position.getRegionId())
1581
                            ,Arrays.asList(positionId)).stream().collect(Collectors.toMap(x->x.getFofoId(),x->x));
32812 shampa 1582
            for (Integer retailerIdToAdd : retailerIdsToAdd) {
1583
                if (!partnerPositionsMapByFofoId.containsKey(retailerIdToAdd)) {
1584
                    PartnerPosition partnerPositionNew = new PartnerPosition();
1585
                    partnerPositionNew.setPositionId(positionId);
1586
                    partnerPositionNew.setFofoId(retailerIdToAdd);
1587
                    partnerPositionNew.setRegionId(position.getRegionId());
32865 amit.gupta 1588
                    partnerPositionRepository.persist(partnerPositionNew);
32812 shampa 1589
                }
1590
            }
1591
        }
1592
 
1593
        for (Map.Entry<Integer, List<String>> positionIdStoreMapEntry : positionIdsToRemoveMap.entrySet()) {
1594
 
1595
            int positionId = positionIdStoreMapEntry.getKey();
1596
            Position position = positionsToUpdateMap.get(positionId);
1597
            List<String> storeCodesToRemove = positionIdStoreMapEntry.getValue();
1598
            List<Integer> retailerIdsToRemove = fofoStoreRepository.selectByStoreCodes(storeCodesToRemove).stream().map(x->x.getId()).collect(Collectors.toList());
1599
            Map<Integer, PartnerPosition> partnerPositionsMapByFofoId  = partnerPositionRepository
1600
                    .selectByRegionIdAndPostionId(Arrays.asList(position.getRegionId()),Arrays.asList(positionId)).stream().collect(Collectors.toMap(x->x.getFofoId(),x->x));
1601
            for (Integer retailerIdToRemove : retailerIdsToRemove) {
1602
                if (partnerPositionsMapByFofoId.containsKey(retailerIdToRemove)) {
1603
                   PartnerPosition partnerPositionToRemove =  partnerPositionsMapByFofoId.get(retailerIdToRemove);
1604
                   partnerPositionRepository.delete(partnerPositionToRemove);
1605
                }
1606
            }
1607
        }
1608
 
1609
 
1610
 
1611
        /*partnerPositionUpdateModels.str
1612
 
1613
        Map<Integer, Position> positionIdMap = positionsToUpdate.stream().collect(Collectors.toMap(x->x.getId(), x->x));
1614
        for (PartnerPositonUpdateModel partnerPositionUpdateModel : partnerPositionUpdateModels) {
1615
            FofoStore fofoStore = fofoStoreRepository.selectByStoreCode(partnerPositionUpdateModel.getStoreCode());
1616
            Position positionFrom = positionIdMap.get(partnerPositionUpdateModel.getPositionIdFrom());
1617
            Position positionTo = positionIdMap.get(partnerPositionUpdateModel.getPositionIdTo());
1618
            if(positionFrom != null) {
1619
                partnerPositionRepository.selectByRegionIdAndPostionId(Arrays.)
1620
              int regionId = positionFrom.getRegionId()
1621
            }
1622
            if(positionTo != null) {
1623
 
1624
            }
1625
        }*/
1626
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1627
        return "response";
1628
 
1629
    }
1630
 
35626 amit 1631
    @PostMapping(value = "/cs/markTicketRead")
1632
    @ResponseBody
1633
    public Map<String, Object> markTicketRead(HttpServletRequest request,
1634
                                              @RequestParam(name = "ticketId") int ticketId,
1635
                                              Model model) throws ProfitMandiBusinessException {
1636
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1637
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
1638
        Map<String, Object> response = new HashMap<>();
32812 shampa 1639
 
35626 amit 1640
        if (isAdmin) {
1641
            AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1642
            csService.markTicketAsRead(ticketId, authUser.getId(), UserType.AUTH_USER);
1643
        } else {
1644
            csService.markTicketAsRead(ticketId, loginDetails.getFofoId(), UserType.PARTNER);
1645
        }
1646
 
1647
        response.put("success", true);
1648
        return response;
1649
    }
1650
 
1651
    @GetMapping(value = "/cs/unreadCount")
1652
    @ResponseBody
1653
    public Map<String, Object> getUnreadCount(HttpServletRequest request) throws ProfitMandiBusinessException {
1654
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1655
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
1656
        Map<String, Object> response = new HashMap<>();
1657
 
1658
        List<Ticket> tickets;
1659
        int userId;
1660
        UserType userType;
1661
 
1662
        if (isAdmin) {
1663
            AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1664
            userId = authUser.getId();
1665
            userType = UserType.AUTH_USER;
1666
            boolean isCrmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1667
            List<Integer> userCategoryIds = positionRepository.selectCategoryIdsByAuthUserId(authUser.getId());
1668
            if (isCrmUser) {
1669
                tickets = ticketRepository.selectAllTicketsPaginated(
1670
                        Optional.of(false), null, null, 0, null,
1671
                        userCategoryIds, 0, 1000);
1672
            } else {
1673
                tickets = ticketRepository.selectAllByAssigneePaginated(
1674
                        authUser.getId(), Optional.of(false), null, null, 0, null,
1675
                        0, 1000);
1676
            }
1677
        } else {
1678
            userId = loginDetails.getFofoId();
1679
            userType = UserType.PARTNER;
1680
            tickets = ticketRepository.selectAllByCreator(loginDetails.getFofoId(), Optional.of(true), null);
1681
        }
1682
 
1683
        Map<Integer, Boolean> unreadMap = csService.getUnreadStatusForTickets(tickets, userId, userType);
1684
        long unreadCount = unreadMap.values().stream().filter(v -> v).count();
1685
 
1686
        response.put("success", true);
1687
        response.put("unreadCount", unreadCount);
1688
        return response;
1689
    }
1690
 
24417 govind 1691
}