Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
27877 amit.gupta 1
package com.spice.profitmandi.service.offers;
2
 
29783 amit.gupta 3
import com.google.common.collect.Lists;
27877 amit.gupta 4
import com.google.gson.Gson;
5
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
33030 amit.gupta 6
import com.spice.profitmandi.common.model.CustomRetailer;
29683 amit.gupta 7
import com.spice.profitmandi.common.model.PartnerTargetModel;
8
import com.spice.profitmandi.common.model.ProfitMandiConstants;
33999 tejus.loha 9
import com.spice.profitmandi.common.util.FileUtil;
35205 amit 10
import com.spice.profitmandi.common.util.FormattingUtils;
31920 amit.gupta 11
import com.spice.profitmandi.common.util.Utils;
27877 amit.gupta 12
import com.spice.profitmandi.dao.entity.catalog.ItemCriteria;
13
import com.spice.profitmandi.dao.entity.catalog.Offer;
35885 amit 14
import com.spice.profitmandi.dao.entity.catalog.OfferPartner;
29783 amit.gupta 15
import com.spice.profitmandi.dao.entity.catalog.TagListing;
31903 amit.gupta 16
import com.spice.profitmandi.dao.entity.catalog.TargetSlabEntity;
31920 amit.gupta 17
import com.spice.profitmandi.dao.entity.fofo.FofoLineItem;
18
import com.spice.profitmandi.dao.entity.fofo.FofoOrderItem;
31205 amit.gupta 19
import com.spice.profitmandi.dao.entity.fofo.InventoryItem;
20
import com.spice.profitmandi.dao.entity.fofo.OfferPayout;
31920 amit.gupta 21
import com.spice.profitmandi.dao.entity.transaction.LineItem;
22
import com.spice.profitmandi.dao.entity.transaction.Order;
31747 amit.gupta 23
import com.spice.profitmandi.dao.entity.transaction.UserWalletHistory;
31920 amit.gupta 24
import com.spice.profitmandi.dao.entity.warehouse.WarehouseInventoryItem;
25
import com.spice.profitmandi.dao.entity.warehouse.WarehouseScan;
26
import com.spice.profitmandi.dao.enumuration.catalog.AchievementType;
29783 amit.gupta 27
import com.spice.profitmandi.dao.enumuration.catalog.AmountType;
29499 amit.gupta 28
import com.spice.profitmandi.dao.enumuration.catalog.OfferSchemeType;
31205 amit.gupta 29
import com.spice.profitmandi.dao.enumuration.transaction.SchemePayoutStatus;
35394 amit 30
import com.spice.profitmandi.dao.model.*;
35856 amit 31
import com.spice.profitmandi.dao.repository.GenericRepository;
30066 amit.gupta 32
import com.spice.profitmandi.dao.repository.catalog.*;
35885 amit 33
import com.spice.profitmandi.dao.repository.catalog.OfferPartnerRepository;
35205 amit 34
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
31920 amit.gupta 35
import com.spice.profitmandi.dao.repository.fofo.ActivatedImeiRepository;
36
import com.spice.profitmandi.dao.repository.fofo.InventoryItemRepository;
31205 amit.gupta 37
import com.spice.profitmandi.dao.repository.fofo.OfferPayoutRepository;
31920 amit.gupta 38
import com.spice.profitmandi.dao.repository.transaction.LineItemImeisRepository;
33087 amit.gupta 39
import com.spice.profitmandi.dao.repository.warehouse.AgeingSummaryModel;
31920 amit.gupta 40
import com.spice.profitmandi.dao.repository.warehouse.WarehouseInventoryItemRepository;
41
import com.spice.profitmandi.dao.repository.warehouse.WarehouseScanRepository;
35205 amit 42
import com.spice.profitmandi.service.NotificationService;
31920 amit.gupta 43
import com.spice.profitmandi.service.pricecircular.PriceCircularService;
44
import com.spice.profitmandi.service.scheme.InventoryPayoutModel;
27877 amit.gupta 45
import com.spice.profitmandi.service.user.RetailerService;
31205 amit.gupta 46
import com.spice.profitmandi.service.wallet.WalletService;
35205 amit 47
import com.spice.profitmandi.service.whatsapp.WhatsappMessageType;
31205 amit.gupta 48
import in.shop2020.model.v1.order.WalletReferenceType;
33999 tejus.loha 49
import org.apache.commons.io.output.ByteArrayOutputStream;
30066 amit.gupta 50
import org.apache.logging.log4j.LogManager;
51
import org.apache.logging.log4j.Logger;
52
import org.apache.poi.ss.usermodel.Cell;
53
import org.apache.poi.ss.usermodel.CellType;
54
import org.apache.poi.ss.usermodel.Row;
55
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
56
import org.apache.poi.xssf.usermodel.XSSFRow;
57
import org.apache.poi.xssf.usermodel.XSSFSheet;
58
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
59
import org.springframework.beans.factory.annotation.Autowired;
60
import org.springframework.cache.CacheManager;
61
import org.springframework.cache.annotation.Cacheable;
62
import org.springframework.stereotype.Component;
27877 amit.gupta 63
 
30066 amit.gupta 64
import java.io.IOException;
65
import java.io.InputStream;
66
import java.time.LocalDate;
31205 amit.gupta 67
import java.time.LocalDateTime;
30066 amit.gupta 68
import java.time.YearMonth;
69
import java.util.*;
70
import java.util.stream.Collectors;
71
 
