Subversion Repositories SmartDukaan

Rev

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

Rev 36644 Rev 36650
Line 61... Line 61...
61
	@Autowired
61
	@Autowired
62
	private BeatScheduleRepository beatScheduleRepository;
62
	private BeatScheduleRepository beatScheduleRepository;
63
	@Autowired
63
	@Autowired
64
	private LeadRouteRepository leadRouteRepository;
64
	private LeadRouteRepository leadRouteRepository;
65
	@Autowired
65
	@Autowired
-
 
66
	private com.spice.profitmandi.dao.service.BeatPlanQueryService beatPlanQueryService;
-
 
67
	@Autowired
66
	private AuthUserLocationRepository authUserLocationRepository;
68
	private AuthUserLocationRepository authUserLocationRepository;
67
	@Autowired
69
	@Autowired
68
	private LeadRepository leadRepository;
70
	private LeadRepository leadRepository;
69
	@Autowired
71
	@Autowired
70
	private PublicHolidaysRepository publicHolidaysRepository;
72
	private PublicHolidaysRepository publicHolidaysRepository;
Line 87... Line 89...
87
		EscalationType[] escalationTypes = EscalationType.values();
89
		EscalationType[] escalationTypes = EscalationType.values();
88
		model.addAttribute("escalationTypes", escalationTypes);
90
		model.addAttribute("escalationTypes", escalationTypes);
89
		return "beat-plan-window";
91
		return "beat-plan-window";
90
	}
92
	}
91
 
93
 
-
 
94
	@Autowired
-
 
95
	private com.spice.profitmandi.dao.repository.dtr.LeadLiveLocationRepository leadLiveLocationRepositoryAuto;
-
 
96
 
-
 
97
	// ====================== DAY VIEW ======================
-
 
98
	// Inline page (loaded into dashboard #main-content): tabular list of all beats
-
 
99
	// scheduled in a date range across all users. Each row has a View button that
-
 
100
	// opens that user's calendar in a modal.
-
 
101
	@GetMapping(value = "/beatPlan/dayView")
-
 
102
	public String beatPlanDayView(HttpServletRequest request, Model model) {
-
 
103
		EscalationType[] escalationTypes = EscalationType.values();
-
 
104
		model.addAttribute("escalationTypes", escalationTypes);
-
 
105
		return "beat-plan-day-view";
-
 
106
	}
-
 
107
 
-
 
108
	// Tabular JSON: one row per (beat, scheduled date) in [startDate, endDate].
-
 
109
	@GetMapping(value = "/beatPlan/scheduledList")
-
 
110
	public ResponseEntity<?> scheduledList(
-
 
111
			@RequestParam(required = false) String startDate,
-
 
112
			@RequestParam(required = false) String endDate) {
-
 
113
 
-
 
114
		LocalDate start, end;
-
 
115
		try {
-
 
116
			start = (startDate == null || startDate.isEmpty()) ? LocalDate.now() : LocalDate.parse(startDate);
-
 
117
			end = (endDate == null || endDate.isEmpty()) ? start.plusDays(7) : LocalDate.parse(endDate);
-
 
118
		} catch (Exception e) {
-
 
119
			return responseSender.badRequest("Invalid date — expected yyyy-MM-dd");
-
 
120
		}
-
 
121
 
-
 
122
		List<com.spice.profitmandi.dao.model.BeatDayDetails> beats =
-
 
123
				beatPlanQueryService.getAllScheduledBeats(start, end);
-
 
124
 
-
 
125
		// Resolve user names in bulk
-
 
126
		Set<Integer> userIds = beats.stream()
-
 
127
				.map(com.spice.profitmandi.dao.model.BeatDayDetails::getAuthUserId)
-
 
128
				.collect(java.util.stream.Collectors.toSet());
-
 
129
		Map<Integer, AuthUser> userMap = new HashMap<>();
-
 
130
		if (!userIds.isEmpty()) {
-
 
131
			authRepository.selectByIds(new ArrayList<>(userIds))
-
 
132
					.forEach(u -> userMap.put(u.getId(), u));
-
 
133
		}
-
 
134
 
-
 
135
		List<Map<String, Object>> rows = new ArrayList<>();
-
 
136
		for (com.spice.profitmandi.dao.model.BeatDayDetails b : beats) {
-
 
137
			AuthUser u = userMap.get(b.getAuthUserId());
-
 
138
			Map<String, Object> row = new HashMap<>();
-
 
139
			row.put("authUserId", b.getAuthUserId());
-
 
140
			row.put("userName", u != null ? (u.getFirstName() + " " + u.getLastName()) : "User #" + b.getAuthUserId());
-
 
141
			row.put("scheduleDate", b.getScheduleDate().toString());
-
 
142
			row.put("dayNumber", b.getDayNumber());
-
 
143
			row.put("beatId", b.getBeatId());
-
 
144
			row.put("beatName", b.getBeatName());
-
 
145
			row.put("beatColor", b.getBeatColor());
-
 
146
			row.put("partnerCount", b.getPartnerStops().size());
-
 
147
			row.put("leadCount", b.getLeadStops().size());
-
 
148
			row.put("visitCount", b.getPartnerStops().size() + b.getLeadStops().size());
-
 
149
			rows.add(row);
-
 
150
		}
-
 
151
 
-
 
152
		Map<String, Object> result = new HashMap<>();
-
 
153
		result.put("rows", rows);
-
 
154
		result.put("startDate", start.toString());
-
 
155
		result.put("endDate", end.toString());
-
 
156
		return responseSender.ok(result);
-
 
157
	}
