Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
27391 tejbeer 1
package com.spice.profitmandi.web.controller;
2
 
29943 amit.gupta 3
import com.jcraft.jsch.*;
29900 amit.gupta 4
import com.spice.profitmandi.common.enumuration.MessageType;
27391 tejbeer 5
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
6
import com.spice.profitmandi.common.model.CustomRetailer;
27876 amit.gupta 7
import com.spice.profitmandi.common.model.ProfitMandiConstants;
29900 amit.gupta 8
import com.spice.profitmandi.common.model.SendNotificationModel;
29904 amit.gupta 9
import com.spice.profitmandi.common.util.FormattingUtils;
27876 amit.gupta 10
import com.spice.profitmandi.common.web.util.ResponseSender;
35501 ranu 11
import com.spice.profitmandi.dao.entity.catalog.BrandCatalog;
27391 tejbeer 12
import com.spice.profitmandi.dao.entity.catalog.Offer;
13
import com.spice.profitmandi.dao.entity.fofo.PartnerType;
14
import com.spice.profitmandi.dao.enumuration.catalog.ItemCriteriaType;
30651 amit.gupta 15
import com.spice.profitmandi.dao.enumuration.catalog.OfferSchemeType;
27391 tejbeer 16
import com.spice.profitmandi.dao.model.CreateOfferRequest;
34176 tejus.loha 17
import com.spice.profitmandi.dao.model.ItemCriteriaPayout;
35501 ranu 18
import com.spice.profitmandi.dao.model.TodayOfferModel;
34552 amit.gupta 19
import com.spice.profitmandi.dao.repository.catalog.*;
27391 tejbeer 20
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
29926 amit.gupta 21
import com.spice.profitmandi.dao.repository.dtr.UserAccountRepository;
29900 amit.gupta 22
import com.spice.profitmandi.service.NotificationService;
29785 amit.gupta 23
import com.spice.profitmandi.service.authentication.RoleManager;
33043 amit.gupta 24
import com.spice.profitmandi.service.catalog.BrandsService;
34176 tejus.loha 25
import com.spice.profitmandi.service.offers.ItemCriteria;
27876 amit.gupta 26
import com.spice.profitmandi.service.offers.OfferService;
35501 ranu 27
import com.spice.profitmandi.service.offers.TodayOfferService;
27391 tejbeer 28
import com.spice.profitmandi.service.user.RetailerService;
29
import com.spice.profitmandi.web.model.LoginDetails;
30
import com.spice.profitmandi.web.util.CookiesProcessor;
31
import com.spice.profitmandi.web.util.MVCResponseSender;
29943 amit.gupta 32
import org.apache.commons.io.FileUtils;
33
import org.apache.commons.io.output.ByteArrayOutputStream;
34
import org.apache.logging.log4j.LogManager;
35
import org.apache.logging.log4j.Logger;
35892 amit 36
import com.google.gson.Gson;
37
import com.spice.profitmandi.service.offers.PartnerCriteria;
29943 amit.gupta 38
import org.springframework.beans.factory.annotation.Autowired;
35892 amit 39
import org.springframework.cache.interceptor.SimpleKey;
32868 amit.gupta 40
import org.springframework.beans.factory.annotation.Value;
29943 amit.gupta 41
import org.springframework.cache.CacheManager;
42
import org.springframework.core.io.InputStreamResource;
43
import org.springframework.http.HttpHeaders;
44
import org.springframework.http.HttpStatus;
45
import org.springframework.http.ResponseEntity;
32204 amit.gupta 46
import org.springframework.mock.web.MockHttpServletRequest;
47
import org.springframework.mock.web.MockHttpServletResponse;
29943 amit.gupta 48
import org.springframework.stereotype.Controller;
35501 ranu 49
import org.springframework.transaction.annotation.Transactional;
29943 amit.gupta 50
import org.springframework.ui.Model;
51
import org.springframework.web.bind.annotation.*;
52
import org.springframework.web.multipart.MultipartFile;
32204 amit.gupta 53
import org.springframework.web.servlet.View;
54
import org.springframework.web.servlet.ViewResolver;
29943 amit.gupta 55
import org.xhtmlrenderer.swing.Java2DRenderer;
27391 tejbeer 56
 
29943 amit.gupta 57
import javax.imageio.ImageIO;
58
import javax.servlet.http.HttpServletRequest;
59
import java.awt.*;
60
import java.awt.image.BufferedImage;
61
import java.io.ByteArrayInputStream;
62
import java.io.File;
63
import java.io.FileNotFoundException;
64
import java.io.InputStream;
33713 tejus.loha 65
import java.time.Instant;
66
import java.time.LocalDate;
67
import java.time.LocalDateTime;
68
import java.time.YearMonth;
35501 ranu 69
import java.util.List;
35205 amit 70
import java.util.*;
29943 amit.gupta 71
import java.util.stream.Collectors;
72
 