27877 amit.gupta 72
@Component
73
public class OfferServiceImpl implements OfferService {
74
 
35394 amit 75
    private static final Logger LOGGER = LogManager.getLogger(OfferServiceImpl.class);
29499 amit.gupta 76
 
35394 amit 77
    // Constants
78
    private static final List<String> TARGETS = Arrays.asList("Target 1", "Target 2", "Target 3", "Target 4", "Target 5");
79
    private static final int STOCK_AGEING_THRESHOLD_DAYS = 300;
80
 
81
    // Dependencies - Core
31747 amit.gupta 82
    @Autowired
83
    private Gson gson;
27877 amit.gupta 84
 
31747 amit.gupta 85
    @Autowired
35394 amit 86
    private CacheManager oneDayCacheManager;
35205 amit 87
 
35394 amit 88
    // Dependencies - Repositories
35205 amit 89
    @Autowired
35856 amit 90
    private GenericRepository genericRepository;
91
 
92
    @Autowired
31747 amit.gupta 93
    private OfferRepository offerRepository;
27877 amit.gupta 94
 
31747 amit.gupta 95
    @Autowired
35394 amit 96
    private OfferPayoutRepository offerPayoutRepository;
27877 amit.gupta 97
 
31747 amit.gupta 98
    @Autowired
35394 amit 99
    private OfferTargetSlabRepository offerTargetSlabRepository;
31205 amit.gupta 100
 
31747 amit.gupta 101
    @Autowired
35885 amit 102
    private OfferPartnerRepository offerPartnerRepository;
103
 
104
    @Autowired
31747 amit.gupta 105
    private ItemCriteriaRepository itemCriteriaRepository;
27877 amit.gupta 106
 
31747 amit.gupta 107
    @Autowired
108
    private ItemRepository itemRepository;
27877 amit.gupta 109
 
31747 amit.gupta 110
    @Autowired
111
    private TagListingRepository tagListingRepository;
29783 amit.gupta 112
 
31747 amit.gupta 113
    @Autowired
35205 amit 114
    private FofoStoreRepository fofoStoreRepository;
30684 amit.gupta 115
 
31747 amit.gupta 116
    @Autowired
35394 amit 117
    private ActivatedImeiRepository activatedImeiRepository;
27877 amit.gupta 118
 
31920 amit.gupta 119
    @Autowired
120
    private WarehouseScanRepository warehouseScanRepository;
121
 
122
    @Autowired
123
    private WarehouseInventoryItemRepository warehouseInventoryItemRepository;
124
 
125
    @Autowired
126
    private LineItemImeisRepository lineItemImeisRepository;
35394 amit 127
 
31920 amit.gupta 128
    @Autowired
129
    private InventoryItemRepository inventoryItemRepository;
130
 
35394 amit 131
    @Autowired
132
    private OfferEligibleImeiRepository offerEligibleImeiRepository;
133
 
134
    // Dependencies - Services
135
    @Autowired
136
    private NotificationService notificationService;
137
 
138
    @Autowired
139
    private RetailerService retailerService;
140
 
141
    @Autowired
142
    private PriceCircularService priceCircularService;
143
 
144
    @Autowired
145
    private WalletService walletService;
146
 
31747 amit.gupta 147
    @Override
148
    public void addOfferService(CreateOfferRequest createOfferRequest) throws ProfitMandiBusinessException {
149
        LOGGER.info("createOfferRequest  -- {}", createOfferRequest);
150
        this.createOffer(createOfferRequest);
151
        this.createTargetSlabs(createOfferRequest);
152
    }
27877 amit.gupta 153
 
31747 amit.gupta 154
    private void createOffer(CreateOfferRequest createOfferRequest) {
155
        Offer offer = new Offer();
156
        offer.setName(createOfferRequest.getName());
157
        offer.setTargetType(createOfferRequest.getTargetType());
158
        offer.setBooster(createOfferRequest.isBooster());
159
        offer.setPayoutType(createOfferRequest.getPayoutType());
160
        offer.setSchemeType(createOfferRequest.getSchemeType());
161
        offer.setBaseCriteia(createOfferRequest.isBaseCriteria());
162
        offer.setEndDate(createOfferRequest.getEndDate());
163
        offer.setStartDate(createOfferRequest.getStartDate());
164
        offer.setBrandSharePercentage(createOfferRequest.getBrandShareTerms());
165
        offer.setSellinPercentage(createOfferRequest.getSellinPercentage());
166
        offer.setOfferNotes(createOfferRequest.getOfferNotes());
167
        offer.setActivationBrands(createOfferRequest.getActivationBrands());
168
        offer.setTerms(createOfferRequest.getTerms());
169
        offer.setItemCriteria(gson.toJson(createOfferRequest.getItemCriteria()));
170
        offer.setPartnerCriteria(gson.toJson(createOfferRequest.getPartnerCriteria()));
32070 amit.gupta 171
        offer.setDiscount(createOfferRequest.isDiscount());
31747 amit.gupta 172
        offerRepository.persist(offer);
173
        createOfferRequest.setId(offer.getId());
174
    }
27877 amit.gupta 175
 
31747 amit.gupta 176
    @Override
35861 ranu 177
    @Cacheable(value = "publishedOffersWithAchievement", cacheManager = "oneDayCacheManager")
33247 ranu 178
    public List<CreateOfferRequest> getPublishedOffers(int fofoId, YearMonth yearMonth) throws ProfitMandiBusinessException {
35394 amit 179
        Map<Integer, List<Offer>> publishedMapByPartner = offerRepository.selectAllPublishedMapByPartner(yearMonth);
180
        List<Offer> publishedOffers = publishedMapByPartner != null ? publishedMapByPartner.get(fofoId) : null;
31747 amit.gupta 181
        List<CreateOfferRequest> createOfferRequests = new ArrayList<>();
182
        if (publishedOffers != null) {
183
            for (Offer offer : publishedOffers) {
184
                CreateOfferRequest createOfferRequest = this.getCreateOfferRequest(offer);
185
                createOfferRequests.add(createOfferRequest);
186
                setCriteriaPayoutAchieved(fofoId, createOfferRequest);
27877 amit.gupta 187
 
31747 amit.gupta 188
            }
189
        }
190
        return createOfferRequests;
191
    }
27877 amit.gupta 192
 
31747 amit.gupta 193
    private void setCriteriaPayoutAchieved(int fofoId, CreateOfferRequest createOfferRequest) {
194
        Map<Integer, Long> criteriaTransactionMap = null;
195
        if (createOfferRequest.getSchemeType().equals(OfferSchemeType.SELLIN)) {
35394 amit 196
            Map<Integer, Map<Integer, Long>> partnerWiseMap = offerRepository.getPartnerWisePurchaseSum(createOfferRequest);
197
            criteriaTransactionMap = partnerWiseMap != null ? partnerWiseMap.get(fofoId) : null;
31747 amit.gupta 198
        } else {
35394 amit 199
            Map<Integer, Map<Integer, Long>> partnerWiseMap = offerRepository.getPartnerWiseSalesSum(createOfferRequest);
200
            criteriaTransactionMap = partnerWiseMap != null ? partnerWiseMap.get(fofoId) : null;
31747 amit.gupta 201
        }
202
        LOGGER.info("I am here ------- {}", createOfferRequest.getId());
203
        List<com.spice.profitmandi.dao.model.ItemCriteriaPayout> itemCriteriaPayouts = createOfferRequest
204
                .getTargetSlabs().get(0).getItemCriteriaPayouts();
27877 amit.gupta 205
 
31747 amit.gupta 206
        for (com.spice.profitmandi.dao.model.ItemCriteriaPayout itemCriteriaPayout : itemCriteriaPayouts) {
207
            itemCriteriaPayout.setNextSlab(null);
208
            LOGGER.info("I am here --- {}", itemCriteriaPayout.getPayoutSlabs());
209
            long saleAmount = 0;
210
            if (criteriaTransactionMap != null
211
                    && criteriaTransactionMap.containsKey(itemCriteriaPayout.getItemCriteria().getId())) {
31853 amit.gupta 212
                saleAmount = criteriaTransactionMap.containsKey(0) ? criteriaTransactionMap.get(0) : criteriaTransactionMap.get(itemCriteriaPayout.getItemCriteria().getId());
31747 amit.gupta 213
            }
214
            itemCriteriaPayout.setAchievedValue(saleAmount);
215
            List<com.spice.profitmandi.service.offers.PayoutSlab> payoutSlabs = itemCriteriaPayout.getPayoutSlabs();
216
            for (int i = 0; i < payoutSlabs.size(); i++) {
217
                com.spice.profitmandi.service.offers.PayoutSlab beginSlab = payoutSlabs.get(i);
218
                com.spice.profitmandi.service.offers.PayoutSlab endSlab = null;
219
                if (payoutSlabs.size() - 1 > i) {
220
                    endSlab = payoutSlabs.get(i + 1);
221
                }
222
                if (beginSlab.getOnwardsAmount() > saleAmount) {
223
                    itemCriteriaPayout.setShortValue(beginSlab.getOnwardsAmount() - saleAmount);
224
                    itemCriteriaPayout.setNextSlab(beginSlab);
225
                    LOGGER.info("I am here");
226
                    break;
227
                }
228
                if (endSlab != null) {
229
                    if (beginSlab.getOnwardsAmount() <= saleAmount && endSlab.getOnwardsAmount() > saleAmount) {
230
                        itemCriteriaPayout.setCurrentSlab(beginSlab);
231
                        beginSlab.setSelected(true);
232
                        itemCriteriaPayout.setNextSlab(endSlab);
233
                        itemCriteriaPayout.setShortValue(endSlab.getOnwardsAmount() - saleAmount);
234
                        LOGGER.info("I am here");
235
                        break;
236
                    }
237
                    // Last loop
238
                } else {
239
                    beginSlab.setSelected(true);
240
                    itemCriteriaPayout.setCurrentSlab(beginSlab);
241
                    LOGGER.info("I am here");
242
                }
243
            }
244
            LOGGER.info("I am here --- {}", itemCriteriaPayout);
245
        }
29783 amit.gupta 246
 
31747 amit.gupta 247
    }
27877 amit.gupta 248
 
31747 amit.gupta 249
    @Override
32868 amit.gupta 250
    @Cacheable(value = "allOffers", cacheManager = "oneDayCacheManager")
33247 ranu 251
    public Map<Integer, CreateOfferRequest> getAllOffers(YearMonth yearMonth) throws ProfitMandiBusinessException {
31747 amit.gupta 252
        List<Offer> allOffers = offerRepository.selectAll(yearMonth, false);
253
        List<CreateOfferRequest> createOfferRequests = new ArrayList<>();
254
        for (Offer offer : allOffers) {
255
            CreateOfferRequest createOfferRequest = this.getCreateOfferRequest(offer);
256
            createOfferRequests.add(createOfferRequest);
257
        }
258
        return createOfferRequests.stream().collect(Collectors.toMap(CreateOfferRequest::getId, x -> x));
259
    }
27877 amit.gupta 260
 
31747 amit.gupta 261
    @Override
262
    @Cacheable(value = "partnerOffers", cacheManager = "thirtyMinsTimeOutCacheManager")
33247 ranu 263
    public CreateOfferRequest getOffer(int fofoId, int offerId) throws ProfitMandiBusinessException {
31747 amit.gupta 264
        Offer offer = offerRepository.selectById(offerId);
265
        CreateOfferRequest createOfferRequest = this.getCreateOfferRequest(offer);
266
        if (fofoId > 0) {
35394 amit 267
            createOfferRequest.setCriteriaQtyAmountModel(this.getCriteriaQtyAmounModelMap(createOfferRequest, fofoId));
31747 amit.gupta 268
        }
29783 amit.gupta 269
 
31747 amit.gupta 270
        return createOfferRequest;
271
    }
27877 amit.gupta 272
 
31747 amit.gupta 273
    @Override
33247 ranu 274
    public CreateOfferRequest getCreateOfferRequest(Offer fromOffer) throws ProfitMandiBusinessException {
31747 amit.gupta 275
        CreateOfferRequest createOfferRequest = new CreateOfferRequest();
276
        createOfferRequest.setName(fromOffer.getName());
32023 amit.gupta 277
        createOfferRequest.setDiscount(fromOffer.isDiscount());
31747 amit.gupta 278
        createOfferRequest.setTargetType(fromOffer.getTargetType());
279
        createOfferRequest.setPayoutType(fromOffer.getPayoutType());
280
        createOfferRequest.setSchemeType(fromOffer.getSchemeType());
281
        createOfferRequest.setActivationBrands(fromOffer.getActivationBrands());
282
        createOfferRequest.setEndDate(fromOffer.getEndDate());
283
        createOfferRequest.setProcessTimestamp(fromOffer.getProcessedTimestamp());
284
        createOfferRequest.setStartDate(fromOffer.getStartDate());
285
        createOfferRequest.setBooster(fromOffer.isBooster());
286
        createOfferRequest.setActive(fromOffer.isActive());
287
        createOfferRequest.setSellinPercentage(fromOffer.getSellinPercentage());
288
        createOfferRequest.setBrandShareTerms(fromOffer.getBrandSharePercentage());
289
        createOfferRequest.setOfferNotes(fromOffer.getOfferNotes());
290
        createOfferRequest.setTerms(fromOffer.getTerms());
291
        createOfferRequest.setBaseCriteria(fromOffer.isBaseCriteia());
292
        createOfferRequest.setItemCriteria(
293
                gson.fromJson(fromOffer.getItemCriteria(), com.spice.profitmandi.service.offers.ItemCriteria.class));
294
        createOfferRequest.setPartnerCriteria(gson.fromJson(fromOffer.getPartnerCriteria(), PartnerCriteria.class));
295
        createOfferRequest.setId(fromOffer.getId());
296
        createOfferRequest.setCreatedOn(fromOffer.getCreatedTimestamp());
297
        createOfferRequest.setItemCriteriaString(
298
                itemCriteriaRepository.getItemCriteriaDescription(createOfferRequest.getItemCriteria()));
299
        List<com.spice.profitmandi.dao.model.TargetSlab> targetSlabs = offerTargetSlabRepository
300
                .getByOfferId(fromOffer.getId());
301
        createOfferRequest.setPartnerCriteriaString(
33030 amit.gupta 302
                this.getPartnerCriteriaString(createOfferRequest.getPartnerCriteria()));
31747 amit.gupta 303
        createOfferRequest.setTargetSlabs(targetSlabs);
35885 amit 304
        if (!targetSlabs.isEmpty() && !targetSlabs.get(0).getItemCriteriaPayouts().isEmpty()) {
305
            for (com.spice.profitmandi.dao.model.ItemCriteriaPayout itemCriteriaPayout : targetSlabs.get(0).getItemCriteriaPayouts()) {
306
                if (!itemCriteriaPayout.getPayoutSlabs().isEmpty()) {
307
                    itemCriteriaPayout.setNextSlab(itemCriteriaPayout.getPayoutSlabs().get(0));
308
                }
309
            }
31747 amit.gupta 310
        }
311
        return createOfferRequest;
312
    }
27877 amit.gupta 313
 
31747 amit.gupta 314
    @Override
33613 amit.gupta 315
    public void reverseAdditionalSelloutSchemes(List<InventoryItem> inventoryItems, String reversalReason) throws ProfitMandiBusinessException {
316
        Map<Integer, List<InventoryItem>> fofoInventoryItemsMap = inventoryItems.stream().collect(Collectors.groupingBy(x -> x.getFofoId()));
317
        for (Map.Entry<Integer, List<InventoryItem>> fofoInventoryItemsEntry : fofoInventoryItemsMap.entrySet()) {
318
            int fofoId = fofoInventoryItemsEntry.getKey();
319
            List<InventoryItem> partnerInventoryItems = fofoInventoryItemsEntry.getValue();
320
            List<OfferPayout> offerPayouts = new ArrayList<>();
321
            LOGGER.info("Reversing schemes for fofoId {}, InventoryItems {}", fofoId, inventoryItems);
322
            //As of now we are not handling non-serialised items
35394 amit 323
            List<InventoryItem> serializedItems = partnerInventoryItems.stream().filter(x -> x.getSerialNumber() != null).collect(Collectors.toList());
324
            if (serializedItems.size() > 0) {
325
                // Batch fetch: collect all serial numbers and fetch in one call per fofoId
326
                Set<String> serialNumbers = serializedItems.stream().map(InventoryItem::getSerialNumber).collect(Collectors.toSet());
327
                offerPayouts = offerPayoutRepository.selectAllBySerialNumbers(fofoId, serialNumbers)
328
                        .stream()
329
                        .filter(x -> x.getRejectTimestamp() == null)
330
                        .collect(Collectors.toList());
33613 amit.gupta 331
                for (OfferPayout offerPayout : offerPayouts) {
332
                    offerPayout.setStatus(SchemePayoutStatus.REJECTED);
333
                    offerPayout.setRejectTimestamp(LocalDateTime.now());
334
                }
335
                Map<Long, Double> offerPayoutAmountMap = offerPayouts.stream().collect(Collectors.groupingBy(x -> x.getOfferId(), Collectors.summingDouble(x -> x.getAmount())));
336
                for (Map.Entry<Long, Double> offerPayoutEntry : offerPayoutAmountMap.entrySet()) {
337
                    List<UserWalletHistory> histories = walletService.getAllByReference(fofoId, offerPayoutEntry.getKey().intValue(), WalletReferenceType.ADDITIONAL_SCHEME);
338
                    if (histories.size() > 0) {
31750 amit.gupta 339
 
33613 amit.gupta 340
                        walletService.rollbackAmountFromWallet(fofoId, offerPayoutEntry.getValue().floatValue(), offerPayoutEntry.getKey().intValue(),
341
                                WalletReferenceType.ADDITIONAL_SCHEME, reversalReason, LocalDateTime.now());
342
                    }
31750 amit.gupta 343
                }
344
            }
31747 amit.gupta 345
        }
346
    }
30684 amit.gupta 347
 
31747 amit.gupta 348
    private void createTargetSlabs(CreateOfferRequest createOfferRequest) throws ProfitMandiBusinessException {
349
        List<com.spice.profitmandi.dao.model.TargetSlab> targetSlabs = createOfferRequest.getTargetSlabs().stream()
350
                .filter(x -> x.validate()).collect(Collectors.toList());
35394 amit 351
        if (!targetSlabs.isEmpty()) {
31747 amit.gupta 352
            Collections.sort(targetSlabs);
353
            for (com.spice.profitmandi.dao.model.TargetSlab targetSlab : targetSlabs) {
354
                if (targetSlab.validate()) {
355
                    List<ItemCriteriaPayout> itemCriteriaPayouts = targetSlab.getItemCriteriaPayouts();
356
                    for (ItemCriteriaPayout itemCriteriaPayout : itemCriteriaPayouts) {
357
                        ItemCriteria itemCriteria = itemCriteriaRepository.selectById(itemCriteriaPayout.getItemCriteria().getId());
358
                        if (itemCriteriaPayout.getItemCriteria().getId() > 0) {
359
                            itemCriteriaPayout.getItemCriteria().setId(0);
360
                        } else {
361
                            String itemCriteriaJson = gson.toJson(itemCriteriaPayout.getItemCriteria());
362
                            itemCriteria = itemCriteriaRepository.selectByCriteria(itemCriteriaJson);
363
                            // ItemCriteria Only once
364
                            if (itemCriteria == null) {
365
                                itemCriteria = new ItemCriteria();
366
                                itemCriteria.setCriteria(gson.toJson(itemCriteriaPayout.getItemCriteria()));
367
                                itemCriteriaRepository.persist(itemCriteria);
368
                            }
369
                        }
370
                        for (PayoutSlab payoutSlab : itemCriteriaPayout.getPayoutSlabs()) {
31903 amit.gupta 371
                            TargetSlabEntity targetSlabEntity = new TargetSlabEntity();
372
                            targetSlabEntity.setOfferId(createOfferRequest.getId());
373
                            targetSlabEntity.setOnwardsTarget(targetSlab.getOnwardsAmount());
374
                            targetSlabEntity.setTargetDescription(targetSlab.getTargetDescription());
375
                            targetSlabEntity.setPayoutTarget(payoutSlab.getOnwardsAmount());
376
                            targetSlabEntity.setPayoutValue(payoutSlab.getPayoutAmount());
377
                            targetSlabEntity.setItemCriteriaId(itemCriteria.getId());
378
                            targetSlabEntity.setAmountType(itemCriteriaPayout.getAmountType());
32979 amit.gupta 379
                            targetSlabEntity.setStartDate(itemCriteriaPayout.getStartDate());
380
                            targetSlabEntity.setEndDate(itemCriteriaPayout.getEndDate());
31903 amit.gupta 381
                            offerTargetSlabRepository.persist(targetSlabEntity);
31747 amit.gupta 382
                        }
383
                    }
384
                }
385
            }
27877 amit.gupta 386
 
31747 amit.gupta 387
        } else {
388
            throw new ProfitMandiBusinessException("Invalid Target Slabs", "Invalid Target", "");
389
        }
27877 amit.gupta 390
 
31747 amit.gupta 391
    }
27877 amit.gupta 392
 
31747 amit.gupta 393
    @Override
33247 ranu 394
    public List<CreateOfferRequest> getPublishedOffers(LocalDate date, int fofoId, int catalogId) throws ProfitMandiBusinessException {
35394 amit 395
        Map<Integer, List<Offer>> publishedMapByPartner = offerRepository.selectAllPublishedMapByPartner(YearMonth.from(date));
396
        List<Offer> publishedOffers = publishedMapByPartner != null ? publishedMapByPartner.get(fofoId) : null;
31747 amit.gupta 397
        List<CreateOfferRequest> createOfferRequests = new ArrayList<>();
398
        if (publishedOffers != null) {
399
            for (Offer offer : publishedOffers) {
400
                boolean found = false;
401
                List<com.spice.profitmandi.dao.model.TargetSlab> targetSlabs = offerTargetSlabRepository
402
                        .getByOfferId(offer.getId());
403
                CreateOfferRequest createOfferRequest = this.getCreateOfferRequest(offer);
404
                createOfferRequest.setTargetSlabs(targetSlabs);
405
                this.setCriteriaPayoutAchieved(fofoId, createOfferRequest);
406
                Set<com.spice.profitmandi.service.offers.ItemCriteria> itemCriteriaSet = targetSlabs.stream()
407
                        .flatMap(x -> x.getItemCriteriaPayouts().stream()).map(x -> x.getItemCriteria()).distinct()
408
                        .filter(x -> itemRepository.containsModel(x, catalogId)).collect(Collectors.toSet());
29499 amit.gupta 409
 
31747 amit.gupta 410
                for (com.spice.profitmandi.dao.model.TargetSlab targetSlab : targetSlabs) {
411
                    targetSlab.setItemCriteriaPayouts(targetSlab.getItemCriteriaPayouts().stream()
412
                            .filter(x -> itemCriteriaSet.contains(x.getItemCriteria())).collect(Collectors.toList()));
413
                    if (targetSlab.getItemCriteriaPayouts().size() > 0) {
414
                        found = true;
415
                    }
416
                }
417
                if (found) {
418
                    createOfferRequests.add(createOfferRequest);
419
                }
420
            }
421
        }
29783 amit.gupta 422
 
31747 amit.gupta 423
        return createOfferRequests;
424
    }
29783 amit.gupta 425
 
31747 amit.gupta 426
    @Override
427
    public void createOffers(InputStream fileInputStream) throws Exception {
428
        Map<CreateOfferRequest, List<PartnerTargetModel>> offerPartnerTargetMap = this.parseFromExcel(fileInputStream);
32868 amit.gupta 429
        Set<YearMonth> ymListToEvict = new HashSet<>();
31747 amit.gupta 430
        for (Map.Entry<CreateOfferRequest, List<PartnerTargetModel>> partnerTargetEntry : offerPartnerTargetMap
431
                .entrySet()) {
432
            CreateOfferRequest createOfferRequest = partnerTargetEntry.getKey();
433
            Map<List<Integer>, List<Integer>> targetPartnerMap = partnerTargetEntry.getValue().stream()
434
                    .collect(Collectors.groupingBy(PartnerTargetModel::getTargets,
435
                            Collectors.mapping(PartnerTargetModel::getFofoId, Collectors.toList())));
436
            for (Map.Entry<List<Integer>, List<Integer>> targetPartnersEntry : targetPartnerMap.entrySet()) {
437
                List<Integer> fofoIds = createOfferRequest.getPartnerCriteria().getFofoIds();
438
                List<Integer> filterFofoIds = targetPartnersEntry.getValue().stream().filter(x -> !fofoIds.contains(x))
439
                        .collect(Collectors.toList());
440
                LOGGER.info("FofoIds {}", filterFofoIds);
441
                List<Integer> targets = targetPartnersEntry.getKey();
442
                LOGGER.info("Targets  {}", targets);
29806 amit.gupta 443
 
31747 amit.gupta 444
                createOfferRequest.getPartnerCriteria().setFofoIds(filterFofoIds);
445
                int counter = 0;
446
                List<ItemCriteriaPayout> itemCriteriaPayouts = createOfferRequest.getTargetSlabs().get(0)
447
                        .getItemCriteriaPayouts();
448
                List<PayoutSlab> payoutSlabs = itemCriteriaPayouts.stream().flatMap(x -> x.getPayoutSlabs().stream()).collect(Collectors.toList());
449
                for (PayoutSlab payoutSlab : payoutSlabs) {
450
                    payoutSlab.setOnwardsAmount(targets.get(counter));
451
                    counter++;
452
                }
453
                this.addOfferService(createOfferRequest);
454
            }
32868 amit.gupta 455
            ymListToEvict.add(YearMonth.from(createOfferRequest.getStartDate()));
31747 amit.gupta 456
        }
32868 amit.gupta 457
        for (YearMonth ymToEvict : ymListToEvict) {
458
            oneDayCacheManager.getCache("allOffers").evict(ymToEvict);
459
        }
31747 amit.gupta 460
    }
29783 amit.gupta 461
 
31747 amit.gupta 462
    private Map<CreateOfferRequest, List<PartnerTargetModel>> parseFromExcel(InputStream inputStream)
463
            throws ProfitMandiBusinessException {
29783 amit.gupta 464
 
31747 amit.gupta 465
        Map<CreateOfferRequest, List<PartnerTargetModel>> offerPartnerTargetMap = new HashMap<>();
466
        XSSFWorkbook myWorkBook = null;
467
        try {
468
            myWorkBook = new XSSFWorkbook(inputStream);
469
            myWorkBook.setMissingCellPolicy(MissingCellPolicy.RETURN_BLANK_AS_NULL);
470
            for (int i = 0; i < myWorkBook.getNumberOfSheets(); i++) {
29683 amit.gupta 471
 
31747 amit.gupta 472
                XSSFSheet mySheet = myWorkBook.getSheetAt(i);
473
                int offerId = Integer.parseInt(mySheet.getSheetName());
474
                CreateOfferRequest existingOffer = this.getOffer(0, offerId);
475
                List<PartnerTargetModel> partnerTargetModels = new ArrayList<>();
476
                offerPartnerTargetMap.put(existingOffer, partnerTargetModels);
477
                this.printIterator(mySheet);
478
                LOGGER.info("rowCellNum {}", mySheet.getLastRowNum());
479
                for (int rowNumber = 1; rowNumber <= mySheet.getLastRowNum(); rowNumber++) {
480
                    XSSFRow row = mySheet.getRow(rowNumber);
481
                    LOGGER.info("row {}", row);
482
                    PartnerTargetModel partnerTargetModel = new PartnerTargetModel();
29783 amit.gupta 483
 
31747 amit.gupta 484
                    if (row.getCell(0) != null && row.getCell(0).getCellTypeEnum() == CellType.NUMERIC) {
485
                        partnerTargetModel.setFofoId((int) row.getCell(0).getNumericCellValue());
486
                    } else {
487
                        ProfitMandiBusinessException profitMandiBusinessException = new ProfitMandiBusinessException(
488
                                "FOFO ID", row.getCell(0).toString(), "TGLSTNG_VE_1010");
489
                        LOGGER.error("Excel file parse error : ", profitMandiBusinessException);
490
                        throw profitMandiBusinessException;
491
                    }
492
                    List<Integer> targets = new ArrayList<>();
493
                    long targetsSize = existingOffer.getTargetSlabs().get(0).getItemCriteriaPayouts().stream().flatMap(x -> x.getPayoutSlabs().stream()).collect(Collectors.counting());
494
                    for (int cellNumber = 1; cellNumber <= targetsSize; cellNumber++) {
495
                        if (row.getCell(cellNumber) != null
496
                                && row.getCell(cellNumber).getCellTypeEnum() == CellType.NUMERIC) {
497
                            targets.add((int) row.getCell(cellNumber).getNumericCellValue());
498
                        } else {
499
                            ProfitMandiBusinessException profitMandiBusinessException = new ProfitMandiBusinessException(
500
                                    "Target Column issue at " + rowNumber + ", " + cellNumber, row.getCell(cellNumber),
501
                                    "Invalid target");
502
                            LOGGER.error("Excel file parse error : ", profitMandiBusinessException);
503
                            throw profitMandiBusinessException;
504
                        }
505
                    }
506
                    partnerTargetModel.setTargets(targets);
507
                    partnerTargetModels.add(partnerTargetModel);
508
                }
509
            }
510
            myWorkBook.close();
511
        } catch (ProfitMandiBusinessException pbse) {
512
            throw pbse;
513
        } catch (IOException ioException) {
514
            ioException.printStackTrace();
515
            throw new ProfitMandiBusinessException(ProfitMandiConstants.EXCEL_FILE, ioException.getMessage(),
516
                    "EXL_VE_1000");
517
        } finally {
518
            if (myWorkBook != null) {
519
                try {
520
                    myWorkBook.close();
521
                } catch (IOException e) {
522
                    // TODO Auto-generated catch block
523
                    e.printStackTrace();
524
                }
525
            }
526
        }
527
        LOGGER.info("offerPartnerTargetMap {}", offerPartnerTargetMap);
528
        return offerPartnerTargetMap;
529
    }
29783 amit.gupta 530
 
31747 amit.gupta 531
    private void printIterator(XSSFSheet sheet) {
532
        Iterator<Row> rowIterator = sheet.iterator();
533
        while (rowIterator.hasNext()) {
534
            Row row = rowIterator.next();
35394 amit 535
            StringBuilder rowContent = new StringBuilder();
31747 amit.gupta 536
            Iterator<Cell> cellIterator = row.cellIterator();
29683 amit.gupta 537
 
31747 amit.gupta 538
            while (cellIterator.hasNext()) {
539
                Cell cell = cellIterator.next();
540
                switch (cell.getCellType()) {
541
                    case Cell.CELL_TYPE_NUMERIC:
35394 amit 542
                        rowContent.append(cell.getNumericCellValue()).append("\t");
31747 amit.gupta 543
                        break;
544
                    case Cell.CELL_TYPE_STRING:
35394 amit 545
                        rowContent.append(cell.getStringCellValue()).append("\t");
31747 amit.gupta 546
                        break;
547
                }
548
            }
35394 amit 549
            LOGGER.debug("Row content: {}", rowContent);
31747 amit.gupta 550
        }
551
    }
29683 amit.gupta 552
 
31747 amit.gupta 553
    @Override
554
    public Map<Integer, CreateOfferRequest> getPublishedOffers(LocalDate date, int fofoId, String brand) {
555
        // TODO Auto-generated method stub
556
        return null;
557
    }
30684 amit.gupta 558
 
31747 amit.gupta 559
    @Override
32043 amit.gupta 560
    @Cacheable(value = "slabPayoutMap1", cacheManager = "oneDayCacheManager")
33247 ranu 561
    public Map<Integer, Map<Integer, Long>> getSlabPayoutMap(CreateOfferRequest createOfferRequest) throws ProfitMandiBusinessException {
31747 amit.gupta 562
        Map<Integer, Map<Integer, Long>> catalogSlabPayoutMap = new HashMap<>();
563
        com.spice.profitmandi.dao.model.TargetSlab targetSlab = createOfferRequest.getTargetSlabs().get(0);
564
        List<ItemCriteriaPayout> payouts = targetSlab.getItemCriteriaPayouts();
29783 amit.gupta 565
 
31747 amit.gupta 566
        for (ItemCriteriaPayout itemCriteriaPayout : payouts) {
567
            com.spice.profitmandi.service.offers.ItemCriteria itemCriteria = itemCriteriaPayout.getItemCriteria();
568
            List<Integer> catalogIds = itemRepository.getCatalogIds(itemCriteria);
569
            for (PayoutSlab payoutSlab : Lists.reverse(itemCriteriaPayout.getPayoutSlabs())) {
570
                if (itemCriteriaPayout.getAmountType().equals(AmountType.FIXED)) {
571
                    for (Integer catalogId : catalogIds) {
572
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
573
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
574
                        }
575
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
576
                                (long) payoutSlab.getPayoutAmount());
577
                    }
578
                } else if (itemCriteriaPayout.getAmountType().equals(AmountType.SLAB_FIXED)) {
579
                    for (Integer catalogId : catalogIds) {
580
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
581
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
582
                        }
583
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
584
                                (long) (payoutSlab.getPayoutAmount() / payoutSlab.getOnwardsAmount()));
585
                    }
586
                } else if (itemCriteriaPayout.getAmountType().equals(AmountType.PERCENTAGE)) {
587
                    Map<Integer, TagListing> tagListingsMap = tagListingRepository.selectAllByCatalogIds(catalogIds);
588
                    for (Map.Entry<Integer, TagListing> tagListingEntry : tagListingsMap.entrySet()) {
589
                        TagListing tagListing = tagListingEntry.getValue();
590
                        if (!catalogSlabPayoutMap.containsKey(tagListingEntry.getKey())) {
591
                            catalogSlabPayoutMap.put(tagListingEntry.getKey(), new LinkedHashMap<>());
592
                        }
593
                        catalogSlabPayoutMap.get(tagListingEntry.getKey()).put(payoutSlab.getOnwardsAmount(),
594
                                (long) (tagListing.getSellingPrice() * payoutSlab.getPayoutAmount() / 100));
595
                    }
596
                }
