* Add weekly and holiday.

This commit is contained in:
孙广明
2021-11-08 09:07:16 +08:00
parent b8f2d9aa80
commit 612c6e0728
30 changed files with 2240 additions and 2 deletions

View File

@@ -206,6 +206,7 @@ define('TABLE_API_LIB_RELEASE', '`' . $config->db->prefix . 'api_lib_release`');
define('TABLE_MODULE', '`' . $config->db->prefix . 'module`');
define('TABLE_ACTION', '`' . $config->db->prefix . 'action`');
define('TABLE_FILE', '`' . $config->db->prefix . 'file`');
define('TABLE_HOLIDAY', '`' . $config->db->prefix . 'holiday`');
define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`');
define('TABLE_EXTENSION', '`' . $config->db->prefix . 'extension`');
define('TABLE_CRON', '`' . $config->db->prefix . 'cron`');
@@ -216,6 +217,7 @@ define('TABLE_SUITECASE', '`' . $config->db->prefix . 'suitecase`');
define('TABLE_TESTREPORT', '`' . $config->db->prefix . 'testreport`');
define('TABLE_ENTRY', '`' . $config->db->prefix . 'entry`');
define('TABLE_WEEKLYREPORT', '`' . $config->db->prefix . 'weeklyreport`');
define('TABLE_WEBHOOK', '`' . $config->db->prefix . 'webhook`');
define('TABLE_LOG', '`' . $config->db->prefix . 'log`');
define('TABLE_SCORE', '`' . $config->db->prefix . 'score`');

View File

@@ -46,3 +46,34 @@ CREATE TABLE IF NOT EXISTS `zt_designspec` (
`files` varchar(255) NOT NULL,
UNIQUE KEY `design` (`design`,`version`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_weeklyreport`;
CREATE TABLE IF NOT EXISTS `zt_weeklyreport`(
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`project` mediumint(8) unsigned NOT NULL,
`weekStart` date NOT NULL,
`pv` float(9,2) NOT NULL,
`ev` float(9,2) NOT NULL,
`ac` float(9,2) NOT NULL,
`sv` float(9,2) NOT NULL,
`cv` float(9,2) NOT NULL,
`staff` smallint(5) unsigned NOT NULL,
`progress` varchar(255) NOT NULL,
`workload` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `week` (`project`,`weekStart`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_holiday`;
CREATE TABLE IF NOT EXISTS `zt_holiday` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL DEFAULT '',
`type` enum('holiday', 'working') NOT NULL DEFAULT 'holiday',
`desc` text NOT NULL,
`year` char(4) NOT NULL,
`begin` date NOT NULL,
`end` date NOT NULL,
PRIMARY KEY (`id`),
KEY `year` (`year`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

View File

@@ -586,6 +586,19 @@ CREATE TABLE IF NOT EXISTS `zt_grouppriv` (
`method` char(30) NOT NULL default '',
UNIQUE KEY `group` (`group`,`module`,`method`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_holiday`;
CREATE TABLE IF NOT EXISTS `zt_holiday` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL DEFAULT '',
`type` enum('holiday', 'working') NOT NULL DEFAULT 'holiday',
`desc` text NOT NULL,
`year` char(4) NOT NULL,
`begin` date NOT NULL,
`end` date NOT NULL,
PRIMARY KEY (`id`),
KEY `year` (`year`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_history`;
CREATE TABLE IF NOT EXISTS `zt_history` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
@@ -1477,6 +1490,22 @@ CREATE TABLE IF NOT EXISTS `zt_userview` (
`sprints` mediumtext NOT NULL,
UNIQUE KEY `account` (`account`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_weeklyreport`;
CREATE TABLE IF NOT EXISTS `zt_weeklyreport`(
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`project` mediumint(8) unsigned NOT NULL,
`weekStart` date NOT NULL,
`pv` float(9,2) NOT NULL,
`ev` float(9,2) NOT NULL,
`ac` float(9,2) NOT NULL,
`sv` float(9,2) NOT NULL,
`cv` float(9,2) NOT NULL,
`staff` smallint(5) unsigned NOT NULL,
`progress` varchar(255) NOT NULL,
`workload` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `week` (`project`,`weekStart`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_webhook`;
CREATE TABLE IF NOT EXISTS `zt_webhook` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,

View File

@@ -881,7 +881,7 @@ class block extends control
}
$today = helper::today();
if(isset($this->config->maxVersion)) $monday = date('Ymd', strtotime($this->loadModel('weekly')->getThisMonday($today)));
$monday = date('Ymd', strtotime($this->loadModel('weekly')->getThisMonday($today)));
$tasks = $this->dao->select("project,
sum(consumed) as totalConsumed,
sum(if(status != 'cancel' and status != 'closed', `left`, 0)) as totalLeft")
@@ -901,7 +901,7 @@ class block extends control
$project->progress = $project->allStories == 0 ? 0 : round($project->doneStories / $project->allStories, 3) * 100;
$project->executions = $this->project->getStats($projectID, 'all', 0, 0, 30, 'id_desc', $pager);
}
elseif($project->model == 'waterfall' and isset($this->config->maxVersion))
elseif($project->model == 'waterfall')
{
$begin = $project->begin;
$weeks = $this->weekly->getWeekPairs($begin);

View File

@@ -0,0 +1,5 @@
<?php
if(!isset($config->holiday)) $config->holiday = new stdclass();
$config->holiday->require = new stdclass();
$config->holiday->require->create = 'name,begin,end';
$config->holiday->require->edit = 'name,begin,end';

117
module/holiday/control.php Normal file
View File

@@ -0,0 +1,117 @@
<?php
/**
* The control file of holiday module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package holiday
* @version $Id
* @link http://www.zentao.net
*/
class holiday extends control
{
/**
* Holiday list.
*
* @access public
* @return void
*/
public function index()
{
$this->locate(inlink('browse'));
}
/**
* Holiday list.
*
* @param string $year
* @access public
* @return void
*/
public function browse($year = '')
{
$holidays = $this->holiday->getList($year);
$yearList = $this->holiday->getYearPairs();
$this->view->title = $this->lang->holiday->browse;
$this->view->holidays = $holidays;
$this->view->yearList = $yearList;
$this->view->currentYear = $year;
$this->display();
}
/**
* Create a holiday.
*
* @access public
* @return void
*/
public function create()
{
if($_POST)
{
$holidayID = $this->holiday->create();
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$actionID = $this->loadModel('action')->create('holiday', $holidayID, 'created');
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->title = $this->lang->holiday->create;
$this->display();
}
/**
* Edit holiday.
*
* @param int $id
* @access public
* @return void
*/
public function edit($id)
{
$holiday = $this->holiday->getById($id);
if($_POST)
{
$this->holiday->update($id);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->title = $this->lang->holiday->edit;
$this->view->holiday = $holiday;
$this->display();
}
/**
* Delete holiday.
*
* @param int $id
* @param int $confirm
* @access public
* @return void
*/
public function delete($id, $confirm = 'no')
{
if($confirm == 'no')
{
die(js::confirm($this->lang->holiday->confirmDelete, inLink('delete', "id=$id&confirm=yes")));
}
else
{
$holidayInformation = $this->dao->select('begin, end')->from(TABLE_HOLIDAY)->where('id')->eq($id)->fetch();
$this->dao->delete()->from(TABLE_HOLIDAY)->where('id')->eq($id)->exec();
/* Update project. */
$this->holiday->updateProgramPlanDuration($holidayInformation->begin, $holidayInformation->end);
$this->holiday->updateProjectRealDuration($holidayInformation->begin, $holidayInformation->end);
/* Update task. */
$this->holiday->updateTaskPlanDuration($holidayInformation->begin, $holidayInformation->end);
$this->holiday->updateTaskRealDuration($holidayInformation->begin, $holidayInformation->end);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
die(js::reload('parent'));
}
}
}

View File

@@ -0,0 +1,3 @@
.tree .active{font-weight: bold;}
.with-side .side {position: absolute; width: 130px;}
.with-side .main {padding-left: 145px; float: left;}

View File

View File

@@ -0,0 +1,276 @@
<?php
public function getHolidays($begin, $end)
{
$records = $this->dao->select('*')->from(TABLE_HOLIDAY)
->where('type')->eq('holiday')
->andWhere('begin')->le($end)
->andWhere('end')->ge($begin)
->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);
}
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;
}
public function getActualWorkingDays($begin, $end)
{
if(empty($begin) or empty($end) or $begin == '0000-00-00' or $end == '0000-00-00') return array();
$actualDays = array();
$currentDay = $begin;
$holidays = $this->getHolidays($begin, $end);
$workingDays = $this->getWorkingDays($begin, $end);
$weekend = isset($this->config->project->weekend) ? $this->config->project->weekend : 2;
/* When the start date and end date are the same. */
if($begin == $end)
{
if(in_array($begin, $workingDays)) return $actualDays[] = $begin;
if(in_array($begin, $holidays)) return $actualDays;
$w = date('w', strtotime($begin));
if($weekend == 2)
{
if($w == 0 or $w == 6) return $actualDays;
}
else
{
if($w == 0) return $actualDays;
}
$actualDays[] = $begin;
return $actualDays;
}
for($i = 0; $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($weekend == 2)
{
if($w == 0 or $w == 6) continue;
}
else
{
if($w == 0) continue;
}
$actualDays[] = $currentDay;
}
return $actualDays;
}
public function getDaysBetween($begin, $end)
{
$beginTime = strtotime($begin);
$endTime = strtotime($end);
$days = ($endTime - $beginTime) / 86400;
$dateList = array();
for($i = 0; $i <= $days; $i ++) $dateList[] = date('Y-m-d', strtotime("+$i days", $beginTime));
return $dateList;
}
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);
}
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);
}
public function update($id)
{
$result = parent::update($id);
if($result)
{
$beginDate = $this->post->begin;
$endDate = $this->post->end;
/* Update project. */
$this->updateProgramPlanDuration($beginDate, $endDate);
$this->updateProjectRealDuration($beginDate, $endDate);
/* Update task. */
$this->updateTaskPlanDuration($beginDate, $endDate);
$this->updateTaskRealDuration($beginDate, $endDate);
}
return $result;
}
public function create()
{
$lastInsertID = parent::create();
if($lastInsertID)
{
$beginDate = $this->post->begin;
$endDate = $this->post->end;
/* Update project. */
$this->updateProgramPlanDuration($beginDate, $endDate);
$this->updateProjectRealDuration($beginDate, $endDate);
/* Update task. */
$this->updateTaskPlanDuration($beginDate, $endDate);
$this->updateTaskRealDuration($beginDate, $endDate);
}
return $lastInsertID;
}
public function delete($id, $null = null)
{
$holidayInformation = $this->dao->select('begin,end')->from(TABLE_HOLIDAY)->where('id')->eq($id)->fetch();
$result = parent::delete($id, $null = null);
if($result)
{
/* Update project. */
$this->updateProgramPlanDuration($holidayInformation->begin, $holidayInformation->end);
$this->updateProjectRealDuration($holidayInformation->begin, $holidayInformation->end);
/* Update task. */
$this->updateTaskPlanDuration($holidayInformation->begin, $holidayInformation->end);
$this->updateTaskRealDuration($holidayInformation->begin, $holidayInformation->end);
}
return $result;
}
public function updateProgramPlanDuration($beginDate, $endDate)
{
$updateProjectList = $this->dao->select('id, begin, end')
->from(TABLE_PROJECT)
->where('begin')->between($beginDate, $endDate)
->orWhere('end')->between($beginDate, $endDate)
->orWhere("(begin < '$beginDate' AND end > '$endDate')")
->andWhere('status')->ne('done')
->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();
}
}
public function updateProjectRealDuration($beginDate, $endDate)
{
$updateProjectList = $this->dao->select('id, realBegan, realEnd')
->from(TABLE_PROJECT)
->where('realBegan')->between($beginDate, $endDate)
->orWhere('realEnd')->between($beginDate, $endDate)
->orWhere("(realBegan < '$beginDate' AND realEnd > '$endDate')")
->andWhere('status')->ne('done')
->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();
}
}
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();
}
}
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->realBegan, date('Y-m-d',strtotime($task->finishedDate)));
$realDuration = count($realDuration);
$this->dao->update(TABLE_TASK)
->set('realDuration')->eq($realDuration)
->where('id')->eq($task->id)
->exec();
}
}

View File

@@ -0,0 +1,27 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = 'Holiday';
$lang->holiday->browse = 'Browse';
$lang->holiday->create = 'Create';
$lang->holiday->edit = 'Edit';
$lang->holiday->delete = 'Delete';
$lang->holiday->createAction = 'Create Holiday';
$lang->holiday->editAction = 'Edit Holiday';
$lang->holiday->deleteAction = 'Delete Holiday';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Name';
$lang->holiday->desc = 'Description';
$lang->holiday->type = 'Type';
$lang->holiday->begin = 'Begin';
$lang->holiday->end = 'End';
$lang->holiday->all = 'All';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->typeList['holiday'] = 'Holiday';
$lang->holiday->typeList['working'] = 'Working Day';
$lang->holiday->emptyTip = 'No Holiday';
$lang->holiday->confirmDelete = 'Confirm removal of holidays?';

View File

@@ -0,0 +1,27 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = 'Holiday';
$lang->holiday->browse = 'Browse';
$lang->holiday->create = 'Create';
$lang->holiday->edit = 'Edit';
$lang->holiday->delete = 'Delete';
$lang->holiday->createAction = 'Create Holiday';
$lang->holiday->editAction = 'Edit Holiday';
$lang->holiday->deleteAction = 'Delete Holiday';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Name';
$lang->holiday->desc = 'Description';
$lang->holiday->type = 'Type';
$lang->holiday->begin = 'Begin';
$lang->holiday->end = 'End';
$lang->holiday->all = 'All';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->typeList['holiday'] = 'Holiday';
$lang->holiday->typeList['working'] = 'Working Day';
$lang->holiday->emptyTip = 'No Holiday';
$lang->holiday->confirmDelete = 'Confirm removal of holidays?';

View File

@@ -0,0 +1,27 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = 'Holiday';
$lang->holiday->browse = 'Browse';
$lang->holiday->create = 'Create';
$lang->holiday->edit = 'Edit';
$lang->holiday->delete = 'Delete';
$lang->holiday->createAction = 'Create Holiday';
$lang->holiday->editAction = 'Edit Holiday';
$lang->holiday->deleteAction = 'Delete Holiday';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Name';
$lang->holiday->desc = 'Description';
$lang->holiday->type = 'Type';
$lang->holiday->begin = 'Begin';
$lang->holiday->end = 'End';
$lang->holiday->all = 'All';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->typeList['holiday'] = 'Holiday';
$lang->holiday->typeList['working'] = 'Working Day';
$lang->holiday->emptyTip = 'No Holiday';
$lang->holiday->confirmDelete = 'Confirm removal of holidays?';

View File

View File

@@ -0,0 +1,27 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = 'Ngày lễ';
$lang->holiday->browse = 'Browse';
$lang->holiday->create = 'Tạo';
$lang->holiday->edit = 'Sửa';
$lang->holiday->delete = 'Xóa';
$lang->holiday->createAction = 'Create Holiday';
$lang->holiday->editAction = 'Edit Holiday';
$lang->holiday->deleteAction = 'Delete Holiday';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Tên';
$lang->holiday->desc = 'Mô tả';
$lang->holiday->type = 'Loại';
$lang->holiday->begin = 'Bắt đầu';
$lang->holiday->end = 'Kết thúc';
$lang->holiday->all = 'All';
$lang->holiday->holiday = 'Ngày lễ';
$lang->holiday->typeList['holiday'] = 'Ngày lễ';
$lang->holiday->typeList['working'] = 'Ngày làm việc';
$lang->holiday->emptyTip = 'No Holiday';
$lang->holiday->confirmDelete = 'Confirm removal of holidays?';

View File

@@ -0,0 +1,27 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = '节假日';
$lang->holiday->browse = '浏览';
$lang->holiday->create = '新建';
$lang->holiday->edit = '编辑';
$lang->holiday->delete = '删除';
$lang->holiday->createAction = '创建节假日';
$lang->holiday->editAction = '编辑节假日';
$lang->holiday->deleteAction = '删除节假日';
$lang->holiday->id = '编号';
$lang->holiday->name = '名称';
$lang->holiday->desc = '描述';
$lang->holiday->type = '类型';
$lang->holiday->begin = '开始日期';
$lang->holiday->end = '结束日期';
$lang->holiday->all = '所有';
$lang->holiday->holiday = '假期';
$lang->holiday->typeList['holiday'] = '假期';
$lang->holiday->typeList['working'] = '补班';
$lang->holiday->emptyTip = '暂时没有节假日。';
$lang->holiday->confirmDelete = '确认删除节假日?';

View File

@@ -0,0 +1,27 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = '節假日';
$lang->holiday->browse = '瀏覽';
$lang->holiday->create = '新建';
$lang->holiday->edit = '編輯';
$lang->holiday->delete = '刪除';
$lang->holiday->createAction = '創建節假日';
$lang->holiday->editAction = '編輯節假日';
$lang->holiday->deleteAction = '刪除節假日';
$lang->holiday->id = '編號';
$lang->holiday->name = '名稱';
$lang->holiday->desc = '描述';
$lang->holiday->type = '類型';
$lang->holiday->begin = '開始日期';
$lang->holiday->end = '結束日期';
$lang->holiday->all = '所有';
$lang->holiday->holiday = '假期';
$lang->holiday->typeList['holiday'] = '假期';
$lang->holiday->typeList['working'] = '補班';
$lang->holiday->emptyTip = '暫時沒有節假日。';
$lang->holiday->confirmDelete = '確認刪除節假日?';

410
module/holiday/model.php Normal file
View File

@@ -0,0 +1,410 @@
<?php
/**
* The model file of holiday module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package holiday
* @version $Id
* @link http://www.zentao.net
*/
class holidayModel extends model
{
/**
* Get holiday by id.
*
* @param int $id
* @access public
* @return object
*/
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 object
*/
public function getList($year = '', $type = 'all')
{
return $this->dao->select('*')->from(TABLE_HOLIDAY)
->where('1')
->beginIf(!empty($year))
->andWhere('year', true)->eq($year)
->orWhere('begin')->like("$year-%")
->orWhere('end')->like("$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.
*
* @access public
* @return int
*/
public function create()
{
$holiday = fixer::input('post')->get();
$holiday->year = substr($holiday->begin, 0, 4);
if(helper::isZeroDate($holiday->year)) return dao::$errors['begin'][] = sprintf($this->lang->error->date, $this->lang->holiday->begin);
if(helper::isZeroDate($holiday->end)) return dao::$errors['end'][] = sprintf($this->lang->error->date, $this->lang->holiday->end);
$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;
$beginDate = $this->post->begin;
$endDate = $this->post->end;
/* Update project. */
$this->updateProgramPlanDuration($beginDate, $endDate);
$this->updateProjectRealDuration($beginDate, $endDate);
/* Update task. */
$this->updateTaskPlanDuration($beginDate, $endDate);
$this->updateTaskRealDuration($beginDate, $endDate);
return $this->dao->lastInsertID();
}
/**
* Edit holiday.
*
* @param int $id
* @access public
* @return bool
*/
public function update($id)
{
$holiday = fixer::input('post')->get();
$holiday->year = substr($holiday->begin, 0, 4);
if(helper::isZeroDate($holiday->year)) return dao::$errors['begin'][] = sprintf($this->lang->error->date, $this->lang->holiday->begin);
if(helper::isZeroDate($holiday->end)) return dao::$errors['end'][] = sprintf($this->lang->error->date, $this->lang->holiday->end);
$this->dao->update(TABLE_HOLIDAY)
->data($holiday)
->autoCheck()
->batchCheck($this->config->holiday->require->edit, 'notempty')
->check('end', 'ge', $holiday->begin)
->where('id')->eq($id)
->exec();
if(!dao::isError())
{
$beginDate = $this->post->begin;
$endDate = $this->post->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('begin')->le($end)
->andWhere('end')->ge($begin)
->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) or empty($end) or $begin == '0000-00-00' or $end == '0000-00-00') return array();
$actualDays = array();
$currentDay = $begin;
$holidays = $this->getHolidays($begin, $end);
$workingDays = $this->getWorkingDays($begin, $end);
$weekend = isset($this->config->project->weekend) ? $this->config->project->weekend : 2;
/* When the start date and end date are the same. */
if($begin == $end)
{
if(in_array($begin, $workingDays)) return $actualDays[] = $begin;
if(in_array($begin, $holidays)) return $actualDays;
$w = date('w', strtotime($begin));
if($weekend == 2)
{
if($w == 0 or $w == 6) return $actualDays;
}
else
{
if($w == 0) return $actualDays;
}
$actualDays[] = $begin;
return $actualDays;
}
for($i = 0; $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($weekend == 2)
{
if($w == 0 or $w == 6) continue;
}
else
{
if($w == 0) continue;
}
$actualDays[] = $currentDay;
}
return $actualDays;
}
/**
* Get diff days.
*
* @param varchar $begin
* @param varchar $end
* @access public
* @return bool
*/
public function getDaysBetween($begin, $end)
{
$beginTime = strtotime($begin);
$endTime = strtotime($end);
$days = ($endTime - $beginTime) / 86400;
$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 plan 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('begin')->between($beginDate, $endDate)
->orWhere('end')->between($beginDate, $endDate)
->orWhere("(begin < '$beginDate' AND end > '$endDate')")
->andWhere('status')->ne('done')
->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('realBegan')->between($beginDate, $endDate)
->orWhere('realEnd')->between($beginDate, $endDate)
->orWhere("(realBegan < '$beginDate' AND realEnd > '$endDate')")
->andWhere('status')->ne('done')
->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',strtotime($task->finishedDate)));
$realDuration = count($realDuration);
$this->dao->update(TABLE_TASK)->set('realDuration')->eq($realDuration)->where('id')->eq($task->id)->exec();
}
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* The browse view file of holiday module of ZenTao.
*
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author chujilu <chujilu@cnezsoft.com>
* @package holiday
* @version $Id$
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainMenu' class='clearfix'>
<div class='pull-left btn-toolbar'>
<?php
echo html::a($this->createLink('holiday', 'browse'), '<span class="text">' . $lang->holiday->all . '</span>', '', "class='btn btn-link btn-active-text'");
?>
</div>
<div class='pull-right'>
<?php common::printLink('holiday', 'create', "", "<i class='icon icon-plus'> </i>" . $lang->holiday->create, '', "class='btn btn-primary iframe'", '', true)?>
</div>
</div>
<div id='mainContent' class='main-row fade in'>
<div class='side-col'>
<div class='panel panel-sm'>
<div class='panel-body'>
<ul class='tree' data-ride='tree' data-collapsed='true'>
<?php foreach($yearList as $year):?>
<li class='<?php echo $year == $currentYear ? 'active' : ''?>'>
<?php common::printLink('holiday', 'browse', "year=$year", $year);?>
</li>
<?php endforeach;?>
</ul>
</div>
</div>
</div>
<div class='main-col main-table'>
<?php if(!empty($holidays)):?>
<table class='table has-sort-head'>
<thead>
<tr>
<th class='w-150px'><?php echo $lang->holiday->name;?></th>
<th class='w-200px'><?php echo $lang->holiday->holiday;?></th>
<th class='w-80px'><?php echo $lang->holiday->type;?></th>
<th><?php echo $lang->holiday->desc;?></th>
<th class='w-100px'><?php echo $lang->actions;?></th>
</tr>
</thead>
<?php foreach($holidays as $holiday):?>
<tr>
<td><?php echo $holiday->name;?></td>
<td><?php echo formatTime($holiday->begin, DT_DATE1) . ' ~ ' . formatTime($holiday->end, DT_DATE1);?></td>
<td><?php echo zget($lang->holiday->typeList, $holiday->type);?></td>
<td><?php echo $holiday->desc;?></td>
<td class=" c-actions">
<?php common::printIcon('holiday', 'edit', "id=$holiday->id", $holiday, 'list', '', '', 'iframe', 'yes');?>
<?php common::printIcon('holiday', 'delete', "id=$holiday->id", $holiday, 'list', '', 'hiddenwin');?>
</td>
</tr>
<?php endforeach;?>
</table>
<?php else:?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->holiday->emptyTip;?></span>
</p>
</div>
<?php endif;?>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -0,0 +1,54 @@
<?php
/**
* The create view file of holiday module of ZenTao.
*
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author chujilu <chujilu@cnezsoft.com>
* @package holiday
* @version $Id$
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<style>form{margin: 40px 0px}</style>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<?php echo $lang->holiday->create;?>
</h2>
</div>
<form class='form-ajax' method='post'>
<table class='table table-form table-condensed'>
<tr>
<th class='w-120px'><?php echo $lang->holiday->type;?></th>
<td><?php echo html::radio('type', $lang->holiday->typeList, 'holiday');?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->begin;?></th>
<td><?php echo html::input('begin', '', "class='form-control form-date' required");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->end;?></th>
<td><?php echo html::input('end', '', "class='form-control form-date' required");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->name;?></th>
<td><?php echo html::input('name', '', "class='form-control' required");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->desc?></th>
<td><?php echo html::textarea('desc', '', "class='form-control'")?></td>
<td></td>
</tr>
<tr><th></th><td clospan='2'><?php echo baseHTML::submitButton();?></td></tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -0,0 +1,54 @@
<?php
/**
* The edit view file of holiday module of ZenTao.
*
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author chujilu <chujilu@cnezsoft.com>
* @package holiday
* @version $Id$
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<style>form{margin: 40px 0px}</style>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<?php echo $lang->holiday->edit;?>
</h2>
</div>
<form class='form-ajax' method='post'>
<table class='table table-form table-condensed'>
<tr>
<th class='w-120px'><?php echo $lang->holiday->type;?></th>
<td><?php echo html::radio('type', $lang->holiday->typeList, $holiday->type);?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->begin?></th>
<td><?php echo html::input('begin', $holiday->begin, "class='form-control form-date' required")?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->end?></th>
<td><?php echo html::input('end', $holiday->end, "class='form-control form-date' required")?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->name?></th>
<td><?php echo html::input('name', $holiday->name, "class='form-control' required")?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->desc?></th>
<td><?php echo html::textarea('desc', $holiday->desc, "class='form-control'")?></td>
<td></td>
</tr>
<tr><th></th><td clospan='2'><?php echo baseHTML::submitButton();?></td></tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>

View File

92
module/weekly/control.php Normal file
View File

@@ -0,0 +1,92 @@
<?php
/**
* The control file of weekly of ChanzhiEPS.
*
* @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Xiying Guan <guanxiying@xirangit.com>
* @package weekly
* @version $Id$
* @link http://www.zentao.net
*/
class weekly extends control
{
/**
* The construct function, load users.
*
* @access public
* @return void
*/
public function __construct()
{
parent::__construct();
$this->view->users = $this->loadModel('user')->getPairs('noletter');
}
/**
* Common action.
*
* @param int $projectID
* @access public
* @return void
*/
public function commonAction($projectID = 0)
{
$this->loadModel('project')->setMenu($projectID);
}
/**
* Index
*
* @param int $projectID
* @param string $date
* @access public
* @return void
*/
public function index($projectID = 0, $date = '')
{
$this->commonAction($projectID);
if(!$date) $date = helper::today();
$date = date('Y-m-d', strtotime($date));
$this->view->title = $this->lang->weekly->common;
$this->view->pv = $this->weekly->getPV($projectID, $date);
$this->view->ev = $this->weekly->getEV($projectID, $date);
$this->view->ac = $this->weekly->getAC($projectID, $date);
$this->view->sv = $this->weekly->getSV($this->view->ev, $this->view->pv);
$this->view->cv = $this->weekly->getCV($this->view->ev, $this->view->ac);
$this->view->project = $this->loadModel('project')->getByID($projectID);
$this->view->weekSN = $this->weekly->getWeekSN($this->view->project->begin, $date);
$this->view->monday = $this->weekly->getThisMonday($date);
$this->view->lastDay = $this->weekly->getLastDay($date);
$this->view->staff = $this->weekly->getStaff($projectID, $date);
$this->view->finished = $this->weekly->getFinished($projectID, $date);
$this->view->postponed = $this->weekly->getPostponed($projectID, $date);
$this->view->nextWeek = $this->weekly->getTasksOfNextWeek($projectID, $date);
$this->view->workload = $this->weekly->getWorkloadByType($projectID, $date);
$this->weekly->save($projectID, $date);
$this->lang->modulePageNav = $this->weekly->getPageNav($this->view->project, $date);
$this->display();
}
/**
* ComputeWeekly
*
* @access public
* @return void
*/
public function computeWeekly()
{
$projects = $this->dao->select('id, name')->from(TABLE_PROJECT)
->where('deleted')->eq(0)
->andWhere('type')->eq('project')
->fetchPairs();
$date = helper::today();
foreach($projects as $projectID => $project) $this->weekly->save($projectID, $date);
}
}

39
module/weekly/lang/de.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
/**
* The weekly module lang file of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青島易軟天創網絡科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package weekly
* @version $Id
* @link http://www.zentao.net
*/
$lang->weekly->common = 'Project Weekly';
$lang->weekly->index = 'Weekly Overview';
$lang->weekly->progress = 'Progress';
$lang->weekly->workload = 'Workload';
$lang->weekly->total = 'Total';
$lang->weekly->reportTtitle = 'Project: % s Weekly (Week % s)';
$lang->weekly->summary = 'Project Progress';
$lang->weekly->finished = 'Work finished this week (100% completed work)';
$lang->weekly->postponed = 'Work unfinished this week';
$lang->weekly->nextWeek = 'Work planned for next week';
$lang->weekly->workloadByType = 'Workload Summary';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = 'Project Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'The number of men in this week';
$lang->weekly->weekDesc = 'Week % s (% s ~% s)';
$lang->weekly->progress = 'Progress of the project';
$lang->weekly->analysisResult = 'Analysis';
$lang->weekly->cost = 'Project Cost';
$lang->weekly->pv = 'Planned Value(PV)';
$lang->weekly->ev = 'Earned Value(EV)';
$lang->weekly->ac = 'Actual Cost(AC)';
$lang->weekly->sv = 'Schedule Variance(SV%)';
$lang->weekly->cv = 'Cost Variance(CV%)';

39
module/weekly/lang/en.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
/**
* The weekly module lang file of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青島易軟天創網絡科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package weekly
* @version $Id
* @link http://www.zentao.net
*/
$lang->weekly->common = 'Project Weekly';
$lang->weekly->index = 'Weekly Overview';
$lang->weekly->progress = 'Progress';
$lang->weekly->workload = 'Workload';
$lang->weekly->total = 'Total';
$lang->weekly->reportTtitle = 'Project: % s Weekly (Week % s)';
$lang->weekly->summary = 'Project Progress';
$lang->weekly->finished = 'Work finished this week (100% completed work)';
$lang->weekly->postponed = 'Work unfinished this week';
$lang->weekly->nextWeek = 'Work planned for next week';
$lang->weekly->workloadByType = 'Workload Summary';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = 'Project Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'The number of men in this week';
$lang->weekly->weekDesc = 'Week % s (% s ~% s)';
$lang->weekly->progress = 'Progress of the project';
$lang->weekly->analysisResult = 'Analysis';
$lang->weekly->cost = 'Project Cost';
$lang->weekly->pv = 'Planned Value(PV)';
$lang->weekly->ev = 'Earned Value(EV)';
$lang->weekly->ac = 'Actual Cost(AC)';
$lang->weekly->sv = 'Schedule Variance(SV%)';
$lang->weekly->cv = 'Cost Variance(CV%)';

39
module/weekly/lang/fr.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
/**
* The weekly module lang file of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青島易軟天創網絡科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package weekly
* @version $Id
* @link http://www.zentao.net
*/
$lang->weekly->common = 'Project Weekly';
$lang->weekly->index = 'Weekly Overview';
$lang->weekly->progress = 'Progress';
$lang->weekly->workload = 'Workload';
$lang->weekly->total = 'Total';
$lang->weekly->reportTtitle = 'Project: % s Weekly (Week % s)';
$lang->weekly->summary = 'Project Progress';
$lang->weekly->finished = 'Work finished this week (100% completed work)';
$lang->weekly->postponed = 'Work unfinished this week';
$lang->weekly->nextWeek = 'Work planned for next week';
$lang->weekly->workloadByType = 'Workload Summary';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = 'Project Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'The number of men in this week';
$lang->weekly->weekDesc = 'Week % s (% s ~% s)';
$lang->weekly->progress = 'Progress of the project';
$lang->weekly->analysisResult = 'Analysis';
$lang->weekly->cost = 'Project Cost';
$lang->weekly->pv = 'Planned Value(PV)';
$lang->weekly->ev = 'Earned Value(EV)';
$lang->weekly->ac = 'Actual Cost(AC)';
$lang->weekly->sv = 'Schedule Variance(SV%)';
$lang->weekly->cv = 'Cost Variance(CV%)';

39
module/weekly/lang/vi.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
/**
* The weekly module lang file of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青島易軟天創網絡科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package weekly
* @version $Id
* @link http://www.zentao.net
*/
$lang->weekly->common = 'Project Weekly';
$lang->weekly->index = 'Weekly Overview';
$lang->weekly->progress = 'Progress';
$lang->weekly->workload = 'Workload';
$lang->weekly->total = 'Total';
$lang->weekly->reportTtitle = 'Project: % s Weekly (Week % s)';
$lang->weekly->summary = 'Project Progress';
$lang->weekly->finished = 'Work finished this week (100% completed work)';
$lang->weekly->postponed = 'Work unfinished this week';
$lang->weekly->nextWeek = 'Work planned for next week';
$lang->weekly->workloadByType = 'Workload Summary';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = 'Project Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'The number of men in this week';
$lang->weekly->weekDesc = 'Week % s (% s ~% s)';
$lang->weekly->progress = 'Progress of the project';
$lang->weekly->analysisResult = 'Analysis';
$lang->weekly->cost = 'Project Cost';
$lang->weekly->pv = 'Planned Value(PV)';
$lang->weekly->ev = 'Earned Value(EV)';
$lang->weekly->ac = 'Actual Cost(AC)';
$lang->weekly->sv = 'Schedule Variance(SV%)';
$lang->weekly->cv = 'Cost Variance(CV%)';

View File

@@ -0,0 +1,39 @@
<?php
/**
* The weekly module lang file of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青島易軟天創網絡科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package weekly
* @version $Id
* @link http://www.zentao.net
*/
$lang->weekly->common = '项目周报';
$lang->weekly->index = '周报总览';
$lang->weekly->progress = '完成百分比';
$lang->weekly->workload = '工作量';
$lang->weekly->total = '合计';
$lang->weekly->reportTtitle = '项目: %s 周报(第 %s 周)';
$lang->weekly->summary = '项目进展状况';
$lang->weekly->finished = '本周工作完成情况100%完成的工作)';
$lang->weekly->postponed = '本周未完成工作';
$lang->weekly->nextWeek = '下周工作计划';
$lang->weekly->workloadByType = '工作量统计';
$lang->weekly->term = '报告周期';
$lang->weekly->project = '项目名称';
$lang->weekly->master = '项目经理 ';
$lang->weekly->staff = '本周投入人数';
$lang->weekly->weekDesc = '第 %s 周( %s ~ %s)';
$lang->weekly->progress = '项目当前进展状况';
$lang->weekly->analysisResult = '分析结果';
$lang->weekly->cost = '项目成本';
$lang->weekly->pv = '计划完成的工作(PV)';
$lang->weekly->ev = '实际完成的工作(EV)';
$lang->weekly->ac = '实际花费的成本(AC)';
$lang->weekly->sv = '进度偏差率(SV%)';
$lang->weekly->cv = '成本偏差率CV%';

View File

@@ -0,0 +1,39 @@
<?php
/**
* The weekly module lang file of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青島易軟天創網絡科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package weekly
* @version $Id
* @link http://www.zentao.net
*/
$lang->weekly->common = '項目周報';
$lang->weekly->index = '周報總覽';
$lang->weekly->progress = '完成百分比';
$lang->weekly->workload = '工作量';
$lang->weekly->total = '合計';
$lang->weekly->reportTtitle = '項目: %s 周報(第 %s 周)';
$lang->weekly->summary = '項目進展狀況';
$lang->weekly->finished = '本週工作完成情況100%完成的工作)';
$lang->weekly->postponed = '本週未完成工作';
$lang->weekly->nextWeek = '下周工作計劃';
$lang->weekly->workloadByType = '工作量統計';
$lang->weekly->term = '報告周期';
$lang->weekly->project = '項目名稱';
$lang->weekly->master = '項目經理 ';
$lang->weekly->staff = '本週投入人數';
$lang->weekly->weekDesc = '第 %s 周( %s ~ %s)';
$lang->weekly->progress = '項目當前進展狀況';
$lang->weekly->analysisResult = '分析結果';
$lang->weekly->cost = '項目成本';
$lang->weekly->pv = '計劃完成的工作(PV)';
$lang->weekly->ev = '實際完成的工作(EV)';
$lang->weekly->ac = '實際花費的成本(AC)';
$lang->weekly->sv = '進度偏差率(SV%)';
$lang->weekly->cv = '成本偏差率CV%';

511
module/weekly/model.php Normal file
View File

@@ -0,0 +1,511 @@
<?php
/**
* The model file of weekly module of ChanzhiEPS.
*
* @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Xiying Guan <guanxiying@xirangit.com>
* @package weekly
* @version $Id$
* @link http://www.zentao.net
*/
class weeklyModel extends model
{
/**
* GetPageNav
*
* @param int $project
* @param int $date
* @access public
* @return string
*/
public function getPageNav($project, $date)
{
$date = date('Ymd', strtotime($this->getThisMonday($date)));
$begin = $project->begin;
$weeks = $this->getWeekPairs($begin);
$current = zget($weeks, $date, '');
$selectHtml = "<div class='btn-group angle-btn'>";
$selectHtml .= html::a('###', $this->lang->weekly->common . $this->lang->colon . $project->name, '', "class='btn'");
$selectHtml .= '</div>';
$selectHtml .= "<div class='btn-group angle-btn'>";
$selectHtml .= "<div class='btn-group'>";
$selectHtml .= "<a data-toggle='dropdown' class='btn' title=$current>" . $current . " <span class='caret'></span></a>";
$selectHtml .= "<ul class='dropdown-menu'>";
foreach($weeks as $day => $title)
{
$selectHtml .= '<li>' . html::a(helper::createLink('weekly', 'index', "project={$project->id}&date=$day"), $title) . '</li>';
}
$selectHtml .='</ul></div></div>';
return $selectHtml;
}
/**
* GetWeekPairs
*
* @param int $begin
* @access public
* @return array
*/
public function getWeekPairs($begin)
{
$sn = $this->getWeekSN($begin, date('Y-m-d'));
$weeks = array();
for($i = 0; $i <= $sn; $i++)
{
$monday = $this->getThisMonday($begin);
$sunday = $this->getThisSunday($begin);
$begin = date('Y-m-d', strtotime("$begin +7 days"));
$key = date('Ymd', strtotime($monday));
$weeks[$key] = sprintf($this->lang->weekly->weekDesc, $i + 1, $monday, $sunday);
}
krsort($weeks);
return $weeks;
}
/**
* GetFromDB
*
* @param int $project
* @param int $date
* @access public
* @return object
*/
public function getFromDB($project, $date)
{
$monday = $this->getThisMonday($date);
return $this->dao->select('*')
->from(TABLE_WEEKLYREPORT)
->where('weekStart')->eq($monday)
->andWhere('project')->eq($project)
->fetch();
}
/**
* Save data.
*
* @param int $project
* @param int $date
* @access public
* @return void
*/
public function save($project, $date)
{
$report = new stdclass;
$report->pv = $this->getPV($project, $date);
$report->ev = $this->getEV($project, $date);
$report->ac = $this->getAC($project, $date);
$report->sv = $this->getSV($report->ev, $report->pv);
$report->cv = $this->getCV($report->ev, $report->ac);
$report->project = $project;
$report->weekStart = $this->getThisMonday($date);
$report->staff = $this->getStaff($project);
$report->workload = json_encode($this->getWorkloadByType($project, $date));
$this->dao->replace(TABLE_WEEKLYREPORT)->data($report)->exec();
}
/**
* GetWeekSN
*
* @param int $begin
* @param int $date
* @access public
* @return int
*/
public function getWeekSN($begin, $date)
{
return ceil((strtotime($date) - strtotime($begin)) / 7 / 86400);
}
/**
* Get monday for a date.
*
* @param int $date
* @access public
* @return date
*/
public function getThisMonday($date)
{
$day = date('w', strtotime($date));
if($day == 0) $day = 7;
$days = $day - 1;
return date('Y-m-d', strtotime("$date - $days days"));
}
/**
* GetThisSunday
*
* @param int $date
* @access public
* @return date
*/
public function getThisSunday($date)
{
$monday = $this->getThisMonday($date);
return date('Y-m-d', strtotime("$monday +6 days"));
}
/**
* GetLastDay
*
* @param int $date
* @access public
* @return string
*/
public function getLastDay($date)
{
$this->loadModel('project');
$weekend = zget($this->config->project, 'weekend', 2);
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$workdays = $this->loadModel('holiday')->getActualWorkingDays($monday, $sunday);
return end($workdays);
}
/**
* GetStaff
*
* @param int $project
* @param string $date
* @access public
* @return array
*/
public function getStaff($project, $date = '')
{
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$executions = $this->loadModel('execution')->getList($project, 'all', 'all', 0, 0, 0);
$executionIdList = array_keys($executions);
return $this->dao->select('count(distinct account) as count')
->from(TABLE_EFFORT)
->where('objectType')->eq('task')
->andWhere('execution')->in($executionIdList)
->andWhere('date')->ge($monday)
->andWhere('date')->le($sunday)
->fetch('count');
}
/**
* GetFinished
*
* @param int $project
* @param string $date
* @param int $pager
* @access public
* @return void
*/
public function getFinished($project, $date = '', $pager = null)
{
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$executions = $this->loadModel('execution')->getList($project, 'all', $status = 'all', $limit = 0, $productID = 0, $branch = 0);
$executionIdList = array_keys($executions);
$tasks = $this->dao->select('*')
->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere("(status='done' or closedReason= 'done')")
->andWhere('finishedDate')->ge($monday)
->andWhere('finishedDate')->le($sunday)
->fetchAll();
return $this->loadModel('task')->processTasks($tasks);
}
/**
* GetPostponed
*
* @param int $project
* @param string $date
* @access public
* @return void
*/
public function getPostponed($project, $date = '')
{
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$executions = $this->loadModel('execution')->getList($project, 'all', $status = 'all', $limit = 0, $productID = 0, $branch = 0);
$executionIdList = array_keys($executions);
$unFinished = $this->dao->select('*')
->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere('status')->in('wait,doing,pause')
->andWhere('deadline')->ge($monday)
->andWhere('deadline')->le($sunday)
->fetchAll('id');
$postponed = $this->dao->select('*')
->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere('finishedDate')->gt($nextMonday)
->andWhere('deadline')->ge($monday)
->andWhere('deadline')->lt($nextMonday)
->fetchAll('id');
$tasks = array_merge($unFinished, $postponed);
return $this->loadModel('task')->processTasks($tasks);
}
/**
* GetTasksOfNextWeek
*
* @param int $project
* @param string $date
* @access public
* @return void
*/
public function getTasksOfNextWeek($project, $date = '')
{
if(!$date) $date = date('Y-m-d');
$sunday = $this->getThisSunday($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$sencondMondy = date('Y-m-d', strtotime("$sunday +8 days"));
$executions = $this->loadModel('execution')->getList($project, 'all', $status = 'all', $limit = 0, $productID = 0, $branch = 0);
$executionIdList = array_keys($executions);
$tasks = $this->dao->select('*')
->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere("((deadline > '$nextMonday' and deadline < '$sencondMondy') or (estStarted > '$nextMonday' and estStarted < '$sencondMondy'))")
->fetchAll('id');
return $this->loadModel('task')->processTasks($tasks);
}
/**
* GetWorkloadByType
*
* @param int $project
* @param string $date
* @access public
* @return object
*/
public function getWorkloadByType($project, $date = '')
{
if(!$date) $date = date('Y-m-d');
$sunday = $this->getThisSunday($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$sencondMondy = date('Y-m-d', strtotime("$sunday +8 days"));
$executions = $this->loadModel('execution')->getList($project, 'all', $status = 'all', $limit = 0, $productID = 0, $branch = 0);
$executionIdList = array_keys($executions);
return $this->dao->select('type, sum(cast(estimate as decimal(10,2))) as workload')
->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->groupBy('type')
->fetchPairs();
}
/**
* GetPlanedTaskByWeek
*
* @param int $project
* @param string $date
* @access public
* @return array
*/
public function getPlanedTaskByWeek($project, $date = '')
{
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$nextMonday = date('Y-m-d', strtotime("$monday +7 days"));
$executions = $this->loadModel('execution')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $project);
$executionIdList = array_keys($executions);
return $this->dao->select('*')
->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere('deadline')->ge($monday)
->fetchAll('id');
}
/**
* GetPV
*
* @param int $project
* @param string $date
* @access public
* @return int
*/
public function getPV($projectID, $date = '')
{
$report = $this->getFromDB($projectID, $date);
if(!empty($report)) return $report->pv;
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$lastDay = $this->getLastDay($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$workdays = $this->loadModel('holiday')->getActualWorkingDays($monday, $sunday);
$executions = $this->loadModel('execution')->getList($projectID);
$executionIdList = array_keys($executions);
$tasks = $this->dao->select('*')->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere("(estStarted < '$nextMonday' or estStarted='0000-00-00')")
->fetchAll('id');
$PV = 0;
foreach($tasks as $task)
{
if($task->estStarted == '0000-00-00') $task->estStarted = date('Y-m-d', strtotime($task->openedDate));
if($task->deadline < $nextMonday)
{
$PV += $task->estimate;
continue;
}
$fullDays = $this->loadModel('holiday')->getActualWorkingDays($task->estStarted, $task->deadline);
$passedDays = $this->loadModel('holiday')->getActualWorkingDays($task->estStarted, $sunday);
if(empty($fullDays) or empty($passedDays) or empty($task->estimate)) continue;
$PV += count($passedDays) * $task->estimate / count($fullDays);
}
return round($PV, 2);
}
/**
* Get EV data.
*
* @param int $projectID
* @param string $date
* @access public
* @return int
*/
public function getEV($projectID, $date = '')
{
$report = $this->getFromDB($projectID, $date);
if(!empty($report)) return $report->ev;
$executions = $this->loadModel('execution')->getList($projectID);
$executionIdList = array_keys($executions);
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$lastDay = $this->getLastDay($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$tasks = $this->dao->select('*')
->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere('consumed')->gt(0)
->andWhere('status')->ne('cancel')
->fetchAll('id');
$EV = 0;
foreach($tasks as $task)
{
if($task->status == 'done' or $task->closedReason == 'done')
{
$EV += $task->estimate;
}
else
{
$task->progress = round($task->consumed / ($task->consumed + $task->left), 2) * 100;
$EV += $task->estimate * $task->progress / 100;
}
}
return round($EV, 2);
}
/**
* Get AC data.
*
* @param int $project
* @param string $date
* @access public
* @return int
*/
public function getAC($project, $date = '')
{
$report = $this->getFromDB($project, $date);
if(!empty($report)) return $report->ac;
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$nextMonday = date('Y-m-d', strtotime("$monday +7 days"));
$executions = $this->loadModel('execution')->getList($project, 'all', 'all', 0, 0, 0);
$executionIdList = array_keys($executions);
$AC = $this->dao->select('sum(consumed) as consumed')
->from(TABLE_EFFORT)
->where('objectType')->eq('task')
->andWhere('execution')->in($executionIdList)
->andWhere('date')->ge($monday)
->andWhere('date')->lt($nextMonday)
->fetch('consumed');
return round($AC, 2);
}
/**
* Get SV data.
*
* @param int $ev
* @param int $pv
* @access public
* @return int
*/
public function getSV($ev, $pv)
{
if($pv == 0) return 0;
$sv = -1 * (1- ($ev / $pv));
return number_format($sv * 100, 2);
}
/**
* GetCV
*
* @param int $ev
* @param int $ac
* @access public
* @return int
*/
public function getCV($ev, $ac)
{
if($ac == 0) return 0;
$cv = -1 * (1 - ($ev / $ac));
return number_format($cv * 100, 2);
}
/**
* GetTips
*
* @param string $type
* @param int $data
* @access public
* @return string
*/
public function getTips($type = 'progress', $data = 0)
{
$this->app->loadConfig('custom');
if($type == 'progress') $tipsConfig = isset($this->config->custom->SV->progressTip) ? $this->config->custom->SV->progressTip : '';
if($type == 'cost') $tipsConfig = isset($this->config->custom->CV->costTip) ? $this->config->custom->CV->costTip : '';
if(empty($tipsConfig)) return '';
$tipsConfig = json_decode($tipsConfig);
foreach($tipsConfig as $tipConfig)
{
if($tipConfig->min <= $data and $tipConfig->max >= $data) return $tipConfig->tip;
}
return '';
}
}

View File

@@ -0,0 +1,186 @@
<?php
/**
* The html template file of index method of index module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package ZenTaoPMS
* @version $Id: index.html.php 5094 2013-07-10 08:46:15Z chencongzhi520@gmail.com $
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainMenu" class="clearfix text-center">
<div id='mainContent' >
<div class='main-table'>
<table class='table table-bordered'>
<tr>
<td><?php echo $lang->weekly->term;?></td>
<td><?php echo $monday . ' ~ ' . $lastDay?></td>
<td><?php echo $lang->weekly->master;?></td>
<td><?php echo zget($users, $project->PM, '');?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->project;?></td>
<td><?php echo $project->name;?></td>
<td><?php echo $lang->weekly->staff;?></td>
<td><?php echo $staff;?></td>
</tr>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->summary;?></h4></div>
<table class='table table-bordered'>
<tr>
<td><?php echo $lang->weekly->progress;?></td>
<td></td>
<td><?php echo $lang->weekly->analysisResult;?></td>
<td></td>
</tr>
<tr>
<td><?php echo $lang->weekly->pv;?></td>
<td><?php echo $pv;?></td>
<td rowspan='4'><?php echo $lang->weekly->progress;?></td>
<td rowspan='4'><?php echo $this->weekly->getTips('progress', $sv);?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->ev;?></td>
<td><?php echo $ev;?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->ac;?></td>
<td><?php echo $ac;?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->sv;?></td>
<td><?php echo $sv ? $sv . '%' : '';?></td>
</tr>
<tr>
<td><?php echo $lang->weekly->cv;?></td>
<td><?php echo $cv ? $cv . '%' : '';?></td>
<td><?php echo $lang->weekly->cost;?></td>
<?php $projectCost = zget($this->config->custom, 'cost', 1);?>
<td><?php echo empty($projectCost) ? 0 : $ac * $projectCost;?></td>
</tr>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->finished;?></h4></div>
<table class='table has-sort-head table-fixed'>
<thead>
<tr>
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='text-left'><?php echo $lang->task->name;?></th>
<th class='text-left w-120px'><?php echo $lang->task->estStarted;?></th>
<th class='text-left w-120px'><?php echo $lang->task->deadline;?></th>
<th class='text-left w-120px'><?php echo $lang->task->realStarted;?></th>
<th class='text-left w-100px'><?php echo $lang->task->finishedBy;?></th>
</tr>
</thead>
<tbody>
<?php foreach($finished as $task):?>
<tr data-id='<?php echo $task->id ?>'>
<td class='c-id'>
<?php printf('%03d', $task->id);?>
</td>
<td class='text-left' title='<?php echo $task->name?>'>
<?php echo html::a($this->createLink('task', 'view', 'id=' . $task->id), $task->name); ?>
</td>
<td class='text-left'><?php echo $task->estStarted;?></td>
<td class='text-left'><?php echo $task->deadline;?></td>
<td class='text-left'><?php if(!helper::isZeroDate($task->realStarted)) echo substr($task->realStarted, 0, 11);?></td>
<td class='text-left'><?php echo zget($users, $task->finishedBy);?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->postponed;?></h4></div>
<table class='table has-sort-head table-fixed'>
<thead>
<tr>
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='text-left'><?php echo $lang->task->name;?></th>
<th class='text-left w-100px'><?php echo $lang->task->assignedTo;?></th>
<th class='text-left w-120px'><?php echo $lang->task->estStarted;?></th>
<th class='text-left w-120px'><?php echo $lang->task->deadline;?></th>
<th class='text-left w-120px'><?php echo $lang->task->realStarted;?></th>
<th class='text-left w-100px'><?php echo $lang->task->progress;?></th>
</tr>
</thead>
<tbody>
<?php foreach($postponed as $task):?>
<tr data-id='<?php echo $task->id ?>'>
<td class='c-id'>
<?php printf('%03d', $task->id);?>
</td>
<td class='text-left' title='<?php echo $task->name?>'>
<?php echo html::a($this->createLink('task', 'view', 'id=' . $task->id), $task->name); ?>
</td>
<td class='text-left'><?php echo zget($users, $task->assignedTo);?></td>
<td class='text-left'><?php echo $task->estStarted;?></td>
<td class='text-left'><?php echo $task->deadline;?></td>
<td class='text-left'><?php if(!helper::isZeroDate($task->realStarted)) echo substr($task->realStarted, 0, 11);?></td>
<td class='text-left'><?php echo $task->progress;?>%</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->nextWeek;?></h4></div>
<table class='table has-sort-head table-fixed'>
<thead>
<tr>
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='text-left'><?php echo $lang->task->name;?></th>
<th class='text-left w-100px'><?php echo $lang->task->assignedTo;?></th>
<th class='text-left w-120px'><?php echo $lang->task->estStarted;?></th>
<th class='text-left w-120px'><?php echo $lang->task->deadline;?></th>
</tr>
</thead>
<tbody>
<?php foreach($nextWeek as $task):?>
<tr data-id='<?php echo $task->id ?>'>
<td class='c-id'>
<?php printf('%03d', $task->id);?>
</td>
<td class='text-left' title='<?php echo $task->name?>'>
<?php echo html::a($this->createLink('task', 'view', 'id=' . $task->id), $task->name); ?>
</td>
<td class='text-left'><?php echo zget($users, $task->assignedTo);?></td>
<td class='text-left'><?php echo $task->estStarted;?></td>
<td class='text-left'><?php echo $task->deadline;?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='page-title'><h4><?php echo $lang->weekly->workloadByType;?></h4></div>
<table class='table has-sort-head table-fixed'>
<thead>
<tr>
<th><?php echo $lang->task->type;?></th>
<?php foreach($lang->task->typeList as $type => $name):?>
<?php if(!$name) continue;?>
<th><?php echo $name;?></th>
<?php endforeach;?>
<th><?php echo $lang->weekly->total;?></th>
</tr>
</thead>
<tbody class='sortable' id='taskTableList'>
<tr>
<th><?php echo $lang->weekly->workload;?></th>
<?php $total = 0;?>
<?php foreach($lang->task->typeList as $type => $name):?>
<?php if(!$name) continue;?>
<?php $worktimes = zget($workload, $type, 0);?>
<td><?php echo $worktimes;?></td>
<?php $total += $worktimes;?>
<?php if(!$name) continue;?>
<?php endforeach;?>
<td><?php echo $total;?></td>
</tr>
</tbody>
</table>
</div>
</div>
<style>
.main-table tbody>tr:nth-child(odd){ background-color:#fff;}
</style>
<?php include '../../common/view/footer.html.php';?>