| Line 533... |
Line 533... |
| 533 |
|
533 |
|
| 534 |
LocalDate today = LocalDate.now();
|
534 |
LocalDate today = LocalDate.now();
|
| 535 |
LocalDateTime stamp = date.equals(today) ? LocalDateTime.now() : date.atTime(java.time.LocalTime.NOON);
|
535 |
LocalDateTime stamp = date.equals(today) ? LocalDateTime.now() : date.atTime(java.time.LocalTime.NOON);
|
| 536 |
int written = 0, zeroTargetSkipped = 0;
|
536 |
int written = 0, zeroTargetSkipped = 0;
|
| 537 |
|
537 |
|
| - |
|
538 |
// Cache monthly targets + MTD ACH per level so the RSM/NSM roll-up
|
| - |
|
539 |
// pass can reuse them without repeating queries.
|
| - |
|
540 |
Map<String, List<SalesHierarchyMonthlyTargetModel>> mtByLevel = new HashMap<>();
|
| - |
|
541 |
Map<String, Map<String, Double>> mtdByLevelKey = new HashMap<>();
|
| - |
|
542 |
|
| 538 |
for (String[] r : roles) {
|
543 |
for (String[] r : roles) {
|
| 539 |
String role = r[0];
|
544 |
String role = r[0];
|
| 540 |
int catId = Integer.parseInt(r[1]);
|
545 |
int catId = Integer.parseInt(r[1]);
|
| 541 |
String levelStr = r[2];
|
546 |
String levelStr = r[2];
|
| 542 |
|
547 |
|
| 543 |
// Monthly target per (authId × warehouse) for this role.
|
- |
|
| 544 |
// Use the target date's month so backfills for past months work correctly.
|
- |
|
| 545 |
List<SalesHierarchyMonthlyTargetModel> monthlyTgts = getSalesMonthlyTargetByRole(catId, levelStr, date);
|
548 |
List<SalesHierarchyMonthlyTargetModel> monthlyTgts = getSalesMonthlyTargetByRole(catId, levelStr, date);
|
| 546 |
if (monthlyTgts.isEmpty()) continue;
|
549 |
mtByLevel.put(role, monthlyTgts);
|
| 547 |
|
550 |
|
| 548 |
// MTD achieved per (authId × warehouse) for this role. Same-day date range → MTD.
|
- |
|
| 549 |
Map<String, Double> mtdByKey = new HashMap<>();
|
551 |
Map<String, Double> mtdByKey = new HashMap<>();
|
| 550 |
for (SalesHierarchyAchievedByMovementModel a :
|
552 |
for (SalesHierarchyAchievedByMovementModel a :
|
| 551 |
getSalesAchievementByRole(catId, levelStr, monthStart, date.plusDays(1))) {
|
553 |
getSalesAchievementByRole(catId, levelStr, monthStart, date.plusDays(1))) {
|
| 552 |
double totBilled =
|
554 |
double totBilled =
|
| 553 |
a.getHidBilled()
|
555 |
a.getHidBilled()
|
| Line 555... |
Line 557... |
| 555 |
+ (a.getRunningBilled() != null ? a.getRunningBilled() : 0)
|
557 |
+ (a.getRunningBilled() != null ? a.getRunningBilled() : 0)
|
| 556 |
+ (a.getSlowMovingBilled() != null ? a.getSlowMovingBilled() : 0)
|
558 |
+ (a.getSlowMovingBilled() != null ? a.getSlowMovingBilled() : 0)
|
| 557 |
+ (a.getOtherBilled() != null ? a.getOtherBilled() : 0);
|
559 |
+ (a.getOtherBilled() != null ? a.getOtherBilled() : 0);
|
| 558 |
mtdByKey.merge(a.getAuthId() + "-" + a.getWarehouseId(), totBilled, Double::sum);
|
560 |
mtdByKey.merge(a.getAuthId() + "-" + a.getWarehouseId(), totBilled, Double::sum);
|
| 559 |
}
|
561 |
}
|
| - |
|
562 |
mtdByLevelKey.put(role, mtdByKey);
|
| 560 |
|
563 |
|
| - |
|
564 |
// Direct-role writer — one row per (authId × warehouse) at this role.
|
| - |
|
565 |
if (monthlyTgts.isEmpty()) continue;
|
| 561 |
for (SalesHierarchyMonthlyTargetModel mt : monthlyTgts) {
|
566 |
for (SalesHierarchyMonthlyTargetModel mt : monthlyTgts) {
|
| 562 |
if (mt.getMonthlyTarget() <= 0) {
|
567 |
if (mt.getMonthlyTarget() <= 0) {
|
| 563 |
zeroTargetSkipped++;
|
568 |
zeroTargetSkipped++;
|
| 564 |
continue;
|
569 |
continue;
|
| 565 |
}
|
570 |
}
|
| Line 585... |
Line 590... |
| 585 |
st.setCreateTimestamp(stamp);
|
590 |
st.setCreateTimestamp(stamp);
|
| 586 |
salesTargetsRepository.persist(st);
|
591 |
salesTargetsRepository.persist(st);
|
| 587 |
written++;
|
592 |
written++;
|
| 588 |
}
|
593 |
}
|
| 589 |
}
|
594 |
}
|
| - |
|
595 |
|
| - |
|
596 |
// Roll-up pass for RSM (L5) and NSM (L6) — uses distinct-partner dedup
|
| - |
|
597 |
// queries so partners assigned to multiple positions in the downline
|
| - |
|
598 |
// aren't counted more than once.
|
| - |
|
599 |
String[] rollUpRoles = {"RSM", "NSM"};
|
| - |
|
600 |
for (String rollUpRole : rollUpRoles) {
|
| - |
|
601 |
String levelStr = "RSM".equals(rollUpRole) ? "L5" : "L6";
|
| - |
|
602 |
for (AuthUser top : csService.getAuthUserByCategoryId(4, EscalationType.valueOf(levelStr))) {
|
| - |
|
603 |
if (!top.isActive()) continue;
|
| - |
|
604 |
Set<Integer> tree = new HashSet<>();
|
| - |
|
605 |
tree.add(top.getId());
|
| - |
|
606 |
List<Integer> reportees = authService.getAllReportees(top.getId());
|
| - |
|
607 |
if (reportees != null) tree.addAll(reportees);
|
| - |
|
608 |
if (tree.isEmpty()) continue;
|
| - |
|
609 |
|
| - |
|
610 |
// Distinct-partner monthly TGT per warehouse for the downline.
|
| - |
|
611 |
Map<Integer, Double> monthlyByWh = new LinkedHashMap<>();
|
| - |
|
612 |
for (com.spice.profitmandi.dao.model.SalesDownlineMonthlyTargetModel d :
|
| - |
|
613 |
getSalesDownlineMonthlyTarget(tree, date)) {
|
| - |
|
614 |
monthlyByWh.put(d.getWarehouseId(), (double) d.getMonthlyTarget());
|
| - |
|
615 |
}
|
| - |
|
616 |
// Distinct-partner MTD ACH per warehouse for the downline.
|
| - |
|
617 |
Map<Integer, Double> mtdByWh = new HashMap<>();
|
| - |
|
618 |
for (com.spice.profitmandi.dao.model.SalesDownlineAchievedByMovementModel d :
|
| - |
|
619 |
getSalesDownlineAchievement(tree, monthStart, date.plusDays(1))) {
|
| - |
|
620 |
double tot = d.getHidBilled() + d.getFastMovingBilled()
|
| - |
|
621 |
+ (d.getRunningBilled() != null ? d.getRunningBilled() : 0)
|
| - |
|
622 |
+ (d.getSlowMovingBilled() != null ? d.getSlowMovingBilled() : 0)
|
| - |
|
623 |
+ (d.getOtherBilled() != null ? d.getOtherBilled() : 0);
|
| - |
|
624 |
mtdByWh.put(d.getWarehouseId(), tot);
|
| - |
|
625 |
}
|
| - |
|
626 |
|
| - |
|
627 |
for (Map.Entry<Integer, Double> e : monthlyByWh.entrySet()) {
|
| - |
|
628 |
int whId = e.getKey();
|
| - |
|
629 |
double monthlyTgt = e.getValue();
|
| - |
|
630 |
if (monthlyTgt <= 0) {
|
| - |
|
631 |
zeroTargetSkipped++;
|
| - |
|
632 |
continue;
|
| - |
|
633 |
}
|
| - |
|
634 |
double achieved = mtdByWh.getOrDefault(whId, 0.0);
|
| - |
|
635 |
double remaining = monthlyTgt - achieved;
|
| - |
|
636 |
double todayTarget = (remainingWorkingDays > 0 && remaining > 0)
|
| - |
|
637 |
? remaining / remainingWorkingDays : 0;
|
| - |
|
638 |
|
| - |
|
639 |
WarehouseMobileStockByMovementModel stock = whStockByWh.get(whId);
|
| - |
|
640 |
if (stock == null || stock.getTotalAvailabilityPrice() <= 0) continue;
|
| - |
|
641 |
float total = stock.getTotalAvailabilityPrice();
|
| - |
|
642 |
|
| - |
|
643 |
SalesTargets st = new SalesTargets();
|
| - |
|
644 |
st.setSalesAuthId(top.getId());
|
| - |
|
645 |
st.setSalesName(top.getFullName());
|
| - |
|
646 |
st.setRole(rollUpRole);
|
| - |
|
647 |
st.setWarehouseId(whId);
|
| - |
|
648 |
st.setHidTarget((float) ((stock.getTotalHidCatalogPrice() / total) * todayTarget));
|
| - |
|
649 |
st.setFastMovingTarget((float) ((stock.getTotalFastMovingCatalogPrice() / total) * todayTarget));
|
| - |
|
650 |
st.setSlowMovingTarget((float) ((stock.getTotalSlowMovingCatalogPrice() / total) * todayTarget));
|
| - |
|
651 |
st.setRunningTarget((float) ((stock.getTotalRunningCatalogPrice() / total) * todayTarget));
|
| - |
|
652 |
st.setOtherTarget((float) ((stock.getTotalOtherCategoryCatalogPrice() / total) * todayTarget));
|
| - |
|
653 |
st.setCreateTimestamp(stamp);
|
| - |
|
654 |
salesTargetsRepository.persist(st);
|
| - |
|
655 |
written++;
|
| - |
|
656 |
}
|
| - |
|
657 |
}
|
| - |
|
658 |
}
|
| 590 |
LOGGER.info("setSalesTargetsForDate: wrote {} sales_targets rows for {} ({} rows skipped due to zero monthly target)",
|
659 |
LOGGER.info("setSalesTargetsForDate: wrote {} sales_targets rows for {} ({} rows skipped due to zero monthly target)",
|
| 591 |
written, date, zeroTargetSkipped);
|
660 |
written, date, zeroTargetSkipped);
|
| 592 |
}
|
661 |
}
|
| 593 |
|
662 |
|
| 594 |
@Override
|
663 |
@Override
|
| Line 620... |
Line 689... |
| 620 |
q.setParameter("refDate", refDate);
|
689 |
q.setParameter("refDate", refDate);
|
| 621 |
return q.getResultList();
|
690 |
return q.getResultList();
|
| 622 |
}
|
691 |
}
|
| 623 |
|
692 |
|
| 624 |
@Override
|
693 |
@Override
|
| - |
|
694 |
public List<com.spice.profitmandi.dao.model.SalesDownlineAchievedByMovementModel>
|
| - |
|
695 |
getSalesDownlineAchievement(Collection<Integer> authIds, LocalDate startDate, LocalDate endDate) {
|
| - |
|
696 |
if (authIds == null || authIds.isEmpty()) return new ArrayList<>();
|
| - |
|
697 |
Session session = sessionFactory.getCurrentSession();
|
| - |
|
698 |
TypedQuery<com.spice.profitmandi.dao.model.SalesDownlineAchievedByMovementModel> q =
|
| - |
|
699 |
session.createNamedQuery("RbmDrr.SalesDownlineAchievedByMovement",
|
| - |
|
700 |
com.spice.profitmandi.dao.model.SalesDownlineAchievedByMovementModel.class);
|
| - |
|
701 |
q.setParameter("authIds", authIds);
|
| - |
|
702 |
q.setParameter("startDate", startDate);
|
| - |
|
703 |
q.setParameter("endDate", endDate);
|
| - |
|
704 |
return q.getResultList();
|
| - |
|
705 |
}
|
| - |
|
706 |
|
| - |
|
707 |
@Override
|
| - |
|
708 |
public List<com.spice.profitmandi.dao.model.SalesDownlineMonthlyTargetModel>
|
| - |
|
709 |
getSalesDownlineMonthlyTarget(Collection<Integer> authIds, LocalDate refDate) {
|
| - |
|
710 |
if (authIds == null || authIds.isEmpty()) return new ArrayList<>();
|
| - |
|
711 |
Session session = sessionFactory.getCurrentSession();
|
| - |
|
712 |
TypedQuery<com.spice.profitmandi.dao.model.SalesDownlineMonthlyTargetModel> q =
|
| - |
|
713 |
session.createNamedQuery("RbmDrr.SalesDownlineMonthlyTarget",
|
| - |
|
714 |
com.spice.profitmandi.dao.model.SalesDownlineMonthlyTargetModel.class);
|
| - |
|
715 |
q.setParameter("authIds", authIds);
|
| - |
|
716 |
q.setParameter("refDate", refDate);
|
| - |
|
717 |
return q.getResultList();
|
| - |
|
718 |
}
|
| - |
|
719 |
|
| - |
|
720 |
@Override
|
| 625 |
public void setSalesAchievements() {
|
721 |
public void setSalesAchievements() {
|
| 626 |
setSalesAchievementsForDate(LocalDate.now());
|
722 |
setSalesAchievementsForDate(LocalDate.now());
|
| 627 |
}
|
723 |
}
|
| 628 |
|
724 |
|
| 629 |
@Override
|
725 |
@Override
|
| Line 637... |
Line 733... |
| 637 |
|
733 |
|
| 638 |
LocalDate today = LocalDate.now();
|
734 |
LocalDate today = LocalDate.now();
|
| 639 |
LocalDateTime stamp = date.equals(today) ? LocalDateTime.now() : date.atTime(java.time.LocalTime.NOON);
|
735 |
LocalDateTime stamp = date.equals(today) ? LocalDateTime.now() : date.atTime(java.time.LocalTime.NOON);
|
| 640 |
int written = 0;
|
736 |
int written = 0;
|
| 641 |
|
737 |
|
| - |
|
738 |
// Cache per-level results so the RSM/NSM roll-up pass reuses them.
|
| - |
|
739 |
Map<String, List<SalesHierarchyAchievedByMovementModel>> byLevel = new HashMap<>();
|
| 642 |
for (String[] r : roles) {
|
740 |
for (String[] r : roles) {
|
| 643 |
String role = r[0];
|
741 |
String role = r[0];
|
| 644 |
int catId = Integer.parseInt(r[1]);
|
742 |
int catId = Integer.parseInt(r[1]);
|
| 645 |
String levelStr = r[2];
|
743 |
String levelStr = r[2];
|
| 646 |
|
744 |
|
| 647 |
for (SalesHierarchyAchievedByMovementModel a :
|
745 |
List<SalesHierarchyAchievedByMovementModel> list =
|
| 648 |
getSalesAchievementByRole(catId, levelStr, date, date.plusDays(1))) {
|
746 |
getSalesAchievementByRole(catId, levelStr, date, date.plusDays(1));
|
| - |
|
747 |
byLevel.put(role, list);
|
| - |
|
748 |
for (SalesHierarchyAchievedByMovementModel a : list) {
|
| 649 |
SalesAchievements sa = new SalesAchievements();
|
749 |
SalesAchievements sa = new SalesAchievements();
|
| 650 |
sa.setSalesAuthId(a.getAuthId());
|
750 |
sa.setSalesAuthId(a.getAuthId());
|
| 651 |
sa.setSalesName(a.getName());
|
751 |
sa.setSalesName(a.getName());
|
| 652 |
sa.setRole(role);
|
752 |
sa.setRole(role);
|
| 653 |
sa.setWarehouseId(a.getWarehouseId());
|
753 |
sa.setWarehouseId(a.getWarehouseId());
|
| Line 659... |
Line 759... |
| 659 |
sa.setCreateTimestamp(stamp);
|
759 |
sa.setCreateTimestamp(stamp);
|
| 660 |
salesAchievementsRepository.persist(sa);
|
760 |
salesAchievementsRepository.persist(sa);
|
| 661 |
written++;
|
761 |
written++;
|
| 662 |
}
|
762 |
}
|
| 663 |
}
|
763 |
}
|
| - |
|
764 |
|
| - |
|
765 |
// Roll-up pass for RSM (L5) and NSM (L6) — uses distinct-partner dedup
|
| - |
|
766 |
// query so partners assigned to multiple positions in the downline
|
| - |
|
767 |
// don't have their orders counted more than once.
|
| - |
|
768 |
String[] rollUpRoles = {"RSM", "NSM"};
|
| - |
|
769 |
for (String rollUpRole : rollUpRoles) {
|
| - |
|
770 |
String levelStr = "RSM".equals(rollUpRole) ? "L5" : "L6";
|
| - |
|
771 |
for (AuthUser top : csService.getAuthUserByCategoryId(4, EscalationType.valueOf(levelStr))) {
|
| - |
|
772 |
if (!top.isActive()) continue;
|
| - |
|
773 |
Set<Integer> tree = new HashSet<>();
|
| - |
|
774 |
tree.add(top.getId());
|
| - |
|
775 |
List<Integer> reportees = authService.getAllReportees(top.getId());
|
| - |
|
776 |
if (reportees != null) tree.addAll(reportees);
|
| - |
|
777 |
if (tree.isEmpty()) continue;
|
| - |
|
778 |
|
| - |
|
779 |
for (com.spice.profitmandi.dao.model.SalesDownlineAchievedByMovementModel d :
|
| - |
|
780 |
getSalesDownlineAchievement(tree, date, date.plusDays(1))) {
|
| - |
|
781 |
SalesAchievements sa = new SalesAchievements();
|
| - |
|
782 |
sa.setSalesAuthId(top.getId());
|
| - |
|
783 |
sa.setSalesName(top.getFullName());
|
| - |
|
784 |
sa.setRole(rollUpRole);
|
| - |
|
785 |
sa.setWarehouseId(d.getWarehouseId());
|
| - |
|
786 |
sa.setAchievedHidTarget(d.getHidBilled());
|
| - |
|
787 |
sa.setAchievedFastMovingTarget(d.getFastMovingBilled());
|
| - |
|
788 |
sa.setAchievedRunningTarget(d.getRunningBilled() != null ? d.getRunningBilled() : 0f);
|
| - |
|
789 |
sa.setAchievedSlowMovingTarget(d.getSlowMovingBilled() != null ? d.getSlowMovingBilled() : 0f);
|
| - |
|
790 |
sa.setAchievedOtherTarget(d.getOtherBilled() != null ? d.getOtherBilled() : 0f);
|
| - |
|
791 |
sa.setCreateTimestamp(stamp);
|
| - |
|
792 |
salesAchievementsRepository.persist(sa);
|
| - |
|
793 |
written++;
|
| - |
|
794 |
}
|
| - |
|
795 |
}
|
| - |
|
796 |
}
|
| 664 |
LOGGER.info("setSalesAchievementsForDate: wrote {} sales_achievements rows for {}", written, date);
|
797 |
LOGGER.info("setSalesAchievementsForDate: wrote {} sales_achievements rows for {}", written, date);
|
| 665 |
}
|
798 |
}
|
| 666 |
|
799 |
|
| 667 |
@Override
|
800 |
@Override
|
| 668 |
public void setMovementWiseRbmAchievement() {
|
801 |
public void setMovementWiseRbmAchievement() {
|