Subversion Repositories SmartDukaan

Rev

Rev 32043 | Rev 32070 | 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;
29683 amit.gupta 6
import com.spice.profitmandi.common.model.PartnerTargetModel;
7
import com.spice.profitmandi.common.model.ProfitMandiConstants;
31920 amit.gupta 8
import com.spice.profitmandi.common.util.Utils;
27877 amit.gupta 9
import com.spice.profitmandi.dao.entity.catalog.ItemCriteria;
10
import com.spice.profitmandi.dao.entity.catalog.Offer;
29783 amit.gupta 11
import com.spice.profitmandi.dao.entity.catalog.TagListing;
31903 amit.gupta 12
import com.spice.profitmandi.dao.entity.catalog.TargetSlabEntity;
31920 amit.gupta 13
import com.spice.profitmandi.dao.entity.fofo.FofoLineItem;
14
import com.spice.profitmandi.dao.entity.fofo.FofoOrderItem;
31205 amit.gupta 15
import com.spice.profitmandi.dao.entity.fofo.InventoryItem;
16
import com.spice.profitmandi.dao.entity.fofo.OfferPayout;
31920 amit.gupta 17
import com.spice.profitmandi.dao.entity.transaction.LineItem;
18
import com.spice.profitmandi.dao.entity.transaction.Order;
31747 amit.gupta 19
import com.spice.profitmandi.dao.entity.transaction.UserWalletHistory;
31920 amit.gupta 20
import com.spice.profitmandi.dao.entity.warehouse.WarehouseInventoryItem;
21
import com.spice.profitmandi.dao.entity.warehouse.WarehouseScan;
22
import com.spice.profitmandi.dao.enumuration.catalog.AchievementType;
29783 amit.gupta 23
import com.spice.profitmandi.dao.enumuration.catalog.AmountType;
29499 amit.gupta 24
import com.spice.profitmandi.dao.enumuration.catalog.OfferSchemeType;
31205 amit.gupta 25
import com.spice.profitmandi.dao.enumuration.transaction.SchemePayoutStatus;
31903 amit.gupta 26
import com.spice.profitmandi.dao.model.AmountModel;
27877 amit.gupta 27
import com.spice.profitmandi.dao.model.CreateOfferRequest;
28
import com.spice.profitmandi.dao.model.ItemCriteriaPayout;
31920 amit.gupta 29
import com.spice.profitmandi.dao.model.OfferRowModel;
30066 amit.gupta 30
import com.spice.profitmandi.dao.repository.catalog.*;
31920 amit.gupta 31
import com.spice.profitmandi.dao.repository.fofo.ActivatedImeiRepository;
32
import com.spice.profitmandi.dao.repository.fofo.InventoryItemRepository;
31205 amit.gupta 33
import com.spice.profitmandi.dao.repository.fofo.OfferPayoutRepository;
31920 amit.gupta 34
import com.spice.profitmandi.dao.repository.transaction.LineItemImeisRepository;
35
import com.spice.profitmandi.dao.repository.warehouse.WarehouseInventoryItemRepository;
36
import com.spice.profitmandi.dao.repository.warehouse.WarehouseScanRepository;
37
import com.spice.profitmandi.service.pricecircular.PriceCircularService;
38
import com.spice.profitmandi.service.scheme.InventoryPayoutModel;
27877 amit.gupta 39
import com.spice.profitmandi.service.user.RetailerService;
31205 amit.gupta 40
import com.spice.profitmandi.service.wallet.WalletService;
41
import in.shop2020.model.v1.order.WalletReferenceType;
30066 amit.gupta 42
import org.apache.logging.log4j.LogManager;
43
import org.apache.logging.log4j.Logger;
44
import org.apache.poi.ss.usermodel.Cell;
45
import org.apache.poi.ss.usermodel.CellType;
46
import org.apache.poi.ss.usermodel.Row;
47
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
48
import org.apache.poi.xssf.usermodel.XSSFRow;
49
import org.apache.poi.xssf.usermodel.XSSFSheet;
50
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
51
import org.springframework.beans.factory.annotation.Autowired;
52
import org.springframework.cache.CacheManager;
53
import org.springframework.cache.annotation.Cacheable;
54
import org.springframework.stereotype.Component;
27877 amit.gupta 55
 
30066 amit.gupta 56
import java.io.IOException;
57
import java.io.InputStream;
58
import java.time.LocalDate;
31205 amit.gupta 59
import java.time.LocalDateTime;
30066 amit.gupta 60
import java.time.YearMonth;
61
import java.util.*;
62
import java.util.stream.Collectors;
63
 
