Subversion Repositories SmartDukaan

Rev

Rev 35493 | Rev 35733 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 35493 Rev 35695
Line 8... Line 8...
8
import com.spice.profitmandi.common.util.FormattingUtils;
8
import com.spice.profitmandi.common.util.FormattingUtils;
9
import com.spice.profitmandi.common.util.StringUtils;
9
import com.spice.profitmandi.common.util.StringUtils;
10
import com.spice.profitmandi.common.util.Utils;
10
import com.spice.profitmandi.common.util.Utils;
11
import com.spice.profitmandi.common.web.client.RestClient;
11
import com.spice.profitmandi.common.web.client.RestClient;
12
import com.spice.profitmandi.dao.cart.SmartCartService;
12
import com.spice.profitmandi.dao.cart.SmartCartService;
-
 
13
import com.spice.profitmandi.dao.entity.catalog.Category;
13
import com.spice.profitmandi.dao.entity.catalog.Item;
14
import com.spice.profitmandi.dao.entity.catalog.Item;
14
import com.spice.profitmandi.dao.entity.catalog.TagListing;
15
import com.spice.profitmandi.dao.entity.catalog.TagListing;
15
import com.spice.profitmandi.dao.entity.catalog.UpgradeOffer;
16
import com.spice.profitmandi.dao.entity.catalog.UpgradeOffer;
16
import com.spice.profitmandi.dao.entity.dtr.*;
17
import com.spice.profitmandi.dao.entity.dtr.*;
17
import com.spice.profitmandi.dao.entity.fofo.*;
18
import com.spice.profitmandi.dao.entity.fofo.*;
Line 217... Line 218...
217
 
218
 
218
    @Autowired
219
    @Autowired
219
    private OrderRepository orderRepository;
220
    private OrderRepository orderRepository;
220
 
221
 
221
    @Autowired
222
    @Autowired
-
 
223
    private CategoryRepository categoryRepository;
-
 
224
 
-
 
225
    @Autowired
222
    private HygieneDataRepository hygieneDataRepository;
226
    private HygieneDataRepository hygieneDataRepository;
223
 
227
 
224
    @Autowired
228
    @Autowired
225
    private SessionFactory sessionFactory;
229
    private SessionFactory sessionFactory;
226
 
230
 
Line 578... Line 582...
578
        Map<Integer, Set<InventoryItem>> inventoryItemsToBill = new HashMap<>();
582
        Map<Integer, Set<InventoryItem>> inventoryItemsToBill = new HashMap<>();
579
        Map<Integer, Integer> inventoryItemIdQuantityUsed = new HashMap<>(); // to keep track of inventoryitem quanity
583
        Map<Integer, Integer> inventoryItemIdQuantityUsed = new HashMap<>(); // to keep track of inventoryitem quanity
580
        // used for scan records insertion
584
        // used for scan records insertion
581
 
585
 
582
        LOGGER.info("itemMap keys {}", itemMap.keySet());
586
        LOGGER.info("itemMap keys {}", itemMap.keySet());
-
 
587
 
-
 
588
        // N+1 fix: Fetch live demo serial numbers once before the loop (was being fetched per serialized item)
-
 
589
        Set<String> liveDemoSerialNumbers = new HashSet<>(liveDemoBillingRespository.selectAllSerialNumber());
-
 
590
        // Batch-fetch LiveDemoSerialNumber entities for all matching serialized inventory serials
-
 
591
        List<String> matchingLiveDemoSerials = serializedInventoryItemMap.values().stream()
-
 
592
                .flatMap(Set::stream)
-
 
593
                .map(InventoryItem::getSerialNumber)
-
 
594
                .filter(liveDemoSerialNumbers::contains)
-
 
595
                .collect(Collectors.toList());
-
 
596
        Map<String, LiveDemoSerialNumber> liveDemoSerialNumberMap = new HashMap<>();
-
 
597
        if (!matchingLiveDemoSerials.isEmpty()) {
-
 
598
            liveDemoSerialNumberMap = liveDemoBillingRespository.selectBySerialNumbers(matchingLiveDemoSerials).stream()
-
 
599
                    .collect(Collectors.toMap(LiveDemoSerialNumber::getSerialNumber, ld -> ld, (a, b) -> a));
-
 
600
        }
