diff --git a/be/app/Http/Controllers/SubTaskController.php b/be/app/Http/Controllers/SubTaskController.php index 98de214..44976ec 100644 --- a/be/app/Http/Controllers/SubTaskController.php +++ b/be/app/Http/Controllers/SubTaskController.php @@ -11,6 +11,8 @@ use App\Models\SubTask; use App\Models\User; use Carbon\Carbon; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Validator; class SubTaskController extends Controller @@ -412,8 +414,9 @@ class SubTaskController extends Controller $subtask->syncTimesheets($data['data']['timesheets']); } - // syncnutie timeblocks - if (isset($data['data']['timeblocks'])) { + // syncnutie timeblocks - PRE DRAFTY s viacerými zamestnancami NIE! + // Timeblocks pre drafty s employees sú uložené v draft_data, nie v tabuľke timeblocks + if (isset($data['data']['timeblocks']) && ! $isDraftWithMultipleEmployees) { $subtask->syncTimeblocks($data['data']['timeblocks']); } @@ -470,48 +473,74 @@ class SubTaskController extends Controller $mastertask = $draft->mastertask; $createdSubtasks = []; - // Vytvoríme subtask pre každého zamestnanca - foreach ($employees as $employee) { - $subtaskData = [ - 'user_id' => $employee['id'], - 'title' => $draft->title, - 'description' => $draft->description, - 'deadline' => $draft->deadline, - 'estimated_time' => $employee['duration'], - 'created_by' => $draft->created_by, - 'is_draft' => false, - 'draft_data' => null, - ]; + // Použijeme transakciu pre atomicitu operácie + try { + DB::beginTransaction(); - $newSubtask = $mastertask->subtasks()->create($subtaskData); + // Vytvoríme subtask pre každého zamestnanca + foreach ($employees as $employee) { + $subtaskData = [ + 'user_id' => $employee['id'], + 'title' => $draft->title, + 'description' => $draft->description, + 'deadline' => $draft->deadline, + 'estimated_time' => $employee['duration'], + 'created_by' => $draft->created_by, + 'is_draft' => false, + 'draft_data' => null, + ]; - // Sync timeblocks ak existujú - if (isset($employee['timeblocks']) && ! empty($employee['timeblocks'])) { - $newSubtask->syncTimeblocks($employee['timeblocks']); + $newSubtask = $mastertask->subtasks()->create($subtaskData); + + // Sync timeblocks ak existujú - DÔLEŽITÉ: odstránime ID aby sa vytvorili nové záznamy + if (isset($employee['timeblocks']) && ! empty($employee['timeblocks'])) { + $cleanTimeblocks = array_map(function ($timeblock) { + // Odstránime ID a sub_task_id, aby sa vytvorili nové záznamy + unset($timeblock['id']); + unset($timeblock['sub_task_id']); + return $timeblock; + }, $employee['timeblocks']); + $newSubtask->createTimeblocks($cleanTimeblocks); + } + + // Skopírujeme attachmenty z pôvodného draftu + foreach ($draft->attachments as $attachment) { + $newSubtask->attachments()->create([ + 'name' => $attachment->name, + 'path' => $attachment->path, + 'size' => $attachment->size, + 'type' => $attachment->type, + ]); + } + + $createdSubtasks[] = $newSubtask; } - // Skopírujeme attachmenty z pôvodného draftu - foreach ($draft->attachments as $attachment) { - $newSubtask->attachments()->create([ - 'name' => $attachment->name, - 'path' => $attachment->path, - 'size' => $attachment->size, - 'type' => $attachment->type, - ]); - } + // Zmažeme pôvodný draft + $draft->timeblocks()->delete(); + $draft->attachments()->delete(); // attachmenty sú už skopírované + $draft->delete(); - $createdSubtasks[] = $newSubtask; + DB::commit(); + + return response()->json([ + 'message' => 'Draft published successfully', + 'subtasks' => SubTaskResource::collection($createdSubtasks), + ], 201); + + } catch (\Exception $e) { + DB::rollBack(); + Log::error('Failed to publish draft: ' . $e->getMessage(), [ + 'draft_id' => $draft->id, + 'employees' => $employees, + 'exception' => $e, + ]); + + return response()->json([ + 'message' => 'Failed to publish draft. Please try again.', + 'error' => $e->getMessage(), + ], 500); } - - // Zmažeme pôvodný draft - $draft->timeblocks()->delete(); - $draft->attachments()->delete(); // attachmenty sú už skopírované - $draft->delete(); - - return response()->json([ - 'message' => 'Draft published successfully', - 'subtasks' => SubTaskResource::collection($createdSubtasks), - ], 201); } public function delete($id) diff --git a/be/app/Http/Resources/SubTaskResource.php b/be/app/Http/Resources/SubTaskResource.php index c667db9..078c6ce 100644 --- a/be/app/Http/Resources/SubTaskResource.php +++ b/be/app/Http/Resources/SubTaskResource.php @@ -44,6 +44,22 @@ class SubTaskResource extends JsonResource // Pre drafty pridáme employees dáta if ($this->is_draft && $this->draft_data) { $data['employees'] = $this->draft_data; + + // Agregované timeblocks zo všetkých zamestnancov pre kalendárne zobrazenie + $allDraftTimeblocks = []; + foreach ($this->draft_data as $employee) { + if (isset($employee['timeblocks']) && is_array($employee['timeblocks'])) { + foreach ($employee['timeblocks'] as $timeblock) { + $allDraftTimeblocks[] = [ + 'employee_id' => $employee['id'], + 'start' => $timeblock['start'] ?? null, + 'end' => $timeblock['end'] ?? null, + 'is_finished' => $timeblock['is_finished'] ?? false, + ]; + } + } + } + $data['all_draft_timeblocks'] = $allDraftTimeblocks; } return $data; diff --git a/be/app/Models/SubTask.php b/be/app/Models/SubTask.php index 518f379..451bbf7 100644 --- a/be/app/Models/SubTask.php +++ b/be/app/Models/SubTask.php @@ -84,21 +84,75 @@ class SubTask extends Model $this->touch(); } + /** + * Synchronizácia timeblocks - aktualizuje existujúce, vytvorí nové, zmaže nepoužité + */ public function syncTimeblocks(Array $timeblocks) { if (empty($timeblocks)) { return $this->timeblocks()->delete(); } - // pripravenie array na upsert - $timeblocks = array_map(function($item) { + + // Získame ID existujúcich timeblocks tohto subtasku + $existingIds = $this->timeblocks()->pluck('id')->toArray(); + + // Rozdelíme na existujúce (s ID) a nové (bez ID alebo s neexistujúcim ID) + $timeblocksToUpdate = []; + $timeblocksToCreate = []; + $receivedIds = []; + + foreach ($timeblocks as $item) { $item['sub_task_id'] = $this->id; - return $item; + + // Ak má ID a toto ID existuje v našich timeblocks, aktualizujeme + if (isset($item['id']) && in_array($item['id'], $existingIds)) { + $timeblocksToUpdate[] = $item; + $receivedIds[] = $item['id']; + } else { + // Nový timeblock - odstránime ID aby sa vytvoril nový záznam + unset($item['id']); + $timeblocksToCreate[] = $item; + } + } + + // Zmažeme timeblocks, ktoré neboli poslané z frontendu + $this->timeblocks()->whereNotIn('id', $receivedIds)->delete(); + + // Aktualizujeme existujúce + foreach ($timeblocksToUpdate as $timeblock) { + $this->timeblocks()->where('id', $timeblock['id'])->update([ + 'start' => $timeblock['start'], + 'end' => $timeblock['end'], + ]); + } + + // Vytvoríme nové + if (! empty($timeblocksToCreate)) { + $this->timeblocks()->createMany($timeblocksToCreate); + } + } + + /** + * Vytvorenie nových timeblocks - pre použitie pri publikovaní draftu + */ + public function createTimeblocks(Array $timeblocks) + { + if (empty($timeblocks)) { + return; + } + + $timeblocksToCreate = array_map(function($item) { + // Odstránime ID a sub_task_id pre istotu + unset($item['id']); + unset($item['sub_task_id']); + return [ + 'start' => $item['start'], + 'end' => $item['end'], + 'is_finished' => $item['is_finished'] ?? false, + ]; }, $timeblocks); - // zmazanie vykazov, ktore neboli poslane z frontendu - $this->timeblocks()->whereNotIn('id', collect($timeblocks)->pluck('id')->filter())->delete(); - - $this->timeblocks()->upsert($timeblocks, ['id']); + $this->timeblocks()->createMany($timeblocksToCreate); } public function deleteAttachments()