Subversion Repositories SmartDukaan

Rev

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