27877 amit.gupta 64
@Component
65
public class OfferServiceImpl implements OfferService {
66
 
31747 amit.gupta 67
    private static final List<String> targets = Arrays.asList("Target 1", "Target 2", "Target 3", "Target 4",
68
            "Target 5");
29499 amit.gupta 69
 
31747 amit.gupta 70
    @Autowired
71
    private Gson gson;
27877 amit.gupta 72
 
31747 amit.gupta 73
    @Autowired
74
    private OfferRepository offerRepository;
27877 amit.gupta 75
 
31747 amit.gupta 76
    @Autowired
77
    private RetailerService retailerService;
31920 amit.gupta 78
    @Autowired
79
    PriceCircularService priceCircularService;
27877 amit.gupta 80
 
31747 amit.gupta 81
    @Autowired
82
    OfferPayoutRepository offerPayoutRepository;
31205 amit.gupta 83
 
31747 amit.gupta 84
    @Autowired
85
    private ItemCriteriaRepository itemCriteriaRepository;
27877 amit.gupta 86
 
31747 amit.gupta 87
    @Autowired
88
    private ItemRepository itemRepository;
27877 amit.gupta 89
 
31747 amit.gupta 90
    @Autowired
91
    private TagListingRepository tagListingRepository;
29783 amit.gupta 92
 
31747 amit.gupta 93
    @Autowired
94
    private OfferTargetSlabRepository offerTargetSlabRepository;
30684 amit.gupta 95
 
31747 amit.gupta 96
    @Autowired
97
    CacheManager thirtyMinsTimeOutCacheManager;
27877 amit.gupta 98
 
29806 amit.gupta 99
 
31747 amit.gupta 100
    private static final Logger LOGGER = LogManager.getLogger(OfferServiceImpl.class);
27877 amit.gupta 101
 
31920 amit.gupta 102
    @Autowired
103
    private ActivatedImeiRepository activatedImeiRepository;
104
    @Autowired
105
    private WarehouseScanRepository warehouseScanRepository;
106
 
107
    @Autowired
108
    private WarehouseInventoryItemRepository warehouseInventoryItemRepository;
109
 
110
    @Autowired
111
    private LineItemImeisRepository lineItemImeisRepository;
112
    @Autowired
113
    private InventoryItemRepository inventoryItemRepository;
114
 
31747 amit.gupta 115
    @Override
116
    public void addOfferService(CreateOfferRequest createOfferRequest) throws ProfitMandiBusinessException {
117
        LOGGER.info("createOfferRequest  -- {}", createOfferRequest);
118
        this.createOffer(createOfferRequest);
119
        this.createTargetSlabs(createOfferRequest);
120
    }
27877 amit.gupta 121
 
31747 amit.gupta 122
    private void createOffer(CreateOfferRequest createOfferRequest) {
123
        Offer offer = new Offer();
124
        offer.setName(createOfferRequest.getName());
125
        offer.setTargetType(createOfferRequest.getTargetType());
126
        offer.setBooster(createOfferRequest.isBooster());
127
        offer.setPayoutType(createOfferRequest.getPayoutType());
128
        offer.setSchemeType(createOfferRequest.getSchemeType());
129
        offer.setBaseCriteia(createOfferRequest.isBaseCriteria());
130
        offer.setEndDate(createOfferRequest.getEndDate());
131
        offer.setStartDate(createOfferRequest.getStartDate());
132
        offer.setBrandSharePercentage(createOfferRequest.getBrandShareTerms());
133
        offer.setSellinPercentage(createOfferRequest.getSellinPercentage());
134
        offer.setOfferNotes(createOfferRequest.getOfferNotes());
135
        offer.setActivationBrands(createOfferRequest.getActivationBrands());
136
        offer.setTerms(createOfferRequest.getTerms());
137
        offer.setItemCriteria(gson.toJson(createOfferRequest.getItemCriteria()));
138
        offer.setPartnerCriteria(gson.toJson(createOfferRequest.getPartnerCriteria()));
139
        offerRepository.persist(offer);
140
        createOfferRequest.setId(offer.getId());
141
    }
27877 amit.gupta 142
 
31747 amit.gupta 143
    @Override
144
    public List<CreateOfferRequest> getPublishedOffers(int fofoId, YearMonth yearMonth) {
145
        List<Offer> publishedOffers = offerRepository.selectAllPublishedMapByPartner(yearMonth).get(fofoId);
146
        List<CreateOfferRequest> createOfferRequests = new ArrayList<>();
147
        if (publishedOffers != null) {
148
            for (Offer offer : publishedOffers) {
149
                CreateOfferRequest createOfferRequest = this.getCreateOfferRequest(offer);
150
                createOfferRequests.add(createOfferRequest);
151
                setCriteriaPayoutAchieved(fofoId, createOfferRequest);
27877 amit.gupta 152
 
31747 amit.gupta 153
            }
154
        }
155
        return createOfferRequests;
156
    }
27877 amit.gupta 157
 
31747 amit.gupta 158
    private void setCriteriaPayoutAchieved(int fofoId, CreateOfferRequest createOfferRequest) {
159
        Map<Integer, Long> criteriaTransactionMap = null;
160
        if (createOfferRequest.getSchemeType().equals(OfferSchemeType.SELLIN)) {
161
            criteriaTransactionMap = offerRepository.getPartnerWisePurchaseSum(createOfferRequest).get(fofoId);
162
        } else {
163
            criteriaTransactionMap = offerRepository.getPartnerWiseSalesSum(createOfferRequest).get(fofoId);
164
        }
165
        LOGGER.info("I am here ------- {}", createOfferRequest.getId());
166
        List<com.spice.profitmandi.dao.model.ItemCriteriaPayout> itemCriteriaPayouts = createOfferRequest
167
                .getTargetSlabs().get(0).getItemCriteriaPayouts();
27877 amit.gupta 168
 
31747 amit.gupta 169
        for (com.spice.profitmandi.dao.model.ItemCriteriaPayout itemCriteriaPayout : itemCriteriaPayouts) {
170
            itemCriteriaPayout.setNextSlab(null);
171
            LOGGER.info("I am here --- {}", itemCriteriaPayout.getPayoutSlabs());
172
            long saleAmount = 0;
173
            if (criteriaTransactionMap != null
174
                    && criteriaTransactionMap.containsKey(itemCriteriaPayout.getItemCriteria().getId())) {
31853 amit.gupta 175
                saleAmount = criteriaTransactionMap.containsKey(0) ? criteriaTransactionMap.get(0) : criteriaTransactionMap.get(itemCriteriaPayout.getItemCriteria().getId());
31747 amit.gupta 176
            }
177
            itemCriteriaPayout.setAchievedValue(saleAmount);
178
            List<com.spice.profitmandi.service.offers.PayoutSlab> payoutSlabs = itemCriteriaPayout.getPayoutSlabs();
179
            for (int i = 0; i < payoutSlabs.size(); i++) {
180
                com.spice.profitmandi.service.offers.PayoutSlab beginSlab = payoutSlabs.get(i);
181
                com.spice.profitmandi.service.offers.PayoutSlab endSlab = null;
182
                if (payoutSlabs.size() - 1 > i) {
183
                    endSlab = payoutSlabs.get(i + 1);
184
                }
185
                if (beginSlab.getOnwardsAmount() > saleAmount) {
186
                    itemCriteriaPayout.setShortValue(beginSlab.getOnwardsAmount() - saleAmount);
187
                    itemCriteriaPayout.setNextSlab(beginSlab);
188
                    LOGGER.info("I am here");
189
                    break;
190
                }
191
                if (endSlab != null) {
192
                    if (beginSlab.getOnwardsAmount() <= saleAmount && endSlab.getOnwardsAmount() > saleAmount) {
193
                        itemCriteriaPayout.setCurrentSlab(beginSlab);
194
                        beginSlab.setSelected(true);
195
                        itemCriteriaPayout.setNextSlab(endSlab);
196
                        itemCriteriaPayout.setShortValue(endSlab.getOnwardsAmount() - saleAmount);
197
                        LOGGER.info("I am here");
198
                        break;
199
                    }
200
                    // Last loop
201
                } else {
202
                    beginSlab.setSelected(true);
203
                    itemCriteriaPayout.setCurrentSlab(beginSlab);
204
                    LOGGER.info("I am here");
205
                }
206
            }
207
            LOGGER.info("I am here --- {}", itemCriteriaPayout);
208
        }
29783 amit.gupta 209
 
31747 amit.gupta 210
    }
27877 amit.gupta 211
 
31747 amit.gupta 212
    @Override
213
    @Cacheable(value = "allOffers", cacheManager = "thirtyMinsTimeOutCacheManager")
214
    public Map<Integer, CreateOfferRequest> getAllOffers(YearMonth yearMonth) {
215
        List<Offer> allOffers = offerRepository.selectAll(yearMonth, false);
216
        List<CreateOfferRequest> createOfferRequests = new ArrayList<>();
217
        for (Offer offer : allOffers) {
218
            CreateOfferRequest createOfferRequest = this.getCreateOfferRequest(offer);
219
            createOfferRequests.add(createOfferRequest);
220
        }
221
        return createOfferRequests.stream().collect(Collectors.toMap(CreateOfferRequest::getId, x -> x));
222
    }
27877 amit.gupta 223
 
31747 amit.gupta 224
    @Override
225
    @Cacheable(value = "partnerOffers", cacheManager = "thirtyMinsTimeOutCacheManager")
226
    public CreateOfferRequest getOffer(int fofoId, int offerId) {
227
        Offer offer = offerRepository.selectById(offerId);
228
        CreateOfferRequest createOfferRequest = this.getCreateOfferRequest(offer);
229
        if (fofoId > 0) {
230
            this.setCriteriaPayoutAchieved(fofoId, createOfferRequest);
231
        }
29783 amit.gupta 232
 
31747 amit.gupta 233
        return createOfferRequest;
234
    }
27877 amit.gupta 235
 
31747 amit.gupta 236
    @Override
237
    public CreateOfferRequest getCreateOfferRequest(Offer fromOffer) {
238
        CreateOfferRequest createOfferRequest = new CreateOfferRequest();
239
        createOfferRequest.setName(fromOffer.getName());
32023 amit.gupta 240
        createOfferRequest.setDiscount(fromOffer.isDiscount());
31747 amit.gupta 241
        createOfferRequest.setTargetType(fromOffer.getTargetType());
242
        createOfferRequest.setPayoutType(fromOffer.getPayoutType());
243
        createOfferRequest.setSchemeType(fromOffer.getSchemeType());
244
        createOfferRequest.setActivationBrands(fromOffer.getActivationBrands());
245
        createOfferRequest.setEndDate(fromOffer.getEndDate());
246
        createOfferRequest.setProcessTimestamp(fromOffer.getProcessedTimestamp());
247
        createOfferRequest.setStartDate(fromOffer.getStartDate());
248
        createOfferRequest.setBooster(fromOffer.isBooster());
249
        createOfferRequest.setActive(fromOffer.isActive());
250
        createOfferRequest.setSellinPercentage(fromOffer.getSellinPercentage());
251
        createOfferRequest.setBrandShareTerms(fromOffer.getBrandSharePercentage());
252
        createOfferRequest.setOfferNotes(fromOffer.getOfferNotes());
253
        createOfferRequest.setTerms(fromOffer.getTerms());
254
        createOfferRequest.setBaseCriteria(fromOffer.isBaseCriteia());
255
        createOfferRequest.setItemCriteria(
256
                gson.fromJson(fromOffer.getItemCriteria(), com.spice.profitmandi.service.offers.ItemCriteria.class));
257
        createOfferRequest.setPartnerCriteria(gson.fromJson(fromOffer.getPartnerCriteria(), PartnerCriteria.class));
258
        createOfferRequest.setId(fromOffer.getId());
259
        createOfferRequest.setCreatedOn(fromOffer.getCreatedTimestamp());
260
        createOfferRequest.setItemCriteriaString(
261
                itemCriteriaRepository.getItemCriteriaDescription(createOfferRequest.getItemCriteria()));
262
        List<com.spice.profitmandi.dao.model.TargetSlab> targetSlabs = offerTargetSlabRepository
263
                .getByOfferId(fromOffer.getId());
264
        createOfferRequest.setPartnerCriteriaString(
265
                retailerService.getPartnerCriteriaString(createOfferRequest.getPartnerCriteria()));
266
        createOfferRequest.setTargetSlabs(targetSlabs);
267
        for (com.spice.profitmandi.dao.model.ItemCriteriaPayout itemCriteriaPayout : createOfferRequest.getTargetSlabs()
268
                .get(0).getItemCriteriaPayouts()) {
269
            itemCriteriaPayout.setNextSlab(itemCriteriaPayout.getPayoutSlabs().get(0));
270
        }
271
        return createOfferRequest;
27877 amit.gupta 272
 
31747 amit.gupta 273
    }
27877 amit.gupta 274
 
31747 amit.gupta 275
    @Autowired
276
    private WalletService walletService;
31205 amit.gupta 277
 
31747 amit.gupta 278
    @Override
279
    public void reverseAdditionalSelloutSchemes(int fofoId, List<InventoryItem> inventoryItems) throws ProfitMandiBusinessException {
280
        List<OfferPayout> offerPayouts = new ArrayList<>();
31748 amit.gupta 281
        LOGGER.info("Reversing schemes for fofoId {}, InventoryItems {}", fofoId, inventoryItems);
31747 amit.gupta 282
        //As of now we are not handling non-serialised items
283
        inventoryItems = inventoryItems.stream().filter(x -> x.getSerialNumber() != null).collect(Collectors.toList());
31750 amit.gupta 284
        if (inventoryItems.size() > 0) {
31205 amit.gupta 285
 
31750 amit.gupta 286
            for (InventoryItem inventoryItem : inventoryItems) {
287
                offerPayouts.addAll(offerPayoutRepository.selectAllBySerialNumber(inventoryItem.getFofoId(), inventoryItem.getSerialNumber())
288
                        .stream()
289
                        .filter(x -> x.getRejectTimestamp() == null)
290
                        .collect(Collectors.toList()));
31747 amit.gupta 291
            }
31750 amit.gupta 292
            for (OfferPayout offerPayout : offerPayouts) {
293
                offerPayout.setStatus(SchemePayoutStatus.REJECTED);
294
                offerPayout.setRejectTimestamp(LocalDateTime.now());
295
            }
296
            Map<Long, Double> offerPayoutAmountMap = offerPayouts.stream().collect(Collectors.groupingBy(x -> x.getOfferId(), Collectors.summingDouble(x -> x.getAmount())));
297
            for (Map.Entry<Long, Double> offerPayoutEntry : offerPayoutAmountMap.entrySet()) {
298
                List<UserWalletHistory> histories = walletService.getAllByReference(fofoId, offerPayoutEntry.getKey().intValue(), WalletReferenceType.ADDITIONAL_SCHEME);
299
                if (histories.size() > 0) {
300
 
301
                    walletService.rollbackAmountFromWallet(fofoId, offerPayoutEntry.getValue().floatValue(), offerPayoutEntry.getKey().intValue(),
302
                            WalletReferenceType.ADDITIONAL_SCHEME, "Models/Imeis for corresponding schemes were returned", LocalDateTime.now());
303
                }
304
            }
31747 amit.gupta 305
        }
306
    }
30684 amit.gupta 307
 
31747 amit.gupta 308
    private void createTargetSlabs(CreateOfferRequest createOfferRequest) throws ProfitMandiBusinessException {
309
        List<com.spice.profitmandi.dao.model.TargetSlab> targetSlabs = createOfferRequest.getTargetSlabs().stream()
310
                .filter(x -> x.validate()).collect(Collectors.toList());
311
        if (targetSlabs.size() >= 0) {
312
            Collections.sort(targetSlabs);
313
            for (com.spice.profitmandi.dao.model.TargetSlab targetSlab : targetSlabs) {
314
                if (targetSlab.validate()) {
315
                    List<ItemCriteriaPayout> itemCriteriaPayouts = targetSlab.getItemCriteriaPayouts();
316
                    for (ItemCriteriaPayout itemCriteriaPayout : itemCriteriaPayouts) {
317
                        ItemCriteria itemCriteria = itemCriteriaRepository.selectById(itemCriteriaPayout.getItemCriteria().getId());
318
                        if (itemCriteriaPayout.getItemCriteria().getId() > 0) {
319
                            itemCriteriaPayout.getItemCriteria().setId(0);
320
                        } else {
27877 amit.gupta 321
 
31747 amit.gupta 322
                            String itemCriteriaJson = gson.toJson(itemCriteriaPayout.getItemCriteria());
323
                            itemCriteria = itemCriteriaRepository.selectByCriteria(itemCriteriaJson);
324
                            // ItemCriteria Only once
325
                            if (itemCriteria == null) {
326
                                itemCriteria = new ItemCriteria();
327
                                itemCriteria.setCriteria(gson.toJson(itemCriteriaPayout.getItemCriteria()));
328
                                itemCriteriaRepository.persist(itemCriteria);
329
                            }
330
                        }
331
                        for (PayoutSlab payoutSlab : itemCriteriaPayout.getPayoutSlabs()) {
31903 amit.gupta 332
                            TargetSlabEntity targetSlabEntity = new TargetSlabEntity();
333
                            targetSlabEntity.setOfferId(createOfferRequest.getId());
334
                            targetSlabEntity.setOnwardsTarget(targetSlab.getOnwardsAmount());
335
                            targetSlabEntity.setTargetDescription(targetSlab.getTargetDescription());
336
                            targetSlabEntity.setPayoutTarget(payoutSlab.getOnwardsAmount());
337
                            targetSlabEntity.setPayoutValue(payoutSlab.getPayoutAmount());
338
                            targetSlabEntity.setItemCriteriaId(itemCriteria.getId());
339
                            targetSlabEntity.setAmountType(itemCriteriaPayout.getAmountType());
340
                            offerTargetSlabRepository.persist(targetSlabEntity);
31747 amit.gupta 341
                        }
342
                    }
343
                }
344
            }
27877 amit.gupta 345
 
31747 amit.gupta 346
        } else {
347
            throw new ProfitMandiBusinessException("Invalid Target Slabs", "Invalid Target", "");
348
        }
27877 amit.gupta 349
 
31747 amit.gupta 350
    }
27877 amit.gupta 351
 
31747 amit.gupta 352
    @Override
353
    public List<CreateOfferRequest> getPublishedOffers(LocalDate date, int fofoId, int catalogId) {
354
        List<Offer> publishedOffers = offerRepository.selectAllPublishedMapByPartner(YearMonth.from(date)).get(fofoId);
355
        List<CreateOfferRequest> createOfferRequests = new ArrayList<>();
356
        if (publishedOffers != null) {
357
            for (Offer offer : publishedOffers) {
358
                boolean found = false;
359
                List<com.spice.profitmandi.dao.model.TargetSlab> targetSlabs = offerTargetSlabRepository
360
                        .getByOfferId(offer.getId());
361
                CreateOfferRequest createOfferRequest = this.getCreateOfferRequest(offer);
362
                createOfferRequest.setTargetSlabs(targetSlabs);
363
                this.setCriteriaPayoutAchieved(fofoId, createOfferRequest);
364
                Set<com.spice.profitmandi.service.offers.ItemCriteria> itemCriteriaSet = targetSlabs.stream()
365
                        .flatMap(x -> x.getItemCriteriaPayouts().stream()).map(x -> x.getItemCriteria()).distinct()
366
                        .filter(x -> itemRepository.containsModel(x, catalogId)).collect(Collectors.toSet());
29499 amit.gupta 367
 
31747 amit.gupta 368
                for (com.spice.profitmandi.dao.model.TargetSlab targetSlab : targetSlabs) {
369
                    targetSlab.setItemCriteriaPayouts(targetSlab.getItemCriteriaPayouts().stream()
370
                            .filter(x -> itemCriteriaSet.contains(x.getItemCriteria())).collect(Collectors.toList()));
371
                    if (targetSlab.getItemCriteriaPayouts().size() > 0) {
372
                        found = true;
373
                    }
374
                }
375
                if (found) {
376
                    createOfferRequests.add(createOfferRequest);
377
                }
378
            }
379
        }
29783 amit.gupta 380
 
31747 amit.gupta 381
        return createOfferRequests;
382
    }
29783 amit.gupta 383
 
31747 amit.gupta 384
    @Override
385
    public void createOffers(InputStream fileInputStream) throws Exception {
386
        Map<CreateOfferRequest, List<PartnerTargetModel>> offerPartnerTargetMap = this.parseFromExcel(fileInputStream);
387
        for (Map.Entry<CreateOfferRequest, List<PartnerTargetModel>> partnerTargetEntry : offerPartnerTargetMap
388
                .entrySet()) {
389
            CreateOfferRequest createOfferRequest = partnerTargetEntry.getKey();
390
            Map<List<Integer>, List<Integer>> targetPartnerMap = partnerTargetEntry.getValue().stream()
391
                    .collect(Collectors.groupingBy(PartnerTargetModel::getTargets,
392
                            Collectors.mapping(PartnerTargetModel::getFofoId, Collectors.toList())));
393
            for (Map.Entry<List<Integer>, List<Integer>> targetPartnersEntry : targetPartnerMap.entrySet()) {
394
                List<Integer> fofoIds = createOfferRequest.getPartnerCriteria().getFofoIds();
395
                List<Integer> filterFofoIds = targetPartnersEntry.getValue().stream().filter(x -> !fofoIds.contains(x))
396
                        .collect(Collectors.toList());
397
                LOGGER.info("FofoIds {}", filterFofoIds);
398
                List<Integer> targets = targetPartnersEntry.getKey();
399
                LOGGER.info("Targets  {}", targets);
29806 amit.gupta 400
 
31747 amit.gupta 401
                createOfferRequest.getPartnerCriteria().setFofoIds(filterFofoIds);
402
                int counter = 0;
403
                List<ItemCriteriaPayout> itemCriteriaPayouts = createOfferRequest.getTargetSlabs().get(0)
404
                        .getItemCriteriaPayouts();
405
                List<PayoutSlab> payoutSlabs = itemCriteriaPayouts.stream().flatMap(x -> x.getPayoutSlabs().stream()).collect(Collectors.toList());
406
                for (PayoutSlab payoutSlab : payoutSlabs) {
407
                    payoutSlab.setOnwardsAmount(targets.get(counter));
408
                    counter++;
409
                }
410
                this.addOfferService(createOfferRequest);
411
            }
412
        }
413
        thirtyMinsTimeOutCacheManager.getCache("allOffers").evict(YearMonth.now());
27877 amit.gupta 414
 
31747 amit.gupta 415
    }
29783 amit.gupta 416
 
31747 amit.gupta 417
    private Map<CreateOfferRequest, List<PartnerTargetModel>> parseFromExcel(InputStream inputStream)
418
            throws ProfitMandiBusinessException {
29783 amit.gupta 419
 
31747 amit.gupta 420
        Map<CreateOfferRequest, List<PartnerTargetModel>> offerPartnerTargetMap = new HashMap<>();
421
        XSSFWorkbook myWorkBook = null;
422
        try {
423
            myWorkBook = new XSSFWorkbook(inputStream);
424
            myWorkBook.setMissingCellPolicy(MissingCellPolicy.RETURN_BLANK_AS_NULL);
425
            for (int i = 0; i < myWorkBook.getNumberOfSheets(); i++) {
29683 amit.gupta 426
 
31747 amit.gupta 427
                XSSFSheet mySheet = myWorkBook.getSheetAt(i);
428
                int offerId = Integer.parseInt(mySheet.getSheetName());
429
                CreateOfferRequest existingOffer = this.getOffer(0, offerId);
430
                List<PartnerTargetModel> partnerTargetModels = new ArrayList<>();
431
                offerPartnerTargetMap.put(existingOffer, partnerTargetModels);
432
                this.printIterator(mySheet);
433
                LOGGER.info("rowCellNum {}", mySheet.getLastRowNum());
434
                for (int rowNumber = 1; rowNumber <= mySheet.getLastRowNum(); rowNumber++) {
435
                    XSSFRow row = mySheet.getRow(rowNumber);
436
                    LOGGER.info("row {}", row);
437
                    PartnerTargetModel partnerTargetModel = new PartnerTargetModel();
29783 amit.gupta 438
 
31747 amit.gupta 439
                    if (row.getCell(0) != null && row.getCell(0).getCellTypeEnum() == CellType.NUMERIC) {
440
                        partnerTargetModel.setFofoId((int) row.getCell(0).getNumericCellValue());
441
                    } else {
442
                        ProfitMandiBusinessException profitMandiBusinessException = new ProfitMandiBusinessException(
443
                                "FOFO ID", row.getCell(0).toString(), "TGLSTNG_VE_1010");
444
                        LOGGER.error("Excel file parse error : ", profitMandiBusinessException);
445
                        throw profitMandiBusinessException;
446
                    }
447
                    List<Integer> targets = new ArrayList<>();
448
                    long targetsSize = existingOffer.getTargetSlabs().get(0).getItemCriteriaPayouts().stream().flatMap(x -> x.getPayoutSlabs().stream()).collect(Collectors.counting());
449
                    for (int cellNumber = 1; cellNumber <= targetsSize; cellNumber++) {
450
                        if (row.getCell(cellNumber) != null
451
                                && row.getCell(cellNumber).getCellTypeEnum() == CellType.NUMERIC) {
452
                            targets.add((int) row.getCell(cellNumber).getNumericCellValue());
453
                        } else {
454
                            ProfitMandiBusinessException profitMandiBusinessException = new ProfitMandiBusinessException(
455
                                    "Target Column issue at " + rowNumber + ", " + cellNumber, row.getCell(cellNumber),
456
                                    "Invalid target");
457
                            LOGGER.error("Excel file parse error : ", profitMandiBusinessException);
458
                            throw profitMandiBusinessException;
459
                        }
460
                    }
461
                    partnerTargetModel.setTargets(targets);
462
                    partnerTargetModels.add(partnerTargetModel);
463
                }
464
            }
465
            myWorkBook.close();
466
        } catch (ProfitMandiBusinessException pbse) {
467
            throw pbse;
468
        } catch (IOException ioException) {
469
            ioException.printStackTrace();
470
            throw new ProfitMandiBusinessException(ProfitMandiConstants.EXCEL_FILE, ioException.getMessage(),
471
                    "EXL_VE_1000");
472
        } finally {
473
            if (myWorkBook != null) {
474
                try {
475
                    myWorkBook.close();
476
                } catch (IOException e) {
477
                    // TODO Auto-generated catch block
478
                    e.printStackTrace();
479
                }
480
            }
481
        }
482
        LOGGER.info("offerPartnerTargetMap {}", offerPartnerTargetMap);
483
        return offerPartnerTargetMap;
484
    }
29783 amit.gupta 485
 
31747 amit.gupta 486
    private void printIterator(XSSFSheet sheet) {
487
        Iterator<Row> rowIterator = sheet.iterator();
488
        while (rowIterator.hasNext()) {
489
            Row row = rowIterator.next();
490
            // For each row, iterate through all the columns
491
            Iterator<Cell> cellIterator = row.cellIterator();
29683 amit.gupta 492
 
31747 amit.gupta 493
            while (cellIterator.hasNext()) {
494
                Cell cell = cellIterator.next();
495
                // Check the cell type and format accordingly
496
                switch (cell.getCellType()) {
497
                    case Cell.CELL_TYPE_NUMERIC:
498
                        System.out.print(cell.getNumericCellValue() + "t");
499
                        break;
500
                    case Cell.CELL_TYPE_STRING:
501
                        System.out.print(cell.getStringCellValue() + "t");
502
                        break;
503
                }
504
            }
505
            System.out.println("");
506
        }
507
    }
29683 amit.gupta 508
 
31747 amit.gupta 509
    @Override
510
    public Map<Integer, CreateOfferRequest> getPublishedOffers(LocalDate date, int fofoId, String brand) {
511
        // TODO Auto-generated method stub
512
        return null;
513
    }
30684 amit.gupta 514
 
31747 amit.gupta 515
    @Override
32043 amit.gupta 516
    @Cacheable(value = "slabPayoutMap1", cacheManager = "oneDayCacheManager")
31747 amit.gupta 517
    public Map<Integer, Map<Integer, Long>> getSlabPayoutMap(CreateOfferRequest createOfferRequest) {
518
        Map<Integer, Map<Integer, Long>> catalogSlabPayoutMap = new HashMap<>();
519
        com.spice.profitmandi.dao.model.TargetSlab targetSlab = createOfferRequest.getTargetSlabs().get(0);
520
        List<ItemCriteriaPayout> payouts = targetSlab.getItemCriteriaPayouts();
29783 amit.gupta 521
 
31747 amit.gupta 522
        for (ItemCriteriaPayout itemCriteriaPayout : payouts) {
523
            com.spice.profitmandi.service.offers.ItemCriteria itemCriteria = itemCriteriaPayout.getItemCriteria();
524
            List<Integer> catalogIds = itemRepository.getCatalogIds(itemCriteria);
525
            for (PayoutSlab payoutSlab : Lists.reverse(itemCriteriaPayout.getPayoutSlabs())) {
526
                if (itemCriteriaPayout.getAmountType().equals(AmountType.FIXED)) {
527
                    for (Integer catalogId : catalogIds) {
528
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
529
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
530
                        }
531
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
532
                                (long) payoutSlab.getPayoutAmount());
533
                    }
534
                } else if (itemCriteriaPayout.getAmountType().equals(AmountType.SLAB_FIXED)) {
535
                    for (Integer catalogId : catalogIds) {
536
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
537
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
538
                        }
539
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
540
                                (long) (payoutSlab.getPayoutAmount() / payoutSlab.getOnwardsAmount()));
541
                    }
542
                } else if (itemCriteriaPayout.getAmountType().equals(AmountType.PERCENTAGE)) {
543
                    Map<Integer, TagListing> tagListingsMap = tagListingRepository.selectAllByCatalogIds(catalogIds);
544
                    for (Map.Entry<Integer, TagListing> tagListingEntry : tagListingsMap.entrySet()) {
545
                        TagListing tagListing = tagListingEntry.getValue();
546
                        if (!catalogSlabPayoutMap.containsKey(tagListingEntry.getKey())) {
547
                            catalogSlabPayoutMap.put(tagListingEntry.getKey(), new LinkedHashMap<>());
548
                        }
549
                        catalogSlabPayoutMap.get(tagListingEntry.getKey()).put(payoutSlab.getOnwardsAmount(),
550
                                (long) (tagListing.getSellingPrice() * payoutSlab.getPayoutAmount() / 100));
551
                    }
552
                }