27391 tejbeer 73
@Controller
35458 amit 74
@Transactional(rollbackFor = Throwable.class)
27391 tejbeer 75
public class OfferController {
32505 amit.gupta 76
    private static final Logger LOGGER = LogManager.getLogger(OfferController.class);
77
    private static final String IMAGE_REMOTE_DIR = "/var/www/dtrdashboard/uploads/campaigns/";
78
    private static final String IMAGE_STATIC_SERVER_URL = "https://images.smartdukaan.com/uploads/campaigns";
79
    @Autowired
80
    UserAccountRepository userAccountRepository;
81
    @Autowired
82
    RoleManager roleManager;
83
    @Autowired
84
    private OfferRepository offerRepository;
85
    @Autowired
86
    private OfferMarginRepository offerMarginRepository;
87
    @Autowired
88
    private FofoStoreRepository fofoStoreRepository;
89
    @Autowired
90
    private ResponseSender responseSender;
91
    @Autowired
92
    private ViewResolver viewResolver;
93
    @Autowired
94
    private ItemRepository itemRepository;
95
    @Autowired
96
    private MVCResponseSender mvcResponseSender;
97
    @Autowired
98
    private RetailerService retailerService;
99
    @Autowired
100
    private NotificationService notificationService;
101
    @Autowired
102
    private CookiesProcessor cookiesProcessor;
103
    @Autowired
104
    private OfferService offerService;
105
    @Autowired
106
    private CacheManager oneDayCacheManager;
27391 tejbeer 107
 
33043 amit.gupta 108
    @Autowired
35857 amit 109
    private CacheManager redisCacheManager;
110
 
111
    @Autowired
112
    private CacheManager redisShortCacheManager;
113
 
114
    @Autowired
35892 amit 115
    private CacheManager thirtyMinsTimeOutCacheManager;
116
 
117
    @Autowired
35893 amit 118
    private Gson gson;
119
 
120
    @Autowired
33043 amit.gupta 121
    BrandsService brandsService;
34553 amit.gupta 122
 
34552 amit.gupta 123
    @Autowired
124
    private CatalogRepository catalogRepository;
33043 amit.gupta 125
 
35501 ranu 126
    @Autowired
127
    TodayOfferService todayOfferService;
128
 
32505 amit.gupta 129
    @RequestMapping(value = "/getCreateOffer", method = RequestMethod.GET)
130
    public String getCreateOffer(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
131
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
132
        List<Integer> fofoIds = fofoStoreRepository.selectActiveStores().stream().map(x -> x.getId())
133
                .collect(Collectors.toList());
27391 tejbeer 134
 
33713 tejus.loha 135
        Set<String> brands = brandsService.getBrandsToDisplay(3).stream().map(x -> x.getName()).collect(Collectors.toSet());
32505 amit.gupta 136
        brands.addAll(itemRepository.selectAllBrands(ProfitMandiConstants.LED_CATEGORY_ID));
33615 amit.gupta 137
        brands.addAll(itemRepository.selectAllBrands(ProfitMandiConstants.SMART_WATCH_CATEGORY_ID));
32505 amit.gupta 138
        //Lets allow demo
139
        brands.add("Live Demo");
27391 tejbeer 140
 
32505 amit.gupta 141
        Map<Integer, CustomRetailer> customRetailerMap = retailerService.getAllFofoRetailers();
27876 amit.gupta 142
 
32505 amit.gupta 143
        Map<Integer, CustomRetailer> customRetailersMap = fofoIds.stream().map(x -> customRetailerMap.get(x))
144
                .filter(x -> x != null).collect(Collectors.toList()).stream()
145
                .collect(Collectors.toMap(x -> x.getPartnerId(), x -> x));
32204 amit.gupta 146
 
32505 amit.gupta 147
        model.addAttribute("customRetailersMap", customRetailersMap);
148
        model.addAttribute("itemCriteriaType", ItemCriteriaType.values());
149
        model.addAttribute("brands", brands);
150
        model.addAttribute("partnerCategories", PartnerType.values());
151
        model.addAttribute("warehouseRegion", ProfitMandiConstants.WAREHOUSE_MAP);
152
        return "scheme_offer";
27391 tejbeer 153
 
32505 amit.gupta 154
    }
29926 amit.gupta 155
 
32505 amit.gupta 156
    @RequestMapping(value = "/createOffer", method = RequestMethod.POST)
157
    public String createOffer(HttpServletRequest request, @RequestBody CreateOfferRequest createOfferRequest,
158
                              Model model) throws Exception {
159
        LOGGER.info("createOfferRequest [{}]", createOfferRequest);
160
        offerService.addOfferService(createOfferRequest);
32868 amit.gupta 161
        oneDayCacheManager.getCache("allOffers").evict(YearMonth.from(createOfferRequest.getStartDate()));
32505 amit.gupta 162
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
163
        return "response";
27391 tejbeer 164
 
32505 amit.gupta 165
    }
27391 tejbeer 166
 
32505 amit.gupta 167
    @RequestMapping(value = "/offers/published", method = RequestMethod.GET)
168
    public String getPublishedOffers(HttpServletRequest request, @RequestParam int fofoId, Model model)
169
            throws Exception {
170
        LOGGER.info("Published");
171
        offerService.getPublishedOffers(fofoId, YearMonth.from(LocalDateTime.now()));
172
        return "scheme_offer/published";
27391 tejbeer 173
 
32505 amit.gupta 174
    }
27391 tejbeer 175
 
32868 amit.gupta 176
    @Value("${prod}")
177
    private boolean isProd;
178
 
32505 amit.gupta 179
    @RequestMapping(value = "/offer/active/{offerId}", method = RequestMethod.GET)
180
    public String activateOffer(HttpServletRequest request, @PathVariable(name = "offerId") String offerIdsString,
181
                                Model model, @RequestParam(defaultValue = "true") boolean active)
182
            throws ProfitMandiBusinessException, Exception {
183
        List<Integer> offerIds = Arrays.stream(offerIdsString.split(",")).map(x -> Integer.parseInt(x))
184
                .collect(Collectors.toList());
185
        List<Offer> offers = offerRepository.selectAllByIds(offerIds);
32868 amit.gupta 186
 
187
        //Consider only offers that have opposite status
188
        offers = offers.stream().filter(x -> x.isActive() != active).collect(Collectors.toList());
189
 
190
        Set<YearMonth> yearMonthsToEvict = new HashSet<>();
32505 amit.gupta 191
        for (Offer offer : offers) {
32868 amit.gupta 192
            offer.setActive(active);
193
            yearMonthsToEvict.add(YearMonth.from(offer.getStartDate()));
32505 amit.gupta 194
        }
32868 amit.gupta 195
        //Evict caches
196
        for (YearMonth ymToEvict : yearMonthsToEvict) {
35857 amit 197
            redisCacheManager.getCache("catalog.published_yearmonth").evict(ymToEvict);
32868 amit.gupta 198
            oneDayCacheManager.getCache("allOffers").evict(ymToEvict);
32505 amit.gupta 199
        }
35857 amit 200
        redisShortCacheManager.getCache("publishedOffersWithAchievement").clear();
35893 amit 201
        // Evict partnerOffers cache for involved partners + admin view
202
        for (Offer offer : offers) {
203
            PartnerCriteria partnerCriteria = gson.fromJson(offer.getPartnerCriteria(), PartnerCriteria.class);
204
            if (partnerCriteria != null && partnerCriteria.getFofoIds() != null) {
205
                for (Integer fofoId : partnerCriteria.getFofoIds()) {
206
                    thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(fofoId, offer.getId()));
207
                }
208
            }
209
            thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(0, offer.getId()));
210
        }