-
 
601
 
583
        // Lets reduce quantity and decide what inventory items to use.
602
        // Lets reduce quantity and decide what inventory items to use.
584
        for (Item item : items) {
603
        for (Item item : items) {
585
            if (item.getType().equals(ItemType.SERIALIZED)) {
604
            if (item.getType().equals(ItemType.SERIALIZED)) {
586
                // TODO:handle null
605
                // TODO:handle null
587
                if (serializedInventoryItemMap.get(item.getId()) == null || itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().size() != serializedInventoryItemMap.get(item.getId()).size()) {
606
                if (serializedInventoryItemMap.get(item.getId()) == null || itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().size() != serializedInventoryItemMap.get(item.getId()).size()) {
Line 589... Line 608...
589
                    if (itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().size() != insuredModels.size()) {
608
                    if (itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().size() != insuredModels.size()) {
590
                        List<String> invalidSerialNumbers = itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().stream().map(x -> x.getSerialNumber()).collect(Collectors.toList());
609
                        List<String> invalidSerialNumbers = itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().stream().map(x -> x.getSerialNumber()).collect(Collectors.toList());
591
                        throw new ProfitMandiBusinessException("invalidSerialNumbers", invalidSerialNumbers, "FFORDR_1004");
610
                        throw new ProfitMandiBusinessException("invalidSerialNumbers", invalidSerialNumbers, "FFORDR_1004");
592
                    }
611
                    }
593
                }
612
                }
594
                List<String> serialNumberList = liveDemoBillingRespository.selectAllSerialNumber();
-
 
595
 
613
 
596
                Set<InventoryItem> inventoryItemsSerializedserialized = serializedInventoryItemMap.get(item.getId());
614
                Set<InventoryItem> inventoryItemsSerializedserialized = serializedInventoryItemMap.get(item.getId());
597
                for (InventoryItem inventoryItem : inventoryItemsSerializedserialized) {
615
                for (InventoryItem inventoryItem : inventoryItemsSerializedserialized) {
598
                    inventoryItem.setGoodQuantity(0);
616
                    inventoryItem.setGoodQuantity(0);
599
                    inventoryItemIdQuantityUsed.put(inventoryItem.getId(), 1);
617
                    inventoryItemIdQuantityUsed.put(inventoryItem.getId(), 1);
600
                    if (serialNumberList.contains(inventoryItem.getSerialNumber())) {
618
                    LiveDemoSerialNumber liveDemoSerialNumber = liveDemoSerialNumberMap.get(inventoryItem.getSerialNumber());
601
                        LiveDemoSerialNumber liveDemoSerialNumber = liveDemoBillingRespository.selectBySerialNumber(inventoryItem.getSerialNumber());
619
                    if (liveDemoSerialNumber != null) {
602
                        liveDemoBillingRespository.delete(liveDemoSerialNumber);
620
                        liveDemoBillingRespository.delete(liveDemoSerialNumber);
603
                    }
621
                    }
604
                }
622
                }
605
                inventoryItemsToBill.put(item.getId(), inventoryItemsSerializedserialized);
623
                inventoryItemsToBill.put(item.getId(), inventoryItemsSerializedserialized);
606
            } else {
624
            } else {
Line 675... Line 693...
675
            gstRateMap = stateGstRateRepository.getStateTaxRate(new ArrayList<>(itemMap.keySet()), stateId);
693
            gstRateMap = stateGstRateRepository.getStateTaxRate(new ArrayList<>(itemMap.keySet()), stateId);
676
        } else {
694
        } else {
677
            gstRateMap = stateGstRateRepository.getIgstTaxRate(new ArrayList<>(itemMap.keySet()));
695
            gstRateMap = stateGstRateRepository.getIgstTaxRate(new ArrayList<>(itemMap.keySet()));
678
        }
696
        }
679
 
697
 
-
 
698
        // N+1 fix: Collect created FofoOrderItems during the loop instead of re-querying
-
 
699
        List<FofoOrderItem> fofoItems = new ArrayList<>();
680
        for (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {
700
        for (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {
681
            FofoOrderItem fofoOrderItem = this.createAndGetFofoOrderItem(customFofoOrderItem, fofoOrder.getId(), itemMap, inventoryItemsToBill.get(customFofoOrderItem.getItemId()), tagListingMap, gstRateMap);
701
            FofoOrderItem fofoOrderItem = this.createAndGetFofoOrderItem(customFofoOrderItem, fofoOrder.getId(), itemMap, inventoryItemsToBill.get(customFofoOrderItem.getItemId()), tagListingMap, gstRateMap);
-
 
702
            fofoItems.add(fofoOrderItem);
682
 
703
 
683
            Item item = itemMap.get(customFofoOrderItem.getItemId());
704
            Item item = itemMap.get(customFofoOrderItem.getItemId());
684
            if (item.getType().equals(ItemType.NON_SERIALIZED)) {
705
            if (item.getType().equals(ItemType.NON_SERIALIZED)) {
685
                if (customFofoOrderItem.getCustomSerialNumbers() != null && !customFofoOrderItem.getCustomSerialNumbers().isEmpty()) {
706
                if (customFofoOrderItem.getCustomSerialNumbers() != null && !customFofoOrderItem.getCustomSerialNumbers().isEmpty()) {
686
                    persistNonSerializedWithCustomSerialNumber(customFofoOrderItem, fofoOrderItem.getId());
707
                    persistNonSerializedWithCustomSerialNumber(customFofoOrderItem, fofoOrderItem.getId());
Line 697... Line 718...
697
            this.updateCurrentInventorySnapshot(currentInventorySnapshots, fofoId, customFofoOrderItem.getItemId(), customFofoOrderItem.getQuantity());
718
            this.updateCurrentInventorySnapshot(currentInventorySnapshots, fofoId, customFofoOrderItem.getItemId(), customFofoOrderItem.getQuantity());
698
 
719
 
699
            this.updateInventoryItemsAndScanRecord(inventoryItems, fofoId, inventoryItemIdQuantityUsed, fofoOrder.getId());
720
            this.updateInventoryItemsAndScanRecord(inventoryItems, fofoId, inventoryItemIdQuantityUsed, fofoOrder.getId());
700
        }
721
        }
701
 
722
 
702
        List<FofoOrderItem> fofoItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
-
 
703
 
-
 
704
        // Use existing itemMap instead of querying DB per item (N+1 fix)
723
        // Use existing itemMap instead of querying DB per item (N+1 fix)
705
        boolean smartPhone = items.stream().anyMatch(Item::isSmartPhone);
724
        boolean smartPhone = items.stream().anyMatch(Item::isSmartPhone);
706
        if (smartPhone) {
725
        if (smartPhone) {
707
            LOGGER.info("Smartphone found in order items");
726
            LOGGER.info("Smartphone found in order items");
708
        } else {
727
        } else {
Line 716... Line 735...
716
        // insurance calculation is insurance flag is enabled
735
        // insurance calculation is insurance flag is enabled
717
        //
736
        //
718
        if (insuredModels.size() > 0) {
737
        if (insuredModels.size() > 0) {
719
            LOGGER.info("Processing insurane for serialNumbers");
738
            LOGGER.info("Processing insurane for serialNumbers");
720
            LOGGER.info("InsuranceModels {}", insuredModels);
739
            LOGGER.info("InsuranceModels {}", insuredModels);
-
 
740
            if (createOrderRequest.getCustomer() == null || createOrderRequest.getCustomer().getDateOfBirth() == null) {
-
 
741
                throw new ProfitMandiBusinessException("Order", "Customer Date of Birth", "Customer date of birth is required for insurance");
-
 
742
            }
721
            LocalDate customerDateOfBirth = LocalDate.from(createOrderRequest.getCustomer().getDateOfBirth());
743
            LocalDate customerDateOfBirth = LocalDate.from(createOrderRequest.getCustomer().getDateOfBirth());
722
            fofoOrder.setDateOfBirth(customerDateOfBirth);
744
            fofoOrder.setDateOfBirth(customerDateOfBirth);
723
            for (InsuranceModel insuranceModel : insuredModels) {
745
            for (InsuranceModel insuranceModel : insuredModels) {
724
                LOGGER.info("G- {}", insuranceModel.getInsuranceId());
746
                LOGGER.info("G- {}", insuranceModel.getInsuranceId());
725
                LOGGER.info("insuranceModel- {}", insuranceModel);
747
                LOGGER.info("insuranceModel- {}", insuranceModel);
Line 1467... Line 1489...
1467
        pdfModel.setCustomer(getCustomCustomer(fofoOrder, customRetailer.getAddress()));
1489
        pdfModel.setCustomer(getCustomCustomer(fofoOrder, customRetailer.getAddress()));
1468
        pdfModel.setInvoiceNumber(fofoOrder.getInvoiceNumber());
1490
        pdfModel.setInvoiceNumber(fofoOrder.getInvoiceNumber());
1469
        pdfModel.setTotalAmount(fofoOrder.getTotalAmount());
1491
        pdfModel.setTotalAmount(fofoOrder.getTotalAmount());
1470
 
1492
 
1471
 
1493
 
1472
        List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>();
1494
        List<CustomOrderItem> regularFofoItems = new ArrayList<>();
-
 
1495
        List<CustomOrderItem> marginSchemeFofoItems = new ArrayList<>();
-
 
1496
        boolean hasMarginSchemeItems = false;
1473
        for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
1497
        for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
1474
            float discount = fofoOrderItem.getDiscount();
1498
            float discount = fofoOrderItem.getDiscount();
1475
            CustomOrderItem customFofoOrderItem = new CustomOrderItem();
1499
            CustomOrderItem customFofoOrderItem = new CustomOrderItem();
1476
            float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();
1500
            float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();
1477
            float taxableSellingPrice = (fofoOrderItem.getSellingPrice() + discount) / (1 + totalTaxRate / 100);
-
 
1478
            float taxableDiscountPrice = discount / (1 + totalTaxRate / 100);
-
 
1479
 
1501
 
1480
            customFofoOrderItem.setAmount(fofoOrderItem.getQuantity() * (taxableSellingPrice - taxableDiscountPrice));
-
 
1481
            customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());
1502
            customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());
1482
            Set<String> serialNumbers = this.toSerialNumbers(fofoOrderItem.getFofoLineItems());
1503
            Set<String> serialNumbers = this.toSerialNumbers(fofoOrderItem.getFofoLineItems());
1483
            List<FofoNonSerializeSerial> nonSerializeSerials = fofoNonSerializeSerialRepository.selectByItemIdAndOrderId(fofoOrderItem.getId());
1504
            List<FofoNonSerializeSerial> nonSerializeSerials = fofoNonSerializeSerialRepository.selectByItemIdAndOrderId(fofoOrderItem.getId());
1484
            // Extract serial numbers from FofoNonSerializeSerial entities
-
 
1485
            List<String> customSerialNumbers = nonSerializeSerials.stream().map(FofoNonSerializeSerial::getSerialNumber).collect(Collectors.toList());
1505
            List<String> customSerialNumbers = nonSerializeSerials.stream().map(FofoNonSerializeSerial::getSerialNumber).collect(Collectors.toList());
1486
            LOGGER.info("nonSerializeSerials {}", nonSerializeSerials);
1506
            LOGGER.info("nonSerializeSerials {}", nonSerializeSerials);
1487
            if (!serialNumbers.isEmpty()) {
1507
            if (!serialNumbers.isEmpty()) {
1488
                customFofoOrderItem.setDescription(
1508
                customFofoOrderItem.setDescription(
1489
                        customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));
1509
                        customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));
1490
            }
1510
            }
1491
            if (!customSerialNumbers.isEmpty()) {
1511
            if (!customSerialNumbers.isEmpty()) {
1492
                customFofoOrderItem.setDescription(
1512
                customFofoOrderItem.setDescription(
1493
                        customFofoOrderItem.getDescription() + "\n SerialNumber - " + String.join(", ", customSerialNumbers));
1513
                        customFofoOrderItem.getDescription() + "\n SerialNumber - " + String.join(", ", customSerialNumbers));
1494
            }
1514
            }
1495
            customFofoOrderItem.setRate(taxableSellingPrice);
-
 
1496
            customFofoOrderItem.setDiscount(taxableDiscountPrice);
-
 
1497
            customFofoOrderItem.setQuantity(fofoOrderItem.getQuantity());
1515
            customFofoOrderItem.setQuantity(fofoOrderItem.getQuantity());
1498
            customFofoOrderItem.setNetAmount(fofoOrderItem.getSellingPrice() * fofoOrderItem.getQuantity());
-
 
1499
            float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;
-
 
1500
            float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;
-
 
1501
            float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;
-
 
1502
            customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());
-
 
1503
            customFofoOrderItem.setIgstAmount(igstAmount);
-
 
1504
            customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());
-
 
1505
            customFofoOrderItem.setCgstAmount(cgstAmount);
-
 
1506
            customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());
-
 
1507
            customFofoOrderItem.setSgstAmount(sgstAmount);
-
 
1508
            customFofoOrderItem.setHsnCode(fofoOrderItem.getHsnCode());
1516
            customFofoOrderItem.setHsnCode(fofoOrderItem.getHsnCode());
-
 
1517
 
-
 
1518
            // Check if this is a margin scheme item
-
 
1519
            boolean isMarginItem = false;
-
 
1520
            try {
-
 
1521
                Item item = itemRepository.selectById(fofoOrderItem.getItemId());
-
 
1522
                Category category = categoryRepository.selectById(item.getCategoryId());
-
 
1523
                isMarginItem = category.isMarginOnly() && !serialNumbers.isEmpty();
-
 
1524
            } catch (Exception e) {
-
 
1525
                LOGGER.warn("Could not check margin scheme for fofo order item {}", fofoOrderItem.getId(), e);
-
 
1526
            }
-
 
1527
 
-
 
1528
            if (isMarginItem) {
-
 
1529
                // Margin Scheme: GST on margin only
-
 
1530
                // Purchase price = what FOFO paid (from fofo.inventory_item.unitPrice)
-
 
1531
                float purchasePrice = getFofoPurchasePrice(serialNumbers.iterator().next(), fofoOrder.getFofoId());
-
 
1532
                float sellingPrice = fofoOrderItem.getSellingPrice();
-
 
1533
                float margin = Math.max(0, sellingPrice - purchasePrice);
-
 
1534
                float taxableMargin = margin / (1 + totalTaxRate / 100);
-
 
1535
 
-
 
1536
                customFofoOrderItem.setMarginScheme(true);
-
 
1537
                customFofoOrderItem.setPurchasePrice(purchasePrice);
-
 
1538
                customFofoOrderItem.setSellingPrice(sellingPrice);
-
 
1539
                customFofoOrderItem.setMargin(margin);
-
 
1540
                customFofoOrderItem.setRate(sellingPrice);
-
 
1541
                customFofoOrderItem.setDiscount(0);
-
 
1542
                customFofoOrderItem.setAmount(taxableMargin * fofoOrderItem.getQuantity());
-
 
1543
                customFofoOrderItem.setNetAmount(fofoOrderItem.getSellingPrice() * fofoOrderItem.getQuantity());
-
 
1544
 
-
 
1545
                float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;
-
 
1546
                float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;
-
 
1547
                float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;
-
 
1548
                customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());
-
 
1549
                customFofoOrderItem.setIgstAmount(igstAmount);
-
 
1550
                customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());
-
 
1551
                customFofoOrderItem.setCgstAmount(cgstAmount);
-
 
1552
                customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());
-
 
1553
                customFofoOrderItem.setSgstAmount(sgstAmount);
-
 
1554
 
-
 
1555
                marginSchemeFofoItems.add(customFofoOrderItem);
-
 
1556
                hasMarginSchemeItems = true;
-
 
1557
            } else {
-
 
1558
                // Regular: GST on full selling price
-
 
1559
                float taxableSellingPrice = (fofoOrderItem.getSellingPrice() + discount) / (1 + totalTaxRate / 100);
-
 
1560
                float taxableDiscountPrice = discount / (1 + totalTaxRate / 100);
-
 
1561
 
-
 
1562
                customFofoOrderItem.setAmount(fofoOrderItem.getQuantity() * (taxableSellingPrice - taxableDiscountPrice));
-
 
1563
                customFofoOrderItem.setRate(taxableSellingPrice);
-
 
1564
                customFofoOrderItem.setDiscount(taxableDiscountPrice);
-
 
1565
                customFofoOrderItem.setNetAmount(fofoOrderItem.getSellingPrice() * fofoOrderItem.getQuantity());
-
 
1566
 
-
 
1567
                float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;
-
 
1568
                float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;
-
 
1569
                float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;
-
 
1570
                customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());
-
 
1571
                customFofoOrderItem.setIgstAmount(igstAmount);
-
 
1572
                customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());
-
 
1573
                customFofoOrderItem.setCgstAmount(cgstAmount);
-
 
1574
                customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());
-
 
1575
                customFofoOrderItem.setSgstAmount(sgstAmount);
-
 
1576
 
1509
            customerFofoOrderItems.add(customFofoOrderItem);
1577
                regularFofoItems.add(customFofoOrderItem);
-
 
1578
            }
1510
        }
