Subversion Repositories SmartDukaan

Rev

Rev 35603 | Rev 35617 | Go to most recent revision | 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;
24620 govind 6
import com.spice.profitmandi.common.util.Utils;
24417 govind 7
import com.spice.profitmandi.dao.entity.auth.AuthUser;
27690 amit.gupta 8
import com.spice.profitmandi.dao.entity.cs.*;
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;
19
import com.spice.profitmandi.service.user.RetailerService;
20
import com.spice.profitmandi.web.model.LoginDetails;
21
import com.spice.profitmandi.web.util.CookiesProcessor;
22
import com.spice.profitmandi.web.util.MVCResponseSender;
27690 amit.gupta 23
import org.apache.logging.log4j.LogManager;
24
import org.apache.logging.log4j.Logger;
25
import org.springframework.beans.factory.annotation.Autowired;
26
import org.springframework.mail.javamail.JavaMailSender;
27
import org.springframework.stereotype.Controller;
28
import org.springframework.transaction.annotation.Transactional;
29
import org.springframework.ui.Model;
30
import org.springframework.web.bind.annotation.*;
24417 govind 31
 
27690 amit.gupta 32
import javax.servlet.http.HttpServletRequest;
35571 amit 33
import javax.swing.SortOrder;
27690 amit.gupta 34
import java.time.LocalDateTime;
35
import java.util.*;
36
import java.util.stream.Collectors;
37
 
24417 govind 38
@Controller
39
@Transactional(rollbackFor = Throwable.class)
40
public class CsController {
41
 
31762 tejbeer 42
    private static final Logger LOGGER = LogManager.getLogger(CsController.class);
43
    private static final String ACTIVITY_SUBJECT = "Message related ticketId#%s";
44
    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";
45
    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";
46
    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";
47
    private static final String INTERNAL_REOPEN_ACTIVITY_MESSAGE = "Hi,My ticket is not resolved yet,so I have reopened it";
24699 govind 48
 
31762 tejbeer 49
    @Autowired
50
    JavaMailSender mailSender;
24620 govind 51
 
31762 tejbeer 52
    @Autowired
53
    private CsService csService;
24417 govind 54
 
31762 tejbeer 55
    @Autowired
56
    private CookiesProcessor cookiesProcessor;
24417 govind 57
 
31762 tejbeer 58
    @Autowired
59
    private TicketCategoryRepository ticketCategoryRepository;
24417 govind 60
 
31762 tejbeer 61
    @Autowired
62
    private TicketSubCategoryRepository ticketSubCategoryRepository;
24417 govind 63
 
31762 tejbeer 64
    @Autowired
65
    private RegionRepository regionRepository;
24417 govind 66
 
31762 tejbeer 67
    @Autowired
68
    private RetailerService retailerService;
24417 govind 69
 
31762 tejbeer 70
    @Autowired
71
    private MVCResponseSender mvcResponseSender;
24417 govind 72
 
31762 tejbeer 73
    @Autowired
74
    private AuthRepository authRepository;
24417 govind 75
 
31762 tejbeer 76
    @Autowired
77
    private PositionRepository positionRepository;
24417 govind 78
 
31762 tejbeer 79
    @Autowired
80
    private TicketRepository ticketRepository;
24417 govind 81
 
31762 tejbeer 82
    @Autowired
83
    private RoleManager roleManager;
24417 govind 84
 
31762 tejbeer 85
    @Autowired
86
    private ActivityRepository activityRepository;
24417 govind 87
 
31762 tejbeer 88
    @Autowired
89
    private ActivityAttachmentRepository activityAttachmentRepository;
27270 tejbeer 90
 
31762 tejbeer 91
    @Autowired
92
    private TicketAssignedRepository ticketAssignedRepository;
24569 govind 93
 
31762 tejbeer 94
    @Autowired
95
    private PartnerRegionRepository partnerRegionRepository;
24500 govind 96
 
31762 tejbeer 97
    @Autowired
32493 amit.gupta 98
    PartnerPositionRepository partnerPositionRepository;
25570 tejbeer 99
 
31762 tejbeer 100
    @Autowired
101
    FofoStoreRepository fofoStoreRepository;
25570 tejbeer 102
 
31762 tejbeer 103
    @Autowired
104
    DocumentRepository documentRepository;
27270 tejbeer 105
 
31762 tejbeer 106
    @GetMapping(value = "/cs/createCategory")
107
    public String getCreateCategory(HttpServletRequest request, Model model) {
108
        List<TicketCategory> ticketCategories = ticketCategoryRepository.selectAll();
109
        model.addAttribute("ticketCategories", ticketCategories);
110
        return "create-ticket-category";
111
    }
24417 govind 112
 
31762 tejbeer 113
    @PostMapping(value = "/cs/createCategory")
33081 ranu 114
    public String createCategory(HttpServletRequest request,
115
                                 @RequestParam(name = "name") String name,
116
                                 @RequestParam(name = "categoryType") int categoryType,
117
                                 @RequestParam(name = "description") String description,
118
                                 Model model) throws ProfitMandiBusinessException {
31762 tejbeer 119
        TicketCategory ticketCategory = ticketCategoryRepository.selectByName(name);
120
        if (ticketCategory != null) {
121
            throw new ProfitMandiBusinessException("name", name, "already exists!");
122
        }
33081 ranu 123
 
31762 tejbeer 124
        ticketCategory = new TicketCategory();
125
        ticketCategory.setName(name);
126
        ticketCategory.setDescription(description);
33081 ranu 127
 
128
        ticketCategory.setCategoryType(categoryType == 1);
31762 tejbeer 129
        ticketCategoryRepository.persist(ticketCategory);
130
        return "create-ticket-category";
131
    }
24417 govind 132
 
33081 ranu 133
 
31762 tejbeer 134
    @GetMapping(value = "/cs/createSubCategory")
135
    public String getCreateSubCategory(HttpServletRequest request, Model model) {
136
        List<TicketCategory> ticketCategories = ticketCategoryRepository.selectAll();
137
        model.addAttribute("ticketCategories", ticketCategories);
138
        return "create-ticket-sub-category";
139
    }
24417 govind 140
 
31762 tejbeer 141
    @GetMapping(value = "/cs/getSubCategoryByCategoryId")
142
    public String getSubCategoryByCategoryId(HttpServletRequest request, @RequestParam(name = "ticketCategoryId", defaultValue = "") int ticketCategoryId, Model model) {
143
        List<TicketSubCategory> ticketSubCategories = ticketSubCategoryRepository.selectAll(ticketCategoryId);
144
        TicketCategory ticketCategory = ticketCategoryRepository.selectById(ticketCategoryId);
33081 ranu 145
        LOGGER.info("ticketSubCategories {}", ticketSubCategories);
146
        LOGGER.info("ticketCategory {}", ticketCategory);
31762 tejbeer 147
        model.addAttribute("ticketSubCategories", ticketSubCategories);
148
        model.addAttribute("ticketCategory", ticketCategory);
149
        return "ticket-sub-category";
150
    }
24417 govind 151
 
31762 tejbeer 152
    @PostMapping(value = "/cs/createSubCategory")
153
    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 154
 
31762 tejbeer 155
        TicketSubCategory ticketSubCategory = ticketSubCategoryRepository.selectTicketSubCategory(categoryId, name);
156
        if (ticketSubCategory != null) {
157
            throw new ProfitMandiBusinessException("name & categoryId", name + "  " + categoryId, "already exists!");
158
        }
24417 govind 159
 
31762 tejbeer 160
        ticketSubCategory = new TicketSubCategory();
161
        ticketSubCategory.setCategoryId(categoryId);
162
        ticketSubCategory.setName(name);
163
        ticketSubCategory.setDescription(description);
164
        ticketSubCategoryRepository.persist(ticketSubCategory);
165
        return "create-ticket-sub-category";
166
    }
24417 govind 167
 
31762 tejbeer 168
    @GetMapping(value = "/cs/createRegion")
169
    public String createRegion(HttpServletRequest request, Model model) {
170
        List<Region> regions = regionRepository.selectAll();
171
        model.addAttribute("regions", regions);
172
        return "create-region";
173
    }
24417 govind 174
 
31762 tejbeer 175
    @PostMapping(value = "/cs/createRegion")
176
    public String createRegion(HttpServletRequest request, @RequestParam(name = "name") String name, @RequestParam(name = "description") String description, Model model) throws Exception {
177
        Region region = regionRepository.selectByName(name);
178
        if (region != null) {
179
            throw new ProfitMandiBusinessException("name", name, "already exists!");
180
        }
181
        region = new Region();
182
        region.setName(name);
183
        region.setDescription(description);
184
        regionRepository.persist(region);
185
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
186
        return "response";
187
    }
24417 govind 188
 
31762 tejbeer 189
    @GetMapping(value = "/cs/getPartners")
33244 ranu 190
    public String getPartners(HttpServletRequest request, @RequestParam(name = "regionId", defaultValue = "0") int regionId, Model model) throws ProfitMandiBusinessException {
31762 tejbeer 191
        List<Integer> fofoIds = fofoStoreRepository.selectAll().stream().map(x -> x.getId()).collect(Collectors.toList());
192
        List<Integer> addedfofoIds = partnerRegionRepository.selectByRegionId(regionId).stream().map(x -> x.getFofoId()).collect(Collectors.toList());
30426 tejbeer 193
 
31762 tejbeer 194
        Map<Integer, CustomRetailer> customRetailerMap = retailerService.getAllFofoRetailers();
195
        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));
196
        model.addAttribute("fofoRetailers", fofoRetailers);
197
        model.addAttribute("addedfofoIds", addedfofoIds);
198
        return "added-region-partners";
199
    }
24569 govind 200
 
31762 tejbeer 201
    @GetMapping(value = "/cs/getPartnersByRegion")
33244 ranu 202
    public String getPartnersByRegion(HttpServletRequest request, @RequestParam(name = "regionId", defaultValue = "0") int regionId, Model model) throws ProfitMandiBusinessException {
31762 tejbeer 203
        List<Integer> fofoIds = null;
204
        fofoIds = partnerRegionRepository.selectByRegionId(regionId).stream().map(x -> x.getFofoId()).collect(Collectors.toList());
25570 tejbeer 205
 
31762 tejbeer 206
        if (fofoIds.contains(0)) {
207
            fofoIds = fofoStoreRepository.selectAll().stream().filter(x -> x.isActive()).collect(Collectors.toList()).stream().map(x -> x.getId()).collect(Collectors.toList());
25570 tejbeer 208
 
31762 tejbeer 209
        }
210
        Map<Integer, CustomRetailer> customRetailerMap = retailerService.getAllFofoRetailers();
25570 tejbeer 211
 
31762 tejbeer 212
        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));
