Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
23365 ashik.ali 1
package com.spice.profitmandi.service.order;
22859 ashik.ali 2
 
24264 amit.gupta 3
import com.spice.profitmandi.common.enumuration.ItemType;
23202 ashik.ali 4
import com.spice.profitmandi.common.enumuration.SearchType;
33838 ranu 5
import com.spice.profitmandi.common.enumuration.UpgradeOfferPaymentStatus;
22859 ashik.ali 6
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
32420 amit.gupta 7
import com.spice.profitmandi.common.model.*;
23650 amit.gupta 8
import com.spice.profitmandi.common.util.FormattingUtils;
22859 ashik.ali 9
import com.spice.profitmandi.common.util.StringUtils;
23172 ashik.ali 10
import com.spice.profitmandi.common.util.Utils;
29515 tejbeer 11
import com.spice.profitmandi.common.web.client.RestClient;
33873 ranu 12
import com.spice.profitmandi.dao.cart.SmartCartService;
22859 ashik.ali 13
import com.spice.profitmandi.dao.entity.catalog.Item;
25103 amit.gupta 14
import com.spice.profitmandi.dao.entity.catalog.TagListing;
33795 ranu 15
import com.spice.profitmandi.dao.entity.catalog.UpgradeOffer;
32420 amit.gupta 16
import com.spice.profitmandi.dao.entity.dtr.*;
17
import com.spice.profitmandi.dao.entity.fofo.*;
28978 amit.gupta 18
import com.spice.profitmandi.dao.entity.inventory.State;
24917 tejbeer 19
import com.spice.profitmandi.dao.entity.transaction.Order;
22859 ashik.ali 20
import com.spice.profitmandi.dao.entity.user.Address;
21
import com.spice.profitmandi.dao.entity.user.Counter;
22
import com.spice.profitmandi.dao.entity.user.PrivateDealUser;
27516 amit.gupta 23
import com.spice.profitmandi.dao.entity.warehouse.WarehouseInventoryItem;
24264 amit.gupta 24
import com.spice.profitmandi.dao.enumuration.catalog.SchemeType;
23546 ashik.ali 25
import com.spice.profitmandi.dao.enumuration.dtr.PaymentOptionReferenceType;
23650 amit.gupta 26
import com.spice.profitmandi.dao.enumuration.fofo.ReturnType;
22859 ashik.ali 27
import com.spice.profitmandi.dao.enumuration.fofo.ScanType;
23655 amit.gupta 28
import com.spice.profitmandi.dao.enumuration.fofo.SettlementType;
29515 tejbeer 29
import com.spice.profitmandi.dao.enumuration.inventory.ScratchedGift;
28339 tejbeer 30
import com.spice.profitmandi.dao.enumuration.transaction.OrderStatus;
33795 ranu 31
import com.spice.profitmandi.dao.repository.catalog.*;
32420 amit.gupta 32
import com.spice.profitmandi.dao.repository.dtr.*;
33
import com.spice.profitmandi.dao.repository.fofo.*;
24854 amit.gupta 34
import com.spice.profitmandi.dao.repository.inventory.StateRepository;
24917 tejbeer 35
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
22859 ashik.ali 36
import com.spice.profitmandi.dao.repository.user.AddressRepository;
37
import com.spice.profitmandi.dao.repository.user.CounterRepository;
38
import com.spice.profitmandi.dao.repository.user.PrivateDealUserRepository;
27516 amit.gupta 39
import com.spice.profitmandi.dao.repository.warehouse.WarehouseInventoryItemRepository;
35236 amit 40
import com.spice.profitmandi.service.catalog.BrandsService;
34798 ranu 41
import com.spice.profitmandi.service.integrations.bharti.model.PlanVariant;
25724 amit.gupta 42
import com.spice.profitmandi.service.integrations.zest.InsuranceService;
31274 amit.gupta 43
import com.spice.profitmandi.service.integrations.zest.MobileInsurancePlan;
23418 ashik.ali 44
import com.spice.profitmandi.service.inventory.InventoryService;
23655 amit.gupta 45
import com.spice.profitmandi.service.inventory.PurchaseReturnService;
26891 amit.gupta 46
import com.spice.profitmandi.service.inventory.SaholicInventoryService;
28166 tejbeer 47
import com.spice.profitmandi.service.offers.ItemCriteria;
22859 ashik.ali 48
import com.spice.profitmandi.service.pricing.PricingService;
49
import com.spice.profitmandi.service.scheme.SchemeService;
23655 amit.gupta 50
import com.spice.profitmandi.service.user.RetailerService;
32420 amit.gupta 51
import org.apache.logging.log4j.LogManager;
52
import org.apache.logging.log4j.Logger;
53
import org.hibernate.Session;
54
import org.hibernate.SessionFactory;
55
import org.json.JSONObject;
56
import org.springframework.beans.factory.annotation.Autowired;
57
import org.springframework.beans.factory.annotation.Qualifier;
58
import org.springframework.beans.factory.annotation.Value;
59
import org.springframework.cache.annotation.Cacheable;
60
import org.springframework.core.io.InputStreamResource;
61
import org.springframework.http.HttpHeaders;
62
import org.springframework.http.HttpStatus;
63
import org.springframework.http.ResponseEntity;
64
import org.springframework.stereotype.Component;
22859 ashik.ali 65
 
32420 amit.gupta 66
import javax.persistence.criteria.CriteriaBuilder;
67
import javax.persistence.criteria.CriteriaQuery;
68
import javax.persistence.criteria.Predicate;
69
import javax.persistence.criteria.Root;
70
import java.io.ByteArrayInputStream;
71
import java.io.InputStream;
72
import java.time.LocalDate;
73
import java.time.LocalDateTime;
74
import java.time.LocalTime;
75
import java.util.AbstractMap.SimpleEntry;
76
import java.util.*;
77
import java.util.function.Function;
78
import java.util.stream.Collectors;
79
 