32868 amit.gupta 211
        if (active) {
212
            for (Offer offer : offers) {
32505 amit.gupta 213
                this.sendNotification(offer);
214
            }
215
        }
32868 amit.gupta 216
 
217
 
32505 amit.gupta 218
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
219
        return "response";
220
    }
27391 tejbeer 221
 
35857 amit 222
    @RequestMapping(value = "/offers/publishAll", method = RequestMethod.POST)
223
    public ResponseEntity<?> publishAllUnpublished(@RequestParam YearMonth yearMonth)
224
            throws ProfitMandiBusinessException, Exception {
225
        List<Offer> published = offerService.publishAllUnpublished(yearMonth);
226
        if (!published.isEmpty()) {
227
            redisCacheManager.getCache("catalog.published_yearmonth").evict(yearMonth);
228
            oneDayCacheManager.getCache("allOffers").evict(yearMonth);
229
            redisShortCacheManager.getCache("publishedOffersWithAchievement").clear();
35893 amit 230
            // Evict partnerOffers cache for involved partners + admin view
35857 amit 231
            for (Offer offer : published) {
35893 amit 232
                PartnerCriteria pc = gson.fromJson(offer.getPartnerCriteria(), PartnerCriteria.class);
233
                if (pc != null && pc.getFofoIds() != null) {
234
                    for (Integer fofoId : pc.getFofoIds()) {
235
                        thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(fofoId, offer.getId()));
236
                    }
237
                }
238
                thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(0, offer.getId()));
239
            }
240
            for (Offer offer : published) {
35857 amit 241
                this.sendNotification(offer);
242
            }
243
        }
244
        return responseSender.ok(published.size() + " offers published");
245
    }
246
 
247
    @RequestMapping(value = "/offer/delete/{offerId}", method = RequestMethod.DELETE)
248
    public ResponseEntity<?> deleteOffer(@PathVariable int offerId) throws ProfitMandiBusinessException {
249
        offerService.deleteOffer(offerId);
250
        return responseSender.ok(true);
251
    }
252
 
32505 amit.gupta 253
    @RequestMapping(value = "/offer/testimage/{offerId}", method = RequestMethod.GET)
254
    public String testOffer(HttpServletRequest request, @PathVariable int offerId, Model model,
255
                            @RequestParam(defaultValue = "true") boolean active) throws ProfitMandiBusinessException, Exception {
256
        Offer offer = offerRepository.selectById(offerId);
257
        // model.addAttribute("response1", mvcResponseSender.createResponseString(true));
258
        // return "response";
259
        CreateOfferRequest createOfferRequest = offerService.getCreateOfferRequest(offer);
260
        Map<String, Object> model1 = new HashMap<>();
261
        model1.put("offer", createOfferRequest);
262
        model1.put("lessThan", "<");
263
        String htmlContent = this.getContentFromTemplate("offer_margin_detail_notify", model1);
264
        model.addAttribute("response1", htmlContent);
265
        return "response";
266
    }
29900 amit.gupta 267
 