553
            }
554
        }
555
        return catalogSlabPayoutMap;
556
    }
557
 
31903 amit.gupta 558
    @Override
559
    @Cacheable(value = "slabPayoutMap", cacheManager = "oneDayCacheManager")
560
    public Map<Integer, Map<Integer, AmountModel>> getSlabPayoutMapNew(CreateOfferRequest createOfferRequest) {
561
        Map<Integer, Map<Integer, AmountModel>> catalogSlabPayoutMap = new HashMap<>();
562
        com.spice.profitmandi.dao.model.TargetSlab targetSlab = createOfferRequest.getTargetSlabs().get(0);
563
        List<ItemCriteriaPayout> payouts = targetSlab.getItemCriteriaPayouts();
564
 
565
        for (ItemCriteriaPayout itemCriteriaPayout : payouts) {
566
            com.spice.profitmandi.service.offers.ItemCriteria itemCriteria = itemCriteriaPayout.getItemCriteria();
567
            List<Integer> catalogIds = itemRepository.getCatalogIds(itemCriteria);
568
            for (PayoutSlab payoutSlab : Lists.reverse(itemCriteriaPayout.getPayoutSlabs())) {
569
                if (itemCriteriaPayout.getAmountType().equals(AmountType.FIXED)) {
570
                    for (Integer catalogId : catalogIds) {
571
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
572
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
573
                        }
574
                        AmountModel amountModel = new AmountModel();
575
                        amountModel.setAmountType(AmountType.FIXED);
576
                        amountModel.setAmount(payoutSlab.getPayoutAmount());
32021 amit.gupta 577
                        amountModel.setDiscount(createOfferRequest.isDiscount());
31903 amit.gupta 578
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
579
                                amountModel);
580
                    }
581
                } else if (itemCriteriaPayout.getAmountType().equals(AmountType.SLAB_FIXED)) {
582
                    for (Integer catalogId : catalogIds) {
583
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
584
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
585
                        }
586
 
587
                        AmountModel amountModel = new AmountModel();
588
                        amountModel.setAmountType(AmountType.FIXED);
32021 amit.gupta 589
                        amountModel.setDiscount(createOfferRequest.isDiscount());
31903 amit.gupta 590
                        amountModel.setAmount(payoutSlab.getPayoutAmount() / payoutSlab.getOnwardsAmount());
591
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
592
                                amountModel);
593
                    }
