| Line 182... |
Line 182... |
| 182 |
|
182 |
|
| 183 |
@Autowired
|
183 |
@Autowired
|
| 184 |
private BeatMissDetectorRunner beatMissDetectorRunner;
|
184 |
private BeatMissDetectorRunner beatMissDetectorRunner;
|
| 185 |
|
185 |
|
| 186 |
@Autowired
|
186 |
@Autowired
|
| - |
|
187 |
private com.smartdukaan.cron.scheduled.remarkscore.RemarkScoreRunner remarkScoreRunner;
|
| - |
|
188 |
|
| - |
|
189 |
@Autowired
|
| - |
|
190 |
private com.smartdukaan.cron.scheduled.remarkscore.DuplicateRemarkDigestRunner duplicateRemarkDigestRunner;
|
| - |
|
191 |
|
| - |
|
192 |
@Autowired
|
| 187 |
private com.spice.profitmandi.service.AgendaAutoRuleService agendaAutoRuleService;
|
193 |
private com.spice.profitmandi.service.AgendaAutoRuleService agendaAutoRuleService;
|
| 188 |
|
194 |
|
| 189 |
@Autowired
|
195 |
@Autowired
|
| 190 |
SmartPingService smartPingService;
|
196 |
SmartPingService smartPingService;
|
| 191 |
|
197 |
|
| Line 4125... |
Line 4131... |
| 4125 |
} catch (Exception e) {
|
4131 |
} catch (Exception e) {
|
| 4126 |
LOGGER.error("detectMissedBeats failed", e);
|
4132 |
LOGGER.error("detectMissedBeats failed", e);
|
| 4127 |
}
|
4133 |
}
|
| 4128 |
}
|
4134 |
}
|
| 4129 |
|
4135 |
|
| - |
|
4136 |
// Every 30 min: score today's freshly checked-out partner-visit remarks so the
|
| - |
|
4137 |
// Beat Journey remark-quality flags (#2/#10/#12) stay current. Idempotent — each
|
| - |
|
4138 |
// remark is scored (committed) exactly once; a re-run scores 0 rows.
|
| - |
|
4139 |
@Scheduled(fixedRate = 1800000)
|
| - |
|
4140 |
public void scoreVisitRemarks() {
|
| - |
|
4141 |
try {
|
| - |
|
4142 |
remarkScoreRunner.scoreForDate(java.time.LocalDate.now());
|
| - |
|
4143 |
} catch (Exception e) {
|
| - |
|
4144 |
LOGGER.error("scoreVisitRemarks failed", e);
|
| - |
|
4145 |
}
|
| - |
|
4146 |
}
|
| - |
|
4147 |
|
| - |
|
4148 |
// 09:15 daily: consolidated HR mail of employees who reused one remark across
|
| - |
|
4149 |
// agendas on more than 3 visits this month (month-to-date, so an offender stays
|
| - |
|
4150 |
// listed for the rest of the month). Silent on a day when nobody is over the line.
|
| - |
|
4151 |
@Scheduled(cron = "0 15 9 * * *")
|
| - |
|
4152 |
public void duplicateRemarkDigest() {
|
| - |
|
4153 |
try {
|
| - |
|
4154 |
duplicateRemarkDigestRunner.sendDigestForDate(java.time.LocalDate.now());
|
| - |
|
4155 |
} catch (Exception e) {
|
| - |
|
4156 |
LOGGER.error("duplicateRemarkDigest failed", e);
|
| - |
|
4157 |
}
|
| - |
|
4158 |
}
|
| - |
|
4159 |
|
| 4130 |
// Nightly PJP agenda sync: evaluate the 5 AUTO agenda rules per partner and
|
4160 |
// Nightly PJP agenda sync: evaluate the 5 AUTO agenda rules per partner and
|
| 4131 |
// open/close user.agenda_instance rows. Scheduled from ScheduledSkeleton at
|
4161 |
// open/close user.agenda_instance rows. Scheduled from ScheduledSkeleton at
|
| 4132 |
// 23:45 — after the 23:30 activation-type cron, so the REVIVAL mirror sees
|
4162 |
// 23:45 — after the 23:30 activation-type cron, so the REVIVAL mirror sees
|
| 4133 |
// today's state.
|
4163 |
// today's state.
|
| 4134 |
public void updatePjpAgendaInstances() {
|
4164 |
public void updatePjpAgendaInstances() {
|
| Line 4602... |
Line 4632... |
| 4602 |
}
|
4632 |
}
|
| 4603 |
}
|
4633 |
}
|
| 4604 |
|
4634 |
|
| 4605 |
}
|
4635 |
}
|
| 4606 |
|
4636 |
|
| 4607 |
public void userMobileNumberOptIn() throws Exception {
|
- |
|
| 4608 |
|
- |
|
| 4609 |
List<FofoStore> fofoStores = fofoStoreRepository.selectActiveStores();
|
- |
|
| 4610 |
|
- |
|
| 4611 |
List<com.spice.profitmandi.dao.entity.user.User> users = userUserRepository.selectByIds(fofoStores.stream().map(x -> x.getId()).collect(Collectors.toList()));
|
- |
|
| 4612 |
|
- |
|
| 4613 |
List<Address> addresses = addressRepository.selectByIds(users.stream().map(x -> x.getAddressId()).collect(Collectors.toList()));
|
- |
|
| 4614 |
|
- |
|
| 4615 |
LOGGER.info("addresses" + addresses);
|
- |
|
| 4616 |
|
- |
|
| 4617 |
for (Address address : addresses) {
|
- |
|
| 4618 |
notificationService.optIn(address.getPhoneNumber());
|
- |
|
| 4619 |
|
- |
|
| 4620 |
}
|
- |
|
| 4621 |
|
- |
|
| 4622 |
}
|
- |
|
| 4623 |
|
- |
|
| 4624 |
public void authUserMobileNumberOptIn() throws HttpHostConnectException, ProfitMandiBusinessException {
|
- |
|
| 4625 |
|
- |
|
| 4626 |
List<AuthUser> authUsers = authRepository.selectAllActiveUser();
|
- |
|
| 4627 |
LOGGER.info("authUsers" + authUsers);
|
- |
|
| 4628 |
|
- |
|
| 4629 |
for (AuthUser authUser : authUsers) {
|
- |
|
| 4630 |
Map<String, String> requestheaders = new HashMap<>();
|
- |
|
| 4631 |
requestheaders.put("Content-Type", "application/x-www-form-urlencoded");
|
- |
|
| 4632 |
Map<String, String> requestParams = new HashMap<>();
|
- |
|
| 4633 |
requestParams.put("userid", String.valueOf(2000215976));
|
- |
|
| 4634 |
requestParams.put("password", "MFRd!BBL");
|
- |
|
| 4635 |
requestParams.put("phone_number", authUser.getMobileNumber());
|
- |
|
| 4636 |
requestParams.put("auth_scheme", "plain");
|
- |
|
| 4637 |
requestParams.put("v", "1.1");
|
- |
|
| 4638 |
requestParams.put("format", "json");
|
- |
|
| 4639 |
|
- |
|
| 4640 |
requestParams.put("method", "OPT_IN");
|
- |
|
| 4641 |
|
- |
|
| 4642 |
requestParams.put("channel", "WHATSAPP");
|
- |
|
| 4643 |
String response = restClient.get("https://media.smsgupshup.com/GatewayAPI/rest", requestParams, requestheaders);
|
- |
|
| 4644 |
LOGGER.info("response" + response);
|
- |
|
| 4645 |
}
|
- |
|
| 4646 |
|
- |
|
| 4647 |
}
|
- |
|
| 4648 |
|
- |
|
| 4649 |
@Autowired
|
4637 |
@Autowired
|
| 4650 |
private HygieneDataRepository hygieneDataRepository;
|
4638 |
private HygieneDataRepository hygieneDataRepository;
|
| 4651 |
|
4639 |
|
| 4652 |
public void hygineAlertForPartner() throws ProfitMandiBusinessException, MessagingException, IOException {
|
4640 |
public void hygineAlertForPartner() throws ProfitMandiBusinessException, MessagingException, IOException {
|
| 4653 |
|
4641 |
|
| Line 5257... |
Line 5245... |
| 5257 |
Exception {
|
5245 |
Exception {
|
| 5258 |
|
5246 |
|
| 5259 |
// Sort by lowest dueDate first (most overdue)
|
5247 |
// Sort by lowest dueDate first (most overdue)
|
| 5260 |
defaultLoans.sort(Comparator.comparing(Loan::getDueDate));
|
5248 |
defaultLoans.sort(Comparator.comparing(Loan::getDueDate));
|
| 5261 |
|
5249 |
|
| 5262 |
String title = "SD Credit Alert!";
|
- |
|
| 5263 |
int whatsAppCount = 0;
|
5250 |
int whatsAppCount = 0;
|
| 5264 |
for (Loan defaultLoan : defaultLoans) {
|
5251 |
for (Loan defaultLoan : defaultLoans) {
|
| 5265 |
double principal = defaultLoan.getPendingAmount().doubleValue();
|
5252 |
double principal = defaultLoan.getPendingAmount().doubleValue();
|
| 5266 |
double interest = defaultLoan.getInterestAccrued().doubleValue() - defaultLoan.getInterestPaid().doubleValue();
|
5253 |
double interest = defaultLoan.getInterestAccrued().doubleValue() - defaultLoan.getInterestPaid().doubleValue();
|
| 5267 |
double total = principal + interest;
|
5254 |
double total = principal + interest;
|
| 5268 |
|
5255 |
|
| 5269 |
com.spice.profitmandi.dao.entity.user.User user = userUserRepository.selectById(defaultLoan.getFofoId());
|
5256 |
com.spice.profitmandi.dao.entity.user.User user = userUserRepository.selectById(defaultLoan.getFofoId());
|
| 5270 |
|
5257 |
|
| 5271 |
Address address = addressRepository.selectById(user.getAddressId());
|
5258 |
Address address = addressRepository.selectById(user.getAddressId());
|
| 5272 |
|
5259 |
|
| 5273 |
// WhatsApp: only top 2 most overdue loans
|
5260 |
// WhatsApp: only top 2 most overdue loans. Days in default and the penalty rate are fixed
|
| - |
|
5261 |
// copy in the approved template, so only the name and the amount are sent.
|
| 5274 |
if (whatsAppCount < 2) {
|
5262 |
if (whatsAppCount < 2) {
|
| 5275 |
String whatsAppMessage = getWhatsAppMessageForDefaultLoan(defaultLoan, total, user.getName());
|
5263 |
notificationService.sendLoanDefaultAlert(address.getPhoneNumber(), user.getName(),
|
| 5276 |
notificationService.sendWhatsappMessage(whatsAppMessage, title, address.getPhoneNumber());
|
5264 |
FormattingUtils.formatDecimal(total));
|
| 5277 |
whatsAppCount++;
|
5265 |
whatsAppCount++;
|
| 5278 |
}
|
5266 |
}
|
| 5279 |
|
5267 |
|
| 5280 |
String emailMessage = getEmailMessageForDefaultLoan(defaultLoan, principal, interest, total, user.getName());
|
5268 |
String emailMessage = getEmailMessageForDefaultLoan(defaultLoan, principal, interest, total, user.getName());
|
| 5281 |
String[] email = {user.getEmailId()};
|
5269 |
String[] email = {user.getEmailId()};
|
| Line 5304... |
Line 5292... |
| 5304 |
sb.append("<p>Team SmartDukaan</p>");
|
5292 |
sb.append("<p>Team SmartDukaan</p>");
|
| 5305 |
sb.append("</body></html>");
|
5293 |
sb.append("</body></html>");
|
| 5306 |
return sb.toString();
|
5294 |
return sb.toString();
|
| 5307 |
}
|
5295 |
}
|
| 5308 |
|
5296 |
|
| 5309 |
private String getWhatsAppMessageForDefaultLoan(Loan loan, double total, String name) {
|
- |
|
| 5310 |
String formattedAmount = FormattingUtils.formatDecimal(total);
|
- |
|
| 5311 |
long daysInDefault = ChronoUnit.DAYS.between(loan.getPenaltyDate(), LocalDate.now());
|
- |
|
| 5312 |
|
- |
|
| 5313 |
return String.format(
|
- |
|
| 5314 |
"Dear %s, Your credit payment has been in default for %d days. " +
|
- |
|
| 5315 |
"A penalty interest of %s%% per day is being charged on your outstanding amount of Rs. %s. " +
|
- |
|
| 5316 |
"Please settle immediately to avoid legal action.\n\nTeam SmartDukaan",
|
- |
|
| 5317 |
name, daysInDefault, loan.getPenaltyRate() != null ? loan.getPenaltyRate() : ProfitMandiConstants.NEW_DELAYED_INTEREST_RATE, formattedAmount);
|
- |
|
| 5318 |
}
|
- |
|
| 5319 |
|
5297 |
|
| 5320 |
@Autowired
|
5298 |
@Autowired
|
| 5321 |
private FofoOpeningStockRepository fofoOpeningStockRepository;
|
5299 |
private FofoOpeningStockRepository fofoOpeningStockRepository;
|
| 5322 |
@Autowired
|
5300 |
@Autowired
|
| 5323 |
private SmartCartService smartCartService;
|
5301 |
private SmartCartService smartCartService;
|