Subversion Repositories SmartDukaan

Rev

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