597
            }
598
        }
599
        return catalogSlabPayoutMap;
600
    }
601
 
31903 amit.gupta 602
    @Override
603
    @Cacheable(value = "slabPayoutMap", cacheManager = "oneDayCacheManager")
604
    public Map<Integer, Map<Integer, AmountModel>> getSlabPayoutMapNew(CreateOfferRequest createOfferRequest) {
605
        Map<Integer, Map<Integer, AmountModel>> catalogSlabPayoutMap = new HashMap<>();
606
        com.spice.profitmandi.dao.model.TargetSlab targetSlab = createOfferRequest.getTargetSlabs().get(0);
607
        List<ItemCriteriaPayout> payouts = targetSlab.getItemCriteriaPayouts();
608
 
609
        for (ItemCriteriaPayout itemCriteriaPayout : payouts) {
610
            com.spice.profitmandi.service.offers.ItemCriteria itemCriteria = itemCriteriaPayout.getItemCriteria();
611
            List<Integer> catalogIds = itemRepository.getCatalogIds(itemCriteria);
612
            for (PayoutSlab payoutSlab : Lists.reverse(itemCriteriaPayout.getPayoutSlabs())) {
613
                if (itemCriteriaPayout.getAmountType().equals(AmountType.FIXED)) {
614
                    for (Integer catalogId : catalogIds) {
615
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
616
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
617
                        }
618
                        AmountModel amountModel = new AmountModel();
619
                        amountModel.setAmountType(AmountType.FIXED);
620
                        amountModel.setAmount(payoutSlab.getPayoutAmount());
32021 amit.gupta 621
                        amountModel.setDiscount(createOfferRequest.isDiscount());
31903 amit.gupta 622
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
623
                                amountModel);
624
                    }
625
                } else if (itemCriteriaPayout.getAmountType().equals(AmountType.SLAB_FIXED)) {
626
                    for (Integer catalogId : catalogIds) {
627
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
628
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
629
                        }
630
 
631
                        AmountModel amountModel = new AmountModel();
632
                        amountModel.setAmountType(AmountType.FIXED);
32021 amit.gupta 633
                        amountModel.setDiscount(createOfferRequest.isDiscount());
31903 amit.gupta 634
                        amountModel.setAmount(payoutSlab.getPayoutAmount() / payoutSlab.getOnwardsAmount());
635
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
636
                                amountModel);
637
                    }
