Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
22653 ashik.ali 1
package com.spice.profitmandi.service.scheme;
2
 
24307 amit.gupta 3
import com.spice.profitmandi.common.enumuration.ItemType;
29927 amit.gupta 4
import com.spice.profitmandi.common.enumuration.MessageType;
22653 ashik.ali 5
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
6
import com.spice.profitmandi.common.model.ProfitMandiConstants;
23019 ashik.ali 7
import com.spice.profitmandi.common.model.SchemeModel;
29927 amit.gupta 8
import com.spice.profitmandi.common.model.SendNotificationModel;
29584 manish 9
import com.spice.profitmandi.common.services.ReporticoService;
27395 amit.gupta 10
import com.spice.profitmandi.common.util.FormattingUtils;
22859 ashik.ali 11
import com.spice.profitmandi.common.util.StringUtils;
30121 amit.gupta 12
import com.spice.profitmandi.common.util.Utils;
31969 amit.gupta 13
import com.spice.profitmandi.dao.entity.catalog.Item;
14
import com.spice.profitmandi.dao.entity.catalog.Scheme;
15
import com.spice.profitmandi.dao.entity.catalog.SchemeRegion;
16
import com.spice.profitmandi.dao.entity.catalog.SchemesImeisModel;
29927 amit.gupta 17
import com.spice.profitmandi.dao.entity.fofo.*;
31903 amit.gupta 18
import com.spice.profitmandi.dao.entity.inventory.PartnerAgeingModel;
26498 amit.gupta 19
import com.spice.profitmandi.dao.entity.transaction.PriceDrop;
31609 amit.gupta 20
import com.spice.profitmandi.dao.entity.transaction.UserWalletHistory;
23527 ashik.ali 21
import com.spice.profitmandi.dao.enumuration.catalog.AmountType;
22653 ashik.ali 22
import com.spice.profitmandi.dao.enumuration.catalog.SchemeType;
25111 amit.gupta 23
import com.spice.profitmandi.dao.enumuration.fofo.ScanType;
27377 amit.gupta 24
import com.spice.profitmandi.dao.enumuration.transaction.SchemePayoutStatus;
31903 amit.gupta 25
import com.spice.profitmandi.dao.model.AmountModel;
25503 amit.gupta 26
import com.spice.profitmandi.dao.model.CreateSchemeRequest;
31170 amit.gupta 27
import com.spice.profitmandi.dao.repository.catalog.*;
23968 amit.gupta 28
import com.spice.profitmandi.dao.repository.dtr.RetailerRepository;
29927 amit.gupta 29
import com.spice.profitmandi.dao.repository.fofo.*;
26498 amit.gupta 30
import com.spice.profitmandi.dao.repository.transaction.PriceDropRepository;
31609 amit.gupta 31
import com.spice.profitmandi.dao.repository.transaction.UserWalletHistoryRepository;
29927 amit.gupta 32
import com.spice.profitmandi.service.NotificationService;
23798 amit.gupta 33
import com.spice.profitmandi.service.authentication.RoleManager;
31903 amit.gupta 34
import com.spice.profitmandi.service.inventory.AgeingService;
26722 amit.gupta 35
import com.spice.profitmandi.service.inventory.PurchaseService;
31903 amit.gupta 36
import com.spice.profitmandi.service.pricecircular.CatalogSummaryModel;
31921 amit.gupta 37
import com.spice.profitmandi.service.pricecircular.PriceCircularService;
31903 amit.gupta 38
import com.spice.profitmandi.service.pricecircular.SchemeSummaryModel;
22859 ashik.ali 39
import com.spice.profitmandi.service.wallet.WalletService;
40
import in.shop2020.model.v1.order.WalletReferenceType;
29927 amit.gupta 41
import org.apache.logging.log4j.LogManager;
42
import org.apache.logging.log4j.Logger;
43
import org.hibernate.Session;
44
import org.hibernate.SessionFactory;
45
import org.hibernate.query.Query;
46
import org.springframework.beans.factory.annotation.Autowired;
47
import org.springframework.beans.factory.annotation.Qualifier;
48
import org.springframework.cache.annotation.Cacheable;
49
import org.springframework.stereotype.Component;
22859 ashik.ali 50
 
31170 amit.gupta 51
import javax.persistence.TypedQuery;
29927 amit.gupta 52
import javax.persistence.criteria.CriteriaBuilder;
53
import javax.persistence.criteria.CriteriaQuery;
54
import javax.persistence.criteria.Predicate;
55
import javax.persistence.criteria.Root;
56
import java.text.MessageFormat;
57
import java.time.LocalDate;
58
import java.time.LocalDateTime;
59
import java.time.YearMonth;
60
import java.util.*;
61
import java.util.stream.Collectors;
62
 