22859 ashik.ali 80
@Component
81
public class OrderServiceImpl implements OrderService {
82
 
32145 tejbeer 83
    private static final Logger LOGGER = LogManager.getLogger(OrderServiceImpl.class);
22859 ashik.ali 84
 
32145 tejbeer 85
    private static Map<String, Integer> serialNumberOrderIdMap = new HashMap<>();
31030 amit.gupta 86
 
32145 tejbeer 87
    static {
88
        serialNumberOrderIdMap.put("862897055749275", 67228);
89
    }
31030 amit.gupta 90
 
32145 tejbeer 91
    @Autowired
35236 amit 92
    BrandsService brandsService;
93
 
94
    @Autowired
32145 tejbeer 95
    @Qualifier("fofoInventoryItemRepository")
96
    private InventoryItemRepository inventoryItemRepository;
27083 amit.gupta 97
 
32145 tejbeer 98
    @Autowired
99
    private StateGstRateRepository stateGstRateRepository;
23650 amit.gupta 100
 
32145 tejbeer 101
    @Autowired
102
    private SaholicInventoryService saholicInventoryService;
27083 amit.gupta 103
 
32145 tejbeer 104
    @Autowired
105
    private LiveDemoBillingRespository liveDemoBillingRespository;
24823 amit.gupta 106
 
32145 tejbeer 107
    @Autowired
108
    private InsuranceService insuranceService;
25724 amit.gupta 109
 
32145 tejbeer 110
    @Autowired
111
    @Qualifier("fofoCurrentInventorySnapshotRepository")
112
    private CurrentInventorySnapshotRepository currentInventorySnapshotRepository;
22859 ashik.ali 113
 
32145 tejbeer 114
    @Autowired
115
    private InvoiceNumberGenerationSequenceRepository invoiceNumberGenerationSequenceRepository;
22859 ashik.ali 116
 
32145 tejbeer 117
    @Autowired
118
    private PurchaseReturnService purchaseReturnService;
23655 amit.gupta 119
 
32145 tejbeer 120
    @Autowired
121
    private RetailerService retailerService;
23655 amit.gupta 122
 
32145 tejbeer 123
    @Autowired
124
    private CustomerRepository customerRepository;
23650 amit.gupta 125
 
32145 tejbeer 126
    @Autowired
127
    private PurchaseReturnItemRepository purchaseReturnItemRepository;
22859 ashik.ali 128
 
32145 tejbeer 129
    @Autowired
130
    private AddressRepository addressRepository;
22859 ashik.ali 131
 
32145 tejbeer 132
    @Autowired
133
    private FofoLineItemRepository fofoLineItemRepository;
22859 ashik.ali 134
 
32145 tejbeer 135
    @Autowired
32816 ranu 136
    private FofoNonSerializeSerialRepository fofoNonSerializeSerialRepository;
137
 
138
    @Autowired
32145 tejbeer 139
    private WarehouseInventoryItemRepository warehouseInventoryItemRepository;
27516 amit.gupta 140
 
32145 tejbeer 141
    @Autowired
142
    private FofoOrderItemRepository fofoOrderItemRepository;
23650 amit.gupta 143
 
32145 tejbeer 144
    @Autowired
145
    private PaymentOptionRepository paymentOptionRepository;
22859 ashik.ali 146
 
32145 tejbeer 147
    @Autowired
148
    private CustomerReturnItemRepository customerReturnItemRepository;
23650 amit.gupta 149
 
32145 tejbeer 150
    @Autowired
151
    @Qualifier("fofoScanRecordRepository")
152
    private ScanRecordRepository scanRecordRepository;
22859 ashik.ali 153
 
32145 tejbeer 154
    @Autowired
155
    private FofoOrderRepository fofoOrderRepository;
22859 ashik.ali 156
 
32145 tejbeer 157
    @Autowired
158
    private RetailerRepository retailerRepository;
22859 ashik.ali 159
 
32145 tejbeer 160
    @Autowired
161
    private UserRepository userRepository;
22859 ashik.ali 162
 
32145 tejbeer 163
    @Autowired
164
    private UserAccountRepository userAccountRepository;
22859 ashik.ali 165
 
32145 tejbeer 166
    @Autowired
167
    private RetailerRegisteredAddressRepository retailerRegisteredAddressRepository;
22859 ashik.ali 168
 
32145 tejbeer 169
    @Autowired
170
    private CustomerAddressRepository customerAddressRepository;
22859 ashik.ali 171
 
32145 tejbeer 172
    @Autowired
173
    @Qualifier("catalogItemRepository")
174
    private ItemRepository itemRepository;
23650 amit.gupta 175
 
32145 tejbeer 176
    @Autowired
177
    private InsuranceProviderRepository insuranceProviderRepository;
23650 amit.gupta 178
 
32145 tejbeer 179
    @Autowired
180
    private InsurancePolicyRepository insurancePolicyRepository;
24917 tejbeer 181
 
32145 tejbeer 182
    @Autowired
183
    private StateRepository stateRepository;
23650 amit.gupta 184
 
32145 tejbeer 185
    @Autowired
186
    private PolicyNumberGenerationSequenceRepository policyNumberGenerationSequenceRepository;
23650 amit.gupta 187
 
32145 tejbeer 188
    @Autowired
189
    private PricingService pricingService;
23650 amit.gupta 190
 
32145 tejbeer 191
    @Autowired
192
    private PrivateDealUserRepository privateDealUserRepository;
23650 amit.gupta 193
 
32145 tejbeer 194
    @Autowired
195
    private TagListingRepository tagListingRepository;
24823 amit.gupta 196
 
32145 tejbeer 197
    @Autowired
198
    private CounterRepository counterRepository;
23650 amit.gupta 199
 
32145 tejbeer 200
    @Autowired
201
    private FofoStoreRepository fofoStoreRepository;
23650 amit.gupta 202
 
32145 tejbeer 203
    @Autowired
204
    private PaymentOptionTransactionRepository paymentOptionTransactionRepository;
23650 amit.gupta 205
 
32145 tejbeer 206
    @Autowired
207
    private SchemeService schemeService;
23650 amit.gupta 208
 
32145 tejbeer 209
    private static final List<Integer> orderIdsConsumed = new ArrayList<>();
28166 tejbeer 210
 
32145 tejbeer 211
    @Autowired
212
    @Qualifier("fofoInventoryService")
213
    private InventoryService inventoryService;
23650 amit.gupta 214
 
32145 tejbeer 215
    @Autowired
216
    private CustomerCreditNoteRepository customerCreditNoteRepository;
23650 amit.gupta 217
 
32145 tejbeer 218
    @Autowired
219
    private OrderRepository orderRepository;
24917 tejbeer 220
 
32145 tejbeer 221
    @Autowired
222
    private HygieneDataRepository hygieneDataRepository;
25640 tejbeer 223
 
32145 tejbeer 224
    @Autowired
225
    private SessionFactory sessionFactory;
28166 tejbeer 226
 
32145 tejbeer 227
    @Autowired
228
    private Mongo mongoClient;
28964 tejbeer 229
 
32145 tejbeer 230
    @Autowired
231
    private PendingOrderRepository pendingOrderRepository;
28964 tejbeer 232
 
32145 tejbeer 233
    @Autowired
33399 ranu 234
 
235
    private PendingOrderService pendingOrderService;
236
 
237
    @Autowired
32145 tejbeer 238
    private PendingOrderItemRepository pendingOrderItemRepository;
28166 tejbeer 239
 
32145 tejbeer 240
    @Autowired
241
    private ScratchOfferRepository scratchOfferRepository;
29515 tejbeer 242
 
32145 tejbeer 243
    @Autowired
244
    RestClient restClient;
29515 tejbeer 245
 
33715 ranu 246
    @Autowired
247
    UpSaleOrderRepository upSaleOrderRepository;
248
 
33795 ranu 249
    @Autowired
250
    private CustomerOfferRepository customerOfferRepository;
251
 
252
    @Autowired
253
    private CustomerOfferItemRepository customerOfferItemRepository;
254
 
255
    @Autowired
256
    private UpgradeOfferRepository upgradeOfferRepository;
257
 
33873 ranu 258
    @Autowired
259
    private SmartCartService smartCartService;
260
 
33895 ranu 261
    @Autowired
262
    private PartnerTypeChangeService partnerTypeChangeService;
263
 
32145 tejbeer 264
    @Value("${prod}")
265
    private boolean prodEnv;
29515 tejbeer 266
 
32145 tejbeer 267
    private static final String SMS_GATEWAY = "http://api.pinnacle.in/index.php/sms/send";
268
    private static final String SENDER = "SMTDKN";
29515 tejbeer 269
 
32145 tejbeer 270
    public static final String APP_DOWNLOAD_BILLING_TEMPLATE_ID = "1507163542403945677";
29515 tejbeer 271
 
32145 tejbeer 272
    public static final String APP_DOWNLOAD_BILLING_OFFER = "Dear Customer, Thank you for purchasing from SmartDukaan pls click %s to download our app to see you invoice and special offers. SmartDukaan";
29515 tejbeer 273
 
34342 ranu 274
    static Map<Double, List<ScratchedGift>> GIFT_SERIES = new TreeMap<>(Comparator.reverseOrder());
275
 
34340 ranu 276
    // Define eligible partners for LED & Microwave Oven
34351 ranu 277
    private static final Set<Integer> PREMIUM_ELIGIBLE_PARTNERS = new HashSet<>(Arrays.asList(175139615, 175139583));
34342 ranu 278
    private static Map<ScratchedGift, Integer> GIFT_QUANTITIES = new HashMap<>();
279
    List<Double> PRICE_RANGE = Arrays.asList(0.0, Double.MAX_VALUE);
33899 ranu 280
 
34340 ranu 281
    static {
34365 ranu 282
        GIFT_QUANTITIES.put(ScratchedGift.ACCESSORIES_50_PERCENT_OFF, 500);
34340 ranu 283
        GIFT_QUANTITIES.put(ScratchedGift.NECK_BAND, 280);
284
        GIFT_QUANTITIES.put(ScratchedGift.LED, 1);
285
        GIFT_QUANTITIES.put(ScratchedGift.MICROWAVE_OVEN, 1);
286
    }
287
 
288
    static {
289
        GIFT_SERIES.put(0.0, Arrays.asList(ScratchedGift.ACCESSORIES_50_PERCENT_OFF, ScratchedGift.NECK_BAND));
34365 ranu 290
        GIFT_SERIES.put(30001.0, Arrays.asList(ScratchedGift.NECK_BAND, ScratchedGift.MICROWAVE_OVEN, ScratchedGift.LED));
34340 ranu 291
    }
292
 
33899 ranu 293
    private void persistNonSerializedWithCustomSerialNumber(CustomFofoOrderItem customFofoOrderItem, int orderItemId) {
294
        // Create a new instance of FofoNonSerializeSerial
295
        for (String accSerialNumber : customFofoOrderItem.getCustomSerialNumbers()) {
296
            if (!accSerialNumber.isEmpty()) {
297
                FofoNonSerializeSerial nonSerializeSerial = new FofoNonSerializeSerial();
298
 
299
                // Populate the entity with relevant information
300
                nonSerializeSerial.setOrderItemId(orderItemId);
301
                nonSerializeSerial.setSerialNumber(accSerialNumber);
302
 
303
                // Save the entity to the database
304
                fofoNonSerializeSerialRepository.persist(nonSerializeSerial);
305
            }
306
 
307
        }
308
    }
309
 
310
 
311
    public void sendAppDownloadBillingOffer(String mobileNumber) throws Exception {
312
        String sdurl = "http://surl.li/anhfn";
313
        try {
314
            if (prodEnv) {
315
                this.sendSms(APP_DOWNLOAD_BILLING_TEMPLATE_ID, String.format(APP_DOWNLOAD_BILLING_OFFER, sdurl), mobileNumber);
316
            }
317
        } catch (Exception e) {
318
            e.printStackTrace();
319
        }
320
 
321
    }
322
 
323
    public void sendSms(String dltTemplateId, String message, String mobileNumber) throws Exception {
324
        Map<String, String> map = new HashMap<>();
325
 
326
        map.put("sender", SENDER);
327
        map.put("messagetype", "TXT");
328
        map.put("apikey", "b866f7-c6c483-682ff5-054420-ad9e2c");
329
 
330
        map.put("numbers", "91" + mobileNumber);
331
        LOGGER.info("Message {}", message);
332
        // OTP Message Template
333
        map.put("message", message);
334
        map.put("dlttempid", dltTemplateId);
335
 
336
        String response = restClient.post(SMS_GATEWAY, map, new HashMap<>());
337
        LOGGER.info(response);
338
 
339
    }
340
 
341
 
342
    private void createScratchOffer(int fofoId, String invoiceNumber, int customerId) {
343
 
344
        //ScratchedGift gift = getScratchedGiftRandom(fofoId, customerId);
345
 
346
 
347
        //  LocalDateTime endDate = LocalDateTime.of(LocalDate.now().getYear(), LocalDate.now().getMonth(), 27, 21, 00);
348
        List<ScratchOffer> scratchOffers = scratchOfferRepository.selectBycCustomerIdAndDate(customerId, ProfitMandiConstants.SCRATCH_OFFER_START_DATE, ProfitMandiConstants.SCRATCH_OFFER_END_DATE);
349
        if (scratchOffers.size() == 0) {
350
            ScratchOffer so2 = new ScratchOffer();
351
            so2.setInvoiceNumber(invoiceNumber);
352
            so2.setScratched(false);
353
            so2.setCreatedTimestamp(LocalDateTime.now());
354
            so2.setExpiredTimestamp(ProfitMandiConstants.SCRATCH_OFFER_END_DATE.plusDays(1).atTime(LocalTime.MAX));
34474 aman.kumar 355
            so2.setOfferName(String.valueOf(ScratchedGift.BLNT));
33899 ranu 356
            so2.setCustomerId(customerId);
357
 
358
            LocalDateTime today830PM = LocalDate.now().atTime(20, 30);
359
            LocalDateTime today9PM = LocalDate.now().atTime(21, 0);
360
            so2.setUnlockedAt(LocalDateTime.now());
361
 
362
//            if (LocalDateTime.now().isAfter(today830PM)) {
363
//                so2.setUnlockedAt(today9PM.plusDays(0));
364
//            } else {
365
//                so2.setUnlockedAt(today9PM);
366
//            }
367
            scratchOfferRepository.persist(so2);
368
        }
369
    }
370
 
34341 ranu 371
 
32145 tejbeer 372
    @Override
34194 ranu 373
    public int createOrder(CreateOrderRequest createOrderRequest, int fofoId, boolean accessoriesDeals) throws Exception {
32145 tejbeer 374
        LOGGER.info("fofoId -- {} Order Request -- {}", fofoId, createOrderRequest);
375
        CustomCustomer customCustomer = createOrderRequest.getCustomer();
376
        Customer customer = customerRepository.selectById(customCustomer.getCustomerId());
22872 ashik.ali 377
 
35156 aman 378
        if ((createOrderRequest.getCustomer().getGender() != null && createOrderRequest.getCustomer().getGender().equals("2"))) {
35097 ranu 379
            customer.setGender("Female");
380
        } else {
381
 
382
            customer.setGender("Male");
383
        }
384
 
32145 tejbeer 385
        if (!StringUtils.isValidGstNumber(customCustomer.getGstNumber())) {
386
            LOGGER.error("invalid customer gstNumber {} ", customCustomer.getGstNumber());
387
            throw new ProfitMandiBusinessException(ProfitMandiConstants.CUSTOMER_GST_NUMBER, customCustomer.getGstNumber(), "VE_1072");
388
        }
23650 amit.gupta 389
 
32145 tejbeer 390
        Map<Integer, Integer> itemIdQuantity = new HashMap<>(); // this is for error
391
        Map<Integer, CustomFofoOrderItem> itemIdCustomFofoOrderItemMap = new HashMap<>();
392
        Map<Integer, Float> lineItemPrice = new HashMap<>(); // this is for pricing error
23650 amit.gupta 393
 
32145 tejbeer 394
        float totalAmount = 0;
395
        boolean noGST = false;
33520 amit.gupta 396
        int changedTotalBillAmount = 0;
397
        for (CustomPaymentOption cpo : createOrderRequest.getPaymentOptions()) {
33399 ranu 398
            changedTotalBillAmount += cpo.getAmount();
399
        }
35493 amit 400
 
401
        // N+1 fix: Batch fetch all PendingOrderItems before the validation loop
402
        List<Integer> validationPoiIds = createOrderRequest.getFofoOrderItems().stream()
403
                .map(CustomFofoOrderItem::getPoiId)
404
                .filter(id -> id > 0)
405
                .collect(Collectors.toList());
406
        Map<Integer, PendingOrderItem> pendingOrderItemMap = new HashMap<>();
407
        if (!validationPoiIds.isEmpty()) {
408
            List<PendingOrderItem> pendingOrderItems = pendingOrderItemRepository.selectByIds(validationPoiIds);
409
            pendingOrderItemMap = pendingOrderItems.stream()
410
                    .collect(Collectors.toMap(PendingOrderItem::getId, poi -> poi));
411
        }
412
 
32145 tejbeer 413
        for (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {
33520 amit.gupta 414
            if (customFofoOrderItem.getPoiId() > 0) {
35493 amit 415
                // N+1 fix: Use pre-fetched map instead of querying per item
416
                PendingOrderItem pendingOrderItem = pendingOrderItemMap.get(customFofoOrderItem.getPoiId());
417
                if (pendingOrderItem == null) {
418
                    throw new ProfitMandiBusinessException("poiId", customFofoOrderItem.getPoiId(), "Pending order item not found");
419
                }
33520 amit.gupta 420
                if (customFofoOrderItem.getQuantity() > pendingOrderItem.getQuantity()) {
33414 amit.gupta 421
                    throw new ProfitMandiBusinessException("itemIdQuantity", customFofoOrderItem.getItemId(), "Quantity should not be greater than order item quantity");
33399 ranu 422
                }
33520 amit.gupta 423
                if (pendingOrderItem.getQuantity() > customFofoOrderItem.getQuantity()) {
424
                    pendingOrderService.duplicatePendingOrder(pendingOrderItem, customFofoOrderItem.getQuantity());
33399 ranu 425
                }
426
            }
32145 tejbeer 427
            // itemIds.add(customFofoOrderItem.getItemId());
428
            Set<String> serialNumbers = this.serialNumberDetailsToSerialNumbers(customFofoOrderItem.getSerialNumberDetails());
429
            if (!serialNumbers.isEmpty() && customFofoOrderItem.getQuantity() != serialNumbers.size()) {
430
                itemIdQuantity.put(customFofoOrderItem.getItemId(), customFofoOrderItem.getQuantity());
431
            }
432
            if (!(customFofoOrderItem.getSellingPrice() > 0)) {
433
                lineItemPrice.put(customFofoOrderItem.getItemId(), customFofoOrderItem.getSellingPrice());
434
            } else {
33554 tejus.loha 435
                totalAmount = totalAmount + customFofoOrderItem.getSellingPrice() * customFofoOrderItem.getQuantity();
32145 tejbeer 436
                for (SerialNumberDetail serialNumberDetail : customFofoOrderItem.getSerialNumberDetails()) {
437
                    if (serialNumberDetail.getAmount() > 0) {
438
                        totalAmount = totalAmount + serialNumberDetail.getAmount();
439
                    }
440
                }
441
            }
23650 amit.gupta 442
 
32145 tejbeer 443
            itemIdCustomFofoOrderItemMap.put(customFofoOrderItem.getItemId(), customFofoOrderItem);
444
        }
445
        if (!itemIdQuantity.isEmpty()) {
446
            // if item quantity does not match with given serialnumbers size
447
            LOGGER.error("itemId's quantity should be equal to given serialnumber size {} ", itemIdQuantity);
448
            throw new ProfitMandiBusinessException("itemIdQuantity", itemIdQuantity, "FFORDR_1001");
449
            // return "error";
450
        }
23650 amit.gupta 451
 
32145 tejbeer 452
        this.validatePaymentOptionsAndTotalAmount(createOrderRequest.getPaymentOptions(), totalAmount);
23650 amit.gupta 453
 
32145 tejbeer 454
        if (!lineItemPrice.isEmpty()) {
455
            // given fofo line item price must be greater than zero
456
            LOGGER.error("requested itemId's selling price must greater than 0");
457
            throw new ProfitMandiBusinessException(ProfitMandiConstants.PRICE, lineItemPrice, "FFORDR_1002");
458
        }
22859 ashik.ali 459
 
32145 tejbeer 460
        List<CurrentInventorySnapshot> currentInventorySnapshots = currentInventorySnapshotRepository.selectByFofoItemIds(fofoId, itemIdCustomFofoOrderItemMap.keySet());
23650 amit.gupta 461
 
32145 tejbeer 462
        this.validateCurrentInventorySnapshotQuantities(currentInventorySnapshots, itemIdCustomFofoOrderItemMap);
22859 ashik.ali 463
 
32145 tejbeer 464
        List<Item> items = itemRepository.selectByIds(itemIdCustomFofoOrderItemMap.keySet());
465
        if (items.size() != itemIdCustomFofoOrderItemMap.keySet().size()) {
466
            LOGGER.error("Requested ItemIds not found in catalog");
467
            // invalid itemIds
468
            throw new ProfitMandiBusinessException("invalidItemIds", itemIdCustomFofoOrderItemMap.keySet(), "FFORDR_1003");
469
        }
23650 amit.gupta 470
 
32145 tejbeer 471
        Map<Integer, Item> itemMap = this.toItemMap(items);
23650 amit.gupta 472
 
32145 tejbeer 473
        Set<Integer> nonSerializedItemIds = new HashSet<>();
474
        Set<String> serialNumbers = new HashSet<>();
475
        List<InsuranceModel> insuredModels = new ArrayList<>();
476
        for (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {
477
            Item item = itemMap.get(customFofoOrderItem.getItemId());
478
            noGST = item.getHsnCode().equals("NOGST");
479
            if (item.getType().equals(ItemType.SERIALIZED)) {
480
                for (SerialNumberDetail serialNumberDetail : customFofoOrderItem.getSerialNumberDetails()) {
481
                    serialNumbers.add(serialNumberDetail.getSerialNumber());
482
                    if (serialNumberDetail.getAmount() > 0) {
483
                        if (customer.getEmailId() == null || customer.getEmailId().equals("")) {
484
                            throw new ProfitMandiBusinessException("Email Id is required for insurance", "Email Id is required for insurance", "Email Id is required for insurance");
485
                        }
34194 ranu 486
 
32145 tejbeer 487
                        InsuranceModel im = new InsuranceModel();
488
                        im.setBrand(item.getBrand());
489
                        im.setColor(item.getColor());
490
                        im.setModelName(item.getModelName() + item.getModelNumber());
491
                        im.setInsuranceAmount(serialNumberDetail.getAmount());
492
                        im.setDeviceSellingPrice(customFofoOrderItem.getSellingPrice());
34194 ranu 493
                        im.setInsuranceUId(serialNumberDetail.getInsurance());
34798 ranu 494
                        im.setCorrelationId(serialNumberDetail.getCorrelationId());
495
 
496
                        PlanVariant oneAssistpremium = insuranceService.getOneAssistPremiumByVariantId(serialNumberDetail.getInsurance());
497
                        if (oneAssistpremium != null) {
498
                            im.setInsuranceId(String.valueOf(oneAssistpremium.getId()));
499
                        } else {
500
                            im.setInsuranceId(String.valueOf(insuranceService.getICICIPremiumByVariantId(serialNumberDetail.getInsurance()).getId()));
501
                        }
32145 tejbeer 502
                        im.setSerialNumber(serialNumberDetail.getSerialNumber());
503
                        im.setMemory(serialNumberDetail.getMemory());
504
                        im.setRam(serialNumberDetail.getRam());
505
                        im.setMfgDate(serialNumberDetail.getMfgDate());
506
                        insuredModels.add(im);
507
                        // Check for free insurance code
508
                        try {
33520 amit.gupta 509
                            Map<String, List<MobileInsurancePlan>> mobileInsurancePlanMap = insuranceService.getAllPlans(item.getId(), im.getDeviceSellingPrice(), false);
32145 tejbeer 510
                            MobileInsurancePlan mobileInsurancePlan = mobileInsurancePlanMap.entrySet().stream().flatMap(x -> x.getValue().stream()).filter(x -> x.getProductId().equals(serialNumberDetail.getInsurance())).findFirst().get();
34798 ranu 511
/*                            if (mobileInsurancePlan.getPlanName().equals("OneAssist Damage Protection Plan")) {
512
                                MobileInsurancePlan freePlan = mobileInsurancePlanMap.get("Prolong Extendended Warranty(SmartDukaan Special Price)").get(0);
513
                                InsuranceModel imFree = new InsuranceModel();
514
                                imFree.setBrand(item.getBrand());
515
                                imFree.setColor(item.getColor());
516
                                imFree.setModelName(item.getModelName() + item.getModelNumber());
517
                                imFree.setInsuranceAmount(0);
518
                                imFree.setDeviceSellingPrice(customFofoOrderItem.getSellingPrice());
519
                                LOGGER.info("freePlan.getProductId() {}", freePlan.getProductId());
520
                                imFree.setInsuranceUId(freePlan.getProductId());
521
                                imFree.setInsuranceId(String.valueOf(insuranceService.getOneAssistPremiumByVariantId(freePlan.getProductId()).getId()));
522
                                imFree.setSerialNumber(serialNumberDetail.getSerialNumber());
523
                                imFree.setMemory(serialNumberDetail.getMemory());
524
                                imFree.setRam(serialNumberDetail.getRam());
525
                                imFree.setMfgDate(serialNumberDetail.getMfgDate());
526
                                insuredModels.add(imFree);
527
                            }*/
32145 tejbeer 528
                        } catch (Exception e) {
529
                            LOGGER.error("Exception - {}", e);
530
                            throw new ProfitMandiBusinessException("problem fetching plans", "problem fetching plans", "problem fetching plans");
531
                        }
532
                    }
31274 amit.gupta 533
 
32145 tejbeer 534
                }
535
            } else {
536
                nonSerializedItemIds.add(customFofoOrderItem.getItemId());
537
            }
538
        }
23650 amit.gupta 539
 
32145 tejbeer 540
        Map<Integer, Set<InventoryItem>> serializedInventoryItemMap = new HashMap<>();
541
        Map<Integer, Set<InventoryItem>> nonSerializedInventoryItemMap = new HashMap<>();
542
        // Map<String, Float> serialNumberItemPrice = new HashMap<>();
23650 amit.gupta 543
 
32145 tejbeer 544
        if (!serialNumbers.isEmpty()) {
545
            List<InventoryItem> serializedInventoryItems = inventoryItemRepository.selectByFofoIdSerialNumbers(fofoId, serialNumbers, false);
546
            LOGGER.info("serializedInventoryItems {}", serializedInventoryItems);
547
            for (InventoryItem inventoryItem : serializedInventoryItems) {
548
                if (inventoryItem.getGoodQuantity() == 1) {
549
                    if (serializedInventoryItemMap.containsKey(inventoryItem.getItemId())) {
550
                        serializedInventoryItemMap.get(inventoryItem.getItemId()).add(inventoryItem);
551
                    } else {
552
                        Set<InventoryItem> itemIdInventoryItems = new HashSet<>();
553
                        itemIdInventoryItems.add(inventoryItem);
554
                        serializedInventoryItemMap.put(inventoryItem.getItemId(), itemIdInventoryItems);
555
                    }
556
                }
557
            }
558
        }
23418 ashik.ali 559
 
32145 tejbeer 560
        if (!nonSerializedItemIds.isEmpty()) {
561
            List<InventoryItem> nonSerializedInventoryItems = inventoryItemRepository.selectByFofoIdItemIds(fofoId, nonSerializedItemIds);
562
            LOGGER.info("nonSerializedInventoryItems {}", nonSerializedInventoryItems);
563
            for (InventoryItem it : nonSerializedInventoryItems) {
564
                if (it.getGoodQuantity() > 0) {
565
                    if (nonSerializedInventoryItemMap.containsKey(it.getItemId())) {
566
                        nonSerializedInventoryItemMap.get(it.getItemId()).add(it);
567
                    } else {
568
                        Set<InventoryItem> tmp = new HashSet<>();
569
                        tmp.add(it);
570
                        nonSerializedInventoryItemMap.put(it.getItemId(), tmp);
571
                    }
572
                }
573
            }
574
        }
23650 amit.gupta 575
 
32145 tejbeer 576
        this.validateItemsSerializedNonSerialized(items, itemIdCustomFofoOrderItemMap);
22859 ashik.ali 577
 
32145 tejbeer 578
        Map<Integer, Set<InventoryItem>> inventoryItemsToBill = new HashMap<>();
579
        Map<Integer, Integer> inventoryItemIdQuantityUsed = new HashMap<>(); // to keep track of inventoryitem quanity
580
        // used for scan records insertion
22859 ashik.ali 581
 
32145 tejbeer 582
        LOGGER.info("itemMap keys {}", itemMap.keySet());
583
        // Lets reduce quantity and decide what inventory items to use.
584
        for (Item item : items) {
585
            if (item.getType().equals(ItemType.SERIALIZED)) {
586
                // TODO:handle null
587
                if (serializedInventoryItemMap.get(item.getId()) == null || itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().size() != serializedInventoryItemMap.get(item.getId()).size()) {
35232 ranu 588
                    LOGGER.info("InsuredModels: {}, and Serialized: {}", insuredModels.size(), itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().size());
589
                    if (itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().size() != insuredModels.size()) {
590
                        List<String> invalidSerialNumbers = itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().stream().map(x -> x.getSerialNumber()).collect(Collectors.toList());
591
                        throw new ProfitMandiBusinessException("invalidSerialNumbers", invalidSerialNumbers, "FFORDR_1004");
592
                    }
32145 tejbeer 593
                }
594
                List<String> serialNumberList = liveDemoBillingRespository.selectAllSerialNumber();
24823 amit.gupta 595
 
32145 tejbeer 596
                Set<InventoryItem> inventoryItemsSerializedserialized = serializedInventoryItemMap.get(item.getId());
597
                for (InventoryItem inventoryItem : inventoryItemsSerializedserialized) {
598
                    inventoryItem.setGoodQuantity(0);
599
                    inventoryItemIdQuantityUsed.put(inventoryItem.getId(), 1);
600
                    if (serialNumberList.contains(inventoryItem.getSerialNumber())) {
601
                        LiveDemoSerialNumber liveDemoSerialNumber = liveDemoBillingRespository.selectBySerialNumber(inventoryItem.getSerialNumber());
602
                        liveDemoBillingRespository.delete(liveDemoSerialNumber);
603
                    }
604
                }
605
                inventoryItemsToBill.put(item.getId(), inventoryItemsSerializedserialized);
606
            } else {
607
                Set<InventoryItem> inventoryItemsNonSerialized = nonSerializedInventoryItemMap.get(item.getId());
608
                int quantityToBill = itemIdCustomFofoOrderItemMap.get(item.getId()).getQuantity();
609
                int totalLeft = quantityToBill;
610
                Set<InventoryItem> inventoryItemsNonSerializedUsed = new HashSet<>();
611
                if (inventoryItemsNonSerialized != null) {
612
                    for (InventoryItem inventoryItem : inventoryItemsNonSerialized) {
613
                        if (totalLeft > 0) {
614
                            int toUse = Math.min(totalLeft, inventoryItem.getGoodQuantity());
615
                            inventoryItemIdQuantityUsed.put(inventoryItem.getId(), toUse);
616
                            inventoryItem.setGoodQuantity(inventoryItem.getGoodQuantity() - toUse);
617
                            totalLeft = totalLeft - toUse;
618
                            inventoryItemsNonSerializedUsed.add(inventoryItem);
619
                        }
620
                    }
621
                }
23650 amit.gupta 622
 
32145 tejbeer 623
                if (totalLeft > 0) {
624
                    // not enough quanity for non-serialized
625
                    LOGGER.error("not enough quanity for non-serialized");
626
                    throw new ProfitMandiBusinessException("notEnoughQuantityForNonSerialized", totalLeft, "FFORDR_1005");
627
                }
628
                inventoryItemsToBill.put(item.getId(), inventoryItemsNonSerializedUsed);
629
            }
630
        }
23650 amit.gupta 631
 
32145 tejbeer 632
        Map<Integer, PriceModel> itemIdMopPriceMap = pricingService.getPurchasePriceMopPriceNotFound(itemIdCustomFofoOrderItemMap.keySet(), fofoId);
633
        LOGGER.info("itemIdMopMap {}", itemIdMopPriceMap);
634
        if (accessoriesDeals) {
32420 amit.gupta 635
            this.validateDpPrice(fofoId, itemIdMopPriceMap, itemIdCustomFofoOrderItemMap);
32145 tejbeer 636
        } else {
32420 amit.gupta 637
            this.validateMopPrice(fofoId, itemIdMopPriceMap, itemIdCustomFofoOrderItemMap);
32145 tejbeer 638
        }
23650 amit.gupta 639
 
32145 tejbeer 640
        String fofoStoreCode = this.getFofoStoreCode(fofoId);
641
        String documentNumber = null;
642
        if (noGST) {
643
            documentNumber = this.getSecurityDepositNumber(fofoId, fofoStoreCode);
24275 amit.gupta 644
 
32145 tejbeer 645
        } else {
646
            documentNumber = this.getInvoiceNumber(fofoId, fofoStoreCode);
647
        }
22859 ashik.ali 648
 
32627 ranu 649
        CustomerAddress customerAddress = null;
650
        if (customCustomer.getCustomerAddressId() != 0) {
651
            customerAddress = customer.getCustomerAddress().stream().filter(x -> x.getId() == customCustomer.getCustomerAddressId()).findFirst().get();
652
        }
34381 vikas.jang 653
        FofoOrder fofoOrder = this.createAndGetFofoOrder(customer.getId(), customCustomer.getGstNumber(), fofoId, documentNumber, totalAmount, customCustomer.getCustomerAddressId(), createOrderRequest.getPoId());
23650 amit.gupta 654
 
32145 tejbeer 655
        this.createPaymentOptions(fofoOrder, createOrderRequest.getPaymentOptions());
23650 amit.gupta 656
 
32145 tejbeer 657
        int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(fofoId);
23650 amit.gupta 658
 
32145 tejbeer 659
        Address retailerAddress = addressRepository.selectById(retailerAddressId);
23650 amit.gupta 660
 
32145 tejbeer 661
        Integer stateId = null;
32634 amit.gupta 662
        if (customerAddress == null || customerAddress.getState() == null || customerAddress.getState().equals(retailerAddress.getState())) {
32145 tejbeer 663
            try {
32634 amit.gupta 664
                State state = stateRepository.selectByName(retailerAddress.getState());
32145 tejbeer 665
                stateId = Long.valueOf(state.getId()).intValue();
666
            } catch (Exception e) {
667
                LOGGER.error("Unable to get state rates");
668
            }
669
        }
23650 amit.gupta 670
 
35493 amit 671
        // N+1 fix: Pre-fetch tagListings and GST rates before the loop
672
        Map<Integer, TagListing> tagListingMap = tagListingRepository.selectByItemIds(itemIdCustomFofoOrderItemMap.keySet());
673
        Map<Integer, GstRate> gstRateMap = null;
674
        if (stateId != null) {
675
            gstRateMap = stateGstRateRepository.getStateTaxRate(new ArrayList<>(itemMap.keySet()), stateId);
676
        } else {
677
            gstRateMap = stateGstRateRepository.getIgstTaxRate(new ArrayList<>(itemMap.keySet()));
678
        }
679
 
32145 tejbeer 680
        for (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {
35493 amit 681
            FofoOrderItem fofoOrderItem = this.createAndGetFofoOrderItem(customFofoOrderItem, fofoOrder.getId(), itemMap, inventoryItemsToBill.get(customFofoOrderItem.getItemId()), tagListingMap, gstRateMap);
23650 amit.gupta 682
 
32816 ranu 683
            Item item = itemMap.get(customFofoOrderItem.getItemId());
684
            if (item.getType().equals(ItemType.NON_SERIALIZED)) {
685
                if (customFofoOrderItem.getCustomSerialNumbers() != null && !customFofoOrderItem.getCustomSerialNumbers().isEmpty()) {
686
                    persistNonSerializedWithCustomSerialNumber(customFofoOrderItem, fofoOrderItem.getId());
687
                } else {
688
                    LOGGER.info("Custom serial numbers are empty. Not persisting data.");
689
                }
690
            }
691
 
692
 
32145 tejbeer 693
            Set<InventoryItem> inventoryItems = inventoryItemsToBill.get(customFofoOrderItem.getItemId());
23650 amit.gupta 694
 
32145 tejbeer 695
            this.createFofoLineItem(fofoOrderItem.getId(), inventoryItems, inventoryItemIdQuantityUsed);
23650 amit.gupta 696
 
32145 tejbeer 697
            this.updateCurrentInventorySnapshot(currentInventorySnapshots, fofoId, customFofoOrderItem.getItemId(), customFofoOrderItem.getQuantity());
23650 amit.gupta 698
 
32145 tejbeer 699
            this.updateInventoryItemsAndScanRecord(inventoryItems, fofoId, inventoryItemIdQuantityUsed, fofoOrder.getId());
700
        }
23650 amit.gupta 701
 
32145 tejbeer 702
        List<FofoOrderItem> fofoItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
25647 tejbeer 703
 
35493 amit 704
        // Use existing itemMap instead of querying DB per item (N+1 fix)
705
        boolean smartPhone = items.stream().anyMatch(Item::isSmartPhone);
706
        if (smartPhone) {
707
            LOGGER.info("Smartphone found in order items");
708
        } else {
32892 ranu 709
            LOGGER.warn("No smartphones found in fofoItems.");
32145 tejbeer 710
        }
31172 tejbeer 711
 
32892 ranu 712
 
32145 tejbeer 713
        if (smartPhone) {
714
            this.createAndGetHygieneData(fofoOrder.getId(), fofoOrder.getFofoId());
715
        }
716
        // insurance calculation is insurance flag is enabled
717
        //
718
        if (insuredModels.size() > 0) {
719
            LOGGER.info("Processing insurane for serialNumbers");
720
            LOGGER.info("InsuranceModels {}", insuredModels);
721
            LocalDate customerDateOfBirth = LocalDate.from(createOrderRequest.getCustomer().getDateOfBirth());
722
            fofoOrder.setDateOfBirth(customerDateOfBirth);
723
            for (InsuranceModel insuranceModel : insuredModels) {
34207 ranu 724
                LOGGER.info("G- {}", insuranceModel.getInsuranceId());
725
                LOGGER.info("insuranceModel- {}", insuranceModel);
33715 ranu 726
                insuranceService.createInsurance(fofoOrder, insuranceModel, false);
32145 tejbeer 727
            }
728
        }
28339 tejbeer 729
 
32145 tejbeer 730
        schemeService.processSchemeOut(fofoOrder.getId(), fofoId);
31993 amit.gupta 731
 
32145 tejbeer 732
        if (createOrderRequest.getPoId() != 0) {
733
            PendingOrder po = pendingOrderRepository.selectById(createOrderRequest.getPoId());
734
            po.setBilledAmount(po.getBilledAmount() + totalAmount);
35493 amit 735
 
736
            // N+1 fix: Batch fetch pending order items instead of querying per item
737
            List<Integer> poiIds = createOrderRequest.getFofoOrderItems().stream()
738
                    .map(CustomFofoOrderItem::getPoiId)
739
                    .filter(id -> id != 0)
740
                    .collect(Collectors.toList());
741
            if (!poiIds.isEmpty()) {
742
                List<PendingOrderItem> pendingOrderItems = pendingOrderItemRepository.selectByIds(poiIds);
743
                LocalDateTime now = LocalDateTime.now();
744
                for (PendingOrderItem poi : pendingOrderItems) {
745
                    poi.setStatus(OrderStatus.BILLED);
746
                    poi.setBilledTimestamp(now);
747
                }
33399 ranu 748
            }
35493 amit 749
 
33436 ranu 750
            po.setStatus(OrderStatus.BILLED);
32145 tejbeer 751
        }
32961 amit.gupta 752
        //Process scratch
753
        this.processScratchOffer(fofoOrder);
29515 tejbeer 754
 
33795 ranu 755
//        persist the data of upgrade offer table
756
        for (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {
34805 ranu 757
            if (customFofoOrderItem.getCustomerOfferItemId().size() > 0) {
758
                for (Integer customerOfferItemId : customFofoOrderItem.getCustomerOfferItemId()) {
759
                    UpgradeOffer upgradeOffer = new UpgradeOffer();
760
                    upgradeOffer.setOrderId(fofoOrder.getId());
761
                    upgradeOffer.setCustomerOfferItemId(customerOfferItemId);
762
                    upgradeOffer.setItemId(customFofoOrderItem.getItemId());
33795 ranu 763
 
34805 ranu 764
                    Set<SerialNumberDetail> serialNumberDetails = customFofoOrderItem.getSerialNumberDetails();
33795 ranu 765
 
34805 ranu 766
                    if (!customFofoOrderItem.getSerialNumberDetails().isEmpty()) {
767
                        String serialNumber = serialNumberDetails.iterator().next().getSerialNumber();
768
                        upgradeOffer.setSerialNumber(serialNumber);
33795 ranu 769
 
34805 ranu 770
                        //                Set<String> serialNumbersSet = this.serialNumberDetailsToSerialNumbers(customFofoOrderItem.getSerialNumberDetails());
771
                        //                LOGGER.info("serialNumbersSet.toString() {}",serialNumbersSet.toString());
772
                        //                upgradeOffer.setSerialNumber(serialNumbersSet.toString());
773
                    } else {
774
                        upgradeOffer.setSerialNumber(null); // Handle case where there is no serial number detail
775
                    }
776
                    upgradeOffer.setCreatedTimestamp(LocalDateTime.now());
777
                    upgradeOffer.setPaymentStatus(UpgradeOfferPaymentStatus.PENDING);
778
                    upgradeOffer.setStatusDescription(UpgradeOfferPaymentStatus.PENDING.getValue());
779
                    upgradeOfferRepository.persist(upgradeOffer);
33795 ranu 780
                }
34805 ranu 781
 
33795 ranu 782
            }
783
        }
784
 
35493 amit 785
//        enable it fo upsell call - N+1 fix: smartPhone already determined, no need to re-query items
786
        if (smartPhone && fofoOrder.getId() > 0) {
787
            List<InsurancePolicy> insurancePolicies = insurancePolicyRepository
788
                    .selectByRetailerIdInvoiceNumber(fofoOrder.getInvoiceNumber());
789
            if (insurancePolicies.isEmpty()) {
790
                UpSaleOrder upSaleOrder = new UpSaleOrder();
791
                upSaleOrder.setCreatedTimestamp(LocalDateTime.now());
792
                upSaleOrder.setOrderId(fofoOrder.getId());
793
                upSaleOrder.setFofoId(fofoOrder.getFofoId());
794
                upSaleOrderRepository.persist(upSaleOrder);
33715 ranu 795
            }
796
        }
33674 ranu 797
 
35493 amit 798
        // Update Partner Opening Stock current qty - N+1 fix: use existing itemMap and batch update
33899 ranu 799
        if (fofoOrder.getId() > 0) {
35493 amit 800
            Map<Integer, Integer> itemIdQuantityMap = new HashMap<>();
801
            for (FofoOrderItem fofoOrderItem : fofoItems) {
802
                itemIdQuantityMap.merge(fofoOrderItem.getItemId(), fofoOrderItem.getQuantity(), Integer::sum);
33873 ranu 803
            }
35493 amit 804
            smartCartService.minusOpeningStockBatch(itemIdQuantityMap, fofoOrder.getFofoId());
33873 ranu 805
        }
806
 
807
 
32961 amit.gupta 808
        return fofoOrder.getId();
809
    }
810
 
33665 ranu 811
    @Override
812
    public void processScratchOffer(FofoOrder fofoOrder) throws ProfitMandiBusinessException {
813
        boolean isSmartPhonePurchased = false;
814
        float maxPurchaseValue = 0;
815
        List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
35493 amit 816
 
817
        // N+1 fix: batch fetch all items instead of querying per order item
818
        Set<Integer> itemIds = fofoOrderItems.stream()
819
                .map(FofoOrderItem::getItemId)
820
                .collect(Collectors.toSet());
821
        Map<Integer, Item> itemMap = itemRepository.selectByIds(itemIds).stream()
822
                .collect(Collectors.toMap(Item::getId, item -> item));
823
 
33665 ranu 824
        for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
35493 amit 825
            Item item = itemMap.get(fofoOrderItem.getItemId());
33665 ranu 826
 
35493 amit 827
            if (item != null && item.isSmartPhone()) {
33665 ranu 828
                LOGGER.info("fofoItem {}", fofoOrderItem);
829
                isSmartPhonePurchased = true;
830
                maxPurchaseValue = Math.max(fofoOrderItem.getSellingPrice(), maxPurchaseValue);
831
            }
832
        }
833
        LocalDate startDate = ProfitMandiConstants.SCRATCH_OFFER_START_DATE;
834
        LocalDate endDate = ProfitMandiConstants.SCRATCH_OFFER_END_DATE;
835
        boolean specificPriceOffer = ProfitMandiConstants.SPECIFIC_PRICE_OFFER;
836
        boolean randomOffer = ProfitMandiConstants.RANDOM_OFFER;
837
 
838
        if (isSmartPhonePurchased) {
839
 
840
            if (LocalDateTime.now().isAfter(startDate.atStartOfDay()) && LocalDateTime.now().isBefore(endDate.atTime(Utils.MAX_TIME))) {
841
                Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());
842
                try {
843
                    this.sendAppDownloadBillingOffer(customer.getMobileNumber());
844
                } catch (Exception e) {
845
                    // TODO Auto-generated catch block
846
                    e.printStackTrace();
847
                }
848
                if (specificPriceOffer) {
33899 ranu 849
                    this.createSpecificPriceScratchOffer(fofoOrder.getInvoiceNumber(), fofoOrder.getCustomerId(), fofoOrder.getFofoId(), maxPurchaseValue);
33665 ranu 850
                } else if (randomOffer) {
851
                    this.createRandomScratchOffer(fofoOrder.getInvoiceNumber(), fofoOrder.getCustomerId());
852
                    LOGGER.info("randomOffer {}", randomOffer);
853
                } else {
854
                    this.createScratchOffer(fofoOrder.getFofoId(), fofoOrder.getInvoiceNumber(), fofoOrder.getCustomerId());
855
                }
856
 
857
            }
858
        }
859
    }
860
 
861
    @Override
33899 ranu 862
    public ScratchedGift getSelectedGift(double purchaseAmount, int fofoId) throws ProfitMandiBusinessException {
34351 ranu 863
        Map<ScratchedGift, Long> scratchOfferCountMap = scratchOfferRepository.countOffersByDateRange(
864
                ProfitMandiConstants.SCRATCH_OFFER_START_DATE, ProfitMandiConstants.SCRATCH_OFFER_END_DATE
865
        );
866
        LOGGER.info("scratchOfferCountMap {}", scratchOfferCountMap);
867
 
868
        LocalDateTime startDateTime = ProfitMandiConstants.SCRATCH_OFFER_START_DATE.atStartOfDay();
34365 ranu 869
        LocalDateTime endDateTime = ProfitMandiConstants.SCRATCH_OFFER_START_DATE.atTime(LocalTime.MAX);
34351 ranu 870
 
34365 ranu 871
        LOGGER.info("start date {}", startDateTime);
872
        LOGGER.info("end date {}", endDateTime);
873
 
33899 ranu 874
        RandomCollection<ScratchedGift> giftRandomCollection = createDynamicGiftSeries(scratchOfferCountMap, purchaseAmount, fofoId);
34351 ranu 875
 
33665 ranu 876
        if (giftRandomCollection.size() > 0) {
34340 ranu 877
            ScratchedGift selectedGift = giftRandomCollection.next();
878
 
34353 ranu 879
            // Ensure one LED for 175139615 and one Oven for 175139583
34351 ranu 880
            if (selectedGift == ScratchedGift.LED || selectedGift == ScratchedGift.MICROWAVE_OVEN) {
34340 ranu 881
                if (!PREMIUM_ELIGIBLE_PARTNERS.contains(fofoId)) {
882
                    LOGGER.info("Partner {} not eligible for {}", fofoId, selectedGift);
34351 ranu 883
                    return ScratchedGift.ACCESSORIES_50_PERCENT_OFF; // Default alternate gift
34340 ranu 884
                }
885
 
34351 ranu 886
                // Restrict LED to Partner 175139615 and Oven to Partner 175139583
887
                if ((selectedGift == ScratchedGift.LED && fofoId != 175139615) ||
888
                        (selectedGift == ScratchedGift.MICROWAVE_OVEN && fofoId != 175139583)) {
889
                    LOGGER.info("Partner {} not eligible for {}", fofoId, selectedGift);
890
                    return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;
891
                }
892
 
34340 ranu 893
                // Ensure only one LED and one Microwave Oven per day
34351 ranu 894
                long ledCount = scratchOfferCountMap.getOrDefault(ScratchedGift.LED, 0L);
895
                long ovenCount = scratchOfferCountMap.getOrDefault(ScratchedGift.MICROWAVE_OVEN, 0L);
896
                if ((selectedGift == ScratchedGift.LED || selectedGift == ScratchedGift.MICROWAVE_OVEN)
897
                        && (ledCount > 0 && ovenCount > 0)) {
898
                    LOGGER.info("Both LED and Microwave Oven already given today.");
34340 ranu 899
                    return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;
900
                }
34354 ranu 901
 
902
                if ((selectedGift == ScratchedGift.LED && ledCount > 0)) {
903
                    LOGGER.info("LED already given today.");
904
                    return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;
905
                }
34367 ranu 906
 
907
                if ((selectedGift == ScratchedGift.LED)) {
908
                    LOGGER.info("LED already given today.");
909
                    return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;
910
                }
911
 
34354 ranu 912
                if ((selectedGift == ScratchedGift.MICROWAVE_OVEN && ovenCount > 0)) {
913
                    LOGGER.info("Oven already given today.");
914
                    return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;
915
                }
34340 ranu 916
            }
917
 
34353 ranu 918
            //  Ensure only one Neckband per partner per day
34351 ranu 919
            if (selectedGift == ScratchedGift.NECK_BAND) {
920
                List<FofoOrder> fofoOrders = fofoOrderRepository.selectByFofoId(fofoId, startDateTime, endDateTime, 0, 0);
921
                List<String> invoiceNumbers = fofoOrders.stream().map(FofoOrder::getInvoiceNumber).collect(Collectors.toList());
922
                List<ScratchOffer> offers = scratchOfferRepository.selectByInvoiceNumbers(invoiceNumbers);
923
                LOGGER.info("offers for partner {}", offers);
34340 ranu 924
 
34474 aman.kumar 925
                boolean neckbandGivenToday = offers.stream().anyMatch(offer -> offer.getOfferName().equals(ScratchedGift.NECK_BAND));
34351 ranu 926
                if (neckbandGivenToday) {
927
                    LOGGER.info("Neckband already given today for partner {}", fofoId);
34340 ranu 928
                    return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;
929
                }
930
            }
931
 
932
            return selectedGift;
33665 ranu 933
        }
34351 ranu 934
 
935
        return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;
33665 ranu 936
    }
937
 
34340 ranu 938
 
34351 ranu 939
    public RandomCollection<ScratchedGift> createDynamicGiftSeries(Map<ScratchedGift, Long> soldGiftContMap, Double sellingPrice, int fofoId) throws ProfitMandiBusinessException {
33665 ranu 940
        int index = 0;
941
        RandomCollection<ScratchedGift> randomCollection = new RandomCollection<>();
33899 ranu 942
        PartnerType partnerType = partnerTypeChangeService.getTypeOnDate(fofoId, LocalDate.now());
943
        LOGGER.info("partnerType {}", partnerType);
944
 
33895 ranu 945
        if (partnerType.equals(PartnerType.BRONZE)) {
33899 ranu 946
            LOGGER.info("partnerType if- {}", partnerType);
33895 ranu 947
            sellingPrice = 0.0;
948
        }
33899 ranu 949
 
950
        for (int i = 0; i < PRICE_RANGE.size(); i++) {
951
            Double price = PRICE_RANGE.get(i);
34351 ranu 952
            Double nextPrice = Double.MAX_VALUE;
953
            if (i != PRICE_RANGE.size() - 1) {
954
                nextPrice = PRICE_RANGE.get(i + 1);
955
            }
33899 ranu 956
            if (sellingPrice >= price && sellingPrice < nextPrice) {
33665 ranu 957
                int divisor = PRICE_RANGE.size() - index;
33899 ranu 958
                LOGGER.info("Processing price range: {}, sellingPrice: {}", price, sellingPrice);
959
 
33665 ranu 960
                for (ScratchedGift gift : GIFT_SERIES.get(price)) {
34351 ranu 961
                    int remainingQty = GIFT_QUANTITIES.get(gift) - soldGiftContMap.getOrDefault(gift, 0L).intValue();
33899 ranu 962
                    LOGGER.info("Checking gift: {}, remainingQty: {}", gift, remainingQty);
963
 
33897 ranu 964
                    if (remainingQty > 0) {
965
                        int weight = (remainingQty > divisor) ? remainingQty / divisor : remainingQty;
34351 ranu 966
                        randomCollection.add(weight, gift);
967
                        LOGGER.info("Added gift: {}, weight: {}", gift, weight);
33665 ranu 968
                    }
969
                }
34351 ranu 970
                break; // Exit the loop once the correct price range is processed
33665 ranu 971
            }
33897 ranu 972
            index++;
33665 ranu 973
        }
33899 ranu 974
 
34351 ranu 975
        // If no gifts were added, log and handle potential issues here
33899 ranu 976
        if (randomCollection.size() == 0) {
977
            LOGGER.info("No gifts added for sellingPrice: {} in createDynamicGiftSeries", sellingPrice);
978
        }
979
 
34351 ranu 980
        LOGGER.info("randomCollectionSize {}, partnerType {}, sellingPrice {}", randomCollection.size(), partnerType, sellingPrice);
33665 ranu 981
        return randomCollection;
982
    }
983
 
33899 ranu 984
 
985
 
33665 ranu 986
    /*static {
32960 amit.gupta 987
        RandomCollection<ScratchedGift> map1 = new RandomCollection<ScratchedGift>().
988
                add(100d, ScratchedGift.GIFT_BOWL);
989
        GIFT_SERIES.put(0.0, map1);
990
        //Map<ScratchedGift, Double> map2 = new HashMap<>();
991
        RandomCollection<ScratchedGift> map2 = new RandomCollection<ScratchedGift>()
992
                .add(40d, ScratchedGift.GIFT_BOWL)
993
                .add(20d, ScratchedGift.NECK_BAND)
994
                .add(30d, ScratchedGift.FLASKNMUG)
995
                .add(10d, ScratchedGift.ELECTRIC_KETTLE);
996
        GIFT_SERIES.put(10001.0, map2);
997
        RandomCollection<ScratchedGift> map3 = new RandomCollection<ScratchedGift>()
998
                .add(25d, ScratchedGift.GIFT_BOWL)
999
                .add(30d, ScratchedGift.NECK_BAND)
1000
                .add(10d, ScratchedGift.SPEAKER)
1001
                .add(25d, ScratchedGift.FLASKNMUG)
1002
                .add(10d, ScratchedGift.ELECTRIC_KETTLE);
1003
        GIFT_SERIES.put(18001.0, map3);
1004
        RandomCollection<ScratchedGift> map4 = new RandomCollection<ScratchedGift>()
1005
                .add(30d, ScratchedGift.NECK_BAND)
1006
                .add(20d, ScratchedGift.SPEAKER)
1007
                .add(20d, ScratchedGift.FLASKNMUG)
1008
                .add(30d, ScratchedGift.ELECTRIC_KETTLE);
1009
        GIFT_SERIES.put(25001.0, map4);
1010
        RandomCollection<ScratchedGift> map5 = new RandomCollection<ScratchedGift>()
1011
                .add(40d, ScratchedGift.SPEAKER)
1012
                .add(60d, ScratchedGift.SMART_WATCH);
32892 ranu 1013
 
32960 amit.gupta 1014
        GIFT_SERIES.put(50001.0, map5);
33665 ranu 1015
    }*/
32892 ranu 1016
 
32960 amit.gupta 1017
 
33895 ranu 1018
    private void createSpecificPriceScratchOffer(String invoiceNumber, int customerId, int fofoId, float purchaseAmount) throws ProfitMandiBusinessException {
33899 ranu 1019
        ScratchedGift selectedGift = getSelectedGift(purchaseAmount, fofoId);
33142 ranu 1020
        List<ScratchOffer> scratchOffers = scratchOfferRepository.selectBycCustomerIdAndDate(customerId, ProfitMandiConstants.SCRATCH_OFFER_START_DATE, ProfitMandiConstants.SCRATCH_OFFER_END_DATE);
1021
        if (scratchOffers.size() == 0) {
1022
            ScratchOffer so2 = new ScratchOffer();
1023
            so2.setInvoiceNumber(invoiceNumber);
1024
            so2.setScratched(false);
1025
            so2.setCreatedTimestamp(LocalDateTime.now());
33679 ranu 1026
            so2.setExpiredTimestamp(ProfitMandiConstants.SCRATCH_OFFER_END_DATE.plusDays(1).atTime(LocalTime.MAX));
34474 aman.kumar 1027
            so2.setOfferName(String.valueOf(selectedGift));
33142 ranu 1028
            so2.setCustomerId(customerId);
1029
            so2.setUnlockedAt(LocalDateTime.now());
1030
            scratchOfferRepository.persist(so2);
1031
        }
1032
    }
32960 amit.gupta 1033
 
33142 ranu 1034
    private void createRandomScratchOffer(String invoiceNumber, int customerId) {
1035
        ScratchedGift selectedGift = getScratchedGiftRandomAccordingQuantity(customerId);
32892 ranu 1036
        List<ScratchOffer> scratchOffers = scratchOfferRepository.selectBycCustomerIdAndDate(customerId, ProfitMandiConstants.SCRATCH_OFFER_START_DATE, ProfitMandiConstants.SCRATCH_OFFER_END_DATE);
1037
        if (scratchOffers.size() == 0) {
1038
            ScratchOffer so2 = new ScratchOffer();
1039
            so2.setInvoiceNumber(invoiceNumber);
1040
            so2.setScratched(false);
1041
            so2.setCreatedTimestamp(LocalDateTime.now());
33679 ranu 1042
            so2.setExpiredTimestamp(ProfitMandiConstants.SCRATCH_OFFER_END_DATE.plusDays(1).atTime(LocalTime.MAX));
34474 aman.kumar 1043
            so2.setOfferName(String.valueOf(selectedGift));
32892 ranu 1044
            so2.setCustomerId(customerId);
1045
            so2.setUnlockedAt(LocalDateTime.now());
1046
            scratchOfferRepository.persist(so2);
1047
        }
1048
    }
1049
 
33247 ranu 1050
    private ScratchedGift getScratchedGiftRandom(int fofoId, int customerId) throws ProfitMandiBusinessException {
32218 tejbeer 1051
        Map<Integer, ScratchedGift> giftSeries = new HashMap<>();
1052
        giftSeries.put(1, ScratchedGift.MINI_CHOPPER);
1053
        giftSeries.put(2, ScratchedGift.FRUIT_JUICER);
1054
        giftSeries.put(3, ScratchedGift.STEAM_IRON);
1055
 
1056
 
32579 amit.gupta 1057
        List<FofoOrder> fofoOrders = fofoOrderRepository.selectByFofoIdBetweenCreatedTimeStamp(fofoId, ProfitMandiConstants.SCRATCH_OFFER_START_DATE.atStartOfDay(),
1058
                ProfitMandiConstants.SCRATCH_OFFER_END_DATE.atTime(Utils.MAX_TIME));
32218 tejbeer 1059
 
1060
        ScratchedGift gift = ScratchedGift.BLNT;
1061
 
1062
        Random random = new Random();
32672 amit.gupta 1063
        int rand;
32218 tejbeer 1064
        while (true) {
1065
            rand = random.nextInt(4);
1066
            if (rand != 0) break;
1067
        }
1068
        if (fofoOrders.isEmpty()) {
1069
            gift = giftSeries.get(rand);
1070
        } else {
1071
 
1072
            List<String> invoiceNumbers = fofoOrders.stream().filter(x -> x.getCancelledTimestamp() == null).map(x -> x.getInvoiceNumber()).collect(Collectors.toList());
1073
 
1074
            List<ScratchOffer> scratchOffers = scratchOfferRepository.selectByInvoiceNumbers(invoiceNumbers);
1075
            if (scratchOffers.isEmpty()) {
1076
                gift = giftSeries.get(rand);
1077
            } else {
1078
                List<ScratchOffer> bigGifts = scratchOffers.stream().filter(x -> !x.getOfferName().equals(ScratchedGift.BLNT) && !x.getOfferName().equals(ScratchedGift.EW)).collect(Collectors.toList());
1079
                if (bigGifts.size() <= 10) {
1080
                    List<Integer> scratchCustomerIds = scratchOffers.stream().map(x -> x.getCustomerId()).collect(Collectors.toList());
1081
                    if (scratchCustomerIds.contains(customerId)) {
1082
 
1083
 
1084
                        gift = ScratchedGift.BLNT;
1085
 
1086
                        LOGGER.info("gift2 {}", gift);
1087
 
1088
                    } else {
1089
 
1090
                        int miniChopper = (int) bigGifts.stream().filter(x -> x.getOfferName().equals(ScratchedGift.MINI_CHOPPER)).count();
1091
                        int fruitJuicer = (int) bigGifts.stream().filter(x -> x.getOfferName().equals(ScratchedGift.FRUIT_JUICER)).count();
1092
                        int streanIron = (int) bigGifts.stream().filter(x -> x.getOfferName().equals(ScratchedGift.STEAM_IRON)).count();
1093
 
1094
                        if (rand == 1) {
1095
                            if (miniChopper < 4) {
1096
                                LOGGER.info("miniChopper {}", miniChopper);
1097
 
1098
 
1099
                                gift = giftSeries.get(rand);
1100
                            }
1101
                        }
1102
 
1103
                        if (rand == 2) {
1104
                            if (fruitJuicer < 3) {
1105
 
1106
                                LOGGER.info("fruitJuicer {}", fruitJuicer);
1107
 
1108
                                gift = giftSeries.get(rand);
1109
                            }
1110
                        }
1111
 
1112
                        if (rand == 3) {
1113
                            if (streanIron < 3) {
1114
 
1115
                                LOGGER.info("streanIron {}", streanIron);
1116
 
1117
 
1118
                                gift = giftSeries.get(rand);
1119
 
1120
                            }
1121
                        }
1122
 
1123
                        LOGGER.info("gift4 {}", gift);
1124
                    }
1125
                }
1126
            }
1127
 
1128
 
1129
        }
32586 ranu 1130
        return gift;
32145 tejbeer 1131
    }
29515 tejbeer 1132
 
33142 ranu 1133
    private ScratchedGift getScratchedGiftRandomAccordingQuantity(int customerId) {
1134
        RandomCollection<ScratchedGift> map1 = new RandomCollection<ScratchedGift>().
1135
                add(50d, ScratchedGift.SOLOR_LAMP)
1136
                .add(100d, ScratchedGift.BLUETOOTH_SPEAKER)
1137
                .add(150d, ScratchedGift.RED_WATER_BOTTLE)
1138
                .add(200d, ScratchedGift.GIFT_BOWL)
1139
                .add(100d, ScratchedGift.EARBUDS);
1140
 
33665 ranu 1141
        ScratchedGift gift;
33142 ranu 1142
 
33665 ranu 1143
        List<ScratchOffer> lastScratchOffers = scratchOfferRepository.selectBycCustomerIdAndDate(customerId, ProfitMandiConstants.LAST_SCRATCH_OFFER_START_DATE, ProfitMandiConstants.LAST_SCRATCH_OFFER_END_DATE);
1144
 
1145
        if (lastScratchOffers.isEmpty()) {
1146
            gift = map1.next();
1147
        } else {
1148
            gift = ScratchedGift.RED_WATER_BOTTLE;
1149
            LOGGER.info("RED_WATER_BOTTLE {}", gift);
33142 ranu 1150
        }
1151
        return gift;
1152
    }
1153
 
32145 tejbeer 1154
    private HygieneData createAndGetHygieneData(int id, int fofoId) {
1155
        HygieneData hygieneData = new HygieneData();
1156
        hygieneData.setOrderId(id);
1157
        hygieneData.setFofoId(fofoId);
1158
        hygieneData.setCreatedTimestamp(LocalDateTime.now());
1159
        hygieneDataRepository.persist(hygieneData);
25640 tejbeer 1160
 
32145 tejbeer 1161
        return hygieneData;
1162
    }
25640 tejbeer 1163
 
33665 ranu 1164
 
32145 tejbeer 1165
    @Override
1166
    public String getInvoiceNumber(int fofoId, String fofoStoreCode) {
1167
        InvoiceNumberGenerationSequence invoiceNumberGenerationSequence = null;
1168
        try {
1169
            invoiceNumberGenerationSequence = invoiceNumberGenerationSequenceRepository.selectByFofoId(fofoId);
1170
            invoiceNumberGenerationSequence.setSequence(invoiceNumberGenerationSequence.getSequence() + 1);
1171
        } catch (ProfitMandiBusinessException profitMandiBusinessException) {
1172
            invoiceNumberGenerationSequence = new InvoiceNumberGenerationSequence();
1173
            invoiceNumberGenerationSequence.setFofoId(fofoId);
1174
            invoiceNumberGenerationSequence.setPrefix(fofoStoreCode);
1175
            invoiceNumberGenerationSequence.setSequence(1);
1176
        }
1177
        invoiceNumberGenerationSequenceRepository.persist(invoiceNumberGenerationSequence);
1178
        return invoiceNumberGenerationSequence.getPrefix() + "/" + invoiceNumberGenerationSequence.getSequence();
1179
    }
24275 amit.gupta 1180
 
32145 tejbeer 1181
    private String getSecurityDepositNumber(int fofoId, String fofoStoreCode) {
1182
        InvoiceNumberGenerationSequence invoiceNumberGenerationSequence = null;
1183
        try {
1184
            invoiceNumberGenerationSequence = invoiceNumberGenerationSequenceRepository.selectByFofoId(fofoId);
1185
            invoiceNumberGenerationSequence.setChallanNumberSequence(invoiceNumberGenerationSequence.getChallanNumberSequence() + 1);
1186
        } catch (ProfitMandiBusinessException profitMandiBusinessException) {
1187
            invoiceNumberGenerationSequence = new InvoiceNumberGenerationSequence();
1188
            invoiceNumberGenerationSequence.setFofoId(fofoId);
1189
            invoiceNumberGenerationSequence.setPrefix(fofoStoreCode);
1190
            invoiceNumberGenerationSequence.setChallanNumberSequence(1);
1191
        }
1192
        invoiceNumberGenerationSequenceRepository.persist(invoiceNumberGenerationSequence);
1193
        return invoiceNumberGenerationSequence.getPrefix() + "/SEC" + invoiceNumberGenerationSequence.getChallanNumberSequence();
1194
    }
24226 amit.gupta 1195
 
32145 tejbeer 1196
    private Set<String> serialNumberDetailsToSerialNumbers(Set<SerialNumberDetail> serialNumberDetails) {
1197
        Set<String> serialNumbers = new HashSet<>();
1198
        for (SerialNumberDetail serialNumberDetail : serialNumberDetails) {
1199
            if (serialNumberDetail.getSerialNumber() != null && !serialNumberDetail.getSerialNumber().isEmpty()) {
1200
                serialNumbers.add(serialNumberDetail.getSerialNumber());
1201
            }
1202
        }
1203
        return serialNumbers;
1204
    }
23650 amit.gupta 1205
 
32145 tejbeer 1206
    @Override
1207
    public InvoicePdfModel getInvoicePdfModel(int orderId) throws ProfitMandiBusinessException {
1208
        FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(orderId);
1209
        return this.getInvoicePdfModel(fofoOrder);
1210
    }
23650 amit.gupta 1211
 
32145 tejbeer 1212
    @Override
1213
    @Cacheable(value = "order.dummymodel", cacheManager = "oneDayCacheManager")
1214
    public InvoicePdfModel getDummyPdfModel(String serialNumber) throws ProfitMandiBusinessException {
1215
        List<WarehouseInventoryItem> warehouseInventoryItems = warehouseInventoryItemRepository.selectWarehouseInventoryItemBySerailNumbers(Arrays.asList(serialNumber));
1216
        if (warehouseInventoryItems.size() > 0) {
1217
            WarehouseInventoryItem warehouseInventoryItem = warehouseInventoryItems.get(0);
1218
            int currentQuantity = warehouseInventoryItems.get(0).getCurrentQuantity();
1219
            if (currentQuantity > 0) {
1220
                throw new ProfitMandiBusinessException("Serial Number", serialNumber, "Serial Number exist in our warehouse");
1221
            } else {
1222
                try {
1223
                    InventoryItem inventoryItem = inventoryItemRepository.selectBySerialNumber(serialNumber);
1224
                    if (inventoryItem.getGoodQuantity() > 0) {
1225
                        throw new ProfitMandiBusinessException("Serial Number", serialNumber, "Serial Number is not yet billed by the partner");
1226
                    } else {
1227
                        List<ScanRecord> scanRecords = scanRecordRepository.selectByInventoryItemId(inventoryItem.getId());
1228
                        Optional<ScanRecord> scanRecord = scanRecords.stream().filter(x -> x.getOrderId() != 0).findFirst();
1229
                        if (scanRecord.isPresent()) {
1230
                            FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(scanRecord.get().getOrderId());
1231
                            orderIdsConsumed.add(fofoOrder.getId());
1232
                            return this.getInvoicePdfModel(fofoOrder);
1233
                        } else {
1234
                            throw new ProfitMandiBusinessException("Serial Number", serialNumber, "Serial Number returned by partner, but in transit");
1235
                        }
1236
                    }
1237
                } catch (Exception e) {
1238
                    int itemId = warehouseInventoryItem.getItemId();
1239
                    if (serialNumberOrderIdMap.containsKey(serialNumber)) {
1240
                        FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(serialNumberOrderIdMap.get(serialNumber));
1241
                        InvoicePdfModel pdfModel = this.getInvoicePdfModel(fofoOrder.getId());
1242
                        this.modifyDummyModel(fofoOrder, pdfModel, itemId, serialNumber);
1243
                        return pdfModel;
1244
                    }
1245
                    // Map this serialNumber for dummy billing
1246
                    LocalDateTime grnDate = warehouseInventoryItem.getCreated();
1247
                    Random random = new Random();
1248
                    int randomDays = random.ints(2, 15).findFirst().getAsInt();
1249
                    LocalDateTime saleDate = grnDate.plusDays(randomDays);
1250
                    if (saleDate.isAfter(LocalDate.now().atStartOfDay())) {
1251
                        saleDate = LocalDateTime.now().minusDays(2);
1252
                    }
1253
                    Random offsetRandom = new Random();
1254
                    int offset = offsetRandom.ints(2, 100).findFirst().getAsInt();
1255
                    FofoOrder fofoOrder = fofoOrderRepository.selectFirstOrderAfterDate(saleDate, offset);
1256
                    while (orderIdsConsumed.contains(fofoOrder.getId())) {
1257
                        Random offsetRandom2 = new Random();
1258
                        int offset2 = offsetRandom2.ints(2, 100).findFirst().getAsInt();
1259
                        FofoOrder fofoOrder2 = fofoOrderRepository.selectFirstOrderAfterDate(saleDate, offset2);
1260
                        if (fofoOrder2 != null) {
1261
                            fofoOrder = fofoOrder2;
1262
                        }
1263
                    }
1264
                    InvoicePdfModel pdfModel = this.getInvoicePdfModel(fofoOrder.getId());
1265
                    orderIdsConsumed.add(fofoOrder.getId());
1266
                    this.modifyDummyModel(fofoOrder, pdfModel, itemId, serialNumber);
1267
                    return pdfModel;
27516 amit.gupta 1268
 
32145 tejbeer 1269
                }
1270
            }
1271
        } else {
1272
            throw new ProfitMandiBusinessException("Serial Number", serialNumber, "Serial Number does not exist in our warehouse");
1273
        }
1274
    }
27516 amit.gupta 1275
 
33665 ranu 1276
    void modifyDummyModel(FofoOrder fofoOrder, InvoicePdfModel pdfModel, int itemId, String serialNumber) throws
1277
            ProfitMandiBusinessException {
28166 tejbeer 1278
 
32145 tejbeer 1279
        int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(fofoOrder.getFofoId());
27516 amit.gupta 1280
 
32145 tejbeer 1281
        Address retailerAddress = addressRepository.selectById(retailerAddressId);
1282
        Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());
27516 amit.gupta 1283
 
32145 tejbeer 1284
        CustomerAddress customerAddress = customer.getCustomerAddress().stream().filter(x -> x.getId() == fofoOrder.getCustomerAddressId()).findFirst().get();
27516 amit.gupta 1285
 
32145 tejbeer 1286
        Integer stateId = null;
1287
        if (customerAddress.getState().equals(retailerAddress.getState())) {
1288
            try {
1289
                // stateId =
1290
                // Long.valueOf(Utils.getStateInfo(customerAddress.getState()).getId()).intValue();
30527 tejbeer 1291
 
32145 tejbeer 1292
                stateId = Long.valueOf(stateRepository.selectByName(customerAddress.getState()).getId()).intValue();
1293
            } catch (Exception e) {
1294
                LOGGER.error("Unable to get state rates");
1295
            }
1296
        }
1297
        CustomOrderItem cli = pdfModel.getOrderItems().stream().findFirst().get();
1298
        List<FofoOrderItem> fofoOrderItems = Arrays.asList(this.getDummyFofoOrderItem(itemId, fofoOrder.getId(), serialNumber, stateId));
1299
        pdfModel.setPaymentOptions(pdfModel.getPaymentOptions().stream().limit(1).collect(Collectors.toList()));
1300
        CustomPaymentOption paymentOption = pdfModel.getPaymentOptions().get(0);
1301
        paymentOption.setAmount(fofoOrderItems.get(0).getMop());
33298 amit.gupta 1302
        List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>();
32145 tejbeer 1303
        for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
1304
            CustomOrderItem customFofoOrderItem = new CustomOrderItem();
1305
            float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();
1306
            float taxableSellingPrice = fofoOrderItem.getSellingPrice() / (1 + totalTaxRate / 100);
1307
            float taxableDiscountPrice = fofoOrderItem.getDiscount() / (1 + totalTaxRate / 100);
27516 amit.gupta 1308
 
32145 tejbeer 1309
            customFofoOrderItem.setAmount(fofoOrderItem.getQuantity() * (taxableSellingPrice - taxableDiscountPrice));
1310
            customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());
1311
            Set<String> serialNumbers = this.toSerialNumbers(fofoOrderItem.getFofoLineItems());
1312
            // LOGGER.info("serialNumbers {}", serialNumbers);
1313
            // LOGGER.info("serialNumbers is empty {}", serialNumbers.isEmpty());
1314
            if (!serialNumbers.isEmpty()) {
1315
                customFofoOrderItem.setDescription(
1316
                        customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));
1317
            }
1318
            customFofoOrderItem.setRate(taxableSellingPrice);
1319
            customFofoOrderItem.setDiscount(taxableDiscountPrice);
1320
            customFofoOrderItem.setQuantity(fofoOrderItem.getQuantity());
1321
            customFofoOrderItem.setNetAmount(
1322
                    (fofoOrderItem.getSellingPrice() - fofoOrderItem.getDiscount()) * fofoOrderItem.getQuantity());
1323
            float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;
1324
            float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;
1325
            float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;
1326
            customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());
