191 lines
7.0 KiB
PHP
191 lines
7.0 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Services\ProjectManagement;
|
||
|
|
|
||
|
|
use App\Models\Admin\AdminPmIssue;
|
||
|
|
use App\Models\Admin\AdminPmProject;
|
||
|
|
use App\Models\Admin\AdminPmTask;
|
||
|
|
use Illuminate\Support\Facades\DB;
|
||
|
|
|
||
|
|
class ImportService
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* JSON 데이터로 프로젝트, 작업, 이슈 일괄 생성
|
||
|
|
*/
|
||
|
|
public function importFromJson(array $data): array
|
||
|
|
{
|
||
|
|
return DB::transaction(function () use ($data) {
|
||
|
|
$result = [
|
||
|
|
'project' => null,
|
||
|
|
'tasks_count' => 0,
|
||
|
|
'issues_count' => 0,
|
||
|
|
];
|
||
|
|
|
||
|
|
// 1. 프로젝트 생성
|
||
|
|
$projectData = $data['project'];
|
||
|
|
$project = AdminPmProject::create([
|
||
|
|
'name' => $projectData['name'],
|
||
|
|
'description' => $projectData['description'] ?? null,
|
||
|
|
'status' => $projectData['status'] ?? AdminPmProject::STATUS_ACTIVE,
|
||
|
|
'start_date' => $projectData['start_date'] ?? null,
|
||
|
|
'end_date' => $projectData['end_date'] ?? null,
|
||
|
|
'created_by' => auth()->id(),
|
||
|
|
]);
|
||
|
|
$result['project'] = $project;
|
||
|
|
|
||
|
|
// 2. 작업 생성
|
||
|
|
$tasks = $data['tasks'] ?? [];
|
||
|
|
$sortOrder = 1;
|
||
|
|
|
||
|
|
foreach ($tasks as $taskData) {
|
||
|
|
$task = AdminPmTask::create([
|
||
|
|
'project_id' => $project->id,
|
||
|
|
'title' => $taskData['title'],
|
||
|
|
'description' => $taskData['description'] ?? null,
|
||
|
|
'status' => $taskData['status'] ?? AdminPmTask::STATUS_TODO,
|
||
|
|
'priority' => $taskData['priority'] ?? AdminPmTask::PRIORITY_MEDIUM,
|
||
|
|
'due_date' => $taskData['due_date'] ?? null,
|
||
|
|
'sort_order' => $sortOrder++,
|
||
|
|
'created_by' => auth()->id(),
|
||
|
|
]);
|
||
|
|
$result['tasks_count']++;
|
||
|
|
|
||
|
|
// 3. 작업별 이슈 생성
|
||
|
|
$issues = $taskData['issues'] ?? [];
|
||
|
|
foreach ($issues as $issueData) {
|
||
|
|
AdminPmIssue::create([
|
||
|
|
'project_id' => $project->id,
|
||
|
|
'task_id' => $task->id,
|
||
|
|
'title' => $issueData['title'],
|
||
|
|
'description' => $issueData['description'] ?? null,
|
||
|
|
'type' => $issueData['type'] ?? AdminPmIssue::TYPE_BUG,
|
||
|
|
'status' => $issueData['status'] ?? AdminPmIssue::STATUS_OPEN,
|
||
|
|
'created_by' => auth()->id(),
|
||
|
|
]);
|
||
|
|
$result['issues_count']++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $result;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 기존 프로젝트에 작업/이슈 추가
|
||
|
|
*/
|
||
|
|
public function importTasksToProject(int $projectId, array $tasks): array
|
||
|
|
{
|
||
|
|
return DB::transaction(function () use ($projectId, $tasks) {
|
||
|
|
$project = AdminPmProject::findOrFail($projectId);
|
||
|
|
|
||
|
|
$result = [
|
||
|
|
'project_id' => $projectId,
|
||
|
|
'tasks_count' => 0,
|
||
|
|
'issues_count' => 0,
|
||
|
|
];
|
||
|
|
|
||
|
|
$maxSortOrder = AdminPmTask::where('project_id', $projectId)->max('sort_order') ?? 0;
|
||
|
|
$sortOrder = $maxSortOrder + 1;
|
||
|
|
|
||
|
|
foreach ($tasks as $taskData) {
|
||
|
|
$task = AdminPmTask::create([
|
||
|
|
'project_id' => $project->id,
|
||
|
|
'title' => $taskData['title'],
|
||
|
|
'description' => $taskData['description'] ?? null,
|
||
|
|
'status' => $taskData['status'] ?? AdminPmTask::STATUS_TODO,
|
||
|
|
'priority' => $taskData['priority'] ?? AdminPmTask::PRIORITY_MEDIUM,
|
||
|
|
'due_date' => $taskData['due_date'] ?? null,
|
||
|
|
'sort_order' => $sortOrder++,
|
||
|
|
'created_by' => auth()->id(),
|
||
|
|
]);
|
||
|
|
$result['tasks_count']++;
|
||
|
|
|
||
|
|
$issues = $taskData['issues'] ?? [];
|
||
|
|
foreach ($issues as $issueData) {
|
||
|
|
AdminPmIssue::create([
|
||
|
|
'project_id' => $project->id,
|
||
|
|
'task_id' => $task->id,
|
||
|
|
'title' => $issueData['title'],
|
||
|
|
'description' => $issueData['description'] ?? null,
|
||
|
|
'type' => $issueData['type'] ?? AdminPmIssue::TYPE_BUG,
|
||
|
|
'status' => $issueData['status'] ?? AdminPmIssue::STATUS_OPEN,
|
||
|
|
'created_by' => auth()->id(),
|
||
|
|
]);
|
||
|
|
$result['issues_count']++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $result;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* JSON 샘플 템플릿 반환
|
||
|
|
*/
|
||
|
|
public function getSampleTemplate(): array
|
||
|
|
{
|
||
|
|
return [
|
||
|
|
'project' => [
|
||
|
|
'name' => '프로젝트명 (필수)',
|
||
|
|
'description' => '프로젝트 설명 (선택)',
|
||
|
|
'status' => 'active',
|
||
|
|
'start_date' => date('Y-m-d'),
|
||
|
|
'end_date' => date('Y-m-d', strtotime('+3 months')),
|
||
|
|
],
|
||
|
|
'tasks' => [
|
||
|
|
[
|
||
|
|
'title' => '작업 1 (필수)',
|
||
|
|
'description' => '작업 설명 (선택)',
|
||
|
|
'status' => 'todo',
|
||
|
|
'priority' => 'medium',
|
||
|
|
'due_date' => date('Y-m-d', strtotime('+1 week')),
|
||
|
|
'issues' => [
|
||
|
|
[
|
||
|
|
'title' => '이슈 1',
|
||
|
|
'description' => '이슈 설명',
|
||
|
|
'type' => 'bug',
|
||
|
|
'status' => 'open',
|
||
|
|
],
|
||
|
|
],
|
||
|
|
],
|
||
|
|
[
|
||
|
|
'title' => '작업 2',
|
||
|
|
'status' => 'todo',
|
||
|
|
'priority' => 'high',
|
||
|
|
],
|
||
|
|
],
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* JSON 유효성 검사 (FormRequest 전에 미리 체크)
|
||
|
|
*/
|
||
|
|
public function validateJsonStructure(array $data): array
|
||
|
|
{
|
||
|
|
$errors = [];
|
||
|
|
|
||
|
|
if (! isset($data['project'])) {
|
||
|
|
$errors[] = 'project 객체가 필요합니다.';
|
||
|
|
} elseif (! isset($data['project']['name']) || empty($data['project']['name'])) {
|
||
|
|
$errors[] = 'project.name은 필수입니다.';
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isset($data['tasks']) && is_array($data['tasks'])) {
|
||
|
|
foreach ($data['tasks'] as $index => $task) {
|
||
|
|
if (! isset($task['title']) || empty($task['title'])) {
|
||
|
|
$errors[] = "tasks[{$index}].title은 필수입니다.";
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isset($task['issues']) && is_array($task['issues'])) {
|
||
|
|
foreach ($task['issues'] as $issueIndex => $issue) {
|
||
|
|
if (! isset($issue['title']) || empty($issue['title'])) {
|
||
|
|
$errors[] = "tasks[{$index}].issues[{$issueIndex}].title은 필수입니다.";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $errors;
|
||
|
|
}
|
||
|
|
}
|