22653 ashik.ali 63
@Component
64
public class SchemeServiceImpl implements SchemeService {
65
 
31410 amit.gupta 66
    private static final Logger LOGGER = LogManager.getLogger(SchemeServiceImpl.class);
31916 amit.gupta 67
    private static final Set<Integer> tagIds = new HashSet<>(Arrays.asList(4));
31410 amit.gupta 68
    private static final List<String> BLOCKED_IMEIS = Arrays.asList("864883056397593", "864883054606656", "864883056567815", "861950056518271", "869175055649511", "861362058924574", "866009066803036", "866009066816699", "866009066816137", "866009066815873", "866009066805536", "866009066803010", "866009066821939", "866009066802756", "866009066820592", "866009066820311", "866009066816491", "866009066816376", "866009066815899", "866009066815774", "866009066817937", "866009066819859", "866009066817655", "866009066820691", "866009066820832", "866009066803291", "866009066820733", "866009066814496", "866009066820451", "866009066820659", "866009066804976", "866009066820717", "866009066816095", "861362054898434", "869599051117852", "869599056695332", "869599056695894", "864883057389656", "862661052418692", "860118051929254", "862888051664998", "862680054625831", "862888051666316", "860118051738895", "868066050447970", "868066052424399", "865084051552576", "865084050755097", "865084050755295", "865084050754819", "864883057487278", "864883057389599", "864883057437455", "864883057388278", "862680058278058", "869599056810139", "862200053994193", "861932057188916", "861175050581774", "863933065909093", "863933065635391", "861362054889177", "864004062055154", "864004062069239", "862661050221676", "862661052416993", "866812058631475", "869599051118173", "869599051504273", "868066052729250", "864883057701397", "864883054123033", "864883054947316", "864883056235694", "868066052727692", "866030052139896", "866030052140175", "860588051522053", "860588051513193", "861932056969779", "869599056171995", "865594061074932", "863935059410491", "866088059072718", "869599055375894", "869599054306916", "863782054006472", "863782054012371", "860588053486992", "868066052726835", "868066052726694", "860688053876430", "860688053869674", "868494052222110", "868494054682394", "869599053512357");
31450 amit.gupta 69
    private static final List<SchemeType> ACTIVATION_SCHEME_TYPES = Arrays.asList(SchemeType.ACTIVATION, SchemeType.SPECIAL_SUPPORT, SchemeType.SELLOUT);
31410 amit.gupta 70
    @Autowired
71
    StateGstRateRepository stateGstRateRepository;
72
    @Autowired
73
    NotificationService notificationService;
74
    @Autowired
75
    @Qualifier("fofoInventoryItemRepository")
76
    private InventoryItemRepository inventoryItemRepository;
77
    @Autowired
78
    private ActivatedImeiRepository activatedImeiRepository;
79
    @Autowired
80
    private PartnerTypeChangeService partnerTypeChangeService;
81
    @Autowired
82
    private PurchaseService purchaseService;
83
    @Autowired
84
    private ScanRecordRepository scanRecordRepository;
85
    @Autowired
86
    private SessionFactory sessionFactory;
87
    @Autowired
88
    private SchemeRepository schemeRepository;
89
    @Autowired
90
    private PriceDropRepository priceDropRepository;
91
    @Autowired
92
    private RoleManager roleManager;
93
    @Autowired
94
    private RetailerRepository retailerRepository;
95
    @Autowired
96
    private ReporticoService reporticoService;
97
    @Autowired
98
    private TagListingRepository tagListingRepository;
99
    @Autowired
100
    private SchemeInOutRepository schemeInOutRepository;
101
    @Autowired
102
    @Qualifier("catalogItemRepository")
103
    private ItemRepository itemRepository;
104
    @Autowired
105
    private SchemeItemRepository schemeItemRepository;
106
    @Autowired
107
    private SchemeRegionRepository schemeRegionRepository;
108
    @Autowired
109
    private WalletService walletService;
110
    @Autowired
111
    private PurchaseRepository purchaseRepository;
112
    @Autowired
113
    private FofoOrderRepository fofoOrderRepository;
23444 amit.gupta 114
 
31921 amit.gupta 115
    @Autowired
116
    private PriceCircularService priceCircularService;
117
 
31410 amit.gupta 118
    @Override
119
    public void saveScheme(int creatorId, CreateSchemeRequest createSchemeRequest) throws ProfitMandiBusinessException {
23444 amit.gupta 120
 
31410 amit.gupta 121
        this.validateCreateSchemeRequest(createSchemeRequest);
27898 amit.gupta 122
 
31410 amit.gupta 123
        Scheme scheme = this.toScheme(creatorId, createSchemeRequest);
25503 amit.gupta 124
 
31410 amit.gupta 125
        if (scheme.getStartDateTime().isAfter(scheme.getEndDateTime())) {
126
            throw new ProfitMandiBusinessException(
127
                    ProfitMandiConstants.START_DATE + ", " + ProfitMandiConstants.END_DATE,
128
                    scheme.getStartDateTime() + ", " + scheme.getEndDateTime(), "SCHM_VE_1005");
129
        }
26722 amit.gupta 130
 
31410 amit.gupta 131
        // this.validateItemIds(createSchemeRequest);
132
        schemeRepository.persist(scheme);
133
        for (int catalogId : createSchemeRequest.getCatalogIds()) {
134
            SchemeItem schemeItem = new SchemeItem();
135
            schemeItem.setSchemeId(scheme.getId());
136
            schemeItem.setCatalogId(catalogId);
137
            schemeItemRepository.persist(schemeItem);
138
        }
23444 amit.gupta 139
 
31410 amit.gupta 140
        for (int regionId : createSchemeRequest.getRegionIds()) {
141
            SchemeRegion schemeRegion = new SchemeRegion();
142
            schemeRegion.setSchemeId(scheme.getId());
143
            schemeRegion.setRegionId(regionId);
144
            schemeRegionRepository.persist(schemeRegion);
145
        }
26332 amit.gupta 146
 
31410 amit.gupta 147
    }
26722 amit.gupta 148
 
31410 amit.gupta 149
    private void validateCreateSchemeRequest(CreateSchemeRequest createSchemeRequest)
150
            throws ProfitMandiBusinessException {
151
        if (createSchemeRequest.getName() == null || createSchemeRequest.getName().isEmpty()) {
152
            throw new ProfitMandiBusinessException(ProfitMandiConstants.NAME, createSchemeRequest.getName(),
153
                    "SCHM_VE_1000");
154
        }
155
        if (createSchemeRequest.getAmount() <= 0) {
156
            throw new ProfitMandiBusinessException(ProfitMandiConstants.AMOUNT, createSchemeRequest.getAmount(),
157
                    "SCHM_VE_1001");
158
        }
26684 amit.gupta 159
 
31410 amit.gupta 160
        if (createSchemeRequest.getAmountType().equals(AmountType.PERCENTAGE)
161
                && createSchemeRequest.getAmount() > 100) {
162
            throw new ProfitMandiBusinessException(ProfitMandiConstants.AMOUNT, createSchemeRequest.getAmount(),
163
                    "SCHM_VE_1002");
164
        }
23444 amit.gupta 165
 
31410 amit.gupta 166
        if (createSchemeRequest.getStartDate() == null) {
167
            throw new ProfitMandiBusinessException(ProfitMandiConstants.START_DATE, createSchemeRequest.getStartDate(),
168
                    "SCHM_VE_1003");
169
        }
170
        if (createSchemeRequest.getEndDate() == null) {
171
            throw new ProfitMandiBusinessException(ProfitMandiConstants.END_DATE, createSchemeRequest.getEndDate(),
172
                    "SCHM_VE_1004");
173
        }
174
    }
23798 amit.gupta 175
 
31410 amit.gupta 176
    private void validateItemIds(CreateSchemeRequest createSchemeRequest) throws ProfitMandiBusinessException {
177
        if (createSchemeRequest.getCatalogIds() == null || createSchemeRequest.getCatalogIds().isEmpty()) {
178
            throw new ProfitMandiBusinessException(ProfitMandiConstants.ITEM_ID, createSchemeRequest.getCatalogIds(),
179
                    "SCHM_1003");
180
        }
181
        List<Integer> foundItemIds = itemRepository.selectIdsByIdsAndType(createSchemeRequest.getCatalogIds(),
182
                ItemType.SERIALIZED);
183
        if (foundItemIds.size() != createSchemeRequest.getCatalogIds().size()) {
184
            createSchemeRequest.getCatalogIds().removeAll(foundItemIds);
185
            throw new ProfitMandiBusinessException(ProfitMandiConstants.ITEM_ID, createSchemeRequest.getCatalogIds(),
186
                    "SCHM_1004");
187
        }
188
    }
29927 amit.gupta 189
 
31410 amit.gupta 190
    @Override
191
    public Scheme getSchemeById(int schemeId) throws ProfitMandiBusinessException {
192
        Scheme scheme = schemeRepository.selectById(schemeId);
193
        List<Integer> catalogIds = schemeItemRepository.selectCatalogIdsBySchemeId(scheme.getId());
194
        if (catalogIds.size() > 0) {
195
            List<Item> items = itemRepository.selectAllByCatalogIds(new HashSet<>(catalogIds));
196
            scheme.setCatalogStringMap(this.toCatalogStringMap(items));
197
        }
198
        return scheme;
199
    }
24562 amit.gupta 200
 
31410 amit.gupta 201
    public Map<Integer, String> toCatalogStringMap(List<Item> items) {
202
        Map<Integer, String> catalogMap = new HashMap<>();
203
        for (Item item : items) {
204
            if (!catalogMap.containsKey(item.getCatalogItemId())) {
205
                catalogMap.put(item.getCatalogItemId(), item.getItemDescriptionNoColor());
206
            }
207
        }
208
        return catalogMap;
209
    }
29927 amit.gupta 210
 
31410 amit.gupta 211
    private Set<Integer> schemeItemsToCatalogIds(List<SchemeItem> schemeItems) {
212
        Set<Integer> catalogId = new HashSet<>();
213
        for (SchemeItem schemeItem : schemeItems) {
214
            catalogId.add(schemeItem.getCatalogId());
215
        }
216
        return catalogId;
217
    }
23444 amit.gupta 218
 
31410 amit.gupta 219
    @Override
220
    public List<SchemeModel> getAllSchemeModels(LocalDateTime startDateTime, LocalDateTime endDateTime) {
221
        List<Scheme> schemes = schemeRepository.selectAllBetweenCreateTimestamp(startDateTime, endDateTime);
222
        Map<Integer, Scheme> schemeIdSchemeMap = schemes.stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
223
        List<SchemeItem> schemeItems = schemeItemRepository.selectBySchemeIds(schemeIdSchemeMap.keySet());
224
        Set<Integer> catalogIds = schemeItems.stream().map(x -> x.getCatalogId()).collect(Collectors.toSet());
225
        List<Item> items = itemRepository.selectAllByCatalogIds(catalogIds);
226
        Map<Integer, String> catalogStringMap = this.toCatalogStringMap(items);
227
        this.addCatalogIdsToSchemes(schemeItems, schemeIdSchemeMap, catalogStringMap);
228
        return this.toSchemeModels(schemeIdSchemeMap);
229
    }
23444 amit.gupta 230
 
31410 amit.gupta 231
    private List<SchemeModel> toSchemeModels(Map<Integer, Scheme> schemeIdSchemeMap) {
232
        List<SchemeModel> schemeModels = new ArrayList<>();
233
        for (Map.Entry<Integer, Scheme> schemeIdSchemeEntry : schemeIdSchemeMap.entrySet()) {
234
            schemeModels.add(this.toSchemeModel(schemeIdSchemeEntry.getValue()));
235
        }
236
        return schemeModels;
237
    }
23444 amit.gupta 238
 
31410 amit.gupta 239
    private SchemeModel toSchemeModel(Scheme scheme) {
240
        SchemeModel schemeModel = new SchemeModel();
241
        schemeModel.setSchemeId(scheme.getId());
242
        schemeModel.setName(scheme.getName());
243
        schemeModel.setDescription(scheme.getDescription());
244
        schemeModel.setSchemeType(scheme.getType().toString());
245
        schemeModel.setAmountType(scheme.getAmountType().toString());
246
        schemeModel.setAmount(scheme.getAmount());
247
        schemeModel.setStartDateTime(StringUtils.toString(scheme.getStartDateTime()));
248
        schemeModel.setEndDateTime(StringUtils.toString(scheme.getEndDateTime()));
249
        schemeModel.setCreateTimestamp(StringUtils.toString(scheme.getCreateTimestamp()));
250
        schemeModel.setActiveTimestamp(StringUtils.toString(scheme.getActiveTimestamp()));
251
        schemeModel.setExpireTimestamp(StringUtils.toString(scheme.getExpireTimestamp()));
252
        schemeModel.setCreatedBy(scheme.getCreatedBy());
253
        schemeModel.setCatalogStringMap(scheme.getCatalogStringMap());
254
        schemeModel.setRetailerIds(scheme.getRetailerIds());
255
        return schemeModel;
256
    }
23444 amit.gupta 257
 
31410 amit.gupta 258
    private void addCatalogIdsToSchemes(List<SchemeItem> schemeItems, Map<Integer, Scheme> schemeIdSchemeMap,
259
                                        Map<Integer, String> catalogStringMap) {
260
        for (SchemeItem schemeItem : schemeItems) {
261
            Scheme scheme = schemeIdSchemeMap.get(schemeItem.getSchemeId());
262
            scheme.getCatalogStringMap().put(schemeItem.getCatalogId(), catalogStringMap.get(schemeItem.getCatalogId()));
263
        }
264
    }
31170 amit.gupta 265
 
31410 amit.gupta 266
    @Override
267
    public void activeSchemeById(int schemeId) throws ProfitMandiBusinessException {
268
        Scheme scheme = schemeRepository.selectById(schemeId);
269
        if (scheme.getActiveTimestamp() != null) {
270
            throw new ProfitMandiBusinessException(ProfitMandiConstants.ACTIVE_TIMESTAMP, scheme.getActiveTimestamp(),
271
                    "SCHM_1005");
272
        }
273
        if (scheme.getExpireTimestamp() != null) {
274
            throw new ProfitMandiBusinessException(ProfitMandiConstants.EXPIRE_TIMESTAMP, scheme.getExpireTimestamp(),
275
                    "SCHM_1006");
276
        }
277
        scheme.setActiveTimestamp(LocalDateTime.now());
278
        this.sendSchemeNotification(scheme);
23444 amit.gupta 279
 
280
 
31410 amit.gupta 281
        /*
282
         * if (scheme.getType() == SchemeType.IN) {
283
         * this.processPreviousPurchases(scheme); } else if (scheme.getType() ==
284
         * SchemeType.OUT) { this.processPreviousSales(scheme); }
285
         */
286
    }
23796 amit.gupta 287
 
31410 amit.gupta 288
    private void sendSchemeNotification(Scheme scheme) throws ProfitMandiBusinessException {
289
        if (ACTIVATION_SCHEME_TYPES.contains(scheme.getType())) {
31336 amit.gupta 290
 
31410 amit.gupta 291
            SendNotificationModel sendNotificationModel = new SendNotificationModel();
292
            List<SchemeItem> schemeItems = schemeItemRepository.selectBySchemeIds(Collections.singleton(scheme.getId()));
293
            Set<Integer> catalogIds = schemeItems.stream().map(x -> x.getCatalogId()).collect(Collectors.toSet());
294
            List<String> itemDescriptions = itemRepository.selectAllByCatalogIds(catalogIds).stream().filter(Utils.distinctByKey(Item::getCatalogItemId))
295
                    .map(x -> x.getItemDescriptionNoColor()).collect(Collectors.toList());
296
            String titleTemplate = "%s of Rs.%s for %s";
297
            String schemeString = "Activation scheme";
298
            if (scheme.getType().equals(SchemeType.SPECIAL_SUPPORT)) {
299
                schemeString = "Special Support";
300
            }
30957 amit.gupta 301
 
31410 amit.gupta 302
            String message = "Duration from - " + FormattingUtils.formatDateMonth(scheme.getStartDateTime()) + " - " + FormattingUtils.formatDateMonth(scheme.getEndDateTime());
303
            sendNotificationModel.setCampaignName("activationscheme");
304
            sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/scheme/" + scheme.getId());
305
            sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(1));
306
            sendNotificationModel.setMessage(message);
307
            sendNotificationModel.setTitle(String.format(titleTemplate, schemeString, FormattingUtils.formatDecimal(scheme.getAmount()), org.apache.commons.lang3.StringUtils.abbreviate(String.join(", ", itemDescriptions), 25)));
308
            sendNotificationModel.setType("url");
309
            sendNotificationModel.setMessageType(MessageType.scheme);
310
            notificationService.sendNotificationToAll(sendNotificationModel);
311
        }
312
    }
23444 amit.gupta 313
 
31410 amit.gupta 314
    @Override
315
    public void expireSchemeById(int schemeId, LocalDateTime expiryTime) throws ProfitMandiBusinessException {
316
        Scheme scheme = schemeRepository.selectById(schemeId);
317
        if (scheme == null || scheme.getActiveTimestamp() == null) {
318
            throw new ProfitMandiBusinessException(ProfitMandiConstants.ACTIVE_TIMESTAMP, scheme.getActiveTimestamp(),
319
                    "SCHM_1007");
320
        }
321
        if (scheme.getExpireTimestamp() != null) {
322
            throw new ProfitMandiBusinessException(ProfitMandiConstants.EXPIRE_TIMESTAMP, scheme.getExpireTimestamp(),
323
                    "SCHM_1008");
324
        }
325
        scheme.setExpireTimestamp(LocalDateTime.now());
326
        if (expiryTime.isAfter(scheme.getEndDateTime())) {
327
            throw new ProfitMandiBusinessException(ProfitMandiConstants.EXPIRE_TIMESTAMP, scheme.getExpireTimestamp(),
328
                    "End Date cant be extended during expiry");
329
        }
330
        scheme.setEndDateTime(expiryTime);
331
        schemeRepository.persist(scheme);
332
    }