213
        model.addAttribute("fofoRetailers", fofoRetailers);
214
        return "added-subregion-partners";
215
    }
25570 tejbeer 216
 
31762 tejbeer 217
    @GetMapping(value = "/cs/createPartnerRegion")
218
    public String createPartnerRegion(HttpServletRequest request, Model model) {
219
        List<Region> regions = regionRepository.selectAll();
220
        model.addAttribute("regions", regions);
221
        return "create-partner-region";
222
    }
24417 govind 223
 
31762 tejbeer 224
    @PostMapping(value = "/cs/createPartnerRegion")
225
    public String createPartnerRegion(HttpServletRequest request, @RequestParam(name = "regionId") int regionId, @RequestBody List<Integer> selectedFofoIds, Model model) throws Exception {
226
        partnerRegionRepository.delete(regionId);
227
        LOGGER.info("successfully removed");
228
        LOGGER.info(selectedFofoIds.size());
229
        csService.addPartnerToRegion(regionId, selectedFofoIds);
230
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
231
        return "response";
232
    }
24417 govind 233
 
31762 tejbeer 234
    @GetMapping(value = "/cs/getPosition")
33244 ranu 235
    public String getPosition(HttpServletRequest request, @RequestParam int positionId, Model model) throws ProfitMandiBusinessException {
27410 tejbeer 236
 
31762 tejbeer 237
        Position position = positionRepository.selectById(positionId);
27410 tejbeer 238
 
31762 tejbeer 239
        List<CustomRetailer> positionIdCustomRetailer = csService.getPositionCustomRetailerMap(Arrays.asList(position)).get(position.getId());
27410 tejbeer 240
 
31762 tejbeer 241
        Map<Integer, CustomRetailer> regionRetailerMap = csService.getRegionPartners(Arrays.asList(position)).get(position.getRegionId()).stream().collect(Collectors.toMap(x -> x.getPartnerId(), x -> x));
27410 tejbeer 242
 
31762 tejbeer 243
        model.addAttribute("position", position);
244
        model.addAttribute("regionRetailerMap", regionRetailerMap);
245
        model.addAttribute("positionIdCustomRetailer", positionIdCustomRetailer);
27410 tejbeer 246
 
31762 tejbeer 247
        return "position-partner";
248
    }
27410 tejbeer 249
 
31762 tejbeer 250
    @GetMapping(value = "/cs/createPosition")
251
    public String createPosition(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, Model model) {
252
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
253
        List<TicketCategory> ticketCategories = ticketCategoryRepository.selectAll();
254
        List<Region> regions = regionRepository.selectAll();
255
        model.addAttribute("escalationTypes", EscalationType.values());
256
        model.addAttribute("authUsers", authUsers);
257
        model.addAttribute("ticketCategories", ticketCategories);
258
        model.addAttribute("regions", regions);
24500 govind 259
 
31762 tejbeer 260
        List<Position> positions = positionRepository.selectAllPosition();
261
        LOGGER.info("positions" + positions);
30426 tejbeer 262
 
31762 tejbeer 263
        Map<Integer, AuthUser> authUserIdAndAuthUserMap = csService.getAuthUserIdAndAuthUserMapUsingPositions(positions);
264
        Map<Integer, TicketCategory> categoryIdAndCategoryMap = csService.getCategoryIdAndCategoryUsingPositions(positions);
265
        Map<Integer, Region> regionIdAndRegionMap = csService.getRegionIdAndRegionMap(positions);
25570 tejbeer 266
 
27410 tejbeer 267
//	    Map<Integer, List<CustomRetailer>> positionIdAndpartnerRegionMap = csService
268
//			.getpositionIdAndpartnerRegionMap(positions);
25570 tejbeer 269
 
27410 tejbeer 270
//	     Map<Integer, List<CustomRetailer>> addedpositionIdAndCustomRetailerMap = csService
271
//				.getPositionCustomRetailerMap(positions);
272
//		LOGGER.info("fofoIdAndCustomRetailerMap" + addedpositionIdAndCustomRetailerMap);
24500 govind 273
 
31762 tejbeer 274
        model.addAttribute("start", offset + 1);
30426 tejbeer 275
 
31762 tejbeer 276
        model.addAttribute("positions", positions);
277
        model.addAttribute("authUserIdAndAuthUserMap", authUserIdAndAuthUserMap);
278
        model.addAttribute("categoryIdAndCategoryMap", categoryIdAndCategoryMap);
279
        model.addAttribute("regionIdAndRegionMap", regionIdAndRegionMap);
280
        // model.addAttribute("positionIdAndCustomRetailerMap",
281
        // addedpositionIdAndCustomRetailerMap);
282
        // model.addAttribute("positionIdAndpartnerRegionMap",
27410 tejbeer 283
// positionIdAndpartnerRegionMap);
25570 tejbeer 284
 
31762 tejbeer 285
        return "create-position";
286
    }
24500 govind 287
 
31762 tejbeer 288
    @GetMapping(value = "/cs/position-paginated")
289
    public String positionPaginated(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, Model model) {
24500 govind 290
 
31762 tejbeer 291
        List<Position> positions = positionRepository.selectAll(offset, limit);
292
        Map<Integer, AuthUser> authUserIdAndAuthUserMap = csService.getAuthUserIdAndAuthUserMapUsingPositions(positions);
293
        Map<Integer, TicketCategory> categoryIdAndCategoryMap = csService.getCategoryIdAndCategoryUsingPositions(positions);
294
        Map<Integer, Region> regionIdAndRegionMap = csService.getRegionIdAndRegionMap(positions);
295
        /*
296
         * Map<Integer, List<CustomRetailer>> positionIdAndpartnerRegionMap = csService
297
         * .getpositionIdAndpartnerRegionMap(positions);
298
         * 
299
         * Map<Integer, List<CustomRetailer>> addedpositionIdAndCustomRetailerMap =
300
         * csService .getPositionCustomRetailerMap(positions);
301
         */
25570 tejbeer 302
 
31762 tejbeer 303
        model.addAttribute("positions", positions);
304
        model.addAttribute("authUserIdAndAuthUserMap", authUserIdAndAuthUserMap);
305
        model.addAttribute("categoryIdAndCategoryMap", categoryIdAndCategoryMap);
306
        model.addAttribute("regionIdAndRegionMap", regionIdAndRegionMap);
307
        // model.addAttribute("positionIdAndCustomRetailerMap",
308
        // addedpositionIdAndCustomRetailerMap);
309
        // model.addAttribute("positionIdAndpartnerRegionMap",
310
        // positionIdAndpartnerRegionMap);
25570 tejbeer 311
 
31762 tejbeer 312
        return "position-paginated";
313
    }
24417 govind 314
 
31762 tejbeer 315
    @PostMapping(value = "/cs/createPosition")
316
    public String createPosition(HttpServletRequest request, @RequestBody CreatePositionModel createPositionModel, Model model) throws Exception {
24417 govind 317
 
35570 amit 318
        LOGGER.info("partnerPosition" + createPositionModel.isTicketAssigned());
25570 tejbeer 319
 
35570 amit 320
        // Validate authUserId exists
321
        int authUserId = createPositionModel.getAuthUserId();
322
        if (authUserId <= 0 || authRepository.selectById(authUserId) == null) {
323
            throw new ProfitMandiBusinessException("Position", authUserId, "Invalid authUserId");
324
        }
325
 
326
        // Validate categoryId exists (0 means "All Categories")
327
        int categoryId = createPositionModel.getCategoryId();
328
        if (categoryId > 0 && ticketCategoryRepository.selectById(categoryId) == null) {
329
            throw new ProfitMandiBusinessException("Position", categoryId, "Invalid categoryId");
330
        }
331
 
332
        // Validate regionId exists (0 or 5 typically means "All Partners/Regions")
333
        int regionId = createPositionModel.getRegionId();
334
        if (regionId > 0 && regionId != 5 && regionRepository.selectById(regionId) == null) {
335
            throw new ProfitMandiBusinessException("Position", regionId, "Invalid regionId");
336
        }
337
 
35589 amit 338
        // Validate fofoIds exist (0 means "All Partners")
35570 amit 339
        List<Integer> fofoIds = createPositionModel.getFofoIds();
35590 amit 340
        if (fofoIds == null || fofoIds.isEmpty()) {
341
            throw new ProfitMandiBusinessException("Position", 0, "At least one partner must be specified");
342
        }
343
        boolean hasAllPartners = fofoIds.contains(0);
344
        if (hasAllPartners && fofoIds.size() > 1) {
345
            throw new ProfitMandiBusinessException("Position", 0, "Cannot mix 'All Partners' (0) with specific partner IDs");
346
        }
347
        if (!hasAllPartners) {
348
            Map<Integer, CustomRetailer> validRetailers = retailerService.getFofoRetailers(false);
349
            for (int fofoId : fofoIds) {
350
                if (!validRetailers.containsKey(fofoId)) {
351
                    throw new ProfitMandiBusinessException("Position", fofoId, "Invalid fofoId");
35570 amit 352
                }
353
            }
354
        }
355
 
356
        Position position = positionRepository.selectPosition(authUserId, categoryId, regionId, createPositionModel.getEscalationType());
31762 tejbeer 357
        if (position == null) {
358
            position = new Position();
35570 amit 359
            position.setAuthUserId(authUserId);
360
            position.setCategoryId(categoryId);
31762 tejbeer 361
            position.setEscalationType(createPositionModel.getEscalationType());
35570 amit 362
            position.setRegionId(regionId);
31762 tejbeer 363
            position.setCreateTimestamp(LocalDateTime.now());
364
            position.setTicketAssignee(createPositionModel.isTicketAssigned());
365
            positionRepository.persist(position);
25570 tejbeer 366
 
35570 amit 367
            if (fofoIds != null) {
368
                for (int fofoId : fofoIds) {
369
                    PartnerPosition partnerPosition = new PartnerPosition();
370
                    partnerPosition.setFofoId(fofoId);
371
                    partnerPosition.setRegionId(regionId);
372
                    partnerPosition.setPositionId(position.getId());
373
                    partnerPositionRepository.persist(partnerPosition);
374
                    LOGGER.info("partnerPosition" + partnerPosition);
375
                }
31762 tejbeer 376
            }
24417 govind 377
 
31762 tejbeer 378
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));
379
        } else {
35570 amit 380
            throw new ProfitMandiBusinessException("Position", authUserId, "already exists!");
31762 tejbeer 381
        }
