diff --git a/module/programplan/control.php b/module/programplan/control.php
index 50a764b310..5ac061522c 100644
--- a/module/programplan/control.php
+++ b/module/programplan/control.php
@@ -149,7 +149,12 @@ class programplan extends control
if($_POST)
{
$this->programplan->create($projectID, $this->productID, $planID);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+ if(dao::isError())
+ {
+ $errors = dao::getError();
+ if(isset($errors['message'])) return $this->send(array('result' => 'fail', 'message' => $errors));
+ if(!isset($errors['message'])) return $this->send(array('result' => 'fail', 'callback' => array('name' => 'addRowErrors', 'params' => array($errors))));
+ }
$locate = $this->createLink('project', 'execution', "status=all&projectID=$projectID&orderBy=order_asc&productID=$productID");
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locate));
diff --git a/module/programplan/css/create.css b/module/programplan/css/create.css
new file mode 100644
index 0000000000..eb0ae52c08
--- /dev/null
+++ b/module/programplan/css/create.css
@@ -0,0 +1 @@
+#planForm tr td {vertical-align: top;}
diff --git a/module/programplan/js/create.js b/module/programplan/js/create.js
index a026b67c73..241610d959 100644
--- a/module/programplan/js/create.js
+++ b/module/programplan/js/create.js
@@ -1,3 +1,11 @@
+$(function()
+{
+ $('input').on('change', function()
+ {
+ $(this).removeClass('has-error');
+ $(this).closest('td').find('.text-danger.help-text').remove();
+ });
+});
/**
* Add item to create view of programplan.
*
@@ -30,3 +38,44 @@ function deleteItem(obj)
if($('#planForm .table tbody').children().length < 2) return false;
$(obj).closest('tr').remove();
}
+
+/**
+ * Add row errors.
+ *
+ * @param array $rowErrors
+ * @access public
+ * @return void
+ */
+function addRowErrors(rowErrors)
+{
+ var errorFieldID, errorTip, errorHTML;
+ $('.text-danger.help-text').remove();
+ $('input').removeClass('has-error');
+ var index = 0;
+ var alterError = '';
+ $('input[name^=names]').each(function()
+ {
+ if($(this).val() == '') return true;
+
+ if(typeof rowErrors[index] == 'object')
+ {
+ for(var errorField in rowErrors[index])
+ {
+ $errorTD = $(this).closest('tr').find('input[name^=' + errorField + ']').closest('td');
+ errorTip = rowErrors[index][errorField];
+ errorHTML = '
' + errorTip + '
';
+ $errorTD.append(errorHTML);
+ $errorTD.find('input').addClass('has-error');
+ }
+ }
+ if(typeof rowErrors['percent'] == 'string')
+ {
+ errorFieldID = $(this).closest('tr').find('input[name^=percent]').attr('id');
+ errorHTML = '' + rowErrors['percent'] + '
';
+ $('#' + errorFieldID).closest('td').append(errorHTML);
+ $('#' + errorFieldID).closest('td').find('input').addClass('has-error');
+ }
+
+ index ++;
+ });
+}
diff --git a/module/programplan/model.php b/module/programplan/model.php
index f2f6e8a069..129bbf63aa 100755
--- a/module/programplan/model.php
+++ b/module/programplan/model.php
@@ -708,22 +708,12 @@ class programplanModel extends model
$parentACL = $parentStage->acl;
}
- if(!$this->checkNameUnique($names))
- {
- $this->app->loadLang('execution');
- dao::$errors['message'][] = empty($type) ? $this->lang->programplan->error->sameName : str_replace($this->lang->execution->stage, '', $this->lang->programplan->error->sameName);;
- return false;
- }
+ $names = array_filter($names);
+ $sameNames = array_diff_assoc($names, array_unique($names));
$project = $this->loadModel('project')->getByID($projectID);
$setCode = (!isset($this->config->setCode) or $this->config->setCode == 1) ? true : false;
- $checkCode = $this->checkCodeUnique($codes, isset($planIDList) ? $planIDList : '');
- if($setCode and $checkCode !== true)
- {
- if($checkCode) dao::$errors['message'][] = sprintf($this->lang->error->repeat, $this->lang->execution->code, $checkCode);
- else dao::$errors['message'][] = $this->lang->programplan->error->sameCode;
- return false;
- }
+ $sameCodes = $this->checkCodeUnique($codes, isset($planIDList) ? $planIDList : '');
$datas = array();
foreach($names as $key => $name)
@@ -756,68 +746,61 @@ class programplanModel extends model
$totalPercent = 0;
$totalDevType = 0;
$milestone = 0;
- foreach($datas as $plan)
+ foreach($datas as $index => $plan)
{
+ if(!empty($sameNames) and in_array($plan->name, $sameNames)) dao::$errors[$index]['name'] = empty($type) ? $this->lang->programplan->error->sameName : str_replace($this->lang->execution->stage, '', $this->lang->programplan->error->sameName);
+ if($setCode and $sameCodes !== true and !empty($sameCodes) and in_array($plan->code, $sameCodes)) dao::$errors[$index]['code'] = sprintf($this->lang->error->repeat, $this->lang->execution->code, $plan->code);
+
if($plan->percent and !preg_match("/^[0-9]+(.[0-9]{1,3})?$/", $plan->percent))
{
- dao::$errors['message'][] = $this->lang->programplan->error->percentNumber;
- return false;
+ dao::$errors[$index]['percent'] = $this->lang->programplan->error->percentNumber;
}
if(helper::isZeroDate($plan->begin))
{
- dao::$errors['message'][] = $this->lang->programplan->emptyBegin;
- return false;
+ dao::$errors[$index]['begin'] = $this->lang->programplan->emptyBegin;
}
- if(!validater::checkDate($plan->begin))
+ if(!validater::checkDate($plan->begin) and empty(dao::$errors[$index]['begin']))
{
- dao::$errors['message'][] = $this->lang->programplan->checkBegin;
- return false;
+ dao::$errors[$index]['begin'] = $this->lang->programplan->checkBegin;
}
if(helper::isZeroDate($plan->end))
{
- dao::$errors['message'][] = $this->lang->programplan->emptyEnd;
- return false;
+ dao::$errors[$index]['end'] = $this->lang->programplan->emptyEnd;
}
- if(!validater::checkDate($plan->end))
+ if(!validater::checkDate($plan->end) and empty(dao::$errors[$index]['end']))
{
- dao::$errors['message'][] = $this->lang->programplan->checkEnd;
- return false;
+ dao::$errors[$index]['end'] = $this->lang->programplan->checkEnd;
}
- if(!helper::isZeroDate($plan->end) and $plan->end < $plan->begin)
+ if(!helper::isZeroDate($plan->end) and $plan->end < $plan->begin and empty(dao::$errors[$index]['begin']))
{
- dao::$errors['message'][] = $this->lang->programplan->error->planFinishSmall;
- return false;
+ dao::$errors[$index]['end'] = $this->lang->programplan->error->planFinishSmall;
}
if(isset($parentStage) and ($plan->end > $parentStage->end || $plan->begin < $parentStage->begin))
{
- dao::$errors['message'][] = $this->lang->programplan->error->parentDuration;
- return false;
+ if($plan->begin < $parentStage->begin and empty(dao::$errors[$index]['begin'])) dao::$errors[$index]['begin'] = $this->lang->programplan->error->parentDuration;
+ if($plan->end < $parentStage->end and empty(dao::$errors[$index]['end'])) dao::$errors[$index]['end'] = $this->lang->programplan->error->parentDuration;
}
- if($plan->begin < $project->begin)
+ if($plan->begin < $project->begin and empty(dao::$errors[$index]['begin']))
{
- dao::$errors['message'][] = sprintf($this->lang->programplan->errorBegin, $project->begin);
- return false;
+ dao::$errors[$index]['begin'] = sprintf($this->lang->programplan->errorBegin, $project->begin);
}
- if(!helper::isZeroDate($plan->end) and $plan->end > $project->end)
+ if(!helper::isZeroDate($plan->end) and $plan->end > $project->end and empty(dao::$errors[$index]['end']))
{
- dao::$errors['message'][] = sprintf($this->lang->programplan->errorEnd, $project->end);
- return false;
+ dao::$errors[$index]['end'] = sprintf($this->lang->programplan->errorEnd, $project->end);
}
if(helper::isZeroDate($plan->begin)) $plan->begin = '';
if(helper::isZeroDate($plan->end)) $plan->end = '';
if($setCode and empty($plan->code))
{
- dao::$errors['message'][] = sprintf($this->lang->error->notempty, $this->lang->execution->code);
- return false;
+ dao::$errors[$index]['code'] = sprintf($this->lang->error->notempty, $this->lang->execution->code);
}
foreach(explode(',', $this->config->programplan->create->requiredFields) as $field)
{
$field = trim($field);
if($field and empty($plan->$field))
{
- dao::$errors['message'][] = sprintf($this->lang->error->notempty, $this->lang->programplan->$field);
- return false;
+ dao::$errors[$index][$field] = sprintf($this->lang->error->notempty, $this->lang->programplan->$field);
}
}
@@ -827,7 +810,8 @@ class programplanModel extends model
if($plan->milestone) $milestone = 1;
}
- if($totalPercent > 100) return dao::$errors['message'][] = $this->lang->programplan->error->percentOver;
+ if($totalPercent > 100) dao::$errors['percent'] = $this->lang->programplan->error->percentOver;
+ if(dao::isError()) return false;
$this->loadModel('action');
$this->loadModel('user');
@@ -1350,7 +1334,7 @@ class programplanModel extends model
->andWhere('deleted')->eq('0')
->andWhere('code')->in($codes)
->beginIF($planIDList)->andWhere('id')->notin($planIDList)->fi()
- ->fetch('code');
+ ->fetchPairs('code');
return $code ? $code : true;
}
diff --git a/module/programplan/view/create.html.php b/module/programplan/view/create.html.php
index 4724742571..a45e7032bf 100644
--- a/module/programplan/view/create.html.php
+++ b/module/programplan/view/create.html.php
@@ -275,91 +275,5 @@ var options = {
reverse: true,
}
$('#planForm tbody.sortable').sortable(options);
-
-$('#planForm').submit(function()
-{
- /* Clear all error messages. */
- $('input[name^=begin]').each(function()
- {
- var beginDateID = $(this).attr('id');
- if(beginDateID == 'begin%i%') return;
-
- var endDateID = beginDateID.replace('begin', 'end');
- $('#help' + beginDateID).remove();
- $('#help' + endDateID).remove();
- });
-
- var submitForm = true;
- $('input[name^=begin]').each(function()
- {
- var beginDate = $(this).val();
- var beginDateID = $(this).attr('id');
- if(beginDateID == 'begin%i%') return;
-
- var nameID = beginDateID.replace('begin', 'names');
- var endDateID = beginDateID.replace('begin', 'end');
- $('#help' + beginDateID).remove();
- $('#help' + endDateID).remove();
-
- /* Invalid data is skipped. */
- var nameVal = $('#' + nameID).val()
- if(!nameVal) return;
-
- /* Check if the begin date is empty. */
- if(!beginDate)
- {
- submitForm = false;
- var emptyBeginHtml = '' + emptyBegin + '
';
- $(this).after(emptyBeginHtml);
- alert(emptyBegin);
- return false;
- }
-
- var endDate = $('#' + endDateID).val();
- if(!endDate)
- {
- submitForm = false;
- var emptyEndHtml = '' + emptyEnd + '
';
- $('#' + endDateID).after(emptyEndHtml);
- alert(emptyEnd);
- return false;
- }
-
- if(endDate < beginDate)
- {
- submitForm = false;
- var emptyEndHtml = '' + planFinishSmall + '
';
- $('#' + endDateID).after(emptyEndHtml);
- alert(planFinishSmall);
- return false;
- }
-
- if(beginDate < projectBeginDate)
- {
- submitForm = false;
- var errorBeginTip = errorBegin.replace('%s', projectBeginDate);
- var errorBeginHtml = '' + errorBeginTip + '
';
- $('#' + beginDateID).after(errorBeginHtml);
- alert(errorBeginTip);
- return false;
- }
-
- if(endDate > projectEndDate)
- {
- submitForm = false;
- var errorEndTip = errorEnd.replace('%s', projectEndDate);
- var errorEndHtml = '' + errorEndTip + '
';
- $('#' + endDateID).after(errorEndHtml);
- alert(errorEndTip);
- return false;
- }
- });
-
- if(!submitForm)
- {
- setTimeout(function(){$('#submit').removeAttr('disabled')}, 500);
- return false;
- }
-});