32505 amit.gupta 268
    private void sendNotification(Offer offer) throws Exception {
269
        if (!YearMonth.from(offer.getStartDate()).equals(YearMonth.now())) {
270
            return;
271
        }
272
        String fileName = "offer-" + offer.getId() + ".png";
32868 amit.gupta 273
        //String htmlFileName = fileName.replace("png", "html");
32505 amit.gupta 274
        CreateOfferRequest createOfferRequest = offerService.getCreateOfferRequest(offer);
34620 amit.gupta 275
        boolean isLiveDemo = createOfferRequest.getTargetSlabs().stream()
276
                .map(x -> x.getItemCriteriaPayouts())
277
                .flatMap(List::stream)
278
                .map(ItemCriteriaPayout::getItemCriteria)
279
                .map(ItemCriteria::getCatalogIds)
280
                .flatMap(List::stream)
281
                .anyMatch(catalogId -> catalogRepository.selectCatalogById(catalogId).getBrand().equals("Live Demo"));
282
        if (!isLiveDemo) {
283
            SendNotificationModel sendNotificationModel = new SendNotificationModel();
284
            sendNotificationModel.setCampaignName("SchemeOffer");
285
            sendNotificationModel.setTitle(offer.getName());
286
            sendNotificationModel.setMessage(createOfferRequest.getSchemeType().name() + " of select models, "
287
                    + FormattingUtils.formatDateMonth(offer.getStartDate()) + " to "
288
                    + FormattingUtils.formatDateMonth(offer.getEndDate()));
289
            sendNotificationModel.setType("url");
290
            String imageUrl = IMAGE_STATIC_SERVER_URL + "/" + "image" + LocalDate.now() + "/" + fileName;
291
            sendNotificationModel.setImageUrl(imageUrl);
292
            sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/notifications");
293
            sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(1));
294
            sendNotificationModel.setMessageType(MessageType.scheme);
295
            //Map<Integer, List<Offer>> offersMap = offerRepository.selectAllPublishedMapByPartner(YearMonth.now());
29900 amit.gupta 296
 
34620 amit.gupta 297
            Map<String, InputStream> fileStreamsMap = new HashMap<>();
298
            Map<String, Object> model = new HashMap<>();
299
            model.put("offer", createOfferRequest);
300
            String htmlContent = this.getContentFromTemplate("offer_margin_detail_notify", model);
301
            LOGGER.info("this.getContentFromTemplate {}", htmlContent);
302
            fileStreamsMap.put(fileName, this.getImageBuffer(htmlContent));
303
            // fileStreamsMap.put(htmlFileName, new
304
            // ByteArrayInputStream(htmlContent.getBytes()));
305
            List<Integer> fofoIds = null;
306
            if (isProd) {
307
                this.uploadFile(fileStreamsMap);
308
            }
309
 
310
            List<Integer> fofoIdSet = new ArrayList<>(offerRepository.getEligibleFofoIds(offer));
311
            //LOGGER.info(fofoIdSet);
312
            List<Integer> userIds = userAccountRepository.selectUserIdsByRetailerIds(new ArrayList<>(fofoIdSet));
313
            sendNotificationModel.setUserIds(userIds);
314
            notificationService.sendNotification(sendNotificationModel);
315
            sendWhatsapp(offer, fofoIds, imageUrl);
32868 amit.gupta 316
        }
32505 amit.gupta 317
    }
27876 amit.gupta 318
 
32505 amit.gupta 319
    private void sendWhatsapp(Offer offer, List<Integer> fofoIds, String imageUrl) throws Exception {
35205 amit 320
        offerService.sendWhatsapp(offer, fofoIds, imageUrl);
32505 amit.gupta 321
    }
27391 tejbeer 322
 
32505 amit.gupta 323
    private InputStream asInputStream(BufferedImage bi) throws Exception {
324
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
325
        ImageIO.write(bi, "png", baos);
326
        return new ByteArrayInputStream(baos.toByteArray());
27391 tejbeer 327
 
32505 amit.gupta 328
    }
27391 tejbeer 329
 
32505 amit.gupta 330
    private ChannelSftp setupJsch() throws JSchException {
331
        JSch jsch = new JSch();
33471 amit.gupta 332
        Session jschSession = jsch.getSession("root", "172.105.58.16");
32505 amit.gupta 333
        // Session jschSession = jsch.getSession("root", "173.255.254.24");
334
        LOGGER.info("getClass().getResource(\"id_rsa\") {}",
335
                getClass().getClassLoader().getResource("id_rsa").getPath());
336
        jsch.addIdentity(getClass().getClassLoader().getResource("id_rsa").getPath());
337
        // jschSession.setPassword("spic@2015static0");
338
        jschSession.setConfig("StrictHostKeyChecking", "no");
339
        jschSession.connect();
340
        return (ChannelSftp) jschSession.openChannel("sftp");
341
    }
30426 tejbeer 342
 
32505 amit.gupta 343
    private void fileUpload(ChannelSftp channelSftp, Map<String, InputStream> streamsFileMap, String destinationPath)
344
            throws SftpException, FileNotFoundException {
27391 tejbeer 345
 
32505 amit.gupta 346
        channelSftp.cd(destinationPath);
347
        String folderName = "image" + LocalDate.now();
27391 tejbeer 348
 
32505 amit.gupta 349
        channelSftp.cd(destinationPath);
350
        SftpATTRS attrs = null;
27391 tejbeer 351
 
32505 amit.gupta 352
        // check if the directory is already existing
353
        try {
354
            attrs = channelSftp.stat(folderName);
355
        } catch (Exception e) {
356
            System.out.println(destinationPath + "/" + folderName + " not found");
357
        }
27391 tejbeer 358
 
32505 amit.gupta 359
        // else create a directory
360
        if (attrs == null) {
361
            channelSftp.mkdir(folderName);
362
            channelSftp.chmod(0755, ".");
363
        }
364
        channelSftp.cd(folderName);
27391 tejbeer 365
 
32505 amit.gupta 366
        for (Map.Entry<String, InputStream> streamsFileEntry : streamsFileMap.entrySet()) {
367
            channelSftp.put(streamsFileEntry.getValue(), streamsFileEntry.getKey(), ChannelSftp.OVERWRITE);
368
        }
27391 tejbeer 369
 
32505 amit.gupta 370
    }