-
 
158
 
-
 
159
	// JSON: beats running for (authUserId, date) — enriched with partner/lead names & coords
-
 
160
	@GetMapping(value = "/beatPlan/dayViewData")
-
 
161
	public ResponseEntity<?> beatPlanDayViewData(
-
 
162
			@RequestParam int authUserId,
-
 
163
			@RequestParam String date) throws ProfitMandiBusinessException {
-
 
164
 
-
 
165
		LocalDate localDate;
-
 
166
		try {
-
 
167
			localDate = LocalDate.parse(date);
-
 
168
		} catch (Exception e) {
-
 
169
			return responseSender.badRequest("Invalid date — expected yyyy-MM-dd");
-
 
170
		}
-
 
171
 
-
 
172
		List<com.spice.profitmandi.dao.model.BeatDayDetails> beats =
-
 
173
				beatPlanQueryService.getBeatsForUserOnDate(authUserId, localDate);
-
 
174
 
-
 
175
		// Collect all partner & lead IDs to fetch metadata in bulk
-
 
176
		Set<Integer> partnerIds = new HashSet<>();
-
 
177
		Set<Integer> leadIds = new HashSet<>();
-
 
178
		for (com.spice.profitmandi.dao.model.BeatDayDetails b : beats) {
-
 
179
			b.getPartnerStops().forEach(s -> partnerIds.add((Integer) s.get("fofoId")));
-
 
180
			b.getLeadStops().forEach(s -> leadIds.add((Integer) s.get("leadId")));
-
 
181
		}
-
 
182
 
-
 
183
		// Partners: name + geocoded lat/lng (geocoder is cached in Redis)
-
 
184
		Map<Integer, CustomRetailer> retailerMap = partnerIds.isEmpty()
-
 
185
				? new HashMap<>()
-
 
186
				: retailerService.getFofoRetailers(new ArrayList<>(partnerIds));
-
 
187
		Map<Integer, FofoStore> storeMap = new HashMap<>();
-
 
188
		if (!partnerIds.isEmpty()) {
-
 
189
			fofoStoreRepository.selectByRetailerIds(new ArrayList<>(partnerIds))
-
 
190
					.forEach(fs -> storeMap.put(fs.getId(), fs));
-
 
191
		}
-
 
192
 
-
 
193
		// Leads: name + geo
-
 
194
		Map<Integer, com.spice.profitmandi.dao.entity.user.Lead> leadMap = new HashMap<>();
-
 
195
		Map<Integer, com.spice.profitmandi.dao.entity.user.LeadLiveLocation> leadGeoMap = new HashMap<>();
-
 
196
		for (int leadId : leadIds) {
-
 
197
			com.spice.profitmandi.dao.entity.user.Lead l = leadRepository.selectById(leadId);
-
 
198
			if (l != null) leadMap.put(leadId, l);
-
 
199
			com.spice.profitmandi.dao.entity.user.LeadLiveLocation lg =
-
 
200
					leadLiveLocationRepositoryAuto.selectApprovedByLeadId(leadId);
-
 
201
			if (lg != null) leadGeoMap.put(leadId, lg);
-
 
202
		}
-
 
203
 
-
 
204
		// Enrich each stop
-
 
205
		List<Map<String, Object>> out = new ArrayList<>();
-
 
206
		for (com.spice.profitmandi.dao.model.BeatDayDetails b : beats) {
-
 
207
			Map<String, Object> beatJson = new HashMap<>();
-
 
208
			beatJson.put("beatId", b.getBeatId());
-
 
209
			beatJson.put("beatName", b.getBeatName());
-
 
210
			beatJson.put("beatColor", b.getBeatColor());
-
 
211
			beatJson.put("dayNumber", b.getDayNumber());
-
 
212
			beatJson.put("scheduleDate", b.getScheduleDate().toString());
-
 
213
			beatJson.put("endAction", b.getEndAction());
-
 
214
			beatJson.put("totalDistanceKm", b.getTotalDistanceKm());
-
 
215
			beatJson.put("totalTimeMins", b.getTotalTimeMins());
-
 
216
			beatJson.put("startLocationName", b.getStartLocationName());
-
 
217
			beatJson.put("startLatitude", b.getStartLatitude());
-
 
218
			beatJson.put("startLongitude", b.getStartLongitude());
-
 
219
 
-
 
220
			List<Map<String, Object>> stops = new ArrayList<>();
-
 
221
			// Partners
-
 
222
			for (Map<String, Object> ps : b.getPartnerStops()) {
-
 
223
				int fofoId = (Integer) ps.get("fofoId");
-
 
224
				Map<String, Object> stop = new HashMap<>();
-
 
225
				stop.put("type", "partner");
-
 
226
				stop.put("id", fofoId);
-
 
227
				stop.put("sequenceOrder", ps.get("sequenceOrder"));
-
 
228
				FofoStore fs = storeMap.get(fofoId);
-
 
229
				CustomRetailer cr = retailerMap.get(fofoId);
-
 
230
				stop.put("code", fs != null ? fs.getCode() : null);
-
 
231
				stop.put("name", fs != null && fs.getOutletName() != null ? fs.getOutletName()
-
 
232
						: (cr != null ? cr.getBusinessName() : "Store #" + fofoId));
-
 
233
				if (cr != null && cr.getAddress() != null) {
-
 
234
					stop.put("address", cr.getAddress().getAddressString());
-
 
235
					try {
-
 
236
						String geoAddr = com.spice.profitmandi.service.GeocodingService.buildGeoAddress(
-
 
237
								cr.getAddress().getLine1(), cr.getAddress().getCity(),
-
 
238
								cr.getAddress().getState(), cr.getAddress().getPinCode());
-
 
239
						double[] coords = geocodingService.geocodeAddress(geoAddr);
-
 
240
						if (coords != null) {
-
 
241
							stop.put("lat", coords[0]);
-
 
242
							stop.put("lng", coords[1]);
-
 
243
						}
-
 
244
					} catch (Exception ignored) {
-
 
245
					}
-
 
246
				}
-
 
247
				stops.add(stop);
-
 
248
			}
-
 
249
			// Leads
-
 
250
			for (Map<String, Object> ls : b.getLeadStops()) {
-
 
251
				int leadId = (Integer) ls.get("leadId");
-
 
252
				Map<String, Object> stop = new HashMap<>();
-
 
253
				stop.put("type", "lead");
-
 
254
				stop.put("id", leadId);
-
 
255
				stop.put("sequenceOrder", ls.get("sequenceOrder"));
-
 
256
				stop.put("nearestStoreId", ls.get("nearestStoreId"));
-
 
257
				com.spice.profitmandi.dao.entity.user.Lead l = leadMap.get(leadId);
-
 
258
				stop.put("name", l != null ? l.getFirstName() + " " + l.getLastName() : "Lead #" + leadId);
-
 
259
				stop.put("mobile", l != null ? l.getLeadMobile() : null);
-
 
260
				stop.put("city", l != null ? l.getCity() : null);
-
 
261
				com.spice.profitmandi.dao.entity.user.LeadLiveLocation lg = leadGeoMap.get(leadId);
-
 
262
				if (lg != null) {
-
 
263
					stop.put("lat", lg.getLatitude());
-
 
264
					stop.put("lng", lg.getLongitude());
-
 
265
				}
-
 
266
				stops.add(stop);
-
 
267
			}
-
 
268
			beatJson.put("stops", stops);
-
 
269
			beatJson.put("partnerCount", b.getPartnerStops().size());
-
 
270
			beatJson.put("leadCount", b.getLeadStops().size());
-
 
271
			out.add(beatJson);
-
 
272
		}
-
 
273
 
-
 
274
		Map<String, Object> result = new HashMap<>();
-
 
275
		result.put("beats", out);
-
 
276
		return responseSender.ok(result);
-
 
277
	}
-
 
278
 
92
	@GetMapping(value = "/beatPlan/getAuthUsers")
279
	@GetMapping(value = "/beatPlan/getAuthUsers")
93
	public ResponseEntity<?> getAuthUsers(
280
	public ResponseEntity<?> getAuthUsers(
94
			@RequestParam int categoryId,
281
			@RequestParam int categoryId,
95
			@RequestParam EscalationType escalationType) {
282
			@RequestParam EscalationType escalationType) {
96
		List<AuthUser> authUsers = csService.getAuthUserByCategoryId(categoryId, escalationType);
283
		List<AuthUser> authUsers = csService.getAuthUserByCategoryId(categoryId, escalationType);