382
        return "response";
383
    }
25570 tejbeer 384
 
31762 tejbeer 385
    @PostMapping(value = "/cs/updatePartnerPosition")
386
    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 387
 
35571 amit 388
        // Validate positionId exists
389
        Position position = positionRepository.selectById(positionId);
390
        if (position == null) {
391
            throw new ProfitMandiBusinessException("Position", positionId, "Position not found");
392
        }
393
 
394
        // Validate regionId exists (0 or 5 typically means "All Partners/Regions")
395
        if (regionId > 0 && regionId != 5 && regionRepository.selectById(regionId) == null) {
396
            throw new ProfitMandiBusinessException("Position", regionId, "Invalid regionId");
397
        }
398
 
35589 amit 399
        // Validate fofoIds exist (0 means "All Partners")
35590 amit 400
        if (selectedFofoIds == null || selectedFofoIds.isEmpty()) {
401
            throw new ProfitMandiBusinessException("Position", 0, "At least one partner must be specified");
402
        }
403
        boolean hasAllPartners = selectedFofoIds.contains(0);
404
        if (hasAllPartners && selectedFofoIds.size() > 1) {
405
            throw new ProfitMandiBusinessException("Position", 0, "Cannot mix 'All Partners' (0) with specific partner IDs");
406
        }
407
        if (!hasAllPartners) {
35607 amit 408
            // Use direct database query instead of cached retailerService to include newly added partners
409
            Set<Integer> validFofoIds = fofoStoreRepository.selectAll().stream()
410
                    .map(fs -> fs.getId())
411
                    .collect(Collectors.toSet());
35590 amit 412
            for (int fofoId : selectedFofoIds) {
35607 amit 413
                if (!validFofoIds.contains(fofoId)) {
35590 amit 414
                    throw new ProfitMandiBusinessException("Position", fofoId, "Invalid fofoId");
35571 amit 415
                }
416
            }
417
        }
418
 
32493 amit.gupta 419
        partnerPositionRepository.delete(positionId);
35571 amit 420
        if (selectedFofoIds != null) {
421
            for (int fofoId : selectedFofoIds) {
422
                PartnerPosition partnerPosition = new PartnerPosition();
423
                partnerPosition.setFofoId(fofoId);
424
                partnerPosition.setRegionId(regionId);
425
                partnerPosition.setPositionId(positionId);
426
                partnerPositionRepository.persist(partnerPosition);
427
            }
31762 tejbeer 428
        }
25570 tejbeer 429
 
31762 tejbeer 430
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
25570 tejbeer 431
 
31762 tejbeer 432
        return "response";
433
    }
24417 govind 434
 
31762 tejbeer 435
    @GetMapping(value = "/cs/createTicket")
436
    public String createTicket(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
437
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
35594 amit 438
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
439
        boolean isCrmUser = false;
440
 
31762 tejbeer 441
        List<TicketCategory> ticketCategories = csService.getAllTicketCategotyFromSubCategory();
35594 amit 442
 
443
        if (isAdmin) {
444
            AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
445
            isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
446
 
447
            // CRM users should not see Sales and RBM categories
448
            if (isCrmUser) {
449
                ticketCategories = ticketCategories.stream()
450
                        .filter(tc -> tc.getId() != ProfitMandiConstants.TICKET_CATEGORY_SALES
451
                                && tc.getId() != ProfitMandiConstants.TICKET_CATEGORY_RBM)
452
                        .collect(Collectors.toList());
453
            }
454
        }
455
 
456
        model.addAttribute("roleType", isAdmin);
31762 tejbeer 457
        model.addAttribute("ticketCategories", ticketCategories);
35594 amit 458
        model.addAttribute("isCrmUser", isCrmUser);
31762 tejbeer 459
        return "create-ticket";
460
    }
24417 govind 461
 
31762 tejbeer 462
    @GetMapping(value = "/cs/getSubCategoriesByCategoryId")
35594 amit 463
    public String getSubCategoriesByCategoryId(HttpServletRequest request, @RequestParam(name = "categoryId", defaultValue = "0") int categoryId, Model model) throws ProfitMandiBusinessException {
464
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
465
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
466
        boolean isCrmUser = false;
467
 
468
        if (isAdmin) {
469
            AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
470
            isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
471
        }
472
 
31830 amit.gupta 473
        List<TicketSubCategory> ticketSubCategories = ticketSubCategoryRepository.selectAllVisible(categoryId);
35594 amit 474
 
475
        // CRM users should not see Sales Escalation and RBM Escalation subcategories
476
        if (isCrmUser) {
477
            ticketSubCategories = ticketSubCategories.stream()
478
                    .filter(tsc -> tsc.getId() != ProfitMandiConstants.TICKET_SUBCATEGORY_SALES_ESCALATION
479
                            && tsc.getId() != ProfitMandiConstants.TICKET_SUBCATEGORY_RBM_ESCALATION)
480
                    .collect(Collectors.toList());
481
        }
482
 
31762 tejbeer 483
        LOGGER.info(ticketSubCategories);
484
        model.addAttribute("ticketSubCategories", ticketSubCategories);
485
        return "ticket-sub-categories";
486
    }
24417 govind 487
 
24791 govind 488
 
31762 tejbeer 489
    @GetMapping(value = "/cs/getEscalationTypeByCategoryId")
490
    public String getEscalationTypeByCategoryId(HttpServletRequest request, @RequestParam(name = "categoryId", defaultValue = "0") int categoryId, @RequestParam(name = "authId", defaultValue = "0") int authId, Model model) {
491
        List<Position> positions = positionRepository.selectPositionbyCategoryIdAndAuthId(categoryId, authId);
492
        List<EscalationType> escalationTypes = new ArrayList<>();
24791 govind 493
 
31762 tejbeer 494
        if (!positions.isEmpty()) {
495
            escalationTypes = positions.stream().map(x -> x.getEscalationType()).distinct().collect(Collectors.toList());
496
        }
24620 govind 497
 
31762 tejbeer 498
        LOGGER.info("escalationTypes {}", escalationTypes);
24500 govind 499
 
31762 tejbeer 500
        model.addAttribute("escalationTypes", escalationTypes);
501
        return "ticket-escalationtype";
502
    }
24500 govind 503
 
24824 govind 504
 
31762 tejbeer 505
    @GetMapping(value = "/cs/getCategoriesByAuthId")
506
    public String getCategoriesByAuthId(HttpServletRequest request, @RequestParam(name = "authId", defaultValue = "0") int authId, Model model) {
24824 govind 507
 
24787 govind 508
 
31762 tejbeer 509
        List<Position> positions = positionRepository.selectPositionByAuthId(authId);
24791 govind 510
 
31762 tejbeer 511
        LOGGER.info("positions {}", positions);
24417 govind 512
 
31762 tejbeer 513
        List<TicketCategory> ticketCategories = new ArrayList<TicketCategory>();
24417 govind 514
 
31762 tejbeer 515
        if (!positions.isEmpty()) {
24417 govind 516
 
31762 tejbeer 517
            List<Integer> categoryIds = positions.stream().map(x -> x.getCategoryId()).collect(Collectors.toList());
518
            ticketCategories = ticketCategoryRepository.selectAll(categoryIds);
519
        }
520
        LOGGER.info("ticketCategories {}", ticketCategories);
521
        model.addAttribute("ticketCategories", ticketCategories);
522
        return "ticket-categories";
523
    }
27270 tejbeer 524
 
31762 tejbeer 525
    @PostMapping(value = "/cs/createTicket")
526
    public String createTicket(HttpServletRequest request, @RequestParam(name = "categoryId") int categoryId, @RequestParam(name = "subCategoryId") int subCategoryId, @RequestParam(name = "message") String message, Model model) throws Exception {
527
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
528
        List<Ticket> tickets = ticketRepository.selectAllResolvedMarkedTicketByCreator(loginDetails.getFofoId());
529
        if (tickets.size() > 3 || tickets.size() == 3) {
530
            model.addAttribute("response1", mvcResponseSender.createResponseString(false));
531
        } else {
532
            csService.createTicket(loginDetails.getFofoId(), categoryId, subCategoryId, message);
533
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));
534
        }
535
        return "response";
536
    }
27270 tejbeer 537
 
31762 tejbeer 538
    @GetMapping(value = "/cs/myticket")
539
    public String getTicket(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 {
540
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
541
        List<Ticket> tickets = null;
542
        List<TicketAssigned> ticketAssigneds = null;
543
        long size = 0;
544
        Map<Integer, AuthUser> authUserIdAndAuthUserMap = null;
35569 amit 545
        boolean isAdmin = roleManager.isAdmin(new HashSet<>(loginDetails.getRoleIds()));
546
        AuthUser currentAuthUser = isAdmin ? authRepository.selectByEmailOrMobile(loginDetails.getEmailId()) : null;
547
 
35592 amit 548
        // Check if user is CRM category - CRM users see ALL tickets to handle partner communications
549
        boolean isCrmUser = isAdmin && currentAuthUser != null && positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
35603 amit 550
        // Check if user is Sales category - Sales users can resolve their own Sales tickets
551
        boolean isSalesUser = isAdmin && currentAuthUser != null && positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_SALES);
552
        // Check if user is RBM category - RBM users can resolve their own RBM tickets
553
        boolean isRbmUser = isAdmin && currentAuthUser != null && positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_RBM);
35592 amit 554
 
