All checks were successful
Build And Deploy Main / build-and-deploy (push) Successful in 35s
194 lines
7.8 KiB
JavaScript
194 lines
7.8 KiB
JavaScript
const db = require("../models");
|
|
const Vehicle = db.vehicle;
|
|
const Customer = db.customer;
|
|
const CalendarEvent = db.calendar_event;
|
|
const moment = require('moment');
|
|
const toSiteNumber = (value) => {
|
|
const parsed = Number(value);
|
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
|
|
};
|
|
|
|
const getAllSites = async () => {
|
|
const [customerSites, vehicleSites, eventSites] = await Promise.all([
|
|
Customer.distinct('site'),
|
|
Vehicle.distinct('site'),
|
|
CalendarEvent.distinct('site')
|
|
]);
|
|
const normalizedSites = [...new Set([...customerSites, ...vehicleSites, ...eventSites]
|
|
.map(toSiteNumber)
|
|
.filter(Boolean))];
|
|
return normalizedSites.length > 0 ? normalizedSites : [1];
|
|
};
|
|
|
|
class ReminderService {
|
|
parseDate(dateString) {
|
|
if (!dateString || typeof dateString !== 'string') return null;
|
|
const [month, day, year] = dateString.split('/').map(Number);
|
|
if (!month || !day || !year) return null;
|
|
const parsedDate = new Date(year, month-1,day);
|
|
return Number.isNaN(parsedDate.getTime()) ? null : parsedDate;
|
|
}
|
|
|
|
parseMonthDay(dateString) {
|
|
if (!dateString || typeof dateString !== 'string') return { month: -1, day: -1 };
|
|
const [month, day] = dateString.split('/').map(Number);
|
|
return {
|
|
month: Number.isInteger(month) ? month : -1,
|
|
day: Number.isInteger(day) ? day : -1
|
|
};
|
|
}
|
|
|
|
async createVehicleRelatedEvents(daysAhead = 30) {
|
|
const today = new Date();
|
|
const futureDate = new Date();
|
|
futureDate.setDate(today.getDate() + daysAhead); // check 30 days ahead
|
|
|
|
const sites = await getAllSites();
|
|
for (const site of sites) {
|
|
const vehicles = await Vehicle.find({status: 'active', site});
|
|
const allVehiclesCalendarEvent = await CalendarEvent.find({type: 'reminder', status: 'active', site, target_type: 'vehicle'});
|
|
for (const vehicle of vehicles) {
|
|
const insuranceExpireDate = this.parseDate(vehicle.insurance_expire_on);
|
|
const titleRegistrationDate = this.parseDate(vehicle.title_registration_on);
|
|
if (!insuranceExpireDate || !titleRegistrationDate) continue;
|
|
const titleExpireDate = new Date(titleRegistrationDate);
|
|
titleExpireDate.setFullYear(titleExpireDate.getFullYear() + 1);
|
|
const emissionTestDate = this.parseDate(vehicle.emission_test_on);
|
|
if (!emissionTestDate) continue;
|
|
const emissionTestExpireDate = new Date(emissionTestDate);
|
|
emissionTestExpireDate.setFullYear(titleExpireDate.getFullYear() + 1);
|
|
const newDate = new Date(insuranceExpireDate);
|
|
newDate.setDate(newDate.getDate() - 15);
|
|
const newDate1 = new Date(emissionTestExpireDate);
|
|
newDate1.setDate(newDate.getDate() - 15);
|
|
const newDate2 = new Date(titleExpireDate);
|
|
newDate2.setDate(newDate.getDate() - 15);
|
|
if ( insuranceExpireDate >= today && insuranceExpireDate < futureDate) {
|
|
if (!allVehiclesCalendarEvent.find(item => item.event_reminder_type === 'insurance_expire' && item.target_uuid === vehicle.id)) {
|
|
const calendarEvent = new CalendarEvent({
|
|
title: `Vehicle ${vehicle?.vehicle_number} (${vehicle?.tag})'s Insurance would expire in 15 days`,
|
|
description: `Vehicle ${vehicle?.vehicle_number} (${vehicle?.tag})'s Insurance would expire in 15 day, please check whether it is renewed properly`,
|
|
type: 'reminder',
|
|
start_time: newDate,
|
|
stop_time: new Date(newDate.getTime() + 10*60*1000),
|
|
color: 'brown',
|
|
target_type: 'vehicle',
|
|
target_uuid: vehicle.id,
|
|
target_name: vechile.vehicle_number,
|
|
event_reminder_type: 'insurance_expire',
|
|
status: 'active',
|
|
site,
|
|
edit_date: new Date(),
|
|
create_date: new Date(),
|
|
create_by: 'system',
|
|
edit_by: 'system',
|
|
edit_history: [{employee: 'system', date: new Date()}]
|
|
})
|
|
await calendarEvent.save(calendarEvent);
|
|
}
|
|
}
|
|
if ( emissionTestExpireDate >= today && emissionTestExpireDate < futureDate) {
|
|
if (!allVehiclesCalendarEvent.find(item => item.event_reminder_type === 'emission_test' && item.target_uuid === vehicle.id)) {
|
|
const calendarEvent = new CalendarEvent({
|
|
title: `Vehicle ${vehicle?.vehicle_number} (${vehicle?.tag})'s Emission Test would expire in 15 days`,
|
|
description: `Vehicle ${vehicle?.vehicle_number} (${vehicle?.tag})'s Emission Test would expire in 15 day, please check whether it is renewed properly`,
|
|
type: 'reminder',
|
|
start_time: newDate1,
|
|
stop_time: new Date(newDate1.getTime() + 10*60*1000),
|
|
color: 'brown',
|
|
target_type: 'vehicle',
|
|
target_uuid: vehicle.id,
|
|
target_name: vechile.vehicle_number,
|
|
event_reminder_type: 'emission_test',
|
|
status: 'active',
|
|
site,
|
|
edit_date: new Date(),
|
|
create_date: new Date(),
|
|
create_by: 'system',
|
|
edit_by: 'system',
|
|
edit_history: [{employee: 'system', date: new Date()}]
|
|
})
|
|
await calendarEvent.save(calendarEvent);
|
|
}
|
|
}
|
|
if ( titleExpireDate >= today && titleExpireDate < futureDate) {
|
|
if (!allVehiclesCalendarEvent.find(item => item.event_reminder_type === 'title_expire' && item.target_uuid === vehicle.id)) {
|
|
const calendarEvent = new CalendarEvent({
|
|
title: `Vehicle ${vehicle?.vehicle_number} (${vehicle?.tag})'s Title would expire in 15 days`,
|
|
description: `Vehicle ${vehicle?.vehicle_number} (${vehicle?.tag})'s Title would expire in 15 day, please check whether it is renewed properly`,
|
|
type: 'reminder',
|
|
start_time: newDate2,
|
|
stop_time: new Date(newDate2.getTime() + 10*60*1000),
|
|
color: 'brown',
|
|
target_type: 'vehicle',
|
|
target_uuid: vehicle.id,
|
|
target_name: vechile.vehicle_number,
|
|
event_reminder_type: 'title_expire',
|
|
status: 'active',
|
|
site,
|
|
edit_date: new Date(),
|
|
create_date: new Date(),
|
|
create_by: 'system',
|
|
edit_by: 'system',
|
|
edit_history: [{employee: 'system', date: new Date()}]
|
|
})
|
|
await calendarEvent.save(calendarEvent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async createCustomerRelatedEvents(daysAhead = 30) {
|
|
const today = new Date();
|
|
const upcomingDates = [];
|
|
|
|
// Calculate dates for the next 'daysAhead' days
|
|
for (let i=0; i<=daysAhead; i++) {
|
|
const targetDate = new Date(today);
|
|
targetDate.setDate(today.getDate() + i);
|
|
|
|
upcomingDates.push(targetDate)
|
|
}
|
|
|
|
const sites = await getAllSites();
|
|
for (const site of sites) {
|
|
const allCustomers = await Customer.find({ site });
|
|
const allExistingBirthdayReminders = await CalendarEvent.find({ type: 'reminder', status: 'active', rrule: 'FREQ=YEARLY', event_reminder_type: 'birthday', site });
|
|
const allExistingPaymentReminders = await CalendarEvent.find({ type: 'reminder', status: 'active', event_reminder_type: 'payment', site });
|
|
|
|
for (const customer of allCustomers) {
|
|
const { month, day } = this.parseMonthDay(customer?.birth_date);
|
|
const { month: month1, day: day1 } = this.parseMonthDay(customer?.payment_due_date);
|
|
for (const targetDate of upcomingDates) {
|
|
// Birthday reminders are rendered dynamically in Important Dates calendar.
|
|
if (month1 === targetDate.getMonth() + 1 && day1 === targetDate.getDate()) {
|
|
if (!allExistingPaymentReminders.find((reminder) => reminder.target_uuid === customer?.id)) {
|
|
const calendarEvent = new CalendarEvent({
|
|
title: `${customer?.name}'s Payment Due Date`,
|
|
description: `${customer?.name}'s payment would be due on ${customer?.payment_due_date}`,
|
|
type: 'reminder',
|
|
start_time: targetDate,
|
|
stop_time: new Date(targetDate.getTime() + 10*60*1000),
|
|
color: 'red',
|
|
target_type: 'customer',
|
|
target_uuid: customer?.id,
|
|
target_name: customer?.name,
|
|
event_reminder_type: 'payment',
|
|
status: 'active',
|
|
site,
|
|
edit_date: new Date(),
|
|
create_date: new Date(),
|
|
create_by: 'system',
|
|
edit_by: 'system',
|
|
edit_history: [{employee: 'system', date: new Date()}]
|
|
})
|
|
await calendarEvent.save(calendarEvent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
module.exports = new ReminderService(); |