1579
        }
-
 
1580
        // Regular items first, then margin scheme items
-
 
1581
        List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>(regularFofoItems);
-
 
1582
        customerFofoOrderItems.addAll(marginSchemeFofoItems);
1511
        pdfModel.setOrderItems(customerFofoOrderItems);
1583
        pdfModel.setOrderItems(customerFofoOrderItems);
-
 
1584
        pdfModel.setHasMarginSchemeItems(hasMarginSchemeItems);
-
 
1585
        if (hasMarginSchemeItems) {
-
 
1586
            List<String> declarations = new ArrayList<>();
-
 
1587
            declarations.add("Items marked under Margin Scheme are taxed under Rule 32(5) of CGST Rules, 2017.");
-
 
1588
            declarations.add("GST is charged on the margin (Selling Price - Purchase Price) and not on the full value of supply.");
-
 
1589
            declarations.add("Input Tax Credit is not available on margin scheme items.");
-
 
1590
            pdfModel.setMarginSchemeDeclarations(declarations);
-
 
1591
        }
1512
        String customerAddressStateCode = "";
1592
        String customerAddressStateCode = "";
1513
        String partnerAddressStateCode = stateRepository.selectByName(pdfModel.getRetailer().getAddress().getState()).getCode();
1593
        String partnerAddressStateCode = stateRepository.selectByName(pdfModel.getRetailer().getAddress().getState()).getCode();