1327
            customFofoOrderItem.setIgstAmount(igstAmount);
1328
            customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());
1329
            customFofoOrderItem.setCgstAmount(cgstAmount);
1330
            customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());
1331
            customFofoOrderItem.setSgstAmount(sgstAmount);
1332
            customFofoOrderItem.setHsnCode(fofoOrderItem.getHsnCode());
1333
            customerFofoOrderItems.add(customFofoOrderItem);
1334
        }
1335
        pdfModel.setTotalAmount(paymentOption.getAmount());
1336
        pdfModel.setOrderItems(customerFofoOrderItems);
28166 tejbeer 1337
 
32145 tejbeer 1338
    }
27516 amit.gupta 1339
 
35034 amit 1340
    @Override
1341
    public InvoicePdfModel getInvoicePdfModel(FofoOrder fofoOrder) throws ProfitMandiBusinessException {
23650 amit.gupta 1342
 
32145 tejbeer 1343
        List<PaymentOptionTransaction> paymentOptionTransactions = paymentOptionTransactionRepository.selectByReferenceIdAndTypes(fofoOrder.getId(), Arrays.asList(PaymentOptionReferenceType.ORDER, PaymentOptionReferenceType.INSURANCE));
23650 amit.gupta 1344
 
32145 tejbeer 1345
        List<CustomPaymentOption> paymentOptions = new ArrayList<>();
23552 amit.gupta 1346
 
32145 tejbeer 1347
        InvoicePdfModel pdfModel = new InvoicePdfModel();
33795 ranu 1348
 
1349
 
1350
        List<FofoOrderItem> fofoOrderItems = this.getByOrderId(fofoOrder.getId());
1351
 
1352
        double upgradePartnerDiscount = 0;
1353
 
35055 ranu 1354
       /* for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
33795 ranu 1355
 
1356
            Set<String> serialNumbers = this.toSerialNumbers(fofoOrderItem.getFofoLineItems());
1357
            for (String serialNumber : serialNumbers) {
1358
                UpgradeOffer upgradeOffer = upgradeOfferRepository.selectBySerialNumber(serialNumber);
1359
                if (upgradeOffer != null) {
1360
                    CustomerOfferItem customerOfferItem = customerOfferItemRepository.selectById(upgradeOffer.getCustomerOfferItemId());
1361
                    upgradePartnerDiscount += customerOfferItem.getDealerPayout();
1362
                }
1363
            }
35055 ranu 1364
        }*/
33795 ranu 1365
 
1366
        boolean hasSamsungUpgrade = paymentOptionTransactions.stream()
1367
                .anyMatch(transaction ->
1368
                        "SAMSUNG UPGRADE".equals(paymentOptionRepository
1369
                                .selectById(transaction.getPaymentOptionId())
1370
                                .getName()));
1371
 
1372
        LOGGER.info("paymentOptionTransactions - {}", paymentOptionTransactions);
1373
        LOGGER.info("hasSamsungUpgrade - {}", hasSamsungUpgrade);
1374
 
1375
        double cashDiscount = paymentOptionTransactions.stream()
1376
                .filter(x -> "CASH DISCOUNT".equals(paymentOptionRepository.selectById(x.getPaymentOptionId()).getName())).mapToDouble(x -> x.getAmount()).findFirst().orElse(0);
1377
 
1378
        LOGGER.info("cashDiscount - {}", cashDiscount);
1379
 
32145 tejbeer 1380
        for (PaymentOptionTransaction paymentOptionTransaction : paymentOptionTransactions) {
33795 ranu 1381
            String paymentOptionName = paymentOptionRepository.selectById(paymentOptionTransaction.getPaymentOptionId()).getName();
1382
 
32145 tejbeer 1383
            CustomPaymentOption cpi = new CustomPaymentOption();
33795 ranu 1384
            LOGGER.info("paymentOptionName {}", paymentOptionName);
1385
 
1386
            float amountToSet = paymentOptionTransaction.getAmount();
1387
 
1388
            if ("SAMSUNG UPGRADE".equals(paymentOptionName) && hasSamsungUpgrade) {
1389
                if (cashDiscount > upgradePartnerDiscount) {
1390
                    amountToSet += (float) upgradePartnerDiscount;
1391
                } else {
1392
                    amountToSet += (float) cashDiscount;
1393
                }
1394
 
1395
            } else if ("CASH".equals(paymentOptionName) && !hasSamsungUpgrade) {
1396
                amountToSet += ((float) cashDiscount - (float) upgradePartnerDiscount);
1397
 
1398
            } else if ("CASH".equals(paymentOptionName) && hasSamsungUpgrade && (cashDiscount > upgradePartnerDiscount)) {
1399
                amountToSet += ((float) cashDiscount - (float) upgradePartnerDiscount);
1400
 
1401
            }
1402
 
1403
            cpi.setAmount(amountToSet);
1404
            cpi.setPaymentOption(paymentOptionName);
1405
 
32145 tejbeer 1406
            paymentOptions.add(cpi);
1407
        }
24215 amit.gupta 1408
 
33795 ranu 1409
 
32145 tejbeer 1410
        pdfModel.setTitle("Retailer Invoice");
1411
        Optional<FofoOrderItem> fofoOrderItemOptional = fofoOrderItems.stream().findAny();
1412
        if (fofoOrderItemOptional.isPresent() && fofoOrderItemOptional.get().equals("NOGST")) {
1413
            pdfModel.setTitle("Security Deposit Receipt");
1414
        }
1415
        pdfModel.setPaymentOptions(paymentOptions);
1416
        pdfModel.setAuther("SmartDukaan");
1417
        pdfModel.setInvoiceDate(FormattingUtils.formatDate(fofoOrder.getCreateTimestamp()));
23650 amit.gupta 1418
 
32145 tejbeer 1419
        // insurance calculation
1420
        List<InsurancePolicy> insurancePolicies = insurancePolicyRepository.selectByRetailerIdInvoiceNumber(fofoOrder.getInvoiceNumber());
33298 amit.gupta 1421
        List<CustomInsurancePolicy> customInsurancePolicies = new ArrayList<>();
32145 tejbeer 1422
        final float totalInsuranceTaxRate = 18;
1423
        for (InsurancePolicy insurancePolicy : insurancePolicies) {
1424
            float taxableInsurancePrice = insurancePolicy.getSaleAmount() / (1 + totalInsuranceTaxRate / 100);
1425
            CustomInsurancePolicy customInsurancePolicy = new CustomInsurancePolicy();
1426
            customInsurancePolicy.setDescription(insurancePolicy.getPolicyPlan() + " for Device #" + insurancePolicy.getSerialNumber() + "\n Plan Reference - " + insurancePolicy.getPolicyNumber());
1427
            customInsurancePolicy.setHsnCode("998716");
1428
            customInsurancePolicy.setRate(taxableInsurancePrice);
1429
            customInsurancePolicy.setIgstRate(18);
1430
            customInsurancePolicy.setIgstAmount(taxableInsurancePrice * 18 / 100);
1431
            customInsurancePolicy.setCgstRate(9);
1432
            customInsurancePolicy.setCgstAmount(taxableInsurancePrice * 9 / 100);
1433
            customInsurancePolicy.setSgstRate(9);
1434
            customInsurancePolicy.setSgstAmount(taxableInsurancePrice * 9 / 100);
1435
            customInsurancePolicy.setNetAmount(insurancePolicy.getSaleAmount());
1436
            customInsurancePolicies.add(customInsurancePolicy);
1437
        }
1438
        pdfModel.setInsurancePolicies(customInsurancePolicies);
24275 amit.gupta 1439
 
32145 tejbeer 1440
        Retailer retailer = retailerRepository.selectById(fofoOrder.getFofoId());
1441
        PrivateDealUser privateDealUser = null;
1442
        try {
1443
            privateDealUser = privateDealUserRepository.selectById(retailer.getId());
1444
        } catch (ProfitMandiBusinessException profitMandiBusinessException) {
1445
            LOGGER.error("Private Deal User not found : ", profitMandiBusinessException);
1446
        }
23650 amit.gupta 1447
 
32145 tejbeer 1448
        User user = userRepository.selectById(userAccountRepository.selectUserIdByRetailerId(retailer.getId()));
1449
        CustomRetailer customRetailer = new CustomRetailer();
1450
        customRetailer.setBusinessName(retailer.getName());
1451
        customRetailer.setMobileNumber(user.getMobileNumber());
1452
        // customRetailer.setTinNumber(retailer.getNumber());
1453
        if (privateDealUser == null) {
1454
            customRetailer.setGstNumber(null);
1455
        } else {
1456
            if (null != privateDealUser.getCounterId()) {
1457
                Counter counter = counterRepository.selectById(privateDealUser.getCounterId());
1458
                customRetailer.setGstNumber(counter.getGstin());
1459
            } else {
1460
                customRetailer.setGstNumber(null);
1461
            }
1462
        }
1463
        Address retailerAddress = addressRepository.selectById(retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailer.getId()));