638
                } else if (itemCriteriaPayout.getAmountType().equals(AmountType.PERCENTAGE)) {
639
                    for (Integer catalogId : catalogIds) {
640
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
641
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
642
                        }
643
                        AmountModel amountModel = new AmountModel();
644
                        amountModel.setAmountType(AmountType.PERCENTAGE);
645
                        amountModel.setAmount(payoutSlab.getPayoutAmount());
32021 amit.gupta 646
                        amountModel.setDiscount(createOfferRequest.isDiscount());
31903 amit.gupta 647
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
648
                                amountModel);
649
                    }
650
                }
651
            }
652
        }
653
        return catalogSlabPayoutMap;
654
    }
655
 
31920 amit.gupta 656
 
657
    private double getAmount(InventoryPayoutModel inventoryPayoutModel, AmountModel amountModel) {
658
        double rollout = 0;
659
        if (amountModel.getAmountType().equals(AmountType.PERCENTAGE)) {
660
            double effectiveDp = inventoryPayoutModel.getDp() - inventoryPayoutModel.getFixedAmount();
661
            double totalPercentage = inventoryPayoutModel.getPercentageAmount() + amountModel.getAmount();
662
            rollout = effectiveDp * (totalPercentage / (100 + totalPercentage) - (inventoryPayoutModel.getPercentageAmount() / (100 + inventoryPayoutModel.getPercentageAmount())));
663
        } else {
664
            rollout = amountModel.getAmount() * (100 / (100 + inventoryPayoutModel.getPercentageAmount()));
665
        }
666
        return rollout;
667
    }
668
 
35394 amit 669
    @Override
670
    public Map<Integer, QtyAmountModel> getCriteriaQtyAmounModelMap(CreateOfferRequest createOfferRequest, int fofoId) throws ProfitMandiBusinessException {
671
        Map<Integer, QtyAmountModel> qtyAmountMap;
672
        if (createOfferRequest.getSchemeType().equals(OfferSchemeType.SELLIN)) {
673
            qtyAmountMap = getCriteriaQtyAmountModelMapForSellin(createOfferRequest, fofoId);
674
        } else {
675
            qtyAmountMap = getCriteriaQtyAmountModelMapForSelloutAndActivation(createOfferRequest, fofoId);
676
        }
677
        LOGGER.info("Qty Amount Map {}", qtyAmountMap);
678
        return qtyAmountMap;
679
    }
34217 amit.gupta 680
 
35667 amit 681
    private PayoutSlab findEligibleSlab(List<PayoutSlab> slabs, int achievedValue) {
682
        PayoutSlab eligibleSlab = null;
683
        for (PayoutSlab slab : slabs) {
684
            if (slab.getOnwardsAmount() <= achievedValue) {
685
                eligibleSlab = slab;
686
            } else {
687
                break;
688
            }
689
        }
690
        return eligibleSlab;
691
    }
692
 
35675 amit 693
    private void setSlabProgress(ItemCriteriaPayout itemCriteriaPayout, PayoutSlab eligibleSlab, int achievedValue) {
694
        List<PayoutSlab> slabs = itemCriteriaPayout.getPayoutSlabs();
695
        itemCriteriaPayout.setCurrentSlab(eligibleSlab);
696
        if (eligibleSlab == null) {
697
            if (!slabs.isEmpty()) {
698
                itemCriteriaPayout.setNextSlab(slabs.get(0));
699
                itemCriteriaPayout.setShortValue(slabs.get(0).getOnwardsAmount() - achievedValue);
700
            }
701
        } else {
702
            int idx = slabs.indexOf(eligibleSlab);
703
            if (idx < slabs.size() - 1) {
704
                PayoutSlab next = slabs.get(idx + 1);
705
                itemCriteriaPayout.setNextSlab(next);
706
                itemCriteriaPayout.setShortValue(next.getOnwardsAmount() - achievedValue);
707
            } else {
708
                itemCriteriaPayout.setNextSlab(null);
709
                itemCriteriaPayout.setShortValue(0);
710
            }
711
        }
712
    }
713
 
35667 amit 714
    private double calculateFinalPayout(PayoutSlab eligibleSlab, AmountType amountType,
715
                                        int valueForPercentage, int valueForFixed) {
716
        if (eligibleSlab == null) return 0;
717
        eligibleSlab.setSelected(true);
718
        float payoutRate = eligibleSlab.getPayoutAmount();
719
        if (AmountType.PERCENTAGE.equals(amountType)) {
720
            return (payoutRate * valueForPercentage) / 100;
721
        } else if (AmountType.FIXED.equals(amountType)) {
722
            return payoutRate * valueForFixed;
723
        } else {
724
            return payoutRate;
725
        }
726
    }
727
 
728
    private QtyAmountModel calculateSellinQtyAndValue(List<Order> orders) {
729
        int qty = orders.stream().collect(Collectors.summingInt(x ->
730
                x.getLineItem().getQuantity() - x.getLineItem().getReturnQty()));
731
        int value = orders.stream().collect(Collectors.summingInt(x ->
732
                Math.round(x.getLineItem().getUnitPrice() *
733
                        (x.getLineItem().getQuantity() - x.getLineItem().getReturnQty()))));
734
        return new QtyAmountModel(qty, value);
735
    }
736
 
35394 amit 737
    private Map<Integer, QtyAmountModel> getCriteriaQtyAmountModelMapForSellin(CreateOfferRequest createOfferRequest, int fofoId) throws ProfitMandiBusinessException {
738
        Map<Integer, QtyAmountModel> criteriaQtyAmountMap = new HashMap<>();
739
 
740
        Map<Integer, List<Order>> criteriaOrdersMap = offerRepository.getPartnerWiseSellin(fofoId, createOfferRequest, true);
741
 
35667 amit 742
        List<Order> baseCriteriaOrders = criteriaOrdersMap.get(0);
35394 amit 743
        Integer userBaseQty = null;
744
        Integer userBaseValue = null;
35667 amit 745
        if (baseCriteriaOrders != null && baseCriteriaOrders.size() > 0) {
746
            QtyAmountModel baseModel = calculateSellinQtyAndValue(baseCriteriaOrders);
747
            userBaseQty = baseModel.getQty();
748
            userBaseValue = (int) baseModel.getAmount();
749
            criteriaQtyAmountMap.put(0, baseModel);
750
        } else {
751
            criteriaQtyAmountMap.put(0, new QtyAmountModel(0, 0));
35394 amit 752
        }
753
 
754
        LOGGER.info("Processing sellin");
755
        for (ItemCriteriaPayout itemCriteriaPayout : createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts()) {
756
            int criteriaId = itemCriteriaPayout.getItemCriteria().getId();
757
 
758
            QtyAmountModel qtyAmountModel = new QtyAmountModel(0, 0);
35667 amit 759
            criteriaQtyAmountMap.put(criteriaId, qtyAmountModel);
35394 amit 760
 
761
            List<Order> orders = criteriaOrdersMap.get(criteriaId);
35667 amit 762
            if (orders == null || orders.isEmpty()) continue;
763
 
764
            QtyAmountModel criteriaModel = calculateSellinQtyAndValue(orders);
765
            int totalBaseQty = criteriaModel.getQty();
766
            int totalBaseValue = (int) criteriaModel.getAmount();
35394 amit 767
            if (userBaseQty != null) {
768
                totalBaseQty = userBaseQty;
769
                totalBaseValue = userBaseValue;
770
            }
771
 
772
            int purchasedValue;
773
            if (createOfferRequest.getTargetType().equals(AchievementType.VALUE)) {
774
                purchasedValue = totalBaseValue;
775
            } else {
776
                purchasedValue = totalBaseQty;
777
            }
778
            qtyAmountModel.setQty(totalBaseQty);
779
            qtyAmountModel.setAmount(totalBaseValue);
780
 
35667 amit 781
            PayoutSlab eligibleSlab = findEligibleSlab(itemCriteriaPayout.getPayoutSlabs(), purchasedValue);
35675 amit 782
            setSlabProgress(itemCriteriaPayout, eligibleSlab, purchasedValue);
35667 amit 783
            double finalPayout = calculateFinalPayout(eligibleSlab, itemCriteriaPayout.getAmountType(),
784
                    purchasedValue, purchasedValue);
35394 amit 785
            qtyAmountModel.setFinalPayout(finalPayout);
786
        }
787
        return criteriaQtyAmountMap;
788
    }
789
 
790
    private Map<Integer, QtyAmountModel> getCriteriaQtyAmountModelMapForSelloutAndActivation(CreateOfferRequest createOfferRequest, int fofoId) {
791
        Map<Integer, Map<Integer, List<FofoOrderItem>>> criteriaPartnerwiseTertiary = offerRepository.getCriteriaWisePartnerTertiary(createOfferRequest, fofoId);
792
        Map<Integer, QtyAmountModel> qtyAmountMap;
793
        final Map<String, LocalDateTime> activatedImeisActivationDateMap;
794
        qtyAmountMap = new HashMap<>();
795
        if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
796
            //All Serialnumbers for all eligible retailers
797
            List<String> serialNumbers = criteriaPartnerwiseTertiary.entrySet().stream().flatMap(x -> x.getValue().entrySet().stream().flatMap(foiList -> foiList.getValue().stream()))
798
                    .flatMap(y -> y.getFofoLineItems().stream()).filter(fli -> fli.getSerialNumber() != null)
799
                    .map(x -> x.getSerialNumber()).collect(Collectors.toList());
800
            if (serialNumbers.size() > 0) {
801
            /*if (imeisAllowedManually != null) {
802
                serialNumbers = serialNumbers.stream().filter(x -> imeisAllowedManually.contains(x)).collect(Collectors.toList());
803
            }*/
804
                activatedImeisActivationDateMap = activatedImeiRepository.selectBySerialNumbers(serialNumbers).stream()
805
                        .filter(x -> createOfferRequest.isWithinRange(x.getActivationTimestamp()))
806
                        .collect(Collectors.toMap(x -> x.getSerialNumber(), x -> x.getActivationTimestamp()));
807
            } else {
808
                activatedImeisActivationDateMap = null;
809
            }
810
        } else {
811
            activatedImeisActivationDateMap = null;
812
        }
813
 
814
        QtyAmountModel qtyAmountModel = null;
815
        if (createOfferRequest.isBaseCriteria()) {
35667 amit 816
            Map<Integer, List<FofoOrderItem>> baseCriteriaMap = criteriaPartnerwiseTertiary.get(0);
817
            List<FofoOrderItem> fofoOrderItems = baseCriteriaMap == null ? null : baseCriteriaMap.get(fofoId);
35394 amit 818
            int totalBaseQty = fofoOrderItems == null ? 0 : fofoOrderItems.stream().filter(x->createOfferRequest.isWithinRange(x.getCreateTimestamp())).collect(Collectors.summingInt(x -> (x.getQuantity())));
819
            int totalBaseValue = fofoOrderItems == null ? 0 : fofoOrderItems.stream().filter(x->createOfferRequest.isWithinRange(x.getCreateTimestamp())).mapToInt(x -> (Math.round(x.getDp())) * x.getQuantity()).sum();
820
            qtyAmountModel = new QtyAmountModel(totalBaseQty, totalBaseValue);
821
            if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
822
                Map<Integer, Integer> inventoryItemValueMap = new HashMap<>();
35667 amit 823
                if (fofoOrderItems != null) {
824
                    for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
825
                        fofoOrderItem.getFofoLineItems().stream().filter(x -> x.getSerialNumber() != null).forEach(
826
                                lineItem -> {
827
                                    if (activatedImeisActivationDateMap == null || activatedImeisActivationDateMap.containsKey(lineItem.getSerialNumber())) {
828
                                        inventoryItemValueMap.put(lineItem.getInventoryItemId(), (int) fofoOrderItem.getDp());
829
                                    }
35394 amit 830
                                }
35667 amit 831
                        );
832
                    }
35394 amit 833
                }
834
                qtyAmountModel.setActivationQty(inventoryItemValueMap.size());
835
                qtyAmountModel.setActivationAmount(inventoryItemValueMap.entrySet().stream().collect(Collectors.summingInt(x -> x.getValue())));
836
                qtyAmountMap.put(0, qtyAmountModel);
837
            }
838
        }
839
 
840
        //CriteriaPayoutWise
