Fixed monthly quota class for flexible week start days.
authorNik Okuntseff <support@anuko.com>
Sat, 23 Jul 2016 17:57:52 +0000 (17:57 +0000)
committerNik Okuntseff <support@anuko.com>
Sat, 23 Jul 2016 17:57:52 +0000 (17:57 +0000)
WEB-INF/lib/form/Calendar.class.php
WEB-INF/lib/ttTimeHelper.class.php
WEB-INF/templates/footer.tpl
plugins/MonthlyQuota.class.php

index b2cdf33..dd6e83a 100644 (file)
@@ -166,7 +166,7 @@ class Calendar extends FormElement {
             $stl_cell = "";
             $stl_link = "";
 
-            // weeekend
+            // weekend
             if ($j==$weekend_start || $j==$weekend_end) {
               $stl_cell = ' class="CalendarDayWeekend"';
               $stl_link = ' class="CalendarLinkWeekend"';
index e574dc8..87b5aea 100644 (file)
@@ -31,6 +31,24 @@ import('DateAndTime');
 // The ttTimeHelper is a class to help with time-related values.
 class ttTimeHelper {
 
+  // isWeekend determines if $date falls on weekend.
+  static function isWeekend($date) {
+    $weekDay = date('w', strtotime($date));
+    return ($weekDay == WEEKEND_START_DAY || $weekDay == (WEEKEND_START_DAY + 1) % 7);
+  }
+
+  // isHoliday determines if $date falls on a holiday.
+  static function isHoliday($date) {
+    global $i18n;
+    // $date is expected as string in DB_DATEFORMAT.
+    $month = date('m', strtotime($date));
+    $day = date('d', strtotime($date));
+    if (in_array($month.'/'.$day, $i18n->holidays))
+      return true;
+
+    return false;
+  }
+
   // isValidTime validates a value as a time string.
   static function isValidTime($value) {
     if (strlen($value)==0 || !isset($value)) return false;
index 5ee0980..a364819 100644 (file)
@@ -12,7 +12,7 @@
       <br>
       <table cellspacing="0" cellpadding="4" width="100%" border="0">
         <tr>
-          <td align="center">&nbsp;Anuko Time Tracker 1.9.27.3518 | Copyright &copy; <a href="https://www.anuko.com/lp/tt_3.htm" target="_blank">Anuko</a> |
+          <td align="center">&nbsp;Anuko Time Tracker 1.9.28.3519 | Copyright &copy; <a href="https://www.anuko.com/lp/tt_3.htm" target="_blank">Anuko</a> |
             <a href="https://www.anuko.com/lp/tt_4.htm" target="_blank">{$i18n.footer.credits}</a> |
             <a href="https://www.anuko.com/lp/tt_5.htm" target="_blank">{$i18n.footer.license}</a> |
             <a href="https://www.anuko.com/lp/tt_7.htm" target="_blank">{$i18n.footer.improve}</a>
index 3516fe4..06b2092 100644 (file)
@@ -89,15 +89,8 @@ class MonthlyQuota {
           return $row['quota'];
         
         // If we did not find a record, return a calculated monthly quota.
-        $holidaysWithYear = array();
-        foreach ($this->holidays as $day) {
-            $parts = explode("/", $day);
-            $holiday = "$year-$parts[0]-$parts[1]";
-            array_push($holidaysWithYear, $holiday);
-        }
-    
-        $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
-        return $this->getWorkingDays("$year-$month-01", "$year-$month-$daysInMonth", $holidaysWithYear) * $this->getWorkdayHours();
+        $numWorkdays = $this->getNumWorkdays($month, $year);
+        return $numWorkdays * $this->getWorkdayHours();
     }
 
     // getMany - returns an array of quotas for a given year for team.
@@ -117,74 +110,19 @@ class MonthlyQuota {
         return $result;
     }
     
-    // The function returns the number of business days between two dates skipping holidays.
-    private function getWorkingDays($startDate, $endDate, $holidays) {
-        // TODO: this function needs a fix, as it assumes Sat + Sun weekends, 
-        // and will not work properly for other week types (ex. Arabic weeks).
-
-        // do strtotime calculations just once
-        $endDate = strtotime($endDate);
-        $startDate = strtotime($startDate);
-
-        //The total number of days between the two dates. We compute the no. of seconds and divide it to 60*60*24
-        //We add one to inlude both dates in the interval.
-        $days = ($endDate - $startDate) / 86400 + 1;
+    // getNumWorkdays returns a number of work days in a given month.
+    private function getNumWorkdays($month, $year) {
 
-        $noOfFullWeeks = floor($days / 7);
-        $noOfRemainingDays = fmod($days, 7);
+      $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year); // Number of calendar days in month.
 
-        //It will return 1 if it's Monday,.. ,7 for Sunday
-        $firstDayofWeek = date("N", $startDate);
-        $lastDayofWeek = date("N", $endDate);
-
-        //---->The two can be equal in leap years when february has 29 days, the equal sign is added here
-        //In the first case the whole interval is within a week, in the second case the interval falls in two weeks.
-        if ($firstDayofWeek <= $lastDayofWeek) {
-            if ($firstDayofWeek <= 6 && 6 <= $lastDayofWeek) {
-                $noOfRemainingDays--;                
-            }
-            
-            if ($firstDayofWeek <= 7 && 7 <= $lastDayofWeek) {
-                $noOfRemainingDays--;
-            }
+      $workdaysInMonth = 0;
+      // Iterate through all.
+      for ($i = 1; $i <= $daysInMonth; $i++) {
+        $date = "$year-$month-$i";
+        if (!ttTimeHelper::isWeekend($date) && !ttTimeHelper::isHoliday($date)) {
+          $workdaysInMonth++;
         }
-        else {
-            // (edit by Tokes to fix an edge case where the start day was a Sunday
-            // and the end day was NOT a Saturday)
-
-            // the day of the week for start is later than the day of the week for end
-            if ($firstDayofWeek == 7) {
-                // if the start date is a Sunday, then we definitely subtract 1 day
-                $noOfRemainingDays--;
-
-                if ($lastDayofWeek == 6) {
-                    // if the end date is a Saturday, then we subtract another day
-                    $noOfRemainingDays--;
-                }
-            }
-            else {
-                // the start date was a Saturday (or earlier), and the end date was (Mon..Fri)
-                // so we skip an entire weekend and subtract 2 days
-                $noOfRemainingDays -= 2;
-            }
-        }
-
-        //T he no. of business days is: (number of weeks between the two dates) * (5 working days) + the remainder
-        // ---->february in none leap years gave a remainder of 0 but still calculated weekends between first and last day, this is one way to fix it
-        $workingDays = $noOfFullWeeks * 5;
-        if ($noOfRemainingDays > 0 ) {
-            $workingDays += $noOfRemainingDays;
-        }
-
-        // We subtract the holidays
-        foreach($holidays as $holiday){
-            $timeStamp = strtotime($holiday);
-            // If the holiday doesn't fall in weekend
-            // TODO: add handling for countries where they move non working day to first working day if holiday is on weekends
-            if ($startDate <= $timeStamp && $timeStamp <= $endDate && date("N", $timeStamp) != 6 && date("N", $timeStamp ) != 7)
-                $workingDays--;
-        }
-
-        return $workingDays;
+      }
+      return $workdaysInMonth;
     }
 }