35569 amit 555
        if (isAdmin) {
556
            int authUserId = currentAuthUser.getId();
35592 amit 557
 
558
            if (isCrmUser) {
35601 amit 559
                // CRM users see ALL tickets EXCEPT Sales Escalation and RBM Escalation subcategories
31762 tejbeer 560
                if (ticketStatus.equals(TicketStatus.RESOLVED)) {
35592 amit 561
                    tickets = ticketRepository.selectAllTickets(Optional.empty(), sortOrder, ticketSearchType, searchTerm);
31762 tejbeer 562
                } else {
35592 amit 563
                    tickets = ticketRepository.selectAllTickets(Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), sortOrder, ticketSearchType, searchTerm);
31762 tejbeer 564
                }
35601 amit 565
 
566
                // Filter out Sales Escalation and RBM Escalation subcategory tickets for CRM users
567
                tickets = tickets.stream()
568
                        .filter(t -> t.getSubCategoryId() != ProfitMandiConstants.TICKET_SUBCATEGORY_SALES_ESCALATION
569
                                && t.getSubCategoryId() != ProfitMandiConstants.TICKET_SUBCATEGORY_RBM_ESCALATION)
570
                        .collect(Collectors.toList());
571
                size = tickets.size();
31762 tejbeer 572
            } else {
35592 amit 573
                // Non-CRM admins see only tickets assigned to them
574
                if (ticketSearchType == null) {
575
                    if (ticketStatus.equals(TicketStatus.RESOLVED)) {
576
                        tickets = ticketRepository.selectAllByAssignee(authUserId, Optional.empty(), sortOrder, null, searchTerm);
577
                        size = ticketRepository.selectAllCountByAssignee(authUserId, Optional.empty(), null, searchTerm);
578
                    } else {
579
                        tickets = ticketRepository.selectAllByAssignee(authUserId, Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), sortOrder, null, searchTerm);
580
                        size = ticketRepository.selectAllCountByAssignee(authUserId, Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), null, searchTerm);
581
                    }
31762 tejbeer 582
                } else {
35592 amit 583
                    if (ticketStatus.equals(TicketStatus.RESOLVED)) {
584
                        tickets = ticketRepository.selectAllByAssignee(authUserId, Optional.empty(), sortOrder, ticketSearchType, searchTerm);
585
                        size = ticketRepository.selectAllCountByAssignee(authUserId, Optional.empty(), ticketSearchType, searchTerm);
586
                    } else {
587
                        tickets = ticketRepository.selectAllByAssignee(authUserId, Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), sortOrder, ticketSearchType, searchTerm);
588
                        size = ticketRepository.selectAllCountByAssignee(authUserId, Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), ticketSearchType, searchTerm);
589
                    }
31762 tejbeer 590
                }
591
            }
592
            // LOGGER.info(size + "size");
593
            if (tickets.size() > 0) {
594
                ticketAssigneds = ticketAssignedRepository.selectByTicketIds(tickets.stream().map(x -> x.getId()).collect(Collectors.toList()));
595
                authUserIdAndAuthUserMap = csService.getAuthUserIdAndAuthUserMap(ticketAssigneds);
596
                Map<Integer, CustomRetailer> fofoIdsAndCustomRetailer = csService.getPartnerByFofoIds(tickets);
597
                model.addAttribute("fofoIdsAndCustomRetailer", fofoIdsAndCustomRetailer);
598
            }
24500 govind 599
 
31762 tejbeer 600
        } else {
601
            tickets = ticketRepository.selectAllByCreator(loginDetails.getFofoId(), Optional.of(TicketStatus.OPENED.equals(ticketStatus)), sortOrder);
602
            size = ticketRepository.selectAllCountByCreator(loginDetails.getFofoId(), Optional.of(TicketStatus.OPENED.equals(ticketStatus)));
603
        }
604
        authUserIdAndAuthUserMap = csService.getTicketIdAndAuthUserMapUsingTickets(tickets);
35571 amit 605
        if (authUserIdAndAuthUserMap == null) {
606
            authUserIdAndAuthUserMap = new HashMap<>();
607
        }
24620 govind 608
 
31762 tejbeer 609
        model.addAttribute("size", size);
35569 amit 610
        model.addAttribute("roleType", isAdmin);
35592 amit 611
        // isCrmUser already calculated at start of method
35569 amit 612
        model.addAttribute("isCrmUser", isCrmUser);
35603 amit 613
        model.addAttribute("isSalesUser", isSalesUser);
614
        model.addAttribute("salesCategoryId", ProfitMandiConstants.TICKET_CATEGORY_SALES);
615
        model.addAttribute("isRbmUser", isRbmUser);
616
        model.addAttribute("rbmCategoryId", ProfitMandiConstants.TICKET_CATEGORY_RBM);
24500 govind 617
 
31762 tejbeer 618
        List<Integer> subCategoryIds = tickets.stream().map(x -> x.getSubCategoryId()).collect(Collectors.toList());
619
        Map<Integer, TicketSubCategory> subCategoryIdAndSubCategoryMap = csService.getSubCategoryIdAndSubCategoryMap(subCategoryIds);
35571 amit 620
        if (subCategoryIdAndSubCategoryMap == null) {
621
            subCategoryIdAndSubCategoryMap = new HashMap<>();
622
        }
24747 govind 623
 
31762 tejbeer 624
        Map<Integer, TicketCategory> subCategoryIdAndCategoryMap = csService.getSubCategoryIdAndCategoryMap(subCategoryIds);
35571 amit 625
        if (subCategoryIdAndCategoryMap == null) {
626
            subCategoryIdAndCategoryMap = new HashMap<>();
627
        }
27318 amit.gupta 628
 
31762 tejbeer 629
        List<Integer> ticketIds = tickets.stream().map(x -> x.getId()).collect(Collectors.toList());
24500 govind 630
 
35569 amit 631
        Map<Integer, List<Activity>> activityMap = new HashMap<>();
33864 ranu 632
        Map<Integer, List<Activity>> activityMapWithActivityId = new HashMap<>();
35569 amit 633
        Map<Integer, AuthUser> authUserMap = new HashMap<>();
24500 govind 634
 
31762 tejbeer 635
        if (!ticketIds.isEmpty()) {
35569 amit 636
            // Fetch activities once and group by both ticketId and activityId
637
            List<Activity> allActivities = activityRepository.selectAll(ticketIds);
638
            activityMap = allActivities.stream().collect(Collectors.groupingBy(Activity::getTicketId));
639
            activityMapWithActivityId = allActivities.stream().collect(Collectors.groupingBy(Activity::getId));
24787 govind 640
 
35569 amit 641
            // Only fetch AuthUsers who created activities (instead of all users)
642
            Set<Integer> activityCreatorIds = allActivities.stream()
643
                    .map(Activity::getCreatedBy)
644
                    .filter(id -> id > 0)
645
                    .collect(Collectors.toSet());
646
            if (!activityCreatorIds.isEmpty()) {
647
                authUserMap = authRepository.selectByIds(new ArrayList<>(activityCreatorIds))
648
                        .stream().collect(Collectors.toMap(AuthUser::getId, x -> x));
649
            }
31762 tejbeer 650
        }
24787 govind 651
 
31762 tejbeer 652
        model.addAttribute("tickets", tickets);
653
        model.addAttribute("resolved", ActivityType.RESOLVED);
654
        model.addAttribute("resolved-accepted", ActivityType.RESOLVED_ACCEPTED);
655
        model.addAttribute("resolved-rejected", ActivityType.RESOLVED_REJECTED);
656
        model.addAttribute("authUserIdAndAuthUserMap", authUserIdAndAuthUserMap);
657
        model.addAttribute("subCategoryIdAndSubCategoryMap", subCategoryIdAndSubCategoryMap);
27318 amit.gupta 658
 
31762 tejbeer 659
        model.addAttribute("subCategoryIdAndCategoryMap", subCategoryIdAndCategoryMap);
660
        model.addAttribute("activityMap", activityMap);
33864 ranu 661
        model.addAttribute("authUserMap", authUserMap);
662
        model.addAttribute("activityMapWithActivityId", activityMapWithActivityId);
24500 govind 663
 
31762 tejbeer 664
        model.addAttribute("ticketStatusValues", TicketStatus.values());
665
        model.addAttribute("orderByValues", SortOrder.values());
666
        model.addAttribute("selectedticketStatus", ticketStatus);
667
        model.addAttribute("selectedorderby", sortOrder);
668
        model.addAttribute("ticketSearchTypes", TicketSearchType.values());
669
        model.addAttribute("ticketSearchType", ticketSearchType);
670
        model.addAttribute("searchTerm", searchTerm);
671
        return "ticket";
672
    }
24500 govind 673
 
27124 amit.gupta 674
 
31762 tejbeer 675
    @GetMapping(value = "/cs/getActivities")
676
    public String getActivity(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, Model model) throws Exception {
35592 amit 677
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
678
        Ticket ticket = ticketRepository.selectById(ticketId);
679
 
680
        if (ticket == null) {
681
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
682
        }
683
 
684
        // Authorization check: verify user has access to this ticket
685
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
686
        if (!isAdmin) {
687
            // Partners can only view their own tickets
688
            if (ticket.getFofoId() != loginDetails.getFofoId()) {
689
                throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to view this ticket");
690
            }
691
        } else {
692
            // Admins must be assigned to the ticket OR be CRM user OR be in the escalation chain
693
            AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
694
            boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
695
 
696
            if (!isCrmUser) {
697
                // Check if user is assigned or in escalation chain
698
                List<TicketAssigned> assignments = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
699
                boolean isAssigned = assignments.stream().anyMatch(ta -> ta.getAssineeId() == currentAuthUser.getId() || ta.getManagerId() == currentAuthUser.getId());
700
                boolean isInEscalationChain = ticket.getL1AuthUser() == currentAuthUser.getId() ||
701
                        ticket.getL2AuthUser() == currentAuthUser.getId() ||
702
                        ticket.getL3AuthUser() == currentAuthUser.getId() ||
703
                        ticket.getL4AuthUser() == currentAuthUser.getId() ||
704
                        ticket.getL5AuthUser() == currentAuthUser.getId();
705
 
706
                if (!isAssigned && !isInEscalationChain) {
707
                    throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to view this ticket");
708
                }
709
            }
710
        }
711
 
31762 tejbeer 712
        List<Activity> allactivities = activityRepository.selectAll(ticketId);
35570 amit 713
 
714
        // Batch fetch all documents for attachments (fix N+1 query)
715
        List<Integer> documentIds = allactivities.stream()
716
                .flatMap(a -> a.getActivityAttachment().stream())
717
                .map(ActivityAttachment::getDocumentId)
718
                .distinct()
719
                .collect(Collectors.toList());
720
 
721
        Map<Integer, Document> documentMap = Collections.emptyMap();
722
        if (!documentIds.isEmpty()) {
723
            documentMap = documentRepository.selectByIds(documentIds).stream()
724
                    .collect(Collectors.toMap(Document::getId, d -> d));
725
        }
726
 
727
        // Set document names transiently (do not persist during GET)
728
        for (Activity activity : allactivities) {
729
            for (ActivityAttachment attachment : activity.getActivityAttachment()) {
730
                Document document = documentMap.get(attachment.getDocumentId());
731
                if (document != null) {
732
                    attachment.setDocumentName(document.getDisplayName());
733
                }
31762 tejbeer 734
            }
735
        }
736
        List<Activity> activities = null;
35592 amit 737
        if (isAdmin) {
31762 tejbeer 738
            Set<Integer> authUserIds = allactivities.stream().map(x -> x.getCreatedBy()).collect(Collectors.toSet());
35395 amit 739
            List<AuthUser> users = authRepository.selectByIds(new ArrayList<>(authUserIds));
31762 tejbeer 740
            Map<Integer, String> authUserNameMap = users.stream().collect(Collectors.toMap(AuthUser::getId, x -> x.getFirstName() + " " + x.getLastName()));
741
            allactivities.stream().forEach(x -> x.setName(authUserNameMap.get(x.getCreatedBy())));
742
            activities = allactivities;
743
        } else {
744
            activities = allactivities.stream().filter(x -> ActivityType.PARTNER_ACTIVITIES.contains(x.getType())).collect(Collectors.toList());
745
        }
746
        if (activities == null) {
747
            throw new ProfitMandiBusinessException("Activity", ticketId, "No Activity Found");
748
        }
749
        model.addAttribute("response1", mvcResponseSender.createResponseString(activities));
750
        return "response";
24500 govind 751
 
31762 tejbeer 752
    }