29926 amit.gupta 371
 
32505 amit.gupta 372
    private void uploadFile(Map<String, InputStream> fileStreamsMap) throws Exception {
373
        ChannelSftp channelSftp = setupJsch();
374
        channelSftp.connect();
375
        this.fileUpload(channelSftp, fileStreamsMap, IMAGE_REMOTE_DIR + "");
376
        channelSftp.exit();
377
    }
27391 tejbeer 378
 
32505 amit.gupta 379
    private InputStream getImageBuffer(String html) throws Exception {
29900 amit.gupta 380
 
32505 amit.gupta 381
        String fileName = "/tmp/" + Instant.now().toEpochMilli();
382
        FileUtils.writeStringToFile(new File(fileName), html, "UTF-8");
383
        String address = "file:" + fileName;
384
        Java2DRenderer renderer = new Java2DRenderer(address, 400);
385
        RenderingHints hints = new RenderingHints(RenderingHints.KEY_COLOR_RENDERING,
386
                RenderingHints.VALUE_COLOR_RENDER_QUALITY);
387
        hints.add(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
388
        hints.add(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
389
        hints.add(new RenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC));
390
        renderer.setRenderingHints(hints);
391
        BufferedImage img = renderer.getImage();
392
        ByteArrayOutputStream os = new ByteArrayOutputStream();
393
        ImageIO.write(img, "png", os);
394
        return new ByteArrayInputStream(os.toByteArray());
395
    }
29926 amit.gupta 396
 
32505 amit.gupta 397
    private String getContentFromTemplate(String template, Map<String, Object> model) throws Exception {
398
        View resolvedView = viewResolver.resolveViewName(template, Locale.US);
399
        MockHttpServletResponse mockResp = new MockHttpServletResponse();
400
        MockHttpServletRequest req = new MockHttpServletRequest();
401
        LOGGER.info("Resolved view ->  {}, {}, {}, {}", resolvedView, model, req, mockResp);
402
        resolvedView.render(model, req, mockResp);
403
        return mockResp.getContentAsString();
404
    }
29926 amit.gupta 405
 
32505 amit.gupta 406
    @RequestMapping(value = "/offerHistory", method = RequestMethod.GET)
407
    public String getPaginatedOffers(HttpServletRequest request, @RequestParam YearMonth yearMonth, Model model)
408
            throws ProfitMandiBusinessException {
30017 amit.gupta 409
 
32505 amit.gupta 410
        List<CreateOfferRequest> publishedOffers = offerService.getAllOffers(yearMonth).values().stream()
411
                .sorted(Comparator.comparing(CreateOfferRequest::getId).reversed()).collect(Collectors.toList());
412
        model.addAttribute("offers", publishedOffers);
413
        model.addAttribute("yearMonth", yearMonth);
414
        model.addAttribute("currentMonth", yearMonth.equals(YearMonth.now()));
29926 amit.gupta 415
 
32505 amit.gupta 416
        return "offer_history";
417
    }
30723 amit.gupta 418
 
32505 amit.gupta 419
    @RequestMapping(value = "/offer-details", method = RequestMethod.GET)
420
    public String schemeDetails(HttpServletRequest request, @RequestParam int offerId, Model model)
421
            throws ProfitMandiBusinessException {
422
        CreateOfferRequest createOfferRequest = offerService.getOffer(0, offerId);
29900 amit.gupta 423
 
32505 amit.gupta 424
        model.addAttribute("offer", createOfferRequest);
425
        return "offer-details";
426
    }
29926 amit.gupta 427
 
32505 amit.gupta 428
    @RequestMapping(value = "/offer/process/{offerId}", method = RequestMethod.GET)
429
    public ResponseEntity<?> processOfferRequest(HttpServletRequest request, @PathVariable int offerId, Model model)
430
            throws Exception {
431
        CreateOfferRequest createOfferRequest = offerService.getOffer(0, offerId);
432
        if (!createOfferRequest.isActive()) {
433
            throw new ProfitMandiBusinessException("Offer not active", "Offer not active", "Offer not active");
434
        }
435
        if (createOfferRequest.getSchemeType().equals(OfferSchemeType.SELLIN)) {
436
            offerService.processSellin(createOfferRequest);
437
        } else if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
438
            offerService.processActivationtOffer(createOfferRequest);
439
        }
440
        return responseSender.ok(true);
441
    }
29926 amit.gupta 442
 
32505 amit.gupta 443
    @RequestMapping(value = "/offerDownload", method = RequestMethod.GET)
444
    public ResponseEntity<?> dowloadOfferSummary(HttpServletRequest request, @RequestParam int offerId, Model model)
445
            throws Exception {
446
        final HttpHeaders headers = new HttpHeaders();
447
        headers.set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
448
        headers.set("Content-disposition", "inline; filename=offer-" + offerId + ".csv");
449
        CreateOfferRequest createOfferRequest = offerService.getOffer(0, offerId);
33999 tejus.loha 450
        ByteArrayOutputStream baos = offerService.createCSVOfferReport(createOfferRequest);
32505 amit.gupta 451
        final InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
452
        final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
453
        return new ResponseEntity<>(inputStreamResource, headers, HttpStatus.OK);
454
    }