1464
        customRetailer.setAddress(this.createCustomAddress(retailerAddress));
1465
        pdfModel.setRetailer(customRetailer);
23650 amit.gupta 1466
 
33089 amit.gupta 1467
        pdfModel.setCustomer(getCustomCustomer(fofoOrder, customRetailer.getAddress()));
1468
        pdfModel.setInvoiceNumber(fofoOrder.getInvoiceNumber());
1469
        pdfModel.setTotalAmount(fofoOrder.getTotalAmount());
1470
 
1471
 
33298 amit.gupta 1472
        List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>();
32145 tejbeer 1473
        for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
1474
            float discount = fofoOrderItem.getDiscount();
1475
            CustomOrderItem customFofoOrderItem = new CustomOrderItem();
1476
            float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();
1477
            float taxableSellingPrice = (fofoOrderItem.getSellingPrice() + discount) / (1 + totalTaxRate / 100);
1478
            float taxableDiscountPrice = discount / (1 + totalTaxRate / 100);
23650 amit.gupta 1479
 
32145 tejbeer 1480
            customFofoOrderItem.setAmount(fofoOrderItem.getQuantity() * (taxableSellingPrice - taxableDiscountPrice));
1481
            customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());
1482
            Set<String> serialNumbers = this.toSerialNumbers(fofoOrderItem.getFofoLineItems());