1514
        if (pdfModel.getCustomer() != null && pdfModel.getCustomer().getAddress() != null &&
1594
        if (pdfModel.getCustomer() != null && pdfModel.getCustomer().getAddress() != null &&
1515
                pdfModel.getCustomer().getAddress().getState() != null &&
1595
                pdfModel.getCustomer().getAddress().getState() != null &&
1516
                !pdfModel.getCustomer().getAddress().getState().trim().isEmpty()) {
1596
                !pdfModel.getCustomer().getAddress().getState().trim().isEmpty()) {
Line 1532... Line 1612...
1532
        pdfModel.setTncs(tncs);
1612
        pdfModel.setTncs(tncs);
1533
        return pdfModel;
1613
        return pdfModel;
1534
 
1614
 
1535
    }
1615
    }
1536
 
1616
 
-
 
1617
    private float getFofoPurchasePrice(String serialNumber, int fofoId) {
-
 
1618
        try {
-
 
1619
            InventoryItem fofoInventoryItem = inventoryItemRepository.selectBySerialNumberFofoId(serialNumber, fofoId);
-
 
1620
            if (fofoInventoryItem != null) {
-
 
1621
                return fofoInventoryItem.getUnitPrice();
-
 
1622
            }
-
 
1623
        } catch (Exception e) {
-
 
1624
            LOGGER.error("Could not fetch FOFO purchase price for serial: {}, fofoId: {}", serialNumber, fofoId, e);
-
 
1625
        }
-
 
1626
        return 0;
-
 
1627
    }