29900 amit.gupta 455
 
32505 amit.gupta 456
    @RequestMapping(value = "/offerById", method = RequestMethod.GET)
457
    public String offerById(HttpServletRequest request, int offerId, Model model) throws ProfitMandiBusinessException {
458
        Offer offer = offerRepository.selectById(offerId);
459
        model.addAttribute("offer", offer);
460
        return "offer-edit";
29900 amit.gupta 461
 
32505 amit.gupta 462
    }
29900 amit.gupta 463
 
34176 tejus.loha 464
    @RequestMapping(value = "/published-offers", method = RequestMethod.GET)
465
    public String publishedOffersOnMonthBefore(HttpServletRequest request, @RequestParam int yearMonth, @RequestParam(required = false, defaultValue = "") String brandFilter, Model model)
32505 amit.gupta 466
            throws ProfitMandiBusinessException {
34176 tejus.loha 467
        LOGGER.info("publishedOffersCalled");
32505 amit.gupta 468
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
469
        int fofoId = loginDetails.getFofoId();
470
        List<CreateOfferRequest> createOffers = offerService.getPublishedOffers(fofoId,
471
                YearMonth.from(LocalDate.now()).minusMonths(yearMonth));
29900 amit.gupta 472
 
34617 amit.gupta 473
        List<CreateOfferRequest> publishedOffers = null;
474
        if (!brandFilter.isEmpty()) {
475
            publishedOffers = createOffers.stream()
34176 tejus.loha 476
                    .filter(createOffer -> createOffer.getTargetSlabs().stream()
477
                            .map(x -> x.getItemCriteriaPayouts())
478
                            .flatMap(List::stream)
479
                            .map(ItemCriteriaPayout::getItemCriteria)
480
                            .map(ItemCriteria::getBrands)
481
                            .flatMap(List::stream)
482
                            .anyMatch(brand -> brand.equals(brandFilter)))
483
                    .collect(Collectors.toList());
34617 amit.gupta 484
        } else {
485
            publishedOffers = createOffers.stream().filter(createOffer -> createOffer.getTargetSlabs().stream()
34557 amit.gupta 486
                    .map(x -> x.getItemCriteriaPayouts())
487
                    .flatMap(List::stream)
488
                    .map(ItemCriteriaPayout::getItemCriteria)
34559 amit.gupta 489
                    .map(ItemCriteria::getCatalogIds)
34557 amit.gupta 490
                    .flatMap(List::stream)
34559 amit.gupta 491
                    .noneMatch(catalogId -> catalogRepository.selectCatalogById(catalogId).getBrand().equals("Live Demo"))).collect(Collectors.toList());
34176 tejus.loha 492
        }
29926 amit.gupta 493
 
34176 tejus.loha 494
        model.addAttribute("publishedOffers", publishedOffers);
495
 
32505 amit.gupta 496
        return "published-offers";
497
    }
29926 amit.gupta 498
 
32505 amit.gupta 499
    @PostMapping(value = "/offers/upload")
500
    public String uploadOffers(HttpServletRequest request, @RequestPart("file") MultipartFile targetFile, Model model)
501
            throws Exception {
502
        offerService.createOffers(targetFile.getInputStream());
503
        model.addAttribute("response1", true);
504
        return "response";
505
    }
29926 amit.gupta 506
 
32505 amit.gupta 507
    @RequestMapping(value = "/getOfferMargins", method = RequestMethod.GET)
508
    public String getOfferMargins(HttpServletRequest request,
509
                                  @RequestParam(name = "offerId", defaultValue = "0") int offerId, Model model) throws Exception {
510
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
511
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
512
        CreateOfferRequest createOfferRequest = offerService.getOffer(isAdmin ? 0 : loginDetails.getFofoId(), offerId);
29900 amit.gupta 513
 
32505 amit.gupta 514
        model.addAttribute("offer", createOfferRequest);
35415 amit 515
        model.addAttribute("isAdmin", isAdmin);
29900 amit.gupta 516
 
32505 amit.gupta 517
        return "offer_margin_detail_partner";
30470 amit.gupta 518
 
32505 amit.gupta 519
    }
29900 amit.gupta 520
 
35501 ranu 521
    @RequestMapping(value = "/todayOffer")
522
    public String todayOffer(HttpServletRequest request, Model model, @RequestParam(name = "fofoId", defaultValue = "0") int fofoId) throws ProfitMandiBusinessException {
523
 
524
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
525
        if (fofoId == 0) {
526
            fofoId = loginDetails.getFofoId();
527
        }
528
        List<BrandCatalog> allBrands = brandsService.getBrandsToDisplay(3);
529
 
530
        // 1. IDs to exclude entirely
531
        List<Integer> excludedIds = Arrays.asList(132, 133, 28, 17, 125);
532
 
533
        // 2. Brands that must come first (in this specific order)
534
        List<String> priorityOrder = Arrays.asList("Samsung", "Oppo", "Vivo", "Xiaomi", "Realme");
535
 
536
        List<BrandCatalog> sortedBrands = allBrands.stream()
537
                .filter(brand -> !excludedIds.contains(brand.getId())) // Remove excluded
538
                .sorted((b1, b2) -> {
539
                    // Get the index of the brand name in our priority list
540
                    int index1 = priorityOrder.indexOf(b1.getName());
541
                    int index2 = priorityOrder.indexOf(b2.getName());
542
 
543
                    // If brand is NOT in priority list, give it a high index (move to bottom)
544
                    int p1 = (index1 != -1) ? index1 : Integer.MAX_VALUE;
545
                    int p2 = (index2 != -1) ? index2 : Integer.MAX_VALUE;
546
 
547
                    if (p1 != p2) {
548
                        return Integer.compare(p1, p2); // Sort by priority first
549
                    }
550
 
551
                    // If both are "Others", sort them alphabetically
552
                    return b1.getName().compareToIgnoreCase(b2.getName());
553
                })
554
                .collect(Collectors.toList());
555
 
556
        model.addAttribute("brands", sortedBrands);
557
        model.addAttribute("fofoId", fofoId);
558
        model.addAttribute("date", FormattingUtils.format(LocalDateTime.now()));
559
 
560
        return "today-offer";
561
    }