32816 ranu 1483
            List<FofoNonSerializeSerial> nonSerializeSerials = fofoNonSerializeSerialRepository.selectByItemIdAndOrderId(fofoOrderItem.getId());
1484
            // Extract serial numbers from FofoNonSerializeSerial entities
1485
            List<String> customSerialNumbers = nonSerializeSerials.stream().map(FofoNonSerializeSerial::getSerialNumber).collect(Collectors.toList());
1486
            LOGGER.info("nonSerializeSerials {}", nonSerializeSerials);
32145 tejbeer 1487
            if (!serialNumbers.isEmpty()) {
1488
                customFofoOrderItem.setDescription(
1489
                        customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));
1490
            }
32816 ranu 1491
            if (!customSerialNumbers.isEmpty()) {
1492
                customFofoOrderItem.setDescription(
1493
                        customFofoOrderItem.getDescription() + "\n SerialNumber - " + String.join(", ", customSerialNumbers));
1494
            }
32145 tejbeer 1495
            customFofoOrderItem.setRate(taxableSellingPrice);
1496
            customFofoOrderItem.setDiscount(taxableDiscountPrice);
1497
            customFofoOrderItem.setQuantity(fofoOrderItem.getQuantity());
1498
            customFofoOrderItem.setNetAmount(fofoOrderItem.getSellingPrice() * fofoOrderItem.getQuantity());
1499
            float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;
1500
            float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;
1501
            float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;
1502
            customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());
1503
            customFofoOrderItem.setIgstAmount(igstAmount);
1504
            customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());
1505
            customFofoOrderItem.setCgstAmount(cgstAmount);
1506
            customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());
1507
            customFofoOrderItem.setSgstAmount(sgstAmount);
1508
            customFofoOrderItem.setHsnCode(fofoOrderItem.getHsnCode());
1509
            customerFofoOrderItems.add(customFofoOrderItem);
1510
        }
1511
        pdfModel.setOrderItems(customerFofoOrderItems);
32627 ranu 1512
        String customerAddressStateCode = "";
32145 tejbeer 1513
        String partnerAddressStateCode = stateRepository.selectByName(pdfModel.getRetailer().getAddress().getState()).getCode();
32627 ranu 1514
        if (pdfModel.getCustomer() != null && pdfModel.getCustomer().getAddress() != null &&
1515
                pdfModel.getCustomer().getAddress().getState() != null &&
1516
                !pdfModel.getCustomer().getAddress().getState().trim().isEmpty()) {
1517
            customerAddressStateCode = stateRepository.selectByName(pdfModel.getCustomer().getAddress().getState()).getCode();
1518
        }
1519
 
32145 tejbeer 1520
        pdfModel.setPartnerAddressStateCode(partnerAddressStateCode);
32627 ranu 1521
        if (!customerAddressStateCode.equals("")) {
1522
            pdfModel.setCustomerAddressStateCode(customerAddressStateCode);
1523
        }
32145 tejbeer 1524
        pdfModel.setCancelled(fofoOrder.getCancelledTimestamp() != null);
1525
        List<String> tncs = new ArrayList<>();
34999 amit 1526
        tncs.add("I agree that goods received are in good working condition.");
1527
        tncs.add("Goods once sold cannot be exchanged or taken back.");
32145 tejbeer 1528
        tncs.add("Warranty for the goods received by me is the responsibility of the manufacturer only.");
1529
        if (pdfModel.getInsurancePolicies() != null && pdfModel.getInsurancePolicies().size() > 0) {
35000 amit 1530
            tncs.add("Extended Warranty/ Damage Protection related issues are to be handled directly by the respective providers.");
32145 tejbeer 1531
        }
1532
        pdfModel.setTncs(tncs);
1533
        return pdfModel;
23650 amit.gupta 1534
 
32145 tejbeer 1535
    }
23650 amit.gupta 1536
 
33665 ranu 1537
    private CustomCustomer getCustomCustomer(FofoOrder fofoOrder, CustomAddress retailerAddress) throws
1538
            ProfitMandiBusinessException {
32145 tejbeer 1539
        Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());
1540
        CustomCustomer customCustomer = new CustomCustomer();
1541
        customCustomer.setFirstName(customer.getFirstName());
1542
        customCustomer.setLastName(customer.getLastName());
1543
        customCustomer.setEmailId(customer.getEmailId());
1544
        customCustomer.setMobileNumber(customer.getMobileNumber());
1545
        customCustomer.setGstNumber(fofoOrder.getCustomerGstNumber());
32627 ranu 1546
        if (fofoOrder.getCustomerAddressId() != 0) {
1547
            CustomerAddress customerAddress = customerAddressRepository.selectById(fofoOrder.getCustomerAddressId());
1548
            customCustomer.setAddress(this.createCustomAddress(customerAddress));
1549
        } else {
33089 amit.gupta 1550
 
1551
            customCustomer.setAddress(this.createCustomAddressWithoutId(customCustomer, retailerAddress));
32627 ranu 1552
        }
32145 tejbeer 1553
        return customCustomer;
32627 ranu 1554
 
32145 tejbeer 1555
    }
23655 amit.gupta 1556
 
32145 tejbeer 1557
    @Override
1558
    public InvoicePdfModel getInvoicePdfModel(int fofoId, int orderId) throws ProfitMandiBusinessException {
1559
        FofoOrder fofoOrder = fofoOrderRepository.selectByFofoIdAndOrderId(fofoId, orderId);
1560
        return this.getInvoicePdfModel(fofoOrder);
1561
    }
23650 amit.gupta 1562
 
32145 tejbeer 1563
    public String getBillingAddress(CustomerAddress customerAddress) {
1564
        StringBuilder address = new StringBuilder();
1565
        if ((customerAddress.getLine1() != null) && (!customerAddress.getLine1().isEmpty())) {
1566
            address.append(customerAddress.getLine1());
1567
            address.append(", ");
1568
        }
22859 ashik.ali 1569
 
32145 tejbeer 1570
        if ((customerAddress.getLine2() != null) && (!customerAddress.getLine2().isEmpty())) {
1571
            address.append(customerAddress.getLine2());
1572
            address.append(", ");
1573
        }
22859 ashik.ali 1574
 
32145 tejbeer 1575
        if ((customerAddress.getLandmark() != null) && (!customerAddress.getLandmark().isEmpty())) {
1576
            address.append(customerAddress.getLandmark());
1577
            address.append(", ");
1578
        }
22859 ashik.ali 1579
 
32145 tejbeer 1580
        if ((customerAddress.getCity() != null) && (!customerAddress.getCity().isEmpty())) {
1581
            address.append(customerAddress.getCity());
1582
            address.append(", ");
1583
        }
22859 ashik.ali 1584
 
32145 tejbeer 1585
        if ((customerAddress.getState() != null) && (!customerAddress.getState().isEmpty())) {
1586
            address.append(customerAddress.getState());
1587
        }
22859 ashik.ali 1588
 
32145 tejbeer 1589
        if ((customerAddress.getPinCode() != null) && (!customerAddress.getPinCode().isEmpty())) {
1590
            address.append("- ");
1591
            address.append(customerAddress.getPinCode());
1592
        }
22859 ashik.ali 1593
 
32145 tejbeer 1594
        return address.toString();
1595
    }
23650 amit.gupta 1596
 
32145 tejbeer 1597
    @Override
1598
    public List<CartFofo> cartCheckout(String cartJson) throws ProfitMandiBusinessException {
1599
        try {
1600
            JSONObject cartObject = new JSONObject(cartJson);
1601
            Iterator<?> keys = cartObject.keys();
23650 amit.gupta 1602
 
32145 tejbeer 1603
            Set<Integer> itemIds = new HashSet<>();
1604
            List<CartFofo> cartItems = new ArrayList<CartFofo>();
23650 amit.gupta 1605
 
32145 tejbeer 1606
            while (keys.hasNext()) {
1607
                String key = (String) keys.next();
1608
                if (cartObject.get(key) instanceof JSONObject) {
1609
                    LOGGER.info(cartObject.get(key).toString());
1610
                }
1611
                CartFofo cf = new CartFofo();
1612
                cf.setItemId(cartObject.getJSONObject(key).getInt("itemId"));
1613
                cf.setQuantity(cartObject.getJSONObject(key).getInt("quantity"));
1614
                if (cartObject.getJSONObject(key).has("poId")) {
23650 amit.gupta 1615
 
32145 tejbeer 1616
                    cf.setPoId(cartObject.getJSONObject(key).getInt("poId"));
1617
                    cf.setPoItemId(cartObject.getJSONObject(key).getInt("poItemId"));
1618
                }
1619
                if (cf.getQuantity() <= 0) {
1620
                    continue;
1621
                }
1622
                cartItems.add(cf);
1623
                itemIds.add(cartObject.getJSONObject(key).getInt("itemId"));
1624
            }
1625
            Map<Integer, Item> itemMap = new HashMap<Integer, Item>();
1626
            if (itemIds.size() > 0) {
1627
                List<Item> items = itemRepository.selectByIds(itemIds);
1628
                for (Item i : items) {
1629
                    itemMap.put(i.getId(), i);
1630
                }
23650 amit.gupta 1631
 
32145 tejbeer 1632
            }
1633
            for (CartFofo cf : cartItems) {
1634
                Item i = itemMap.get(cf.getItemId());
1635
                if (i == null) {
1636
                    continue;
1637
                }
1638
                cf.setDisplayName(getValidName(i.getBrand()) + " " + getValidName(i.getModelName()) + " " + getValidName(i.getModelNumber()) + " " + getValidName(i.getColor()).replaceAll("\\s+", " "));
1639
                cf.setItemType(i.getType());
1640
            }
1641
            return cartItems;
1642
        } catch (Exception e) {
1643
            LOGGER.error("Unable to Prepare cart to place order...", e);
1644
            throw new ProfitMandiBusinessException("cartData", cartJson, "FFORDR_1006");
1645
        }
1646
    }
23650 amit.gupta 1647
 
32145 tejbeer 1648
    @Override
33665 ranu 1649
    public Map<String, Object> getSaleHistory(int fofoId, SearchType searchType, String searchValue, LocalDateTime
1650
            startDate, LocalDateTime endDate, int offset, int limit) throws ProfitMandiBusinessException {
32145 tejbeer 1651
        long countItems = 0;
1652
        List<FofoOrder> fofoOrders = new ArrayList<>();
23650 amit.gupta 1653
 
32145 tejbeer 1654
        if (searchType == SearchType.CUSTOMER_MOBILE_NUMBER && !searchValue.isEmpty()) {
1655
            fofoOrders = fofoOrderRepository.selectByFofoIdAndCustomerMobileNumber(fofoId, searchValue, null, null, offset, limit);
1656
            countItems = fofoOrderRepository.selectCountByCustomerMobileNumber(fofoId, searchValue, null, null);
1657
        } else if (searchType == SearchType.CUSTOMER_NAME && !searchValue.isEmpty()) {
1658
            fofoOrders = fofoOrderRepository.selectByFofoIdAndCustomerName(fofoId, searchValue, null, null, offset, limit);
1659
            countItems = fofoOrderRepository.selectCountByCustomerName(fofoId, searchValue, null, null);
1660
        } else if (searchType == SearchType.IMEI && !searchValue.isEmpty()) {
1661
            fofoOrders = fofoOrderRepository.selectByFofoIdAndSerialNumber(fofoId, searchValue, null, null, offset, limit);
1662
            countItems = fofoOrderRepository.selectCountBySerialNumber(fofoId, searchValue, null, null);
1663
        } else if (searchType == SearchType.ITEM_NAME && !searchValue.isEmpty()) {
1664
            fofoOrders = fofoOrderRepository.selectByFofoIdAndItemName(fofoId, searchValue, null, null, offset, limit);
1665
            countItems = fofoOrderRepository.selectCountByItemName(fofoId, searchValue, null, null);
1666
        } else if (searchType == SearchType.INVOICE_NUMBER && !searchValue.isEmpty()) {
1667
            fofoOrders = Arrays.asList(fofoOrderRepository.selectByFofoIdAndInvoiceNumber(fofoId, searchValue));
1668
            countItems = fofoOrders.size();
1669
        } else if (searchType == SearchType.DATE_RANGE) {
1670
            fofoOrders = fofoOrderRepository.selectByFofoId(fofoId, startDate, endDate, offset, limit);
1671
            countItems = fofoOrderRepository.selectCountByFofoId(fofoId, startDate, endDate);
1672
        }
1673
        Map<String, Object> map = new HashMap<>();
23650 amit.gupta 1674
 
32145 tejbeer 1675
        map.put("saleHistories", fofoOrders);
1676
        map.put("start", offset + 1);
1677
        map.put("size", countItems);
1678
        map.put("searchType", searchType);
1679
        map.put("searchTypes", SearchType.values());
1680
        map.put("startDate", startDate);
1681
        map.put("searchValue", searchValue);
1682
        map.put(ProfitMandiConstants.END_TIME, endDate);
1683
        if (fofoOrders.size() < limit) {
1684
            map.put("end", offset + fofoOrders.size());
1685
        } else {
1686
            map.put("end", offset + limit);
1687
        }
1688
        return map;
1689
    }
30426 tejbeer 1690
 
33665 ranu 1691
    public ResponseEntity<?> downloadReportInCsv(org.apache.commons.io.output.ByteArrayOutputStream
1692
                                                         baos, List<List<?>> rows, String fileName) {
32145 tejbeer 1693
        final HttpHeaders headers = new HttpHeaders();
1694
        headers.set("Content-Type", "text/csv");
30426 tejbeer 1695
 
32145 tejbeer 1696
        headers.set("Content-disposition", "inline; filename=" + fileName + ".csv");
1697
        headers.setContentLength(baos.toByteArray().length);
23202 ashik.ali 1698
 
32145 tejbeer 1699
        final InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
1700
        final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
30426 tejbeer 1701
 
33454 amit.gupta 1702
        return new ResponseEntity<>(inputStreamResource, headers, HttpStatus.OK);
32145 tejbeer 1703
    }
30157 manish 1704
 
32145 tejbeer 1705
    @Override
33665 ranu 1706
    public Map<String, Object> getSaleHistoryPaginated(int fofoId, SearchType searchType, String
1707
            searchValue, LocalDateTime startDate, LocalDateTime endDate, int offset, int limit) throws
1708
            ProfitMandiBusinessException {
32145 tejbeer 1709
        List<FofoOrder> fofoOrders = new ArrayList<>();
23650 amit.gupta 1710
 
32145 tejbeer 1711
        if (searchType == SearchType.CUSTOMER_MOBILE_NUMBER && !searchValue.isEmpty()) {
1712
            fofoOrders = fofoOrderRepository.selectByFofoIdAndCustomerMobileNumber(fofoId, searchValue, startDate, endDate, offset, limit);
1713
        } else if (searchType == SearchType.CUSTOMER_NAME && !searchValue.isEmpty()) {
1714
            fofoOrders = fofoOrderRepository.selectByFofoIdAndCustomerName(fofoId, searchValue, startDate, endDate, offset, limit);
1715
        } else if (searchType == SearchType.IMEI && !searchValue.isEmpty()) {
1716
            fofoOrders = fofoOrderRepository.selectByFofoIdAndSerialNumber(fofoId, searchValue, startDate, endDate, offset, limit);
1717
        } else if (searchType == SearchType.ITEM_NAME && !searchValue.isEmpty()) {
1718
            fofoOrders = fofoOrderRepository.selectByFofoIdAndItemName(fofoId, searchValue, startDate, endDate, offset, limit);
24275 amit.gupta 1719
 
32145 tejbeer 1720
        } else if (searchType == SearchType.DATE_RANGE) {
1721
            fofoOrders = fofoOrderRepository.selectByFofoId(fofoId, startDate, endDate, offset, limit);
1722
        }
1723
        Map<String, Object> map = new HashMap<>();
1724
        map.put("saleHistories", fofoOrders);
1725
        map.put("searchType", searchType);
1726
        map.put("searchTypes", SearchType.values());
1727
        map.put("startDate", startDate);
1728
        map.put("searchValue", searchValue);
1729
        map.put(ProfitMandiConstants.END_TIME, endDate);
1730
        return map;
1731
    }
23650 amit.gupta 1732
 
32145 tejbeer 1733
    private String getFofoStoreCode(int fofoId) throws ProfitMandiBusinessException {
1734
        FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
1735
        return fofoStore.getCode();
1736
    }
23650 amit.gupta 1737
 
32145 tejbeer 1738
    private String getValidName(String name) {
1739
        return name != null ? name : "";
1740
    }
23650 amit.gupta 1741
 
32145 tejbeer 1742
    private Set<String> toSerialNumbers(Set<FofoLineItem> fofoLineItems) {
1743
        Set<String> serialNumbers = new HashSet<>();
1744
        for (FofoLineItem fofoLineItem : fofoLineItems) {
1745
            if (fofoLineItem.getSerialNumber() != null && !fofoLineItem.getSerialNumber().isEmpty()) {
1746
                serialNumbers.add(fofoLineItem.getSerialNumber());
1747
            }
1748
        }
1749
        return serialNumbers;
1750
    }
23650 amit.gupta 1751
 
33520 amit.gupta 1752
    static final List<String> MOP_VOILATED_BRANDS = Arrays.asList("Live Demo", "Almost New");
1753
 
33665 ranu 1754
    private void validateDpPrice(int fofoId, Map<
1755
            Integer, PriceModel> itemIdMopPriceMap, Map<Integer, CustomFofoOrderItem> itemIdCustomFofoLineItemMap) throws
