| Line 841... |
Line 841... |
| 841 |
ok.put("status", true);
|
841 |
ok.put("status", true);
|
| 842 |
ok.put("message", (isLead ? "Lead" : "Partner") + " added to beat '" + beat.getName() + "' on " + dateStr);
|
842 |
ok.put("message", (isLead ? "Lead" : "Partner") + " added to beat '" + beat.getName() + "' on " + dateStr);
|
| 843 |
return responseSender.ok(ok);
|
843 |
return responseSender.ok(ok);
|
| 844 |
}
|
844 |
}
|
| 845 |
|
845 |
|
| - |
|
846 |
// ==================== ASSIGN LEADS ONTO BEATS ====================
|
| - |
|
847 |
// A rep's assigned leads can be routed onto a beat from two surfaces:
|
| - |
|
848 |
// • Route Planner "Assigned Leads" list → single lead, calendar-chip picks beat+date
|
| - |
|
849 |
// • Day View "Add Lead" modal → bulk write onto a known beat+date
|
| - |
|
850 |
// Both converge on the same dated, APPROVED lead_route write (writeLeadRoute),
|
| - |
|
851 |
// mirroring VisitRequestController.approveSchedule and deferredAssignToBeat's
|
| - |
|
852 |
// lead branch. Nothing downstream changes — getBeatVisits and the
|
| - |
|
853 |
// /visit-approvals/beat-route feed already render lead_route rows for the run.
|
| - |
|
854 |
|
| - |
|
855 |
// Active/open lead colours a manager can still route (matches getOpenLead's
|
| - |
|
856 |
// All → yellow+green expansion). Red/other are dropped as not-worth-visiting.
|
| - |
|
857 |
private static final Set<String> ROUTABLE_LEAD_COLORS =
|
| - |
|
858 |
new HashSet<>(Arrays.asList("yellow", "green"));
|
| - |
|
859 |
|
| - |
|
860 |
// Can the caller see the selected user's leads? Super-admin sees everyone;
|
| - |
|
861 |
// otherwise the user must be the caller or in their downline.
|
| - |
|
862 |
private boolean canViewUserLeads(AuthUser me, int authUserId) {
|
| - |
|
863 |
if (me == null) return false;
|
| - |
|
864 |
if (isSuperAdmin(me)) return true;
|
| - |
|
865 |
if (me.getId() == authUserId) return true;
|
| - |
|
866 |
return new HashSet<>(authService.getAllReportees(me.getId())).contains(authUserId);
|
| - |
|
867 |
}
|
| - |
|
868 |
|
| - |
|
869 |
// GET /beatPlan/assignedLeads?authUserId=&beatId=&date=
|
| - |
|
870 |
// Lists the selected user's active/open leads (pending + follow-up, yellow/green).
|
| - |
|
871 |
// When beatId+date are supplied (Day View), each lead is tagged alreadyOnBeat if
|
| - |
|
872 |
// it already has a non-cancelled lead_route on that beat+date.
|
| - |
|
873 |
@GetMapping(value = "/beatPlan/assignedLeads")
|
| - |
|
874 |
public ResponseEntity<?> assignedLeads(
|
| - |
|
875 |
HttpServletRequest request,
|
| - |
|
876 |
@RequestParam int authUserId,
|
| - |
|
877 |
@RequestParam(required = false) Integer beatId,
|
| - |
|
878 |
@RequestParam(required = false) String date) throws ProfitMandiBusinessException {
|
| - |
|
879 |
|
| - |
|
880 |
AuthUser me = currentUser(request);
|
| - |
|
881 |
if (me == null) return responseSender.unauthorized("Not logged in");
|
| - |
|
882 |
if (!canViewUserLeads(me, authUserId)) {
|
| - |
|
883 |
// Not visible to this manager → empty (mirrors VisitRequestController.list).
|
| - |
|
884 |
return responseSender.ok(Collections.singletonMap("rows", new ArrayList<>()));
|
| - |
|
885 |
}
|
| - |
|
886 |
|
| - |
|
887 |
// Active/open only — pending + follow-up.
|
| - |
|
888 |
List<Lead> leads = new ArrayList<>();
|
| - |
|
889 |
leads.addAll(leadRepository.selectByAssignAuthIdAndStatus(
|
| - |
|
890 |
authUserId, com.spice.profitmandi.dao.enumuration.dtr.LeadStatus.pending));
|
| - |
|
891 |
leads.addAll(leadRepository.selectByAssignAuthIdAndStatus(
|
| - |
|
892 |
authUserId, com.spice.profitmandi.dao.enumuration.dtr.LeadStatus.followUp));
|
| - |
|
893 |
|
| - |
|
894 |
// Leads already on this beat+date (Day View only), to flag dupes in the picker.
|
| - |
|
895 |
LocalDate onDate = (date != null && !date.isEmpty()) ? LocalDate.parse(date) : null;
|
| - |
|
896 |
Set<Integer> alreadyOnBeat = new HashSet<>();
|
| - |
|
897 |
if (beatId != null && onDate != null) {
|
| - |
|
898 |
for (LeadRoute lr : leadRouteRepository.selectByBeatId(beatId)) {
|
| - |
|
899 |
if (onDate.equals(lr.getScheduleDate()) && !"CANCELLED".equals(lr.getStatus())) {
|
| - |
|
900 |
alreadyOnBeat.add(lr.getLeadId());
|
| - |
|
901 |
}
|
| - |
|
902 |
}
|
| - |
|
903 |
}
|
| - |
|
904 |
|
| - |
|
905 |
// Colour-filter + dedupe, then batch-resolve approved geo (avoids N+1).
|
| - |
|
906 |
List<Lead> routable = new ArrayList<>();
|
| - |
|
907 |
Set<Integer> seen = new HashSet<>();
|
| - |
|
908 |
for (Lead lead : leads) {
|
| - |
|
909 |
if (!seen.add(lead.getId())) continue;
|
| - |
|
910 |
String color = lead.getColor() != null ? lead.getColor().toLowerCase() : "";
|
| - |
|
911 |
if (!ROUTABLE_LEAD_COLORS.contains(color)) continue;
|
| - |
|
912 |
routable.add(lead);
|
| - |
|
913 |
}
|
| - |
|
914 |
Set<Integer> withGeo = new HashSet<>();
|
| - |
|
915 |
if (!routable.isEmpty()) {
|
| - |
|
916 |
List<Integer> ids = routable.stream().map(Lead::getId).collect(Collectors.toList());
|
| - |
|
917 |
for (com.spice.profitmandi.dao.entity.user.LeadLiveLocation loc :
|
| - |
|
918 |
leadLiveLocationRepositoryAuto.selectByLeadIds(ids)) {
|
| - |
|
919 |
if (loc.getStatus() != null && "APPROVED".equals(loc.getStatus().name())) {
|
| - |
|
920 |
withGeo.add(loc.getLeadId());
|
| - |
|
921 |
}
|
| - |
|
922 |
}
|
| - |
|
923 |
}
|
| - |
|
924 |
|
| - |
|
925 |
List<Map<String, Object>> rows = new ArrayList<>();
|
| - |
|
926 |
for (Lead lead : routable) {
|
| - |
|
927 |
Map<String, Object> m = new HashMap<>();
|
| - |
|
928 |
m.put("leadId", lead.getId());
|
| - |
|
929 |
String name = ((lead.getFirstName() != null ? lead.getFirstName() : "") + " "
|
| - |
|
930 |
+ (lead.getLastName() != null ? lead.getLastName() : "")).trim();
|
| - |
|
931 |
m.put("leadName", name.isEmpty() ? ("Lead #" + lead.getId()) : name);
|
| - |
|
932 |
m.put("outletName", lead.getOutLetName());
|
| - |
|
933 |
m.put("mobile", lead.getLeadMobile());
|
| - |
|
934 |
m.put("city", lead.getCity());
|
| - |
|
935 |
m.put("state", lead.getState());
|
| - |
|
936 |
m.put("stage", lead.getEffectiveStage() != null ? lead.getEffectiveStage().name() : "");
|
| - |
|
937 |
m.put("color", lead.getColor());
|
| - |
|
938 |
m.put("hasGeo", withGeo.contains(lead.getId()));
|
| - |
|
939 |
m.put("alreadyOnBeat", alreadyOnBeat.contains(lead.getId()));
|
| - |
|
940 |
rows.add(m);
|
| - |
|
941 |
}
|
| - |
|
942 |
|
| - |
|
943 |
return responseSender.ok(Collections.singletonMap("rows", rows));
|
| - |
|
944 |
}
|
| - |
|
945 |
|
| - |
|
946 |
// Shared, idempotent lead_route write. Returns true when a new row is created,
|
| - |
|
947 |
// false when the lead is already on that (beat, date). Best-effort nudges the
|
| - |
|
948 |
// lead forward to BEAT_PLANNED. Callers are responsible for the beat-runs-on-date
|
| - |
|
949 |
// and future-date guards. Mirrors deferredAssignToBeat's lead branch.
|
| - |
|
950 |
private boolean writeLeadRoute(int beatId, int leadId, LocalDate date, int approverAuthId) {
|
| - |
|
951 |
boolean exists = leadRouteRepository.selectByBeatId(beatId).stream()
|
| - |
|
952 |
.anyMatch(lr -> lr.getLeadId() == leadId
|
| - |
|
953 |
&& date.equals(lr.getScheduleDate())
|
| - |
|
954 |
&& !"CANCELLED".equals(lr.getStatus()));
|
| - |
|
955 |
if (exists) return false;
|
| - |
|
956 |
|
| - |
|
957 |
LocalDateTime now = LocalDateTime.now();
|
| - |
|
958 |
LeadRoute lr = new LeadRoute();
|
| - |
|
959 |
lr.setBeatId(beatId);
|
| - |
|
960 |
lr.setLeadId(leadId);
|
| - |
|
961 |
lr.setScheduleDate(date);
|
| - |
|
962 |
lr.setSequenceOrder(9999); // append; planner can reorder
|
| - |
|
963 |
lr.setStatus("APPROVED");
|
| - |
|
964 |
lr.setApprovedBy(approverAuthId);
|
| - |
|
965 |
lr.setApprovedTimestamp(now);
|
| - |
|
966 |
lr.setCreatedTimestamp(now);
|
| - |
|
967 |
lr.setUpdatedTimestamp(now);
|
| - |
|
968 |
leadRouteRepository.persist(lr);
|
| - |
|
969 |
|
| - |
|
970 |
advanceLeadToBeatPlanned(leadId);
|
| - |
|
971 |
return true;
|
| - |
|
972 |
}
|
| - |
|
973 |
|
| - |
|
974 |
// Best-effort: move a lead forward to BEAT_PLANNED when it's still in an earlier
|
| - |
|
975 |
// happy-path stage. Never regresses a VISITED+ lead and never aborts the caller's
|
| - |
|
976 |
// write on failure (the legacy status is kept in sync via toLegacyStatus()).
|
| - |
|
977 |
private void advanceLeadToBeatPlanned(int leadId) {
|
| - |
|
978 |
try {
|
| - |
|
979 |
Lead lead = leadRepository.selectById(leadId);
|
| - |
|
980 |
if (lead == null) return;
|
| - |
|
981 |
com.spice.profitmandi.dao.enumuration.dtr.LeadStage cur = lead.getEffectiveStage();
|
| - |
|
982 |
boolean beforeBeatPlanned =
|
| - |
|
983 |
cur == com.spice.profitmandi.dao.enumuration.dtr.LeadStage.NEW
|
| - |
|
984 |
|| cur == com.spice.profitmandi.dao.enumuration.dtr.LeadStage.ASSIGNED
|
| - |
|
985 |
|| cur == com.spice.profitmandi.dao.enumuration.dtr.LeadStage.CONTACTED
|
| - |
|
986 |
|| cur == com.spice.profitmandi.dao.enumuration.dtr.LeadStage.QUALIFIED;
|
| - |
|
987 |
if (!beforeBeatPlanned) return;
|
| - |
|
988 |
com.spice.profitmandi.dao.enumuration.dtr.LeadStage target =
|
| - |
|
989 |
com.spice.profitmandi.dao.enumuration.dtr.LeadStage.BEAT_PLANNED;
|
| - |
|
990 |
lead.setStage(target);
|
| - |
|
991 |
lead.setStatus(target.toLegacyStatus());
|
| - |
|
992 |
lead.setUpdatedTimestamp(LocalDateTime.now());
|
| - |
|
993 |
leadRepository.persist(lead);
|
| - |
|
994 |
} catch (Exception e) {
|
| - |
|
995 |
LOGGER.warn("Could not advance lead {} to BEAT_PLANNED", leadId, e);
|
| - |
|
996 |
}
|
| - |
|
997 |
}
|
| - |
|
998 |
|
| - |
|
999 |
// Confirm a beat actually runs on the given date.
|
| - |
|
1000 |
private boolean beatRunsOnDate(int beatId, LocalDate date) {
|
| - |
|
1001 |
return beatScheduleRepository.selectByBeatId(beatId).stream()
|
| - |
|
1002 |
.anyMatch(s -> date.equals(s.getStartDate()));
|
| - |
|
1003 |
}
|
| - |
|
1004 |
|
| - |
|
1005 |
// POST /beatPlan/lead/scheduleOnBeat {leadId, beatId, date}
|
| - |
|
1006 |
// Single-lead write for the Route Planner calendar-chip handoff. Strictly-future
|
| - |
|
1007 |
// date only (matches the visit-request / deferred chip flow).
|
| - |
|
1008 |
@PostMapping(value = "/beatPlan/lead/scheduleOnBeat")
|
| - |
|
1009 |
public ResponseEntity<?> leadScheduleOnBeat(
|
| - |
|
1010 |
HttpServletRequest request,
|
| - |
|
1011 |
@org.springframework.web.bind.annotation.RequestBody Map<String, Object> body) throws Exception {
|
| - |
|
1012 |
AuthUser me = currentUser(request);
|
| - |
|
1013 |
if (me == null) return responseSender.unauthorized("Not logged in");
|
| - |
|
1014 |
if (!canEditBeat(me)) return responseSender.badRequest("Scheduling a lead is restricted to L2 and above.");
|
| - |
|
1015 |
|
| - |
|
1016 |
Integer beatId = body.get("beatId") != null ? ((Number) body.get("beatId")).intValue() : null;
|
| - |
|
1017 |
Integer leadId = body.get("leadId") != null ? ((Number) body.get("leadId")).intValue() : null;
|
| - |
|
1018 |
String dateStr = (String) body.get("date");
|
| - |
|
1019 |
if (beatId == null || leadId == null || dateStr == null)
|
| - |
|
1020 |
return responseSender.badRequest("leadId, beatId and date are required");
|
| - |
|
1021 |
|
| - |
|
1022 |
LocalDate date;
|
| - |
|
1023 |
try {
|
| - |
|
1024 |
date = LocalDate.parse(dateStr);
|
| - |
|
1025 |
} catch (Exception e) {
|
| - |
|
1026 |
return responseSender.badRequest("Invalid date (yyyy-MM-dd)");
|
| - |
|
1027 |
}
|
| - |
|
1028 |
if (!date.isAfter(LocalDate.now()))
|
| - |
|
1029 |
return responseSender.badRequest("Pick a future date — today is already in progress.");
|
| - |
|
1030 |
|
| - |
|
1031 |
Beat beat = beatRepository.selectById(beatId);
|
| - |
|
1032 |
if (beat == null) return responseSender.badRequest("Beat not found");
|
| - |
|
1033 |
if (!beatRunsOnDate(beatId, date))
|
| - |
|
1034 |
return responseSender.badRequest("That beat is not scheduled on " + dateStr);
|
| - |
|
1035 |
if (leadRepository.selectById(leadId) == null)
|
| - |
|
1036 |
return responseSender.badRequest("Lead not found");
|
| - |
|
1037 |
|
| - |
|
1038 |
boolean created = writeLeadRoute(beatId, leadId, date, me.getId());
|
| - |
|
1039 |
|
| - |
|
1040 |
Map<String, Object> ok = new HashMap<>();
|
| - |
|
1041 |
ok.put("status", true);
|
| - |
|
1042 |
ok.put("created", created);
|
| - |
|
1043 |
ok.put("beatId", beatId);
|
| - |
|
1044 |
ok.put("scheduleDate", date.toString());
|
| - |
|
1045 |
ok.put("message", created
|
| - |
|
1046 |
? "Lead added to beat '" + beat.getName() + "' on " + dateStr
|
| - |
|
1047 |
: "Lead is already on that beat for " + dateStr);
|
| - |
|
1048 |
return responseSender.ok(ok);
|
| - |
|
1049 |
}
|
| - |
|
1050 |
|
| - |
|
1051 |
// POST /beatPlan/leadsForBeat/submit {beatId, date, leadIds:[...]}
|
| - |
|
1052 |
// Bulk write for the Day View "Add Lead" modal onto a known beat+date. Allows
|
| - |
|
1053 |
// today or a future date (the row's scheduled run may be today).
|
| - |
|
1054 |
@PostMapping(value = "/beatPlan/leadsForBeat/submit")
|
| - |
|
1055 |
public ResponseEntity<?> leadsForBeatSubmit(
|
| - |
|
1056 |
HttpServletRequest request,
|
| - |
|
1057 |
@org.springframework.web.bind.annotation.RequestBody Map<String, Object> body) throws Exception {
|
| - |
|
1058 |
AuthUser me = currentUser(request);
|
| - |
|
1059 |
if (me == null) return responseSender.unauthorized("Not logged in");
|
| - |
|
1060 |
if (!canEditBeat(me)) return responseSender.badRequest("Adding a lead is restricted to L2 and above.");
|
| - |
|
1061 |
|
| - |
|
1062 |
Integer beatId = body.get("beatId") != null ? ((Number) body.get("beatId")).intValue() : null;
|
| - |
|
1063 |
String dateStr = (String) body.get("date");
|
| - |
|
1064 |
List<?> leadIdsRaw = (List<?>) body.get("leadIds");
|
| - |
|
1065 |
if (beatId == null || dateStr == null || leadIdsRaw == null || leadIdsRaw.isEmpty())
|
| - |
|
1066 |
return responseSender.badRequest("beatId, date and leadIds are required");
|
| - |
|
1067 |
|
| - |
|
1068 |
LocalDate date;
|
| - |
|
1069 |
try {
|
| - |
|
1070 |
date = LocalDate.parse(dateStr);
|
| - |
|
1071 |
} catch (Exception e) {
|
| - |
|
1072 |
return responseSender.badRequest("Invalid date (yyyy-MM-dd)");
|
| - |
|
1073 |
}
|
| - |
|
1074 |
if (date.isBefore(LocalDate.now()))
|
| - |
|
1075 |
return responseSender.badRequest("Pick today or a future date.");
|
| - |
|
1076 |
|
| - |
|
1077 |
Beat beat = beatRepository.selectById(beatId);
|
| - |
|
1078 |
if (beat == null) return responseSender.badRequest("Beat not found");
|
| - |
|
1079 |
if (!beatRunsOnDate(beatId, date))
|
| - |
|
1080 |
return responseSender.badRequest("That beat is not scheduled on " + dateStr);
|
| - |
|
1081 |
|
| - |
|
1082 |
int added = 0, skipped = 0;
|
| - |
|
1083 |
for (Object idRaw : leadIdsRaw) {
|
| - |
|
1084 |
int leadId = ((Number) idRaw).intValue();
|
| - |
|
1085 |
if (leadRepository.selectById(leadId) == null) {
|
| - |
|
1086 |
skipped++;
|
| - |
|
1087 |
continue;
|
| - |
|
1088 |
}
|
| - |
|
1089 |
if (writeLeadRoute(beatId, leadId, date, me.getId())) added++;
|
| - |
|
1090 |
else skipped++;
|
| - |
|
1091 |
}
|
| - |
|
1092 |
|
| - |
|
1093 |
Map<String, Object> ok = new HashMap<>();
|
| - |
|
1094 |
ok.put("status", true);
|
| - |
|
1095 |
ok.put("added", added);
|
| - |
|
1096 |
ok.put("skipped", skipped);
|
| - |
|
1097 |
ok.put("message", added + " lead(s) added to '" + beat.getName() + "' on " + dateStr
|
| - |
|
1098 |
+ (skipped > 0 ? " (" + skipped + " already present or invalid)" : ""));
|
| - |
|
1099 |
return responseSender.ok(ok);
|
| - |
|
1100 |
}
|
| - |
|
1101 |
|
| - |
|
1102 |
// POST /beatPlan/lead/createBeatAndSchedule {authUserId, leadId, date, beatName?}
|
| - |
|
1103 |
// The "+ New beat" action — a 1-day beat with this lead as the only Day-1 stop,
|
| - |
|
1104 |
// for a rep who has no beat to land on. Mirrors VisitRequestController.createBeatAndSchedule.
|
| - |
|
1105 |
@PostMapping(value = "/beatPlan/lead/createBeatAndSchedule")
|
| - |
|
1106 |
public ResponseEntity<?> leadCreateBeatAndSchedule(
|
| - |
|
1107 |
HttpServletRequest request,
|
| - |
|
1108 |
@org.springframework.web.bind.annotation.RequestBody Map<String, Object> body) throws Exception {
|
| - |
|
1109 |
AuthUser me = currentUser(request);
|
| - |
|
1110 |
if (me == null) return responseSender.unauthorized("Not logged in");
|
| - |
|
1111 |
if (!canEditBeat(me)) return responseSender.badRequest("Creating a beat is restricted to L2 and above.");
|
| - |
|
1112 |
|
| - |
|
1113 |
Integer authUserId = body.get("authUserId") != null ? ((Number) body.get("authUserId")).intValue() : null;
|
| - |
|
1114 |
Integer leadId = body.get("leadId") != null ? ((Number) body.get("leadId")).intValue() : null;
|
| - |
|
1115 |
String dateStr = (String) body.get("date");
|
| - |
|
1116 |
if (authUserId == null || leadId == null || dateStr == null)
|
| - |
|
1117 |
return responseSender.badRequest("authUserId, leadId and date are required");
|
| - |
|
1118 |
|
| - |
|
1119 |
LocalDate date;
|
| - |
|
1120 |
try {
|
| - |
|
1121 |
date = LocalDate.parse(dateStr);
|
| - |
|
1122 |
} catch (Exception e) {
|
| - |
|
1123 |
return responseSender.badRequest("Invalid date (yyyy-MM-dd)");
|
| - |
|
1124 |
}
|
| - |
|
1125 |
if (!date.isAfter(LocalDate.now()))
|
| - |
|
1126 |
return responseSender.badRequest("Pick a future date — today is already in progress.");
|
| - |
|
1127 |
|
| - |
|
1128 |
Lead lead = leadRepository.selectById(leadId);
|
| - |
|
1129 |
if (lead == null) return responseSender.badRequest("Lead not found");
|
| - |
|
1130 |
|
| - |
|
1131 |
// One-beat-per-day guard for the rep.
|
| - |
|
1132 |
for (Beat existing : beatRepository.selectActiveByAuthUserId(authUserId)) {
|
| - |
|
1133 |
for (BeatSchedule s : beatScheduleRepository.selectByBeatId(existing.getId())) {
|
| - |
|
1134 |
if (date.equals(s.getStartDate())) {
|
| - |
|
1135 |
return responseSender.badRequest("This user already has '"
|
| - |
|
1136 |
+ (existing.getName() != null ? existing.getName() : "Beat #" + existing.getId())
|
| - |
|
1137 |
+ "' scheduled on " + date + " — use Schedule on a beat instead.");
|
| - |
|
1138 |
}
|
| - |
|
1139 |
}
|
| - |
|
1140 |
}
|
| - |
|
1141 |
|
| - |
|
1142 |
String leadLabel = ((lead.getFirstName() != null ? lead.getFirstName() : "") + " "
|
| - |
|
1143 |
+ (lead.getLastName() != null ? lead.getLastName() : "")).trim();
|
| - |
|
1144 |
if (leadLabel.isEmpty()) leadLabel = "Lead #" + leadId;
|
| - |
|
1145 |
Object nameRaw = body.get("beatName");
|
| - |
|
1146 |
String beatName = (nameRaw != null && !nameRaw.toString().trim().isEmpty())
|
| - |
|
1147 |
? nameRaw.toString().trim()
|
| - |
|
1148 |
: ("Lead - " + leadLabel + " - " + date);
|
| - |
|
1149 |
if (beatName.length() > 100) beatName = beatName.substring(0, 100);
|
| - |
|
1150 |
|
| - |
|
1151 |
LocalDateTime now = LocalDateTime.now();
|
| - |
|
1152 |
Beat beat = new Beat();
|
| - |
|
1153 |
beat.setName(beatName);
|
| - |
|
1154 |
beat.setAuthUserId(authUserId);
|
| - |
|
1155 |
beat.setBeatColor(BEAT_COLORS[Math.abs(beatName.hashCode()) % BEAT_COLORS.length]);
|
| - |
|
1156 |
beat.setTotalDays(1);
|
| - |
|
1157 |
beat.setActive(true);
|
| - |
|
1158 |
beat.setCreatedBy(me.getId());
|
| - |
|
1159 |
beat.setCreatedTimestamp(now);
|
| - |
|
1160 |
beatRepository.persist(beat);
|
| - |
|
1161 |
|
| - |
|
1162 |
BeatSchedule sched = new BeatSchedule();
|
| - |
|
1163 |
sched.setBeatId(beat.getId());
|
| - |
|
1164 |
sched.setStartDate(date);
|
| - |
|
1165 |
sched.setEndDate(date);
|
| - |
|
1166 |
sched.setDayNumber(1);
|
| - |
|
1167 |
sched.setEndAction("HOME");
|
| - |
|
1168 |
sched.setCreatedTimestamp(now);
|
| - |
|
1169 |
beatScheduleRepository.persist(sched);
|
| - |
|
1170 |
|
| - |
|
1171 |
writeLeadRoute(beat.getId(), leadId, date, me.getId());
|
| - |
|
1172 |
|
| - |
|
1173 |
Map<String, Object> ok = new HashMap<>();
|
| - |
|
1174 |
ok.put("status", true);
|
| - |
|
1175 |
ok.put("beatId", beat.getId());
|
| - |
|
1176 |
ok.put("beatName", beatName);
|
| - |
|
1177 |
ok.put("scheduleDate", date.toString());
|
| - |
|
1178 |
ok.put("message", "Beat '" + beatName + "' created on " + dateStr);
|
| - |
|
1179 |
return responseSender.ok(ok);
|
| - |
|
1180 |
}
|
| - |
|
1181 |
|
| 846 |
// authUserId -> dtr.users id (via shared email), memoized in the passed cache.
|
1182 |
// authUserId -> dtr.users id (via shared email), memoized in the passed cache.
|
| 847 |
// Used by the reschedule action to create the new PENDING location_tracking row.
|
1183 |
// Used by the reschedule action to create the new PENDING location_tracking row.
|
| 848 |
private Integer resolveDtrId(int authUserId, Map<Integer, Integer> cache) {
|
1184 |
private Integer resolveDtrId(int authUserId, Map<Integer, Integer> cache) {
|
| 849 |
if (cache.containsKey(authUserId)) return cache.get(authUserId);
|
1185 |
if (cache.containsKey(authUserId)) return cache.get(authUserId);
|
| 850 |
Integer dtrId = null;
|
1186 |
Integer dtrId = null;
|