24620 govind 753
 
31762 tejbeer 754
    @PostMapping(value = "/cs/createActivity")
755
    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 756
 
31762 tejbeer 757
                                 Model model) throws Exception {
24620 govind 758
 
31762 tejbeer 759
        LOGGER.info("documentIds" + documentIds);
760
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
761
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 762
 
763
        if (ticket == null) {
764
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
765
        }
766
 
767
        // Authorization check: verify user has access to add activity to this ticket
768
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
769
        if (!isAdmin) {
770
            // Partners can only add activity to their own tickets
771
            if (ticket.getFofoId() != loginDetails.getFofoId()) {
772
                throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to add activity to this ticket");
773
            }
774
        } else {
775
            // Admins must be assigned to the ticket OR be CRM user OR be in the escalation chain
776
            AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
777
            boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
778
 
779
            if (!isCrmUser) {
780
                List<TicketAssigned> assignments = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
781
                boolean isAssigned = assignments.stream().anyMatch(ta -> ta.getAssineeId() == currentAuthUser.getId() || ta.getManagerId() == currentAuthUser.getId());
782
                boolean isInEscalationChain = ticket.getL1AuthUser() == currentAuthUser.getId() ||
783
                        ticket.getL2AuthUser() == currentAuthUser.getId() ||
784
                        ticket.getL3AuthUser() == currentAuthUser.getId() ||
785
                        ticket.getL4AuthUser() == currentAuthUser.getId() ||
786
                        ticket.getL5AuthUser() == currentAuthUser.getId();
787
 
788
                if (!isAssigned && !isInEscalationChain) {
789
                    throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to add activity to this ticket");
790
                }
791
            }
792
        }
31762 tejbeer 793
        List<TicketAssigned> ticketAssignedList = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
794
        List<Integer> authUserIds = ticketAssignedList.stream().map(x -> x.getAssineeId()).collect(Collectors.toList());
795
        authUserIds.add(ticketAssignedList.get(ticketAssignedList.size() - 1).getManagerId());
35395 amit 796
        Map<Integer, AuthUser> authUsersMap = authRepository.selectByIds(authUserIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
31762 tejbeer 797
        if (ticket.getCloseTimestamp() == null) {
798
            Activity activity = new Activity();
799
            activity.setCreatedBy(0);
800
            activity.setCreateTimestamp(LocalDateTime.now());
801
            String subject = null;
802
            String mailMessage = null;
803
            activity.setMessage(message);
804
            if (!roleManager.isAdmin(new HashSet<>(loginDetails.getRoleIds()))) {
805
                CustomRetailer customRetailer = retailerService.getFofoRetailers(true).get(loginDetails.getFofoId());
806
                activity.setType(ActivityType.COMMUNICATION_IN);
807
                subject = String.format("Ticket Update #%s by franchisee %s", ticket.getId(), customRetailer.getBusinessName() + "(" + customRetailer.getCode() + ")");
808
                mailMessage = String.format("Franchisee message - %s", message);
809
            } else {
810
                AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
811
                activity.setCreatedBy(authUser.getId());
812
                authUsersMap.remove(authUser.getId());
813
                subject = String.format("Ticket Update #%s by %s", ticket.getId(), authUser.getName());
814
                mailMessage = String.format("%s's message - %s", authUser.getFirstName(), message);
35569 amit 815
                // Only CRM users can send external communications
816
                boolean isCrmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
817
                if (internal || !isCrmUser) {
31762 tejbeer 818
                    activity.setType(ActivityType.COMMUNICATION_INTERNAL);
819
                } else {
820
                    String updatedBy = "SD Team";
31854 amit.gupta 821
                    CustomRetailer customRetailer = retailerService.getFofoRetailers(false).get(ticket.getFofoId());
31762 tejbeer 822
                    subject = String.format("Ticket Update #%s by %s", ticket.getId(), updatedBy);
823
                    String partnerMessage = String.format("%s's message - %s", updatedBy, message);
824
                    this.activityRelatedMail(customRetailer.getEmail(), null, "subject", partnerMessage);
825
                    activity.setType(ActivityType.COMMUNICATION_OUT);
826
                }
827
            }
828
            activityRepository.persist(activity);
829
 
830
            for (Integer documentId : documentIds) {
831
                ActivityAttachment activityAttachment = new ActivityAttachment();
832
                activityAttachment.setActivityId(activity.getId());
833
                activityAttachment.setDocumentId(documentId);
834
                activityAttachmentRepository.persist(activityAttachment);
835
            }
836
 
837
            csService.addActivity(ticket, activity);
838
            AuthUser authUser = authUsersMap.remove(authUserIds.get(0));
839
            if (authUser == null) {
840
                authUser = authUsersMap.remove(authUserIds.get(1));
841
            }
842
            model.addAttribute("response1", mvcResponseSender.createResponseString(authUser));
843
            String[] cc = authUsersMap.entrySet().stream().map(x -> x.getValue().getEmailId()).toArray(String[]::new);
844
            this.activityRelatedMail(authUser.getEmailId(), cc, subject, mailMessage);
845
        } else {
846
            throw new ProfitMandiBusinessException("Ticket", ticket.getId(), "Already closed ticket");
847
        }
848
        return "response";
849
    }
850
 
851
    private void activityRelatedMail(String to, String[] cc, String subject, String message) throws ProfitMandiBusinessException {
852
        try {
853
            Utils.sendMailWithAttachments(mailSender, to, cc, subject, message, null);
854
        } catch (Exception e) {
855
            throw new ProfitMandiBusinessException("Ticket Activity", to, "Could not send ticket activity mail");
856
        }
857
    }
858
 
859
    @PostMapping(value = "/cs/closeTicket")
860
    public String closeTicket(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, @RequestParam(name = "happyCode") String happyCode, Model model) throws Exception {
35592 amit 861
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
31762 tejbeer 862
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 863
 
864
        if (ticket == null) {
865
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
866
        }
867
 
868
        // Authorization check: only the ticket owner (partner) can close the ticket
869
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
870
        if (isAdmin) {
871
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Only partners can close tickets using happy code");
872
        }
873
 
874
        // Verify the partner owns this ticket
875
        if (ticket.getFofoId() != loginDetails.getFofoId()) {
876
            throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to close this ticket");
877
        }
878
 
31762 tejbeer 879
        if (ticket.getHappyCode().equals(happyCode)) {
880
            ticket.setCloseTimestamp(LocalDateTime.now());
881
            ticketRepository.persist(ticket);
882
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));
883
        } else {
884
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Happy Code can't match");
885
        }
886
        return "response";
887
    }
888
 
34913 ranu 889
    @GetMapping(value = "/cs/myPartyTicketTicket")