1756
            ProfitMandiBusinessException {
32420 amit.gupta 1757
        if (pricingService.getMopVoilatedRetailerIds().contains(fofoId)) return;
32145 tejbeer 1758
        for (Map.Entry<Integer, CustomFofoOrderItem> entry : itemIdCustomFofoLineItemMap.entrySet()) {
1759
            int itemId = entry.getKey();
1760
            CustomFofoOrderItem customFofoOrderItem = entry.getValue();
1761
            LOGGER.info("CustomFofoOrderItem -- {}", customFofoOrderItem);
1762
            PriceModel priceModel = itemIdMopPriceMap.get(itemId);
1763
            Item item = itemRepository.selectById(itemId);
34994 ranu 1764
//                Comment this as of now 11 sep 2025 as per tarun sir
1765
            /*if (!MOP_VOILATED_BRANDS.contains(item.getBrand()) && (item.getCategoryId() == ProfitMandiConstants.MOBILE_CATEGORY_ID || item.getCategoryId() == ProfitMandiConstants.TABLET_CATEGORY_ID || item.getCategoryId() == ProfitMandiConstants.LED_CATEGORY_ID) && customFofoOrderItem.getSerialNumberDetails().stream().filter(x -> org.apache.commons.lang.StringUtils.isNotEmpty(x.getSerialNumber())).collect(Collectors.toList()).size() > 0) {
32145 tejbeer 1766
                if (Utils.compareFloat(priceModel.getPrice(), customFofoOrderItem.getSellingPrice() + customFofoOrderItem.getDiscountAmount()) > 0) {
1767
                    throw new ProfitMandiBusinessException("Selling Price for ", item.getItemDescription(), "FFORDR_1010");
1768
                }
1769
            } else {
33520 amit.gupta 1770
                if (!MOP_VOILATED_BRANDS.contains(item.getBrand()) && priceModel.getPurchasePrice() > customFofoOrderItem.getSellingPrice()) {
32145 tejbeer 1771
                    throw new ProfitMandiBusinessException("Selling Price", itemRepository.selectById(itemId).getItemDescription(), "Selling Price should not be less than DP");
1772
                }
34994 ranu 1773
            }*/
32145 tejbeer 1774
        }
1775
    }
24275 amit.gupta 1776
 
33665 ranu 1777
    private void validateMopPrice(int fofoId, Map<
1778
            Integer, PriceModel> itemIdMopPriceMap, Map<Integer, CustomFofoOrderItem> itemIdCustomFofoLineItemMap) throws
1779
            ProfitMandiBusinessException {
32420 amit.gupta 1780
        if (pricingService.getMopVoilatedRetailerIds().contains(fofoId)) return;
32145 tejbeer 1781
        Map<Integer, Float> invalidMopItemIdPriceMap = new HashMap<>();
1782
        for (Map.Entry<Integer, PriceModel> entry : itemIdMopPriceMap.entrySet()) {
1783
            CustomFofoOrderItem customFofoOrderItem = itemIdCustomFofoLineItemMap.get(entry.getKey());
1784
            Item item = itemRepository.selectById(customFofoOrderItem.getItemId());
33520 amit.gupta 1785
            if (!(MOP_VOILATED_BRANDS.contains(item.getBrand()) || item.getCategoryId() != ProfitMandiConstants.MOBILE_CATEGORY_ID || item.getCategoryId() != ProfitMandiConstants.TABLET_CATEGORY_ID) && customFofoOrderItem.getSellingPrice() + customFofoOrderItem.getDiscountAmount() < entry.getValue().getPrice()) {
32145 tejbeer 1786
                invalidMopItemIdPriceMap.put(entry.getKey(), customFofoOrderItem.getSellingPrice());
1787
            }
1788
        }
34994 ranu 1789
//                Comment this as of now 11 sep 2025 as per tarun sir
1790
        /*if (!invalidMopItemIdPriceMap.isEmpty()) {
32145 tejbeer 1791
            LOGGER.error("Invalid itemIds selling prices{} should be greater than mop prices {}", invalidMopItemIdPriceMap, itemIdMopPriceMap);
1792
            throw new ProfitMandiBusinessException("invalidMopItemIdPrice", invalidMopItemIdPriceMap, "FFORDR_1010");
34994 ranu 1793
        }*/
23650 amit.gupta 1794
 
32145 tejbeer 1795
    }
23650 amit.gupta 1796
 
33665 ranu 1797
    private void updateInventoryItemsAndScanRecord(Set<InventoryItem> inventoryItems, int fofoId, Map<
1798
            Integer, Integer> inventoryItemQuantityUsed, int fofoOrderId) {
32145 tejbeer 1799
        for (InventoryItem inventoryItem : inventoryItems) {
1800
            inventoryItem.setLastScanType(ScanType.SALE);
33087 amit.gupta 1801
            inventoryItem.setUpdateTimestamp(LocalDateTime.now());
32145 tejbeer 1802
            ScanRecord scanRecord = new ScanRecord();
1803
            scanRecord.setInventoryItemId(inventoryItem.getId());
1804
            scanRecord.setFofoId(fofoId);
1805
            scanRecord.setOrderId(fofoOrderId);
1806
            // correct this
1807
            scanRecord.setQuantity(inventoryItemQuantityUsed.get(inventoryItem.getId()));
1808
            scanRecord.setType(ScanType.SALE);
1809
            scanRecordRepository.persist(scanRecord);
1810
            purchaseReturnItemRepository.deleteById(inventoryItem.getId());
23650 amit.gupta 1811
 
32145 tejbeer 1812
        }
1813
    }
23650 amit.gupta 1814
 
33665 ranu 1815
    private void createFofoLineItem(int fofoOrderItemId, Set<
1816
            InventoryItem> inventoryItems, Map<Integer, Integer> inventoryItemIdQuantityUsed) {
32145 tejbeer 1817
        for (InventoryItem inventoryItem : inventoryItems) {
1818
            FofoLineItem fofoLineItem = new FofoLineItem();
1819
            fofoLineItem.setFofoOrderItemId(fofoOrderItemId);
1820
            fofoLineItem.setSerialNumber(inventoryItem.getSerialNumber());
1821
            fofoLineItem.setInventoryItemId(inventoryItem.getId());
1822
            fofoLineItem.setQuantity(inventoryItemIdQuantityUsed.get(inventoryItem.getId()));
1823
            fofoLineItemRepository.persist(fofoLineItem);
1824
        }
1825
    }
23650 amit.gupta 1826
 
33665 ranu 1827
    private FofoOrderItem createAndGetFofoOrderItem(CustomFofoOrderItem customFofoOrderItem, int fofoOrderId, Map<
35493 amit 1828
            Integer, Item> itemMap, Set<InventoryItem> inventoryItems, Map<Integer, TagListing> tagListingMap,
1829
            Map<Integer, GstRate> gstRateMap) throws ProfitMandiBusinessException {
32145 tejbeer 1830
        FofoOrderItem fofoOrderItem = new FofoOrderItem();
1831
        fofoOrderItem.setItemId(customFofoOrderItem.getItemId());
1832
        fofoOrderItem.setQuantity(customFofoOrderItem.getQuantity());
1833
        fofoOrderItem.setSellingPrice(customFofoOrderItem.getSellingPrice());
34381 vikas.jang 1834
        fofoOrderItem.setPendingOrderItemId(customFofoOrderItem.getPoiId());
32145 tejbeer 1835
        fofoOrderItem.setOrderId(fofoOrderId);
35493 amit 1836
 
1837
        // N+1 fix: Use pre-fetched tagListingMap instead of querying per item
1838
        TagListing tl = tagListingMap.get(customFofoOrderItem.getItemId());
32145 tejbeer 1839
        // In case listing gets removed rebill it using the selling price
1840
        if (tl != null) {
1841
            fofoOrderItem.setDp(tl.getSellingPrice());
1842
            fofoOrderItem.setMop(tl.getMop());
1843
        } else {
1844
            fofoOrderItem.setDp(customFofoOrderItem.getSellingPrice());
1845
            fofoOrderItem.setMop(customFofoOrderItem.getSellingPrice());
1846
        }
1847
        fofoOrderItem.setDiscount(customFofoOrderItem.getDiscountAmount());
24823 amit.gupta 1848
 
32145 tejbeer 1849
        Item item = itemMap.get(customFofoOrderItem.getItemId());
35493 amit 1850
 
1851
        // N+1 fix: Use pre-fetched gstRateMap instead of querying per item
32145 tejbeer 1852
        for (InventoryItem inventoryItem : inventoryItems) {
35493 amit 1853
            GstRate gstRate = gstRateMap.get(inventoryItem.getItemId());
1854
            if (gstRate != null) {
1855
                fofoOrderItem.setIgstRate(gstRate.getIgstRate());
1856
                fofoOrderItem.setCgstRate(gstRate.getCgstRate());
1857
                fofoOrderItem.setSgstRate(gstRate.getSgstRate());
1858
            }
32145 tejbeer 1859
            fofoOrderItem.setHsnCode(inventoryItem.getHsnCode());
1860
            break;
1861
        }
1862
        fofoOrderItem.setBrand(item.getBrand());
1863
        fofoOrderItem.setModelName(item.getModelName());
1864
        fofoOrderItem.setModelNumber(item.getModelNumber());
1865
        fofoOrderItem.setColor(item.getColor());
1866
        fofoOrderItemRepository.persist(fofoOrderItem);
1867
        return fofoOrderItem;
1868
    }
27516 amit.gupta 1869
 
33665 ranu 1870
    private FofoOrderItem getDummyFofoOrderItem(int itemId, int fofoOrderId, String serialNumber, Integer stateId) throws
1871
            ProfitMandiBusinessException {
32145 tejbeer 1872
        Item item = itemRepository.selectById(itemId);
1873
        TagListing tl = tagListingRepository.selectByItemId(itemId);
1874
        FofoOrderItem fofoOrderItem = new FofoOrderItem();
1875
        fofoOrderItem.setItemId(itemId);
1876
        fofoOrderItem.setQuantity(1);
1877
        fofoOrderItem.setSellingPrice(tl.getMop());
1878
        fofoOrderItem.setOrderId(fofoOrderId);
1879
        // In case listing gets removed rebill it using the selling price
1880
        fofoOrderItem.setDp(tl.getSellingPrice());
1881
        fofoOrderItem.setMop(tl.getMop());
1882
        fofoOrderItem.setDiscount(0);
27516 amit.gupta 1883
 
32145 tejbeer 1884
        Map<Integer, GstRate> itemIdStateTaxRateMap = null;
1885
        if (stateId != null) {
1886
            itemIdStateTaxRateMap = stateGstRateRepository.getStateTaxRate(Arrays.asList(itemId), stateId);
1887
        } else {
1888
            itemIdStateTaxRateMap = stateGstRateRepository.getIgstTaxRate(Arrays.asList(itemId));
1889
        }
27516 amit.gupta 1890
 
32145 tejbeer 1891
        fofoOrderItem.setIgstRate(itemIdStateTaxRateMap.get(itemId).getIgstRate());
27516 amit.gupta 1892
 
32145 tejbeer 1893
        fofoOrderItem.setCgstRate(itemIdStateTaxRateMap.get(itemId).getCgstRate());
1894
        fofoOrderItem.setSgstRate(itemIdStateTaxRateMap.get(itemId).getSgstRate());
23650 amit.gupta 1895
 
1896
 
32145 tejbeer 1897
        fofoOrderItem.setHsnCode(item.getHsnCode());
1898
        fofoOrderItem.setBrand(item.getBrand());
1899
        fofoOrderItem.setModelName(item.getModelName());
1900
        fofoOrderItem.setModelNumber(item.getModelNumber());
1901
        fofoOrderItem.setColor(item.getColor());
23650 amit.gupta 1902
 
32145 tejbeer 1903
        Set<FofoLineItem> fofoLineItems = new HashSet<>();
1904
        FofoLineItem fli = new FofoLineItem();
1905
        fli.setQuantity(1);
1906
        fli.setSerialNumber(serialNumber);
1907
        fofoLineItems.add(fli);
1908
        fofoOrderItem.setFofoLineItems(fofoLineItems);
22859 ashik.ali 1909
 
32145 tejbeer 1910
        return fofoOrderItem;
1911
    }
22859 ashik.ali 1912
 
33665 ranu 1913
    private void updateCurrentInventorySnapshot(List<CurrentInventorySnapshot> currentInventorySnapshots,
1914
                                                int fofoId, int itemId, int quantity) throws ProfitMandiBusinessException {
32145 tejbeer 1915
        for (CurrentInventorySnapshot currentInventorySnapshot : currentInventorySnapshots) {
1916
            if (currentInventorySnapshot.getItemId() == itemId && currentInventorySnapshot.getFofoId() == fofoId) {
1917
                currentInventorySnapshotRepository.updateAvailabilityByItemIdAndFofoId(itemId, fofoId, currentInventorySnapshot.getAvailability() - quantity);
1918
            }
1919
        }
1920
    }
23650 amit.gupta 1921
 
33665 ranu 1922
    private void createPaymentOptions(FofoOrder fofoOrder, Set<CustomPaymentOption> customPaymentOptions) throws
1923
            ProfitMandiBusinessException {
32145 tejbeer 1924
        for (CustomPaymentOption customPaymentOption : customPaymentOptions) {
1925
            if (customPaymentOption.getAmount() > 0) {
1926
                PaymentOptionTransaction paymentOptionTransaction = new PaymentOptionTransaction();
1927
                paymentOptionTransaction.setReferenceId(fofoOrder.getId());
1928
                paymentOptionTransaction.setPaymentOptionId(customPaymentOption.getPaymentOptionId());
1929
                paymentOptionTransaction.setReferenceType(PaymentOptionReferenceType.ORDER);
1930
                paymentOptionTransaction.setAmount(customPaymentOption.getAmount());
1931
                paymentOptionTransaction.setFofoId(fofoOrder.getFofoId());
1932
                paymentOptionTransactionRepository.persist(paymentOptionTransaction);
1933
            }
1934
        }
1935
    }
22859 ashik.ali 1936
 
33665 ranu 1937
    private FofoOrder createAndGetFofoOrder(int customerId, String customerGstNumber, int fofoId, String
34381 vikas.jang 1938
            documentNumber, float totalAmount, int customerAddressId, int poId) {
32145 tejbeer 1939
        FofoOrder fofoOrder = new FofoOrder();
1940
        fofoOrder.setCustomerGstNumber(customerGstNumber);
1941
        fofoOrder.setCustomerId(customerId);
1942
        fofoOrder.setFofoId(fofoId);
34381 vikas.jang 1943
        fofoOrder.setPendingOrderId(poId);
32145 tejbeer 1944
        fofoOrder.setInvoiceNumber(documentNumber);
1945
        fofoOrder.setTotalAmount(totalAmount);
1946
        fofoOrder.setCustomerAddressId(customerAddressId);
1947
        fofoOrderRepository.persist(fofoOrder);
1948
        return fofoOrder;
1949
    }
23650 amit.gupta 1950
 
33665 ranu 1951
    private void validateItemsSerializedNonSerialized
1952
            (List<Item> items, Map<Integer, CustomFofoOrderItem> customFofoOrderItemMap) throws
1953
            ProfitMandiBusinessException {
32145 tejbeer 1954
        List<Integer> invalidItemIdSerialNumbers = new ArrayList<Integer>();
1955
        List<Integer> itemIdNonSerializedSerialNumbers = new ArrayList<Integer>();
1956
        for (Item i : items) {
1957
            CustomFofoOrderItem customFofoOrderItem = customFofoOrderItemMap.get(i.getId());
1958
            if (i.getType().equals(ItemType.SERIALIZED)) {
1959
                if (customFofoOrderItem == null || customFofoOrderItem.getSerialNumberDetails().isEmpty()) {
1960
                    invalidItemIdSerialNumbers.add(i.getId());
1961
                }
1962
            } else {
1963
                Set<String> serialNumbers = this.serialNumberDetailsToSerialNumbers(customFofoOrderItem.getSerialNumberDetails());
1964
                if (customFofoOrderItem == null || !serialNumbers.isEmpty()) {
1965
                    itemIdNonSerializedSerialNumbers.add(i.getId());
1966
                }
1967
            }
1968
        }
23650 amit.gupta 1969
 
32145 tejbeer 1970
        if (!invalidItemIdSerialNumbers.isEmpty()) {
1971
            LOGGER.error("Invalid itemId's serialNumbers for serialized{}", invalidItemIdSerialNumbers);
1972
            // itemId's are serialized you are saying these are not serialized
1973
            throw new ProfitMandiBusinessException("invalidItemIdSerialNumbers", invalidItemIdSerialNumbers, "FFORDR_1013");
1974
        }
22859 ashik.ali 1975
 
32145 tejbeer 1976
        if (!itemIdNonSerializedSerialNumbers.isEmpty()) {
1977
            LOGGER.error("Invalid itemId's serialNumbers for non serialized{}", itemIdNonSerializedSerialNumbers);
1978
            // itemId's are non serialized you are saying these are serialized
1979
            throw new ProfitMandiBusinessException("itemIdNonSerializedSerialNumbers", itemIdNonSerializedSerialNumbers, "FFORDR_1014");
1980
        }
1981
    }
22859 ashik.ali 1982
 
33665 ranu 1983
    private void validateCurrentInventorySnapshotQuantities
1984
            (List<CurrentInventorySnapshot> currentInventorySnapshots, Map<Integer, CustomFofoOrderItem> itemIdCustomFofoOrderItemMap) throws
1985
            ProfitMandiBusinessException {
32145 tejbeer 1986
        if (itemIdCustomFofoOrderItemMap.keySet().size() != currentInventorySnapshots.size()) {
1987
            throw new ProfitMandiBusinessException("quantiiesSize", currentInventorySnapshots.size(), "");
1988
        }
1989
        List<ItemIdQuantityAvailability> itemIdQuantityAvailabilities = new ArrayList<>(); // this is for error
1990
        LOGGER.info("currentInventorySnapshots " + currentInventorySnapshots);
1991
        LOGGER.info("CustomFofoLineItemMap {}", itemIdCustomFofoOrderItemMap);
1992
        for (CurrentInventorySnapshot currentInventorySnapshot : currentInventorySnapshots) {
1993
            CustomFofoOrderItem customFofoOrderItem = itemIdCustomFofoOrderItemMap.get(currentInventorySnapshot.getItemId());
1994
            LOGGER.info("customFofoOrderItem {}", customFofoOrderItem);
1995
            if (customFofoOrderItem.getQuantity() > currentInventorySnapshot.getAvailability()) {
1996
                ItemIdQuantityAvailability itemIdQuantityAvailability = new ItemIdQuantityAvailability();
1997
                itemIdQuantityAvailability.setItemId(customFofoOrderItem.getItemId());
1998
                Quantity quantity = new Quantity();
1999
                quantity.setAvailable(currentInventorySnapshot.getAvailability());
2000
                quantity.setRequested(customFofoOrderItem.getQuantity());
2001
                itemIdQuantityAvailability.setQuantity(quantity);
2002
                itemIdQuantityAvailabilities.add(itemIdQuantityAvailability);
2003
            }
2004
        }
22859 ashik.ali 2005
 
32145 tejbeer 2006
        if (!itemIdQuantityAvailabilities.isEmpty()) {
2007
            // itemIdQuantity request is not valid
2008
            LOGGER.error("Requested quantities should not be greater than currently available quantities {}", itemIdQuantityAvailabilities);
2009
            throw new ProfitMandiBusinessException("itemIdQuantityAvailabilities", itemIdQuantityAvailabilities, "FFORDR_1015");
2010
        }
2011
    }
22859 ashik.ali 2012
 
33665 ranu 2013
    private int getItemIdFromSerialNumber(Map<Integer, CustomFofoOrderItem> itemIdCustomFofoOrderItemMap, String
2014
            serialNumber) {
32145 tejbeer 2015
        int itemId = 0;
2016
        for (Map.Entry<Integer, CustomFofoOrderItem> entry : itemIdCustomFofoOrderItemMap.entrySet()) {
2017
            Set<SerialNumberDetail> serialNumberDetails = entry.getValue().getSerialNumberDetails();
2018
            for (SerialNumberDetail serialNumberDetail : serialNumberDetails) {
2019
                if (serialNumberDetail.getSerialNumber().equals(serialNumber)) {
2020
                    itemId = entry.getKey();
2021
                    break;
2022
                }
2023
            }
2024
        }
2025
        return itemId;
2026
    }
23650 amit.gupta 2027
 
32145 tejbeer 2028
    private Map<Integer, Item> toItemMap(List<Item> items) {
2029
        Function<Item, Integer> itemIdFunction = new Function<Item, Integer>() {
2030
            @Override
2031
            public Integer apply(Item item) {
2032
                return item.getId();
2033
            }
2034
        };
2035
        Function<Item, Item> itemFunction = new Function<Item, Item>() {
2036
            @Override
2037
            public Item apply(Item item) {
2038
                return item;
2039
            }
2040
        };
2041
        return items.stream().collect(Collectors.toMap(itemIdFunction, itemFunction));
2042
    }
23650 amit.gupta 2043
 
32145 tejbeer 2044
    private void setCustomerAddress(CustomerAddress customerAddress, CustomAddress customAddress) {
2045
        customerAddress.setName(customAddress.getName());
2046
        customerAddress.setLastName(customAddress.getLastName());
2047
        customerAddress.setLine1(customAddress.getLine1());
2048
        customerAddress.setLine2(customAddress.getLine2());
2049
        customerAddress.setLandmark(customAddress.getLandmark());
2050
        customerAddress.setCity(customAddress.getCity());
2051
        customerAddress.setPinCode(customAddress.getPinCode());
2052
        customerAddress.setState(customAddress.getState());
2053
        customerAddress.setCountry(customAddress.getCountry());
2054
        customerAddress.setPhoneNumber(customAddress.getPhoneNumber());
2055
    }
23650 amit.gupta 2056
 
