fix: properly handling moving recurring charging profiles
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStationUtils.ts
index 939c7b8e433da90eb7f8b561a021306acb0cabb6..9da406c282d448b8b713dd116658433c4e291994 100644 (file)
@@ -10,13 +10,10 @@ import {
   addWeeks,
   differenceInDays,
   differenceInWeeks,
-  endOfDay,
-  endOfWeek,
   isAfter,
   isBefore,
   isWithinInterval,
-  startOfDay,
-  startOfWeek,
+  toDate,
 } from 'date-fns';
 
 import type { ChargingStation } from './ChargingStation';
@@ -57,10 +54,10 @@ import {
   isNotEmptyString,
   isNullOrUndefined,
   isUndefined,
+  isValidDate,
   logger,
   secureRandom,
 } from '../utils';
-import { isValidDate } from '../utils/Utils';
 
 const moduleName = 'ChargingStationUtils';
 
@@ -690,11 +687,11 @@ const getLimitFromChargingProfiles = (
   const connectorStatus = chargingStation.getConnectorStatus(connectorId);
   for (const chargingProfile of chargingProfiles) {
     if (
-      chargingProfile.validFrom &&
-      chargingProfile.validTo &&
+      isValidDate(chargingProfile.validFrom) &&
+      isValidDate(chargingProfile.validTo) &&
       !isWithinInterval(currentDate, {
-        start: chargingProfile.validFrom,
-        end: chargingProfile.validTo,
+        start: chargingProfile.validFrom!,
+        end: chargingProfile.validTo!,
       })
     ) {
       logger.debug(
@@ -727,50 +724,8 @@ const getLimitFromChargingProfiles = (
       );
       continue;
     }
-    // Adjust recurring start schedule
     if (chargingProfile.chargingProfileKind === ChargingProfileKindType.RECURRING) {
-      switch (chargingProfile.recurrencyKind) {
-        case RecurrencyKindType.DAILY:
-          if (isBefore(chargingSchedule.startSchedule, startOfDay(currentDate))) {
-            addDays(
-              chargingSchedule.startSchedule,
-              differenceInDays(chargingSchedule.startSchedule, endOfDay(currentDate)),
-            );
-            if (
-              isBefore(chargingSchedule.startSchedule, startOfDay(currentDate)) ||
-              isAfter(chargingSchedule.startSchedule, endOfDay(currentDate))
-            ) {
-              logger.error(
-                `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Recurring ${
-                  chargingProfile.recurrencyKind
-                } charging profile id ${
-                  chargingProfile.chargingProfileId
-                } startSchedule ${chargingSchedule.startSchedule.toISOString()} is not properly translated to the current day`,
-              );
-            }
-          }
-          break;
-        case RecurrencyKindType.WEEKLY:
-          if (isBefore(chargingSchedule.startSchedule, startOfWeek(currentDate))) {
-            addWeeks(
-              chargingSchedule.startSchedule,
-              differenceInWeeks(chargingSchedule.startSchedule, endOfWeek(currentDate)),
-            );
-            if (
-              isBefore(chargingSchedule.startSchedule, startOfWeek(currentDate)) ||
-              isAfter(chargingSchedule.startSchedule, endOfWeek(currentDate))
-            ) {
-              logger.error(
-                `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Recurring ${
-                  chargingProfile.recurrencyKind
-                } charging profile id ${
-                  chargingProfile.chargingProfileId
-                } startSchedule ${chargingSchedule.startSchedule.toISOString()} is not properly translated to the current week`,
-              );
-            }
-          }
-          break;
-      }
+      prepareRecurringChargingProfile(chargingProfile, currentDate, logPrefix);
     } else if (
       chargingProfile.chargingProfileKind === ChargingProfileKindType.RELATIVE &&
       connectorStatus?.transactionStarted
@@ -835,6 +790,73 @@ const getLimitFromChargingProfiles = (
   }
 };
 
+/**
+ *  Adjust recurring charging profile startSchedule to the current recurrency time interval if needed
+ *
+ * @param chargingProfile -
+ * @param currentDate -
+ * @param logPrefix -
+ */
+const prepareRecurringChargingProfile = (
+  chargingProfile: ChargingProfile,
+  currentDate: Date,
+  logPrefix: string,
+) => {
+  const chargingSchedule = chargingProfile.chargingSchedule;
+  let recurringInterval: Interval;
+  switch (chargingProfile.recurrencyKind) {
+    case RecurrencyKindType.DAILY:
+      recurringInterval = {
+        start: chargingSchedule.startSchedule!,
+        end: addDays(chargingSchedule.startSchedule!, 1),
+      };
+      if (
+        !isWithinInterval(currentDate, recurringInterval) &&
+        isBefore(chargingSchedule.startSchedule!, currentDate)
+      ) {
+        chargingSchedule.startSchedule = addDays(
+          chargingSchedule.startSchedule!,
+          differenceInDays(chargingSchedule.startSchedule!, recurringInterval.end),
+        );
+        recurringInterval = {
+          start: chargingSchedule.startSchedule,
+          end: addDays(chargingSchedule.startSchedule, 1),
+        };
+      }
+      break;
+    case RecurrencyKindType.WEEKLY:
+      recurringInterval = {
+        start: chargingSchedule.startSchedule!,
+        end: addWeeks(chargingSchedule.startSchedule!, 1),
+      };
+      if (
+        !isWithinInterval(currentDate, recurringInterval) &&
+        isBefore(chargingSchedule.startSchedule!, currentDate)
+      ) {
+        chargingSchedule.startSchedule = addWeeks(
+          chargingSchedule.startSchedule!,
+          differenceInWeeks(chargingSchedule.startSchedule!, recurringInterval.end),
+        );
+        recurringInterval = {
+          start: chargingSchedule.startSchedule,
+          end: addWeeks(chargingSchedule.startSchedule, 1),
+        };
+      }
+      break;
+  }
+  if (!isWithinInterval(currentDate, recurringInterval!)) {
+    logger.error(
+      `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Recurring ${
+        chargingProfile.recurrencyKind
+      } charging profile id ${
+        chargingProfile.chargingProfileId
+      } startSchedule ${chargingSchedule.startSchedule!.toISOString()} is not properly translated to current recurrency time interval [${toDate(
+        recurringInterval!.start,
+      ).toISOString()}, ${toDate(recurringInterval!.end).toISOString()}]`,
+    );
+  }
+};
+
 const getRandomSerialNumberSuffix = (params?: {
   randomBytesLength?: number;
   upperCase?: boolean;