890
    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 {
891
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
892
        long size = 0;
893
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
894
        List<Ticket> tickets = new ArrayList<>();
895
        Map<String, Set<Integer>> storeGuyMap = csService.getAuthUserPartnerIdMapping();
896
        Set<Integer> fofoIds = storeGuyMap.get(authUser.getEmailId());
897
 
898
        Map<Integer, List<AuthUser>> authUserListMap = null;
899
        if (fofoIds != null && !fofoIds.isEmpty()) {
35571 amit 900
            // Batch fetch all open tickets for all fofoIds (fix N+1 query)
901
            List<Ticket> allPartnerTickets = ticketRepository.selectAllOpenTickets(new ArrayList<>(fofoIds));
902
            if (allPartnerTickets != null && !allPartnerTickets.isEmpty()) {
903
                // Filter tickets where last_activity is not "RESOLVED"
904
                tickets = allPartnerTickets.stream()
905
                        .filter(ticket -> ticket.getLastActivity() == null ||
906
                                ticket.getLastActivity() != ActivityType.RESOLVED)
907
                        .collect(Collectors.toList());
34913 ranu 908
            }
909
        }
910
 
911
        authUserListMap = csService.getAssignedAuthList(tickets);
912
 
913
 
914
        if (tickets.size() > 0) {
915
            Map<Integer, CustomRetailer> fofoIdsAndCustomRetailer = csService.getPartnerByFofoIds(tickets);
916
            model.addAttribute("fofoIdsAndCustomRetailer", fofoIdsAndCustomRetailer);
917
        }
918
 
919
        model.addAttribute("size", tickets.size());
920
        model.addAttribute("tickets", tickets);
921
 
922
        List<Integer> subCategoryIds = tickets.stream().map(x -> x.getSubCategoryId()).collect(Collectors.toList());
923
        Map<Integer, TicketSubCategory> subCategoryIdAndSubCategoryMap = csService.getSubCategoryIdAndSubCategoryMap(subCategoryIds);
35571 amit 924
        if (subCategoryIdAndSubCategoryMap == null) {
925
            subCategoryIdAndSubCategoryMap = new HashMap<>();
926
        }
34913 ranu 927
 
928
        Map<Integer, TicketCategory> subCategoryIdAndCategoryMap = csService.getSubCategoryIdAndCategoryMap(subCategoryIds);
35571 amit 929
        if (subCategoryIdAndCategoryMap == null) {
930
            subCategoryIdAndCategoryMap = new HashMap<>();
931
        }
34913 ranu 932
 
933
        List<Integer> ticketIds = tickets.stream().map(x -> x.getId()).collect(Collectors.toList());
934
        Map<Integer, List<Activity>> activityMap = new HashMap<>();
935
        Map<Integer, List<Activity>> activityMapWithActivityId = new HashMap<>();
35569 amit 936
        Map<Integer, AuthUser> authUserMap = new HashMap<>();
34913 ranu 937
 
938
        if (!ticketIds.isEmpty()) {
35569 amit 939
            // Fetch activities once and group by both ticketId and activityId
940
            List<Activity> allActivities = activityRepository.selectAll(ticketIds);
941
            activityMap = allActivities.stream().collect(Collectors.groupingBy(Activity::getTicketId));
942
            activityMapWithActivityId = allActivities.stream().collect(Collectors.groupingBy(Activity::getId));
34913 ranu 943
 
35569 amit 944
            // Only fetch AuthUsers who created activities (instead of all users)
945
            Set<Integer> activityCreatorIds = allActivities.stream()
946
                    .map(Activity::getCreatedBy)
947
                    .filter(id -> id > 0)
948
                    .collect(Collectors.toSet());
949
            if (!activityCreatorIds.isEmpty()) {
950
                authUserMap = authRepository.selectByIds(new ArrayList<>(activityCreatorIds))
951
                        .stream().collect(Collectors.toMap(AuthUser::getId, x -> x));
952
            }
34913 ranu 953
        }
954
 
955
        model.addAttribute("ticketStatusValues", TicketStatus.values());
956
        model.addAttribute("orderByValues", SortOrder.values());
957
        model.addAttribute("selectedticketStatus", ticketStatus);
958
        model.addAttribute("selectedorderby", sortOrder);
959
        model.addAttribute("tickets", tickets);
960
        model.addAttribute("ticketSearchTypes", TicketSearchType.values());
961
        model.addAttribute("ticketSearchType", ticketSearchType);
962
        model.addAttribute("searchTerm", searchTerm);
35571 amit 963
        model.addAttribute("authUserListMap", authUserListMap != null ? authUserListMap : new HashMap<>());
34913 ranu 964
        model.addAttribute("subCategoryIdAndSubCategoryMap", subCategoryIdAndSubCategoryMap);
965
 
966
        model.addAttribute("subCategoryIdAndCategoryMap", subCategoryIdAndCategoryMap);
967
 
968
        model.addAttribute("activityMap", activityMap);
969
        model.addAttribute("authUserMap", authUserMap);
970
        model.addAttribute("activityMapWithActivityId", activityMapWithActivityId);
35569 amit 971
        // Check if user is in CRM category (only CRM can send external communications)
972
        boolean isCrmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
973
        model.addAttribute("isCrmUser", isCrmUser);
34913 ranu 974
 
975
        return "my-partner-tickets";
976
    }
977
 
31762 tejbeer 978
    @GetMapping(value = "/cs/managerTicket")
979
    public String getManagerTickets(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 {
980
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
981
        long size = 0;
982
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
35594 amit 983
        boolean isCrmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
984
 
31762 tejbeer 985
        List<Ticket> tickets = null;
986
        Map<Integer, List<AuthUser>> authUserListMap = null;
35594 amit 987
 
988
        // CRM users can see all tickets to assign them (like managers)
989
        if (isCrmUser) {
31762 tejbeer 990
            if (ticketStatus.equals(TicketStatus.RESOLVED)) {
35594 amit 991
                tickets = ticketRepository.selectAllTickets(Optional.empty(), sortOrder, ticketSearchType, searchTerm);
992
                size = ticketRepository.selectAllTicketsCount(Optional.empty(), ticketSearchType, searchTerm);
993
            } else {
994
                tickets = ticketRepository.selectAllTickets(Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), sortOrder, ticketSearchType, searchTerm);
995
                size = ticketRepository.selectAllTicketsCount(Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), ticketSearchType, searchTerm);
996
            }
997
        } else if (ticketSearchType == null) {
998
            if (ticketStatus.equals(TicketStatus.RESOLVED)) {
31762 tejbeer 999
                tickets = ticketRepository.selectAllManagerTicket(authUser.getId(), sortOrder, Optional.empty(), null, searchTerm);
1000
                size = ticketRepository.selectAllCountByManagerTicket(authUser.getId(), Optional.empty(), null, 0);
1001
            } else {
1002
                tickets = ticketRepository.selectAllManagerTicket(authUser.getId(), sortOrder, Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), null, searchTerm);
1003
                size = ticketRepository.selectAllCountByManagerTicket(authUser.getId(), Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), null, 0);
1004
            }
1005
        } else {
1006
            if (ticketStatus.equals(TicketStatus.RESOLVED)) {
1007
                tickets = ticketRepository.selectAllManagerTicket(authUser.getId(), sortOrder, Optional.empty(), ticketSearchType, searchTerm);
1008
                size = ticketRepository.selectAllCountByManagerTicket(authUser.getId(), Optional.empty(), ticketSearchType, searchTerm);
1009
            } else {
1010
                tickets = ticketRepository.selectAllManagerTicket(authUser.getId(), sortOrder, Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), ticketSearchType, searchTerm);
1011
                size = ticketRepository.selectAllCountByManagerTicket(authUser.getId(), Optional.of(TicketStatus.CLOSED.equals(ticketStatus)), ticketSearchType, searchTerm);
1012
            }
1013
 
1014
        }
1015
        authUserListMap = csService.getAssignedAuthList(tickets);
1016
 
1017
        if (tickets.size() > 0) {
1018
            Map<Integer, CustomRetailer> fofoIdsAndCustomRetailer = csService.getPartnerByFofoIds(tickets);
1019
            model.addAttribute("fofoIdsAndCustomRetailer", fofoIdsAndCustomRetailer);
1020
        }
1021
 
1022
        model.addAttribute("size", size);
1023
        model.addAttribute("tickets", tickets);
1024
 
1025
        List<Integer> subCategoryIds = tickets.stream().map(x -> x.getSubCategoryId()).collect(Collectors.toList());
1026
        Map<Integer, TicketSubCategory> subCategoryIdAndSubCategoryMap = csService.getSubCategoryIdAndSubCategoryMap(subCategoryIds);
35571 amit 1027
        if (subCategoryIdAndSubCategoryMap == null) {
1028
            subCategoryIdAndSubCategoryMap = new HashMap<>();
1029
        }
31762 tejbeer 1030
 
1031
        Map<Integer, TicketCategory> subCategoryIdAndCategoryMap = csService.getSubCategoryIdAndCategoryMap(subCategoryIds);
35571 amit 1032
        if (subCategoryIdAndCategoryMap == null) {
1033
            subCategoryIdAndCategoryMap = new HashMap<>();
1034
        }
31762 tejbeer 1035
 
1036
        List<Integer> ticketIds = tickets.stream().map(x -> x.getId()).collect(Collectors.toList());
1037
        Map<Integer, List<Activity>> activityMap = new HashMap<>();
33778 ranu 1038
        Map<Integer, List<Activity>> activityMapWithActivityId = new HashMap<>();
35570 amit 1039
        Map<Integer, AuthUser> authUserMap = new HashMap<>();
31762 tejbeer 1040
 
1041
        if (!ticketIds.isEmpty()) {
35570 amit 1042
            // Fetch activities once and reuse for both maps (fix duplicate query)
1043
            List<Activity> allActivities = activityRepository.selectAll(ticketIds);
1044
            activityMap = allActivities.stream().collect(Collectors.groupingBy(Activity::getTicketId));
1045
            activityMapWithActivityId = allActivities.stream().collect(Collectors.groupingBy(Activity::getId));
31762 tejbeer 1046
 
35570 amit 1047
            // Only fetch users who created activities (fix loading ALL users)
1048
            Set<Integer> activityCreatorIds = allActivities.stream()
1049
                    .map(Activity::getCreatedBy)
1050
                    .filter(id -> id > 0)
1051
                    .collect(Collectors.toSet());
1052
            if (!activityCreatorIds.isEmpty()) {
1053
                authUserMap = authRepository.selectByIds(new ArrayList<>(activityCreatorIds))
1054
                        .stream().collect(Collectors.toMap(AuthUser::getId, x -> x));
1055
            }
31762 tejbeer 1056
        }
33778 ranu 1057
 
31762 tejbeer 1058
        model.addAttribute("ticketStatusValues", TicketStatus.values());
1059
        model.addAttribute("orderByValues", SortOrder.values());
1060
        model.addAttribute("selectedticketStatus", ticketStatus);
1061
        model.addAttribute("selectedorderby", sortOrder);
1062
        model.addAttribute("tickets", tickets);
1063
        model.addAttribute("ticketSearchTypes", TicketSearchType.values());
1064
        model.addAttribute("ticketSearchType", ticketSearchType);
1065
        model.addAttribute("searchTerm", searchTerm);
1066
        model.addAttribute("authUserListMap", authUserListMap);
1067
        model.addAttribute("subCategoryIdAndSubCategoryMap", subCategoryIdAndSubCategoryMap);
1068
 
1069
        model.addAttribute("subCategoryIdAndCategoryMap", subCategoryIdAndCategoryMap);
1070
 
1071
        model.addAttribute("activityMap", activityMap);
33778 ranu 1072
        model.addAttribute("authUserMap", authUserMap);
1073
        model.addAttribute("activityMapWithActivityId", activityMapWithActivityId);
35594 amit 1074
        model.addAttribute("isCrmUser", isCrmUser);
31762 tejbeer 1075
 
1076
        return "managerTicket";
1077
    }
1078
 
1079
 
1080
    @GetMapping(value = "/cs/edit-ticket")
