| Line 459... |
Line 459... |
| 459 |
}
|
459 |
}
|
| 460 |
|
460 |
|
| 461 |
@RequestMapping(value = "/addItemToScheme", method = RequestMethod.POST)
|
461 |
@RequestMapping(value = "/addItemToScheme", method = RequestMethod.POST)
|
| 462 |
public String updateScheme(HttpServletRequest request, @RequestBody SchemeItems schemeItems, Model model)
|
462 |
public String updateScheme(HttpServletRequest request, @RequestBody SchemeItems schemeItems, Model model)
|
| 463 |
throws Exception {
|
463 |
throws Exception {
|
| - |
|
464 |
LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
|
| 464 |
for (int schemeId : schemeItems.getSchemeIds()) {
|
465 |
for (int schemeId : schemeItems.getSchemeIds()) {
|
| 465 |
List<Integer> catalogIds = schemeItemRepository.selectCatalogIdsBySchemeId(schemeId);
|
466 |
Scheme scheme = schemeRepository.selectById(schemeId);
|
| 466 |
if (schemeRepository.selectById(schemeId) != null)
|
467 |
if (scheme != null) {
|
| 467 |
for (int catalogId : schemeItems.getCatalogIds()) {
|
468 |
for (int catalogId : schemeItems.getCatalogIds()) {
|
| 468 |
if (!(catalogIds.contains(catalogId))) {
|
469 |
// Use dates from request if provided, else default to scheme's window
|
| 469 |
SchemeItem si = new SchemeItem();
|
470 |
LocalDateTime startDate = schemeItems.getStartDate() != null ? schemeItems.getStartDate() : scheme.getStartDateTime();
|
| 470 |
si.setCatalogId(catalogId);
|
- |
|
| 471 |
si.setSchemeId(schemeId);
|
- |
|
| 472 |
si.setCreateTimestamp(LocalDateTime.now());
|
471 |
LocalDateTime endDate = schemeItems.getEndDate() != null ? schemeItems.getEndDate() : scheme.getEndDateTime();
|
| 473 |
try {
|
472 |
try {
|
| 474 |
schemeItemRepository.persist(si);
|
473 |
schemeService.addSchemeItemWithDates(schemeId, catalogId, startDate, endDate, loginDetails.getFofoId());
|
| 475 |
} catch (Exception e) {
|
474 |
} catch (ProfitMandiBusinessException e) {
|
| 476 |
LOGGER.info("Scheme already exist");
|
- |
|
| 477 |
}
|
475 |
throw e;
|
| 478 |
model.addAttribute("response1", mvcResponseSender.createResponseString(true));
|
- |
|
| 479 |
} else {
|
476 |
} catch (Exception e) {
|
| 480 |
throw new ProfitMandiBusinessException("Catalog exist for scheme",
|
- |
|
| 481 |
"SchemeId= " + schemeId + ", CatalogId= " + catalogId, "Catalog exist for scheme");
|
477 |
LOGGER.info("Scheme already exist for schemeId={}, catalogId={}", schemeId, catalogId);
|
| 482 |
}
|
478 |
}
|
| - |
|
479 |
model.addAttribute("response1", mvcResponseSender.createResponseString(true));
|
| 483 |
}
|
480 |
}
|
| - |
|
481 |
}
|
| 484 |
}
|
482 |
}
|
| 485 |
return "response";
|
483 |
return "response";
|
| 486 |
}
|
484 |
}
|
| 487 |
|
485 |
|
| 488 |
@RequestMapping(value = "/createScheme", method = RequestMethod.GET)
|
486 |
@RequestMapping(value = "/createScheme", method = RequestMethod.GET)
|
| Line 790... |
Line 788... |
| 790 |
|
788 |
|
| 791 |
return "scheme-imei-results-modal";
|
789 |
return "scheme-imei-results-modal";
|
| 792 |
}
|
790 |
}
|
| 793 |
|
791 |
|
| 794 |
/**
|
792 |
/**
|
| - |
|
793 |
* Scheme-only net-margin modal for an IMEI, priced at the IMEI's
|
| - |
|
794 |
* purchase-billed date (the date schemes were locked in when the
|
| - |
|
795 |
* partner was billed-in). Offers are intentionally excluded.
|
| - |
|
796 |
*/
|
| - |
|
797 |
@RequestMapping(value = "/getImeiNetMarginModal", method = RequestMethod.GET)
|
| - |
|
798 |
public String getImeiNetMarginModal(HttpServletRequest request,
|
| - |
|
799 |
@RequestParam(defaultValue = "") String searchImei,
|
| - |
|
800 |
@RequestParam int fofoId,
|
| - |
|
801 |
Model model) throws ProfitMandiBusinessException {
|
| - |
|
802 |
|
| - |
|
803 |
model.addAttribute("searchImei", searchImei);
|
| - |
|
804 |
model.addAttribute("fofoId", fofoId);
|
| - |
|
805 |
|
| - |
|
806 |
if (StringUtils.isBlank(searchImei)) {
|
| - |
|
807 |
model.addAttribute("errorMessage", "Please enter an IMEI.");
|
| - |
|
808 |
return "imei-net-margin-modal";
|
| - |
|
809 |
}
|
| - |
|
810 |
|
| - |
|
811 |
InventoryItem inventoryItem = inventoryItemRepository.selectBySerialNumber(searchImei);
|
| - |
|
812 |
if (inventoryItem == null) {
|
| - |
|
813 |
model.addAttribute("errorMessage", "IMEI not found.");
|
| - |
|
814 |
return "imei-net-margin-modal";
|
| - |
|
815 |
}
|
| - |
|
816 |
if (inventoryItem.getFofoId() != fofoId) {
|
| - |
|
817 |
model.addAttribute("errorMessage", "IMEI not found for this partner.");
|
| - |
|
818 |
return "imei-net-margin-modal";
|
| - |
|
819 |
}
|
| - |
|
820 |
|
| - |
|
821 |
List<ItemPurchaseSummaryModel> purchaseSummaries = inventoryItemRepository
|
| - |
|
822 |
.selectPurchaseSummary(Arrays.asList(inventoryItem.getId()));
|
| - |
|
823 |
if (purchaseSummaries.isEmpty() || purchaseSummaries.get(0).getInvoiceDate() == null) {
|
| - |
|
824 |
model.addAttribute("errorMessage", "IMEI not yet billed-in — margin unavailable.");
|
| - |
|
825 |
return "imei-net-margin-modal";
|
| - |
|
826 |
}
|
| - |
|
827 |
ItemPurchaseSummaryModel purchaseSummary = purchaseSummaries.get(0);
|
| - |
|
828 |
LocalDate billedDate = purchaseSummary.getInvoiceDate().toLocalDate();
|
| - |
|
829 |
|
| - |
|
830 |
Item item = purchaseSummary.getItem() != null
|
| - |
|
831 |
? purchaseSummary.getItem()
|
| - |
|
832 |
: itemRepository.selectById(inventoryItem.getItemId());
|
| - |
|
833 |
int catalogId = item.getCatalogItemId();
|
| - |
|
834 |
|
| - |
|
835 |
PriceCircularModel priceCircularModel = priceCircularService
|
| - |
|
836 |
.getPriceCircularByOffer(fofoId, Arrays.asList(catalogId), billedDate);
|
| - |
|
837 |
|
| - |
|
838 |
com.spice.profitmandi.service.pricecircular.PriceCircularItemModelNew itemModel = null;
|
| - |
|
839 |
if (priceCircularModel != null && priceCircularModel.getPriceCircularItemModelNews() != null) {
|
| - |
|
840 |
itemModel = priceCircularModel.getPriceCircularItemModelNews().stream()
|
| - |
|
841 |
.filter(x -> x.getCatalogId() == catalogId)
|
| - |
|
842 |
.findFirst().orElse(null);
|
| - |
|
843 |
}
|
| - |
|
844 |
|
| - |
|
845 |
// Use the same DP basis as SchemeServiceImpl.createSchemeInOut →
|
| - |
|
846 |
// PriceCircularService.getPayouts: actual purchase price stamped on
|
| - |
|
847 |
// inventory_item at GRN time, minus any price-drop credited against
|
| - |
|
848 |
// it. This is what the persisted scheme_in_out.amount values were
|
| - |
|
849 |
// computed against.
|
| - |
|
850 |
double purchasePrice = inventoryItem.getUnitPrice();
|
| - |
|
851 |
double priceDropAmount = Math.max(0d, inventoryItem.getPriceDropAmount());
|
| - |
|
852 |
double effectiveDP = purchasePrice - priceDropAmount;
|
| - |
|
853 |
|
| - |
|
854 |
// Pull per-IMEI price-drop history for reference display.
|
| - |
|
855 |
List<PriceDropIMEI> priceDropImeis = priceDropIMEIRepository
|
| - |
|
856 |
.selectByFofoIdImei(fofoId, searchImei);
|
| - |
|
857 |
if (priceDropImeis != null && !priceDropImeis.isEmpty()) {
|
| - |
|
858 |
List<Integer> priceDropIds = priceDropImeis.stream()
|
| - |
|
859 |
.map(PriceDropIMEI::getPriceDropId).distinct().collect(Collectors.toList());
|
| - |
|
860 |
Map<Integer, PriceDrop> priceDropMap = priceDropRepository.selectByIds(priceDropIds)
|
| - |
|
861 |
.stream().collect(Collectors.toMap(PriceDrop::getId, x -> x));
|
| - |
|
862 |
for (PriceDropIMEI pdi : priceDropImeis) {
|
| - |
|
863 |
pdi.setPriceDrop(priceDropMap.get(pdi.getPriceDropId()));
|
| - |
|
864 |
}
|
| - |
|
865 |
}
|
| - |
|
866 |
|
| - |
|
867 |
model.addAttribute("imei", searchImei);
|
| - |
|
868 |
model.addAttribute("billedDate", billedDate);
|
| - |
|
869 |
model.addAttribute("invoiceNumber", purchaseSummary.getInvoiceNumber());
|
| - |
|
870 |
model.addAttribute("modelName", item.getItemDescriptionNoColor());
|
| - |
|
871 |
model.addAttribute("purchasePrice", fmt2(purchasePrice));
|
| - |
|
872 |
model.addAttribute("priceDropAmount", fmt2(priceDropAmount));
|
| - |
|
873 |
model.addAttribute("hasPriceDrop", priceDropAmount > 0d);
|
| - |
|
874 |
model.addAttribute("priceDropImeis", priceDropImeis == null ? Collections.emptyList() : priceDropImeis);
|
| - |
|
875 |
|
| - |
|
876 |
if (itemModel == null || itemModel.getSchemeSummaryModels() == null
|
| - |
|
877 |
|| itemModel.getSchemeSummaryModels().isEmpty()) {
|
| - |
|
878 |
model.addAttribute("noSchemes", true);
|
| - |
|
879 |
model.addAttribute("dp", fmt2(effectiveDP));
|
| - |
|
880 |
model.addAttribute("schemeSummaryModels", Collections.emptyList());
|
| - |
|
881 |
model.addAttribute("contributionMap", Collections.emptyMap());
|
| - |
|
882 |
model.addAttribute("rateMap", Collections.emptyMap());
|
| - |
|
883 |
model.addAttribute("fixedSchemeAmount", fmt2(0d));
|
| - |
|
884 |
model.addAttribute("percentageSchemeAmount", fmt2(0d));
|
| - |
|
885 |
model.addAttribute("nlc", fmt2(effectiveDP));
|
| - |
|
886 |
model.addAttribute("netMargin", fmt2(0d));
|
| - |
|
887 |
return "imei-net-margin-modal";
|
| - |
|
888 |
}
|
| - |
|
889 |
|
| - |
|
890 |
double fixedTotal = itemModel.getFixedSchemeAmount();
|
| - |
|
891 |
double percentageTotal = itemModel.getPercentageSchemeAmount();
|
| - |
|
892 |
// Recompute NLC against effectiveDP — do NOT reuse
|
| - |
|
893 |
// PriceCircularItemModelNew.getNlc() because it is derived from the
|
| - |
|
894 |
// current TagListing list-DP, not the partner's actual purchase price.
|
| - |
|
895 |
double nlc = (effectiveDP - fixedTotal) / (1d + percentageTotal / 100d);
|
| - |
|
896 |
double netMargin = effectiveDP - nlc;
|
| - |
|
897 |
|
| - |
|
898 |
Map<Integer, String> contributionMap = new HashMap<>();
|
| - |
|
899 |
Map<Integer, String> rateMap = new HashMap<>();
|
| - |
|
900 |
for (com.spice.profitmandi.service.pricecircular.SchemeSummaryModel ssm : itemModel.getSchemeSummaryModels()) {
|
| - |
|
901 |
double contribution;
|
| - |
|
902 |
if (ssm.getAmountType() == AmountType.FIXED) {
|
| - |
|
903 |
contribution = ssm.getAmount() == null ? 0d : ssm.getAmount();
|
| - |
|
904 |
} else if (ssm.getAmountType() == AmountType.PERCENTAGE && percentageTotal > 0) {
|
| - |
|
905 |
double pct = ssm.getAmount() == null ? 0d : ssm.getAmount();
|
| - |
|
906 |
contribution = effectiveDP * (pct / (100d + percentageTotal));
|
| - |
|
907 |
} else {
|
| - |
|
908 |
contribution = 0d;
|
| - |
|
909 |
}
|
| - |
|
910 |
contributionMap.put(ssm.getSchemeId(), fmt2(contribution));
|
| - |
|
911 |
double rate = ssm.getAmount() == null ? 0d : ssm.getAmount();
|
| - |
|
912 |
String rateStr = ssm.getAmountType() == AmountType.PERCENTAGE
|
| - |
|
913 |
? fmt2(rate) + "%"
|
| - |
|
914 |
: "₹ " + fmt2(rate);
|
| - |
|
915 |
rateMap.put(ssm.getSchemeId(), rateStr);
|
| - |
|
916 |
}
|
| - |
|
917 |
|
| - |
|
918 |
model.addAttribute("noSchemes", false);
|
| - |
|
919 |
model.addAttribute("dp", fmt2(effectiveDP));
|
| - |
|
920 |
model.addAttribute("schemeSummaryModels", itemModel.getSchemeSummaryModels());
|
| - |
|
921 |
model.addAttribute("contributionMap", contributionMap);
|
| - |
|
922 |
model.addAttribute("rateMap", rateMap);
|
| - |
|
923 |
model.addAttribute("fixedSchemeAmount", fmt2(fixedTotal));
|
| - |
|
924 |
model.addAttribute("percentageSchemeAmount", fmt2(percentageTotal));
|
| - |
|
925 |
model.addAttribute("nlc", fmt2(nlc));
|
| - |
|
926 |
model.addAttribute("netMargin", fmt2(netMargin));
|
| - |
|
927 |
|
| - |
|
928 |
return "imei-net-margin-modal";
|
| - |
|
929 |
}
|
| - |
|
930 |
|
| - |
|
931 |
private static String fmt2(double v) {
|
| - |
|
932 |
return String.format(Locale.ENGLISH, "%.2f", v);
|
| - |
|
933 |
}
|
| - |
|
934 |
|
| - |
|
935 |
/**
|
| 795 |
* New endpoint for modal model-wise margin search
|
936 |
* New endpoint for modal model-wise margin search
|
| 796 |
* Accepts fofoId as parameter to work for both admin and partner views
|
937 |
* Accepts fofoId as parameter to work for both admin and partner views
|
| 797 |
*/
|
938 |
*/
|
| 798 |
@RequestMapping(value = "/getModelMarginModal", method = RequestMethod.GET)
|
939 |
@RequestMapping(value = "/getModelMarginModal", method = RequestMethod.GET)
|
| 799 |
public String getModelMarginModal(HttpServletRequest request,
|
940 |
public String getModelMarginModal(HttpServletRequest request,
|
| Line 1530... |
Line 1671... |
| 1530 |
throws ProfitMandiBusinessException {
|
1671 |
throws ProfitMandiBusinessException {
|
| 1531 |
LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
|
1672 |
LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
|
| 1532 |
|
1673 |
|
| 1533 |
boolean fullAccess = this.getAccess(loginDetails.getEmailId());
|
1674 |
boolean fullAccess = this.getAccess(loginDetails.getEmailId());
|
| 1534 |
Scheme scheme = schemeService.getSchemeById(schemeId);
|
1675 |
Scheme scheme = schemeService.getSchemeById(schemeId);
|
| - |
|
1676 |
List<SchemeItem> schemeItems = schemeItemRepository.selectBySchemeId(schemeId);
|
| - |
|
1677 |
List<Category> categories = categoryRepository.selectByIds(categoryIds);
|
| - |
|
1678 |
categories = categories.stream().sorted(Comparator.comparing(Category::getId)).collect(Collectors.toList());
|
| 1535 |
model.addAttribute("fullAccess", fullAccess);
|
1679 |
model.addAttribute("fullAccess", fullAccess);
|
| 1536 |
model.addAttribute("scheme", scheme);
|
1680 |
model.addAttribute("scheme", scheme);
|
| - |
|
1681 |
model.addAttribute("schemeItems", schemeItems);
|
| - |
|
1682 |
model.addAttribute("categories", categories);
|
| 1537 |
model.addAttribute("isAdmin", roleManager.isAdmin(loginDetails.getRoleIds()));
|
1683 |
model.addAttribute("isAdmin", roleManager.isAdmin(loginDetails.getRoleIds()));
|
| 1538 |
return "scheme-details";
|
1684 |
return "scheme-details";
|
| 1539 |
}
|
1685 |
}
|
| 1540 |
|
1686 |
|
| 1541 |
@RequestMapping(value = "/activeSchemeById", method = RequestMethod.PUT)
|
1687 |
@RequestMapping(value = "/activeSchemeById", method = RequestMethod.PUT)
|
| Line 1580... |
Line 1726... |
| 1580 |
throws ProfitMandiBusinessException {
|
1726 |
throws ProfitMandiBusinessException {
|
| 1581 |
schemeService.expireSchemeById(schemeId, expiryTimestamp);
|
1727 |
schemeService.expireSchemeById(schemeId, expiryTimestamp);
|
| 1582 |
return getDefaultSchemes(request, model);
|
1728 |
return getDefaultSchemes(request, model);
|
| 1583 |
}
|
1729 |
}
|
| 1584 |
|
1730 |
|
| - |
|
1731 |
@RequestMapping(value = "/scheme/item/window", method = RequestMethod.PUT)
|
| - |
|
1732 |
public ResponseEntity<?> updateSchemeItemWindow(HttpServletRequest request,
|
| - |
|
1733 |
@RequestParam(name = "schemeItemId") long schemeItemId,
|
| - |
|
1734 |
@RequestParam(name = "startDate") LocalDateTime startDate,
|
| - |
|
1735 |
@RequestParam(name = "endDate") LocalDateTime endDate)
|
| - |
|
1736 |
throws ProfitMandiBusinessException {
|
| - |
|
1737 |
LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
|
| - |
|
1738 |
schemeService.updateSchemeItemWindow(schemeItemId, startDate, endDate, loginDetails.getFofoId());
|
| - |
|
1739 |
return responseSender.ok("Scheme item window updated");
|
| - |
|
1740 |
}
|
| - |
|
1741 |
|
| - |
|
1742 |
@RequestMapping(value = "/scheme/item/add", method = RequestMethod.POST)
|
| - |
|
1743 |
public ResponseEntity<?> addSchemeItemWithDates(HttpServletRequest request,
|
| - |
|
1744 |
@RequestParam(name = "schemeId") int schemeId,
|
| - |
|
1745 |
@RequestParam(name = "catalogId") int catalogId,
|
| - |
|
1746 |
@RequestParam(name = "startDate") LocalDateTime startDate,
|
| - |
|
1747 |
@RequestParam(name = "endDate") LocalDateTime endDate)
|
| - |
|
1748 |
throws ProfitMandiBusinessException {
|
| - |
|
1749 |
LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
|
| - |
|
1750 |
SchemeItem item = schemeService.addSchemeItemWithDates(schemeId, catalogId, startDate, endDate, loginDetails.getFofoId());
|
| - |
|
1751 |
return responseSender.ok(item);
|
| - |
|
1752 |
}
|
| - |
|
1753 |
|
| - |
|
1754 |
@RequestMapping(value = "/scheme/items", method = RequestMethod.GET)
|
| - |
|
1755 |
public ResponseEntity<?> getSchemeItems(@RequestParam(name = "schemeId") int schemeId)
|
| - |
|
1756 |
throws ProfitMandiBusinessException {
|
| - |
|
1757 |
List<SchemeItem> items = schemeItemRepository.selectBySchemeId(schemeId);
|
| - |
|
1758 |
return responseSender.ok(items);
|
| - |
|
1759 |
}
|
| - |
|
1760 |
|
| 1585 |
@RequestMapping(value = "/getSchemesJson", method = RequestMethod.GET)
|
1761 |
@RequestMapping(value = "/getSchemesJson", method = RequestMethod.GET)
|
| 1586 |
public ResponseEntity<?> getSchemesJson(HttpServletRequest request,
|
1762 |
public ResponseEntity<?> getSchemesJson(HttpServletRequest request,
|
| 1587 |
@RequestParam(name = "offset", defaultValue = "0") int offset,
|
1763 |
@RequestParam(name = "offset", defaultValue = "0") int offset,
|
| 1588 |
@RequestParam(name = "limit", defaultValue = "10") int limit, Model model)
|
1764 |
@RequestParam(name = "limit", defaultValue = "10") int limit, Model model)
|
| 1589 |
throws ProfitMandiBusinessException {
|
1765 |
throws ProfitMandiBusinessException {
|