841
        for (ItemCriteriaPayout itemCriteriaPayout : createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts()) {
842
            int criteriaId = itemCriteriaPayout.getItemCriteria().getId();
843
            Map<Integer, List<FofoOrderItem>> ordersMap = criteriaPartnerwiseTertiary.get(criteriaId);
844
 
35667 amit 845
            QtyAmountModel criteriaQtyAmountModel = new QtyAmountModel(0, 0);
846
            qtyAmountMap.put(criteriaId, criteriaQtyAmountModel);
35394 amit 847
 
35667 amit 848
            if (ordersMap == null) continue;
35394 amit 849
 
35667 amit 850
            List<FofoOrderItem> fofoOrderItems = ordersMap.get(fofoId);
851
            if (fofoOrderItems == null || fofoOrderItems.isEmpty()) continue;
35394 amit 852
 
35673 amit 853
            int totalQty = fofoOrderItems.stream().filter(x -> createOfferRequest.isWithinRange(x.getCreateTimestamp())).collect(Collectors.summingInt(x -> (x.getQuantity())));
854
            int totalValue = fofoOrderItems.stream().filter(x -> createOfferRequest.isWithinRange(x.getCreateTimestamp())).collect(Collectors.summingInt(x -> Math.round(x.getDp()) * (x.getQuantity())));
35667 amit 855
            int eligibleQty = totalQty;
856
            int eligibleValue = totalValue;
857
            criteriaQtyAmountModel.setQty(totalQty);
858
            criteriaQtyAmountModel.setAmount(totalValue);
35394 amit 859
 
35667 amit 860
            Map<FofoLineItem, Integer> lineItemValueMap = new HashMap<>();
861
            if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
862
                for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
863
                    fofoOrderItem.getFofoLineItems().stream().filter(x -> x.getSerialNumber() != null).forEach(
864
                            lineItem -> {
865
                                if (activatedImeisActivationDateMap == null) {
866
                                    lineItemValueMap.put(lineItem, (int) fofoOrderItem.getDp());
867
                                } else if (activatedImeisActivationDateMap.containsKey(lineItem.getSerialNumber())) {
868
                                    if (itemCriteriaPayout.isWithinRange(activatedImeisActivationDateMap.get(lineItem.getSerialNumber()))) {
869
                                        lineItemValueMap.put(lineItem, (int) fofoOrderItem.getDp());
870
                                    }
871
                                }
872
                            }
873
                    );
35394 amit 874
                }
35667 amit 875
                eligibleQty = lineItemValueMap.size();
876
                eligibleValue = lineItemValueMap.entrySet().stream().collect(Collectors.summingInt(x -> x.getValue()));
877
                criteriaQtyAmountModel.setActivationQty(eligibleQty);
878
                criteriaQtyAmountModel.setActivationAmount(eligibleValue);
879
            }
35394 amit 880
 
35667 amit 881
            int eligibleBaseQty = eligibleQty;
882
            int eligibleBaseValue = eligibleValue;
883
            if (createOfferRequest.isBaseCriteria()) {
884
                eligibleBaseQty = qtyAmountModel.getActivationQty();
885
                eligibleBaseValue = (int) qtyAmountModel.getActivationAmount();
886
            }
35394 amit 887
 
35667 amit 888
            int eligibleSale = eligibleBaseValue;
889
            int eligibleCriteriaSale = eligibleValue;
890
            int eligibleCriteriaSaleDp = eligibleValue;
35394 amit 891
 
35667 amit 892
            if (createOfferRequest.getTargetType().equals(AchievementType.QUANTITY)) {
893
                eligibleSale = eligibleBaseQty;
894
                eligibleCriteriaSale = eligibleQty;
35394 amit 895
            }
896
 
35667 amit 897
            PayoutSlab eligibleSlab = findEligibleSlab(itemCriteriaPayout.getPayoutSlabs(), eligibleSale);
35675 amit 898
            setSlabProgress(itemCriteriaPayout, eligibleSlab, eligibleSale);
35667 amit 899
            double finalPayout = calculateFinalPayout(eligibleSlab, itemCriteriaPayout.getAmountType(),
900
                    eligibleCriteriaSaleDp, eligibleCriteriaSale);
901
            if (eligibleSlab != null) {
902
                LOGGER.info("Eligible Slab {}", eligibleSlab);
903
            }
904
            criteriaQtyAmountModel.setFinalPayout(finalPayout);
905
            LOGGER.info("Final Payout - {}", finalPayout);
35394 amit 906
        }
907
        return qtyAmountMap;
908
    }
909
 
31920 amit.gupta 910
    @Override
911
    public void processActivationtOffer(CreateOfferRequest createOfferRequest) throws ProfitMandiBusinessException {
912
        List<OfferPayout> offerPayouts = offerPayoutRepository.selectAllByOfferId(createOfferRequest.getId());
913
        List<ItemCriteriaPayout> itemCriteriaPayouts = createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts();
914
        Map<Integer, ItemCriteriaPayout> itemCriteriaPayoutMap = itemCriteriaPayouts.stream().collect(Collectors.toMap(x -> x.getItemCriteria().getId(), x -> x));
31923 amit.gupta 915
        LOGGER.info("itemCriteriaPayoutMap {}", itemCriteriaPayoutMap);
916
        LOGGER.info("offerPayouts {}", offerPayouts);
31924 amit.gupta 917
        Map<Integer, Map<Integer, Double>> fixedSlabCriteriaPartnerMap = offerPayouts.stream().filter(x -> itemCriteriaPayoutMap.get((int) x.getCriteriaId()).getAmountType().equals(AmountType.SLAB_FIXED))
31920 amit.gupta 918
                .collect(Collectors.groupingBy(x -> (int) x.getCriteriaId(), Collectors.groupingBy(x -> (int) x.getFofoId(), Collectors.summingDouble(x -> x.getSlabAmount()))));
919
 
920
 
921
        Map<String, Double> serialNumberPaid = offerPayouts.stream().filter(x -> x.getRejectTimestamp() == null).collect(Collectors.groupingBy(x -> x.getSerialNumber(), Collectors.summingDouble(x -> x.getSlabAmount())));
922
        Map<Integer, Map<Integer, List<FofoOrderItem>>> criteriaPartnerwiseTertiary = offerRepository.getCriteriaWisePartnerTertiary(createOfferRequest);
923
 
33087 amit.gupta 924
        Map<String, AgeingSummaryModel> ageingSummaryModelsMap = null;
33662 amit.gupta 925
        final Map<String, LocalDateTime> activatedImeisActivationDateMap;
34217 amit.gupta 926
        //Find Only eligible imeis if any
927
        List<String> imeisAllowedManually = offerEligibleImeiRepository.selectEligibleImeisByOfferId(createOfferRequest.getId());
928
 
31920 amit.gupta 929
        if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
930
            //All Serialnumbers for all eligible retailers
931
            List<String> serialNumbers = criteriaPartnerwiseTertiary.entrySet().stream().flatMap(x -> x.getValue().entrySet().stream().flatMap(foiList -> foiList.getValue().stream()))
932
                    .flatMap(y -> y.getFofoLineItems().stream()).filter(fli -> fli.getSerialNumber() != null)
933
                    .map(x -> x.getSerialNumber()).collect(Collectors.toList());
934
            if (serialNumbers.size() > 0) {
34217 amit.gupta 935
                if (imeisAllowedManually != null) {
936
                    serialNumbers = serialNumbers.stream().filter(x -> imeisAllowedManually.contains(x)).collect(Collectors.toList());
937
                }
33662 amit.gupta 938
                activatedImeisActivationDateMap = activatedImeiRepository.selectBySerialNumbers(serialNumbers).stream()
31920 amit.gupta 939
                        .filter(x -> createOfferRequest.isWithinRange(x.getActivationTimestamp()))
33441 amit.gupta 940
                        .collect(Collectors.toMap(x -> x.getSerialNumber(), x -> x.getActivationTimestamp()));
33613 amit.gupta 941
                ageingSummaryModelsMap = warehouseInventoryItemRepository.findStockAgeingByFofoIdSerialNumbers(0, serialNumbers).stream().collect(Collectors.toMap(x -> x.getSerialNumber(), x -> x, (u, v) -> v));
31920 amit.gupta 942
            } else {
33662 amit.gupta 943
                activatedImeisActivationDateMap = null;
31920 amit.gupta 944
            }
945
        } else {
33662 amit.gupta 946
            activatedImeisActivationDateMap = null;
31920 amit.gupta 947
        }
948
 
949
        Map<Integer, Integer> userBaseQtyMap = new HashMap<>();
950
        Map<Integer, Integer> userBaseValueMap = new HashMap<>();
951
        Map<Integer, Integer> eligibleBaseQtyMap = new HashMap<>();
952
        Map<Integer, Integer> eligibleBaseValueMap = new HashMap<>();
953
 
954
        if (createOfferRequest.isBaseCriteria()) {
955
            Map<Integer, List<FofoOrderItem>> foiMap = criteriaPartnerwiseTertiary.get(0);
956
            for (Map.Entry<Integer, List<FofoOrderItem>> orderEntry : foiMap.entrySet()) {
957
                int fofoId = orderEntry.getKey();
958
                List<FofoOrderItem> fofoOrderItems = orderEntry.getValue();
959
                int totalBaseQty = fofoOrderItems.stream().collect(Collectors.summingInt(x -> (x.getQuantity())));
960
                int totalBaseValue = fofoOrderItems.stream().collect(Collectors.summingInt(x -> (Math.round(x.getDp())) * x.getQuantity()));
961
                userBaseQtyMap.put(fofoId, totalBaseQty);
962
                userBaseValueMap.put(fofoId, totalBaseValue);
963
                if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
964
                    Map<Integer, Integer> inventoryItemValueMap = new HashMap<>();
965
                    for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
966
                        fofoOrderItem.getFofoLineItems().stream().filter(x -> x.getSerialNumber() != null).forEach(
967
                                lineItem -> {
33662 amit.gupta 968
                                    if (activatedImeisActivationDateMap == null || activatedImeisActivationDateMap.containsKey(lineItem.getSerialNumber())) {
31920 amit.gupta 969
                                        inventoryItemValueMap.put(lineItem.getInventoryItemId(), (int) fofoOrderItem.getDp());
970
                                    }
971
                                }
972
                        );
973
                    }
974
                    eligibleBaseQtyMap.put(fofoId, inventoryItemValueMap.size());
975
                    eligibleBaseValueMap.put(fofoId, inventoryItemValueMap.entrySet().stream().collect(Collectors.summingInt(x -> x.getValue())));
976
                } else {
977
                    eligibleBaseQtyMap.put(fofoId, totalBaseQty);
978
                    eligibleBaseValueMap.put(fofoId, totalBaseValue);
979
 
980
                }
981
 
982
            }
983
        }
984
 
985
        //As of now eligible sale is considered to be without special criteria like brand/
33441 amit.gupta 986
        //CriteriaPayoutWise
31920 amit.gupta 987
        for (ItemCriteriaPayout itemCriteriaPayout : createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts()) {
988
            int criteriaId = itemCriteriaPayout.getItemCriteria().getId();
989
            Map<Integer, List<FofoOrderItem>> ordersMap = criteriaPartnerwiseTertiary.get(criteriaId);
33441 amit.gupta 990
            //Partywise iteration
31920 amit.gupta 991
            for (Map.Entry<Integer, List<FofoOrderItem>> orderEntry : ordersMap.entrySet()) {
31992 amit.gupta 992
                double totalRolloutAmount = 0;
31920 amit.gupta 993
                int fofoId = orderEntry.getKey();
994
                List<FofoOrderItem> fofoOrderItems = orderEntry.getValue();
995
                OfferRowModel offerRowModel = new OfferRowModel();
996
                int totalQty = fofoOrderItems.stream().collect(Collectors.summingInt(x -> (x.getQuantity())));
997
                int totalValue = fofoOrderItems.stream().collect(Collectors.summingInt(x -> Math.round(x.getDp()) * (x.getQuantity())));
998
                int eligibleQty = totalQty;
999
                int eligibleValue = totalValue;
1000
                Map<FofoLineItem, Integer> lineItemValueMap = new HashMap<>();
1001
                if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
1002
                    for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
1003
                        fofoOrderItem.getFofoLineItems().stream().filter(x -> x.getSerialNumber() != null).forEach(
1004
                                lineItem -> {
33662 amit.gupta 1005
                                    if (activatedImeisActivationDateMap == null) {
31920 amit.gupta 1006
                                        lineItemValueMap.put(lineItem, (int) fofoOrderItem.getDp());
33441 amit.gupta 1007
 
33662 amit.gupta 1008
                                    } else if (activatedImeisActivationDateMap.containsKey(lineItem.getSerialNumber())) {
1009
                                        if (itemCriteriaPayout.isWithinRange(activatedImeisActivationDateMap.get(lineItem.getSerialNumber()))) {
33441 amit.gupta 1010
                                            lineItemValueMap.put(lineItem, (int) fofoOrderItem.getDp());
1011
                                        }
31920 amit.gupta 1012
                                    }
33441 amit.gupta 1013
 
31920 amit.gupta 1014
                                }
1015
                        );
1016
                    }
1017
                    eligibleQty = lineItemValueMap.size();
1018
                    eligibleValue = lineItemValueMap.entrySet().stream().collect(Collectors.summingInt(x -> x.getValue()));
1019
                    offerRowModel.setEligibleImeis(lineItemValueMap.keySet().stream().map(x -> x.getSerialNumber()).collect(Collectors.toList()));
1020
                }
1021
 
1022
                int totalBaseQty = totalQty;
1023
                int totalBaseValue = totalValue;
1024
                int eligibleBaseQty = eligibleQty;
1025
                int eligibleBaseValue = eligibleValue;
1026
                if (createOfferRequest.isBaseCriteria()) {
1027
                    totalBaseQty = userBaseQtyMap.get(fofoId) == null ? 0 : userBaseQtyMap.get(fofoId);
1028
                    totalBaseValue = userBaseValueMap.get(fofoId) == null ? 0 : userBaseValueMap.get(fofoId);
1029
                    eligibleBaseQty = eligibleBaseQtyMap.get(fofoId) == null ? 0 : eligibleBaseQtyMap.get(fofoId);
1030
                    eligibleBaseValue = eligibleBaseValueMap.get(fofoId) == null ? 0 : eligibleBaseValueMap.get(fofoId);
1031
                }
1032
 
1033
 
1034
                int totalSale = totalBaseValue;
1035
                int eligibleSale = eligibleBaseValue;
1036
                int eligibleCriteriaSale = eligibleValue;
1037
                int eligibleCriteriaSaleDp = eligibleValue;
1038
 
1039
                if (createOfferRequest.getTargetType().equals(AchievementType.QUANTITY)) {
1040
                    totalSale = totalBaseQty;
1041
                    eligibleSale = eligibleBaseQty;
1042
                    eligibleCriteriaSale = eligibleQty;
1043
                }
1044
 
1045
                offerRowModel.setTotalSale(totalSale);
1046
                offerRowModel.setEligibleSale(eligibleSale);