32145 tejbeer 2057
    private CustomAddress createCustomAddress(Address address) {
2058
        CustomAddress customAddress = new CustomAddress();
2059
        customAddress.setName(address.getName());
2060
        customAddress.setLine1(address.getLine1());
2061
        customAddress.setLine2(address.getLine2());
2062
        customAddress.setLandmark(address.getLandmark());
2063
        customAddress.setCity(address.getCity());
2064
        customAddress.setPinCode(address.getPinCode());
2065
        customAddress.setState(address.getState());
2066
        customAddress.setCountry(address.getCountry());
2067
        customAddress.setPhoneNumber(address.getPhoneNumber());
2068
        return customAddress;
2069
    }
23650 amit.gupta 2070
 
32145 tejbeer 2071
    private CustomAddress createCustomAddress(CustomerAddress customerAddress) {
2072
        CustomAddress customAddress = new CustomAddress();
2073
        customAddress.setName(customerAddress.getName());
2074
        customAddress.setLastName(customerAddress.getLastName());
2075
        customAddress.setLine1(customerAddress.getLine1());
2076
        customAddress.setLine2(customerAddress.getLine2());
2077
        customAddress.setLandmark(customerAddress.getLandmark());
2078
        customAddress.setCity(customerAddress.getCity());
2079
        customAddress.setPinCode(customerAddress.getPinCode());
2080
        customAddress.setState(customerAddress.getState());
2081
        customAddress.setCountry(customerAddress.getCountry());
2082
        customAddress.setPhoneNumber(customerAddress.getPhoneNumber());
2083
        return customAddress;
2084
    }
23650 amit.gupta 2085
 
33665 ranu 2086
    private CustomAddress createCustomAddressWithoutId(CustomCustomer customerAddress, CustomAddress
2087
            retailerAddress) {
32627 ranu 2088
        CustomAddress customAddress = new CustomAddress();
2089
        customAddress.setName(customerAddress.getFirstName());
2090
        customAddress.setLastName(customerAddress.getLastName());
2091
        customAddress.setLine1("");
2092
        customAddress.setLine2("");
2093
        customAddress.setLandmark("");
33089 amit.gupta 2094
        customAddress.setCity(retailerAddress.getCity());
2095
        customAddress.setPinCode(retailerAddress.getPinCode());
2096
        customAddress.setState(retailerAddress.getState());
32627 ranu 2097
        customAddress.setCountry("");
2098
        customAddress.setPhoneNumber(customerAddress.getMobileNumber());
2099
        return customAddress;
2100
    }
2101
 
33665 ranu 2102
    private void validatePaymentOptionsAndTotalAmount(Set<CustomPaymentOption> customPaymentOptions,
2103
                                                      float totalAmount) throws ProfitMandiBusinessException {
32145 tejbeer 2104
        Set<Integer> paymentOptionIds = new HashSet<>();
23650 amit.gupta 2105
 
32145 tejbeer 2106
        float calculatedAmount = 0;
2107
        for (CustomPaymentOption customPaymentOption : customPaymentOptions) {
2108
            paymentOptionIds.add(customPaymentOption.getPaymentOptionId());
2109
            calculatedAmount = calculatedAmount + customPaymentOption.getAmount();
2110
        }
2111
        if (calculatedAmount != totalAmount) {
2112
            LOGGER.warn("Error occured while validating payment options amount - {} != TotalAmount {}", calculatedAmount, totalAmount);
2113
            throw new ProfitMandiBusinessException(ProfitMandiConstants.PAYMENT_OPTION_CALCULATED_AMOUNT, calculatedAmount, "FFORDR_1016");
2114
        }
23418 ashik.ali 2115
 
32145 tejbeer 2116
        List<Integer> foundPaymentOptionIds = paymentOptionRepository.selectIdsByIds(paymentOptionIds);
2117
        if (foundPaymentOptionIds.size() != paymentOptionIds.size()) {
2118
            paymentOptionIds.removeAll(foundPaymentOptionIds);
2119
            throw new ProfitMandiBusinessException(ProfitMandiConstants.PAYMENT_OPTION_ID, paymentOptionIds, "FFORDR_1017");
2120
        }
2121
    }
25101 amit.gupta 2122
 
32145 tejbeer 2123
    @Override
2124
    public List<FofoOrderItem> getByOrderId(int orderId) throws ProfitMandiBusinessException {
2125
        List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(orderId);
2126
        if (!fofoOrderItems.isEmpty()) {
2127
            List<FofoOrderItem> newFofoOrderItems = new ArrayList<>();
2128
            Map<Integer, Set<FofoLineItem>> fofoOrderItemIdFofoLineItemsMap = this.toFofoOrderItemIdFofoLineItems(fofoOrderItems);
2129
            Iterator<FofoOrderItem> fofoOrderItemsIterator = fofoOrderItems.iterator();
2130
            while (fofoOrderItemsIterator.hasNext()) {
2131
                FofoOrderItem fofoOrderItem = fofoOrderItemsIterator.next();
2132
                fofoOrderItem.setFofoLineItems(fofoOrderItemIdFofoLineItemsMap.get(fofoOrderItem.getId()));
2133
                newFofoOrderItems.add(fofoOrderItem);
2134
                fofoOrderItemsIterator.remove();
2135
            }
2136
            fofoOrderItems = newFofoOrderItems;
2137
        }
2138
        return fofoOrderItems;
2139
    }
25101 amit.gupta 2140
 
32145 tejbeer 2141
    private Set<Integer> toFofoOrderItemIds(List<FofoOrderItem> fofoOrderItems) {
2142
        Function<FofoOrderItem, Integer> fofoOrderItemToFofoOrderItemIdFunction = new Function<FofoOrderItem, Integer>() {
2143
            @Override
2144
            public Integer apply(FofoOrderItem fofoOrderItem) {
2145
                return fofoOrderItem.getId();
2146
            }
2147
        };
2148
        return fofoOrderItems.stream().map(fofoOrderItemToFofoOrderItemIdFunction).collect(Collectors.toSet());
2149
    }
25101 amit.gupta 2150
 
33665 ranu 2151
    private Map<Integer, Set<FofoLineItem>> toFofoOrderItemIdFofoLineItems(List<FofoOrderItem> fofoOrderItems) throws
2152
            ProfitMandiBusinessException {
32145 tejbeer 2153
        Set<Integer> fofoOrderItemIds = this.toFofoOrderItemIds(fofoOrderItems);
2154
        List<FofoLineItem> fofoLineItems = fofoLineItemRepository.selectByFofoOrderItemIds(fofoOrderItemIds);
2155
        Map<Integer, Set<FofoLineItem>> fofoOrderItemIdFofoLineItemsMap = new HashMap<>();
2156
        for (FofoLineItem fofoLineItem : fofoLineItems) {
2157
            if (!fofoOrderItemIdFofoLineItemsMap.containsKey(fofoLineItem.getFofoOrderItemId())) {
2158
                Set<FofoLineItem> fofoLineItems2 = new HashSet<>();
2159
                fofoLineItems2.add(fofoLineItem);
2160
                fofoOrderItemIdFofoLineItemsMap.put(fofoLineItem.getFofoOrderItemId(), fofoLineItems2);
2161
            } else {
2162
                fofoOrderItemIdFofoLineItemsMap.get(fofoLineItem.getFofoOrderItemId()).add(fofoLineItem);
2163
            }
2164
        }
2165
        return fofoOrderItemIdFofoLineItemsMap;
2166
    }
25101 amit.gupta 2167
 
32145 tejbeer 2168
    @Override
33665 ranu 2169
    public void updateCustomerDetails(CustomCustomer customCustomer, String invoiceNumber) throws
2170
            ProfitMandiBusinessException {
32145 tejbeer 2171
        FofoOrder fofoOrder = fofoOrderRepository.selectByInvoiceNumber(invoiceNumber);
34718 aman.kumar 2172
        LOGGER.info("fofoOrder{}", fofoOrder);
32145 tejbeer 2173
        Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());
34718 aman.kumar 2174
        LOGGER.info("customer{}", customer);
32145 tejbeer 2175
        customer.setFirstName(customCustomer.getFirstName());
2176
        customer.setLastName(customCustomer.getLastName());
2177
        customer.setMobileNumber(customCustomer.getMobileNumber());
2178
        customer.setEmailId(customCustomer.getEmailId());
2179
        customerRepository.persist(customer);
34338 ranu 2180
        if (fofoOrder.getCustomerAddressId() == 0) {
2181
            CustomAddress customAddress = customCustomer.getAddress();
2182
 
2183
            if (customAddress == null ||
2184
                    isNullOrEmpty(customAddress.getName()) ||
2185
                    isNullOrEmpty(customAddress.getLastName()) ||
2186
                    isNullOrEmpty(customAddress.getLine1()) ||
2187
                    isNullOrEmpty(customAddress.getCity()) ||
2188
                    isNullOrEmpty(customAddress.getPinCode()) ||
2189
                    isNullOrEmpty(customAddress.getState()) ||
34718 aman.kumar 2190
//                    isNullOrEmpty(customAddress.getCountry()) ||
34338 ranu 2191
                    isNullOrEmpty(customAddress.getPhoneNumber())) {
2192
                throw new IllegalArgumentException("Required customer address fields are missing.");
2193
            }
2194
 
2195
            CustomerAddress customerAddress = new CustomerAddress();
2196
            customerAddress.setCustomerId(fofoOrder.getCustomerId());
2197
            customerAddress.setName(customAddress.getName());
2198
            customerAddress.setLastName(customAddress.getLastName());
2199
            customerAddress.setLine1(customAddress.getLine1());
2200
            customerAddress.setLine2(customAddress.getLine2());
2201
            customerAddress.setLandmark(customAddress.getLandmark());
2202
            customerAddress.setCity(customAddress.getCity());
2203
            customerAddress.setPinCode(customAddress.getPinCode());
2204
            customerAddress.setState(customAddress.getState());
34718 aman.kumar 2205
//            customerAddress.setCountry(customAddress.getCountry());
34338 ranu 2206
            customerAddress.setPhoneNumber(customAddress.getPhoneNumber());
2207
            customerAddressRepository.persist(customerAddress);
2208
            fofoOrder.setCustomerAddressId(customerAddress.getId());
2209
 
2210
        }
32145 tejbeer 2211
        CustomerAddress customerAddress = customerAddressRepository.selectById(fofoOrder.getCustomerAddressId());
2212
        if (!customerAddress.getState().equalsIgnoreCase(customCustomer.getAddress().getState())) {
2213
            List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
2214
            resetTaxation(fofoOrder.getFofoId(), customerAddress, fofoOrderItems);
2215
        }
2216
        this.setCustomerAddress(customerAddress, customCustomer.getAddress());
2217
        fofoOrder.setCustomerGstNumber(customCustomer.getGstNumber());
2218
    }
23638 amit.gupta 2219
 
34338 ranu 2220
    private boolean isNullOrEmpty(String str) {
2221
        return str == null || str.trim().isEmpty();
2222
    }
2223
 
33665 ranu 2224
    private void resetTaxation(int fofoId, CustomerAddress customerAddress, List<FofoOrderItem> fofoOrderItems) throws
2225
            ProfitMandiBusinessException {
32145 tejbeer 2226
        int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(fofoId);
23650 amit.gupta 2227
 
32145 tejbeer 2228
        Address retailerAddress = addressRepository.selectById(retailerAddressId);
24275 amit.gupta 2229
 
32145 tejbeer 2230
        Integer stateId = null;
2231
        if (customerAddress.getState().equalsIgnoreCase(retailerAddress.getState())) {
2232
            try {
2233
                stateId = Long.valueOf(stateRepository.selectByName(customerAddress.getState()).getId()).intValue();
2234
            } catch (Exception e) {
2235
                LOGGER.error("Unable to get state rates");
2236
            }
2237
        }
2238
        List<Integer> itemIds = fofoOrderItems.stream().map(x -> x.getItemId()).collect(Collectors.toList());
2239
        final Map<Integer, GstRate> gstRates;
2240
        if (stateId != null) {
2241
            gstRates = stateGstRateRepository.getStateTaxRate(itemIds, stateId);
2242
        } else {
2243
            gstRates = stateGstRateRepository.getIgstTaxRate(itemIds);
2244
        }
2245
        for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
2246
            GstRate rate = gstRates.get(fofoOrderItem.getItemId());
2247
            fofoOrderItem.setCgstRate(rate.getCgstRate());
2248
            fofoOrderItem.setSgstRate(rate.getSgstRate());
2249
            fofoOrderItem.setIgstRate(rate.getIgstRate());
2250
        }
2251
    }
2252
    @Override
33665 ranu 2253
    public CustomerCreditNote badReturn(int fofoId, FoiBadReturnRequest foiBadReturnRequest) throws
2254
            ProfitMandiBusinessException {
34141 tejus.loha 2255
        return this.badReturn(null, fofoId, foiBadReturnRequest);
2256
    }
2257
    @Override
2258
    public CustomerCreditNote badReturn(String loginMail,int fofoId, FoiBadReturnRequest foiBadReturnRequest) throws
2259
            ProfitMandiBusinessException {
32145 tejbeer 2260
        FofoOrderItem foi = fofoOrderItemRepository.selectById(foiBadReturnRequest.getFofoOrderItemId());
2261
        FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(foi.getOrderId());
2262
        if (fofoOrder.getFofoId() != fofoId) {
2263
            throw new ProfitMandiBusinessException("Partner Auth", "", "Invalid Order");
2264
        }
2265
        int billedQty = foi.getQuantity() - customerReturnItemRepository.selectAllByOrderItemId(foi.getId()).size();
2266
        if (foiBadReturnRequest.getMarkedBadArr().size() > billedQty) {
2267
            throw new ProfitMandiBusinessException("Cant bad return more than what is billed", "", "Invalid Quantity");
2268
        }
2269
        List<CustomerReturnItem> customerReturnItems = new ArrayList<>();
2270
        for (BadReturnRequest badReturnRequest : foiBadReturnRequest.getMarkedBadArr()) {
2271
            CustomerReturnItem customerReturnItem = new CustomerReturnItem();
2272
            customerReturnItem.setFofoId(fofoId);
2273
            customerReturnItem.setFofoOrderItemId(foiBadReturnRequest.getFofoOrderItemId());
2274
            customerReturnItem.setFofoOrderId(fofoOrder.getId());
2275
            customerReturnItem.setRemarks(badReturnRequest.getRemarks());
2276
            customerReturnItem.setInventoryItemId(badReturnRequest.getInventoryItemId());
2277
            customerReturnItem.setQuantity(1);
2278
            customerReturnItem.setType(ReturnType.BAD);
2279
            // customerReturnItemRepository.persist(customerReturnItem);
2280
            inventoryService.saleReturnInventoryItem(customerReturnItem);
2281
            customerReturnItems.add(customerReturnItem);
2282
        }
2283
        CustomerCreditNote creditNote = generateCreditNote(fofoOrder, customerReturnItems);
2284
        for (CustomerReturnItem customerReturnItem : customerReturnItems) {
2285
            purchaseReturnService.returnInventoryItem(fofoId, false, customerReturnItem.getInventoryItemId(), ReturnType.BAD);
2286
        }
2287
        // This should cancel the order
2288
        fofoOrder.setCancelledTimestamp(LocalDateTime.now());
2289
        this.reverseScheme(fofoOrder);
2290
        return creditNote;
2291
    }
23638 amit.gupta 2292
 
33665 ranu 2293
    private CustomerCreditNote generateCreditNote(FofoOrder
2294
                                                          fofoOrder, List<CustomerReturnItem> customerReturnItems) throws ProfitMandiBusinessException {
24275 amit.gupta 2295
 
32145 tejbeer 2296
        InvoiceNumberGenerationSequence sequence = invoiceNumberGenerationSequenceRepository.selectByFofoId(fofoOrder.getFofoId());
2297
        sequence.setCreditNoteSequence(sequence.getCreditNoteSequence() + 1);
2298
        invoiceNumberGenerationSequenceRepository.persist(sequence);
24275 amit.gupta 2299
 
32145 tejbeer 2300
        String creditNoteNumber = sequence.getPrefix() + "/" + sequence.getCreditNoteSequence();
2301
        CustomerCreditNote creditNote = new CustomerCreditNote();
2302
        creditNote.setCreditNoteNumber(creditNoteNumber);
2303
        creditNote.setFofoId(fofoOrder.getFofoId());
2304
        creditNote.setFofoOrderId(fofoOrder.getId());
2305
        creditNote.setFofoOrderItemId(customerReturnItems.get(0).getFofoOrderItemId());
2306
        creditNote.setSettlementType(SettlementType.UNSETTLED);
2307
        customerCreditNoteRepository.persist(creditNote);
24275 amit.gupta 2308
 
32145 tejbeer 2309
        for (CustomerReturnItem customerReturnItem : customerReturnItems) {
2310
            customerReturnItem.setCreditNoteId(creditNote.getId());
2311
            customerReturnItemRepository.persist(customerReturnItem);
2312
        }
2313
        // this.returnInventoryItems(inventoryItems, debitNote);
23655 amit.gupta 2314
 
32145 tejbeer 2315
        return creditNote;
2316
    }
23655 amit.gupta 2317
 
32145 tejbeer 2318
    @Override
2319
    public CreditNotePdfModel getCreditNotePdfModel(int customerCreditNoteId) throws ProfitMandiBusinessException {
2320
        CustomerCreditNote creditNote = customerCreditNoteRepository.selectById(customerCreditNoteId);
2321
        return getCreditNotePdfModel(creditNote);
2322
    }
24275 amit.gupta 2323
 
33665 ranu 2324
    private CreditNotePdfModel getCreditNotePdfModel(CustomerCreditNote creditNote) throws
2325
            ProfitMandiBusinessException {
32145 tejbeer 2326
        FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(creditNote.getFofoOrderId());
2327
        List<CustomerReturnItem> customerReturnItems = customerReturnItemRepository.selectAllByCreditNoteId(creditNote.getId());
33090 amit.gupta 2328
        CustomRetailer customRetailer = retailerService.getFofoRetailer(fofoOrder.getFofoId());
2329
        CustomCustomer customCustomer = getCustomCustomer(fofoOrder, customRetailer.getAddress());
24275 amit.gupta 2330
 
33298 amit.gupta 2331
        List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>();
23655 amit.gupta 2332
 
32145 tejbeer 2333
        FofoOrderItem fofoOrderItem = fofoOrderItemRepository.selectById(creditNote.getFofoOrderItemId());
2334
        float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();
2335
        float taxableSellingPrice = fofoOrderItem.getSellingPrice() / (1 + totalTaxRate / 100);
2336
        float taxableDiscountPrice = fofoOrderItem.getDiscount() / (1 + totalTaxRate / 100);
24275 amit.gupta 2337
 
32145 tejbeer 2338
        CustomOrderItem customFofoOrderItem = new CustomOrderItem();
2339
        customFofoOrderItem.setAmount(customerReturnItems.size() * (taxableSellingPrice - taxableDiscountPrice));
2340
        customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());
24275 amit.gupta 2341
 
32145 tejbeer 2342
        if (ItemType.SERIALIZED.equals(itemRepository.selectById(fofoOrderItem.getItemId()).getType())) {
2343
            Set<Integer> inventoryItemIds = customerReturnItems.stream().map(x -> x.getInventoryItemId()).collect(Collectors.toSet());
2344
            List<String> serialNumbers = inventoryItemRepository.selectByIds(inventoryItemIds).stream().map(x -> x.getSerialNumber()).collect(Collectors.toList());
2345
            customFofoOrderItem.setDescription(
2346
                    customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));
2347
        }
23638 amit.gupta 2348
 
32145 tejbeer 2349
        customFofoOrderItem.setRate(taxableSellingPrice);
2350
        customFofoOrderItem.setDiscount(taxableDiscountPrice);
2351
        customFofoOrderItem.setQuantity(customerReturnItems.size());
2352
        customFofoOrderItem.setNetAmount(
2353
                (fofoOrderItem.getSellingPrice() - fofoOrderItem.getDiscount()) * customFofoOrderItem.getQuantity());
29707 tejbeer 2354
 
32145 tejbeer 2355
        float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;
2356
        float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;
2357
        float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;
2358
        LOGGER.info("fofoOrderItem - {}", fofoOrderItem);
2359
        customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());
2360
        customFofoOrderItem.setIgstAmount(igstAmount);
2361
        customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());
2362
        customFofoOrderItem.setCgstAmount(cgstAmount);
2363
        customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());
2364
        customFofoOrderItem.setSgstAmount(sgstAmount);
2365
        customFofoOrderItem.setHsnCode(fofoOrderItem.getHsnCode());
2366
        customFofoOrderItem.setOrderId(1);
2367
        customerFofoOrderItems.add(customFofoOrderItem);
29707 tejbeer 2368
 
32145 tejbeer 2369
        InvoicePdfModel pdfModel = new InvoicePdfModel();
2370
        pdfModel.setAuther("NSSPL");
2371
        pdfModel.setCustomer(customCustomer);
2372
        pdfModel.setInvoiceNumber(fofoOrder.getInvoiceNumber());
2373
        pdfModel.setInvoiceDate(FormattingUtils.formatDate(fofoOrder.getCreateTimestamp()));
2374
        pdfModel.setTitle("Credit Note");
2375
        pdfModel.setRetailer(customRetailer);
2376
        pdfModel.setTotalAmount(customFofoOrderItem.getNetAmount());
2377
        pdfModel.setOrderItems(customerFofoOrderItems);
29707 tejbeer 2378
 
32145 tejbeer 2379
        CreditNotePdfModel creditNotePdfModel = new CreditNotePdfModel();
2380
        creditNotePdfModel.setCreditNoteDate(FormattingUtils.formatDate(creditNote.getCreateTimestamp()));
2381
        creditNotePdfModel.setCreditNoteNumber(creditNote.getCreditNoteNumber());
2382
        creditNotePdfModel.setPdfModel(pdfModel);
2383
        return creditNotePdfModel;
2384
    }
24264 amit.gupta 2385
 
32145 tejbeer 2386
    // This will remove the order and maintain order record and reverse inventory
2387
    // and scheme
2388
    @Override