594
                } else if (itemCriteriaPayout.getAmountType().equals(AmountType.PERCENTAGE)) {
595
                    for (Integer catalogId : catalogIds) {
596
                        if (!catalogSlabPayoutMap.containsKey(catalogId)) {
597
                            catalogSlabPayoutMap.put(catalogId, new LinkedHashMap<>());
598
                        }
599
                        AmountModel amountModel = new AmountModel();
600
                        amountModel.setAmountType(AmountType.PERCENTAGE);
601
                        amountModel.setAmount(payoutSlab.getPayoutAmount());
32021 amit.gupta 602
                        amountModel.setDiscount(createOfferRequest.isDiscount());
31903 amit.gupta 603
                        catalogSlabPayoutMap.get(catalogId).put(payoutSlab.getOnwardsAmount(),
604
                                amountModel);
605
                    }
606
                }
607
            }
608
        }
609
        return catalogSlabPayoutMap;
610
    }
611
 
31920 amit.gupta 612
 
613
    private double getAmount(InventoryPayoutModel inventoryPayoutModel, AmountModel amountModel) {
614
        double rollout = 0;
615
        if (amountModel.getAmountType().equals(AmountType.PERCENTAGE)) {
616
            double effectiveDp = inventoryPayoutModel.getDp() - inventoryPayoutModel.getFixedAmount();
617
            double totalPercentage = inventoryPayoutModel.getPercentageAmount() + amountModel.getAmount();
618
            rollout = effectiveDp * (totalPercentage / (100 + totalPercentage) - (inventoryPayoutModel.getPercentageAmount() / (100 + inventoryPayoutModel.getPercentageAmount())));
619
        } else {
620
            rollout = amountModel.getAmount() * (100 / (100 + inventoryPayoutModel.getPercentageAmount()));
621
        }
622
        return rollout;
623
    }