1047
                float eligiblePayoutValue = 0;
33662 amit.gupta 1048
                float previousPayoutValue = 0;
32345 amit.gupta 1049
                double finalPayout;
31920 amit.gupta 1050
                for (PayoutSlab payoutSlab : itemCriteriaPayout.getPayoutSlabs()) {
1051
                    if (payoutSlab.getOnwardsAmount() <= eligibleSale) {
32039 amit.gupta 1052
                        LOGGER.info("Eligible Sale {}", eligibleSale);
31920 amit.gupta 1053
                        offerRowModel.setPayoutTargetAchieved(payoutSlab.getOnwardsAmount());
1054
                        eligiblePayoutValue = payoutSlab.getPayoutAmount();
33662 amit.gupta 1055
                        previousPayoutValue = Math.min(eligiblePayoutValue, previousPayoutValue);
31920 amit.gupta 1056
                        offerRowModel.setPayoutValue(eligiblePayoutValue);
33662 amit.gupta 1057
                    } else {
1058
                        break;
31920 amit.gupta 1059
                    }
1060
                }
1061
                if (AmountType.PERCENTAGE.equals(itemCriteriaPayout.getAmountType())) {
1062
                    finalPayout = (eligiblePayoutValue * eligibleCriteriaSaleDp) / 100;
1063
                } else if (AmountType.FIXED.equals(itemCriteriaPayout.getAmountType())) {
1064
                    finalPayout = eligiblePayoutValue * eligibleCriteriaSale;
1065
                } else {
32039 amit.gupta 1066
                    Map<Integer, Double> fofoCriteriaMap = fixedSlabCriteriaPartnerMap.get(criteriaId);
1067
                    LOGGER.info("fofoCriteriaMap {}", fofoCriteriaMap);
31920 amit.gupta 1068
                    finalPayout = eligiblePayoutValue;
1069
                    if (fofoCriteriaMap != null) {
1070
                        if (fofoCriteriaMap.containsKey(fofoId)) {
33662 amit.gupta 1071
                            //double totalPayout = fofoCriteriaMap.get(fofoId);
1072
                            finalPayout = eligiblePayoutValue - previousPayoutValue;
32039 amit.gupta 1073
                            if (Math.abs(finalPayout) < Utils.DOUBLE_EPSILON) {
31920 amit.gupta 1074
                                finalPayout = 0;
32039 amit.gupta 1075
                            }
31920 amit.gupta 1076
                        }
1077
                    }
1078
                }
1079
 
32039 amit.gupta 1080
                LOGGER.info("Final Payout - {}", finalPayout);
1081
 
31920 amit.gupta 1082
                if (finalPayout > 0) {
1083
                    List<Integer> inventoryItemIds = lineItemValueMap.keySet().stream().map(x -> x.getInventoryItemId()).collect(Collectors.toList());
33662 amit.gupta 1084
                    int totalDpValue = lineItemValueMap.values().stream().collect(Collectors.summingInt(x -> x));
1085
                    LOGGER.info("Total DP Value {}", totalDpValue);
31920 amit.gupta 1086
                    Map<Integer, InventoryItem> inventoryItemsMap = inventoryItemRepository.selectAllByIds(inventoryItemIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
1087
                    for (Map.Entry<FofoLineItem, Integer> lineItemValueEntry : lineItemValueMap.entrySet()) {
33087 amit.gupta 1088
                        FofoLineItem fofoLineItem = lineItemValueEntry.getKey();
31920 amit.gupta 1089
                        double amount = 0;
1090
                        if (AmountType.SLAB_FIXED.equals(itemCriteriaPayout.getAmountType())) {
32039 amit.gupta 1091
                            amount = (eligiblePayoutValue * lineItemValueEntry.getValue()) / totalDpValue;
31920 amit.gupta 1092
                        } else {
33662 amit.gupta 1093
                            if (ageingSummaryModelsMap.containsKey(fofoLineItem.getSerialNumber())) {
35394 amit 1094
                                if (ageingSummaryModelsMap.get(fofoLineItem.getSerialNumber()).isAgedAbove(STOCK_AGEING_THRESHOLD_DAYS)) {
33662 amit.gupta 1095
                                    continue;
1096
                                }
1097
                            }
31920 amit.gupta 1098
                            amount = eligiblePayoutValue;
1099
                        }
33662 amit.gupta 1100
                        if (serialNumberPaid.containsKey(fofoLineItem.getSerialNumber())) {
1101
                            amount = amount - serialNumberPaid.get(fofoLineItem.getSerialNumber());
1102
                        }
32039 amit.gupta 1103
                        LOGGER.info("Amount - {}", amount);
31920 amit.gupta 1104
                        //ignore reasonably small
1105
                        if (amount < Utils.DOUBLE_EPSILON) continue;
1106
                        AmountModel amountModel = new AmountModel();
1107
                        amountModel.setAmountType(itemCriteriaPayout.getAmountType());
1108
                        amountModel.setAmount(amount);
32021 amit.gupta 1109
                        amountModel.setDiscount(createOfferRequest.isDiscount());
33087 amit.gupta 1110
                        InventoryPayoutModel inventoryPayoutModel = priceCircularService.getPayouts(inventoryItemsMap.get(fofoLineItem.getInventoryItemId()));
31920 amit.gupta 1111
                        double rolloutAmount = inventoryPayoutModel.getRolloutAmount(amountModel);
1112
                        totalRolloutAmount += rolloutAmount;
1113
 
33087 amit.gupta 1114
                        OfferPayout offerPayout = new OfferPayout(fofoId, createOfferRequest.getId(), criteriaId, amount, fofoLineItem.getSerialNumber(), rolloutAmount, SchemePayoutStatus.CREDITED, createOfferRequest.getDescription(), LocalDateTime.now());
33459 amit.gupta 1115
                        offerPayout.setInventoryItemId(fofoLineItem.getInventoryItemId());
31920 amit.gupta 1116
                        offerPayoutRepository.persist(offerPayout);
1117
                    }
32039 amit.gupta 1118
                    walletService.addAmountToWallet((int) fofoId, createOfferRequest.getId(), WalletReferenceType.ADDITIONAL_SCHEME, createOfferRequest.getDescription(), (float) totalRolloutAmount, LocalDateTime.now());
31920 amit.gupta 1119
                }
1120
            }
1121
        }
1122
        Offer offer = offerRepository.selectById(createOfferRequest.getId());
1123
        offer.setProcessedTimestamp(LocalDateTime.now());
1124
    }
1125
 
1126
    @Override
