function calcOverTimePolicyTotalTime($udt_meal_policy_adjustment_arr, $udt_break_policy_adjustment_arr) { global $profiler; $profiler->startTimer('UserDateTotal::calcOverTimePolicyTotalTime() - Part 1'); //If this user is scheduled, get schedule overtime policy id. $schedule_total_time = 0; $schedule_over_time_policy_id = 0; $slf = TTnew('ScheduleListFactory'); $slf->getByUserDateIdAndStatusId($this->getUserDateID(), 10); //FIXME: Allow overtime policies to be specified on absence shifts too, like premium policies? if ($slf->getRecordCount() > 0) { //Check for schedule policy foreach ($slf as $s_obj) { Debug::text(' Schedule Total Time: ' . $s_obj->getTotalTime(), __FILE__, __LINE__, __METHOD__, 10); $schedule_total_time += $s_obj->getTotalTime(); if (is_object($s_obj->getSchedulePolicyObject()) and $s_obj->getSchedulePolicyObject()->getOverTimePolicyID() != FALSE) { $schedule_over_time_policy_id = $s_obj->getSchedulePolicyObject()->getOverTimePolicyID(); Debug::text('Found New Schedule Overtime Policies to apply: ' . $schedule_over_time_policy_id, __FILE__, __LINE__, __METHOD__, 10); } } } else { //If they are not scheduled, we use the PolicyGroup list to get a Over Schedule / No Schedule overtime policy. //We could check for an active recurring schedule, but there could be multiple, and which //one do we use? } //Apply policies for OverTime hours $otplf = TTnew('OverTimePolicyListFactory'); $otp_calculation_order = $otplf->getOptions('calculation_order'); $otplf->getByPolicyGroupUserIdOrId($this->getUserDateObject()->getUser(), $schedule_over_time_policy_id); if ($otplf->getRecordCount() > 0) { Debug::text('Found Overtime Policies to apply.', __FILE__, __LINE__, __METHOD__, 10); //Get Pay Period Schedule info if (is_object($this->getUserDateObject()->getPayPeriodObject()) and is_object($this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject())) { $start_week_day_id = $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject()->getStartWeekDay(); } else { $start_week_day_id = 0; } Debug::text('Start Week Day ID: ' . $start_week_day_id, __FILE__, __LINE__, __METHOD__, 10); //Convert all OT policies to daily before applying. //For instance, 40+hrs/week policy if they are currently at 35hrs is a 5hr daily policy. //For weekly OT policies, they MUST include regular time + other WEEKLY over time rules. $udtlf = TTnew('UserDateTotalListFactory'); $weekly_total = $udtlf->getWeekRegularTimeSumByUserIDAndEpochAndStartWeekEpoch($this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp(), TTDate::getBeginWeekEpoch($this->getUserDateObject()->getDateStamp(), $start_week_day_id)); Debug::text('Weekly Total: ' . (int) $weekly_total, __FILE__, __LINE__, __METHOD__, 10); //Daily policy always takes precedence, then Weekly, Bi-Weekly, Day Of Week etc... //So unless the next policy in the list has a lower trigger time then the previous policy //We ignore it. //ie: if Daily OT is after 8hrs, and Day Of Week is after 10. Day of week will be ignored. // If Daily OT is after 8hrs, and Weekly is after 40, and they worked 35 up to yesterday, // and 12 hrs today, from 5hrs to 8hrs will be weekly, then anything after that is daily. //FIXME: Take rate into account, so for example if we have a daily OT policy after 8hrs at 1.5x // and a Holiday OT policy after 0hrs at 2.0x. If the employee works 10hrs on the holiday we want all 10hrs to be Holiday time. // We shouldn't go back to a lesser rate of 1.5x for the Daily OT policy. However if we do this we also need to take into account accrual rates, as time could be banked. // Combine Rate and Accrual rate to use for sorting, as some 2.0x rate overtime policies might accrual/bank it all (Rate: 0 Accrual Rate: 2.0), but it should still be considered a 2.0x rate. // *The work around for this currently is to have multiple holiday policies that match the daily overtime policies so they take priority. $tmp_trigger_time_arr = array(); foreach ($otplf as $otp_obj) { Debug::text(' Checking Against Policy: ' . $otp_obj->getName() . ' Trigger Time: ' . $otp_obj->getTriggerTime(), __FILE__, __LINE__, __METHOD__, 10); $trigger_time = NULL; switch ($otp_obj->getType()) { case 10: //Daily $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); break; case 20: //Weekly $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' Weekly Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); break; case 30: //Bi-Weekly //Convert biweekly into a weekly policy by taking the hours worked in the //first of the two week period and reducing the trigger time by that amount. //When does the bi-weekly cutoff start though? It must have a hard date that it can be based on so we don't count the same week twice. //Try to synchronize it with the week of the first pay period? Just figure out if we are odd or even weeks. //FIXME: Set flag that tells smartRecalculate to calculate the next week or not. $week_modifier = 0; //0=Even, 1=Odd if (is_object($this->getUserDateObject()->getPayPeriodObject())) { $week_modifier = TTDate::getWeek($this->getUserDateObject()->getPayPeriodObject()->getStartDate(), $start_week_day_id) % 2; } $current_week_modifier = TTDate::getWeek($this->getUserDateObject()->getDateStamp(), $start_week_day_id) % 2; Debug::text(' Current Week: ' . $current_week_modifier . ' Week Modifier: ' . $week_modifier, __FILE__, __LINE__, __METHOD__, 10); $first_week_total = 0; if ($current_week_modifier != $week_modifier) { //$udtlf->getWeekRegularTimeSumByUserIDAndEpochAndStartWeekEpoch() uses "< $epoch" so the current day is ignored, but in this //case we want to include the last day of the week, so we need to add one day to this argument. $first_week_total = $udtlf->getWeekRegularTimeSumByUserIDAndEpochAndStartWeekEpoch($this->getUserDateObject()->getUser(), TTDate::getEndWeekEpoch(TTDate::getMiddleDayEpoch($this->getUserDateObject()->getDateStamp()) - 86400 * 7, $start_week_day_id) + 86400, TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($this->getUserDateObject()->getDateStamp()) - 86400 * 7, $start_week_day_id)); Debug::text(' Week modifiers differ, calculate total time for the first week: ' . $first_week_total, __FILE__, __LINE__, __METHOD__, 10); } else { UserDateTotalFactory::setEnableCalcFutureWeek(TRUE); } $trigger_time = $otp_obj->getTriggerTime() - $first_week_total; if ($trigger_time < 0) { $trigger_time = 0; } Debug::text('Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); unset($first_week_total, $week_modifier, $current_week_modifier); break; case 40: //Sunday if (date('w', $this->getUserDateObject()->getDateStamp()) == 0) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' DayOfWeek OT for Sat ... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT DayOfWeek OT for Sat...', __FILE__, __LINE__, __METHOD__, 10); continue; } break; case 50: //Monday if (date('w', $this->getUserDateObject()->getDateStamp()) == 1) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' DayOfWeek OT for Sat ... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT DayOfWeek OT for Sat...', __FILE__, __LINE__, __METHOD__, 10); continue; } break; case 60: //Tuesday if (date('w', $this->getUserDateObject()->getDateStamp()) == 2) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' DayOfWeek OT for Sat ... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT DayOfWeek OT for Sat...', __FILE__, __LINE__, __METHOD__, 10); continue; } break; case 70: //Wed if (date('w', $this->getUserDateObject()->getDateStamp()) == 3) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' DayOfWeek OT for Sat ... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT DayOfWeek OT for Sat...', __FILE__, __LINE__, __METHOD__, 10); continue; } break; case 80: //Thu if (date('w', $this->getUserDateObject()->getDateStamp()) == 4) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' DayOfWeek OT for Sat ... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT DayOfWeek OT for Sat...', __FILE__, __LINE__, __METHOD__, 10); continue; } break; case 90: //Fri if (date('w', $this->getUserDateObject()->getDateStamp()) == 5) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' DayOfWeek OT for Sat ... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT DayOfWeek OT for Sat...', __FILE__, __LINE__, __METHOD__, 10); continue; } break; case 100: //Sat if (date('w', $this->getUserDateObject()->getDateStamp()) == 6) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' DayOfWeek OT for Sat ... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT DayOfWeek OT for Sat...', __FILE__, __LINE__, __METHOD__, 10); continue; } break; case 150: //2-day/week Consecutive //2-day/week Consecutive case 151: //3-day/week Consecutive //3-day/week Consecutive case 152: //4-day/week Consecutive //4-day/week Consecutive case 153: //5-day/week Consecutive //5-day/week Consecutive case 154: //6-day/week Consecutive //6-day/week Consecutive case 155: //7-day/week Consecutive switch ($otp_obj->getType()) { case 150: $minimum_days_worked = 2; break; case 151: $minimum_days_worked = 3; break; case 152: $minimum_days_worked = 4; break; case 153: $minimum_days_worked = 5; break; case 154: $minimum_days_worked = 6; break; case 155: $minimum_days_worked = 7; break; } //Should these be reset on the week boundary or should any consecutive days worked apply? Or should we offer both options? //We should probably break this out to just a general "consecutive days worked" and add a field to specify any number of days //and a field to specify if its only per week, or any timeframe. //Will probably want to include a flag to consider scheduled days only too. $days_worked_arr = (array) $udtlf->getDaysWorkedByUserIDAndStartDateAndEndDate($this->getUserDateObject()->getUser(), TTDate::getBeginWeekEpoch($this->getUserDateObject()->getDateStamp(), $start_week_day_id), $this->getUserDateObject()->getDateStamp()); $weekly_days_worked = count($days_worked_arr); Debug::text(' Weekly Days Worked: ' . $weekly_days_worked . ' Minimum Required: ' . $minimum_days_worked, __FILE__, __LINE__, __METHOD__, 10); if ($weekly_days_worked >= $minimum_days_worked and TTDate::isConsecutiveDays($days_worked_arr) == TRUE) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' After Days Consecutive... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT After Days Consecutive Worked...', __FILE__, __LINE__, __METHOD__, 10); continue; } unset($days_worked_arr, $weekly_days_worked, $minimum_days_worked); break; case 300: //2-day Consecutive //2-day Consecutive case 301: //3-day Consecutive //3-day Consecutive case 302: //4-day Consecutive //4-day Consecutive case 303: //5-day Consecutive //5-day Consecutive case 304: //6-day Consecutive //6-day Consecutive case 305: //7-day Consecutive switch ($otp_obj->getType()) { case 300: $minimum_days_worked = 2; break; case 301: $minimum_days_worked = 3; break; case 302: $minimum_days_worked = 4; break; case 303: $minimum_days_worked = 5; break; case 304: $minimum_days_worked = 6; break; case 305: $minimum_days_worked = 7; break; } //This does not reset on the week boundary. $days_worked_arr = (array) $udtlf->getDaysWorkedByUserIDAndStartDateAndEndDate($this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp() - 86400 * $minimum_days_worked, $this->getUserDateObject()->getDateStamp()); $weekly_days_worked = count($days_worked_arr); Debug::text(' Weekly Days Worked: ' . $weekly_days_worked . ' Minimum Required: ' . $minimum_days_worked, __FILE__, __LINE__, __METHOD__, 10); //Since these can span overtime weeks, we need to calculate the future week as well. UserDateTotalFactory::setEnableCalcFutureWeek(TRUE); if ($weekly_days_worked >= $minimum_days_worked and TTDate::isConsecutiveDays($days_worked_arr) == TRUE) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' After Days Consecutive... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT After Days Consecutive Worked...', __FILE__, __LINE__, __METHOD__, 10); continue; } unset($days_worked_arr, $weekly_days_worked, $minimum_days_worked); break; case 350: //2nd Consecutive Day //2nd Consecutive Day case 351: //3rd Consecutive Day //3rd Consecutive Day case 352: //4th Consecutive Day //4th Consecutive Day case 353: //5th Consecutive Day //5th Consecutive Day case 354: //6th Consecutive Day //6th Consecutive Day case 355: //7th Consecutive Day switch ($otp_obj->getType()) { case 350: $minimum_days_worked = 2; break; case 351: $minimum_days_worked = 3; break; case 352: $minimum_days_worked = 4; break; case 353: $minimum_days_worked = 5; break; case 354: $minimum_days_worked = 6; break; case 355: $minimum_days_worked = 7; break; } $range_start_date = TTDate::getMiddleDayEpoch($this->getUserDateObject()->getDateStamp()) - 86400 * $minimum_days_worked; $previous_day_with_overtime_result = $udtlf->getPreviousDayByUserIdAndStartDateAndEndDateAndOverTimePolicyId($this->getUserDateObject()->getUser(), $range_start_date, $this->getUserDateObject()->getDateStamp(), $otp_obj->getId()); if ($previous_day_with_overtime_result !== FALSE) { $previous_day_with_overtime = TTDate::getMiddleDayEpoch(TTDate::strtotime($previous_day_with_overtime_result)); Debug::text(' Previous Day with OT: ' . TTDate::getDate('DATE', $previous_day_with_overtime) . ' Start Date: ' . TTDate::getDate('DATE', $range_start_date) . ' End Date: ' . TTDate::getDate('DATE', $this->getUserDateObject()->getDateStamp()), __FILE__, __LINE__, __METHOD__, 10); } if (isset($previous_day_with_overtime) and $previous_day_with_overtime >= $range_start_date) { $range_start_date = TTDate::getMiddleDayEpoch($previous_day_with_overtime) + 86400; Debug::text(' bPrevious Day with OT: ' . TTDate::getDate('DATE', $previous_day_with_overtime) . ' Start Date: ' . TTDate::getDate('DATE', $range_start_date) . ' End Date: ' . TTDate::getDate('DATE', $this->getUserDateObject()->getDateStamp()), __FILE__, __LINE__, __METHOD__, 10); } //This does not reset on the week boundary. $days_worked_arr = (array) $udtlf->getDaysWorkedByUserIDAndStartDateAndEndDate($this->getUserDateObject()->getUser(), $range_start_date, $this->getUserDateObject()->getDateStamp()); sort($days_worked_arr); $weekly_days_worked = count($days_worked_arr); Debug::text(' Weekly Days Worked: ' . $weekly_days_worked . ' Minimum Required: ' . $minimum_days_worked, __FILE__, __LINE__, __METHOD__, 10); //Since these can span overtime weeks, we need to calculate the future week as well. UserDateTotalFactory::setEnableCalcFutureWeek(TRUE); $days_worked_arr_key = $minimum_days_worked - 1; if ($weekly_days_worked >= $minimum_days_worked and TTDate::isConsecutiveDays($days_worked_arr) == TRUE and isset($days_worked_arr[$days_worked_arr_key]) and TTDate::getMiddleDayEpoch(TTDate::strtotime($days_worked_arr[$days_worked_arr_key])) == TTDate::getMiddleDayEpoch($this->getUserDateObject()->getDateStamp())) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' After Days Consecutive... Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' NOT After Days Consecutive Worked...', __FILE__, __LINE__, __METHOD__, 10); continue; } unset($range_start_date, $previous_day_with_overtime, $previous_day_with_overtime, $days_worked_arr, $weekly_days_worked, $minimum_days_worked); break; case 180: //Holiday $hlf = TTnew('HolidayListFactory'); $hlf->getByPolicyGroupUserIdAndDate($this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp()); if ($hlf->getRecordCount() > 0) { $holiday_obj = $hlf->getCurrent(); Debug::text(' Found Holiday: ' . $holiday_obj->getName(), __FILE__, __LINE__, __METHOD__, 10); if ($holiday_obj->getHolidayPolicyObject()->getForceOverTimePolicy() == TRUE or $holiday_obj->isEligible($this->getUserDateObject()->getUser())) { $trigger_time = $otp_obj->getTriggerTime(); Debug::text(' Is Eligible for Holiday: ' . $holiday_obj->getName() . ' Daily Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' Not Eligible for Holiday: ' . $holiday_obj->getName(), __FILE__, __LINE__, __METHOD__, 10); continue 2; //Skip to next policy } } else { Debug::text(' Not Holiday...', __FILE__, __LINE__, __METHOD__, 10); continue 2; //Skip to next policy } unset($hlf, $holiday_obj); break; case 200: //Over schedule (Daily) / No Schedule. Have trigger time extend the schedule time. $trigger_time = $schedule_total_time + $otp_obj->getTriggerTime(); Debug::text(' Over Schedule/No Schedule Trigger Time: ' . $trigger_time, __FILE__, __LINE__, __METHOD__, 10); break; case 210: //Over Schedule (Weekly) / No Schedule //Get schedule time for the entire week, and add the Active After time to that. $schedule_weekly_total_time = $slf->getWeekWorkTimeSumByUserIDAndEpochAndStartWeekEpoch($this->getUserDateObject()->getUser(), TTDate::getEndWeekEpoch($this->getUserDateObject()->getDateStamp(), $start_week_day_id), TTDate::getBeginWeekEpoch($this->getUserDateObject()->getDateStamp(), $start_week_day_id)); Debug::text('Schedule Weekly Total Time: ' . $schedule_weekly_total_time, __FILE__, __LINE__, __METHOD__, 10); $trigger_time = $schedule_weekly_total_time + $otp_obj->getTriggerTime(); unset($schedule_weekly_total_time); break; } if (is_numeric($trigger_time) and $trigger_time < 0) { $trigger_time = 0; } if (is_numeric($trigger_time)) { $trigger_time_arr[] = array('calculation_order' => $otp_calculation_order[$otp_obj->getType()], 'trigger_time' => $trigger_time, 'over_time_policy_id' => $otp_obj->getId(), 'over_time_policy_type_id' => $otp_obj->getType(), 'combined_rate' => $otp_obj->getRate() + $otp_obj->getAccrualRate()); } unset($trigger_time); } if (isset($trigger_time_arr)) { $trigger_time_arr = $this->processTriggerTimeArray($trigger_time_arr, $weekly_total); } //Debug::Arr($trigger_time_arr, 'Trigger Time Array', __FILE__, __LINE__, __METHOD__, 10); } else { Debug::text(' No OverTime Policies found for this user.', __FILE__, __LINE__, __METHOD__, 10); } unset($otp_obj, $otplf); if (isset($trigger_time_arr)) { $total_daily_hours = 0; $total_daily_hours_used = 0; //get all worked total hours. $udtlf = TTnew('UserDateTotalListFactory'); $udtlf->getByUserDateIdAndStatus($this->getUserDateID(), 20); if ($udtlf->getRecordCount() > 0) { Debug::text('Found Total Hours to attempt to apply policy: Record Count: ' . $udtlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10); if ($trigger_time_arr[0]['trigger_time'] > 0) { //No trigger time set at 0. $enable_regular_hour_calculating = TRUE; } else { $enable_regular_hour_calculating = FALSE; } $tmp_policy_total_time = NULL; foreach ($udtlf as $udt_obj) { //Ignore incomplete punches if ($udt_obj->getTotalTime() == 0) { continue; } $udt_total_time = $udt_obj->getTotalTime(); if (isset($udt_meal_policy_adjustment_arr[$udt_obj->getId()])) { $udt_total_time = bcadd($udt_total_time, $udt_meal_policy_adjustment_arr[$udt_obj->getId()]); } if (isset($udt_break_policy_adjustment_arr[$udt_obj->getId()])) { $udt_total_time = bcadd($udt_total_time, $udt_break_policy_adjustment_arr[$udt_obj->getId()]); } $total_daily_hours = bcadd($total_daily_hours, $udt_total_time); //Loop through each trigger. $i = 0; Debug::text('Total Hour: ID: ' . $udt_obj->getId() . ' Status: ' . $udt_obj->getStatus() . ' Total Time: ' . $udt_obj->getTotalTime() . ' Total Daily Hours: ' . $total_daily_hours . ' Used Total Time: ' . $total_daily_hours_used . ' Branch ID: ' . $udt_obj->getBranch() . ' Department ID: ' . $udt_obj->getDepartment() . ' Job ID: ' . $udt_obj->getJob() . ' Job Item ID: ' . $udt_obj->getJobItem() . ' Quantity: ' . $udt_obj->getQuantity(), __FILE__, __LINE__, __METHOD__, 10); foreach ($trigger_time_arr as $trigger_time_data) { if (isset($trigger_time_arr[$i + 1]['trigger_time']) and $total_daily_hours_used >= $trigger_time_arr[$i + 1]['trigger_time']) { Debug::text(' ' . $i . ': SKIPPING THIS TRIGGER TIME: ' . $trigger_time_data['trigger_time'], __FILE__, __LINE__, __METHOD__, 10); $i++; continue; } Debug::text(' ' . $i . ': Trigger Time Data: Trigger Time: ' . $trigger_time_data['trigger_time'] . ' ID: ' . $trigger_time_data['over_time_policy_id'], __FILE__, __LINE__, __METHOD__, 10); Debug::text(' ' . $i . ': Used Total Time: ' . $total_daily_hours_used, __FILE__, __LINE__, __METHOD__, 10); //Only consider Regular Time ONCE per user date total row. if ($i == 0 and $trigger_time_arr[$i]['trigger_time'] > 0 and $total_daily_hours_used < $trigger_time_arr[$i]['trigger_time']) { Debug::text(' ' . $i . ': Trigger Time: ' . $trigger_time_arr[$i]['trigger_time'] . ' greater then 0, found Regular Time.', __FILE__, __LINE__, __METHOD__, 10); if ($total_daily_hours > $trigger_time_arr[$i]['trigger_time']) { $regular_total_time = $trigger_time_arr[$i]['trigger_time'] - $total_daily_hours_used; $regular_quantity_percent = bcdiv($trigger_time_arr[$i]['trigger_time'], $udt_obj->getTotalTime()); $regular_quantity = round(bcmul($udt_obj->getQuantity(), $regular_quantity_percent), 2); $regular_bad_quantity = round(bcmul($udt_obj->getBadQuantity(), $regular_quantity_percent), 2); } else { //$regular_total_time = $udt_obj->getTotalTime(); $regular_total_time = $udt_total_time; $regular_quantity = $udt_obj->getQuantity(); $regular_bad_quantity = $udt_obj->getBadQuantity(); } Debug::text(' ' . $i . ': Regular Total Time: ' . $regular_total_time . ' Regular Quantity: ' . $regular_quantity, __FILE__, __LINE__, __METHOD__, 10); if (isset($user_data_total_compact_arr[20][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()])) { Debug::text(' Adding to Compact Array: Branch: ' . (int) $udt_obj->getBranch() . ' Department: ' . (int) $udt_obj->getDepartment(), __FILE__, __LINE__, __METHOD__, 10); $user_data_total_compact_arr[20][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['total_time'] += $regular_total_time; $user_data_total_compact_arr[20][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['quantity'] += $regular_quantity; $user_data_total_compact_arr[20][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['bad_quantity'] += $regular_bad_quantity; } else { Debug::text(' Initiating Compact Sub-Array: Branch: ' . (int) $udt_obj->getBranch() . ' Department: ' . (int) $udt_obj->getDepartment(), __FILE__, __LINE__, __METHOD__, 10); $user_data_total_compact_arr[20][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()] = array('total_time' => $regular_total_time, 'quantity' => $regular_quantity, 'bad_quantity' => $regular_bad_quantity); } Debug::text(' Compact Array Regular Total: ' . $user_data_total_compact_arr[20][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['total_time'], __FILE__, __LINE__, __METHOD__, 10); $total_daily_hours_used += $regular_total_time; } Debug::text(' ' . $i . ': Daily Total Time: ' . $total_daily_hours . ' Trigger Time: ' . $trigger_time_arr[$i]['trigger_time'] . ' Used Total Time: ' . $total_daily_hours_used . ' Overtime Policy Type: ' . $trigger_time_arr[$i]['over_time_policy_type_id'], __FILE__, __LINE__, __METHOD__, 10); if ($total_daily_hours > $trigger_time_arr[$i]['trigger_time']) { Debug::text(' ' . $i . ': Trigger Time: ' . $trigger_time_arr[$i]['trigger_time'] . ' greater then 0, found Over Time.', __FILE__, __LINE__, __METHOD__, 10); if (isset($trigger_time_arr[$i + 1]['trigger_time'])) { Debug::text(' ' . $i . ': Found trigger time after this one: ' . $trigger_time_arr[$i + 1]['trigger_time'], __FILE__, __LINE__, __METHOD__, 10); $max_trigger_time = $trigger_time_arr[$i + 1]['trigger_time'] - $trigger_time_arr[$i]['trigger_time']; } else { $max_trigger_time = $trigger_time_arr[$i]['trigger_time']; } Debug::text(' aMax Trigger Time ' . $max_trigger_time, __FILE__, __LINE__, __METHOD__, 10); if (isset($trigger_time_arr[$i + 1]['trigger_time']) and $total_daily_hours_used > $trigger_time_arr[$i]['trigger_time']) { //$max_trigger_time = $max_trigger_time - ($total_daily_hours_used - $max_trigger_time); $max_trigger_time = $max_trigger_time - ($total_daily_hours_used - $trigger_time_arr[$i]['trigger_time']); } Debug::text(' bMax Trigger Time ' . $max_trigger_time, __FILE__, __LINE__, __METHOD__, 10); $over_time_total = $total_daily_hours - $total_daily_hours_used; if (isset($trigger_time_arr[$i + 1]['trigger_time']) and $max_trigger_time > 0 and $over_time_total > $max_trigger_time) { $over_time_total = $max_trigger_time; } if ($over_time_total > 0) { $over_time_quantity_percent = bcdiv($over_time_total, $udt_obj->getTotalTime()); $over_time_quantity = round(bcmul($udt_obj->getQuantity(), $over_time_quantity_percent), 2); $over_time_bad_quantity = round(bcmul($udt_obj->getBadQuantity(), $over_time_quantity_percent), 2); Debug::text(' Inserting Hours (' . $over_time_total . ') for Policy ID: ' . $trigger_time_arr[$i]['over_time_policy_id'], __FILE__, __LINE__, __METHOD__, 10); if (isset($user_data_total_compact_arr[30][$trigger_time_arr[$i]['over_time_policy_id']][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()])) { Debug::text(' Adding to Compact Array: Policy ID: ' . $trigger_time_arr[$i]['over_time_policy_id'] . ' Branch: ' . (int) $udt_obj->getBranch() . ' Department: ' . (int) $udt_obj->getDepartment(), __FILE__, __LINE__, __METHOD__, 10); $user_data_total_compact_arr[30][$trigger_time_arr[$i]['over_time_policy_id']][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['total_time'] += $over_time_total; $user_data_total_compact_arr[30][$trigger_time_arr[$i]['over_time_policy_id']][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['quantity'] += $over_time_quantity; $user_data_total_compact_arr[30][$trigger_time_arr[$i]['over_time_policy_id']][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['bad_quantity'] += $over_time_bad_quantity; } else { Debug::text(' Initiating Compact Sub-Array: Policy ID: ' . $trigger_time_arr[$i]['over_time_policy_id'] . ' Branch: ' . (int) $udt_obj->getBranch() . ' Department: ' . (int) $udt_obj->getDepartment(), __FILE__, __LINE__, __METHOD__, 10); $user_data_total_compact_arr[30][$trigger_time_arr[$i]['over_time_policy_id']][(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()] = array('total_time' => $over_time_total, 'quantity' => $over_time_quantity, 'bad_quantity' => $over_time_bad_quantity); } $total_daily_hours_used += $over_time_total; } else { Debug::text(' Over Time Total is 0: ' . $over_time_total, __FILE__, __LINE__, __METHOD__, 10); } unset($over_time_total, $over_time_quantity_percent, $over_time_quantity, $over_time_bad_quantity); } else { break; } $i++; } unset($udt_total_time); } unset($tmp_policy_total_time, $trigger_time_data, $trigger_time_arr); } } $profiler->stopTimer('UserDateTotal::calcOverTimePolicyTotalTime() - Part 1'); if (isset($user_data_total_compact_arr)) { return $user_data_total_compact_arr; } return FALSE; }