| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- <?php
- /**
- * The model file of holiday module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
- * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author Chunsheng Wang <chunsheng@cnezsoft.com>
- * @package holiday
- * @version $Id
- * @link https://www.zentao.net
- */
- class holidayModel extends model
- {
- /**
- * 通过 ID 获取节假日。
- * Get holiday by id.
- *
- * @param int $id
- * @access public
- * @return object|bool
- */
- public function getById($id)
- {
- return $this->dao->select('*')->from(TABLE_HOLIDAY)->where('id')->eq($id)->fetch();
- }
- /**
- * 获取节假日列表。
- * Get holiday list.
- *
- * @param string $year
- * @param string $type
- * @access public
- * @return array
- */
- public function getList($year = '', $type = 'all')
- {
- return $this->dao->select('*')->from(TABLE_HOLIDAY)
- ->where('1=1')
- ->beginIf(!empty($year))
- ->andWhere('year', true)->eq($year)
- ->orWhere("DATE_FORMAT(`begin`, 'YYYY')")->eq($year)
- ->orWhere("DATE_FORMAT(`end`, 'YYYY')")->eq($year)
- ->markright(1)
- ->fi()
- ->beginIf($type != 'all' && $type)->andWhere('type')->eq($type)->fi()
- ->fetchAll('id');
- }
- /**
- * 获取年份列表。
- * Get year pairs.
- *
- * @access public
- * @return array
- */
- public function getYearPairs()
- {
- return $this->dao->select('year,year')->from(TABLE_HOLIDAY)->groupBy('year')->orderBy('year_desc')->fetchPairs();
- }
- /**
- * 创建一个节假日。
- * Create a holiday.
- *
- * @param object $holiday
- * @access public
- * @return int|bool
- */
- public function create($holiday)
- {
- $this->dao->insert(TABLE_HOLIDAY)->data($holiday)
- ->autoCheck()
- ->batchCheck($this->config->holiday->require->create, 'notempty')
- ->check('end', 'ge', $holiday->begin)
- ->exec();
- $lastInsertID = $this->dao->lastInsertID();
- if(dao::isError()) return false;
- $beginDate = $holiday->begin;
- $endDate = $holiday->end;
- /* Update project. */
- $this->updateProgramPlanDuration($beginDate, $endDate);
- $this->updateProjectRealDuration($beginDate, $endDate);
- /* Update task. */
- $this->updateTaskPlanDuration($beginDate, $endDate);
- $this->updateTaskRealDuration($beginDate, $endDate);
- return $lastInsertID;
- }
- /**
- * 编辑一个节假日。
- * Edit holiday.
- *
- * @param object $holiday
- * @access public
- * @return bool
- */
- public function update($holiday)
- {
- $this->dao->update(TABLE_HOLIDAY)
- ->data($holiday)
- ->autoCheck()
- ->batchCheck($this->config->holiday->require->edit, 'notempty')
- ->check('end', 'ge', $holiday->begin)
- ->where('id')->eq($holiday->id)
- ->exec();
- if(dao::isError()) return false;
- $beginDate = $holiday->begin;
- $endDate = $holiday->end;
- /* Update project. */
- $this->updateProgramPlanDuration($beginDate, $endDate);
- $this->updateProjectRealDuration($beginDate, $endDate);
- /* Update task. */
- $this->updateTaskPlanDuration($beginDate, $endDate);
- $this->updateTaskRealDuration($beginDate, $endDate);
- return !dao::isError();
- }
- /**
- * 通过开始和结束日期获取节假日。
- * Get holidays by begin and end.
- *
- * @param string $begin
- * @param string $end
- * @access public
- * @return array
- */
- public function getHolidays($begin, $end)
- {
- $records = $this->dao->select('*')->from(TABLE_HOLIDAY)
- ->where('type')->eq('holiday')
- ->andWhere('end')->ge($begin)
- ->andWhere('begin')->le($end)
- ->fetchAll('id');
- $naturalDays = $this->getDaysBetween($begin, $end);
- $holidays = array();
- foreach($records as $record)
- {
- $dates = $this->getDaysBetween($record->begin, $record->end);
- $holidays = array_merge($holidays, $dates);
- }
- return array_intersect($naturalDays, $holidays);
- }
- /**
- * 获取工作日。
- * Get working days.
- *
- * @param string $begin
- * @param string $end
- * @access public
- * @return array
- */
- public function getWorkingDays($begin = '', $end = '')
- {
- $records = $this->dao->select('*')->from(TABLE_HOLIDAY)
- ->where('type')->eq('working')
- ->andWhere('begin')->le($end)
- ->andWhere('end')->ge($begin)
- ->fetchAll('id');
- $workingDays = array();
- foreach($records as $record)
- {
- $dates = $this->getDaysBetween($record->begin, $record->end);
- $workingDays = array_merge($workingDays, $dates);
- }
- return $workingDays;
- }
- /**
- * 获取实际工作日。
- * Get actual working days.
- *
- * @param string $begin
- * @param string $end
- * @access public
- * @return array
- */
- public function getActualWorkingDays($begin, $end)
- {
- if(empty($begin) || empty($end) || $begin == '0000-00-00' || $end == '0000-00-00') return array();
- /* Get holidays, working days and weekend days .*/
- $holidays = $this->getHolidays($begin, $end);
- $workingDays = $this->getWorkingDays($begin, $end);
- $weekend = isset($this->config->execution->weekend) ? $this->config->execution->weekend : 2;
- /* When the start date and end date are the same. */
- $actualDays = array();
- if($begin == $end)
- {
- if(in_array($begin, $workingDays)) return array($begin);
- if(in_array($begin, $holidays)) return array();
- $w = date('w', strtotime($begin));
- if($w == 0 || ($weekend == 2 && $w == 6)) return array();
- return array($begin);
- }
- /* Process actual working days. */
- for($i = 0, $currentDay = $begin; $currentDay < $end; $i ++)
- {
- $currentDay = date('Y-m-d', strtotime("{$begin} + {$i} days"));
- $w = date('w', strtotime($currentDay));
- if(in_array($currentDay, $workingDays))
- {
- $actualDays[] = $currentDay;
- continue;
- }
- if(in_array($currentDay, $holidays)) continue;
- if($w == 0 || ($weekend == 2 && $w == 6)) continue;
- $actualDays[] = $currentDay;
- }
- return $actualDays;
- }
- /**
- * 获取开始和结束日期间的日期。
- * Get the dates between the begin and end.
- *
- * @param string $begin
- * @param string $end
- * @access public
- * @return array
- */
- public function getDaysBetween($begin, $end)
- {
- $beginTime = strtotime($begin);
- $endTime = strtotime($end);
- $days = ($endTime - $beginTime) / 86400;
- if(!$beginTime) return array();
- $dateList = array();
- for($i = 0; $i <= $days; $i ++) $dateList[] = date('Y-m-d', strtotime("+{$i} days", $beginTime));
- return $dateList;
- }
- /**
- * 判断一天是否是节假日。
- * Judge if is holiday.
- *
- * @param string $date
- * @access public
- * @return bool
- */
- public function isHoliday($date)
- {
- $record = $this->dao->select('*')->from(TABLE_HOLIDAY)
- ->where('type')->eq('holiday')
- ->andWhere('begin')->le($date)
- ->andWhere('end')->ge($date)
- ->fetch();
- return !empty($record);
- }
- /**
- * 判断一天是否是工作日。
- * Judge if is working days.
- *
- * @param string $date
- * @access public
- * @return bool
- */
- public function isWorkingDay($date)
- {
- $record = $this->dao->select('*')->from(TABLE_HOLIDAY)
- ->where('type')->eq('working')
- ->andWhere('begin')->le($date)
- ->andWhere('end')->ge($date)
- ->fetch();
- return !empty($record);
- }
- /**
- * 更新项目的工期。
- * Update project duration.
- *
- * @param string $beginDate
- * @param string $endDate
- * @access public
- * @return void
- */
- public function updateProgramPlanDuration($beginDate, $endDate)
- {
- $updateProjectList = $this->dao->select('id, begin, end')
- ->from(TABLE_PROJECT)
- ->where('status')->ne('done')
- ->andWhere('type')->ne('program')
- ->andWhere('end')->ne(LONG_TIME)
- ->andWhere('begin', true)->between($beginDate, $endDate)
- ->orWhere('end')->between($beginDate, $endDate)
- ->orWhere("(`begin` < '{$beginDate}' AND `end` > '{$endDate}')")
- ->markRight(1)
- ->fetchAll();
- foreach($updateProjectList as $project)
- {
- $realDuration = $this->getActualWorkingDays($project->begin, $project->end);
- $realDuration = count($realDuration);
- $this->dao->update(TABLE_PROJECT)->set('planDuration')->eq($realDuration)->where('id')->eq($project->id)->exec();
- }
- }
- /**
- * 测试更新项目实际工期。
- * Update project real duration.
- *
- * @param string $beginDate
- * @param string $endDate
- * @access public
- * @return void
- */
- public function updateProjectRealDuration($beginDate, $endDate)
- {
- $updateProjectList = $this->dao->select('id, realBegan, realEnd')
- ->from(TABLE_PROJECT)
- ->where('status')->ne('done')
- ->andWhere('type')->ne('program')
- ->andwhere('realBegan', true)->between($beginDate, $endDate)
- ->orWhere('realEnd')->between($beginDate, $endDate)
- ->orWhere("(`realBegan` < '{$beginDate}' AND `realEnd` > '{$endDate}')")
- ->markRight(1)
- ->fetchAll();
- foreach($updateProjectList as $project)
- {
- $realDuration = $this->getActualWorkingDays($project->realBegan, $project->realEnd);
- $realDuration = count($realDuration);
- $this->dao->update(TABLE_PROJECT)->set('realDuration')->eq($realDuration)->where('id')->eq($project->id)->exec();
- }
- }
- /**
- * 更新任务的计划工期。
- * Update task plan duration.
- *
- * @param string $beginDate
- * @param string $endDate
- * @access public
- * @return void
- */
- public function updateTaskPlanDuration($beginDate, $endDate)
- {
- $updateTaskList = $this->dao->select('id, estStarted, deadline')
- ->from(TABLE_TASK)
- ->where('estStarted')->between($beginDate, $endDate)
- ->orWhere('deadline')->between($beginDate, $endDate)
- ->orWhere("(`estStarted` < '{$beginDate}' AND `deadline` > '{$endDate}')")
- ->andWhere('status') ->ne('done')
- ->fetchAll();
- foreach($updateTaskList as $task)
- {
- $planduration = $this->getActualWorkingDays($task->estStarted, $task->deadline);
- $planduration = count($planduration);
- $this->dao->update(TABLE_TASK)->set('planduration')->eq($planduration)->where('id')->eq($task->id)->exec();
- }
- }
- /**
- * 更新任务的实际工期。
- * Update task real duration.
- *
- * @param string $beginDate
- * @param string $endDate
- * @access public
- * @return void
- */
- public function updateTaskRealDuration($beginDate, $endDate)
- {
- $updateTaskList = $this->dao->select('id, realStarted, finishedDate')
- ->from(TABLE_TASK)
- ->where('realStarted')->between($beginDate, $endDate)
- ->orWhere("date_format(`finishedDate`,'%Y-%m-%d')")->between($beginDate, $endDate)
- ->orWhere("(`realStarted` < '$beginDate' AND date_format(`finishedDate`,'%Y-%m-%d') > '$endDate')")
- ->andWhere('status')->ne('done')
- ->fetchAll();
- foreach($updateTaskList as $task)
- {
- $realDuration = $this->getActualWorkingDays($task->realStarted, date('Y-m-d', $task->finishedDate ? strtotime($task->finishedDate) : time()));
- $realDuration = count($realDuration);
- $this->dao->update(TABLE_TASK)->set('realDuration')->eq($realDuration)->where('id')->eq($task->id)->exec();
- }
- }
- /**
- * API: 获取节假日。
- * Get holidays by api.
- *
- * @param string $year
- * @access public
- * @return array
- */
- public function getHolidayByAPI($year = '')
- {
- /* Get holidays by file. */
- $yearFile = $this->app->wwwRoot . 'static/json/holiday/' . $year . '.json';
- $defaultFile = $this->app->wwwRoot . 'static/json/holiday/default.json';
- $data = file_exists($yearFile) ? file_get_contents($yearFile) : file_get_contents($defaultFile);
- $data = $data ? json_decode($data) : '';
- $days = isset($data->days) ? (array)$data->days : array();
- if(empty($days))
- {
- /* Get holidays by api. */
- if(empty($year)) $year = date('Y');
- $apiRoot = sprintf($this->config->holiday->apiRoot, $year);
- $data = json_decode(common::http($apiRoot));
- $days = isset($data->days) ? (array)$data->days : array();
- }
- /* Build holiday data. */
- $holidays = array();
- $privDay = 0;
- $prevDayOff = true;
- $daysIndex = count($days) - 1;
- foreach($days as $index => $day)
- {
- if($index < $daysIndex && (strtotime($day->date) - $privDay > 86400 || $day->isOffDay != $prevDayOff))
- {
- $holiday = new stdClass();
- $holiday->type = $day->isOffDay ? 'holiday' : 'working';
- $holiday->name = $day->name . zget($this->lang->holiday->typeList, $holiday->type);
- $holiday->begin = $day->date;
- $holiday->end = '';
- $holidays[] = $holiday;
- }
- if(isset($holiday) || $index == $daysIndex)
- {
- $holidayNum = count($holidays);
- if($holidayNum > 1)
- {
- if(isset($holiday))
- {
- $holidays[$holidayNum - 2]->end = date('Y-m-d', $privDay);
- }
- else
- {
- $holidays[$holidayNum - 1]->end = $day->date;
- }
- }
- if(isset($holiday)) unset($holiday);
- }
- $privDay = strtotime($day->date);
- $prevDayOff = $day->isOffDay;
- }
- return $holidays;
- }
- /**
- * 批量创建节假日。
- * Batch create holiday.
- *
- * @param array $holidays
- * @access public
- * @return int|bool
- */
- public function batchCreate($holidays)
- {
- foreach($holidays as $holiday)
- {
- $this->dao->insert(TABLE_HOLIDAY)->data($holiday)
- ->autoCheck()
- ->batchCheck($this->config->holiday->require->create, 'notempty')
- ->check('end', 'ge', $holiday->begin)
- ->exec();
- }
- if(dao::isError()) return false;
- $lastInsertID = $this->dao->lastInsertID();
- return $lastInsertID;
- }
- }
|