562
 
563
    @RequestMapping(value = "/todayOfferList")
564
    public String todayOfferList(HttpServletRequest request, Model model, @RequestParam String brand, @RequestParam(defaultValue = "0", required = false) int fofoId) throws ProfitMandiBusinessException {
565
 
566
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
567
        if (fofoId == 0) {
568
            fofoId = loginDetails.getFofoId();
569
        }
570
 
571
        List<String> brands = brandsService.getBrandsToDisplay(3).stream().map(x -> x.getName()).collect(Collectors.toList());
572
 
573
        List<TodayOfferModel> todayOfferModels = todayOfferService.findAllTodayOffer(brand, fofoId);
574
 
575
        List<TodayOfferModel> groupedOffers = todayOfferService.groupSameOffers(todayOfferModels);
576
        model.addAttribute("brands", brands);
35505 ranu 577
        model.addAttribute("fofoId", fofoId);
35501 ranu 578
        model.addAttribute("todayOfferModels", todayOfferModels);
579
        model.addAttribute("groupedOffers", groupedOffers);
580
 
581
 
582
        return "today-offer-list";
583
    }
584
 
585
    @RequestMapping(value = "/todayFofoOffer")
586
    public String todayFofoOffer(HttpServletRequest request, Model model, @RequestParam(name = "fofoId", defaultValue = "0") int fofoId) throws ProfitMandiBusinessException {
587
 
588
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
589
        if (fofoId == 0) {
590
            fofoId = loginDetails.getFofoId();
591
        }
592
        List<BrandCatalog> allBrands = brandsService.getBrandsToDisplay(3);
593
 
594
        // 1. IDs to exclude entirely
595
        List<Integer> excludedIds = Arrays.asList(132, 133, 28, 17, 125);
596
 
597
        // 2. Brands that must come first (in this specific order)
598
        List<String> priorityOrder = Arrays.asList("Samsung", "Oppo", "Vivo", "Xiaomi", "Realme");
599
 
600
        List<BrandCatalog> sortedBrands = allBrands.stream()
601
                .filter(brand -> !excludedIds.contains(brand.getId())) // Remove excluded
602
                .sorted((b1, b2) -> {
603
                    // Get the index of the brand name in our priority list
604
                    int index1 = priorityOrder.indexOf(b1.getName());
605
                    int index2 = priorityOrder.indexOf(b2.getName());
606
 
607
                    // If brand is NOT in priority list, give it a high index (move to bottom)
608
                    int p1 = (index1 != -1) ? index1 : Integer.MAX_VALUE;
609
                    int p2 = (index2 != -1) ? index2 : Integer.MAX_VALUE;
610
 
611
                    if (p1 != p2) {
612
                        return Integer.compare(p1, p2); // Sort by priority first
613
                    }
614
 
615
                    // If both are "Others", sort them alphabetically
616
                    return b1.getName().compareToIgnoreCase(b2.getName());
617
                })
618
                .collect(Collectors.toList());
619
 
620
        model.addAttribute("brands", sortedBrands);
621
        model.addAttribute("fofoId", fofoId);
622
        model.addAttribute("date", FormattingUtils.format(LocalDateTime.now()));
623
 
624
        return "today-fofo-offer";
625
    }
626
 
35886 amit 627
    // ===== Offer Partner & Target Management (Admin Only) =====
628
 
629
    @RequestMapping(value = "/offer/partners", method = RequestMethod.GET)
630
    public String getOfferPartners(HttpServletRequest request, @RequestParam int offerId, Model model) throws Exception {
631
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
632
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
633
            throw new ProfitMandiBusinessException("Unauthorized", "Unauthorized", "");
634
        }
635
        CreateOfferRequest offer = offerService.getOffer(0, offerId);
636
        Map<Integer, CustomRetailer> customRetailerMap = retailerService.getAllFofoRetailers();
637
 
35888 amit 638
        // Partners are stored in partner_criteria JSON, not in offer_partners table
639
        List<Integer> partnerFofoIds = offer.getPartnerCriteria() != null
640
                ? offer.getPartnerCriteria().getFofoIds() : new ArrayList<>();
641
        if (partnerFofoIds == null) partnerFofoIds = new ArrayList<>();
642
 
35886 amit 643
        List<Integer> allFofoIds = fofoStoreRepository.selectActiveStores().stream()
644
                .map(x -> x.getId()).collect(Collectors.toList());
645
        Map<Integer, CustomRetailer> allRetailersMap = allFofoIds.stream()
646
                .map(id -> customRetailerMap.get(id))
647
                .filter(x -> x != null)