-
 
1628
 
1537
    private CustomCustomer getCustomCustomer(FofoOrder fofoOrder, CustomAddress retailerAddress) throws
1629
    private CustomCustomer getCustomCustomer(FofoOrder fofoOrder, CustomAddress retailerAddress) throws
1538
            ProfitMandiBusinessException {
1630
            ProfitMandiBusinessException {
1539
        Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());
1631
        Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());
1540
        CustomCustomer customCustomer = new CustomCustomer();
1632
        CustomCustomer customCustomer = new CustomCustomer();
1541
        customCustomer.setFirstName(customer.getFirstName());
1633
        customCustomer.setFirstName(customer.getFirstName());
Line 2330... Line 2422...
2330
 
2422
 
2331
        List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>();
2423
        List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>();
2332
 
2424
 
2333
        FofoOrderItem fofoOrderItem = fofoOrderItemRepository.selectById(creditNote.getFofoOrderItemId());
2425
        FofoOrderItem fofoOrderItem = fofoOrderItemRepository.selectById(creditNote.getFofoOrderItemId());
2334
        float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();
2426
        float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();
2335
        float taxableSellingPrice = fofoOrderItem.getSellingPrice() / (1 + totalTaxRate / 100);
-
 
2336
        float taxableDiscountPrice = fofoOrderItem.getDiscount() / (1 + totalTaxRate / 100);
