Subversion Repositories SmartDukaan

Rev

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