624
 
625
    @Override
626
    public void processActivationtOffer(CreateOfferRequest createOfferRequest) throws ProfitMandiBusinessException {
627
        List<OfferPayout> offerPayouts = offerPayoutRepository.selectAllByOfferId(createOfferRequest.getId());
628
        List<ItemCriteriaPayout> itemCriteriaPayouts = createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts();
629
        Map<Integer, ItemCriteriaPayout> itemCriteriaPayoutMap = itemCriteriaPayouts.stream().collect(Collectors.toMap(x -> x.getItemCriteria().getId(), x -> x));
31923 amit.gupta 630
        LOGGER.info("itemCriteriaPayoutMap {}", itemCriteriaPayoutMap);
631
        LOGGER.info("offerPayouts {}", offerPayouts);
31924 amit.gupta 632
        Map<Integer, Map<Integer, Double>> fixedSlabCriteriaPartnerMap = offerPayouts.stream().filter(x -> itemCriteriaPayoutMap.get((int) x.getCriteriaId()).getAmountType().equals(AmountType.SLAB_FIXED))
31920 amit.gupta 633
                .collect(Collectors.groupingBy(x -> (int) x.getCriteriaId(), Collectors.groupingBy(x -> (int) x.getFofoId(), Collectors.summingDouble(x -> x.getSlabAmount()))));
634
 
635
 
636
        Map<String, Double> serialNumberPaid = offerPayouts.stream().filter(x -> x.getRejectTimestamp() == null).collect(Collectors.groupingBy(x -> x.getSerialNumber(), Collectors.summingDouble(x -> x.getSlabAmount())));
637
        Map<Integer, Map<Integer, List<FofoOrderItem>>> criteriaPartnerwiseTertiary = offerRepository.getCriteriaWisePartnerTertiary(createOfferRequest);
638
 
639
 
640
        final Set<String> activatedImeis;
641
        if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
642
            //All Serialnumbers for all eligible retailers
643
            List<String> serialNumbers = criteriaPartnerwiseTertiary.entrySet().stream().flatMap(x -> x.getValue().entrySet().stream().flatMap(foiList -> foiList.getValue().stream()))
644
                    .flatMap(y -> y.getFofoLineItems().stream()).filter(fli -> fli.getSerialNumber() != null)
645
                    .map(x -> x.getSerialNumber()).collect(Collectors.toList());
646
            if (serialNumbers.size() > 0) {
647
                activatedImeis = activatedImeiRepository.selectBySerialNumbers(serialNumbers).stream()
648
                        .filter(x -> createOfferRequest.isWithinRange(x.getActivationTimestamp()))
649
                        .map(x -> x.getSerialNumber()).collect(Collectors.toSet());
650
            } else {
651
                activatedImeis = null;
652
            }
653
        } else {
654
            activatedImeis = null;
655
        }
656
 
657
        Map<Integer, Integer> userBaseQtyMap = new HashMap<>();
658
        Map<Integer, Integer> userBaseValueMap = new HashMap<>();
659
        Map<Integer, Integer> eligibleBaseQtyMap = new HashMap<>();
660
        Map<Integer, Integer> eligibleBaseValueMap = new HashMap<>();
661
 
