Subversion Repositories SmartDukaan

Rev

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