1127
    public void processSellin(CreateOfferRequest createOfferRequest) throws Exception {
1128
 
1129
        //List<OfferRowModel> offerRowModels = new ArrayList<>();
1130
        List<OfferPayout> offerPayouts = offerPayoutRepository.selectAllByOfferId(createOfferRequest.getId());
32345 amit.gupta 1131
        Map<String, Double> serialNumberPaid = offerPayouts.stream().filter(x -> x.getRejectTimestamp() == null).collect(Collectors.groupingBy(x -> x.getSerialNumber(), Collectors.summingDouble(x -> x.getSlabAmount())));
34072 ranu 1132
        LOGGER.info("serialNumberPaid {}", serialNumberPaid);
32345 amit.gupta 1133
        List<ItemCriteriaPayout> itemCriteriaPayouts = createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts();
1134
        Map<Integer, ItemCriteriaPayout> itemCriteriaPayoutMap = itemCriteriaPayouts.stream().collect(Collectors.toMap(x -> x.getItemCriteria().getId(), x -> x));
1135
        Map<Integer, Map<Integer, Double>> fixedSlabCriteriaPartnerMap = offerPayouts.stream().filter(x -> itemCriteriaPayoutMap.get((int) x.getCriteriaId()).getAmountType().equals(AmountType.SLAB_FIXED))
1136
                .collect(Collectors.groupingBy(x -> (int) x.getCriteriaId(), Collectors.groupingBy(x -> (int) x.getFofoId(), Collectors.summingDouble(x -> x.getSlabAmount()))));
31920 amit.gupta 1137
        Set<Long> fofoIds = offerPayouts.stream().map(x -> x.getFofoId()).collect(Collectors.toSet());
1138
 
1139
        Map<Integer, Map<Integer, List<Order>>> criteriaOrdersMap = offerRepository.getPartnerWiseSellin(createOfferRequest, true);
1140
 
32345 amit.gupta 1141
 
31920 amit.gupta 1142
        Map<Integer, List<Order>> userBaseCriteriaOrdersMap = null;
1143
        if (criteriaOrdersMap.get(0) != null && criteriaOrdersMap.get(0).size() > 0) {
1144
            userBaseCriteriaOrdersMap = criteriaOrdersMap.get(0).entrySet().stream()
1145
                    .filter(x -> !fofoIds.contains(x.getKey())).collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
1146
        }
1147
 
32345 amit.gupta 1148
 
31920 amit.gupta 1149
        Map<Integer, Integer> userBaseQtyMap = null;
1150
        Map<Integer, Integer> userBaseValueMap = null;
1151
        if (userBaseCriteriaOrdersMap != null) {
1152
            userBaseQtyMap = new HashMap<>();
1153
            userBaseValueMap = new HashMap<>();
1154
            for (Map.Entry<Integer, List<Order>> orderEntry : userBaseCriteriaOrdersMap.entrySet()) {
1155
                int fofoId = orderEntry.getKey();
1156
                List<Order> orders = orderEntry.getValue();
1157
                int totalBaseQty = orders.stream().collect(Collectors.summingInt(x -> (x.getLineItem().getQuantity() - x.getLineItem().getReturnQty())));
1158
                int totalBaseValue = orders.stream().collect(Collectors.summingInt(x ->
1159
                        Math.round(x.getLineItem().getUnitPrice() * (x.getLineItem().getQuantity() - x.getLineItem().getReturnQty()))
1160
                ));
1161
                userBaseQtyMap.put(fofoId, totalBaseQty);
1162
                userBaseValueMap.put(fofoId, totalBaseValue);
1163
            }
1164
        }
1165
        LOGGER.info("Base Qty Map - {}", userBaseQtyMap);
1166
        LOGGER.info("Base Value Map - {}", userBaseValueMap);
1167
 
1168
        LOGGER.info("Processing sellin");
1169
        List<OfferPayout> offerPayoutsNew = new ArrayList<>();
1170
        for (ItemCriteriaPayout itemCriteriaPayout : createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts()) {
1171
            int criteriaId = itemCriteriaPayout.getItemCriteria().getId();
1172
            Map<Integer, List<Order>> ordersMap = criteriaOrdersMap.get(criteriaId).entrySet().stream()
1173
                    .filter(x -> !fofoIds.contains(x.getKey())).collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
1174
            for (Map.Entry<Integer, List<Order>> orderEntry : ordersMap.entrySet()) {
1175
                int fofoId = orderEntry.getKey();
1176
                //CustomRetailer retailer = retailerService.getAllFofoRetailers().get(fofoId);
1177
                List<Order> orders = orderEntry.getValue();
32345 amit.gupta 1178
                //Set<String> returnedSerialNumbers = orders.stream().filter(x -> x.getSerialNumber() != null).flatMap(x -> x.getReturnedImeis().stream()).collect(Collectors.toSet());
31920 amit.gupta 1179
                int totalQty = orders.stream().collect(Collectors.summingInt(x -> (x.getLineItem().getQuantity() - x.getLineItem().getReturnQty())));
1180
                int totalValue = orders.stream().collect(Collectors.summingInt(x -> Math.round(x.getLineItem().
1181
                        getUnitPrice() * (x.getLineItem().getQuantity() - x.getLineItem().getReturnQty()))));
1182
                int totalBaseQty = totalQty;
1183
                int totalBaseValue = totalValue;
1184
                if (userBaseCriteriaOrdersMap != null) {
1185
                    if (userBaseQtyMap.containsKey(fofoId)) {
1186
                        totalBaseQty = userBaseQtyMap.get(fofoId);
1187
                        totalBaseValue = userBaseValueMap.get(fofoId);
1188
                    } else {
1189
                        continue;
1190
                    }
1191
                }
1192
 
1193
                int purchasedValue;
1194
                if (createOfferRequest.getTargetType().equals(AchievementType.VALUE)) {
1195
                    purchasedValue = totalBaseValue;
1196
                } else {
1197
                    purchasedValue = totalBaseQty;
1198
                }
1199
 
33695 amit.gupta 1200
                PayoutSlab eligibleSlab = null;
33662 amit.gupta 1201
 
1202
                for (PayoutSlab payoutSlab : itemCriteriaPayout.getPayoutSlabs()) {
1203
                    if (payoutSlab.getOnwardsAmount() <= purchasedValue) {
1204
                        eligibleSlab = payoutSlab;
1205
                    } else {
1206
                        break;
1207
                    }
1208
                }
33695 amit.gupta 1209
                if (eligibleSlab == null) continue;
31920 amit.gupta 1210
                List<Integer> orderIds = orders.stream().map(x -> x.getId()).collect(Collectors.toList());
1211
                Map<Integer, LineItem> lineItemMap = orders.stream().collect(Collectors.toMap(x -> x.getLineItem().getId(), x -> x.getLineItem()));
1212
                List<WarehouseScan> warehouseScans = warehouseScanRepository.selectAllByOrderIds(orderIds);
32540 amit.gupta 1213
                LOGGER.info("Warehosue scans --> {}", warehouseScans);
32345 amit.gupta 1214
                List<Integer> warehouseInventoryItemIds = warehouseScans.stream().collect(Collectors.groupingBy(x -> x.getInventoryItemId())).entrySet()
31920 amit.gupta 1215
                        .stream().filter(x -> x.getValue().size() == 1).map(x -> x.getKey()).collect(Collectors.toList());
32795 amit.gupta 1216
 
1217
                List<OfferPayout> partnerPayouts = offerPayouts.stream().filter(x -> x.getFofoId() == fofoId).collect(Collectors.toList());
32868 amit.gupta 1218
                Set<String> serialNumbersRejected = partnerPayouts.stream().filter(x -> x.getStatus().equals(SchemePayoutStatus.REJECTED)).map(x -> x.getSerialNumber()).collect(Collectors.toSet());
32795 amit.gupta 1219
 
34092 amit.gupta 1220
                Set<String> billedNotCancelledSerialNumbers;
32345 amit.gupta 1221
                LOGGER.info("warehouseInventoryItemIds {}", warehouseInventoryItemIds);
1222
                if (warehouseInventoryItemIds.size() > 0) {
1223
                    List<WarehouseInventoryItem> warehouseInventoryItems = warehouseInventoryItemRepository.selectAllByIds(warehouseInventoryItemIds);
34092 amit.gupta 1224
                    billedNotCancelledSerialNumbers = warehouseInventoryItems.stream().map(x -> x.getSerialNumber()).collect(Collectors.toSet());
31920 amit.gupta 1225
                } else {
34092 amit.gupta 1226
                    billedNotCancelledSerialNumbers = new HashSet<>();
31920 amit.gupta 1227
                }
34092 amit.gupta 1228
                LOGGER.info("billedNotCancelledSerialNumbers {}", billedNotCancelledSerialNumbers);
1229
 
31920 amit.gupta 1230
                Map<String, LineItem> serialNumberMap = lineItemImeisRepository.selectByLineItemIds(new ArrayList<>(lineItemMap.keySet()))
32868 amit.gupta 1231
                        .stream().filter(x -> !serialNumbersRejected.contains(x.getSerialNumber())).collect(Collectors.toMap(x -> x.getSerialNumber(), x -> lineItemMap.get(x.getLineItemId()), (x1, x2) -> x1.getId() > x2.getId() ? x1 : x2));
31920 amit.gupta 1232
 
34226 amit.gupta 1233
                List<String> manuallyEligibleImeis = offerEligibleImeiRepository.selectEligibleImeisByOfferId(createOfferRequest.getId());
32795 amit.gupta 1234
 
34092 amit.gupta 1235
                serialNumberMap = serialNumberMap.entrySet().stream().filter(x -> billedNotCancelledSerialNumbers.contains(x.getKey())).collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
34231 amit.gupta 1236
 
1237
                //Just a validation need to revaluate this
1238
                Map<String, InventoryItem> serialNumberInventoryItemMap = this.getInventoryItemMap(fofoId, serialNumberMap);
1239
                if (serialNumberInventoryItemMap.size() < billedNotCancelledSerialNumbers.size()) continue;
1240
 
34623 amit.gupta 1241
                LOGGER.info("serialNumberMap {}", serialNumberMap);
34226 amit.gupta 1242
                if (manuallyEligibleImeis != null) {
34227 amit.gupta 1243
                    serialNumberMap = serialNumberMap.entrySet().stream().filter(x -> manuallyEligibleImeis.contains(x.getKey())).collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
34624 amit.gupta 1244
                    if (serialNumberMap.size() == 0) continue;
34231 amit.gupta 1245
                    serialNumberInventoryItemMap = this.getInventoryItemMap(fofoId, serialNumberMap);
34226 amit.gupta 1246
                }
32543 amit.gupta 1247
                if (serialNumberMap.size() == 0) continue;
32064 amit.gupta 1248
                //Continue if all imeis havent been grned
1249
 
32345 amit.gupta 1250
 
33662 amit.gupta 1251
                float eligiblePayoutValue = eligibleSlab.getPayoutAmount();
32345 amit.gupta 1252
                double finalPayout;
1253
                if (AmountType.PERCENTAGE.equals(itemCriteriaPayout.getAmountType())) {
1254
                    finalPayout = (eligiblePayoutValue * purchasedValue) / 100;
1255
                } else if (AmountType.FIXED.equals(itemCriteriaPayout.getAmountType())) {
1256
                    finalPayout = eligiblePayoutValue * purchasedValue;
1257
                } else {
33695 amit.gupta 1258
                    Map<Integer, Double> fofoCriteriaPayoutMap = fixedSlabCriteriaPartnerMap.get(criteriaId);
1259
                    LOGGER.info("fofoCriteriaMap {}", fofoCriteriaPayoutMap);
32345 amit.gupta 1260
                    finalPayout = eligiblePayoutValue;
33695 amit.gupta 1261
                    if (fofoCriteriaPayoutMap != null && fofoCriteriaPayoutMap.containsKey(fofoId)) {
1262
                        finalPayout = eligiblePayoutValue - fofoCriteriaPayoutMap.get(fofoId);
1263
                        if (Math.abs(finalPayout) < Utils.DOUBLE_EPSILON) {
1264
                            finalPayout = 0;
32345 amit.gupta 1265
                        }
31920 amit.gupta 1266
                    }
1267
                }
32345 amit.gupta 1268
 
1269
                LOGGER.info("Or - {}", finalPayout);
1270
 
1271
                if (finalPayout > 0) {
1272
                    double totalRolloutAmount = 0;
1273
                    int totalDpValue = serialNumberInventoryItemMap.entrySet().stream().mapToInt(x -> (int) x.getValue().getUnitPrice()).sum();
1274
                    for (Map.Entry<String, InventoryItem> serialNumberInventoryItemEntry : serialNumberInventoryItemMap.entrySet()) {
1275
                        double amount = 0;
1276
                        LOGGER.info("Total DP Value {}", totalDpValue);
1277
                        if (AmountType.SLAB_FIXED.equals(itemCriteriaPayout.getAmountType())) {
1278
                            amount = (eligiblePayoutValue * serialNumberInventoryItemEntry.getValue().getUnitPrice()) / totalDpValue;
1279
                            LOGGER.info("Amount - {}", amount);
1280
                        } else {
1281
                            amount = eligiblePayoutValue;
1282
                            if (serialNumberPaid.containsKey(serialNumberInventoryItemEntry.getKey())) {
34073 ranu 1283
                                LOGGER.info("serial number slab amount {}", serialNumberPaid.get(serialNumberInventoryItemEntry.getKey()));
32345 amit.gupta 1284
                                amount = amount - serialNumberPaid.get(serialNumberInventoryItemEntry.getKey());
1285
                            }
1286
                        }
1287
                        LOGGER.info("Amount - {}", amount);
1288
                        //ignore reasonably small
33662 amit.gupta 1289
                        if (Math.abs(amount) < Utils.DOUBLE_EPSILON) continue;
32345 amit.gupta 1290
                        AmountModel amountModel = new AmountModel();
1291
                        amountModel.setAmountType(itemCriteriaPayout.getAmountType());
1292
                        amountModel.setAmount(amount);
1293
                        amountModel.setDiscount(createOfferRequest.isDiscount());
1294
                        InventoryPayoutModel inventoryPayoutModel = priceCircularService.getPayouts(serialNumberInventoryItemEntry.getValue());
1295
                        double rolloutAmount = inventoryPayoutModel.getRolloutAmount(amountModel);
1296
                        totalRolloutAmount += rolloutAmount;
1297
 
1298
                        OfferPayout offerPayout = new OfferPayout(fofoId, createOfferRequest.getId(), criteriaId, amount, serialNumberInventoryItemEntry.getKey(), rolloutAmount, SchemePayoutStatus.CREDITED, createOfferRequest.getDescription(), LocalDateTime.now());
33459 amit.gupta 1299
                        offerPayout.setInventoryItemId(serialNumberInventoryItemEntry.getValue().getId());
32345 amit.gupta 1300
                        offerPayoutRepository.persist(offerPayout);
1301
                    }
34623 amit.gupta 1302
                    walletService.addAmountToWallet(fofoId, createOfferRequest.getId(), WalletReferenceType.ADDITIONAL_SCHEME, createOfferRequest.getDescription(), (float) totalRolloutAmount, LocalDateTime.now());
32345 amit.gupta 1303
                }
31920 amit.gupta 1304
            }
1305
        }
1306
        Offer offer = offerRepository.selectById(createOfferRequest.getId());
1307
        offer.setProcessedTimestamp(LocalDateTime.now());
1308
    }
32064 amit.gupta 1309
 
33441 amit.gupta 1310
    private void rollbackPayout(int fofoId, int offerId, List<
1311
            OfferPayout> partnerPayouts, Set<String> returnedSerialNumbers) throws ProfitMandiBusinessException {
32795 amit.gupta 1312
        LOGGER.info("Rollback payout called for offerId {}", offerId);
1313
        float amountToRollback = 0;
1314
        int totalImeis = 0;
1315
        for (OfferPayout partnerPayout : partnerPayouts) {
1316
            LOGGER.info("serialNumberInventoryItemMap - {}", returnedSerialNumbers);
1317
            LOGGER.info("Serial Number - {}", partnerPayout.getSerialNumber());
1318
            if (returnedSerialNumbers.contains(partnerPayout.getSerialNumber()) && partnerPayout.getStatus().equals(SchemePayoutStatus.CREDITED)) {
1319
                partnerPayout.setRejectTimestamp(LocalDateTime.now());
1320
                partnerPayout.setStatus(SchemePayoutStatus.REJECTED);
1321
                amountToRollback += partnerPayout.getAmount();
1322
                totalImeis += 1;
1323
            }
1324
        }
1325
        if (amountToRollback > 0) {
1326
            LOGGER.info("Amount to Rollback - {}", amountToRollback);
1327
            walletService.rollbackAmountFromWallet(fofoId, amountToRollback, offerId, WalletReferenceType.ADDITIONAL_SCHEME, "Stock Returned, total " + totalImeis + "pc(s)", LocalDateTime.now());
1328
        }
1329
    }
1330
 
33441 amit.gupta 1331
    private Map<String, InventoryItem> getInventoryItemMap(int fofoId, Map<String, LineItem> serialNumberMap) throws
1332
            ProfitMandiBusinessException {
32064 amit.gupta 1333
        List<InventoryItem> inventoryItems = inventoryItemRepository.selectBySerialNumbers(serialNumberMap.keySet());
32345 amit.gupta 1334
        inventoryItems = inventoryItems.stream().filter(x -> x.getFofoId() == fofoId).collect(Collectors.toList());
1335
        Map<String, InventoryItem> inventoryItemMap = inventoryItems.stream().collect(Collectors.toMap(x -> x.getSerialNumber(), x -> x, (u, v) -> v.getCreateTimestamp().isAfter(u.getCreateTimestamp()) ? v : u));
32064 amit.gupta 1336
        return inventoryItemMap;
1337
    }
33030 amit.gupta 1338
 
1339
 
1340
    @Override
33247 ranu 1341
    public String getPartnerCriteriaString(PartnerCriteria partnerCriteria) throws ProfitMandiBusinessException {
33030 amit.gupta 1342
        StringBuilder sb = new StringBuilder();
1343
        if (partnerCriteria.getFofoIds().size() > 0) {
1344
            List<Integer> fofoIds = partnerCriteria.getFofoIds();
1345
            appendPartnerCodes(fofoIds, sb);
1346
 
1347
        } else {
1348
            sb.append("All");
1349
            if (partnerCriteria.getPartnerTypes().size() > 0) {
1350
                sb.append(" ").append(String.join(", ", partnerCriteria.getPartnerTypes().stream().map(x -> x.getValue()).collect(Collectors.toList())));
1351
            }
1352
            sb.append(" partners ");
1353
            if (partnerCriteria.getRegionIds().size() > 0) {
1354
                sb.append("from ");
1355
                sb.append(String.join(", ", partnerCriteria.getRegionIds().stream().map(x -> ProfitMandiConstants.WAREHOUSE_MAP.get(x)).collect(Collectors.toList())));
1356
            }
1357
            if (partnerCriteria.getExcludeFofoIds() != null && partnerCriteria.getExcludeFofoIds().size() > 0) {
35394 amit 1358
                sb.append("<b>excluding</b> ");
33030 amit.gupta 1359
                appendPartnerCodes(partnerCriteria.getExcludeFofoIds(), sb);
1360
            }
1361
        }
1362
        return sb.toString();
1363
    }
1364
 
33999 tejus.loha 1365
    @Override