662
        if (createOfferRequest.isBaseCriteria()) {
663
            Map<Integer, List<FofoOrderItem>> foiMap = criteriaPartnerwiseTertiary.get(0);
664
            for (Map.Entry<Integer, List<FofoOrderItem>> orderEntry : foiMap.entrySet()) {
665
                int fofoId = orderEntry.getKey();
666
                List<FofoOrderItem> fofoOrderItems = orderEntry.getValue();
667
                int totalBaseQty = fofoOrderItems.stream().collect(Collectors.summingInt(x -> (x.getQuantity())));
668
                int totalBaseValue = fofoOrderItems.stream().collect(Collectors.summingInt(x -> (Math.round(x.getDp())) * x.getQuantity()));
669
                userBaseQtyMap.put(fofoId, totalBaseQty);
670
                userBaseValueMap.put(fofoId, totalBaseValue);
671
                if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
672
                    Map<Integer, Integer> inventoryItemValueMap = new HashMap<>();
673
                    for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
674
                        fofoOrderItem.getFofoLineItems().stream().filter(x -> x.getSerialNumber() != null).forEach(
675
                                lineItem -> {
676
                                    if (activatedImeis == null || activatedImeis.contains(lineItem.getSerialNumber())) {
677
                                        inventoryItemValueMap.put(lineItem.getInventoryItemId(), (int) fofoOrderItem.getDp());
678
                                    }
679
                                }
680
                        );
681
                    }
682
                    eligibleBaseQtyMap.put(fofoId, inventoryItemValueMap.size());
683
                    eligibleBaseValueMap.put(fofoId, inventoryItemValueMap.entrySet().stream().collect(Collectors.summingInt(x -> x.getValue())));
684
                } else {
685
                    eligibleBaseQtyMap.put(fofoId, totalBaseQty);
686
                    eligibleBaseValueMap.put(fofoId, totalBaseValue);
687
 
688
                }
689
 
690
            }
691
        }
692
 
693
        //As of now eligible sale is considered to be without special criteria like brand/
694
        for (ItemCriteriaPayout itemCriteriaPayout : createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts()) {
695
            int criteriaId = itemCriteriaPayout.getItemCriteria().getId();
696
            Map<Integer, List<FofoOrderItem>> ordersMap = criteriaPartnerwiseTertiary.get(criteriaId);
697
            for (Map.Entry<Integer, List<FofoOrderItem>> orderEntry : ordersMap.entrySet()) {
31992 amit.gupta 698
                double totalRolloutAmount = 0;
31920 amit.gupta 699
                int fofoId = orderEntry.getKey();
700
                List<FofoOrderItem> fofoOrderItems = orderEntry.getValue();
701
                OfferRowModel offerRowModel = new OfferRowModel();
702
                int totalQty = fofoOrderItems.stream().collect(Collectors.summingInt(x -> (x.getQuantity())));
703
                int totalValue = fofoOrderItems.stream().collect(Collectors.summingInt(x -> Math.round(x.getDp()) * (x.getQuantity())));
704
                int eligibleQty = totalQty;
705
                int eligibleValue = totalValue;
706
                Map<FofoLineItem, Integer> lineItemValueMap = new HashMap<>();
707
                if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
708
                    for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
709
                        fofoOrderItem.getFofoLineItems().stream().filter(x -> x.getSerialNumber() != null).forEach(
710
                                lineItem -> {
711
                                    if (activatedImeis == null || activatedImeis.contains(lineItem.getSerialNumber())) {
712
                                        lineItemValueMap.put(lineItem, (int) fofoOrderItem.getDp());
713
                                    }
714
                                }
715
                        );
716
                    }
717
                    eligibleQty = lineItemValueMap.size();
718
                    eligibleValue = lineItemValueMap.entrySet().stream().collect(Collectors.summingInt(x -> x.getValue()));
719
                    offerRowModel.setEligibleImeis(lineItemValueMap.keySet().stream().map(x -> x.getSerialNumber()).collect(Collectors.toList()));
720
                }
721
 
722
                int totalBaseQty = totalQty;
723
                int totalBaseValue = totalValue;
724
                int eligibleBaseQty = eligibleQty;
725
                int eligibleBaseValue = eligibleValue;
726
                if (createOfferRequest.isBaseCriteria()) {
727
                    totalBaseQty = userBaseQtyMap.get(fofoId) == null ? 0 : userBaseQtyMap.get(fofoId);
728
                    totalBaseValue = userBaseValueMap.get(fofoId) == null ? 0 : userBaseValueMap.get(fofoId);
729
                    eligibleBaseQty = eligibleBaseQtyMap.get(fofoId) == null ? 0 : eligibleBaseQtyMap.get(fofoId);
730
                    eligibleBaseValue = eligibleBaseValueMap.get(fofoId) == null ? 0 : eligibleBaseValueMap.get(fofoId);
731
                }
732
 
733
 
734
                int totalSale = totalBaseValue;
735
                int eligibleSale = eligibleBaseValue;
736
                int criteriaSale = totalValue;
737
                int eligibleCriteriaSale = eligibleValue;
738
                int eligibleCriteriaSaleDp = eligibleValue;
739
 
740
                if (createOfferRequest.getTargetType().equals(AchievementType.QUANTITY)) {
741
                    totalSale = totalBaseQty;
742
                    eligibleSale = eligibleBaseQty;
743
                    criteriaSale = totalQty;
744
                    eligibleCriteriaSale = eligibleQty;
745
                }
746
 
747
                offerRowModel.setTotalSale(totalSale);
748
                offerRowModel.setEligibleSale(eligibleSale);
749
                float eligiblePayoutValue = 0;
750
                double finalPayout = 0;
751
                for (PayoutSlab payoutSlab : itemCriteriaPayout.getPayoutSlabs()) {
752
                    if (payoutSlab.getOnwardsAmount() <= eligibleSale) {
32039 amit.gupta 753
                        LOGGER.info("Eligible Sale {}", eligibleSale);
31920 amit.gupta 754
                        offerRowModel.setPayoutTargetAchieved(payoutSlab.getOnwardsAmount());
755
                        eligiblePayoutValue = payoutSlab.getPayoutAmount();
756
                        offerRowModel.setPayoutValue(eligiblePayoutValue);
757
                    }
758
                }
759
                if (AmountType.PERCENTAGE.equals(itemCriteriaPayout.getAmountType())) {
760
                    finalPayout = (eligiblePayoutValue * eligibleCriteriaSaleDp) / 100;
761
                } else if (AmountType.FIXED.equals(itemCriteriaPayout.getAmountType())) {
762
                    finalPayout = eligiblePayoutValue * eligibleCriteriaSale;
763
                } else {
32039 amit.gupta 764
                    Map<Integer, Double> fofoCriteriaMap = fixedSlabCriteriaPartnerMap.get(criteriaId);
765
                    LOGGER.info("fofoCriteriaMap {}", fofoCriteriaMap);
31920 amit.gupta 766
                    finalPayout = eligiblePayoutValue;
767
                    if (fofoCriteriaMap != null) {
768
                        if (fofoCriteriaMap.containsKey(fofoId)) {
769
                            double totalPayout = fofoCriteriaMap.get(fofoId);
32039 amit.gupta 770
                            finalPayout = eligiblePayoutValue - totalPayout;
771
                            if (Math.abs(finalPayout) < Utils.DOUBLE_EPSILON) {
31920 amit.gupta 772
                                finalPayout = 0;
32039 amit.gupta 773
                            }
31920 amit.gupta 774
                        }
775
                    }
776
                }
777
 
32039 amit.gupta 778
                LOGGER.info("Final Payout - {}", finalPayout);
779
 
