fix statistics;

rewrite availability filters;
fix availability filters;
ProtectedRoute.IsInRole helper
This commit is contained in:
Dobromir Popov
2024-04-27 15:31:28 +03:00
parent 029a9af390
commit 58ac046ee5
12 changed files with 267 additions and 138 deletions

View File

@ -226,7 +226,7 @@ in schedule admin - if a publisher is always pair & family is not in the shift -
last login. pubs. last login. pubs.
otchet - za denq otchet - za denq
делете цонфирм OK - делете цонфирм
статистика - фкс (янка) + posledno vlizane статистика - фкс (янка) + posledno vlizane
заместник, предпочитание в миналото - да не може. заместник, предпочитание в миналото - да не може.

View File

@ -2,6 +2,8 @@ import React, { useState, useEffect } from 'react';
import { Calendar, momentLocalizer, dateFnsLocalizer } from 'react-big-calendar'; import { Calendar, momentLocalizer, dateFnsLocalizer } from 'react-big-calendar';
import 'react-big-calendar/lib/css/react-big-calendar.css'; import 'react-big-calendar/lib/css/react-big-calendar.css';
import AvailabilityForm from '../availability/AvailabilityForm'; import AvailabilityForm from '../availability/AvailabilityForm';
import ProtectedRoute from '../protectedRoute';
import { UserRole } from "@prisma/client";
import common from '../../src/helpers/common'; import common from '../../src/helpers/common';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
@ -16,6 +18,7 @@ import { MdToday } from 'react-icons/md';
import { useSwipeable } from 'react-swipeable'; import { useSwipeable } from 'react-swipeable';
import axiosInstance from '../../src/axiosSecure'; import axiosInstance from '../../src/axiosSecure';
// import { set, format, addDays } from 'date-fns'; // import { set, format, addDays } from 'date-fns';
// import { isEqual, isSameDay, getHours, getMinutes } from 'date-fns'; // import { isEqual, isSameDay, getHours, getMinutes } from 'date-fns';
import { filter } from 'jszip'; import { filter } from 'jszip';
@ -45,6 +48,8 @@ const messages = {
const AvCalendar = ({ publisherId, events, selectedDate }) => { const AvCalendar = ({ publisherId, events, selectedDate }) => {
const isAdmin = ProtectedRoute.IsInRole(UserRole.ADMIN);
const [date, setDate] = useState(new Date()); const [date, setDate] = useState(new Date());
//ToDo: see if we can optimize this //ToDo: see if we can optimize this
const [evts, setEvents] = useState(events); // Existing events const [evts, setEvents] = useState(events); // Existing events
@ -211,8 +216,9 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
if (!start || !end) return; if (!start || !end) return;
//readonly for past dates (ToDo: if not admin) //readonly for past dates (ToDo: if not admin)
if (startdate < new Date() || end < new Date() || startdate > end) return; if (!isAdmin) {
if (startdate < new Date() || end < new Date() || startdate > end) return;
}
// Check if start and end are on the same day // Check if start and end are on the same day
if (startdate.toDateString() !== enddate.toDateString()) { if (startdate.toDateString() !== enddate.toDateString()) {
end = common.setTimeHHmm(startdate, "23:59"); end = common.setTimeHHmm(startdate, "23:59");

View File

@ -68,3 +68,8 @@ export async function serverSideAuth({ req, allowedRoles }) {
// Return the session if the user is authenticated and has the required role // Return the session if the user is authenticated and has the required role
return { session }; return { session };
} }
// Static method to check if the user has a specific role
ProtectedRoute.IsInRole = async (roleName) => {
const session = await getSession();
return session && session.user && session.user.role === roleName;
};

View File

@ -114,7 +114,7 @@ function ConfirmationModal({ isOpen, onClose, onConfirm, subscribedPublishers, a
checked={selectedGroups.includes('availablePublishers')} checked={selectedGroups.includes('availablePublishers')}
onChange={() => handleToggleGroup('availablePublishers')} onChange={() => handleToggleGroup('availablePublishers')}
/> />
<span className="text-sm font-medium">На разположение:</span> <span className="text-sm font-medium">На разположение :</span>
</div> </div>
<div className="flex flex-wrap"> <div className="flex flex-wrap">
{availablePublishers.map(pub => ( {availablePublishers.map(pub => (

View File

@ -272,7 +272,8 @@ export default async function handler(req, res) {
if (toAvailable) { if (toAvailable) {
availablePublishers = await data.filterPublishersNew("id,firstName,lastName,email", new Date(assignment.shift.startTime), true, false); availablePublishers = await data.filterPublishersNew("id,firstName,lastName,email", new Date(assignment.shift.startTime),
true, false);
} }
//concat and remove duplicate emails //concat and remove duplicate emails

View File

@ -4,6 +4,7 @@ import { DayOfWeek, AvailabilityType } from '@prisma/client';
const common = require('../../src/helpers/common'); const common = require('../../src/helpers/common');
const data = require('../../src/helpers/data'); const data = require('../../src/helpers/data');
const subq = require('../../prisma/bl/subqueries'); const subq = require('../../prisma/bl/subqueries');
import { addMinutes } from 'date-fns';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
@ -350,7 +351,7 @@ export default async function handler(req, res) {
break; break;
case "getPossibleShiftPublisherEmails": case "getPossibleShiftPublisherEmails":
const subscribedPublishers = await prisma.publisher.findMany({ let subscribedPublishers = await prisma.publisher.findMany({
where: { where: {
isSubscribedToCoverMe: true isSubscribedToCoverMe: true
}, },
@ -373,10 +374,37 @@ export default async function handler(req, res) {
let shift = await prisma.shift.findUnique({ let shift = await prisma.shift.findUnique({
where: { where: {
id: parseInt(req.query.shiftId) id: parseInt(req.query.shiftId)
},
include: {
assignments: {
include: {
publisher: {
select: {
id: true,
firstName: true,
lastName: true,
email: true
}
}
}
}
} }
}); });
let availablePublishers = await filterPublishersNew_Available("id,firstName,lastName,email", new Date(shift.startTime), true, false); let availableIn = new Date(addMinutes(shift.startTime, 0))
let availablePublishers = await filterPublishersNew_Available("id,firstName,lastName,email", availableIn,
true, 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 //return names and email info only
availablePublishers = availablePublishers.map(pub => { availablePublishers = availablePublishers.map(pub => {
return { return {
id: pub.id, id: pub.id,

View File

@ -603,7 +603,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
message="Това ще изпрати имейли до всички участници за смените им през избрания месец. Сигурни ли сте?" message="Това ще изпрати имейли до всички участници за смените им през избрания месец. Сигурни ли сте?"
/> />
<button <button
className={`button btn m-2 ${isPublished ? 'hover:bg-gray-100 bg-yellow-500' : 'hover:bg-red-300 bg-blue-400'}`} className={`button btn m-2 ${isPublished ? 'hover:bg-gray-500 bg-yellow-500' : 'hover:bg-red-300 bg-blue-400'}`}
onClick={togglePublished}> onClick={togglePublished}>
<i className={`fas ${isPublished ? 'fa-check' : 'fa-close'} mr-2`}></i> <i className={`fas ${isPublished ? 'fa-check' : 'fa-close'} mr-2`}></i>
{isPublished ? "Скрий" : "Публикувай"} графика (м.) {isPublished ? "Скрий" : "Публикувай"} графика (м.)

View File

@ -3,6 +3,8 @@ import NewPubPage from "../new";
export default NewPubPage; export default NewPubPage;
import { Assignment, Shift, UserRole, AvailabilityType } from "prisma/prisma-client"; import { Assignment, Shift, UserRole, AvailabilityType } from "prisma/prisma-client";
//import ProtectedRoute from '../../../../components/protectedRoute';
// import { monthNamesBG } from "~/src/helpers/const" // import { monthNamesBG } from "~/src/helpers/const"
import { monthNamesBG } from "src/helpers/const"; import { monthNamesBG } from "src/helpers/const";
@ -38,6 +40,7 @@ function getShiftGroups(shifts: [Shift]) {
export const getServerSideProps = async (context) => { export const getServerSideProps = async (context) => {
const axios = await axiosServer(context); const axios = await axiosServer(context);
// const isAdmin = await ProtectedRoute.IsInRole(UserRole.ADMIN); does not work on server side
context.res.setHeader("Cache-Control", "s-maxage=1, stale-while-revalidate"); context.res.setHeader("Cache-Control", "s-maxage=1, stale-while-revalidate");
if (!context.query || !context.query.id) { if (!context.query || !context.query.id) {
return { return {
@ -50,11 +53,9 @@ export const getServerSideProps = async (context) => {
// item.allShifts = item.assignments.map((a: Assignment[]) => a.shift); // item.allShifts = item.assignments.map((a: Assignment[]) => a.shift);
//group shifts by month, remove duplicates // ============================================================
//sort availabilities by start time // don't show past availabilities (if user not admin) ToDo: add admin check
// item.availabilities = item.availabilities // ============================================================
// .sort((a, b) => b.startTime - a.startTime);
item.availabilities = item.availabilities.filter((a) => new Date(a.startTime) >= new Date() || a.type == AvailabilityType.Weekly); item.availabilities = item.availabilities.filter((a) => new Date(a.startTime) >= new Date() || a.type == AvailabilityType.Weekly);
item.assignments = item.assignments item.assignments = item.assignments
.sort((a, b) => b.startTime - a.startTime) .sort((a, b) => b.startTime - a.startTime)

View File

@ -127,7 +127,7 @@ export const getServerSideProps = async (context) => {
const prisma = common.getPrismaClient(); const prisma = common.getPrismaClient();
const dateStr = new Date().toISOString().split('T')[0]; const dateStr = new Date().toISOString().split('T')[0];
let publishers = await data.filterPublishersNew('id,firstName,lastName,email,isActive,desiredShiftsPerMonth,lastLogin', dateStr, false, true, true, true); let publishers = await data.filterPublishersNew('id,firstName,lastName,email,isActive,desiredShiftsPerMonth,lastLogin', dateStr, false, true, true, true, true);
// const axios = await axiosServer(context); // 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`); // const { data: publishers } = await axios.get(`api/?action=filterPublishers&assignments=true&availabilities=true&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth`);

View File

@ -3,9 +3,8 @@ import Layout from "../components/layout"
import AvCalendar from '../components/calendar/avcalendar'; import AvCalendar from '../components/calendar/avcalendar';
import { getSession } from "next-auth/react"; import { getSession } from "next-auth/react";
import common from '../src/helpers/common'; import common from '../src/helpers/common';
import { Availability } from "@prisma/client"; import { Availability, UserRole } from "@prisma/client";
import ProtectedRoute, { serverSideAuth } from "../components/protectedRoute"; import ProtectedRoute, { serverSideAuth } from "../components/protectedRoute";
import { UserRole } from "@prisma/client";
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import axiosInstance from '../src/axiosSecure'; import axiosInstance from '../src/axiosSecure';
@ -56,6 +55,15 @@ export default function IndexPage({ initialItems, initialUserId }: IProps) {
} }
}; };
// EXAMPLE USAGE OF ProtectedRoute
ProtectedRoute.IsInRole(UserRole.ADMIN).then(isAdmin => {
if (isAdmin) {
console.log("User is an admin.");
} else {
console.log("User is not an admin.");
}
});
return ( return (
<Layout> <Layout>
<ProtectedRoute deniedMessage=""> <ProtectedRoute deniedMessage="">

View File

@ -78,7 +78,7 @@ exports.getPrismaClient = function getPrismaClient() {
if (!prisma) { if (!prisma) {
logger.debug("getPrismaClient: process.env.DATABASE = ", process.env.DATABASE); logger.debug("getPrismaClient: process.env.DATABASE = ", process.env.DATABASE);
prisma = new PrismaClient({ prisma = new PrismaClient({
// Optional: Enable logging // Optional: Enable Prisma logging
//log: ['query', 'info', 'warn', 'error'], //log: ['query', 'info', 'warn', 'error'],
datasources: { db: { url: process.env.DATABASE } }, datasources: { db: { url: process.env.DATABASE } },
}); });
@ -757,6 +757,11 @@ exports.getInitials = function (names) {
const parts = names.split(' '); const parts = names.split(' ');
return parts.map(part => part[0] + ".").join(''); return parts.map(part => part[0] + ".").join('');
} }
// ? import { addMinutes } from 'date-fns';
exports.addMinutes = function (date, minutes) {
return new Date(date.getTime() + minutes * 60000); // 60000 milliseconds in a minute
}
// exports.getInitials = function (names) { // exports.getInitials = function (names) {
// const parts = names.split(' '); // Split the full name into parts // const parts = names.split(' '); // Split the full name into parts
// if (parts.length === 0) { // if (parts.length === 0) {

View File

@ -260,110 +260,174 @@ async function filterPublishersNew(selectFields, filterDate, isExactTime = false
} }
}; };
var monthInfo = common.getMonthDatesInfo(filterDate); let filterTimeFrom = new Date(filterDate)
var weekNr = common.getWeekOfMonth(filterDate); //getWeekNumber let filterTimeTo = new Date(filterDate);
let dayOfWeekEnum = common.getDayOfWeekNameEnEnumForDate(filterDate); let isDayFilter = true;
if (!isExactTime) {
filterDate.setHours(0, 0, 0, 0); // Set to midnight
}
const filterDateEnd = new Date(filterDate);
filterDateEnd.setHours(23, 59, 59, 999);
let whereClause = {}; let whereClause = {};
//if full day, match by date only //if full day, match by date only
if (!isExactTime) { // Check only by date without considering time ( Assignments on specific days without time) // if (!isExactTime) { // Check only by date without considering time ( Assignments on specific days without time)
whereClause["availabilities"] = { // whereClause["availabilities"] = {
some: { // some: {
OR: [ // OR: [
{ // {
startTime: { gte: filterDate }, // dayOfMonth: { not: null },
endTime: { lte: filterDateEnd }, // startTime: { gte: filterDate },
} // // endTime: { lte: filterDateEnd },
, // }
// Check if dayOfMonth is null and match by day of week using the enum (Assigments every week) // ,
// This includes availabilities from previous assignments but not with preference // // Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
{ // // This includes availabilities from previous assignments but not with preference
dayOfMonth: null, // includes monthly and weekly repeats // {
dayofweek: dayOfWeekEnum, // dayOfMonth: null, // includes monthly and weekly repeats
// ToDo: and weekOfMonth // dayofweek: dayOfWeekEnum,
startTime: { lte: filterDate }, // // ToDo: and weekOfMonth
AND: [ // startTime: { lte: filterDate },
{ // AND: [
OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever // {
{ endDate: { gte: filterDate } }, // OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
{ endDate: null } // { endDate: { gte: filterDate } },
] // { endDate: null }
} // ]
] // }
} // ]
] // }
} // ]
}; // }
} // };
//if not full day, match by date and time // }
else { // //if not full day, match by date and time
//match exact time (should be same as data.findPublisherAvailability()) // else {
whereClause["availabilities"] = { // //match exact time (should be same as data.findPublisherAvailability())
some: { // whereClause["availabilities"] = {
OR: [ // some: {
// Check if dayOfMonth is set and filterDate is between start and end dates (Assignments on specific days AND time) // OR: [
{ // // Check if dayOfMonth is set and filterDate is between start and end dates (Assignments on specific days AND time)
// dayOfMonth: filterDate.getDate(), // {
startTime: { lte: filterDate }, // // dayOfMonth: filterDate.getDate(),
endTime: { gte: filterDate } // startTime: { gte: filterDate },
}, // // endTime: { lte: filterDate }
// Check if dayOfMonth is null and match by day of week using the enum (Assigments every week) // },
{ // // Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
dayOfMonth: null, // {
dayofweek: dayOfWeekEnum, // dayOfMonth: null,
startTime: { gte: filterDate }, // dayofweek: dayOfWeekEnum,
AND: [ // startTime: { gte: filterDate },
{ // AND: [
OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever // {
{ endDate: { gte: filterDate } }, // OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
{ endDate: null } // { endDate: { gte: filterDate } },
] // { endDate: null }
} // ]
] // }
} // ]
] // }
} // ]
}; // }
} // };
// }
// if (isForTheMonth) {
// // If no filter date, return all publishers's availabilities for currentMonthStart
// 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: monthInfo.firstMonday },
// // endTime: { lte: monthInfo.lastSunday }
// },
// // Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
// {
// dayOfMonth: null,
// AND: [
// {
// OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
// { endDate: { gte: filterDate } },
// { endDate: null }
// ]
// }
// ]
// }
// ]
// }
// };
// }
var monthInfo = common.getMonthDatesInfo(filterDate);
if (isForTheMonth) { if (isForTheMonth) {
// If no filter date, return all publishers's availabilities for currentMonthStart var weekNr = common.getWeekOfMonth(filterDate); //getWeekNumber
whereClause["availabilities"] = { filterTimeFrom = monthInfo.firstMonday;
some: { filterTimeTo = monthInfo.lastSunday;
OR: [ isDayFilter = false;
// Check if dayOfMonth is not null and startTime is after monthInfo.firstMonday (Assignments on specific days AND time) }
{ if (isExactTime) {
dayOfMonth: { not: null }, //add +- 90 minutes to the filterDate ToDo: should be "shift duration"
startTime: { gte: monthInfo.firstMonday }, // filterTimeFrom.setMinutes(filterTimeFrom.getMinutes() - 90);
// endTime: { lte: monthInfo.lastSunday } filterTimeTo.setMinutes(filterTimeTo.getMinutes() + 90);
}, }
// Check if dayOfMonth is null and match by day of week using the enum (Assigments every week) else {
{ filterTimeFrom.setHours(0, 0, 0, 0);
dayOfMonth: null, filterTimeTo.setHours(23, 59, 59, 999);
AND: [ }
{
OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever whereClause["availabilities"] = {
{ endDate: { gte: filterDate } }, some: {
{ endDate: null } 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,
AND: [
{
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 {
} }
};
if (!noEndDateFilter) { // Check if we need to apply the endTime filter
whereClause["availabilities"].some.OR[0].endTime = { lte: monthInfo.lastSunday };
} }
} }
console.log(`getting publishers for date: ${filterDate}, isExactTime: ${isExactTime}, isForTheMonth: ${isForTheMonth}`); console.log(`getting publishers for date: ${filterDate}, isExactTime: ${isExactTime}, isForTheMonth: ${isForTheMonth}`);
//include availabilities if flag is true //include availabilities if flag is true
const prisma = common.getPrismaClient(); //why we need to get it again? const prisma = common.getPrismaClient(); //why we need to get it again?
@ -377,7 +441,7 @@ async function filterPublishersNew(selectFields, filterDate, isExactTime = false
console.log(`publishers: ${publishers.length}, WhereClause: ${JSON.stringify(whereClause)}`); console.log(`publishers: ${publishers.length}, WhereClause: ${JSON.stringify(whereClause)}`);
// convert matching weekly availabilities to availabilities for the day to make furter processing easier on the client. // 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. // we trust that the filtering was OK, so we use the dateFilter as date.
publishers.forEach(pub => { publishers.forEach(pub => {
pub.availabilities = pub.availabilities.map(avail => { pub.availabilities = pub.availabilities.map(avail => {
@ -415,10 +479,11 @@ async function filterPublishersNew(selectFields, filterDate, isExactTime = false
//get if publisher has assignments for current weekday, week, current month, previous month //get if publisher has assignments for current weekday, week, current month, previous month
publishers.forEach(pub => { publishers.forEach(pub => {
// Filter assignments for current day // Filter assignments for current day
pub.currentDayAssignments = pub.assignments?.filter(assignment => { if (isDayFilter) {
return assignment.shift.startTime >= filterDate && assignment.shift.startTime <= filterDateEnd; pub.currentDayAssignments = pub.assignments?.filter(assignment => {
}).length; return assignment.shift.startTime >= filterDate && assignment.shift.startTime <= filterTimeTo;
}).length;
}
// Filter assignments for current week // Filter assignments for current week
pub.currentWeekAssignments = pub.assignments?.filter(assignment => { pub.currentWeekAssignments = pub.assignments?.filter(assignment => {
return assignment.shift.startTime >= currentWeekStart && assignment.shift.startTime <= currentWeekEnd; return assignment.shift.startTime >= currentWeekStart && assignment.shift.startTime <= currentWeekEnd;
@ -426,7 +491,7 @@ async function filterPublishersNew(selectFields, filterDate, isExactTime = false
// Filter assignments for current month // Filter assignments for current month
pub.currentMonthAssignments = pub.assignments?.filter(assignment => { pub.currentMonthAssignments = pub.assignments?.filter(assignment => {
return assignment.shift.startTime >= currentMonthStart && assignment.shift.startTime <= currentMonthEnd; return assignment.shift.startTime >= currentMonthStart && (noEndDateFilter || assignment.shift.startTime <= currentMonthEnd);
}).length; }).length;
// Filter assignments for previous month // Filter assignments for previous month
@ -437,7 +502,7 @@ async function filterPublishersNew(selectFields, filterDate, isExactTime = false
} }
//get the availabilities for the day. Calcullate: //get the availabilities for the day. Calculate:
//1. how many days the publisher is available for the current month - only with dayOfMonth //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) //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 //3. how many hours in total the publisher is available for the current month
@ -445,7 +510,7 @@ async function filterPublishersNew(selectFields, filterDate, isExactTime = false
if (isWithStats) { if (isWithStats) {
pub.currentMonthAvailability = pub.availabilities?.filter(avail => { pub.currentMonthAvailability = pub.availabilities?.filter(avail => {
// return avail.dayOfMonth != null && avail.startTime >= currentMonthStart && avail.startTime <= currentMonthEnd; // return avail.dayOfMonth != null && avail.startTime >= currentMonthStart && avail.startTime <= currentMonthEnd;
return avail.startTime >= currentMonthStart && avail.startTime <= currentMonthEnd; return avail.startTime >= currentMonthStart && (noEndDateFilter || avail.startTime <= currentMonthEnd);
}) })
pub.currentMonthAvailabilityDaysCount = pub.currentMonthAvailability.length || 0; pub.currentMonthAvailabilityDaysCount = pub.currentMonthAvailability.length || 0;
// pub.currentMonthAvailabilityDaysCount += pub.availabilities.filter(avail => { // pub.currentMonthAvailabilityDaysCount += pub.availabilities.filter(avail => {
@ -465,37 +530,47 @@ async function filterPublishersNew(selectFields, filterDate, isExactTime = false
pub.hasEverFilledForm = pub.availabilities?.some(avail => { pub.hasEverFilledForm = pub.availabilities?.some(avail => {
return avail.isFromPreviousAssignments == false; return avail.isFromPreviousAssignments == false;
}); });
if (isDayFilter) {
//if pub has availabilities for the current day //if pub has availabilities for the current day
pub.hasAvailabilityForCurrentDay = pub.availabilities?.some(avail => { pub.hasAvailabilityForCurrentDay = pub.availabilities?.some(avail => {
return avail.startTime >= filterDate && avail.startTime <= filterDateEnd; return avail.startTime >= filterDate && avail.startTime <= filterTimeTo;
}); });
}
}); });
if (isExactTime) { if (isExactTime) {
// Post filter for time if dayOfMonth is null as we can't only by time for multiple dates in SQL //HERE WE FILTER by time for repeating availabilities. We can't do that if we don't have
// Modify the availabilities array of the filtered publishers // whereClause["availabilities"].some.OR[1].startTime = { gte: filterTimeFrom };
// whereClause["availabilities"].some.OR[1].endTime = { gte: filterTimeTo }
publishers.forEach(pub => { publishers.forEach(pub => {
pub.availabilities = pub.availabilities?.filter(avail => matchesAvailability(avail, filterDate)); 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; return publishers;
} }
function matchesAvailability(avail, filterDate) { // function matchesAvailability(avail, filterDate) {
// Setting the start and end time of the filterDate // // Setting the start and end time of the filterDate
filterDate.setHours(0, 0, 0, 0); // filterDate.setHours(0, 0, 0, 0);
const filterDateEnd = new Date(filterDate); // const filterDateEnd = new Date(filterDate);
filterDateEnd.setHours(23, 59, 59, 999); // filterDateEnd.setHours(23, 59, 59, 999);
// Return true if avail.startTime is between filterDate and filterDateEnd // // Return true if avail.startTime is between filterDate and filterDateEnd
return avail.startTime >= filterDate && avail.startTime <= filterDateEnd; // return avail.startTime >= filterDate && avail.startTime <= filterDateEnd;
} // }
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');