23444 amit.gupta 333
 
31410 amit.gupta 334
    private Map<Integer, Scheme> toSchemeIdSchemeMap(List<Scheme> schemes) {
335
        Map<Integer, Scheme> schemeIdSchemeMap = new HashMap<>();
336
        for (Scheme scheme : schemes) {
337
            schemeIdSchemeMap.put(scheme.getId(), scheme);
338
        }
339
        return schemeIdSchemeMap;
340
    }
23444 amit.gupta 341
 
31410 amit.gupta 342
    private Map<Integer, Set<Scheme>> toCatalogIdSchemesMap(List<SchemeItem> schemeItems, List<Scheme> schemes) {
343
        Map<Integer, Scheme> schemesMap = schemes.stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
344
        Map<Integer, Set<Scheme>> catalogSchemesMap = new HashMap<>();
345
        for (SchemeItem schemeItem : schemeItems) {
346
            if (!catalogSchemesMap.containsKey(schemeItem.getCatalogId())) {
347
                catalogSchemesMap.put(schemeItem.getCatalogId(), new HashSet<>());
348
            }
349
            Set<Scheme> schemesSet = catalogSchemesMap.get(schemeItem.getCatalogId());
350
            schemesSet.add(schemesMap.get(schemeItem.getSchemeId()));
351
        }
352
        return catalogSchemesMap;
353
    }
23444 amit.gupta 354
 
31410 amit.gupta 355
    private Map<InventoryItem, Set<Scheme>> toInventoryItemSchemesMap(List<Scheme> schemes,
356
                                                                      List<InventoryItem> inventoryItems) {
357
        Set<Integer> schemeIds = schemes.stream().map(x -> x.getId()).collect(Collectors.toSet());
358
        Set<Integer> itemIds = inventoryItems.stream().map(x -> x.getItemId()).collect(Collectors.toSet());
359
        Set<Integer> catalogIds = itemRepository.selectByIds(itemIds).stream().map(x -> x.getCatalogItemId()).collect(Collectors.toSet());
360
        List<SchemeItem> schemeItems = schemeItemRepository.selectBySchemeIdsAndCatalogIds(schemeIds, catalogIds);
23444 amit.gupta 361
 
31410 amit.gupta 362
        Map<Integer, Set<Scheme>> catalogIdSchemesMap = this.toCatalogIdSchemesMap(schemeItems, schemes);
363
        Map<InventoryItem, Set<Scheme>> inventoryItemSchemesMap = new HashMap<>();
364
        for (InventoryItem inventoryItem : inventoryItems) {
365
            LOGGER.info("inventoryItem {}", inventoryItem);
366
            LOGGER.info("inventoryItem.getItem() {}", inventoryItem.getItem());
367
            LOGGER.info("catalogIdSchemesMap {}", catalogIdSchemesMap);
368
            if (catalogIdSchemesMap.containsKey(inventoryItem.getItem().getCatalogItemId())) {
369
                inventoryItemSchemesMap.put(inventoryItem, catalogIdSchemesMap.get(inventoryItem.getItem().getCatalogItemId()));
370
            }
371
        }
372
        return inventoryItemSchemesMap;
373
    }
31170 amit.gupta 374
 
31903 amit.gupta 375
    @Autowired
376
    OfferTargetSlabRepository offerTargetSlabRepository;
377
 
378
    /*@Override
31410 amit.gupta 379
    public void processSchemeIn(int purchaseId, int retailerId) throws ProfitMandiBusinessException {
380
        LOGGER.info("Trying to process SchemeIn with purchaseId [{}] and retailerId [{}]", purchaseId, retailerId);
381
        Purchase purchase = purchaseRepository.selectByIdAndFofoId(purchaseId, retailerId);
31903 amit.gupta 382
 
383
 
31410 amit.gupta 384
        // TODO - SCHEME
385
        PartnerType partnerType = partnerTypeChangeService.getTypeOnMonth(retailerId,
386
                YearMonth.from(purchase.getCreateTimestamp()));
387
        // PartnerType partnerType = partnerTypeChangeService.getTypeOnDate(retailerId,
388
        // purchase.getCreateTimestamp().toLocalDate());
23444 amit.gupta 389
 
31410 amit.gupta 390
        List<Scheme> schemes = schemeRepository.selectActiveAll(Arrays.asList(SchemeType.IN), partnerType,
391
                purchase.getCreateTimestamp().toLocalDate(), false);
392
        List<Integer> validSchemeIds = schemeRepository.selectSchemesByRetailerIdsSchemeIds(retailerId, schemes.stream().map(x -> x.getId()).collect(Collectors.toList()));
393
        schemes = schemes.stream().filter(x -> validSchemeIds.contains(x.getId())).collect(Collectors.toList());
394
        float totalCashback = 0;
23444 amit.gupta 395
 
31410 amit.gupta 396
        if (schemes.isEmpty()) {
397
            return;
398
        }
399
        List<InventoryItem> inventoryItems = inventoryItemRepository.selectByPurchaseId(purchaseId);
400
        //Remove imeis from blocked imeis list
401
        inventoryItems = inventoryItems.stream().filter(inventoryItem -> !BLOCKED_IMEIS.contains(inventoryItem.getSerialNumber())).collect(Collectors.toList());
402
        if (inventoryItems.size() == 0) return;
403
        Set<Integer> itemIds = inventoryItems.stream().map(x -> x.getItemId()).collect(Collectors.toSet());
404
        Map<Integer, Item> itemsMap = itemRepository.selectByIds(itemIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
405
        inventoryItems.stream().forEach(x -> x.setItem(itemsMap.get(x.getItemId())));
23444 amit.gupta 406
 
31410 amit.gupta 407
        LocalDateTime billingDate = purchaseService.getBillingDateOfPurchase(purchaseId);
408
        Set<Integer> itemIdsSet = tagListingRepository.selectByItemIdsAndTagIds(itemIds, tagIds).stream()
409
                .filter(x -> x.getEolDate() == null || x.getEolDate().isAfter(billingDate)).map(x -> x.getItemId())
410
                .collect(Collectors.toSet());
411
        // Only consider inventory items that were not returned
412
        inventoryItems = inventoryItems.stream().filter(x -> itemIdsSet.contains(x.getItemId()))
413
                .filter(x -> !x.getLastScanType().equals(ScanType.PURCHASE_RET_BAD))
414
                .filter(x -> !x.getLastScanType().equals(ScanType.PURCHASE_RET)).collect(Collectors.toList());
415
        LOGGER.info(inventoryItems);
416
        if (inventoryItems.size() == 0)
417
            return;
418
        Map<InventoryItem, Set<Scheme>> inventoryItemSchemesMap = this.toInventoryItemSchemesMap(schemes,
419
                inventoryItems);
23444 amit.gupta 420
 
31410 amit.gupta 421
        if (inventoryItemSchemesMap.isEmpty()) {
422
            return;
423
        }
424
        Map<InventoryItem, Set<Scheme>> allInventoryItemSchemesMap = new HashMap<>();
23444 amit.gupta 425
 
31410 amit.gupta 426
        for (Map.Entry<InventoryItem, Set<Scheme>> inventoryItemSchemesEntry : inventoryItemSchemesMap.entrySet()) {
427
            Set<Scheme> allSchemes = new HashSet<>();
428
            for (Scheme scheme : inventoryItemSchemesEntry.getValue()) {
429
                allSchemes.add(scheme);
430
            }
431
            allInventoryItemSchemesMap.put(inventoryItemSchemesEntry.getKey(), allSchemes);
432
        }
29927 amit.gupta 433
 
31410 amit.gupta 434
        //
23444 amit.gupta 435
 
31410 amit.gupta 436
        int itemsCount = 0;
437
        for (Map.Entry<InventoryItem, Set<Scheme>> allInventoryItemSchemesEntry : allInventoryItemSchemesMap
438
                .entrySet()) {
439
            float inventoryItemCashback = 0;
440
            for (Scheme scheme : allInventoryItemSchemesEntry.getValue()) {
441
                InventoryItem inventoryItem = allInventoryItemSchemesEntry.getKey();
31903 amit.gupta 442
                float cashback = this.createSchemeInOut(null, inventoryItem, partnerType);
31410 amit.gupta 443
                inventoryItemCashback += cashback;
444
            }
445
            if (inventoryItemCashback > 0) {
446
                totalCashback += inventoryItemCashback;
447
                itemsCount++;
448
            }
449
        }
23444 amit.gupta 450
 
31410 amit.gupta 451
        LOGGER.info("Items count for purchase id {} is {}", purchaseId, itemsCount);
452
        if (itemsCount > 0) {
453
            walletService.addAmountToWallet(
454
                    retailerId, purchaseId, WalletReferenceType.SCHEME_IN, "Added for SCHEME IN against invoice "
455
                            + purchase.getPurchaseReference() + " (total " + itemsCount + " pcs)",
456
                    totalCashback, purchase.getCreateTimestamp());
457
            LOGGER.info("Added Rs.{} for SCHEME IN against invoice {} total pcs({}) {}", totalCashback,
458
                    purchase.getPurchaseReference(), itemsCount);
459
            purchase.setCashback(purchase.getCashback() + totalCashback);
460
            purchaseRepository.persist(purchase);
461
        }
31903 amit.gupta 462
    }*/
23444 amit.gupta 463
 
31410 amit.gupta 464
    private Scheme toScheme(int creatorId, CreateSchemeRequest createSchemeRequest) {
465
        Scheme scheme = new Scheme();
466
        scheme.setName(createSchemeRequest.getName());
467
        scheme.setDescription(createSchemeRequest.getDescription());
468
        scheme.setType(createSchemeRequest.getType());
469
        scheme.setAmountType(createSchemeRequest.getAmountType());
470
        scheme.setAmount(createSchemeRequest.getAmount());
471
        scheme.setPartnerType(createSchemeRequest.getPartnerType());
472
        scheme.setStartDateTime(createSchemeRequest.getStartDate());
473
        scheme.setEndDateTime(createSchemeRequest.getEndDate());
474
        scheme.setCreatedBy(creatorId);
475
        scheme.setCashback(createSchemeRequest.isCashback());
476
        return scheme;
477
    }
23444 amit.gupta 478
 
31903 amit.gupta 479
    @Autowired
480
    OfferRepository offerRepository;
481
    @Autowired
482
    OfferPayoutRepository offerPayoutRepository;
483
    @Autowired
484
    AgeingService ageingService;
31588 amit.gupta 485
 