648
                .collect(Collectors.toMap(CustomRetailer::getPartnerId, x -> x));
649
 
650
        model.addAttribute("offer", offer);
651
        model.addAttribute("offerId", offerId);
35888 amit 652
        model.addAttribute("partnerFofoIds", partnerFofoIds);
35886 amit 653
        model.addAttribute("customRetailerMap", customRetailerMap);
654
        model.addAttribute("allRetailersMap", allRetailersMap);
655
        return "offer_partners";
656
    }
657
 
658
    @RequestMapping(value = "/offer/removePartners", method = RequestMethod.POST)
659
    public ResponseEntity<?> removePartnersFromOffer(HttpServletRequest request,
660
            @RequestParam int offerId, @RequestParam List<Integer> fofoIds,
661
            @RequestParam(required = false, defaultValue = "false") boolean createNewOffer,
662
            @RequestParam(required = false) List<Integer> targets) throws Exception {
663
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
664
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
665
            throw new ProfitMandiBusinessException("Unauthorized", "Unauthorized", "");
666
        }
667
        Offer offer = offerRepository.selectById(offerId);
668
        YearMonth ym = YearMonth.from(offer.getStartDate());
669
 
670
        offerService.removePartnersFromOffer(offerId, fofoIds);
671
 
672
        Integer newOfferId = null;
673
        String message;
674
        if (createNewOffer && targets != null && !targets.isEmpty()) {
675
            newOfferId = offerService.cloneOfferForPartners(offerId, fofoIds, targets);
676
            message = "Partner(s) removed from Offer #" + offerId + ". New Offer #" + newOfferId + " created (Unpublished).";
677
        } else {
678
            message = "Partner(s) removed from Offer #" + offerId + ".";
679
        }
680
 
35892 amit 681
        oneDayCacheManager.getCache("allOffers").evict(ym);
682
        redisCacheManager.getCache("catalog.published_yearmonth").evict(ym);
683
        redisShortCacheManager.getCache("publishedOffersWithAchievement").clear();
684
        // Evict partnerOffers cache for removed partners + admin view
685
        for (Integer fofoId : fofoIds) {
686
            thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(fofoId, offerId));
687
        }
688
        thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(0, offerId));
689
 
35886 amit 690
        Map<String, Object> response = new HashMap<>();
691
        response.put("message", message);
692
        response.put("newOfferId", newOfferId);
693
        response.put("yearMonth", ym.toString());
694
        return responseSender.ok(response);
695
    }
696
 
697
    @RequestMapping(value = "/offer/addPartners", method = RequestMethod.POST)
698
    public ResponseEntity<?> addPartnersToOffer(HttpServletRequest request,
699
            @RequestParam int offerId, @RequestParam List<Integer> fofoIds) throws Exception {
700
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
701
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
702
            throw new ProfitMandiBusinessException("Unauthorized", "Unauthorized", "");
703
        }
704
        offerService.addPartnersToOffer(offerId, fofoIds);
705
 
706
        Offer offer = offerRepository.selectById(offerId);
707
        YearMonth ym = YearMonth.from(offer.getStartDate());
35892 amit 708
        oneDayCacheManager.getCache("allOffers").evict(ym);
709
        redisCacheManager.getCache("catalog.published_yearmonth").evict(ym);
710
        redisShortCacheManager.getCache("publishedOffersWithAchievement").clear();
711
        // Evict partnerOffers cache for added partners + admin view
712
        for (Integer fofoId : fofoIds) {
713
            thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(fofoId, offerId));
714
        }
715
        thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(0, offerId));
35886 amit 716
 
717
        Map<String, Object> response = new HashMap<>();
718
        response.put("message", "Partner(s) added to Offer #" + offerId + ".");
719
        response.put("yearMonth", ym.toString());
720
        return responseSender.ok(response);
721
    }
722
 
723
    @RequestMapping(value = "/offer/updateTargets", method = RequestMethod.POST)
724
    public ResponseEntity<?> updateOfferTargets(HttpServletRequest request,
725
            @RequestParam int offerId, @RequestParam List<Integer> targets) throws Exception {
726
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
727
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
728
            throw new ProfitMandiBusinessException("Unauthorized", "Unauthorized", "");
729
        }
730
        offerService.updateOfferTargets(offerId, targets);
731
 
732
        Offer offer = offerRepository.selectById(offerId);
733
        YearMonth ym = YearMonth.from(offer.getStartDate());
734
        oneDayCacheManager.getCache("allOffers").evict(ym);
735
        redisCacheManager.getCache("catalog.published_yearmonth").evict(ym);
736
        redisShortCacheManager.getCache("publishedOffersWithAchievement").clear();
35892 amit 737
        // Evict partnerOffers cache for all partners of this offer + admin view
35893 amit 738
        PartnerCriteria partnerCriteria = gson.fromJson(offer.getPartnerCriteria(), PartnerCriteria.class);
35892 amit 739
        if (partnerCriteria != null && partnerCriteria.getFofoIds() != null) {
740
            for (Integer fofoId : partnerCriteria.getFofoIds()) {
741
                thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(fofoId, offerId));
742
            }
743
        }
744
        thirtyMinsTimeOutCacheManager.getCache("partnerOffers").evict(new SimpleKey(0, offerId));
35886 amit 745
 
746
        return responseSender.ok("Targets updated for Offer #" + offerId);
747
    }
748
 
27895 amit.gupta 749
}