-
 
2337
 
2427
 
2338
        CustomOrderItem customFofoOrderItem = new CustomOrderItem();
2428
        CustomOrderItem customFofoOrderItem = new CustomOrderItem();
2339
        customFofoOrderItem.setAmount(customerReturnItems.size() * (taxableSellingPrice - taxableDiscountPrice));
-
 
2340
        customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());
2429
        customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());
2341
 
2430
 
-
 
2431
        List<String> serialNumbers = new ArrayList<>();
2342
        if (ItemType.SERIALIZED.equals(itemRepository.selectById(fofoOrderItem.getItemId()).getType())) {
2432
        if (ItemType.SERIALIZED.equals(itemRepository.selectById(fofoOrderItem.getItemId()).getType())) {
2343
            Set<Integer> inventoryItemIds = customerReturnItems.stream().map(x -> x.getInventoryItemId()).collect(Collectors.toSet());
2433
            Set<Integer> inventoryItemIds = customerReturnItems.stream().map(x -> x.getInventoryItemId()).collect(Collectors.toSet());
2344
            List<String> serialNumbers = inventoryItemRepository.selectByIds(inventoryItemIds).stream().map(x -> x.getSerialNumber()).collect(Collectors.toList());
2434
            serialNumbers = inventoryItemRepository.selectByIds(inventoryItemIds).stream().map(x -> x.getSerialNumber()).collect(Collectors.toList());
2345
            customFofoOrderItem.setDescription(
2435
            customFofoOrderItem.setDescription(
2346
                    customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));
2436
                    customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));