31903 amit.gupta 486
    public void processSchemeIn(int purchaseId, int retailerId) throws ProfitMandiBusinessException {
487
        Purchase purchase = purchaseRepository.selectByIdAndFofoId(purchaseId, retailerId);
488
        PartnerType partnerType = partnerTypeChangeService.getTypeOnMonth(retailerId,
489
                YearMonth.from(purchase.getCreateTimestamp()));
490
        List<InventoryItem> inventoryItems = inventoryItemRepository.selectByPurchaseId(purchaseId);
491
        //Remove imeis from blocked imeis list
492
        inventoryItems = inventoryItems.stream().filter(inventoryItem -> !BLOCKED_IMEIS.contains(inventoryItem.getSerialNumber())).collect(Collectors.toList());
493
        if (inventoryItems.size() == 0) return;
23444 amit.gupta 494
 
31903 amit.gupta 495
        Set<Integer> itemIds = inventoryItems.stream().map(x -> x.getItemId()).collect(Collectors.toSet());
496
        Map<Integer, Item> itemsMap = itemRepository.selectByIds(itemIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
497
        inventoryItems.stream().forEach(x -> x.setItem(itemsMap.get(x.getItemId())));
23444 amit.gupta 498
 
499
 
31903 amit.gupta 500
        LocalDateTime billingDate = purchaseService.getBillingDateOfPurchase(purchaseId);
501
        Set<Integer> itemIdsSet = tagListingRepository.selectByItemIdsAndTagIds(itemIds, tagIds).stream()
502
                .filter(x -> x.getEolDate() == null || x.getEolDate().isAfter(billingDate)).map(x -> x.getItemId())
503
                .collect(Collectors.toSet());
504
        // Only consider inventory items that were not returned and not eol
505
        inventoryItems = inventoryItems.stream().filter(x -> itemIdsSet.contains(x.getItemId()))
506
                .filter(x -> !x.getLastScanType().equals(ScanType.PURCHASE_RET_BAD))
507
                .filter(x -> !x.getLastScanType().equals(ScanType.PURCHASE_RET)).collect(Collectors.toList());
508
 
509
        if (inventoryItems.size() == 0) return;
510
 
511
        Map<Integer, List<InventoryItem>> catalogInventoryItemMap = inventoryItems.stream().collect(Collectors.groupingBy(x -> x.getItem().getCatalogItemId()));
512
        Map<CatalogSummaryModel, List<SchemeSummaryModel>> catalogSchemeSummaryMap = tagListingRepository.getModelSchemesByCatalogIdsAndType(retailerId,
513
                partnerType, new ArrayList<>(catalogInventoryItemMap.keySet()), purchase.getCreateTimestamp());
514
 
515
 
516
        int itemsCount = 0;
517
        float totalCashback = 0;
518
        for (Map.Entry<CatalogSummaryModel, List<SchemeSummaryModel>> catalogSummaryModelListEntry : catalogSchemeSummaryMap.entrySet()) {
519
            CatalogSummaryModel catalogSummaryModel = catalogSummaryModelListEntry.getKey();
31930 amit.gupta 520
            List<SchemeSummaryModel> schemeSummaryModels = catalogSummaryModelListEntry.getValue().stream().filter(x->x !=null).collect(Collectors.toList());
521
            schemeSummaryModels.stream().filter(x -> x!=null && x.getSchemeType().equals(SchemeType.IN)).forEach(x -> x.setProcess(true));
31903 amit.gupta 522
            if (schemeSummaryModels.stream().filter(x -> x.isProcess()).count() == 0) continue;
523
            List<InventoryItem> modelInventoryItems = catalogInventoryItemMap.get(catalogSummaryModel.getCatalogId());
524
            for (InventoryItem inventoryItem : modelInventoryItems) {
525
                float inventoryItemCashback = this.createSchemeInOut(schemeSummaryModels, inventoryItem, partnerType);
526
                if (inventoryItemCashback > 0) {
527
                    itemsCount++;
528
                    totalCashback += inventoryItemCashback;
31410 amit.gupta 529
                }
530
            }
31903 amit.gupta 531
        }
22653 ashik.ali 532
 
29927 amit.gupta 533
 
31903 amit.gupta 534
        LOGGER.info("Items count for purchase id {} is {}", purchaseId, itemsCount);
535
        if (itemsCount > 0) {
536
            walletService.addAmountToWallet(
537
                    retailerId, purchaseId, WalletReferenceType.SCHEME_IN, "Added for SCHEME IN against invoice "
538
                            + purchase.getPurchaseReference() + " (total " + itemsCount + " pcs)",
539
                    totalCashback, purchase.getCreateTimestamp());
540
            LOGGER.info("Added Rs.{} for SCHEME IN against invoice {} total pcs({}) {}", totalCashback,
541
                    purchase.getPurchaseReference(), itemsCount);
542
        }
543
 
544
    }
545
 
546
 
31410 amit.gupta 547
    // We are maintaining price drop after grn
548
    private float getAmount(InventoryItem inventoryItem, Scheme scheme) throws ProfitMandiBusinessException {
549
        if (BLOCKED_IMEIS.contains(inventoryItem.getSerialNumber())) {
550
            return 0;
551
        }
552
        float amount = 0;
553
        float dpForCalc = 0;
554
        float taxableSellingPrice = 0;
29927 amit.gupta 555
 
31410 amit.gupta 556
        //float totalTaxRate = stateGstRateRepository.getTotalTaxRate(inventoryItem.getItemId());
557
        if (scheme.getAmountType().equals(AmountType.PERCENTAGE)) {
558
            if (scheme.getType().equals(SchemeType.IN)) {
559
                dpForCalc = inventoryItem.getUnitPrice() - inventoryItem.getPriceDropAmount();
560
            } else {
561
                try {
562
                    dpForCalc = Math.min(inventoryItem.getUnitPrice() - inventoryItem.getPriceDropAmount(),
563
                            tagListingRepository.selectByItemId(inventoryItem.getItemId()).getSellingPrice());
564
                } catch (Exception e) {
565
                    LOGGER.info("Could not find tag Listing entry in {}", inventoryItem.getItemId());
566
                    e.printStackTrace();
567
                }
568
            }
569
            //TODO:Should be calculated on unit price
570
            //taxableSellingPrice = dpForCalc / (1 + totalTaxRate / 100);
571
            //amount = taxableSellingPrice * scheme.getAmount() / 100;
572
            amount = dpForCalc * scheme.getAmount() / 100;
573
            System.out.println(String.format("%d\t%s\t%d\t%d\t%s\t%s\t%s\t%s\t%f\t%f\t%f\t%f", inventoryItem.getId(),
574
                    inventoryItem.getSerialNumber(), inventoryItem.getItemId(), scheme.getId(), scheme.getName(),
575
                    scheme.getType(), scheme.getAmountType(), scheme.getPartnerType(), dpForCalc, taxableSellingPrice,
576
                    scheme.getAmount(), amount));
577
        } else if (scheme.getType().equals(SchemeType.IN)) {
578
            amount = scheme.getAmount();
579
        }
580
        return amount;
581
    }
23444 amit.gupta 582
 
31903 amit.gupta 583
    //Only in and activation margins are allowed to be rolled out more than twice
584
    private float createSchemeInOut(List<SchemeSummaryModel> schemeSummaryModels, InventoryItem inventoryItem, PartnerType partnerType) throws ProfitMandiBusinessException {
585
 
31921 amit.gupta 586
        InventoryPayoutModel inventoryPayoutModel = priceCircularService.getPayouts(inventoryItem);
31903 amit.gupta 587
        //Get all schemes
588
        List<SchemeSummaryModel> inventoryPayoutModelToProcess = schemeSummaryModels.stream().filter(x -> x.isProcess()).collect(Collectors.toList());
589
 
590
        List<SchemeInOut> sios = inventoryPayoutModel.getSchemePayouts();
591
        Map<SchemeType, List<SchemeInOut>> paidSchemeTypesMap = inventoryPayoutModel.getSchemePayouts().stream().collect(Collectors.groupingBy(x -> x.getScheme().getType()));
592
        Map<Integer, SchemeInOut> paidSchemesMap = sios.stream().collect(Collectors.toMap(x -> x.getSchemeId(), x -> x));
593
 
594
        double percentageToPay = 0d;
595
        double fixedToPay = 0d;
596
        Map<SchemeSummaryModel, AmountModel> payoutSchemeSummaryModelMap = new HashMap<>();
597
        for (SchemeSummaryModel schemeSummaryModelToProcess : inventoryPayoutModelToProcess) {
598
            if (paidSchemesMap.containsKey(schemeSummaryModelToProcess.getSchemeId())) continue;
599
            //If different type but on higher side provide the higher margin
600
            if (Arrays.asList(SchemeType.ACTIVATION, SchemeType.SPECIAL_SUPPORT).contains(schemeSummaryModelToProcess.getSchemeType())) {
601
                SchemeInOut sio = new SchemeInOut();
602
                sio.setAmount(0);
603
                sio.setInventoryItemId(inventoryItem.getId());
604
                sio.setSchemeId(schemeSummaryModelToProcess.getSchemeId());
605
                sio.setStatusDescription("Activation pending for IMEI#" + inventoryItem.getSerialNumber());
606
                sio.setStatus(SchemePayoutStatus.PENDING);
607
                schemeInOutRepository.persist(sio);
608
            } else if (!SchemeType.IN.equals(schemeSummaryModelToProcess.getSchemeType())) {
609
                //We have got non repeating scheme type
610
                if (paidSchemeTypesMap.containsKey(schemeSummaryModelToProcess.getSchemeType())) {
611
                    SchemeInOut sio = paidSchemeTypesMap.get(schemeSummaryModelToProcess.getSchemeType()).get(0);
612
                    Scheme paidScheme = sio.getScheme();
613
                    //Don't entertain if amount types do not match for same type
614
                    if (paidScheme.getAmountType().equals(schemeSummaryModelToProcess.getAmountType()) &&
615
                            schemeSummaryModelToProcess.getAmount() > paidScheme.getAmount() + Utils.DOUBLE_EPSILON) {
616
                        sio.setRolledBackTimestamp(LocalDateTime.now());
617
                        sio.setStatus(SchemePayoutStatus.REJECTED);
618
                        sio.setStatusDescription("Eligible for higher margin for " + sio.getSchemeType() + " new entry added");
619
                        if (paidScheme.getAmountType().equals(AmountType.PERCENTAGE)) {
620
                            percentageToPay += schemeSummaryModelToProcess.getAmount() - paidScheme.getAmount();
621
                        } else {
622
                            fixedToPay += schemeSummaryModelToProcess.getAmount() - paidScheme.getAmount();
623
                        }
624
                        payoutSchemeSummaryModelMap.put(schemeSummaryModelToProcess, new AmountModel(schemeSummaryModelToProcess.getAmount() - paidScheme.getAmount(), schemeSummaryModelToProcess.getAmountType()));
625
                    }
626
                } else {
627
                    if (schemeSummaryModelToProcess.getAmountType().equals(AmountType.PERCENTAGE)) {
628
                        percentageToPay += schemeSummaryModelToProcess.getAmount();
629
                    } else {
630
                        fixedToPay += schemeSummaryModelToProcess.getAmount();
631
                    }
632
                    payoutSchemeSummaryModelMap.put(schemeSummaryModelToProcess, new AmountModel(schemeSummaryModelToProcess.getAmount(), schemeSummaryModelToProcess.getAmountType()));
633
                }
634
            } else {
635
                if (schemeSummaryModelToProcess.getAmountType().equals(AmountType.PERCENTAGE)) {
636
                    percentageToPay += schemeSummaryModelToProcess.getAmount();
637
                } else {
638
                    fixedToPay += schemeSummaryModelToProcess.getAmount();
639
                }
640
                payoutSchemeSummaryModelMap.put(schemeSummaryModelToProcess, new AmountModel(schemeSummaryModelToProcess.getAmount(), schemeSummaryModelToProcess.getAmountType()));
641
            }
642
        }
643
        double walletCredit = 0d;
644
        if (fixedToPay > 0) {
31913 amit.gupta 645
            double fixedRollout = fixedToPay * (100 / (100 + inventoryPayoutModel.getPercentageAmount()));
31903 amit.gupta 646
            for (Map.Entry<SchemeSummaryModel, AmountModel> schemeSummaryModelAmountModelEntry : payoutSchemeSummaryModelMap.entrySet()) {
647
                SchemeSummaryModel schemeSummaryModel = schemeSummaryModelAmountModelEntry.getKey();
648
                AmountModel amountModel = schemeSummaryModelAmountModelEntry.getValue();
649
                if (amountModel.getAmountType().equals(AmountType.FIXED)) {
650
                    SchemeInOut sio = new SchemeInOut();
651
                    sio.setSchemeId(schemeSummaryModel.getSchemeId());
652
                    sio.setInventoryItemId(inventoryItem.getId());
653
                    sio.setStatus(SchemePayoutStatus.CREDITED);
654
                    sio.setCreditTimestamp(LocalDateTime.now());
655
                    sio.setAmount((float) (fixedRollout * amountModel.getAmount() / fixedToPay));
656
                    if (schemeSummaryModel.getSchemeType().equals(SchemeType.IN))
657
                        sio.setStatusDescription("Credited for GRN of IMEI-" + inventoryItem.getSerialNumber());
658
                    else
659
                        sio.setStatusDescription("Credited for Sale of IMEI-" + inventoryItem.getSerialNumber());
660
                    schemeInOutRepository.persist(sio);
661
                }
662
            }
663
            walletCredit += fixedRollout;
664
        }
665
 
666
        if (percentageToPay > 0) {
31987 amit.gupta 667
            LOGGER.info("inventoryPayoutModel.getFixedAmount() ----> {}", inventoryPayoutModel.getFixedAmount());
31914 amit.gupta 668
            double effectiveDP = inventoryPayoutModel.getDp() - (inventoryPayoutModel.getFixedAmount() + fixedToPay);
31903 amit.gupta 669
            double totalPercentage = inventoryPayoutModel.getPercentageAmount() + percentageToPay;
670
            double percentageRollout = effectiveDP * (totalPercentage / (100 + totalPercentage) - (inventoryPayoutModel.getPercentageAmount() / (100 + inventoryPayoutModel.getPercentageAmount())));
671
            for (Map.Entry<SchemeSummaryModel, AmountModel> schemeSummaryModelAmountModelEntry : payoutSchemeSummaryModelMap.entrySet()) {
672
                SchemeSummaryModel schemeSummaryModel = schemeSummaryModelAmountModelEntry.getKey();
673
                AmountModel amountModel = schemeSummaryModelAmountModelEntry.getValue();
674
                if (amountModel.getAmountType().equals(AmountType.PERCENTAGE)) {
675
                    SchemeInOut sio = new SchemeInOut();
676
                    sio.setInventoryItemId(inventoryItem.getId());
677
                    sio.setSchemeId(schemeSummaryModel.getSchemeId());
678
                    sio.setStatus(SchemePayoutStatus.CREDITED);
679
                    sio.setCreditTimestamp(LocalDateTime.now());
680
                    sio.setAmount((float) (percentageRollout * amountModel.getAmount() / percentageToPay));
681
                    if (schemeSummaryModel.getSchemeType().equals(SchemeType.IN))
682
                        sio.setStatusDescription("Credited for GRN of IMEI-" + inventoryItem.getSerialNumber());
683
                    else
684
                        sio.setStatusDescription("Credited for Sale of IMEI-" + inventoryItem.getSerialNumber());
685
                    schemeInOutRepository.persist(sio);
686
                }
687
            }
688
            walletCredit += percentageRollout;
689
        }
690
 
691
        return (float) walletCredit;
692
    }
693
 
694
    private Set<Integer> filterImeisByAgeing(Set<Integer> inventoryItemIds, FofoOrder fofoOrder) {
695
        Set<Integer> filteredInventoryIds = new HashSet<>();
696
        List<PartnerAgeingModel> partnerAgeingModels = ageingService.filterAgedInventory(inventoryItemIds);
697
        for (PartnerAgeingModel partnerAgeingModel : partnerAgeingModels) {
698
            LOGGER.info("Serial Number - {}", partnerAgeingModel.getSerialNumber());
699
            if (partnerAgeingModel.getBrand().equalsIgnoreCase("Samsung")) {
700
                ActivatedImei activatedImei = activatedImeiRepository.selectBySerialNumber(partnerAgeingModel.getSerialNumber());
701
                if (activatedImei != null && activatedImei.getActivationTimestamp().toLocalDate()
702
                        .isBefore(partnerAgeingModel.getBillingDate().plusDays(partnerAgeingModel.getMaxAgeingDays()))) {
703
                    //Lets give money if activation is there and is before the ageing limit of that brand.
704
                    filteredInventoryIds.add(partnerAgeingModel.getInventoryItemId());
705
                } else {
706
                    //If billing happens before ageing expiry
707
                    if (fofoOrder.getCreateTimestamp().toLocalDate().isBefore(partnerAgeingModel.getBillingDate().plusDays(partnerAgeingModel.getMaxAgeingDays()))) {
708
                        filteredInventoryIds.add(partnerAgeingModel.getInventoryItemId());
709
                    }
710
                }
711
            } else {
712
                filteredInventoryIds.add(partnerAgeingModel.getInventoryItemId());
713
            }
714
        }
715
        return filteredInventoryIds;
716
    }
717
 
31410 amit.gupta 718
    @Override
719
    public float processSchemeOut(int fofoOrderId, int retailerId) throws ProfitMandiBusinessException {
720
        float totalCashback = 0;
721
        FofoOrder fofoOrder = fofoOrderRepository.selectByFofoIdAndOrderId(retailerId, fofoOrderId);
722
        // Process only if order is not cancelled
723
        if (fofoOrder.getCancelledTimestamp() == null) {
724
            // PartnerType partnerType = partnerTypeChangeService.getTypeOnDate(retailerId,
725
            // fofoOrder.getCreateTimestamp().toLocalDate());
726
            // TODO - SCHEME
727
            PartnerType partnerType = partnerTypeChangeService.getTypeOnMonth(retailerId,
728
                    YearMonth.from(fofoOrder.getCreateTimestamp()));
29927 amit.gupta 729
 
31410 amit.gupta 730
            List<ScanRecord> scanRecords = scanRecordRepository.selectAllByOrderId(fofoOrderId);
731
            if (scanRecords.size() == 0) return 0;
732
            Set<Integer> inventoryItemIds = scanRecords.stream().map(x -> x.getInventoryItemId())
733
                    .collect(Collectors.toSet());
31903 amit.gupta 734
            //Check for ageing
31912 amit.gupta 735
            //inventoryItemIds = this.filterImeisByAgeing(inventoryItemIds, fofoOrder);
31903 amit.gupta 736
            //ageingService.filterAgedInventory(inventoryItemIds);
31410 amit.gupta 737
            LOGGER.info("fofoOrderId --- {}", fofoOrderId);
738
            LOGGER.info("scanRecords --- {}", scanRecords);
739
            LOGGER.info("inventoryItemIds --- {}", inventoryItemIds);
31903 amit.gupta 740
 
741
            if (inventoryItemIds.size() == 0) return 0;
742
 
31410 amit.gupta 743
            Set<InventoryItem> inventoryItems = inventoryItemRepository.selectByIds(inventoryItemIds).stream()
744
                    .filter(x -> x.getSerialNumber() != null && !x.getSerialNumber().equals(""))
745
                    .collect(Collectors.toSet());
746
            inventoryItems = inventoryItems.stream().filter(inventoryItem -> !BLOCKED_IMEIS.contains(inventoryItem.getSerialNumber())).collect(Collectors.toSet());
29927 amit.gupta 747
 
31903 amit.gupta 748
            if (inventoryItems.size() == 0) return 0;
29927 amit.gupta 749
 
31903 amit.gupta 750
            Map<Integer, List<InventoryItem>> catalogInventoryItemMap = inventoryItems.stream().collect(Collectors.groupingBy(x -> x.getItem().getCatalogItemId()));
751
            Map<CatalogSummaryModel, List<SchemeSummaryModel>> catalogSchemeSummaryMap = tagListingRepository.getModelSchemesByCatalogIdsAndType(retailerId,
752
                    partnerType, new ArrayList<>(catalogInventoryItemMap.keySet()), fofoOrder.getCreateTimestamp());
23444 amit.gupta 753
 
31903 amit.gupta 754
 
31410 amit.gupta 755
            int count = 0;
31903 amit.gupta 756
            for (Map.Entry<CatalogSummaryModel, List<SchemeSummaryModel>> catalogSummaryModelListEntry : catalogSchemeSummaryMap.entrySet()) {
757
                CatalogSummaryModel catalogSummaryModel = catalogSummaryModelListEntry.getKey();
31930 amit.gupta 758
                List<SchemeSummaryModel> schemeSummaryModels = catalogSummaryModelListEntry.getValue().stream().filter(x->x != null).collect(Collectors.toList());
31903 amit.gupta 759
                List<SchemeType> allOutSchemeTypes = new ArrayList<>();
760
                allOutSchemeTypes.addAll(Arrays.asList(SchemeType.ACTIVATION, SchemeType.INVESTMENT, SchemeType.SPECIAL_SUPPORT, SchemeType.SELLOUT));
761
                allOutSchemeTypes.addAll(OUT_SCHEME_TYPES);
762
                schemeSummaryModels.stream().filter(x -> allOutSchemeTypes.contains(x.getSchemeType())).forEach(x -> x.setProcess(true));
763
                if (schemeSummaryModels.stream().filter(x -> x.isProcess()).count() == 0) continue;
23444 amit.gupta 764
 
31903 amit.gupta 765
                List<InventoryItem> modelInventoryItems = catalogInventoryItemMap.get(catalogSummaryModel.getCatalogId());
766
                for (InventoryItem inventoryItem : modelInventoryItems) {
767
                    float inventoryItemCashback = this.createSchemeInOut(schemeSummaryModels, inventoryItem, partnerType);
768
                    if (inventoryItemCashback > 0) {
769
                        count++;
770
                        totalCashback += inventoryItemCashback;
771
                    }
31410 amit.gupta 772
                }
773
            }
31903 amit.gupta 774
 
31410 amit.gupta 775
            if (count > 0) {
776
                walletService.addAmountToWallet(
777
                        retailerId, fofoOrderId, WalletReferenceType.SCHEME_OUT, "Sales margin for invoice number "
778
                                + fofoOrder.getInvoiceNumber() + ". Total " + count + " pc(s)",
779
                        totalCashback, fofoOrder.getCreateTimestamp());
780
                fofoOrder.setCashback(totalCashback + fofoOrder.getCashback());
781
            }
782
        }
783
        return totalCashback;
784
    }
22653 ashik.ali 785
 
31410 amit.gupta 786
    @Override
787
    //Tax rate has been passed to 0 to ensure no tax deduction
788
    public float getSpecialSupportAmount(float supportAmount, PartnerType partnerType, LocalDate onDate,
789
                                         int catalogId) throws ProfitMandiBusinessException {
790
        //int itemId = itemRepository.selectAllByCatalogItemId(catalogId).stream().findAny().get().getId();
791
        //float totalTaxRate = stateGstRateRepository.getTotalTaxRate(itemId);
792
        return this.getSpecialSupportAmount(supportAmount, partnerType, onDate, catalogId, 0);
793
    }
23444 amit.gupta 794
 
31410 amit.gupta 795
    @Override
796
    public float getSpecialSupportAmount(float supportAmount, PartnerType partnerType, LocalDate onDate,
797
                                         int catalogId, float taxRate) throws ProfitMandiBusinessException {
798
        float totalMargin = this.selectPercentageScheme(partnerType, onDate, catalogId, false, 0, 0).stream().collect(Collectors.summingDouble(x -> x.getAmount())).floatValue();
799
        float amountToCredit = supportAmount * (1 - (totalMargin / (100 + taxRate)));
800
        return amountToCredit;
801
    }
23444 amit.gupta 802
 
31410 amit.gupta 803
    private void processSpecialSupport(FofoOrder fofoOrder, List<Scheme> supportSchemes, InventoryItem
804
            inventoryItem, PartnerType partnerType, LocalDateTime saleDate) throws ProfitMandiBusinessException {
805
        int catalogId = inventoryItem.getItem().getCatalogItemId();
806
        float totalMargin = this.selectPercentageScheme(partnerType, saleDate.toLocalDate(), catalogId, false, 0, 0).stream().collect(Collectors.summingDouble(x -> x.getAmount())).floatValue();
807
        LOGGER.info("total percentage margin - {}", totalMargin);
808
        for (Scheme scheme : supportSchemes) {
809
            float amountToCredit = scheme.getAmount() * (1 - (totalMargin / 100));
810
            List<SchemeInOut> schemeInOuts = schemeInOutRepository.selectByScheme(scheme.getId(), inventoryItem.getId());
811
            SchemeInOut schemeInOut = schemeInOuts.stream().filter(x -> x.getRolledBackTimestamp() == null).findFirst().orElse(null);
812
            if (schemeInOut == null) {
813
                schemeInOut = new SchemeInOut();
31903 amit.gupta 814
                schemeInOut.setInventoryItemId(inventoryItem.getId());
31410 amit.gupta 815
                schemeInOut.setSchemeId(scheme.getId());
816
                schemeInOut.setInventoryItemId(inventoryItem.getId());
817
                schemeInOut.setCreateTimestamp(LocalDateTime.now());
818
                if (SchemeType.SELLOUT.equals(scheme.getType())) {
819
                    schemeInOut.setStatus(SchemePayoutStatus.CREDITED);
820
                    schemeInOut.setCreditTimestamp(LocalDateTime.now());
821
                    schemeInOut.setStatusDescription("Modelwise sellout support credited");
822
                    walletService.addAmountToWallet(inventoryItem.getFofoId(), fofoOrder.getId(), WalletReferenceType.SPECIAL_SUPPORT,
823
                            "Modelwise sellout support credited for Imei - " + inventoryItem.getSerialNumber(), amountToCredit,
824
                            fofoOrder.getCreateTimestamp());
825
                } else {
826
                    schemeInOut.setStatusDescription("Special support, Activation pending for IMEI#" + inventoryItem.getSerialNumber());
827
                    schemeInOut.setStatus(SchemePayoutStatus.PENDING);
828
                }
829
                schemeInOut.setAmount(amountToCredit);
830
                schemeInOutRepository.persist(schemeInOut);
29231 amit.gupta 831
 
31410 amit.gupta 832
            } else if (Double.valueOf(schemeInOut.getAmount()).intValue() != Double.valueOf(amountToCredit).intValue()) {
833
                SchemeInOut schemeInOutNew = new SchemeInOut();
834
                schemeInOutNew.setInventoryItemId(inventoryItem.getId());
835
                schemeInOutNew.setSchemeId(scheme.getId());
836
                schemeInOutNew.setCreateTimestamp(LocalDateTime.now());
837
                schemeInOutNew.setAmount(amountToCredit);
838
                if (schemeInOut.getStatus().equals(SchemePayoutStatus.PENDING)) {
839
                    schemeInOutNew.setStatus(SchemePayoutStatus.PENDING);
840
                    schemeInOutNew.setStatusDescription("Special support, Activation pending for IMEI#" + inventoryItem.getSerialNumber());
841
                    schemeInOutRepository.persist(schemeInOutNew);
842
                } else if (schemeInOut.getStatus().equals(SchemePayoutStatus.CREDITED)) {
843
                    schemeInOutNew.setStatus(SchemePayoutStatus.CREDITED);
844
                    schemeInOutNew.setCreditTimestamp(LocalDateTime.now());
845
                    schemeInOutNew.setStatusDescription("Special support credited");
846
                    schemeInOutRepository.persist(schemeInOutNew);
847
                    walletService.addAmountToWallet(inventoryItem.getFofoId(), fofoOrder.getId(), WalletReferenceType.SPECIAL_SUPPORT,
848
                            "Special support adjusted against overall margin gains for Imei - " + inventoryItem.getSerialNumber(), amountToCredit - schemeInOut.getAmount(),
849
                            fofoOrder.getCreateTimestamp());
31170 amit.gupta 850
 
31410 amit.gupta 851
                }
852
                schemeInOut.setStatus(SchemePayoutStatus.REJECTED);
853
                schemeInOut.setStatusDescription("Failed!!, New Margin Entry added");
854
                schemeInOut.setRolledBackTimestamp(LocalDateTime.now());
855
            }
30191 amit.gupta 856
 
31410 amit.gupta 857
        }
23444 amit.gupta 858
 
31410 amit.gupta 859
    }
23444 amit.gupta 860
 
31410 amit.gupta 861
    @Override
862
    public void rollbackSchemes(List<Integer> inventoryItemIds, int rollbackReference, String rollbackReason)
863
            throws Exception {
864
        Set<Integer> inventoryItemIdSet = new HashSet<>(inventoryItemIds);
865
        float amountToRollback = 0;
866
        List<SchemeInOut> schemes = schemeInOutRepository.selectByInventoryItemIds(inventoryItemIdSet);
867
        for (SchemeInOut schemeInOut : schemes) {
868
            if (schemeInOut.getRolledBackTimestamp() == null) {
869
                schemeInOut.setRolledBackTimestamp(LocalDateTime.now());
870
                if (schemeInOut.getStatus() == null || schemeInOut.getStatus().equals(SchemePayoutStatus.CREDITED)) {
871
                    amountToRollback += schemeInOut.getAmount();
872
                }
873
                schemeInOut.setStatus(SchemePayoutStatus.REJECTED);
874
                schemeInOut.setStatusDescription(rollbackReason);
875
            }
876
        }
877
        if (amountToRollback > 0) {
878
            int inventoryItemId = inventoryItemIds.get(0);
879
            InventoryItem ii = inventoryItemRepository.selectById(inventoryItemId);
880
            Integer fofoId = ii.getFofoId();
881
            // Purchase p = purchaseRepository.selectById(ii.getPurchaseId());
882
            // TODO//
883
            walletService.rollbackAmountFromWallet(fofoId, amountToRollback, ii.getPurchaseId(),
884
                    WalletReferenceType.SCHEME_IN, rollbackReason, LocalDateTime.now());
885
        }
886
    }
23444 amit.gupta 887
 
31410 amit.gupta 888
    @Override
889
    public Map<String, Object> getSchemes(Set<Integer> roleIds, int offset, int limit)
890
            throws ProfitMandiBusinessException {
891
        Map<String, Object> map = new HashMap<>();
892
        List<Scheme> schemes = null;
893
        long size = 0;
894
        if (roleManager.isAdmin(roleIds)) {
895
            schemes = schemeRepository.selectAll(offset, limit);
896
            size = schemeRepository.selectAllCount();
897
        } else {
898
            schemes = schemeRepository.selectActiveAll(offset, limit);
899
            size = schemeRepository.selectAllActiveCount();
900
        }
901
        map.put("schemes", schemes);
902
        map.put("start", offset + 1);
903
        map.put("size", size);
904
        if (schemes.size() < limit) {
905
            map.put("end", offset + schemes.size());
906
        } else {
907
            map.put("end", offset + limit);
908
        }
909
        return map;
910
    }
26722 amit.gupta 911
 
31410 amit.gupta 912
    @Override
913
    public List<Scheme> getPaginatedSchemes(Set<Integer> roleIds, int offset, int limit)
914
            throws ProfitMandiBusinessException {
915
        LOGGER.info("requested offset=[{}], limit = [{}]", offset, limit);
916
        List<Scheme> schemes = null;
917
        if (roleManager.isAdmin(roleIds)) {
918
            schemes = schemeRepository.selectAll(offset, limit);
919
        } else {
920
            schemes = schemeRepository.selectActiveAll(offset, limit);
921
        }
922
        return schemes;
923
    }
27898 amit.gupta 924
 
31410 amit.gupta 925
    @Override
926
    // This is being called to reverse schemes while processing price Drop
927
    public void reverseSchemes(List<InventoryItem> inventoryItems, int priceDropId, String reversalReason)
928
            throws ProfitMandiBusinessException {
929
        PriceDrop priceDrop = priceDropRepository.selectById(priceDropId);
930
        Map<Integer, List<InventoryItem>> purchaseInventoryListMap = inventoryItems.stream()
931
                .collect(Collectors.groupingBy(InventoryItem::getPurchaseId, Collectors.toList()));
29927 amit.gupta 932
 
31410 amit.gupta 933
        for (Map.Entry<Integer, List<InventoryItem>> purchaseEntry : purchaseInventoryListMap.entrySet()) {
934
            float amountToCredit = 0;
935
            float amountToDebit = 0;
936
            int purchaseId = purchaseEntry.getKey();
937
            List<InventoryItem> purchaseInventoryItemList = purchaseEntry.getValue();
30454 amit.gupta 938
 
31410 amit.gupta 939
            Map<Integer, InventoryItem> inventoryItemsMap = purchaseInventoryItemList.stream()
940
                    .collect(Collectors.toMap(x -> x.getId(), x -> x));
29927 amit.gupta 941
 
31410 amit.gupta 942
            List<SchemeInOut> schemeInOuts = schemeInOutRepository.selectByInventoryItemIds(inventoryItemsMap.keySet());
943
            LOGGER.info("Scheme InOuts , {}", schemeInOuts);
944
            if (schemeInOuts.size() == 0) {
945
                continue;
946
            }
947
            List<Integer> schemeIds = schemeInOuts.stream().map(x -> x.getSchemeId()).collect(Collectors.toList());
948
            Map<Integer, Scheme> schemesMap = schemeRepository.selectBySchemeIds(schemeIds, 0, schemeIds.size())
949
                    .stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
950
            for (SchemeInOut schemeInOut : schemeInOuts) {
951
                InventoryItem ii = inventoryItemsMap.get(schemeInOut.getInventoryItemId());
952
                Scheme scheme = schemesMap.get(schemeInOut.getSchemeId());
953
                if (scheme.getAmountType().equals(AmountType.FIXED)) {
954
                    continue;
955
                }
956
                if (scheme.getType().equals(SchemeType.IN) && schemeInOut.getRolledBackTimestamp() == null) {
957
                    float newAmount = getAmount(ii, scheme);
958
                    if (Math.abs(schemeInOut.getAmount() - newAmount) >= 0.01f) {
959
                        schemeInOut.setRolledBackTimestamp(LocalDateTime.now());
29231 amit.gupta 960
 
31410 amit.gupta 961
                        SchemeInOut sioNew = new SchemeInOut();
962
                        sioNew.setAmount(newAmount);
963
                        sioNew.setStatus(schemeInOut.getStatus());
964
                        sioNew.setStatusDescription(schemeInOut.getStatusDescription());
965
                        sioNew.setInventoryItemId(schemeInOut.getInventoryItemId());
966
                        sioNew.setSchemeId(schemeInOut.getSchemeId());
967
                        sioNew.setCreditTimestamp(LocalDateTime.now());
968
                        schemeInOutRepository.persist(sioNew);
30957 amit.gupta 969
 
31410 amit.gupta 970
                        schemeInOut.setStatus(SchemePayoutStatus.REJECTED);
971
                        schemeInOut.setStatusDescription("Change in margins due to price drop");
972
                        // IF not credited then dont consider any credit/debit for that sio entry
973
                        if (schemeInOut.getCreditTimestamp() != null) {
974
                            amountToCredit += sioNew.getAmount();
975
                            amountToDebit += schemeInOut.getAmount();
976
                        }
977
                    }
29927 amit.gupta 978
 
31410 amit.gupta 979
                }
980
            }
981
            int fofoId = inventoryItems.get(0).getFofoId();
982
            if (amountToDebit > 0) {
983
                walletService.addAmountToWallet(fofoId, purchaseId, WalletReferenceType.SCHEME_IN,
984
                        MessageFormat.format(reversalReason, purchaseInventoryItemList.size()), -amountToDebit,
985
                        priceDrop.getAffectedOn());
986
            }
987
            if (amountToCredit > 0) {
988
                walletService.addAmountToWallet(fofoId, purchaseId, WalletReferenceType.SCHEME_IN,
989
                        MessageFormat.format(reversalReason, purchaseInventoryItemList.size()), amountToCredit,
990
                        priceDrop.getAffectedOn());
991
            }
992
        }
993
    }
29231 amit.gupta 994
 
31609 amit.gupta 995
    @Autowired
996
    UserWalletHistoryRepository userWalletHistoryRepository;
997
 
31410 amit.gupta 998
    @Override
999
    // Always being called from cancel order/bad return means no SCHEME IN is considered
1000
    public void reverseSchemes(List<InventoryItem> inventoryItems, int reversalReference, String reversalReason,
1001
                               List<SchemeType> schemeTypes) throws ProfitMandiBusinessException {
1002
        Map<Integer, InventoryItem> inventoryItemsMap = inventoryItems.stream()
1003
                .collect(Collectors.toMap(x -> x.getId(), x -> x));
1004
        LOGGER.info("inventoryItems" + inventoryItems);
23444 amit.gupta 1005
 
31410 amit.gupta 1006
        Map<SchemeType, SchemeInOut> schemeTypeMap = new HashMap<>();
30454 amit.gupta 1007
 
31410 amit.gupta 1008
        List<SchemeInOut> schemeInOuts = schemeInOutRepository.selectByInventoryItemIds(inventoryItemsMap.keySet());
1009
        LOGGER.info("schemeInOuts" + schemeInOuts);
1010
        float amountToRollback = 0;
23444 amit.gupta 1011
 
31410 amit.gupta 1012
        if (!schemeInOuts.isEmpty()) {
1013
            List<Integer> schemeIds = schemeInOuts.stream().map(x -> x.getSchemeId()).collect(Collectors.toList());
1014
            LOGGER.info("schemeIds" + schemeIds);
29231 amit.gupta 1015
 
31410 amit.gupta 1016
            Map<Integer, Scheme> schemesMap = schemeRepository.selectBySchemeIds(schemeIds, 0, schemeIds.size())
1017
                    .stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
1018
            for (SchemeInOut schemeInOut : schemeInOuts) {
1019
                Scheme scheme = schemesMap.get(schemeInOut.getSchemeId());
1020
                if (schemeTypes.contains(scheme.getType())) {
1021
                    schemeTypeMap.put(scheme.getType(), schemeInOut);
1022
                    if (schemeInOut.getRolledBackTimestamp() == null) {
1023
                        schemeInOut.setRolledBackTimestamp(LocalDateTime.now());
1024
                        if (schemeInOut.getStatus().equals(SchemePayoutStatus.CREDITED)) {
1025
                            amountToRollback += schemeInOut.getAmount();
1026
                        }
1027
                        schemeInOut.setStatus(SchemePayoutStatus.REJECTED);
1028
                        schemeInOut.setStatusDescription(reversalReason);
1029
                    }
1030
                }
1031
            }
1032
        }
1033
        int fofoId = inventoryItems.get(0).getFofoId();
31609 amit.gupta 1034
        WalletReferenceType walletReferenceType = schemeTypes.containsAll(SchemeService.OUT_SCHEME_TYPES) ? WalletReferenceType.SCHEME_OUT
1035
                : schemeTypes.contains(SchemeType.ACTIVATION) ? WalletReferenceType.ACTIVATION_SCHEME
1036
                : schemeTypes.contains(SchemeType.SPECIAL_SUPPORT) ? WalletReferenceType.SPECIAL_SUPPORT
1037
                : schemeTypes.contains(SchemeType.INVESTMENT) ? WalletReferenceType.INVESTMENT_PAYOUT : null;
1038
 
1039
        if (walletReferenceType == null)
1040
            if (amountToRollback > 0 && walletReferenceType != null) {
1041
                // Mark appropriate reference of rollback investment margin
1042
                if (schemeTypes.contains(SchemeType.INVESTMENT)) {
1043
                    List<UserWalletHistory> userWalletHistoryList = userWalletHistoryRepository.selectAllByreferenceIdandreferenceType(reversalReference, walletReferenceType);
1044
                    if (userWalletHistoryList.size() == 0) {
1045
                        reversalReference = Integer
1046
                                .parseInt(FormattingUtils.getYearMonth(schemeTypeMap.get(SchemeType.INVESTMENT).getCreditTimestamp().minusMonths(1)));
1047
                    }
1048
 
1049
                }
1050
                walletService.rollbackAmountFromWallet(fofoId, amountToRollback, reversalReference, walletReferenceType,
31903 amit.gupta 1051
                        reversalReason, LocalDateTime.now());
1052
            }
31410 amit.gupta 1053
    }
29231 amit.gupta 1054
 
31410 amit.gupta 1055
    @Override
1056
    public double getTotalMargin(int itemId, PartnerType partnerType, LocalDateTime dateTime) {
1057
        Session session = sessionFactory.getCurrentSession();
1058
        CriteriaBuilder cb = session.getCriteriaBuilder();
1059
        CriteriaQuery<Double> criteriaQuery = cb.createQuery(Double.class);
1060
        Root<SchemeItem> schemeItem = criteriaQuery.from(SchemeItem.class);
1061
        Root<Scheme> scheme = criteriaQuery.from(Scheme.class);
1062
        Predicate schemePredicate = cb.equal(scheme.get(ProfitMandiConstants.AMOUNT_TYPE), AmountType.PERCENTAGE);
1063
        Predicate lessThanPredicate = cb.lessThanOrEqualTo(scheme.get(ProfitMandiConstants.END_DATE_TIME), dateTime);
1064
        Predicate greaterThanPredicate = cb.greaterThanOrEqualTo(scheme.get(ProfitMandiConstants.START_DATE_TIME),
1065
                dateTime);
1066
        Predicate joinPredicate = cb.equal(scheme.get("id"), schemeItem.get("schemeId"));
1067
        Predicate schemeItemPredicate = cb.equal(schemeItem.get(ProfitMandiConstants.ITEM_ID), itemId);
1068
        criteriaQuery.select(cb.sum(scheme.get(ProfitMandiConstants.AMOUNT))).where(schemePredicate, lessThanPredicate,
1069
                greaterThanPredicate, schemeItemPredicate, joinPredicate);
29231 amit.gupta 1070
 
31410 amit.gupta 1071
        Query<Double> query = session.createQuery(criteriaQuery);
1072
        return query.getSingleResult() + ProfitMandiConstants.SCHEME_INVESTMENT_MARGIN;
29231 amit.gupta 1073
 
31410 amit.gupta 1074
    }
23444 amit.gupta 1075
 
31410 amit.gupta 1076
    @Override
1077
    @Cacheable(value = "itemSchemeCashback", cacheManager = "timeoutCacheManager")
1078
    public Map<Integer, Float> getCatalogSchemeCashBack() {
1079
        Map<Integer, Float> itemCashbackMap = new HashMap<>();
1080
        Map<Integer, Scheme> cashbackSchemesMap = schemeRepository
31450 amit.gupta 1081
                .selectActiveAll(Arrays.asList(SchemeType.ACTIVATION, SchemeType.SPECIAL_SUPPORT, SchemeType.SELLOUT), PartnerType.ALL, LocalDate.now(), false)
31410 amit.gupta 1082
                .stream().filter(x -> x.getAmountType().equals(AmountType.FIXED))
1083
                .collect(Collectors.toMap(x -> x.getId(), x -> x));
1084
        if (cashbackSchemesMap.size() > 0) {
1085
            List<SchemeItem> schemeItems = schemeItemRepository.selectBySchemeIds(cashbackSchemesMap.keySet());
1086
            schemeItems.stream().forEach(x -> {
1087
                float cashbackAmount = cashbackSchemesMap.get(x.getSchemeId()).getAmount();
1088
                if (!itemCashbackMap.containsKey(x.getCatalogId())) {
1089
                    itemCashbackMap.put(x.getCatalogId(), cashbackAmount);
1090
                } else {
1091
                    itemCashbackMap.put(x.getCatalogId(), itemCashbackMap.get(x.getCatalogId()) + cashbackAmount);
1092
                }
1093
            });
1094
        }
1095
        // A107FD Model needs to removed
1096
        itemCashbackMap.remove(30211);
1097
        itemCashbackMap.remove(30212);
1098
        itemCashbackMap.remove(30213);
1099
        itemCashbackMap.remove(30756);
1100
        return itemCashbackMap;
1101
    }
30572 amit.gupta 1102
 
31410 amit.gupta 1103
    @Override
31903 amit.gupta 1104
    public List<Scheme> selectSchemeByPartnerTypeFofoId(PartnerType partnerType, LocalDate onDate, int catalogId,
1105
                                                        int fofoId, int offset, int limit) throws ProfitMandiBusinessException {
31410 amit.gupta 1106
        Session session = sessionFactory.getCurrentSession();
1107
        final TypedQuery<Scheme> typedQuery = session.createNamedQuery(
1108
                "Scheme.selectSchemeByModelsPartnerTypeFofoId", Scheme.class);
1109
        typedQuery.setParameter("catalogIds", Arrays.asList(catalogId));
1110
        typedQuery.setParameter("fofoIds", Arrays.asList(fofoId, 0));
1111
        typedQuery.setParameter("onDate", onDate.atStartOfDay());
1112
        typedQuery.setParameter("partnerTypes", Arrays.asList(partnerType, partnerType.ALL));
1113
        typedQuery.setFirstResult(offset);
1114
        if (limit != 0) {
1115
            typedQuery.setMaxResults(limit);
1116
        }
1117
        return typedQuery.getResultList();
1118
    }
30463 amit.gupta 1119
 
31410 amit.gupta 1120
    @Override
1121
    public List<Scheme> selectSchemeByPartnerType(PartnerType partnerType, LocalDate onDate, int catalogId,
1122
                                                  boolean isAdmin, int offset, int limit) throws ProfitMandiBusinessException {
1123
        Session session = sessionFactory.getCurrentSession();
1124
        List<Predicate> andPredicates = new ArrayList<>();
1125
        CriteriaBuilder cb = session.getCriteriaBuilder();
1126
        CriteriaQuery<Scheme> query = cb.createQuery(Scheme.class);
1127
        Root<Scheme> scheme = query.from(Scheme.class);
1128
        if (!partnerType.equals(PartnerType.ALL)) {
1129
            List<PartnerType> pt = new ArrayList<>();
1130
            pt.add(PartnerType.ALL);
1131
            pt.add(partnerType);
1132
            andPredicates.add(cb.in(scheme.get("partnerType")).value(pt));
1133
        }
1134
        cb.desc(cb.isNull(scheme.get("expireTimestamp")));
1135
        if (catalogId > 0) {
30454 amit.gupta 1136
 
31410 amit.gupta 1137
            List<Integer> schemeIds = schemeItemRepository.selectSchemeIdByCatalogId(catalogId);
1138
            LOGGER.info("schemeId" + schemeIds);
1139
            if (schemeIds.isEmpty()) {
1140
                return new ArrayList<>();
1141
            }
1142
            andPredicates.add(cb.in(scheme.get("id")).value(schemeIds));
1143
            if (onDate != null) {
1144
                andPredicates.add(cb.greaterThan(scheme.get("endDateTime"), onDate.atStartOfDay()));
1145
                andPredicates.add(cb.lessThanOrEqualTo(scheme.get("startDateTime"), onDate.atStartOfDay()));
1146
            }
1147
        }
1148
        if (!isAdmin) {
1149
            andPredicates.add(cb.isNotNull(scheme.get("activeTimestamp")));
1150
        }
1151
        query.where(cb.and(andPredicates.toArray(new Predicate[0])));
1152
        query.orderBy(cb.desc(cb.function("isnull", Boolean.class, scheme.get("expireTimestamp"))));
1153
        if (limit == 0) {
1154
            return session.createQuery(query).setFirstResult(offset).getResultList();
1155
        }
1156
        return session.createQuery(query).setFirstResult(offset).setMaxResults(limit).getResultList();
30454 amit.gupta 1157
 
31410 amit.gupta 1158
    }
30454 amit.gupta 1159
 
31410 amit.gupta 1160
    @Override
1161
    public List<Scheme> selectPercentageScheme(PartnerType partnerType, LocalDate onDate, int catalogId,
1162
                                               boolean isAdmin, int offset, int limit) throws ProfitMandiBusinessException {
1163
        List<Scheme> schemes = this.selectSchemeByPartnerType(partnerType, onDate, catalogId, isAdmin, offset, limit);
1164
        return schemes.stream().filter(x -> x.getAmountType().equals(AmountType.PERCENTAGE)).collect(Collectors.toList());
1165
    }
30454 amit.gupta 1166
 
31410 amit.gupta 1167
    @Override
1168
    public void processActivation() throws ProfitMandiBusinessException {
1169
        List<SchemeInOut> pendingPayouts = schemeInOutRepository.selectAllPending();
1170
        List<Integer> schemeIds = new ArrayList<>();
1171
        Set<Integer> inventoryIds = new HashSet<>();
1172
        for (SchemeInOut pendingPayout : pendingPayouts) {
1173
            schemeIds.add(pendingPayout.getSchemeId());
1174
        }
1175
        Map<Integer, Scheme> schemesMap = schemeRepository.selectBySchemeIds(schemeIds, 0, 0).stream()
1176
                .filter(x -> x.getType().equals(SchemeType.ACTIVATION) || x.getType().equals(SchemeType.SPECIAL_SUPPORT))
1177
                .collect(Collectors.toMap(x -> x.getId(), x -> x));
1178
        pendingPayouts = pendingPayouts.stream().filter(x -> schemesMap.get(x.getSchemeId()) != null)
1179
                .collect(Collectors.toList());
23884 amit.gupta 1180
 
31410 amit.gupta 1181
        for (SchemeInOut pendingPayout : pendingPayouts) {
1182
            inventoryIds.add(pendingPayout.getInventoryItemId());
1183
        }
1184
        Map<Integer, InventoryItem> inventoryItemMap = inventoryItemRepository.selectByIds(inventoryIds).stream()
1185
                .collect(Collectors.toMap(x -> x.getId(), x -> x));
1186
        Map<String, InventoryItem> serialNumberMap = inventoryItemMap.values().stream()
1187
                .collect(Collectors.toMap(x -> x.getSerialNumber(), x -> x));
23796 amit.gupta 1188
 
31410 amit.gupta 1189
        List<ActivatedImei> activatedImeis = activatedImeiRepository
1190
                .selectBySerialNumbers(new ArrayList<>(serialNumberMap.keySet())).stream().collect(Collectors.toList());
23508 amit.gupta 1191
 
31410 amit.gupta 1192
        Map<String, ActivatedImei> activatedImeiMap = activatedImeis.stream()
1193
                .collect(Collectors.toMap(x -> x.getSerialNumber().toLowerCase(), x -> x));
1194
        for (SchemeInOut pendingPayout : pendingPayouts) {
31914 amit.gupta 1195
            Scheme scheme = schemesMap.get(pendingPayout.getSchemeId());
31410 amit.gupta 1196
            InventoryItem ii = inventoryItemMap.get(pendingPayout.getInventoryItemId());
1197
            String serialNumber = ii.getSerialNumber().toLowerCase();
1198
            ActivatedImei activatedImei = activatedImeiMap.get(serialNumber);
1199
            if (activatedImei == null) {
1200
                continue;
1201
            }
1202
            if (scheme.isWithinRange(activatedImei.getActivationTimestamp())) {
1203
                int fofoId = ii.getFofoId();
1204
                // Get latest order Id
1205
                int orderId = scanRecordRepository.selectByInventoryItemId(ii.getId()).stream()
1206
                        .filter(x -> x.getOrderId() > 0)
1207
                        .sorted(Comparator.comparing(ScanRecord::getCreateTimestamp).reversed()).findFirst().get()
1208
                        .getOrderId();
1209
                FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(orderId);
31916 amit.gupta 1210
 
31921 amit.gupta 1211
                InventoryPayoutModel inventoryPayoutModel = priceCircularService.getPayouts(ii);
31916 amit.gupta 1212
                AmountModel amountModel = new AmountModel();
1213
                amountModel.setAmount(scheme.getAmount());
1214
                amountModel.setAmountType(scheme.getAmountType());
31921 amit.gupta 1215
                double amountToRollout = inventoryPayoutModel.getRolloutAmount(amountModel);
31919 amit.gupta 1216
                pendingPayout.setAmount((float)amountToRollout);
31410 amit.gupta 1217
                if (scheme.getType().equals(SchemeType.ACTIVATION)) {
1218
                    walletService.addAmountToWallet(fofoId, orderId, WalletReferenceType.ACTIVATION_SCHEME,
31914 amit.gupta 1219
                            "Activation margin for " + ii.getItem().getItemDescriptionNoColor() + ", Imei - " + serialNumber, (float) amountToRollout,
31410 amit.gupta 1220
                            fofoOrder.getCreateTimestamp());
1221
                    pendingPayout.setStatusDescription("Activation margin credited, activated on " + FormattingUtils.formatDate(activatedImei.getActivationTimestamp()));
1222
                } else {
1223
                    walletService.addAmountToWallet(fofoId, orderId, WalletReferenceType.SPECIAL_SUPPORT,
31914 amit.gupta 1224
                            "Special Support for " + ii.getItem().getItemDescriptionNoColor() + ", Imei - " + serialNumber, (float) amountToRollout,
31410 amit.gupta 1225
                            fofoOrder.getCreateTimestamp());
1226
                    pendingPayout.setStatusDescription("Special support credited, activated on " + FormattingUtils.formatDate(activatedImei.getActivationTimestamp()));
1227
                }
1228
                pendingPayout.setCreditTimestamp(LocalDateTime.now());
1229
                pendingPayout.setStatus(SchemePayoutStatus.CREDITED);
1230
            } else {
1231
                pendingPayout.setStatus(SchemePayoutStatus.REJECTED);
1232
                pendingPayout.setRolledBackTimestamp(LocalDateTime.now());
1233
                ;
1234
                pendingPayout.setStatusDescription(
1235
                        "Rejected, activated on " + FormattingUtils.formatDate(activatedImei.getActivationTimestamp()));
1236
            }
1237
        }
1238
    }
24976 amit.gupta 1239
 
31410 amit.gupta 1240
    @Override
1241
    public void processActivatedImeisForSchemes() throws ProfitMandiBusinessException {
1242
        List<SchemesImeisModel> schemesImeisModels = schemeRepository.selectSelectUnpaidSchemes();
1243
        LOGGER.info("Total Size - " + schemesImeisModels.size());
1244
        List<Integer> orderIds = schemesImeisModels.stream().map(x -> x.getOrderId()).collect(Collectors.toList());
1245
        List<FofoOrder> fofoOrders = fofoOrderRepository.selectAllByOrderIds(orderIds);
1246
        Map<Integer, FofoOrder> validOrdersMap = fofoOrders.stream().filter(x -> x.getCancelledTimestamp() == null).collect(Collectors.toMap(x -> x.getId(), x -> x));
1247
        Map<String, List<SchemesImeisModel>> validImeiSchemesModelMap = schemesImeisModels.stream().filter(x -> validOrdersMap.containsKey(x.getOrderId())).collect(Collectors.groupingBy(x -> x.getImei()));
1248
        for (Map.Entry<String, List<SchemesImeisModel>> imeiListEntry : validImeiSchemesModelMap.entrySet()) {
1249
            SchemesImeisModel schemesImeisModel = imeiListEntry.getValue().get(0);
1250
            List<Integer> schemeIds = imeiListEntry.getValue().stream().map(x -> x.getSchemeId()).collect(Collectors.toList());
1251
            LOGGER.info("Serial Number  - {}, Scheme IDs - {}", schemesImeisModel.getImei(), schemeIds);
1252
            InventoryItem inventoryItem = inventoryItemRepository.selectById(schemesImeisModel.getInventoryItemId());
1253
            List<Scheme> schemes = schemeRepository.selectBySchemeIds(schemeIds);
1254
            List<Scheme> supportSchemes = schemes.stream().filter(x -> Arrays.asList(SchemeType.SPECIAL_SUPPORT, SchemeType.ACTIVATION).contains(x.getType())).collect(Collectors.toList());
1255
            if (supportSchemes.size() > 0) {
1256
                FofoOrder fofoOrder = validOrdersMap.get(schemesImeisModel.getOrderId());
1257
                PartnerType partnerType = partnerTypeChangeService.getTypeOnMonth(fofoOrder.getFofoId(),
1258
                        YearMonth.from(fofoOrder.getCreateTimestamp()));
1259
                this.processSpecialSupport(fofoOrder, supportSchemes, inventoryItem, partnerType, fofoOrder.getCreateTimestamp());
1260
            }
1261
        }
1262
    }
22653 ashik.ali 1263
}