31920 amit.gupta 780
                if (finalPayout > 0) {
781
                    List<Integer> inventoryItemIds = lineItemValueMap.keySet().stream().map(x -> x.getInventoryItemId()).collect(Collectors.toList());
782
                    Map<Integer, InventoryItem> inventoryItemsMap = inventoryItemRepository.selectAllByIds(inventoryItemIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
783
                    for (Map.Entry<FofoLineItem, Integer> lineItemValueEntry : lineItemValueMap.entrySet()) {
784
                        double amount = 0;
32039 amit.gupta 785
                        int totalDpValue = lineItemValueMap.values().stream().collect(Collectors.summingInt(x -> x));
786
                        LOGGER.info("Total DP Value {}", totalDpValue);
31920 amit.gupta 787
                        if (AmountType.SLAB_FIXED.equals(itemCriteriaPayout.getAmountType())) {
32039 amit.gupta 788
                            amount = (eligiblePayoutValue * lineItemValueEntry.getValue()) / totalDpValue;
789
                            LOGGER.info("Amount - {}", amount);
31920 amit.gupta 790
                            //Fixed slab should be treated as fixed after payout
791
                        } else {
792
                            amount = eligiblePayoutValue;
32039 amit.gupta 793
                            //Fixed slab has already taken care of that amount;
794
                            if (serialNumberPaid.containsKey(lineItemValueEntry.getKey().getSerialNumber())) {
795
                                amount = amount - serialNumberPaid.get(lineItemValueEntry.getKey().getSerialNumber());
796
                            }
31920 amit.gupta 797
                        }
32039 amit.gupta 798
                        LOGGER.info("Amount - {}", amount);
31920 amit.gupta 799
                        //ignore reasonably small
800
                        if (amount < Utils.DOUBLE_EPSILON) continue;
801
                        AmountModel amountModel = new AmountModel();
802
                        amountModel.setAmountType(itemCriteriaPayout.getAmountType());
803
                        amountModel.setAmount(amount);
32021 amit.gupta 804
                        amountModel.setDiscount(createOfferRequest.isDiscount());
31920 amit.gupta 805
                        InventoryPayoutModel inventoryPayoutModel = priceCircularService.getPayouts(inventoryItemsMap.get(lineItemValueEntry.getKey().getInventoryItemId()));
806
                        double rolloutAmount = inventoryPayoutModel.getRolloutAmount(amountModel);
807
                        totalRolloutAmount += rolloutAmount;
808
 
809
                        OfferPayout offerPayout = new OfferPayout(fofoId, createOfferRequest.getId(), criteriaId, amount, lineItemValueEntry.getKey().getSerialNumber(), rolloutAmount, SchemePayoutStatus.CREDITED, createOfferRequest.getDescription(), LocalDateTime.now());
810
                        //offerPayout.setInventoryItemId(inventoryItemSaleModelsMap.get(lineItemValueEntry.getKey().getInventoryItemId()));
811
                        offerPayoutRepository.persist(offerPayout);
812
                    }
32039 amit.gupta 813
                    walletService.addAmountToWallet((int) fofoId, createOfferRequest.getId(), WalletReferenceType.ADDITIONAL_SCHEME, createOfferRequest.getDescription(), (float) totalRolloutAmount, LocalDateTime.now());
31920 amit.gupta 814
                }
815
            }
816
        }
817
        Offer offer = offerRepository.selectById(createOfferRequest.getId());
818
        offer.setProcessedTimestamp(LocalDateTime.now());
819
    }
820
 