35594 amit 1081
    public String getEditTicket(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, Model model) throws ProfitMandiBusinessException {
1082
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1083
        AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1084
        boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1085
 
31762 tejbeer 1086
        Ticket ticket = ticketRepository.selectById(ticketId);
1087
        List<TicketCategory> ticketCategories = csService.getAllTicketCategotyFromSubCategory();
1088
        TicketSubCategory ticketSubCategory = ticketSubCategoryRepository.selectById(ticket.getSubCategoryId());
1089
        List<TicketSubCategory> ticketSubCategories = ticketSubCategoryRepository.selectAll(ticketSubCategory.getCategoryId());
1090
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
35594 amit 1091
 
1092
        // CRM users should not see Sales/RBM categories and their Escalation subcategories
1093
        if (isCrmUser) {
1094
            ticketCategories = ticketCategories.stream()
1095
                    .filter(tc -> tc.getId() != ProfitMandiConstants.TICKET_CATEGORY_SALES
1096
                            && tc.getId() != ProfitMandiConstants.TICKET_CATEGORY_RBM)
1097
                    .collect(Collectors.toList());
1098
            ticketSubCategories = ticketSubCategories.stream()
1099
                    .filter(tsc -> tsc.getId() != ProfitMandiConstants.TICKET_SUBCATEGORY_SALES_ESCALATION
1100
                            && tsc.getId() != ProfitMandiConstants.TICKET_SUBCATEGORY_RBM_ESCALATION)
1101
                    .collect(Collectors.toList());
1102
        }
1103
 
1104
        // Get partner name for modal title
1105
        String partnerName = retailerService.getFofoRetailer(ticket.getFofoId()).getBusinessName();
1106
 
31762 tejbeer 1107
        model.addAttribute("ticket", ticket);
1108
        model.addAttribute("ticketCategories", ticketCategories);
1109
        model.addAttribute("ticketSubCategories", ticketSubCategories);
1110
        model.addAttribute("ticketSubCategory", ticketSubCategory);
1111
        model.addAttribute("authUsers", authUsers);
35594 amit 1112
        model.addAttribute("isCrmUser", isCrmUser);
1113
        model.addAttribute("partnerName", partnerName);
31762 tejbeer 1114
        return "edit-ticket-modal";
1115
    }
1116
 
34913 ranu 1117
    @GetMapping(value = "/cs/edit-partner-ticket")
35594 amit 1118
    public String getEditPartnerTicket(HttpServletRequest request, @RequestParam(name = "ticketId", defaultValue = "0") int ticketId, Model model) throws ProfitMandiBusinessException {
1119
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1120
        AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1121
        boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1122
 
34913 ranu 1123
        Ticket ticket = ticketRepository.selectById(ticketId);
1124
        List<TicketCategory> ticketCategories = csService.getAllTicketCategotyFromSubCategory();
1125
        TicketSubCategory ticketSubCategory = ticketSubCategoryRepository.selectById(ticket.getSubCategoryId());
1126
        List<TicketSubCategory> ticketSubCategories = ticketSubCategoryRepository.selectAll(ticketSubCategory.getCategoryId());
1127
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
35594 amit 1128
 
1129
        // CRM users should not see Sales/RBM categories and their Escalation subcategories
1130
        if (isCrmUser) {
1131
            ticketCategories = ticketCategories.stream()
1132
                    .filter(tc -> tc.getId() != ProfitMandiConstants.TICKET_CATEGORY_SALES
1133
                            && tc.getId() != ProfitMandiConstants.TICKET_CATEGORY_RBM)
1134
                    .collect(Collectors.toList());
1135
            ticketSubCategories = ticketSubCategories.stream()
1136
                    .filter(tsc -> tsc.getId() != ProfitMandiConstants.TICKET_SUBCATEGORY_SALES_ESCALATION
1137
                            && tsc.getId() != ProfitMandiConstants.TICKET_SUBCATEGORY_RBM_ESCALATION)
1138
                    .collect(Collectors.toList());
1139
        }
1140
 
1141
        // Get partner name for modal title
1142
        String partnerName = retailerService.getFofoRetailer(ticket.getFofoId()).getBusinessName();
1143
 
34913 ranu 1144
        model.addAttribute("ticket", ticket);
1145
        model.addAttribute("ticketCategories", ticketCategories);
1146
        model.addAttribute("ticketSubCategories", ticketSubCategories);
1147
        model.addAttribute("ticketSubCategory", ticketSubCategory);
1148
        model.addAttribute("authUsers", authUsers);
35594 amit 1149
        model.addAttribute("isCrmUser", isCrmUser);
1150
        model.addAttribute("partnerName", partnerName);
34913 ranu 1151
        return "edit-ticket-partner-modal";
1152
    }
1153
 
31762 tejbeer 1154
    @PostMapping(value = "/cs/edit-ticket")
1155
    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 {
1156
        LOGGER.info("Ticket Id {}, CategoryId {}, SubCategory Id {} authUserId {}", ticketId, categoryId, subCategoryId, authUserId);
35592 amit 1157
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1158
 
1159
        // Only admins can edit tickets
1160
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
1161
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Only admins can edit tickets");
1162
        }
1163
 
31762 tejbeer 1164
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 1165
        if (ticket == null) {
1166
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
1167
        }
1168
 
1169
        // Verify admin has access to this ticket (assigned, manager, escalation chain, or CRM)
1170
        AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1171
        boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1172
 
1173
        if (!isCrmUser) {
1174
            List<TicketAssigned> assignments = ticketAssignedRepository.selectByTicketIds(Arrays.asList(ticketId));
1175
            boolean isAssigned = assignments.stream().anyMatch(ta -> ta.getAssineeId() == currentAuthUser.getId() || ta.getManagerId() == currentAuthUser.getId());
1176
            boolean isInEscalationChain = ticket.getL1AuthUser() == currentAuthUser.getId() ||
1177
                    ticket.getL2AuthUser() == currentAuthUser.getId() ||
1178
                    ticket.getL3AuthUser() == currentAuthUser.getId() ||
1179
                    ticket.getL4AuthUser() == currentAuthUser.getId() ||
1180
                    ticket.getL5AuthUser() == currentAuthUser.getId();
1181
 
1182
            if (!isAssigned && !isInEscalationChain) {
1183
                throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to edit this ticket");
1184
            }
1185
        }
1186
 
31762 tejbeer 1187
        csService.updateTicket(categoryId, subCategoryId, ticket, authUserId, escalationType);
1188
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1189
        return "response";
1190
 
1191
    }
1192
 
34913 ranu 1193
    @PostMapping(value = "/cs/edit-partner-ticket")
1194
    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 {
1195
        LOGGER.info("Ticket Id {}, CategoryId {}, SubCategory Id {} authUserId {}", ticketId, categoryId, subCategoryId, authUserId);
35592 amit 1196
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1197
 
1198
        // Only admins can edit partner tickets
1199
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
1200
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Only admins can edit partner tickets");
1201
        }
1202
 
34913 ranu 1203
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 1204
        if (ticket == null) {
1205
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
1206
        }
1207
 
1208
        // Verify admin has access (must be in Sales, ABM, or RBM position for the partner)
1209
        AuthUser currentAuthUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1210
        Map<String, Set<Integer>> authUserPartnerMap = csService.getAuthUserPartnerIdMapping();
1211
        Set<Integer> allowedPartnerIds = authUserPartnerMap.get(currentAuthUser.getEmailId());
1212
 
1213
        if (allowedPartnerIds == null || !allowedPartnerIds.contains(ticket.getFofoId())) {
1214
            // Also allow CRM users
1215
            boolean isCrmUser = positionRepository.hasCategory(currentAuthUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
1216
            if (!isCrmUser) {
1217
                throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to edit this partner's ticket");
1218
            }
1219
        }
1220
 
34913 ranu 1221
        csService.updateTicket(categoryId, subCategoryId, ticket, authUserId, escalationType);
1222
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1223
        return "response";
1224
 
1225
    }
1226
 
31762 tejbeer 1227
    @PostMapping(value = "/cs/changeTicketAssignee")
1228
    public String changeTicketAssignee(HttpServletRequest request, @RequestParam(name = "positionId", defaultValue = "0") int positionId, Model model) throws Exception {
1229
        Position position = positionRepository.selectById(positionId);
1230
        if (position.isTicketAssignee()) {
1231
            position.setTicketAssignee(false);
1232
        } else {
1233
            position.setTicketAssignee(true);
1234
        }
1235
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1236
        return "response";
1237
    }
1238
 
1239
 
1240
    @DeleteMapping(value = "/cs/removePosition")
1241
    public String removePosition(HttpServletRequest request, @RequestParam(name = "positionId", defaultValue = "0") int positionId, Model model) throws Exception {
1242
        positionRepository.delete(positionId);
1243
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1244
        return "response";
1245
    }
1246
 
1247
    @PostMapping(value = "/cs/create-last-activity")
1248
    public String createlastActivity(HttpServletRequest request, @RequestParam(name = "ticketId") int ticketId, @RequestParam(name = "lastactivity") ActivityType lastActivity, Model model) throws Exception {
1249
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
1250
        Ticket ticket = ticketRepository.selectById(ticketId);
35592 amit 1251
 
1252
        if (ticket == null) {
1253
            throw new ProfitMandiBusinessException("Ticket", ticketId, "Ticket not found");
1254
        }
1255
 
1256
        // Authorization check for partners: can only update their own tickets
1257
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
1258
        if (!isAdmin && ticket.getFofoId() != loginDetails.getFofoId()) {
1259
            throw new ProfitMandiBusinessException("Ticket", ticketId, "You do not have permission to update this ticket");
1260
        }
1261
 
31762 tejbeer 1262
        Activity activity = new Activity();
1263
        String subject = String.format(ACTIVITY_SUBJECT, ticket.getId());
35592 amit 1264
        if (isAdmin) {
35603 amit 1265
            // CRM team members can resolve any ticket
1266
            // Sales team members can resolve their own Sales category tickets
1267
            // RBM team members can resolve their own RBM category tickets
35592 amit 1268
            AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
1269
            boolean isCrmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_CRM);
35603 amit 1270
            boolean isSalesUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_SALES);
1271
            boolean isRbmUser = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_RBM);
1272
 
1273
            // Check if ticket belongs to Sales or RBM category