1366
    public ByteArrayOutputStream createCSVOfferReport(CreateOfferRequest createOfferRequest) throws Exception {
1367
        List<List<?>> listOfRows = new ArrayList<>();
1368
        ByteArrayOutputStream baos = null;
1369
        Collection<OfferRowModel> offerRowModels = offerRepository.getOfferRows(createOfferRequest);
1370
        ItemCriteriaPayout itemCriteriaPayout = createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts().get(0);
35394 amit 1371
        // Batch fetch all retailers once to avoid N+1 queries
1372
        Map<Integer, CustomRetailer> allRetailers = retailerService.getAllFofoRetailers();
33999 tejus.loha 1373
        if (createOfferRequest.getSchemeType().equals(OfferSchemeType.SELLIN)) {
1374
            for (OfferRowModel offerRowModel : offerRowModels) {
35394 amit 1375
                CustomRetailer customRetailer = allRetailers.get(offerRowModel.getFofoId());
33999 tejus.loha 1376
                listOfRows.add(Arrays.asList(
1377
                        createOfferRequest.getId()
1378
                        , createOfferRequest.getName()
1379
                        , createOfferRequest.getTargetType()
1380
                        , createOfferRequest.getSchemeType()
1381
                        , itemCriteriaPayout.getStartDate()
1382
                        , itemCriteriaPayout.getEndDate()
1383
//                        , createOfferRequest.getBrandShareTerms()
1384
                        , createOfferRequest.getSellinPercentage()
1385
                        , "--"
1386
                        , createOfferRequest.getItemCriteriaString()
1387
                        , createOfferRequest.getStartDate()
1388
                        , createOfferRequest.getEndDate()
1389
                        , createOfferRequest.getCreatedOn()
1390
                        , customRetailer.getPartnerId()
1391
                        , customRetailer.getBusinessName()
1392
                        , customRetailer.getCode()
1393
                        , offerRowModel.getTotalBasePurchaseValue()
1394
                        , offerRowModel.getAchievedTarget()
1395
                        , offerRowModel.getPayoutPurchaseValue()
1396
                        , offerRowModel.getPayout()
1397
                        , offerRowModel.getPayoutType()
1398
                        , offerRowModel.getFinalPayout()
1399
                        , String.join(", ", offerRowModel.getEligibleImeis())));
1400
            }
1401
            baos = FileUtil.getCSVByteStream(
1402
                    Arrays.asList(
1403
                            "Id"
1404
                            , "Name"
1405
                            , "Target Type"
1406
                            , "Scheme Type"
1407
                            , "Payout Start"
1408
                            , "Payout End"
1409
//                            , "Brand %"
1410
                            , "Sellin %"
1411
                            , "Partner Criteria"
1412
                            , "Item Criteria"
1413
                            , "Start"
1414
                            , "End"
1415
                            , "Created"
1416
                            , "Partner Id"
1417
                            , "Partner Name"
1418
                            , "Partner Code"
1419
                            , "Base Purchase"
1420
                            , "Achieved Target"
1421
                            , "Eligible Purchase"
1422
                            , "Slab Amount"
1423
                            , "Slab Amount Type"
1424
                            , "Payout Value(Rs.)"
1425
                            , "Eligible IMEIs"
1426
                            , "Billing Pending Imeis"
1427
                    ), listOfRows);
1428
        } else {
1429
            for (OfferRowModel offerRowModel : offerRowModels) {
35394 amit 1430
                CustomRetailer customRetailer = allRetailers.get(offerRowModel.getFofoId());
33999 tejus.loha 1431
                listOfRows.add(Arrays.asList(
1432
                                createOfferRequest.getId()
1433
                                , createOfferRequest.getName()
1434
                                , createOfferRequest.getTargetType()
1435
                                , createOfferRequest.getSchemeType()
1436
                                , itemCriteriaPayout.getStartDate()
1437
                                , itemCriteriaPayout.getEndDate()
1438
//                                , createOfferRequest.getBrandShareTerms()
1439
                                , createOfferRequest.getSellinPercentage()
1440
                                , createOfferRequest.getPartnerCriteriaString()
1441
                                , createOfferRequest.getItemCriteriaString()
1442
                                , createOfferRequest.getStartDate()
1443
                                , createOfferRequest.getEndDate()
1444
                                , createOfferRequest.getCreatedOn()
1445
                                , customRetailer.getPartnerId()
1446
                                , customRetailer.getBusinessName()
1447
                                , customRetailer.getCode()
1448
                                , offerRowModel.getTotalSale()
1449
                                , offerRowModel.getEligibleSale()
1450
                                , offerRowModel.getPayoutTargetAchieved()
1451
                                , offerRowModel.getPayoutValue()
1452
                                , offerRowModel.getPayoutType()
1453
                                , offerRowModel.getPayoutValueDp()
1454
                                , offerRowModel.getFinalPayout()
1455
                                , String.join(", ", offerRowModel.getEligibleImeis())
1456
//                        ,String.join(", ", offerRowModel.getBaseCriteria())
1457
                        )
1458
                );
1459
            }
1460
            baos = FileUtil.getCSVByteStream(
1461
                    Arrays.asList(
1462
                            "Id"
1463
                            , "Name"
1464
                            , "Target Type"
1465
                            , "Scheme Type"
1466
                            , "Payout Start"
1467
                            , "Payout End"
1468
//                            , "Brand %"
1469
                            , "Sellin %"
1470
                            , "Partner Criteria"
1471
                            , "Item Criteria"
1472
                            , "Start"
1473
                            , "End"
1474
                            , "Created"
1475
                            , "Partner Id"
1476
                            , "Partner Name"
1477
                            , "Partner Code"
1478
                            , "Total Sale"
1479
                            , "Eligible Sale"
1480
                            , "Payout Target Achieved"
1481
                            , "Payout Amount"
1482
                            , "Payout Amount Type"
1483
                            , "Payout Value DP"
1484
                            , "Amount to be credited"
1485
                            , "Eligible Activated Imeis"
1486
                    ), listOfRows);
1487
        }
1488
        return baos;
1489
    }
1490
 
35205 amit 1491
    @Override
1492
    public void sendWhatsapp(Offer offer, List<Integer> fofoIds, String imageUrl) throws Exception {
1493
        if (fofoIds == null) {
1494
            fofoIds = fofoStoreRepository.selectActiveStores().stream().map(x -> x.getId()).collect(Collectors.toList());
1495
        }
1496
        final List<Integer> finalFofoIds = fofoIds;
1497
        //List<String> mobileNumbers = retailerService.getAllFofoRetailers().entrySet().stream().filter(x -> finalFofoIds.contains(x.getKey())).map(x -> x.getValue().getMobileNumber()).collect(Collectors.toList());
1498
        List<String> mobileNumbers = new ArrayList<>();
1499
        mobileNumbers.add("9911565032");
1500
        //mobileNumbers.add("9990381569");
1501
        //mobileNumbers.add("8383849914");
1502
        String message = "%s\n" +
1503
                "On %s of select models\n" +
1504
                "From %s to %s\n" +
1505
                "\n" +
1506
                "Happy Selling\n" +
1507
                "Team Smartdukaan";
1508
        //TV's mobile
1509
        for (String mobileNumber : mobileNumbers) {
1510
            notificationService.sendWhatsappMediaMessage(String.format(message, offer.getName(),
1511
                    offer.getSchemeType().toString(), FormattingUtils.formatDate(offer.getStartDate()),
1512
                    FormattingUtils.formatDate(offer.getEndDate())), mobileNumber, imageUrl, "offer-" + offer.getId() + ".png", WhatsappMessageType.IMAGE);
1513
        }
1514
    }
1515
 
33247 ranu 1516
    private void appendPartnerCodes(List<Integer> fofoIds, StringBuilder sb) throws ProfitMandiBusinessException {
33030 amit.gupta 1517
        Map<Integer, CustomRetailer> customRetailersMap = retailerService.getAllFofoRetailers();
33031 amit.gupta 1518
        List<String> businessNames = fofoIds.stream().map(x -> customRetailersMap.get(x)).filter(x -> x != null).map(x -> x.getBusinessName()).collect(Collectors.toList());
33030 amit.gupta 1519
        sb.append(String.join(", ", businessNames));
1520
    }
35856 amit 1521
 
1522
    @Override
1523
    public void deleteOffer(int offerId) throws ProfitMandiBusinessException {
1524
        Offer offer = offerRepository.selectById(offerId);
1525
        if (offer == null) {
1526
            throw new ProfitMandiBusinessException("Offer not found", "Offer not found", "");
1527
        }
1528
        if (offer.isActive()) {
1529
            throw new ProfitMandiBusinessException("Cannot delete a published offer", "Cannot delete a published offer", "");
1530
        }
1531
        List<TargetSlabEntity> targetSlabs = offerTargetSlabRepository.selectByOfferIds(Collections.singletonList(offerId));
1532
        for (TargetSlabEntity targetSlab : targetSlabs) {
1533
            genericRepository.delete(targetSlab);
1534
        }
1535
        genericRepository.delete(offer);
1536
        LOGGER.info("Deleted offer {} and {} target slabs", offerId, targetSlabs.size());
1537
    }
1538
 
1539
    @Override
1540
    public List<Offer> publishAllUnpublished(YearMonth yearMonth) throws ProfitMandiBusinessException {
1541
        List<Offer> allOffers = offerRepository.selectAll(yearMonth, false);
1542
        List<Offer> unpublished = allOffers.stream().filter(o -> !o.isActive()).collect(Collectors.toList());
1543
        for (Offer offer : unpublished) {
1544
            offer.setActive(true);
1545
        }
1546
        LOGGER.info("Published {} unpublished offers for {}", unpublished.size(), yearMonth);
1547
        return unpublished;
1548
    }
35885 amit 1549
 
1550
    @Override
1551
    public void removePartnersFromOffer(int offerId, List<Integer> fofoIds) throws ProfitMandiBusinessException {
1552
        Offer offer = offerRepository.selectById(offerId);
1553
        if (offer == null) {
1554
            throw new ProfitMandiBusinessException("Offer not found", "Offer not found", "");
1555
        }
1556
        PartnerCriteria partnerCriteria = gson.fromJson(offer.getPartnerCriteria(), PartnerCriteria.class);
1557
        if (partnerCriteria.getFofoIds() != null) {
1558
            partnerCriteria.getFofoIds().removeAll(fofoIds);
1559
        }
1560
        offer.setPartnerCriteria(gson.toJson(partnerCriteria));
1561
        genericRepository.persist(offer);
1562
        offerPartnerRepository.deleteByOfferIdAndFofoIds(offerId, fofoIds);
1563
        LOGGER.info("Removed partners {} from offer {}", fofoIds, offerId);
1564
    }
1565
 
1566
    @Override
1567
    public void addPartnersToOffer(int offerId, List<Integer> fofoIds) throws ProfitMandiBusinessException {
1568
        Offer offer = offerRepository.selectById(offerId);
1569
        if (offer == null) {
1570
            throw new ProfitMandiBusinessException("Offer not found", "Offer not found", "");
1571
        }
1572
        PartnerCriteria partnerCriteria = gson.fromJson(offer.getPartnerCriteria(), PartnerCriteria.class);
1573
        List<Integer> existingFofoIds = partnerCriteria.getFofoIds();
1574
        if (existingFofoIds == null) {
1575
            existingFofoIds = new ArrayList<>();
1576
        }
1577
        for (int fofoId : fofoIds) {
1578
            if (!existingFofoIds.contains(fofoId)) {
1579
                existingFofoIds.add(fofoId);
1580
                OfferPartner offerPartner = new OfferPartner();
1581
                offerPartner.setOfferId(offerId);
1582
                offerPartner.setFofoId(fofoId);
1583
                offerPartnerRepository.persist(offerPartner);
1584
            }
1585
        }
1586
        partnerCriteria.setFofoIds(existingFofoIds);
1587
        offer.setPartnerCriteria(gson.toJson(partnerCriteria));
1588
        genericRepository.persist(offer);
1589
        LOGGER.info("Added partners {} to offer {}", fofoIds, offerId);
1590
    }
1591
 
1592
    @Override
1593
    public int cloneOfferForPartners(int sourceOfferId, List<Integer> fofoIds, List<Integer> targets) throws ProfitMandiBusinessException {
1594
        Offer sourceOffer = offerRepository.selectById(sourceOfferId);
1595
        if (sourceOffer == null) {
1596
            throw new ProfitMandiBusinessException("Source offer not found", "Source offer not found", "");
1597
        }
1598
        CreateOfferRequest clonedRequest = this.getCreateOfferRequest(sourceOffer);
1599
        clonedRequest.setId(0);
1600
        clonedRequest.setActive(false);
1601
 
1602
        PartnerCriteria newPartnerCriteria = new PartnerCriteria();
1603
        newPartnerCriteria.setFofoIds(new ArrayList<>(fofoIds));
1604
        newPartnerCriteria.setExcludeFofoIds(new ArrayList<>());
1605
        newPartnerCriteria.setRegionIds(clonedRequest.getPartnerCriteria().getRegionIds() != null
1606
                ? new ArrayList<>(clonedRequest.getPartnerCriteria().getRegionIds()) : new ArrayList<>());
1607
        newPartnerCriteria.setPartnerTypes(clonedRequest.getPartnerCriteria().getPartnerTypes() != null
1608
                ? new ArrayList<>(clonedRequest.getPartnerCriteria().getPartnerTypes()) : new ArrayList<>());
1609
        clonedRequest.setPartnerCriteria(newPartnerCriteria);
1610
 
1611
        if (targets != null && !targets.isEmpty() && !clonedRequest.getTargetSlabs().isEmpty()) {
1612
            List<PayoutSlab> payoutSlabs = clonedRequest.getTargetSlabs().get(0).getItemCriteriaPayouts()
1613
                    .stream().flatMap(x -> x.getPayoutSlabs().stream()).collect(Collectors.toList());
1614
            int counter = 0;
1615
            for (PayoutSlab payoutSlab : payoutSlabs) {
1616
                if (counter < targets.size()) {
1617
                    payoutSlab.setOnwardsAmount(targets.get(counter));
1618
                    counter++;
1619
                }
1620
            }
1621
        }
1622
 
1623
        this.addOfferService(clonedRequest);
1624
        LOGGER.info("Cloned offer {} to new offer {} for partners {}", sourceOfferId, clonedRequest.getId(), fofoIds);
1625
        return clonedRequest.getId();
1626
    }
1627
 
1628
    @Override
1629
    public void updateOfferTargets(int offerId, List<Integer> newTargets) throws ProfitMandiBusinessException {
1630
        Offer offer = offerRepository.selectById(offerId);
1631
        if (offer == null) {
1632
            throw new ProfitMandiBusinessException("Offer not found", "Offer not found", "");
1633
        }
1634
        List<TargetSlabEntity> targetSlabs = offerTargetSlabRepository.selectEntitiesByOfferId(offerId);
1635
        targetSlabs.sort(Comparator.comparing(TargetSlabEntity::getPayoutTarget));
1636
 
1637
        if (newTargets.size() != targetSlabs.size()) {
1638
            throw new ProfitMandiBusinessException(
1639
                    "Target count mismatch. Expected " + targetSlabs.size() + " but got " + newTargets.size(),
1640
                    "Target count mismatch", "");
1641
        }
1642
        for (int i = 0; i < targetSlabs.size(); i++) {
1643
            targetSlabs.get(i).setPayoutTarget(newTargets.get(i));
1644
            genericRepository.persist(targetSlabs.get(i));
1645
        }
1646
        LOGGER.info("Updated targets for offer {} to {}", offerId, newTargets);
1647
    }
27877 amit.gupta 1648
}