|
|
@@ -995,7 +995,7 @@ class ItemService extends Service
|
|
|
return [true, $list];
|
|
|
}
|
|
|
|
|
|
- public function itemRule(&$data, $user, $is_add = true){
|
|
|
+ public function itemRule1(&$data, $user, $is_add = true){
|
|
|
$data['top_depart_id'] = $user['top_depart_id'];
|
|
|
if(empty($data['code'])) return [false, '项目编码不能为空'];
|
|
|
if(empty($data['title'])) return [false, '项目名称不能为空'];
|
|
|
@@ -1077,6 +1077,107 @@ class ItemService extends Service
|
|
|
return [true, ''];
|
|
|
}
|
|
|
|
|
|
+ public function itemRule(&$data, $user, $is_add = true)
|
|
|
+ {
|
|
|
+ $data['top_depart_id'] = $user['top_depart_id'];
|
|
|
+
|
|
|
+ // 1. 基础必填校验
|
|
|
+ if (empty($data['code'])) return [false, '项目编码不能为空'];
|
|
|
+ if (empty($data['title'])) return [false, '项目名称不能为空'];
|
|
|
+ if (empty($data['state'])) return [false, '项目状态不能为空'];
|
|
|
+ if (!isset(Item::State_Type[$data['state']])) return [false, '项目状态不存在'];
|
|
|
+ if (!empty($data['item_attribute']) && !isset(Item::Item_Attribute[$data['item_attribute']])) return [false, '项目属性不存在'];
|
|
|
+
|
|
|
+ // 2. 时间校验
|
|
|
+ if (!empty($data['start_time'])) $data['start_time'] = $this->changeDateToDate($data['start_time']);
|
|
|
+ if (!empty($data['end_time'])) $data['end_time'] = $this->changeDateToDate($data['end_time'], true);
|
|
|
+
|
|
|
+ if (!empty($data['start_time']) && !empty($data['end_time'])) {
|
|
|
+ if ($data['start_time'] > $data['end_time']) return [false, '开始时间不能大于结束时间'];
|
|
|
+
|
|
|
+ $isMonthEnd = date('j', $data['end_time']) == date('t', $data['end_time']);
|
|
|
+ if (!$isMonthEnd) return [false, '项目结束日期必须是当月最后一天'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 预算校验
|
|
|
+ if (isset($data['budget'])) {
|
|
|
+ $res = $this->checkNumber($data['budget'], 2, 'non-negative');
|
|
|
+ if (!$res['valid']) return [false, '预算:' . $res['error']];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 列表类数据校验(人员与设备)
|
|
|
+ if (empty($data['man_list'])) return [false, '人员不能为空'];
|
|
|
+ list($status, $msg) = $this->validateListRelation($data['man_list'], $data['top_depart_id'], '人员', 'data_id');
|
|
|
+ if (!$status) return [false, $msg];
|
|
|
+
|
|
|
+ if (empty($data['device_list'])) return [false, '设备不能为空'];
|
|
|
+ list($status, $msg) = $this->validateListRelation($data['device_list'], $data['top_depart_id'], '设备', 'data_id');
|
|
|
+ if (!$status) return [false, $msg];
|
|
|
+
|
|
|
+
|
|
|
+ // 5. 核心业务逻辑校验(新增 vs 编辑)
|
|
|
+ $codeQuery = Item::where('code', $data['code'])
|
|
|
+ ->where('top_depart_id', $data['top_depart_id'])
|
|
|
+ ->where('del_time', 0);
|
|
|
+
|
|
|
+ if ($is_add) {
|
|
|
+ // 新增:只需查重
|
|
|
+ if ($codeQuery->exists()) return [false, '项目编码已存在'];
|
|
|
+ } else {
|
|
|
+ // 编辑:深度校验状态
|
|
|
+ if (empty($data['id'])) return [false, 'ID不能为空'];
|
|
|
+
|
|
|
+ $item = Item::where('id', $data['id'])->where('del_time', 0)->first();
|
|
|
+ if (empty($item)) return [false, '项目不存在或已被删除'];
|
|
|
+
|
|
|
+ // 状态拦截
|
|
|
+ if ($item->state == Item::TYPE_THREE) return [false, '项目已完结,操作失败'];
|
|
|
+
|
|
|
+ // 统一权限和审核状态拦截
|
|
|
+ if ($item->approval_state == Item::TYPE_MINUS_ONE) {
|
|
|
+ $errorMsg = $user['select_tree_type'] ? '审核中不允许编辑' : '项目审核中,操作失败';
|
|
|
+ return [false, $errorMsg];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 试图完结项目时,校验下游节点
|
|
|
+ if ($data['state'] == Item::TYPE_THREE) {
|
|
|
+ $hasUnfinishedNode = ItemNode::where('del_time', 0)
|
|
|
+ ->where('item_id', $data['id'])
|
|
|
+ ->where('state', '<>', ItemNode::TYPE_THREE)
|
|
|
+ ->exists();
|
|
|
+ if ($hasUnfinishedNode) return [false, '项目下存在节点未完结'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查重排除自身
|
|
|
+ if ($codeQuery->where('id', '<>', $data['id'])->exists()) {
|
|
|
+ return [false, '项目编码已存在'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 变更及草稿判定
|
|
|
+ $return = $this->checkIsChanged($data, $user);
|
|
|
+ if (is_array($return)) {
|
|
|
+ return $return; // 直接返回 checkIsChanged 的错误结果
|
|
|
+ } elseif ($return) {
|
|
|
+ $data['draft'] = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 辅助方法:提取出来的公共列表和排重校验
|
|
|
+ */
|
|
|
+ private function validateListRelation(&$list, $topDepartId, $fieldTitle, $keyName = 'data_id')
|
|
|
+ {
|
|
|
+ foreach ($list as $key => $value) {
|
|
|
+ if (empty($value['type'])) return [false, "{$fieldTitle}类型不能为空"];
|
|
|
+ if (empty($value[$keyName])) return [false, "{$fieldTitle}不能为空"];
|
|
|
+ $list[$key]['top_depart_id'] = $topDepartId;
|
|
|
+ }
|
|
|
+ return $this->checkArrayRepeat($list, $keyName, $fieldTitle);
|
|
|
+ }
|
|
|
+
|
|
|
public function fillData($data){
|
|
|
if(empty($data['data'])) return $data;
|
|
|
|
|
|
@@ -1777,7 +1878,7 @@ class ItemService extends Service
|
|
|
return [true, $list];
|
|
|
}
|
|
|
|
|
|
- public function itemNodeRule(&$data, $user, $is_add = true){
|
|
|
+ public function itemNodeRule1(&$data, $user, $is_add = true){
|
|
|
$data['top_depart_id'] = $user['top_depart_id'];
|
|
|
if(empty($data['item_id'])) return [false, '项目ID不能为空'];
|
|
|
$item = Item::where('id', $data['item_id'])->where('del_time',0)->first();
|
|
|
@@ -1873,6 +1974,94 @@ class ItemService extends Service
|
|
|
return [true, ''];
|
|
|
}
|
|
|
|
|
|
+ public function itemNodeRule(&$data, $user, $is_add = true)
|
|
|
+ {
|
|
|
+ $data['top_depart_id'] = $user['top_depart_id'];
|
|
|
+
|
|
|
+ // 1. 关联项目及状态基础校验
|
|
|
+ if (empty($data['item_id'])) return [false, '项目ID不能为空'];
|
|
|
+
|
|
|
+ $project = Item::where('id', $data['item_id'])->where('del_time', 0)->first();
|
|
|
+ if (empty($project)) return [false, '项目不存在或已被删除'];
|
|
|
+ if ($project->state == Item::TYPE_THREE) return [false, '项目已完结,操作失败'];
|
|
|
+
|
|
|
+ // 2. 节点基础字段校验
|
|
|
+ if (empty($data['title'])) return [false, '节点名称不能为空'];
|
|
|
+ if (!isset($data['node_weight'])) return [false, '节点权重不存在'];
|
|
|
+
|
|
|
+ list($status, $res) = $this->checkWeight($data['node_weight'], '节点权重');
|
|
|
+ if (!$status) return [false, $res];
|
|
|
+
|
|
|
+ // 3. 时间及边界校验
|
|
|
+ if (!empty($data['start_time'])) $data['start_time'] = $this->changeDateToDate($data['start_time']);
|
|
|
+ if (!empty($data['end_time'])) $data['end_time'] = $this->changeDateToDate($data['end_time'], true);
|
|
|
+
|
|
|
+ if (!empty($data['start_time']) && !empty($data['end_time'])) {
|
|
|
+ if ($data['start_time'] > $data['end_time']) return [false, '开始时间不能大于结束时间'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验节点时间是否超出项目大周期边界
|
|
|
+ if (!empty($data['start_time']) && $project->start_time > 0 && $data['start_time'] < $project->start_time) {
|
|
|
+ return [false, '节点开始时间不能早于项目开始时间:' . date('Y-m-d', $project->start_time)];
|
|
|
+ }
|
|
|
+ if (!empty($data['end_time']) && $project->end_time > 0 && $data['end_time'] > $project->end_time) {
|
|
|
+ return [false, '节点结束时间不能晚于项目结束时间:' . date('Y-m-d', $project->end_time)];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 列表类数据校验(复用公共辅助方法)
|
|
|
+ if (!empty($data['man_list'])) {
|
|
|
+ list($status, $msg) = $this->validateListRelation($data['man_list'], $data['top_depart_id'], '人员', 'data_id');
|
|
|
+ if (!$status) return [false, $msg];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!empty($data['device_list'])) {
|
|
|
+ list($status, $msg) = $this->validateListRelation($data['device_list'], $data['top_depart_id'], '设备', 'data_id');
|
|
|
+ if (!$status) return [false, $msg];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 核心业务逻辑校验(新增 vs 编辑)
|
|
|
+ $titleQuery = ItemNode::where('item_id', $data['item_id'])
|
|
|
+ ->where('top_depart_id', $data['top_depart_id'])
|
|
|
+ ->where('title', $data['title'])
|
|
|
+ ->where('del_time', 0);
|
|
|
+
|
|
|
+ if ($is_add) {
|
|
|
+ // 新增:同项目下名称查重
|
|
|
+ if ($titleQuery->exists()) return [false, '该项目下节点名称已存在'];
|
|
|
+ } else {
|
|
|
+ // 编辑:深度状态及下游校验
|
|
|
+ if (empty($data['id'])) return [false, 'ID不能为空'];
|
|
|
+
|
|
|
+ $node = ItemNode::where('id', $data['id'])->where('del_time', 0)->first();
|
|
|
+ if (empty($node)) return [false, '项目节点不存在或已被删除'];
|
|
|
+ if ($node->approval_state == ItemNode::TYPE_MINUS_ONE) return [false, '节点审核中,操作失败'];
|
|
|
+
|
|
|
+ // 试图完结节点时,校验下游任务
|
|
|
+ if (isset($data['state']) && $data['state'] == ItemNode::TYPE_THREE) {
|
|
|
+ $hasUnfinishedMission = ItemNodeMission::where('del_time', 0)
|
|
|
+ ->where('item_node_id', $data['id'])
|
|
|
+ ->where('state', '<>', ItemNodeMission::TYPE_THREE)
|
|
|
+ ->exists();
|
|
|
+ if ($hasUnfinishedMission) return [false, '节点下存在任务未完结'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 编辑查重:排除自身
|
|
|
+ if ($titleQuery->where('id', '<>', $data['id'])->exists()) {
|
|
|
+ return [false, '该项目下节点名称已存在'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 变更及草稿判定
|
|
|
+ $return = $this->checkItemNodeIsChanged($data, $user);
|
|
|
+ if (is_array($return)) {
|
|
|
+ return $return;
|
|
|
+ } elseif ($return) {
|
|
|
+ $data['draft'] = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
public function fillNodeData($data){
|
|
|
if(empty($data['data'])) return $data;
|
|
|
|
|
|
@@ -2574,7 +2763,7 @@ class ItemService extends Service
|
|
|
return [true, $model];
|
|
|
}
|
|
|
|
|
|
- public function itemNodeMissionRule(&$data, $user, $is_add = true){
|
|
|
+ public function itemNodeMissionRule1(&$data, $user, $is_add = true){
|
|
|
$data['top_depart_id'] = $user['top_depart_id'];
|
|
|
if(empty($data['item_node_id']) && empty($data['parent_item_node_mission_id'])) return [false, '节点与父级任务不能同时为空'];
|
|
|
if(empty($data['item_node_id'])) return [false, '项目节点ID不能为空'];
|
|
|
@@ -2672,6 +2861,108 @@ class ItemService extends Service
|
|
|
return [true, ''];
|
|
|
}
|
|
|
|
|
|
+ public function itemNodeMissionRule(&$data, $user, $is_add = true)
|
|
|
+ {
|
|
|
+ $data['top_depart_id'] = $user['top_depart_id'];
|
|
|
+
|
|
|
+ // 1. 父级任务与关联节点前置校验
|
|
|
+ if (!empty($data['parent_item_node_mission_id'])) {
|
|
|
+ $parentMission = ItemNodeMission::where('id', $data['parent_item_node_mission_id'])
|
|
|
+ ->where('del_time', 0)
|
|
|
+ ->first();
|
|
|
+ if (empty($parentMission)) return [false, '父任务不存在或已被删除'];
|
|
|
+
|
|
|
+ // 如果前端没传节点 ID,自动继承父任务的节点 ID
|
|
|
+ if (empty($data['item_node_id'])) {
|
|
|
+ $data['item_node_id'] = $parentMission->item_node_id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (empty($data['item_node_id'])) return [false, '项目节点ID不能为空'];
|
|
|
+
|
|
|
+ // 2. 关联节点及状态校验
|
|
|
+ $node = ItemNode::where('id', $data['item_node_id'])->where('del_time', 0)->first();
|
|
|
+ if (empty($node)) return [false, '项目节点不存在或已被删除'];
|
|
|
+ if ($node->state == ItemNode::TYPE_THREE) return [false, '节点已完结,操作失败'];
|
|
|
+ $data['item_id'] = $node->item_id;
|
|
|
+
|
|
|
+ // 3. 任务基础字段与权重校验
|
|
|
+ if (empty($data['title'])) return [false, '任务名称不能为空'];
|
|
|
+ if (!isset($data['mission_weight'])) return [false, '任务权重不存在'];
|
|
|
+
|
|
|
+ list($status, $res) = $this->checkWeight($data['mission_weight'], '任务权重');
|
|
|
+ if (!$status) return [false, $res];
|
|
|
+
|
|
|
+ // 4. 时间及大周期边界校验
|
|
|
+ if (!empty($data['start_time'])) $data['start_time'] = $this->changeDateToDate($data['start_time']);
|
|
|
+ if (!empty($data['end_time'])) $data['end_time'] = $this->changeDateToDate($data['end_time'], true);
|
|
|
+
|
|
|
+ if (!empty($data['start_time']) && !empty($data['end_time'])) {
|
|
|
+ if ($data['start_time'] > $data['end_time']) return [false, '开始时间不能大于结束时间'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验任务时间是否超出节点大周期
|
|
|
+ if (!empty($data['start_time']) && $node->start_time > 0 && $data['start_time'] < $node->start_time) {
|
|
|
+ return [false, '任务开始时间不能早于项目节点开始时间:' . date('Y-m-d', $node->start_time)];
|
|
|
+ }
|
|
|
+ if (!empty($data['end_time']) && $node->end_time > 0 && $data['end_time'] > $node->end_time) {
|
|
|
+ return [false, '任务结束时间不能晚于项目节点结束时间:' . date('Y-m-d', $node->end_time)];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 人员与设备列表校验
|
|
|
+ if (!empty($data['man_list'])) {
|
|
|
+ list($status, $msg) = $this->validateListRelation($data['man_list'], $data['top_depart_id'], '人员', 'data_id');
|
|
|
+ if (!$status) return [false, $msg];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!empty($data['device_list'])) {
|
|
|
+ list($status, $msg) = $this->validateListRelation($data['device_list'], $data['top_depart_id'], '设备', 'data_id');
|
|
|
+ if (!$status) return [false, $msg];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6. 核心重名与状态校验(新增 vs 编辑)
|
|
|
+ $titleQuery = ItemNodeMission::where('item_node_id', $data['item_node_id'])
|
|
|
+ ->where('top_depart_id', $data['top_depart_id'])
|
|
|
+ ->where('title', $data['title'])
|
|
|
+ ->where('del_time', 0);
|
|
|
+
|
|
|
+ if ($is_add) {
|
|
|
+ // 新增:同节点下任务重名校验
|
|
|
+ if ($titleQuery->exists()) return [false, '该项目节点下任务名称已存在'];
|
|
|
+ } else {
|
|
|
+ // 编辑:状态、下游子任务校验
|
|
|
+ if (empty($data['id'])) return [false, 'ID不能为空'];
|
|
|
+
|
|
|
+ $mission = ItemNodeMission::where('id', $data['id'])->where('del_time', 0)->first();
|
|
|
+ if (empty($mission)) return [false, '项目节点下任务不存在或已被删除'];
|
|
|
+ if ($mission->approval_state == ItemNodeMission::TYPE_MINUS_ONE) return [false, '任务审核中,操作失败'];
|
|
|
+
|
|
|
+ // 试图完结任务时,校验其下面的子任务是否全部完结
|
|
|
+ if (isset($data['state']) && $data['state'] == ItemNodeMission::TYPE_THREE) {
|
|
|
+ $hasUnfinishedSubMission = ItemNodeMission::where('del_time', 0)
|
|
|
+ ->where('parent_item_node_mission_id', $data['id'])
|
|
|
+ ->where('state', '<>', ItemNodeMission::TYPE_THREE)
|
|
|
+ ->exists();
|
|
|
+ if ($hasUnfinishedSubMission) return [false, '任务下存在子任务未完结'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 编辑查重:排除自身
|
|
|
+ if ($titleQuery->where('id', '<>', $data['id'])->exists()) {
|
|
|
+ return [false, '该项目节点下任务名称已存在'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 变更及草稿判定
|
|
|
+ $return = $this->checkItemNodeMissionIsChanged($data, $user);
|
|
|
+ if (is_array($return)) {
|
|
|
+ return $return;
|
|
|
+ } elseif ($return) {
|
|
|
+ $data['draft'] = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
public function checkItemNodeMissionIsChanged($data, $user) {
|
|
|
// 1. 获取旧数据
|
|
|
list($status, $oldData) = $this->itemNodeMissionDetail($data, $user);
|