2347
        }
2437
        }
2348
 
2438
 
-
 
2439
        // Check if margin scheme item
-
 
2440
        boolean isMarginItem = false;
-
 
2441
        try {
-
 
2442
            Item item = itemRepository.selectById(fofoOrderItem.getItemId());
-
 
2443
            Category category = categoryRepository.selectById(item.getCategoryId());
-
 
2444
            isMarginItem = category.isMarginOnly() && !serialNumbers.isEmpty();
-
 
2445
        } catch (Exception e) {
-
 
2446
            LOGGER.warn("Could not check margin scheme for credit note item {}", fofoOrderItem.getId(), e);
-
 
2447
        }
-
 
2448
 
-
 
2449
        if (isMarginItem) {
-
 
2450
            // Margin Scheme credit note: reverse GST on margin only
-
 
2451
            float purchasePrice = getFofoPurchasePrice(serialNumbers.get(0), fofoOrder.getFofoId());
-
 
2452
            float sellingPrice = fofoOrderItem.getSellingPrice();
-
 
2453
            float margin = Math.max(0, sellingPrice - purchasePrice);
-
 
2454
            float taxableMargin = margin / (1 + totalTaxRate / 100);
-
 
2455
 
-
 
2456
            customFofoOrderItem.setMarginScheme(true);
-
 
2457
            customFofoOrderItem.setPurchasePrice(purchasePrice);
-
 
2458
            customFofoOrderItem.setSellingPrice(sellingPrice);
-
 
2459
            customFofoOrderItem.setMargin(margin);
-
 
2460
            customFofoOrderItem.setRate(sellingPrice);
-
 
2461
            customFofoOrderItem.setDiscount(0);
-
 
2462
            customFofoOrderItem.setAmount(taxableMargin * customerReturnItems.size());
-
 
2463
        } else {
-
 
2464
            float taxableSellingPrice = fofoOrderItem.getSellingPrice() / (1 + totalTaxRate / 100);
-
 
2465
            float taxableDiscountPrice = fofoOrderItem.getDiscount() / (1 + totalTaxRate / 100);
-
 
2466
            customFofoOrderItem.setAmount(customerReturnItems.size() * (taxableSellingPrice - taxableDiscountPrice));
2349
        customFofoOrderItem.setRate(taxableSellingPrice);
2467
            customFofoOrderItem.setRate(taxableSellingPrice);
2350
        customFofoOrderItem.setDiscount(taxableDiscountPrice);
2468
            customFofoOrderItem.setDiscount(taxableDiscountPrice);
-
 
2469
        }
