/** * createTimePeriodsForUpgrade * * This function creates the TimePeriods for the case where the system is handling upgrades * * In the case of upgrades we take the following steps: * 1) We find out what the current TimePeriod is (if one exists) * 2) We then use the supplied start date of the fiscal period and build leaf TimePeriods backwards until we reach * the current TimePeriod * 3) The current TimePeriod's end date is adjusted to extend up to the most recent backward leaf TimePeriod(s), if * available, or extend out to the day before the start date of the fiscal period * 4) We then build out any new forward TimePeriod(s) based on the configuration settings * * @param $currentSettings Array of the current forecast settings * @param $currentDate TimeDate instance of the current date when upgrade was run * @return Array of TimePeriod instances created for the upgrade */ public function createTimePeriodsForUpgrade($currentSettings, $currentDate) { $created = array(); $isLeafTimePeriod = true; $timeperiodInterval = $currentSettings['timeperiod_interval']; $timePeriodLeafInterval = $currentSettings['timeperiod_leaf_interval']; //Now try to find the current leaf TimePeriod. We have no way of knowing what the leaf type is so we cannot use TimePeriod::getCurrentId since //that assumes a type argument is supplied or it will use the defaults from the config. So instead we just search based on the closest TimePeriod $timedate = TimeDate::getInstance(); $db = DBManagerFactory::getInstance(); $query = sprintf("SELECT id FROM timeperiods WHERE start_date <= %s AND (parent_id IS NOT NULL OR parent_id <> '') AND deleted = 0 ORDER BY start_date DESC", $db->convert($db->quoted($currentDate->asDbDate()), 'date')); $result = $db->limitQuery($query, 0, 1); $currentTimePeriod = null; if (!empty($result)) { $row = $db->fetchByAssoc($result); if (!empty($row)) { $currentTimePeriod = new TimePeriod(); $currentTimePeriod->retrieve($row['id']); } } if (empty($currentTimePeriod)) { //If no currentTimePeriod instance was found, just use the most recent upcoming TimePeriod instance $query = sprintf("SELECT id FROM timeperiods WHERE start_date > %s AND parent_id IS NOT NULL AND deleted = 0 ORDER BY start_date ASC", $db->convert($db->quoted($currentDate->asDbDate()), 'date')); $result = $db->limitQuery($query, 0, 1); $row = $db->fetchByAssoc($result); if (!empty($row)) { $currentTimePeriod = new TimePeriod(); $currentTimePeriod->retrieve($row['id']); } if (empty($currentTimePeriod)) { //One last attempt using timeperiods without parent_id $query = sprintf("SELECT id FROM timeperiods WHERE start_date <= %s AND end_date >= %s AND parent_id IS NULL AND deleted = 0 ORDER BY start_date ASC", $db->convert($db->quoted($currentDate->asDbDate()), 'date'), $db->convert($db->quoted($currentDate->asDbDate()), 'date')); $result = $db->limitQuery($query, 0, 1); $row = $db->fetchByAssoc($result); if (!empty($row)) { $currentTimePeriod = new TimePeriod(); $currentTimePeriod->retrieve($row['id']); $isLeafTimePeriod = false; } //If a current TimePeriod still cannot be determined, just create a leaf with the correct current start date for the current date if (empty($currentTimePeriod)) { $currentTimePeriod = TimePeriod::getByType($timePeriodLeafInterval); $currentTimePeriod->setStartDate($this->determineCurrentStartDateByType($timePeriodLeafInterval, $timedate->getNow()->asDbDate())); $currentTimePeriod->save(); $created[] = $currentTimePeriod; } } } //Now mark all TimePeriods that start after the current TimePeriod to be deleted $db->query(sprintf("UPDATE timeperiods SET deleted = 1 WHERE start_date >= %s", $db->convert($db->quoted($currentTimePeriod->start_date), 'date'))); //Delete the current TimePeriod itself since we will re-create it with the appropriate type attributes and adjusted end date $db->query(sprintf("DELETE FROM timeperiods WHERE id = %s", $db->quoted($currentTimePeriod->id))); $currentEndDate = $timedate->fromDbDate($currentTimePeriod->end_date); $selectedStartDate = $timedate->fromDbDate($currentSettings["timeperiod_start_date"]); $targetStartDate = $timedate->getNow()->setDate($currentEndDate->format('Y'), $selectedStartDate->format('m'), $selectedStartDate->format('d')); //Now create the new TimePeriods with the forward date modifier $timePeriod = TimePeriod::getByType($timeperiodInterval); //If the target starting date is before the current year's starting date, keep incrementing the year until we are past the current TimePeriod's end date while ($targetStartDate < $currentEndDate) { $targetStartDate->modify($timePeriod->next_date_modifier); } //Create a parent TimePeriod instance $currentParentTimePeriodInstance = TimePeriod::getByType($timeperiodInterval); $currentParentTimePeriodInstance->setStartDate($timedate->fromDbDate($targetStartDate->asDbDate())->modify($currentParentTimePeriodInstance->previous_date_modifier)->asDbDate()); $currentParentTimePeriodInstance->name = $currentParentTimePeriodInstance->getTimePeriodName(1); $currentParentTimePeriodInstance->save(); $created[] = $currentParentTimePeriodInstance; //Now get the leaf type we will be building $leaf = TimePeriod::getByType($timePeriodLeafInterval); $leafCycle = $timePeriod->leaf_periods; //If we are to create any TimePeriods leading back to the current TimePeriod's end date, we'd first start with //a TimePeriod one back of the target start date $previousLeafTimePeriodStartDate = $timedate->fromDbDate($targetStartDate->asDbDate())->modify($leaf->previous_date_modifier); //While the current date is before any potential previous leaf TimePeriod start date, create leaf TimePeriod while ($isLeafTimePeriod && $currentEndDate < $previousLeafTimePeriodStartDate || $currentDate < $previousLeafTimePeriodStartDate && $isLeafTimePeriod == false) { $previousLeafTimePeriod = TimePeriod::getByType($leaf->type); $previousLeafTimePeriod->setStartDate($previousLeafTimePeriodStartDate->asDbDate()); $previousLeafTimePeriod->leaf_cycle = $leafCycle; $previousLeafTimePeriod->name = $previousLeafTimePeriod->getTimePeriodName($leafCycle); $previousLeafTimePeriod->parent_id = $currentParentTimePeriodInstance->id; $previousLeafTimePeriod->save(); $created[] = $previousLeafTimePeriod; $leafCycle--; $previousLeafTimePeriodStartDate = $previousLeafTimePeriodStartDate->modify($leaf->previous_date_modifier); } //The current TimePeriod end date is now the last unadjusted previousLeafTimePeriodStartDate value $newCurrentTimePeriod = TimePeriod::getByType($leaf->type); $newCurrentTimePeriod->new_with_id = true; $newCurrentTimePeriod->id = $currentTimePeriod->id; $newCurrentTimePeriod->parent_id = $currentParentTimePeriodInstance->id; if ($isLeafTimePeriod) { $newCurrentTimePeriod->setStartDate($currentTimePeriod->start_date); } else { $newCurrentTimePeriod->setStartDate($previousLeafTimePeriodStartDate->asDbDate()); } $newCurrentTimePeriod->end_date = $previousLeafTimePeriodStartDate->modify($leaf->next_date_modifier)->modify('-1 day')->asDbDate(); $newCurrentTimePeriod->leaf_cycle = $leafCycle; $newCurrentTimePeriod->name = $newCurrentTimePeriod->getTimePeriodName($leafCycle); $newCurrentTimePeriod->save(); $created[] = $newCurrentTimePeriod; //We set it back once here since the buildTimePeriods code triggers the modification immediately //$targetStartDate->modify($timePeriod->previous_date_modifier); $timePeriod->setStartDate($targetStartDate->asDbDate()); return array_merge($created, $timePeriod->buildTimePeriods($currentSettings['timeperiod_shown_forward'], 'forward')); }