Subversion Repositories SmartDukaan

Rev

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