cqp 3 周之前
父節點
當前提交
2ced6ac359
共有 1 個文件被更改,包括 294 次插入3 次删除
  1. 294 3
      app/Service/ItemService.php

+ 294 - 3
app/Service/ItemService.php

@@ -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);