1274
            TicketSubCategory ticketSubCategory = ticketSubCategoryRepository.selectById(ticket.getSubCategoryId());
1275
            boolean isSalesTicket = ticketSubCategory != null && ticketSubCategory.getCategoryId() == ProfitMandiConstants.TICKET_CATEGORY_SALES;
1276
            boolean isRbmTicket = ticketSubCategory != null && ticketSubCategory.getCategoryId() == ProfitMandiConstants.TICKET_CATEGORY_RBM;
1277
 
1278
            // Allow if CRM user OR (Sales user AND Sales ticket) OR (RBM user AND RBM ticket)
1279
            if (!isCrmUser && !(isSalesUser && isSalesTicket) && !(isRbmUser && isRbmTicket)) {
1280
                throw new ProfitMandiBusinessException("Ticket", ticketId, "Only CRM, Sales (for Sales tickets), or RBM (for RBM tickets) team can mark tickets as resolved");
35592 amit 1281
            }
31762 tejbeer 1282
            ticket.setLastActivity(lastActivity);
1283
            String to = retailerService.getFofoRetailer(ticket.getFofoId()).getEmail();
1284
            String message = String.format(PARTNER_RESOLVED_TICKET_MAIL, ticketId, "REOPEN");
1285
            activity.setMessage(message);
35592 amit 1286
            activity.setCreatedBy(authUser.getId());
31762 tejbeer 1287
            activity.setTicketId(ticketId);
1288
            activity.setCreateTimestamp(LocalDateTime.now());
1289
            activity.setType(ActivityType.COMMUNICATION_OUT);
1290
            this.activityRelatedMail(to, null, subject, message);
1291
        } else {
1292
            if (ActivityType.RESOLVED_ACCEPTED == lastActivity) {
1293
                ticket.setLastActivity(lastActivity);
1294
                ticket.setCloseTimestamp(LocalDateTime.now());
1295
                activity.setMessage(ActivityType.RESOLVED_ACCEPTED.toString());
1296
                activity.setCreatedBy(0);
1297
                activity.setTicketId(ticketId);
1298
                activity.setType(ActivityType.COMMUNICATION_IN);
1299
                activity.setCreateTimestamp(LocalDateTime.now());
1300
            } else {
1301
                String message = String.format(INTERNAL_REOPEN_MAIL, ticketId, retailerService.getFofoRetailer(loginDetails.getFofoId()).getBusinessName());
1302
                String to = authRepository.selectById(ticket.getL1AuthUser()).getEmailId();
35395 amit 1303
                String[] ccTo = authRepository.selectByIds(Arrays.asList(ticket.getL2AuthUser(), ticket.getL3AuthUser(), ticket.getL4AuthUser(), ticket.getL5AuthUser())).stream().map(x -> x.getEmailId()).toArray(String[]::new);
31762 tejbeer 1304
                ticket.setLastActivity(lastActivity);
1305
                ticket.setUpdateTimestamp(LocalDateTime.now());
1306
                ticketAssignedRepository.deleteByTicketId(ticketId);
1307
                TicketAssigned ticketAssigned = new TicketAssigned();
1308
                ticketAssigned.setAssineeId(ticket.getL1AuthUser());
1309
                ticketAssigned.setTicketId(ticketId);
1310
                ticketAssignedRepository.persist(ticketAssigned);
1311
                activity.setMessage(INTERNAL_REOPEN_ACTIVITY_MESSAGE);
1312
                activity.setCreatedBy(0);
1313
                activity.setTicketId(ticketId);
1314
                activity.setType(ActivityType.COMMUNICATION_IN);
1315
                activity.setCreateTimestamp(LocalDateTime.now());
1316
                this.activityRelatedMail(to, ccTo, subject, message);
1317
                this.activityRelatedMail(retailerService.getFofoRetailer(loginDetails.getFofoId()).getEmail(), null, subject, String.format(PARTNER_REOPEN, ticketId));
1318
            }
1319
 
1320
        }
1321
        activityRepository.persist(activity);
1322
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1323
        return "response";
1324
    }
1325
 
32812 shampa 1326
 
1327
 
1328
 
1329
 
1330
    @PostMapping(value = "/partner-position/update")
1331
    public String positionUpdated(Model model, @RequestBody List<PartnerPositonUpdateModel> partnerPositionUpdateModels)
1332
            throws Exception {
1333
 
32821 shampa 1334
        Map<Integer, List<String>> positionIdsToAddMap = partnerPositionUpdateModels.stream().filter(x->x.getPositionIdTo()!=0).collect(Collectors.groupingBy(x->x.getPositionIdTo(),
32812 shampa 1335
                Collectors.mapping(x->x.getStoreCode(), Collectors.toList())));
1336
 
32821 shampa 1337
        Map<Integer, List<String>> positionIdsToRemoveMap = partnerPositionUpdateModels.stream().filter(x->x.getPositionIdFrom()!=0).collect(Collectors.groupingBy(x->x.getPositionIdFrom(),
32812 shampa 1338
                Collectors.mapping(x->x.getStoreCode(), Collectors.toList())));
1339
 
1340
        List<Integer> positionIdsToUpdate = new ArrayList<>();
1341
        positionIdsToUpdate.addAll(positionIdsToAddMap.keySet());
1342
        positionIdsToUpdate.addAll(positionIdsToRemoveMap.keySet());
1343
 
35395 amit 1344
        Map<Integer, Position> positionsToUpdateMap =  positionRepository.selectByIds(positionIdsToUpdate).stream().collect(Collectors.toMap(x->x.getId(), x->x));
32812 shampa 1345
        List<Integer> invalidPositionIds = positionsToUpdateMap.values().stream().filter(x-> x.getCategoryId()!= ProfitMandiConstants.TICKET_CATEGORY_RBM
34908 ranu 1346
                && x.getCategoryId() != ProfitMandiConstants.TICKET_CATEGORY_SALES && x.getCategoryId() != ProfitMandiConstants.TICKET_CATEGORY_ABM).map(x -> x.getId()).collect(Collectors.toList());
32812 shampa 1347
        if(invalidPositionIds.size() > 0) {
34908 ranu 1348
            String message = "Non RBM/Sales/ABM are not allowed - " + invalidPositionIds;
32812 shampa 1349
            throw new ProfitMandiBusinessException(message, message, message);
1350
        }
1351
 
1352
        for (Map.Entry<Integer, List<String>> positionIdStoreMapEntry : positionIdsToAddMap.entrySet()) {
1353
            int positionId = positionIdStoreMapEntry.getKey();
1354
            Position position = positionsToUpdateMap.get(positionId);
32821 shampa 1355
            LOGGER.info("positionId - {}, Position - {}", positionId, position);
32812 shampa 1356
            List<String> storeCodesToAdd = positionIdStoreMapEntry.getValue();
1357
            List<Integer> retailerIdsToAdd = fofoStoreRepository.selectByStoreCodes(storeCodesToAdd).stream().map(x->x.getId()).collect(Collectors.toList());
1358
            Map<Integer, PartnerPosition> partnerPositionsMapByFofoId  = partnerPositionRepository
32821 shampa 1359
                    .selectByRegionIdAndPostionId(Arrays.asList(position.getRegionId())
1360
                            ,Arrays.asList(positionId)).stream().collect(Collectors.toMap(x->x.getFofoId(),x->x));
32812 shampa 1361
            for (Integer retailerIdToAdd : retailerIdsToAdd) {
1362
                if (!partnerPositionsMapByFofoId.containsKey(retailerIdToAdd)) {
1363
                    PartnerPosition partnerPositionNew = new PartnerPosition();
1364
                    partnerPositionNew.setPositionId(positionId);
1365
                    partnerPositionNew.setFofoId(retailerIdToAdd);
1366
                    partnerPositionNew.setRegionId(position.getRegionId());
32865 amit.gupta 1367
                    partnerPositionRepository.persist(partnerPositionNew);
32812 shampa 1368
                }
1369
            }
1370
        }
1371
 
1372
        for (Map.Entry<Integer, List<String>> positionIdStoreMapEntry : positionIdsToRemoveMap.entrySet()) {
1373
 
1374
            int positionId = positionIdStoreMapEntry.getKey();
1375
            Position position = positionsToUpdateMap.get(positionId);
1376
            List<String> storeCodesToRemove = positionIdStoreMapEntry.getValue();
1377
            List<Integer> retailerIdsToRemove = fofoStoreRepository.selectByStoreCodes(storeCodesToRemove).stream().map(x->x.getId()).collect(Collectors.toList());
1378
            Map<Integer, PartnerPosition> partnerPositionsMapByFofoId  = partnerPositionRepository
1379
                    .selectByRegionIdAndPostionId(Arrays.asList(position.getRegionId()),Arrays.asList(positionId)).stream().collect(Collectors.toMap(x->x.getFofoId(),x->x));
1380
            for (Integer retailerIdToRemove : retailerIdsToRemove) {
1381
                if (partnerPositionsMapByFofoId.containsKey(retailerIdToRemove)) {
1382
                   PartnerPosition partnerPositionToRemove =  partnerPositionsMapByFofoId.get(retailerIdToRemove);
1383
                   partnerPositionRepository.delete(partnerPositionToRemove);
1384
                }
1385
            }
1386
        }
1387
 
1388
 
1389
 
1390
        /*partnerPositionUpdateModels.str
1391
 
1392
        Map<Integer, Position> positionIdMap = positionsToUpdate.stream().collect(Collectors.toMap(x->x.getId(), x->x));
1393
        for (PartnerPositonUpdateModel partnerPositionUpdateModel : partnerPositionUpdateModels) {
1394
            FofoStore fofoStore = fofoStoreRepository.selectByStoreCode(partnerPositionUpdateModel.getStoreCode());
1395
            Position positionFrom = positionIdMap.get(partnerPositionUpdateModel.getPositionIdFrom());
1396
            Position positionTo = positionIdMap.get(partnerPositionUpdateModel.getPositionIdTo());
1397
            if(positionFrom != null) {
1398
                partnerPositionRepository.selectByRegionIdAndPostionId(Arrays.)
1399
              int regionId = positionFrom.getRegionId()
1400
            }
1401
            if(positionTo != null) {
1402
 
1403
            }
1404
        }*/
1405
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
1406
        return "response";
1407
 
1408
    }
1409
 
1410
 
24417 govind 1411
}