This commit is contained in:
@@ -3,35 +3,39 @@ const Vehicle = db.vehicle;
|
|||||||
const Customer = db.customer;
|
const Customer = db.customer;
|
||||||
const CalendarEvent = db.calendar_event;
|
const CalendarEvent = db.calendar_event;
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const siteMap = {
|
const toSiteNumber = (value) => {
|
||||||
'ws1': 1,
|
const parsed = Number(value);
|
||||||
'worldshine1': 1,
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
|
||||||
'ws2': 2,
|
|
||||||
'worldshine2': 2,
|
|
||||||
'ws3': 3,
|
|
||||||
'worldshine3': 3,
|
|
||||||
'worldshine4': 4,
|
|
||||||
'ws4': 4,
|
|
||||||
'worldshine.mayo.llc': 1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSite = () => {
|
const getAllSites = async () => {
|
||||||
console.log('here', __dirname);
|
const [customerSites, vehicleSites, eventSites] = await Promise.all([
|
||||||
let site = 1;
|
Customer.distinct('site'),
|
||||||
const arr = __dirname.split('/');
|
Vehicle.distinct('site'),
|
||||||
for (const key of Object.keys(siteMap)) {
|
CalendarEvent.distinct('site')
|
||||||
if (arr.includes(key)) {
|
]);
|
||||||
site = siteMap[key];
|
const normalizedSites = [...new Set([...customerSites, ...vehicleSites, ...eventSites]
|
||||||
break;
|
.map(toSiteNumber)
|
||||||
}
|
.filter(Boolean))];
|
||||||
}
|
return normalizedSites.length > 0 ? normalizedSites : [1];
|
||||||
return site;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
class ReminderService {
|
class ReminderService {
|
||||||
parseDate(dateString) {
|
parseDate(dateString) {
|
||||||
|
if (!dateString || typeof dateString !== 'string') return null;
|
||||||
const [month, day, year] = dateString.split('/').map(Number);
|
const [month, day, year] = dateString.split('/').map(Number);
|
||||||
return new Date(year, month-1,day);
|
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) {
|
async createVehicleRelatedEvents(daysAhead = 30) {
|
||||||
@@ -39,15 +43,18 @@ class ReminderService {
|
|||||||
const futureDate = new Date();
|
const futureDate = new Date();
|
||||||
futureDate.setDate(today.getDate() + daysAhead); // check 30 days ahead
|
futureDate.setDate(today.getDate() + daysAhead); // check 30 days ahead
|
||||||
|
|
||||||
const vehicles = await Vehicle.find({status: 'active', site: getSite()});
|
const sites = await getAllSites();
|
||||||
const allVehiclesCalendarEvent = await CalendarEvent.find({type: 'reminder', status: 'active', site: getSite(), target_type: 'vehicle'});
|
for (const site of sites) {
|
||||||
console.log('vehicles', vehicles);
|
const vehicles = await Vehicle.find({status: 'active', site});
|
||||||
for (const vehicle of vehicles) {
|
const allVehiclesCalendarEvent = await CalendarEvent.find({type: 'reminder', status: 'active', site, target_type: 'vehicle'});
|
||||||
const insuranceExpireDate = this.parseDate(vehicle.insurance_expire_on);
|
for (const vehicle of vehicles) {
|
||||||
const titleRegistrationDate = this.parseDate(vehicle.title_registration_on);
|
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);
|
const titleExpireDate = new Date(titleRegistrationDate);
|
||||||
titleExpireDate.setFullYear(titleExpireDate.getFullYear() + 1);
|
titleExpireDate.setFullYear(titleExpireDate.getFullYear() + 1);
|
||||||
const emissionTestDate = this.parseDate(vehicle.emission_test_on);
|
const emissionTestDate = this.parseDate(vehicle.emission_test_on);
|
||||||
|
if (!emissionTestDate) continue;
|
||||||
const emissionTestExpireDate = new Date(emissionTestDate);
|
const emissionTestExpireDate = new Date(emissionTestDate);
|
||||||
emissionTestExpireDate.setFullYear(titleExpireDate.getFullYear() + 1);
|
emissionTestExpireDate.setFullYear(titleExpireDate.getFullYear() + 1);
|
||||||
const newDate = new Date(insuranceExpireDate);
|
const newDate = new Date(insuranceExpireDate);
|
||||||
@@ -70,7 +77,7 @@ class ReminderService {
|
|||||||
target_name: vechile.vehicle_number,
|
target_name: vechile.vehicle_number,
|
||||||
event_reminder_type: 'insurance_expire',
|
event_reminder_type: 'insurance_expire',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
site: getSite(),
|
site,
|
||||||
edit_date: new Date(),
|
edit_date: new Date(),
|
||||||
create_date: new Date(),
|
create_date: new Date(),
|
||||||
create_by: 'system',
|
create_by: 'system',
|
||||||
@@ -94,7 +101,7 @@ class ReminderService {
|
|||||||
target_name: vechile.vehicle_number,
|
target_name: vechile.vehicle_number,
|
||||||
event_reminder_type: 'emission_test',
|
event_reminder_type: 'emission_test',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
site: getSite(),
|
site,
|
||||||
edit_date: new Date(),
|
edit_date: new Date(),
|
||||||
create_date: new Date(),
|
create_date: new Date(),
|
||||||
create_by: 'system',
|
create_by: 'system',
|
||||||
@@ -118,7 +125,7 @@ class ReminderService {
|
|||||||
target_name: vechile.vehicle_number,
|
target_name: vechile.vehicle_number,
|
||||||
event_reminder_type: 'title_expire',
|
event_reminder_type: 'title_expire',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
site: getSite(),
|
site,
|
||||||
edit_date: new Date(),
|
edit_date: new Date(),
|
||||||
create_date: new Date(),
|
create_date: new Date(),
|
||||||
create_by: 'system',
|
create_by: 'system',
|
||||||
@@ -127,6 +134,7 @@ class ReminderService {
|
|||||||
})
|
})
|
||||||
await calendarEvent.save(calendarEvent);
|
await calendarEvent.save(calendarEvent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,44 +151,17 @@ class ReminderService {
|
|||||||
upcomingDates.push(targetDate)
|
upcomingDates.push(targetDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
const allCustomers = await Customer.find({ site: getSite()});
|
const sites = await getAllSites();
|
||||||
console.log('allCustomers', allCustomers);
|
for (const site of sites) {
|
||||||
const allExistingBirthdayReminders = await CalendarEvent.find({ type: 'reminder', status: 'active', rrule: 'FREQ=YEARLY', event_reminder_type: 'birthday', site: getSite() });
|
const allCustomers = await Customer.find({ site });
|
||||||
const allExistingPaymentReminders = await CalendarEvent.find({ type: 'reminder', status: 'active', event_reminder_type: 'payment', site: getSite() });
|
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) {
|
for (const customer of allCustomers) {
|
||||||
const [month, day, year] = customer?.birth_date?.split('/').map(Number) || [-1, -1, -1];
|
const { month, day } = this.parseMonthDay(customer?.birth_date);
|
||||||
const [month1, day1, year1] = customer?.payment_due_date?.split('/').map(Number) || [-1, -1, -1];
|
const { month: month1, day: day1 } = this.parseMonthDay(customer?.payment_due_date);
|
||||||
for (const targetDate of upcomingDates) {
|
for (const targetDate of upcomingDates) {
|
||||||
if (month === targetDate.getMonth() + 1 && day === targetDate.getDate()) {
|
// Birthday reminders are rendered dynamically in Important Dates calendar.
|
||||||
console.log('targetDate found', targetDate);
|
|
||||||
console.log('are you sure you find', allExistingBirthdayReminders.find((reminder) => reminder.target_uuid === customer?.id));
|
|
||||||
if (!allExistingBirthdayReminders.find((reminder) => reminder.target_uuid === customer?.id)) {
|
|
||||||
console.log(123123);
|
|
||||||
const calendarEvent = new CalendarEvent({
|
|
||||||
title: `${customer?.name}'s Birthday`,
|
|
||||||
description: `Happy Birthday to ${customer?.name}`,
|
|
||||||
type: 'reminder',
|
|
||||||
start_time: targetDate,
|
|
||||||
stop_time: new Date(targetDate.getTime() + 10*60*1000),
|
|
||||||
color: 'orange',
|
|
||||||
target_type: 'customer',
|
|
||||||
target_uuid: customer?.id,
|
|
||||||
target_name: customer?.name,
|
|
||||||
event_reminder_type: 'birthday',
|
|
||||||
rrule: 'FREQ=YEARLY',
|
|
||||||
status: 'active',
|
|
||||||
site: getSite(),
|
|
||||||
edit_date: new Date(),
|
|
||||||
create_date: new Date(),
|
|
||||||
create_by: 'system',
|
|
||||||
edit_by: 'system',
|
|
||||||
edit_history: [{employee: 'system', date: new Date()}]
|
|
||||||
});
|
|
||||||
console.log('start to create', calendarEvent);
|
|
||||||
await calendarEvent.save(calendarEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (month1 === targetDate.getMonth() + 1 && day1 === targetDate.getDate()) {
|
if (month1 === targetDate.getMonth() + 1 && day1 === targetDate.getDate()) {
|
||||||
if (!allExistingPaymentReminders.find((reminder) => reminder.target_uuid === customer?.id)) {
|
if (!allExistingPaymentReminders.find((reminder) => reminder.target_uuid === customer?.id)) {
|
||||||
const calendarEvent = new CalendarEvent({
|
const calendarEvent = new CalendarEvent({
|
||||||
@@ -195,7 +176,7 @@ class ReminderService {
|
|||||||
target_name: customer?.name,
|
target_name: customer?.name,
|
||||||
event_reminder_type: 'payment',
|
event_reminder_type: 'payment',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
site: getSite(),
|
site,
|
||||||
edit_date: new Date(),
|
edit_date: new Date(),
|
||||||
create_date: new Date(),
|
create_date: new Date(),
|
||||||
create_by: 'system',
|
create_by: 'system',
|
||||||
@@ -206,6 +187,7 @@ class ReminderService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,6 +217,46 @@ const EventsCalendar = () => {
|
|||||||
return instances;
|
return instances;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const buildDynamicBirthdayEvents = (customerList = [], rangeFrom, rangeTo) => {
|
||||||
|
if (!rangeFrom || !rangeTo) return [];
|
||||||
|
const from = new Date(rangeFrom);
|
||||||
|
const to = new Date(rangeTo);
|
||||||
|
const startYear = from.getFullYear();
|
||||||
|
const endYear = to.getFullYear();
|
||||||
|
const dynamicEvents = [];
|
||||||
|
|
||||||
|
customerList.forEach((customer) => {
|
||||||
|
const birthDate = `${customer?.birth_date || ''}`;
|
||||||
|
const [month, day] = birthDate.split('/').map(Number);
|
||||||
|
if (!month || !day) return;
|
||||||
|
|
||||||
|
for (let year = startYear; year <= endYear; year++) {
|
||||||
|
const birthday = new Date(year, month - 1, day);
|
||||||
|
if (Number.isNaN(birthday.getTime())) continue;
|
||||||
|
if (birthday < from || birthday > to) continue;
|
||||||
|
dynamicEvents.push({
|
||||||
|
id: `dynamic-birthday-${customer.id}-${year}`,
|
||||||
|
type: 'reminder',
|
||||||
|
status: 'active',
|
||||||
|
title: `${customer?.name}'s Birthday`,
|
||||||
|
description: `Happy Birthday to ${customer?.name}`,
|
||||||
|
start_time: birthday,
|
||||||
|
stop_time: new Date(birthday.getTime() + 10 * 60 * 1000),
|
||||||
|
color: 'member_related',
|
||||||
|
target_type: 'customer',
|
||||||
|
target_uuid: customer?.id,
|
||||||
|
target_name: customer?.name,
|
||||||
|
event_reminder_type: 'birthday',
|
||||||
|
rrule: 'FREQ=YEARLY',
|
||||||
|
create_by: 'system-dynamic',
|
||||||
|
edit_by: 'system-dynamic'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return dynamicEvents;
|
||||||
|
};
|
||||||
|
|
||||||
const eventTypeMap = {
|
const eventTypeMap = {
|
||||||
medicalCalendar: 'medical',
|
medicalCalendar: 'medical',
|
||||||
activitiesCalendar: 'activity',
|
activitiesCalendar: 'activity',
|
||||||
@@ -426,11 +466,21 @@ const EventsCalendar = () => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Expand recurring event rules into individual instances and merge with regular events
|
// Expand recurring event rules into individual instances and merge with regular events
|
||||||
const recurInstances = allEventRecurrences
|
let recurInstances = allEventRecurrences
|
||||||
.filter(rule => rule.type === eventTypeMap[currentTab] && rule.status === 'active')
|
.filter(rule => rule.type === eventTypeMap[currentTab] && rule.status === 'active')
|
||||||
.flatMap(rule => expandRecurrence(rule, fromDate, toDate));
|
.flatMap(rule => expandRecurrence(rule, fromDate, toDate));
|
||||||
const originalEvents = [...allEvents, ...recurInstances];
|
let baseEvents = [...allEvents];
|
||||||
let filteredEvents = originalEvents?.filter(item => item.type === eventTypeMap[currentTab])?.map(item => {
|
if (currentTab === 'reminderDatesCalendar') {
|
||||||
|
// Birthday reminders are rendered dynamically from customer data.
|
||||||
|
baseEvents = baseEvents.filter((item) => item?.event_reminder_type !== 'birthday');
|
||||||
|
recurInstances = recurInstances.filter((item) => item?.event_reminder_type !== 'birthday');
|
||||||
|
}
|
||||||
|
const originalEvents = [...baseEvents, ...recurInstances];
|
||||||
|
const dynamicBirthdayEvents = currentTab === 'reminderDatesCalendar'
|
||||||
|
? buildDynamicBirthdayEvents(customers, fromDate, toDate)
|
||||||
|
: [];
|
||||||
|
const mergedEvents = [...originalEvents, ...dynamicBirthdayEvents];
|
||||||
|
let filteredEvents = mergedEvents?.filter(item => item.type === eventTypeMap[currentTab])?.map(item => {
|
||||||
// For Important Dates, remap old blue/orange colors to new member_related/vehicle_maintenance
|
// For Important Dates, remap old blue/orange colors to new member_related/vehicle_maintenance
|
||||||
let eventColor = item?.color;
|
let eventColor = item?.color;
|
||||||
if (currentTab === 'reminderDatesCalendar') {
|
if (currentTab === 'reminderDatesCalendar') {
|
||||||
|
|||||||
Reference in New Issue
Block a user