32064 amit.gupta 821
    private void extracted(CreateOfferRequest createOfferRequest, Map<String, Double> serialNumberPaid, ItemCriteriaPayout itemCriteriaPayout, int criteriaId, double totalRolloutAmount, int fofoId, Map<FofoLineItem, Integer> lineItemValueMap, float eligiblePayoutValue) throws ProfitMandiBusinessException {
822
        List<Integer> inventoryItemIds = lineItemValueMap.keySet().stream().map(x -> x.getInventoryItemId()).collect(Collectors.toList());
823
        Map<Integer, InventoryItem> inventoryItemsMap = inventoryItemRepository.selectAllByIds(inventoryItemIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
824
        for (Map.Entry<FofoLineItem, Integer> lineItemValueEntry : lineItemValueMap.entrySet()) {
825
            double amount = 0;
826
            int totalDpValue = lineItemValueMap.values().stream().collect(Collectors.summingInt(x -> x));
827
            LOGGER.info("Total DP Value {}", totalDpValue);
828
            if (AmountType.SLAB_FIXED.equals(itemCriteriaPayout.getAmountType())) {
829
                amount = (eligiblePayoutValue * lineItemValueEntry.getValue()) / totalDpValue;
830
                LOGGER.info("Amount - {}", amount);
831
                //Fixed slab should be treated as fixed after payout
832
            } else {
833
                amount = eligiblePayoutValue;
834
                //Fixed slab has already taken care of that amount;
835
                if (serialNumberPaid.containsKey(lineItemValueEntry.getKey().getSerialNumber())) {
836
                    amount = amount - serialNumberPaid.get(lineItemValueEntry.getKey().getSerialNumber());
837
                }
838
            }
839
            LOGGER.info("Amount - {}", amount);
840
            //ignore reasonably small
841
            if (amount < Utils.DOUBLE_EPSILON) continue;
842
            AmountModel amountModel = new AmountModel();
843
            amountModel.setAmountType(itemCriteriaPayout.getAmountType());
844
            amountModel.setAmount(amount);
845
            amountModel.setDiscount(createOfferRequest.isDiscount());
846
            InventoryPayoutModel inventoryPayoutModel = priceCircularService.getPayouts(inventoryItemsMap.get(lineItemValueEntry.getKey().getInventoryItemId()));
847
            double rolloutAmount = inventoryPayoutModel.getRolloutAmount(amountModel);
848
            totalRolloutAmount += rolloutAmount;
849
 
850
            OfferPayout offerPayout = new OfferPayout(fofoId, createOfferRequest.getId(), criteriaId, amount, lineItemValueEntry.getKey().getSerialNumber(), rolloutAmount, SchemePayoutStatus.CREDITED, createOfferRequest.getDescription(), LocalDateTime.now());
851
            //offerPayout.setInventoryItemId(inventoryItemSaleModelsMap.get(lineItemValueEntry.getKey().getInventoryItemId()));
852
            offerPayoutRepository.persist(offerPayout);
853
        }
854
        walletService.addAmountToWallet((int) fofoId, createOfferRequest.getId(), WalletReferenceType.ADDITIONAL_SCHEME, createOfferRequest.getDescription(), (float) totalRolloutAmount, LocalDateTime.now());
855
    }
856
 
31920 amit.gupta 857
    @Override
858
    public void processSellin(CreateOfferRequest createOfferRequest) throws Exception {
859
 
860
        //List<OfferRowModel> offerRowModels = new ArrayList<>();
861
        List<OfferPayout> offerPayouts = offerPayoutRepository.selectAllByOfferId(createOfferRequest.getId());
862
        Set<Long> fofoIds = offerPayouts.stream().map(x -> x.getFofoId()).collect(Collectors.toSet());
863
 
864
        Map<Integer, Map<Integer, List<Order>>> criteriaOrdersMap = offerRepository.getPartnerWiseSellin(createOfferRequest, true);
865
 
866
        Map<Integer, List<Order>> userBaseCriteriaOrdersMap = null;
867
        if (criteriaOrdersMap.get(0) != null && criteriaOrdersMap.get(0).size() > 0) {
868
            userBaseCriteriaOrdersMap = criteriaOrdersMap.get(0).entrySet().stream()
869
                    .filter(x -> !fofoIds.contains(x.getKey())).collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
870
        }
871
 
872
        Map<Integer, Integer> userBaseQtyMap = null;
873
        Map<Integer, Integer> userBaseValueMap = null;
874
        if (userBaseCriteriaOrdersMap != null) {
875
            userBaseQtyMap = new HashMap<>();
876
            userBaseValueMap = new HashMap<>();
877
            for (Map.Entry<Integer, List<Order>> orderEntry : userBaseCriteriaOrdersMap.entrySet()) {
878
                int fofoId = orderEntry.getKey();
879
                List<Order> orders = orderEntry.getValue();
880
                int totalBaseQty = orders.stream().collect(Collectors.summingInt(x -> (x.getLineItem().getQuantity() - x.getLineItem().getReturnQty())));
881
                int totalBaseValue = orders.stream().collect(Collectors.summingInt(x ->
882
                        Math.round(x.getLineItem().getUnitPrice() * (x.getLineItem().getQuantity() - x.getLineItem().getReturnQty()))
883
                ));
884
                userBaseQtyMap.put(fofoId, totalBaseQty);
885
                userBaseValueMap.put(fofoId, totalBaseValue);
886
            }
887
        }
888
        LOGGER.info("Base Qty Map - {}", userBaseQtyMap);
889
        LOGGER.info("Base Value Map - {}", userBaseValueMap);
890
 
891
        LOGGER.info("Processing sellin");
892
        List<OfferPayout> offerPayoutsNew = new ArrayList<>();
893
        for (ItemCriteriaPayout itemCriteriaPayout : createOfferRequest.getTargetSlabs().get(0).getItemCriteriaPayouts()) {
894
            int criteriaId = itemCriteriaPayout.getItemCriteria().getId();
895
            Map<Integer, List<Order>> ordersMap = criteriaOrdersMap.get(criteriaId).entrySet().stream()
896
                    .filter(x -> !fofoIds.contains(x.getKey())).collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
897
            for (Map.Entry<Integer, List<Order>> orderEntry : ordersMap.entrySet()) {
898
                int fofoId = orderEntry.getKey();
899
                //CustomRetailer retailer = retailerService.getAllFofoRetailers().get(fofoId);
900
                List<Order> orders = orderEntry.getValue();
901
                Set<String> returnedSerialNumbers = orders.stream().filter(x -> x.getSerialNumber() != null).flatMap(x -> x.getReturnedImeis().stream()).collect(Collectors.toSet());
902
                int totalQty = orders.stream().collect(Collectors.summingInt(x -> (x.getLineItem().getQuantity() - x.getLineItem().getReturnQty())));
903
                int totalValue = orders.stream().collect(Collectors.summingInt(x -> Math.round(x.getLineItem().
904
                        getUnitPrice() * (x.getLineItem().getQuantity() - x.getLineItem().getReturnQty()))));
905
                int totalBaseQty = totalQty;
906
                int totalBaseValue = totalValue;
907
                if (userBaseCriteriaOrdersMap != null) {
908
                    if (userBaseQtyMap.containsKey(fofoId)) {
909
                        totalBaseQty = userBaseQtyMap.get(fofoId);
910
                        totalBaseValue = userBaseValueMap.get(fofoId);
911
                    } else {
912
                        continue;
913
                    }
914
                }
915
 
916
                int purchasedValue;
917
                if (createOfferRequest.getTargetType().equals(AchievementType.VALUE)) {
918
                    purchasedValue = totalBaseValue;
919
                } else {
920
                    purchasedValue = totalBaseQty;
921
                }
922
                PayoutSlab currentSlab = itemCriteriaPayout.getPayoutSlabs().stream()
923
                        .filter(x -> x.getOnwardsAmount() <= purchasedValue).max(Comparator.comparing(x
924
                                -> x.getOnwardsAmount())).orElse(null);
925
 
926
                //TODO-- payouts handling is here
927
                if (currentSlab == null) continue;
928
                //Need to remove hardcoding on tax
929
                List<Integer> orderIds = orders.stream().map(x -> x.getId()).collect(Collectors.toList());
930
                Map<Integer, LineItem> lineItemMap = orders.stream().collect(Collectors.toMap(x -> x.getLineItem().getId(), x -> x.getLineItem()));
931
                List<WarehouseScan> warehouseScans = warehouseScanRepository.selectAllByOrderIds(orderIds);
932
                List<Integer> inventoryItemIds = warehouseScans.stream().collect(Collectors.groupingBy(x -> x.getInventoryItemId())).entrySet()
933
                        .stream().filter(x -> x.getValue().size() == 1).map(x -> x.getKey()).collect(Collectors.toList());
934
                Set<String> serialNumbers;
935
                LOGGER.info("inventoryItemIds {}", inventoryItemIds);
936
                if (inventoryItemIds.size() > 0) {
937
                    List<WarehouseInventoryItem> warehouseInventoryItems = warehouseInventoryItemRepository.selectAllByIds(inventoryItemIds);
938
                    serialNumbers = warehouseInventoryItems.stream().map(x -> x.getSerialNumber()).collect(Collectors.toSet());
939
                } else {
940
                    serialNumbers = new HashSet<>();
941
                }
942
                LOGGER.info("SerialNumbers {}", serialNumbers);
943
                Map<String, Long> serialNumberCountMap = lineItemImeisRepository.selectByLineItemIds(new ArrayList<>(lineItemMap.keySet()))
944
                        .stream().collect(Collectors.groupingBy(x -> x.getSerialNumber(), Collectors.counting()));
945
                LOGGER.info("SerialNumbers Count Map {}", serialNumberCountMap);
946
                Map<String, LineItem> serialNumberMap = lineItemImeisRepository.selectByLineItemIds(new ArrayList<>(lineItemMap.keySet()))
947
                        .stream().collect(Collectors.toMap(x -> x.getSerialNumber(), x -> lineItemMap.get(x.getLineItemId()), (x1, x2) -> x1.getId() > x2.getId() ? x1 : x2));
948
 
949
                serialNumberMap = serialNumberMap.entrySet().stream().filter(x -> serialNumbers.contains(x.getKey())).collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
950
 
32064 amit.gupta 951
                Map<String, InventoryItem> serialNumberInventoryItemMap = this.getInventoryItemMap(fofoId, serialNumberMap);
952
                //Continue if all imeis havent been grned
953
                if(serialNumberInventoryItemMap.size() < serialNumberCountMap.size()) continue;
954
 
31920 amit.gupta 955
                LOGGER.info("serialNumberMap {}", serialNumberMap);
956
                double amount = 0;
957
                int lineItemsValue = serialNumberMap.values().stream().collect(Collectors.summingInt(x -> x.getUnitPrice().intValue()));
958
                LOGGER.info("lineItemsValue - {}, totalValue - {}", lineItemsValue, totalValue);
959
                for (Map.Entry<String, LineItem> entry : serialNumberMap.entrySet()) {
960
                    LOGGER.info("Serial no - {}", entry.getKey());
961
                    LineItem lineItem = entry.getValue();
962
                    if (AmountType.PERCENTAGE.equals(itemCriteriaPayout.getAmountType())) {
963
                        float percentageAmount = currentSlab.getPayoutAmount();
964
                        amount = entry.getValue().getUnitPrice() * (percentageAmount / 100);
965
                    } else if (AmountType.SLAB_FIXED.equals(itemCriteriaPayout.getAmountType())) {
966
                        float totalAmount = currentSlab.getPayoutAmount();
967
                        amount = Math.round((totalAmount / totalValue) * lineItem.getUnitPrice());
968
                        LOGGER.info("Serial no - {}, unitPrice - {}, amount - {}", entry.getKey(), lineItem.getUnitPrice(), amount);
969
                    } else {
970
                        //per unit amount
971
                        amount = currentSlab.getPayoutAmount();
972
                    }
32064 amit.gupta 973
                    AmountModel amountModel = new AmountModel();
974
                    amountModel.setAmountType(itemCriteriaPayout.getAmountType());
975
                    amountModel.setAmount(amount);
976
                    amountModel.setDiscount(createOfferRequest.isDiscount());
977
                    InventoryPayoutModel inventoryPayoutModel = priceCircularService.getPayouts(serialNumberInventoryItemMap.get(entry.getKey()));
978
                    double rolloutAmount = inventoryPayoutModel.getRolloutAmount(amountModel);
31920 amit.gupta 979
                    if (fofoIds.contains(Long.valueOf(fofoId))) continue;
32064 amit.gupta 980
                    OfferPayout offerPayout = new OfferPayout(fofoId, createOfferRequest.getId(), criteriaId, currentSlab.getPayoutAmount(), entry.getKey(), rolloutAmount, SchemePayoutStatus.CREDITED, createOfferRequest.getDescription(), LocalDateTime.now());
31920 amit.gupta 981
                    //offerPayout.setLineItemId();
982
                    offerPayoutRepository.persist(offerPayout);
983
                    offerPayoutsNew.add(offerPayout);
984
                }
985
            }
986
        }
987
        Map<Long, Double> offerPayoutMap = offerPayoutsNew.stream().collect(Collectors.groupingBy(x -> x.getFofoId(), Collectors.summingDouble(x -> x.getAmount())));
988
        for (Map.Entry<Long, Double> offerPayoutEntry : offerPayoutMap.entrySet()) {
989
            long fofoId = offerPayoutEntry.getKey();
990
            double amountToCredit = offerPayoutEntry.getValue();
991
            walletService.addAmountToWallet((int) fofoId, createOfferRequest.getId(), WalletReferenceType.ADDITIONAL_SCHEME, createOfferRequest.getDescription(), (float) amountToCredit, LocalDateTime.now());
992
        }
993
        Offer offer = offerRepository.selectById(createOfferRequest.getId());
994
        offer.setProcessedTimestamp(LocalDateTime.now());
995
    }
32064 amit.gupta 996
 
997
    private Map<String, InventoryItem> getInventoryItemMap(int fofoId, Map<String, LineItem> serialNumberMap) {
998
        List<InventoryItem> inventoryItems = inventoryItemRepository.selectBySerialNumbers(serialNumberMap.keySet());
999
        inventoryItems = inventoryItems.stream().filter(x->x.getFofoId()== fofoId).collect(Collectors.toList());
1000
        Map<String,InventoryItem> inventoryItemMap = inventoryItems.stream().collect(Collectors.toMap(x->x.getSerialNumber(), x->x, (u,v)->v.getCreateTimestamp().isAfter(u.getCreateTimestamp()) ? v : u));
1001
        return inventoryItemMap;
1002
    }
27877 amit.gupta 1003
}