
show unpublished events in calendar for ADMINS mark unavailable publishers when they are available on another time on the same day;
818 lines
32 KiB
JavaScript
818 lines
32 KiB
JavaScript
|
|
const common = require('./common');
|
|
|
|
async function findPublisher(names, email, select, getAll = false) {
|
|
// Normalize and split the name if provided
|
|
let nameParts = names ? names.normalize('NFC').trim().split(/\s+/) : [];
|
|
|
|
// Construct the select clause
|
|
let selectClause = select
|
|
? select.split(",").reduce((acc, curr) => ({ ...acc, [curr]: true }), {})
|
|
: { id: true, firstName: true, lastName: true };
|
|
|
|
|
|
// Construct the where clause based on the provided data
|
|
let whereClause = [];
|
|
if (nameParts.length > 0) {
|
|
if (nameParts.length === 1) {
|
|
// If only one name part is provided, check it against both firstName and lastName
|
|
whereClause.push({ OR: [{ firstName: nameParts[0] }, { lastName: nameParts[0] }] });
|
|
} else if (nameParts.length === 2) {
|
|
// If two name parts are provided, check combinations of firstName and lastName
|
|
whereClause.push({ firstName: nameParts[0], lastName: nameParts[1] });
|
|
whereClause.push({ firstName: nameParts[1], lastName: nameParts[0] });
|
|
} else if (nameParts.length === 3) {
|
|
// If three name parts are provided, consider the middle name part of first or last name
|
|
whereClause.push({ firstName: `${nameParts[0]} ${nameParts[1]}`, lastName: nameParts[2] });
|
|
whereClause.push({ firstName: nameParts[0], lastName: `${nameParts[1]} ${nameParts[2]}` });
|
|
} else if (nameParts.length > 3) {
|
|
// Join all parts except the last as the first name, and consider the last part as the last name
|
|
const firstName = nameParts.slice(0, -1).join(' ');
|
|
const lastName = nameParts.slice(-1).join(' ');
|
|
whereClause.push({ firstName: firstName, lastName: lastName });
|
|
|
|
// Alternative case: First part as first name, and join the rest as the last name
|
|
const altFirstName = nameParts.slice(0, 1).join(' ');
|
|
const altLastName = nameParts.slice(1).join(' ');
|
|
whereClause.push({ firstName: altFirstName, lastName: altLastName });
|
|
}
|
|
}
|
|
|
|
if (email) {
|
|
whereClause.push({ email: email });
|
|
}
|
|
|
|
if (whereClause.length === 0) {
|
|
return null; // No search criteria provided
|
|
}
|
|
|
|
|
|
const prisma = common.getPrismaClient();
|
|
// let publisher = await prisma.publisher.findFirst({
|
|
// select: selectClause,
|
|
// where: { OR: whereClause }
|
|
// });
|
|
// Retrieve all matching records
|
|
try {
|
|
let result = await prisma.publisher.findMany({
|
|
select: selectClause,
|
|
where: { OR: whereClause }
|
|
});
|
|
|
|
// If getAll is false, take only the first record
|
|
if (!getAll && result.length > 0) {
|
|
result = result.length > 0 ? [result[0]] : [];
|
|
}
|
|
if (result.length === 0 && names) {
|
|
console.log("No publisher found, trying fuzzy search for '" + names + "'- email: '" + email + "'");
|
|
const publishers = await prisma.publisher.findMany();
|
|
result = [await common.fuzzySearch(publishers, names, 0.90)];
|
|
console.log("Fuzzy search result: " + result[0]?.firstName + " " + result[0]?.lastName + " - " + result[0]?.email);
|
|
}
|
|
//always return an array
|
|
result = result || [];
|
|
return result;
|
|
} catch (error) {
|
|
console.error("Error finding publisher: ", error);
|
|
throw error; // Rethrow the error or handle it as needed
|
|
}
|
|
}
|
|
|
|
async function findPublisherAvailability(publisherId, date) {
|
|
const prisma = common.getPrismaClient();
|
|
date = new Date(date); // Convert to date object if not already
|
|
const hours = date.getHours();
|
|
const minutes = date.getMinutes();
|
|
|
|
const potentialAvailabilities = await prisma.availability.findMany({
|
|
where: {
|
|
publisherId: publisherId,
|
|
AND: [ // Ensure both conditions must be met
|
|
{
|
|
startTime: {
|
|
lte: new Date(date), // startTime is less than or equal to the date
|
|
},
|
|
},
|
|
{
|
|
endTime: {
|
|
gte: new Date(date), // endTime is greater than or equal to the date
|
|
},
|
|
},
|
|
],
|
|
}
|
|
});
|
|
|
|
if (potentialAvailabilities.length === 0) {
|
|
return null; // No availability found
|
|
}
|
|
// Filter the results based on time and other criteria when not exact date match
|
|
const availability = potentialAvailabilities.find(avail => {
|
|
const availStartHours = avail.startTime.getHours();
|
|
const availStartMinutes = avail.startTime.getMinutes();
|
|
const availEndHours = avail.endTime.getHours();
|
|
const availEndMinutes = avail.endTime.getMinutes();
|
|
|
|
const isAfterStartTime = hours > availStartHours || (hours === availStartHours && minutes >= availStartMinutes);
|
|
const isBeforeEndTime = hours < availEndHours || (hours === availEndHours && minutes <= availEndMinutes);
|
|
// check day of week if not null
|
|
const isCorrectDayOfWeek = avail.repeatWeekly ? avail.startTime.getDay() === date.getDay() : true;
|
|
const isExactDateMatch = avail.dayOfMonth ? avail.startTime.toDateString() === date.toDateString() : true;
|
|
const isBeforeEndDate = avail.repeatWeekly ? true : avail.endTime > date;
|
|
//const isCorrectWeekOfMonth = avail.repeatWeekly ? true : avail.weekOfMonth === weekOfMonth;
|
|
|
|
return isAfterStartTime && isBeforeEndTime && isCorrectDayOfWeek && isExactDateMatch && isBeforeEndDate;
|
|
});
|
|
|
|
return availability;
|
|
}
|
|
|
|
|
|
async function getAvailabilities(userId) {
|
|
const prismaClient = common.getPrismaClient();
|
|
const items = await prismaClient.availability.findMany({
|
|
where: {
|
|
publisherId: userId,
|
|
},
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
isActive: true,
|
|
isFromPreviousAssignment: true,
|
|
dayofweek: true,
|
|
dayOfMonth: true,
|
|
startTime: true,
|
|
endTime: true,
|
|
repeatWeekly: true,
|
|
endDate: true,
|
|
publisher: {
|
|
select: {
|
|
firstName: true,
|
|
lastName: true,
|
|
id: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
// Convert Date objects to ISO strings
|
|
const serializableItems = items.map(item => ({
|
|
...item,
|
|
startTime: item.startTime.toISOString(),
|
|
endTime: item.endTime.toISOString(),
|
|
name: common.getTimeFormatted(item.startTime) + "-" + common.getTimeFormatted(item.endTime),
|
|
//endDate can be null
|
|
endDate: item.endDate ? item.endDate.toISOString() : null,
|
|
type: 'availability',
|
|
// Convert other Date fields similarly if they exist
|
|
}));
|
|
|
|
/*model Assignment {
|
|
id Int @id @default(autoincrement())
|
|
shift Shift @relation(fields: [shiftId], references: [id], onDelete: Cascade)
|
|
shiftId Int
|
|
publisher Publisher @relation(fields: [publisherId], references: [id], onDelete: Cascade)
|
|
publisherId String
|
|
isActive Boolean @default(true)
|
|
isConfirmed Boolean @default(false)
|
|
isWithTransport Boolean @default(false)
|
|
Report Report[]
|
|
}*/
|
|
//get assignments for this user
|
|
const assignments = await prismaClient.assignment.findMany({
|
|
where: {
|
|
publisherId: userId,
|
|
},
|
|
select: {
|
|
id: true,
|
|
isBySystem: true,
|
|
isConfirmed: true,
|
|
isWithTransport: true,
|
|
shift: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
startTime: true,
|
|
endTime: true,
|
|
//select all assigned publishers names as name - comma separated
|
|
assignments: {
|
|
select: {
|
|
publisher: {
|
|
select: {
|
|
firstName: true,
|
|
lastName: true,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
const serializableAssignments = assignments.map(item => ({
|
|
...item,
|
|
startTime: item.shift.startTime.toISOString(),
|
|
endTime: item.shift.endTime.toISOString(),
|
|
// name: item.shift.publishers.map(p => p.firstName + " " + p.lastName).join(", "),
|
|
//name: item.shift.assignments.map(a => a.publisher.firstName[0] + " " + a.publisher.lastName).join(", "),
|
|
name: common.getTimeFormatted(new Date(item.shift.startTime)) + "-" + common.getTimeFormatted(new Date(item.shift.endTime)),
|
|
type: 'assignment',
|
|
//delete shift object
|
|
shift: null,
|
|
publisher: { id: userId }
|
|
}));
|
|
|
|
serializableItems.push(...serializableAssignments);
|
|
|
|
return serializableItems;
|
|
|
|
}
|
|
|
|
|
|
async function filterPublishersNew(selectFields, filterDate, isExactTime = false, isForTheMonth = false, noEndDateFilter = false, isWithStats = true, includeOldAvailabilities = false) {
|
|
|
|
const prisma = common.getPrismaClient();
|
|
filterDate = new Date(filterDate); // Convert to date object if not already
|
|
|
|
const monthInfo = common.getMonthDatesInfo(filterDate);
|
|
let prevMnt = new Date(filterDate)
|
|
prevMnt.setMonth(prevMnt.getMonth() - 1);
|
|
const prevMonthInfo = common.getMonthDatesInfo(prevMnt);
|
|
|
|
// Only attempt to split if selectFields is a string; otherwise, use it as it is.
|
|
selectFields = typeof selectFields === 'string' ? selectFields.split(",") : selectFields;
|
|
|
|
let selectBase = selectFields.reduce((acc, curr) => {
|
|
acc[curr] = true;
|
|
return acc;
|
|
}, {});
|
|
|
|
|
|
selectBase.assignments = {
|
|
select: {
|
|
id: true,
|
|
shift: {
|
|
select: {
|
|
id: true,
|
|
startTime: true,
|
|
endTime: true
|
|
}
|
|
}
|
|
},
|
|
where: {
|
|
shift: {
|
|
startTime: {
|
|
gte: prevMnt,
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
let filterTimeFrom = new Date(filterDate)
|
|
let filterTimeTo = new Date(filterDate);
|
|
let isDayFilter = true;
|
|
let whereClause = {};
|
|
|
|
if (isForTheMonth) {
|
|
var weekNr = common.getWeekOfMonth(filterDate); //getWeekNumber
|
|
|
|
filterTimeFrom = monthInfo.firstMonday;
|
|
filterTimeTo = monthInfo.lastSunday;
|
|
isDayFilter = false;
|
|
}
|
|
if (isExactTime) {
|
|
//add +- 90 minutes to the filterDate ToDo: should be "shift duration"
|
|
// filterTimeFrom.setMinutes(filterTimeFrom.getMinutes() - 90);
|
|
filterTimeTo.setMinutes(filterTimeTo.getMinutes() + 90);
|
|
}
|
|
else {
|
|
filterTimeFrom.setHours(0, 0, 0, 0);
|
|
filterTimeTo.setHours(23, 59, 59, 999);
|
|
}
|
|
|
|
whereClause["availabilities"] = {
|
|
some: {
|
|
OR: [
|
|
// Check if dayOfMonth is not null and startTime is after monthInfo.firstMonday (Assignments on specific days AND time)
|
|
{
|
|
//dayOfMonth: { not: null },
|
|
startTime: { gte: filterTimeFrom },
|
|
// endTime: { lte: monthInfo.lastSunday }
|
|
},
|
|
// Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
|
|
{
|
|
// dayOfMonth: null,
|
|
// startTime: { gte: filterTimeFrom },
|
|
AND: [
|
|
{ dayOfMonth: null },
|
|
{ startTime: { lte: filterTimeTo } }, // startTime included
|
|
{
|
|
OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
|
|
{ endDate: { gte: filterTimeFrom } }, // endDate included
|
|
{ endDate: null }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
};
|
|
|
|
/* FILTERS
|
|
1. exact time
|
|
2. exact date
|
|
3. the month
|
|
4. from start date only
|
|
*/
|
|
|
|
if (noEndDateFilter) {
|
|
isDayFilter = false;
|
|
}
|
|
else {
|
|
whereClause["availabilities"].some.OR[0].endTime = { lte: filterTimeTo };
|
|
if (isForTheMonth) {
|
|
// no dayofweek or time filters here
|
|
}
|
|
else {
|
|
let dayOfWeekEnum = common.getDayOfWeekNameEnEnumForDate(filterDate);
|
|
whereClause["availabilities"].some.OR[1].dayofweek = dayOfWeekEnum;
|
|
//NOTE: we filter by date after we calculate the correct dates post query
|
|
if (isExactTime) {
|
|
//if exact time we need the availability to be starting on or before start of the shift and ending on or after the end of the shift
|
|
whereClause["availabilities"].some.OR[0].startTime = { lte: filterTimeFrom };
|
|
whereClause["availabilities"].some.OR[0].endTime = { gte: filterTimeTo };
|
|
}
|
|
else {
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
console.log(`getting publishers for date: ${filterDate}, isExactTime: ${isExactTime}, isForTheMonth: ${isForTheMonth}`);
|
|
console.log`whereClause: ${JSON.stringify(whereClause)}`
|
|
//include availabilities if flag is true
|
|
let publishers = await prisma.publisher.findMany({
|
|
where: whereClause,
|
|
select: {
|
|
...selectBase,
|
|
availabilities: true
|
|
}
|
|
});
|
|
|
|
console.log(`publishers: ${publishers.length}, WhereClause: ${JSON.stringify(whereClause)}`);
|
|
|
|
// convert matching weekly availabilities to availabilities for the day to make further processing easier on the client.
|
|
// we trust that the filtering was OK, so we use the dateFilter as date.
|
|
publishers.forEach(pub => {
|
|
pub.availabilities = pub.availabilities.map(avail => {
|
|
if (avail.dayOfMonth == null) {
|
|
let newStart = new Date(filterDate);
|
|
newStart.setHours(avail.startTime.getHours(), avail.startTime.getMinutes(), 0, 0);
|
|
let newEnd = new Date(filterDate);
|
|
newEnd.setHours(avail.endTime.getHours(), avail.endTime.getMinutes(), 0, 0);
|
|
return {
|
|
...avail,
|
|
startTime: newStart,
|
|
endTime: newEnd
|
|
}
|
|
}
|
|
return avail;
|
|
});
|
|
});
|
|
|
|
|
|
let currentWeekStart, currentWeekEnd;
|
|
|
|
if (isWithStats) {
|
|
currentWeekStart = common.getStartOfWeek(filterDate);
|
|
currentWeekEnd = common.getEndOfWeek(filterDate);
|
|
|
|
//get if publisher has assignments for current weekday, week, current month, previous month
|
|
publishers.forEach(pub => {
|
|
// Filter assignments for current day
|
|
if (isDayFilter) {
|
|
pub.currentDayAssignments = pub.assignments?.filter(assignment => {
|
|
return assignment.shift.startTime >= filterDate && assignment.shift.startTime <= filterTimeTo;
|
|
}).length;
|
|
}
|
|
// Filter assignments for current week
|
|
pub.currentWeekAssignments = pub.assignments?.filter(assignment => {
|
|
return assignment.shift.startTime >= currentWeekStart && assignment.shift.startTime <= currentWeekEnd;
|
|
}).length;
|
|
|
|
// Filter assignments for current month
|
|
pub.currentMonthAssignments = pub.assignments?.filter(assignment => {
|
|
return assignment.shift.startTime >= monthInfo.firstMonday && (noEndDateFilter || assignment.shift.startTime <= monthInfo.lastSunday);
|
|
}).length;
|
|
|
|
// Filter assignments for previous month
|
|
pub.previousMonthAssignments = pub.assignments?.filter(assignment => {
|
|
return assignment.shift.startTime >= prevMonthInfo.firstMonday && assignment.shift.startTime <= prevMonthInfo.lastSunday;
|
|
}).length;
|
|
});
|
|
|
|
}
|
|
|
|
//get the availabilities for the day. Calculate:
|
|
//1. how many days the publisher is available for the current month - only with dayOfMonth
|
|
//2. how many days the publisher is available without dayOfMonth (previous months count)
|
|
//3. how many hours in total the publisher is available for the current month
|
|
publishers.forEach(pub => {
|
|
if (isWithStats) {
|
|
pub.currentMonthAvailability = pub.availabilities?.filter(avail => {
|
|
// return avail.dayOfMonth != null && avail.startTime >= currentMonthStart && avail.startTime <= monthInfo.lastSunday;
|
|
return avail.startTime >= monthInfo.firstMonday && (noEndDateFilter || avail.startTime <= monthInfo.lastSunday);
|
|
})
|
|
pub.currentMonthAvailabilityDaysCount = pub.currentMonthAvailability.length;
|
|
// pub.currentMonthAvailabilityDaysCount += pub.availabilities.filter(avail => {
|
|
// return avail.dayOfMonth == null;
|
|
// }).length;
|
|
pub.currentMonthAvailabilityHoursCount = pub.currentMonthAvailability.reduce((acc, curr) => {
|
|
return acc + (curr.endTime.getTime() - curr.startTime.getTime()) / (1000 * 60 * 60);
|
|
}, 0);
|
|
//if pub has up-to-date availabilities (with dayOfMonth) for the current month
|
|
pub.hasUpToDateAvailabilities = pub.availabilities?.some(avail => {
|
|
return avail.dayOfMonth != null && avail.startTime >= monthInfo.firstMonday; // && avail.startTime <= monthInfo.lastSunday;
|
|
});
|
|
|
|
}
|
|
|
|
//if pub has ever filled the form - if has availabilities which are not from previous assignments
|
|
pub.hasEverFilledForm = pub.availabilities?.some(avail => {
|
|
return avail.isFromPreviousAssignments == false;
|
|
});
|
|
if (isDayFilter) {
|
|
//if pub has availabilities for the current day
|
|
pub.hasAvailabilityForCurrentDay = pub.availabilities?.some(avail => {
|
|
return avail.startTime >= filterDate && avail.startTime <= filterTimeTo;
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
|
|
if (isExactTime) {
|
|
//HERE WE FILTER by time for repeating availabilities. We can't do that if we don't have
|
|
// whereClause["availabilities"].some.OR[1].startTime = { gte: filterTimeFrom };
|
|
// whereClause["availabilities"].some.OR[1].endTime = { gte: filterTimeTo }
|
|
publishers.forEach(pub => {
|
|
pub.availabilities.filter(a => a.startTime > filterTimeFrom && a.endTime < filterTimeTo)
|
|
});
|
|
publishers.filter(pub => pub.availabilities.length > 0);
|
|
}
|
|
|
|
// if (isExactTime) {
|
|
// // Post filter for time if dayOfMonth is null as we can't only by time for multiple dates in SQL
|
|
// // Modify the availabilities array of the filtered publishers
|
|
// publishers.forEach(pub => {
|
|
// pub.availabilities = pub.availabilities?.filter(avail => matchesAvailability(avail, filterDate));
|
|
// });
|
|
// }
|
|
return publishers;
|
|
|
|
}
|
|
|
|
//ToDo: refactor this function
|
|
async function getAllPublishersWithStatistics(filterDate) {
|
|
|
|
const prisma = common.getPrismaClient();
|
|
const monthInfo = common.getMonthDatesInfo(new Date(filterDate));
|
|
const dateStr = new Date(monthInfo.firstMonday).toISOString().split('T')[0];
|
|
|
|
let publishers = await filterPublishersNew('id,firstName,lastName,email,isActive,desiredShiftsPerMonth,lastLogin,type', dateStr, false, true, true, true, true);
|
|
|
|
// const axios = await axiosServer(context);
|
|
// const { data: publishers } = await axios.get(`api/?action=filterPublishers&assignments=true&availabilities=true&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth`);
|
|
|
|
// api/index?action=filterPublishers&assignments=true&availabilities=true&date=2024-03-14&select=id%2CfirstName%2ClastName%2CisActive%2CdesiredShiftsPerMonth
|
|
publishers.forEach(publisher => {
|
|
publisher.desiredShiftsPerMonth = publisher.desiredShiftsPerMonth || 0;
|
|
publisher.assignments = publisher.assignments || [];
|
|
publisher.availabilities = publisher.availabilities || [];
|
|
publisher.lastUpdate = publisher.availabilities.reduce((acc, curr) => curr.dateOfEntry > acc ? curr.dateOfEntry : acc, null);
|
|
if (publisher.lastUpdate) {
|
|
publisher.lastUpdate = common.getDateFormated(publisher.lastUpdate);
|
|
}
|
|
else {
|
|
publisher.lastUpdate = "Няма данни";
|
|
}
|
|
//serialize dates in publisher.assignments and publisher.availabilities
|
|
publisher.assignments.forEach(assignment => {
|
|
if (assignment.shift && assignment.shift.startTime) {
|
|
assignment.shift.startTime = assignment.shift.startTime.toISOString();
|
|
assignment.shift.endTime = assignment.shift.endTime.toISOString();
|
|
}
|
|
});
|
|
publisher.availabilities.forEach(availability => {
|
|
if (availability.startTime) {
|
|
availability.startTime = availability.startTime.toISOString();
|
|
availability.endTime = availability.endTime.toISOString();
|
|
if (availability.dateOfEntry) {
|
|
availability.dateOfEntry = availability.dateOfEntry.toISOString();
|
|
}
|
|
}
|
|
});
|
|
publisher.lastLogin = publisher.lastLogin ? publisher.lastLogin.toISOString() : null;
|
|
//remove availabilities that isFromPreviousAssignment
|
|
publisher.availabilities = publisher.availabilities.filter(availability => !availability.isFromPreviousAssignment);
|
|
|
|
|
|
});
|
|
//remove publishers without availabilities
|
|
publishers = publishers.filter(publisher => publisher.availabilities.length > 0);
|
|
|
|
let allPublishers = await prisma.publisher.findMany({
|
|
select: {
|
|
id: true,
|
|
firstName: true,
|
|
lastName: true,
|
|
email: true,
|
|
phone: true,
|
|
isActive: true,
|
|
desiredShiftsPerMonth: true,
|
|
lastLogin: true,
|
|
type: true,
|
|
assignments: {
|
|
select: {
|
|
id: true,
|
|
shift: {
|
|
select: {
|
|
startTime: true,
|
|
endTime: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
availabilities: {
|
|
select: {
|
|
startTime: true,
|
|
endTime: true,
|
|
dateOfEntry: true,
|
|
isFromPreviousAssignment: true,
|
|
},
|
|
// where: {
|
|
// startTime: {
|
|
// gte: new Date(monthInfo.firstMonday),
|
|
// },
|
|
// },
|
|
|
|
},
|
|
},
|
|
});
|
|
|
|
|
|
let prevMnt = new Date();
|
|
prevMnt.setMonth(prevMnt.getMonth() - 1);
|
|
let prevMonthInfo = common.getMonthDatesInfo(prevMnt);
|
|
|
|
|
|
allPublishers.forEach(publisher => {
|
|
// Use helper functions to calculate and assign assignment counts
|
|
publisher.currentMonthAssignments = countAssignments(publisher.assignments, monthInfo.firstMonday, monthInfo.lastSunday);
|
|
publisher.previousMonthAssignments = countAssignments(publisher.assignments, prevMonthInfo.firstMonday, prevMonthInfo.lastSunday);
|
|
|
|
publisher.lastLogin = publisher.lastLogin ? publisher.lastLogin.toISOString() : null;
|
|
// Convert date formats within the same iteration
|
|
convertShiftDates(publisher.assignments);
|
|
convertAvailabilityDates(publisher.availabilities);
|
|
// common.convertDatesToISOStrings(publisher.availabilities); //ToDo fix the function to work with this sctucture and use it
|
|
});
|
|
|
|
|
|
//merge allPublishers with publishers
|
|
allPublishers = allPublishers.map(pub => {
|
|
const found = publishers.find(publisher => publisher.id === pub.id);
|
|
if (found) {
|
|
return { ...pub, ...found };
|
|
}
|
|
return pub;
|
|
});
|
|
|
|
return allPublishers;
|
|
}
|
|
|
|
|
|
// Helper functions ToDo: move them to common and replace all implementations with the common ones
|
|
function countAssignments(assignments, startTime, endTime) {
|
|
return assignments.filter(assignment =>
|
|
assignment.shift.startTime >= startTime && assignment.shift.startTime <= endTime
|
|
).length;
|
|
}
|
|
function convertAvailabilityDates(availabilities) {
|
|
availabilities.forEach(av => {
|
|
av.startTime = new Date(av.startTime).toISOString();
|
|
av.endTime = new Date(av.endTime).toISOString();
|
|
av.dateOfEntry = new Date(av.dateOfEntry).toISOString()
|
|
});
|
|
}
|
|
function convertShiftDates(assignments) {
|
|
assignments.forEach(assignment => {
|
|
if (assignment.shift && assignment.shift.startTime) {
|
|
assignment.shift.startTime = new Date(assignment.shift.startTime).toISOString();
|
|
assignment.shift.endTime = new Date(assignment.shift.endTime).toISOString();
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
async function getCalendarEvents(publisherId, availabilities = true, assignments = true, includeUnpublished = false) {
|
|
const result = [];
|
|
// let pubs = await filterPublishers("id,firstName,lastName,email".split(","), "", date, assignments, availabilities, date ? true : false, publisherId);
|
|
|
|
const prisma = common.getPrismaClient();
|
|
let publisher = await prisma.publisher.findUnique({
|
|
where: {
|
|
id: publisherId
|
|
},
|
|
select: {
|
|
id: true,
|
|
firstName: true,
|
|
lastName: true,
|
|
email: true,
|
|
availabilities: {
|
|
select: {
|
|
id: true,
|
|
dayOfMonth: true,
|
|
dayofweek: true,
|
|
weekOfMonth: true,
|
|
startTime: true,
|
|
endTime: true,
|
|
name: true,
|
|
isFromPreviousAssignment: true,
|
|
isFromPreviousMonth: true,
|
|
repeatWeekly: true,
|
|
isWithTransportIn: true,
|
|
isWithTransportOut: true,
|
|
}
|
|
},
|
|
assignments: {
|
|
select: {
|
|
id: true,
|
|
// publisherId: true,
|
|
shift: {
|
|
select: {
|
|
id: true,
|
|
startTime: true,
|
|
endTime: true,
|
|
isPublished: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
if (publisher) {
|
|
if (availabilities) {
|
|
publisher.availabilities?.forEach(item => {
|
|
result.push({
|
|
...item,
|
|
title: common.getTimeFormatted(new Date(item.startTime)) + "-" + common.getTimeFormatted(new Date(item.endTime)), //item.name,
|
|
date: new Date(item.startTime),
|
|
startTime: new Date(item.startTime),
|
|
endTime: new Date(item.endTime),
|
|
publisherId: publisher.id,
|
|
type: "availability",
|
|
isFromPreviousAssignment: item.isFromPreviousAssignment,
|
|
isWithTransportIn: item.isWithTransportIn,
|
|
isWithTransportOut: item.isWithTransportOut,
|
|
});
|
|
});
|
|
}
|
|
if (assignments) {
|
|
//only published shifts
|
|
|
|
publisher.assignments?.filter(
|
|
assignment => assignment.shift.isPublished || includeUnpublished
|
|
).forEach(item => {
|
|
result.push({
|
|
...item,
|
|
title: common.getTimeFormatted(new Date(item.shift.startTime)) + "-" + common.getTimeFormatted(new Date(item.shift.endTime)),
|
|
date: new Date(item.shift.startTime),
|
|
startTime: new Date(item.shift.startTime),
|
|
endTime: new Date(item.shift.endTime),
|
|
// publisherId: item.publisherId,
|
|
publisherId: publisher.id,
|
|
type: "assignment",
|
|
});
|
|
});
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// exports.getCoverMePublisherEmails = async function (shiftId) {
|
|
async function getCoverMePublisherEmails(shiftId) {
|
|
const prisma = common.getPrismaClient();
|
|
let subscribedPublishers = await prisma.publisher.findMany({
|
|
where: {
|
|
isSubscribedToCoverMe: true
|
|
},
|
|
select: {
|
|
id: true,
|
|
firstName: true,
|
|
lastName: true,
|
|
email: true
|
|
}
|
|
}).then(pubs => {
|
|
return pubs.map(pub => {
|
|
return {
|
|
id: pub.id,
|
|
firstName: pub.firstName,
|
|
lastName: pub.lastName,
|
|
name: pub.firstName + " " + pub.lastName,
|
|
email: pub.email
|
|
}
|
|
});
|
|
});
|
|
|
|
let shift = await prisma.shift.findUnique({
|
|
where: {
|
|
id: shiftId
|
|
},
|
|
include: {
|
|
assignments: {
|
|
include: {
|
|
publisher: {
|
|
select: {
|
|
id: true,
|
|
firstName: true,
|
|
lastName: true,
|
|
email: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
let availableIn = new Date(shift.startTime)
|
|
let availablePublishers = await filterPublishersNew("id,firstName,lastName,email", availableIn,
|
|
true, false, false, false, false);
|
|
|
|
//filter out publishers that are already assigned to the shift
|
|
availablePublishers = availablePublishers.filter(pub => {
|
|
return shift.assignments.findIndex(assignment => assignment.publisher.id == pub.id) == -1;
|
|
});
|
|
//subscribed list includes only publishers that are not already assigned to the shift
|
|
subscribedPublishers = subscribedPublishers.filter(pub => {
|
|
return availablePublishers.findIndex(availablePub => availablePub.id == pub.id) == -1
|
|
&& shift.assignments.findIndex(assignment => assignment.publisher.id == pub.id) == -1;
|
|
});
|
|
//return names and email info only
|
|
|
|
availablePublishers = availablePublishers.map(pub => {
|
|
return {
|
|
id: pub.id,
|
|
firstName: pub.firstName,
|
|
lastName: pub.lastName,
|
|
name: pub.firstName + " " + pub.lastName,
|
|
email: pub.email
|
|
}
|
|
});
|
|
return { shift, availablePublishers: availablePublishers, subscribedPublishers };
|
|
}
|
|
|
|
// function matchesAvailability(avail, filterDate) {
|
|
// // Setting the start and end time of the filterDate
|
|
// filterDate.setHours(0, 0, 0, 0);
|
|
// const filterDateEnd = new Date(filterDate);
|
|
// filterDateEnd.setHours(23, 59, 59, 999);
|
|
|
|
// // Return true if avail.startTime is between filterDate and filterDateEnd
|
|
// return avail.startTime >= filterDate && avail.startTime <= filterDateEnd;
|
|
// }
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
async function runSqlFile(filePath) {
|
|
|
|
const prisma = common.getPrismaClient();
|
|
// Seed the database with some sample data
|
|
try {
|
|
// Read the SQL file
|
|
const sql = fs.readFileSync(filePath, { encoding: 'utf-8' });
|
|
|
|
// Split the file content by semicolon and filter out empty statements
|
|
const statements = sql.split(';').map(s => s.trim()).filter(s => s.length);
|
|
|
|
// Execute each statement
|
|
for (const statement of statements) {
|
|
await prisma.$executeRawUnsafe(statement);
|
|
}
|
|
console.log('SQL script executed successfully.');
|
|
} catch (error) {
|
|
console.error('Error executing SQL script:', error);
|
|
}
|
|
|
|
}
|
|
|
|
module.exports = {
|
|
findPublisher,
|
|
findPublisherAvailability,
|
|
runSqlFile,
|
|
getAvailabilities,
|
|
filterPublishersNew,
|
|
getCoverMePublisherEmails,
|
|
getAllPublishersWithStatistics,
|
|
getCalendarEvents
|
|
}; |