-
 
2470
 
2351
        customFofoOrderItem.setQuantity(customerReturnItems.size());
2471
        customFofoOrderItem.setQuantity(customerReturnItems.size());
2352
        customFofoOrderItem.setNetAmount(
2472
        customFofoOrderItem.setNetAmount(
2353
                (fofoOrderItem.getSellingPrice() - fofoOrderItem.getDiscount()) * customFofoOrderItem.getQuantity());
2473
                (fofoOrderItem.getSellingPrice() - fofoOrderItem.getDiscount()) * customFofoOrderItem.getQuantity());
2354
 
2474
 
2355
        float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;
2475
        float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;
Line 2373... Line 2493...
2373
        pdfModel.setInvoiceDate(FormattingUtils.formatDate(fofoOrder.getCreateTimestamp()));
2493
        pdfModel.setInvoiceDate(FormattingUtils.formatDate(fofoOrder.getCreateTimestamp()));
2374
        pdfModel.setTitle("Credit Note");
2494
        pdfModel.setTitle("Credit Note");
2375
        pdfModel.setRetailer(customRetailer);
2495
        pdfModel.setRetailer(customRetailer);
2376
        pdfModel.setTotalAmount(customFofoOrderItem.getNetAmount());
2496
        pdfModel.setTotalAmount(customFofoOrderItem.getNetAmount());
2377
        pdfModel.setOrderItems(customerFofoOrderItems);
2497
        pdfModel.setOrderItems(customerFofoOrderItems);
-
 
2498
        pdfModel.setHasMarginSchemeItems(isMarginItem);
2378
 
2499
 
2379
        CreditNotePdfModel creditNotePdfModel = new CreditNotePdfModel();
2500
        CreditNotePdfModel creditNotePdfModel = new CreditNotePdfModel();
2380
        creditNotePdfModel.setCreditNoteDate(FormattingUtils.formatDate(creditNote.getCreateTimestamp()));
2501
        creditNotePdfModel.setCreditNoteDate(FormattingUtils.formatDate(creditNote.getCreateTimestamp()));
2381
        creditNotePdfModel.setCreditNoteNumber(creditNote.getCreditNoteNumber());
2502
        creditNotePdfModel.setCreditNoteNumber(creditNote.getCreditNoteNumber());
2382
        creditNotePdfModel.setPdfModel(pdfModel);
2503
        creditNotePdfModel.setPdfModel(pdfModel);