2389
    public void cancelOrder(List<String> invoiceNumbers) throws ProfitMandiBusinessException {
2390
        for (String invoiceNumber : invoiceNumbers) {
2391
            // Cancel only when not cancelled
2392
            FofoOrder fofoOrder = fofoOrderRepository.selectByInvoiceNumber(invoiceNumber);
2393
            if (fofoOrder.getCancelledTimestamp() == null) {
2394
                fofoOrder.setCancelledTimestamp(LocalDateTime.now());
2395
                PaymentOptionTransaction paymentTransaction = new PaymentOptionTransaction();
2396
                paymentTransaction.setAmount(-fofoOrder.getTotalAmount());
2397
                paymentTransaction.setFofoId(fofoOrder.getFofoId());
2398
                paymentTransaction.setReferenceId(fofoOrder.getId());
2399
                paymentTransaction.setReferenceType(PaymentOptionReferenceType.ORDER);
2400
                paymentTransaction.setPaymentOptionId(1);
2401
                paymentOptionTransactionRepository.persist(paymentTransaction);
31030 amit.gupta 2402
 
32145 tejbeer 2403
                List<FofoOrderItem> fois = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
2404
                if (fois.size() > 0) {
2405
                    List<InventoryItem> inventoryItems = new ArrayList<>();
2406
                    fois.stream().forEach(x -> {
2407
                        x.getFofoLineItems().stream().forEach(y -> {
2408
                            inventoryService.rollbackInventory(y.getInventoryItemId(), y.getQuantity(), fofoOrder.getFofoId());
2409
                            inventoryItems.add(inventoryItemRepository.selectById(y.getInventoryItemId()));
2410
                        });
2411
                    });
2412
                    // if(invoice)
2413
                    this.reverseScheme(fofoOrder);
2414
                }
2415
                insuranceService.cancelInsurance(fofoOrder);
2416
            }
2417
        }
2418
    }
31030 amit.gupta 2419
 
32145 tejbeer 2420
    @Override
2421
    public void reverseScheme(FofoOrder fofoOrder) throws ProfitMandiBusinessException {
2422
        String reversalReason = "Order Rolledback/Cancelled/Returned for Invoice #" + fofoOrder.getInvoiceNumber();
2423
        List<FofoOrderItem> fois = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
2424
        Set<Integer> inventoryItemIds = fois.stream().flatMap(x -> x.getFofoLineItems().stream().map(y -> y.getInventoryItemId())).collect(Collectors.toSet());
2425
        List<InventoryItem> inventoryItems = inventoryItemRepository.selectByIds(inventoryItemIds);
34486 amit.gupta 2426
        schemeService.reverseSchemes(inventoryItems, fofoOrder.getId(), reversalReason, SchemeType.OUT_SCHEME_TYPES);
34504 amit.gupta 2427
        //schemeService.reverseSchemes(inventoryItems, fofoOrder.getId(), reversalReason, Arrays.asList(SchemeType.INVESTMENT));
32145 tejbeer 2428
        schemeService.reverseSchemes(inventoryItems, fofoOrder.getId(), reversalReason, Arrays.asList(SchemeType.SPECIAL_SUPPORT));
31030 amit.gupta 2429
 
32145 tejbeer 2430
    }
24271 amit.gupta 2431
 
32145 tejbeer 2432
    @Override
2433
    public void reverseActivationScheme(List<Integer> inventoryItemIds) throws ProfitMandiBusinessException {
2434
        List<InventoryItem> inventoryItems = inventoryItemRepository.selectAllByIds(inventoryItemIds);
2435
        for (InventoryItem inventoryItem : inventoryItems) {
2436
            List<FofoLineItem> fofoLineItems = fofoLineItemRepository.selectByInventoryItemId(inventoryItem.getId());
2437
            FofoLineItem fofoLineItem = fofoLineItems.get(0);
2438
            FofoOrderItem fofoOrderItem = fofoOrderItemRepository.selectById(fofoLineItem.getFofoOrderItemId());
2439
            FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(fofoOrderItem.getOrderId());
2440
            String reversalReason = "Scheme rolled back as activation date is invalid for imei " + inventoryItem.getSerialNumber();
34319 amit.gupta 2441
            //schemeService.reverseSchemes(Arrays.asList(inventoryItem), fofoOrder.getId(), reversalReason, Arrays.asList(SchemeType.ACTIVATION));
32145 tejbeer 2442
            schemeService.reverseSchemes(Arrays.asList(inventoryItem), fofoOrder.getId(), reversalReason, Arrays.asList(SchemeType.SPECIAL_SUPPORT));
27083 amit.gupta 2443
 
32145 tejbeer 2444
        }
24271 amit.gupta 2445
 
32145 tejbeer 2446
    }
24271 amit.gupta 2447
 
32145 tejbeer 2448
    @Override
2449
    public float getSales(int fofoId, LocalDateTime startDate, LocalDateTime endDate) {
2450
        Float sales = fofoOrderRepository.selectSaleSumGroupByFofoIds(startDate, endDate).get(fofoId);
2451
        return sales == null ? 0f : sales;
2452
    }
24271 amit.gupta 2453
 
32145 tejbeer 2454
    @Override
2455
    public LocalDateTime getMaxSalesDate(int fofoId, LocalDateTime startDate, LocalDateTime endDate) {
2456
        LocalDateTime dateTime = fofoOrderRepository.selectMaxSaleDateGroupByFofoIds(startDate, endDate).get(fofoId);
2457
        return dateTime;
2458
    }
25101 amit.gupta 2459
 
32145 tejbeer 2460
    @Override
2461
    // Only being used internally
2462
    public float getSales(int fofoId, LocalDate onDate) {
2463
        LocalDateTime startTime = LocalDateTime.of(onDate, LocalTime.MIDNIGHT);
2464
        LocalDateTime endTime = LocalDateTime.of(onDate, LocalTime.MIDNIGHT).plusDays(1);
2465
        return this.getSales(fofoId, startTime, endTime);
2466
    }
24917 tejbeer 2467
 
32145 tejbeer 2468
    @Override
2469
    public float getSales(LocalDateTime onDate) {
2470
        // TODO Auto-generated method stub
2471
        return 0;
2472
    }
28166 tejbeer 2473
 
32145 tejbeer 2474
    @Override
2475
    public float getSales(LocalDateTime startDate, LocalDateTime endDate) {
2476
        // TODO Auto-generated method stub
2477
        return 0;
2478
    }
28166 tejbeer 2479
 
32145 tejbeer 2480
    @Override
2481
    public boolean notifyColorChange(int orderId, int itemId) throws ProfitMandiBusinessException {
2482
        Order order = orderRepository.selectById(orderId);
2483
        saholicInventoryService.reservationCountByColor(itemId, order);
28166 tejbeer 2484
 
32145 tejbeer 2485
        order.getLineItem().setItemId(itemId);
2486
        Item item = itemRepository.selectById(itemId);
2487
        order.getLineItem().setColor(item.getColor());
2488
        return true;
2489
    }
28166 tejbeer 2490
 
32145 tejbeer 2491
    @Override
2492
    public FofoOrder getOrderByInventoryItemId(int inventoryItemId) throws Exception {
2493
        List<FofoLineItem> lineItems = fofoLineItemRepository.selectByInventoryItemId(inventoryItemId);
2494
        if (lineItems.size() > 0) {
2495
            FofoOrderItem fofoOrderItem = fofoOrderItemRepository.selectById(lineItems.get(0).getFofoOrderItemId());
2496
            fofoOrderItem.setFofoLineItems(new HashSet<>(lineItems));
2497
            FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(fofoOrderItem.getOrderId());
2498
            fofoOrder.setOrderItem(fofoOrderItem);
2499
            return fofoOrder;
2500
        } else {
2501
            throw new Exception(String.format("Could not find inventoryItemId - %s", inventoryItemId));
2502
        }
2503
    }
28166 tejbeer 2504
 
32145 tejbeer 2505
    @Override
2506
    public Map<Integer, Long> carryBagCreditCount(int fofoId) throws ProfitMandiBusinessException {
28166 tejbeer 2507
 
32145 tejbeer 2508
        FofoStore fs = fofoStoreRepository.selectByRetailerId(fofoId);
2509
        LocalDateTime lastCredit = fs.getBagsLastCredited();
2510
        /*
2511
         * long carryBagCount = 0; List<FofoOrder> fofoOrders =
2512
         * fofoOrderRepository.selectByFofoIdBetweenCreatedTimeStamp(fofoId,
2513
         * lastCredit.atStartOfDay(), LocalDate.now().plusDays(1).atStartOfDay()); for
2514
         * (FofoOrder fo : fofoOrders) { carryBagCount +=
2515
         * fofoOrderItemRepository.selectByOrderId(fo.getId()).stream() .filter(x ->
2516
         * x.getSellingPrice() >= 12000).count();
2517
         *
2518
         * }
2519
         */
28166 tejbeer 2520
 
32145 tejbeer 2521
        Session session = sessionFactory.getCurrentSession();
2522
        CriteriaBuilder cb = session.getCriteriaBuilder();
2523
 
2524
        CriteriaQuery<SimpleEntry> query = cb.createQuery(SimpleEntry.class);
2525
        Root<FofoOrder> fofoOrder = query.from(FofoOrder.class);
2526
        Root<FofoOrderItem> fofoOrderItem = query.from(FofoOrderItem.class);
2527
        Root<TagListing> tagListingRoot = query.from(TagListing.class);
2528
        Root<Item> itemRoot = query.from(Item.class);
2529
 
2530
        Predicate p2 = cb.between(fofoOrder.get(ProfitMandiConstants.CREATE_TIMESTAMP), lastCredit, LocalDate.now().atStartOfDay());
2531
        Predicate p3 = cb.isNull(fofoOrder.get("cancelledTimestamp"));
2532
        Predicate joinPredicate = cb.and(
2533
                cb.equal(fofoOrder.get(ProfitMandiConstants.ID), fofoOrderItem.get(ProfitMandiConstants.ORDER_ID)), cb.equal(fofoOrderItem.get("itemId"), tagListingRoot.get("itemId")), cb.equal(itemRoot.get("id"), tagListingRoot.get("itemId")), cb.equal(fofoOrder.get(ProfitMandiConstants.FOFO_ID), fofoId));
2534
        ItemCriteria itemCriteria = new ItemCriteria();
35236 amit 2535
        itemCriteria.setBrands(brandsService.getBrands(fofoId, null, 3).stream().map(x -> x.getName()).collect(Collectors.toList()));
32145 tejbeer 2536
        float startValue = 12000;
2537
        itemCriteria.setStartPrice(startValue);
2538
        itemCriteria.setEndPrice(0);
2539
        itemCriteria.setFeaturedPhone(false);
2540
        itemCriteria.setSmartPhone(true);
2541
        itemCriteria.setCatalogIds(new ArrayList<>());
2542
        itemCriteria.setExcludeCatalogIds(new ArrayList<>());
2543
        Predicate itemPredicate = itemRepository.getItemPredicate(itemCriteria, cb, itemRoot, tagListingRoot.get("itemId"), tagListingRoot.get("sellingPrice"));
2544
        Predicate finalPredicate = cb.and(itemPredicate, p2, p3, joinPredicate);
2545
        query = query.multiselect(fofoOrder.get(ProfitMandiConstants.FOFO_ID), cb.count(fofoOrder)).where(finalPredicate).groupBy(fofoOrder.get(ProfitMandiConstants.FOFO_ID));
2546
        List<SimpleEntry> simpleEntries = session.createQuery(query).getResultList();
2547
        Map<Integer, Long> returnMap = new HashMap<>();
2548
 
2549
        for (SimpleEntry simpleEntry : simpleEntries) {
2550
            returnMap.put((Integer) simpleEntry.getKey(), (Long) simpleEntry.getValue());
2551
        }
2552
        return returnMap;
2553
 
2554
    }
32607 ranu 2555
 
2556
    @Override
2557
    public void createMissingScratchOffers() {
2558
        List<FofoOrder> fofoOrders = fofoOrderRepository.selectFromSaleDate(LocalDate.of(2023, 11, 6).atStartOfDay());
2559
        for (FofoOrder fofoOrder : fofoOrders) {
2560
            if (fofoOrder.getCancelledTimestamp() == null) { // Check if cancelled_timestamp is not null
2561
                try {
2562
                    this.createScratchOffer(fofoOrder.getFofoId(), fofoOrder.getInvoiceNumber(), fofoOrder.getCustomerId());
2563
                } catch (Exception e) {
2564
                    LOGGER.error("Error while processing missing scratch offer invoice orderId", fofoOrder.getId());
2565
                }
2566
            }
2567
        }
2568
    }
32724 amit.gupta 2569
 
2570
    @Override
33665 ranu 2571
    public boolean refundOrder(int orderId, String refundedBy, String refundReason) throws
2572
            ProfitMandiBusinessException {
32724 amit.gupta 2573
        /*def refund_order(order_id, refunded_by, reason):
2574
        """
2575
        If the order is in RTO_RECEIVED_PRESTINE, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
2576
            1. Creates a refund request for batch processing.
2577
            2. Creates a return order for the warehouse executive to return the shipped material.
2578
            3. Marks the current order as RTO_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
2579
 
2580
        If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
2581
            1. Creates a refund request for batch processing.
2582
            2. Cancels the reservation of the item in the warehouse.
2583
            3. Marks the current order as the REFUNDED final state.
2584
 
2585
        For all COD orders, if the order is in INIT, SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
2586
            1. Cancels the reservation of the item in the warehouse.
2587
            2. Marks the current order as CANCELED.
2588
 
2589
        In all cases, it updates the reason for cancellation or refund and the person who performed the action.
2590
 
2591
        Returns True if it is successful, False otherwise.
2592
 
2593
        Throws an exception if the order with the given id couldn't be found.
2594
 
2595
        Parameters:
2596
         - order_id
2597
         - refunded_by
2598
         - reason
2599
        """
2600
        LOGGER.info("Refunding order id: {}", orderId);
2601
        Order order = orderRepository.selectById(orderId);
2602
 
2603
        if order.cod:
2604
        logging.info("Refunding COD order with status " + str(order.status))
2605
        status_transition = refund_status_transition
2606
        if order.status not in status_transition.keys():
2607
        raise TransactionServiceException(114, "This order can't be refunded")
2608
 
2609
        if order.status in [OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.ACCEPTED]:
2610
        __update_inventory_reservation(order, refund=True)
2611
        order.statusDescription = "Order Cancelled"
2612
            #Shipment Id and Airway Bill No should be none in case of Cancellation
2613
        order.logisticsTransactionId = None
2614
        order.tracking_id = None
2615
        order.airwaybill_no = None
2616
        elif order.status == OrderStatus.BILLED:
2617
        __create_return_order(order)
2618
        order.statusDescription = "Order Cancelled"
2619
        elif order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT]:
2620
        if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
2621
        __create_return_order(order)
2622
        order.statusDescription = "RTO Refunded"
2623
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
2624
            #__create_return_order(order)
2625
        order.statusDescription = "Lost in Transit Refunded"
2626
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
2627
        if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
2628
        __create_return_order(order)
2629
        __create_refund(order, 0, 'Should be unreachable for now')
2630
        order.statusDescription = "DOA Refunded"
2631
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
2632
        if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
2633
        __create_return_order(order)
2634
        __create_refund(order, 0, 'Should be unreachable for now')
2635
        order.statusDescription = "Return Refunded"
2636
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
2637
        if order.previousStatus in [OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.ACCEPTED]:
2638
        __update_inventory_reservation(order, refund=True)
2639
        order.statusDescription = "Order Cancelled on customer request"
2640
        elif order.previousStatus == OrderStatus.BILLED:
2641
        __create_return_order(order)
2642
        order.statusDescription = "Order Cancelled on customer request"
2643
        order.received_return_timestamp = datetime.datetime.now()
2644
    else:
2645
        status_transition = {OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,
2646
                OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
2647
                OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
2648
                OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
2649
                OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
2650
                OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
2651
                OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
2652
                OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
2653
                OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
2654
                OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
2655
                OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
2656
                OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
2657
                OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2658
                OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2659
                OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2660
                OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2661
                OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2662
                OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2663
                OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2664
                OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST,
2665
                OrderStatus.PAYMENT_FLAGGED : OrderStatus.PAYMENT_FLAGGED_DENIED
2666
                     }
2667
        if order.status not in status_transition.keys():
2668
        raise TransactionServiceException(114, "This order can't be refunded")
2669
 
2670
        if order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT] :
2671
        if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
2672
        __create_return_order(order)
2673
        __create_refund(order, order.wallet_amount, 'Order #{0} is RTO refunded'.format(order.id))
2674
        order.statusDescription = "RTO Refunded"
2675
            #Start:- Added By Manish Sharma for Creating a new Ticket: Category- RTO Refund on 21-Jun-2013
2676
        try:
2677
        crmServiceClient = CRMClient().get_client()
2678
        ticket =Ticket()
2679
        activity = Activity()
2680
 
2681
        description = "Creating Ticket for " + order.statusDescription + " Order"
2682
        ticket.creatorId = 1
2683
        ticket.assigneeId = 34
2684
        ticket.category = TicketCategory.RTO_REFUND
2685
        ticket.priority = TicketPriority.MEDIUM
2686
        ticket.status = TicketStatus.OPEN
2687
        ticket.description = description
2688
        ticket.orderId = order.id
2689
 
2690
        activity.creatorId = 1
2691
        activity.ticketAssigneeId = ticket.assigneeId
2692
        activity.type = ActivityType.OTHER
2693
        activity.description = description
2694
        activity.ticketCategory = ticket.category
2695
        activity.ticketDescription = ticket.description
2696
        activity.ticketPriority = ticket.priority
2697
        activity.ticketStatus = ticket.status
2698
 
2699
        ticket.customerId= order.customer_id
2700
        ticket.customerEmailId = order.customer_email
2701
        ticket.customerMobileNumber = order.customer_mobilenumber
2702
        ticket.customerName = order.customer_name
2703
        activity.customerId = ticket.customerId
2704
        activity.customerEmailId = order.customer_email
2705
        activity.customerMobileNumber = order.customer_mobilenumber
2706
        activity.customerName = order.customer_name
2707
 
2708
        crmServiceClient.insertTicket(ticket, activity)
2709
 
2710
        except:
2711
        print "Ticket for RTO Refund is not created."
2712
            #End:- Added By Manish Sharma for Creating a new Ticket: Category- RTO Refund on 21-Jun-2013
2713
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
2714
            #__create_return_order(order)
2715
        __create_refund(order, order.wallet_amount, 'Order #{0} is Lost in Transit'.format(order.id))
2716
        order.statusDescription = "Lost in Transit Refunded"
2717
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
2718
        if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
2719
        __create_return_order(order)
2720
        __create_refund(order, 0, 'This should be unreachable')
2721
        order.statusDescription = "DOA Refunded"
2722
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
2723
        if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
2724
        __create_return_order(order)
2725
        __create_refund(order, 0, 'This should be unreachable')
2726
        order.statusDescription = "Return Refunded"
2727
        elif order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.ACCEPTED]:
2728
        __update_inventory_reservation(order, refund=True)
2729
        order.statusDescription = "Order Refunded"
2730
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
2731
        if order.previousStatus in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.PAYMENT_FLAGGED, OrderStatus.ACCEPTED]:
2732
        __update_inventory_reservation(order, refund=True)
2733
        order.statusDescription = "Order Cancelled on customer request"
2734
        elif order.previousStatus == OrderStatus.BILLED:
2735
        __create_refund(order, order.wallet_amount,  'Order #{0} Cancelled on customer request'.format(order.id))
2736
        order.statusDescription = "Order Cancelled on customer request"
2737
 
2738
        elif order.status == OrderStatus.PAYMENT_FLAGGED:
2739
        __update_inventory_reservation(order, refund=True)
2740
        order.statusDescription = "Order Cancelled due to payment flagged"
2741
 
2742
    # For orders that are cancelled after being billed, we need to scan in the scanned out
2743
    # inventory item and change availability accordingly
2744
        inventoryClient = InventoryClient().get_client()
2745
        warehouse = inventoryClient.getWarehouse(order.warehouse_id)
2746
        if warehouse.billingType == BillingType.OURS or warehouse.billingType == BillingType.OURS_EXTERNAL:
2747
        #Now BILLED orders can also be refunded directly with low inventory cancellations
2748
        if order.status in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH]:
2749
        __create_refund(order, order.wallet_amount, reason)
2750
        if order.status in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH] or (order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED and order.previousStatus in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH]):
2751
        lineitem = order.lineitems[0]
2752
        catalogClient = CatalogClient().get_client()
2753
        item = catalogClient.getItem(lineitem.item_id)
2754
        warehouseClient = WarehouseClient().get_client()
2755
        if warehouse.billingType == BillingType.OURS:
2756
        if ItemType.SERIALIZED == item.type:
2757
        for serial_number in str(lineitem.serial_number).split(','):
2758
        warehouseClient.scanSerializedItemForOrder(serial_number, ScanType.SALE_RET, order.id, order.fulfilmentWarehouseId, 1, order.warehouse_id)
2759
                else:
2760
        warehouseClient.scanForOrder(None, ScanType.SALE_RET, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
2761
        if warehouse.billingType == BillingType.OURS_EXTERNAL:
2762
        warehouseClient.scanForOursExternalSaleReturn(order.id, lineitem.transfer_price)
2763
        if order.freebieItemId:
2764
        warehouseClient.scanfreebie(order.id, order.freebieItemId, 0, ScanType.SALE_RET)
2765
 
2766
        order.status = status_transition[order.status]
2767
        order.statusDescription = OrderStatus._VALUES_TO_NAMES[order.status]
2768
        order.refund_timestamp = datetime.datetime.now()
2769
        order.refunded_by = refunded_by
2770
        order.refund_reason = reason
2771
    #to re evaluate the shipping charge if any order is being cancelled.
2772
    #_revaluate_shiping(order_id)
2773
        session.commit()
2774
        return True*/
2775
        return true;
2776
    }
2777
 
2778
    @Autowired
2779
    DebitNoteRepository debitNoteRepository;
2780
 
2781
    //initiate refund only if the stock is returned
2782
 
25724 amit.gupta 2783
}