Merge branch 'main' of bitbucket.org:studiotem/jandl-taskmanager-app

This commit is contained in:
Matej Glasnák committed 2026-02-03 04:19:01 +01:00
commit 44d315c961
3 files changed
+125 -18

No files matched your search

+48 -11
View File
@@ -11,6 +11,8 @@ use App\Models\SubTask;
use App\Models\User; use App\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
class SubTaskController extends Controller class SubTaskController extends Controller
@@ -412,8 +414,9 @@ class SubTaskController extends Controller
$subtask->syncTimesheets($data['data']['timesheets']); $subtask->syncTimesheets($data['data']['timesheets']);
} }
// syncnutie timeblocks // syncnutie timeblocks - PRE DRAFTY s viacerými zamestnancami NIE!
if (isset($data['data']['timeblocks'])) { // 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']); $subtask->syncTimeblocks($data['data']['timeblocks']);
} }
@@ -430,7 +433,8 @@ class SubTaskController extends Controller
*/ */
private function publishDraftWithMultipleEmployees(SubTask $draft, Request $request) private function publishDraftWithMultipleEmployees(SubTask $draft, Request $request)
{ {
$employees = $draft->draft_data; // Použij employees z requestu ak existujú, inak fallback na draft_data z DB
$employees = $request->all()['data']['employees'] ?? $draft->draft_data;
// Ak je employees pole prázdne, zlyhaj // Ak je employees pole prázdne, zlyhaj
if (empty($employees)) { if (empty($employees)) {
@@ -450,15 +454,16 @@ class SubTaskController extends Controller
// Ak duration nie je nastavený, vypočítaj ho z timeblocks // Ak duration nie je nastavený, vypočítaj ho z timeblocks
if (! isset($employee['duration']) || $employee['duration'] === null) { if (! isset($employee['duration']) || $employee['duration'] === null) {
if (isset($employee['timeblocks']) && ! empty($employee['timeblocks'])) { if (isset($employee['timeblocks']) && ! empty($employee['timeblocks'])) {
$totalDuration = 0; $totalDurationMinutes = 0;
foreach ($employee['timeblocks'] as $timeblock) { foreach ($employee['timeblocks'] as $timeblock) {
if (isset($timeblock['start']) && isset($timeblock['end'])) { if (isset($timeblock['start']) && isset($timeblock['end'])) {
$start = Carbon::parse($timeblock['start']); $start = Carbon::parse($timeblock['start']);
$end = Carbon::parse($timeblock['end']); $end = Carbon::parse($timeblock['end']);
$totalDuration += $end->diffInMinutes($start); $totalDurationMinutes += $end->diffInMinutes($start);
} }
} }
$employees[$key]['duration'] = $totalDuration; // Konvertuj na hodiny (frontend očakáva hodiny)
$employees[$key]['duration'] = $totalDurationMinutes / 60;
} else { } else {
return response()->json([ return response()->json([
'message' => 'Draft cannot be published. Each employee must have duration or timeblocks.', 'message' => 'Draft cannot be published. Each employee must have duration or timeblocks.',
@@ -470,13 +475,23 @@ class SubTaskController extends Controller
$mastertask = $draft->mastertask; $mastertask = $draft->mastertask;
$createdSubtasks = []; $createdSubtasks = [];
// Použijeme transakciu pre atomicitu operácie
try {
DB::beginTransaction();
// Získame aktuálne hodnoty z requestu (ak existujú), inak fallback na draft
$requestData = $request->all()['data'] ?? [];
$title = $requestData['title'] ?? $draft->title;
$description = $requestData['description'] ?? $draft->description;
$deadline = $requestData['deadline'] ?? $draft->deadline;
// Vytvoríme subtask pre každého zamestnanca // Vytvoríme subtask pre každého zamestnanca
foreach ($employees as $employee) { foreach ($employees as $employee) {
$subtaskData = [ $subtaskData = [
'user_id' => $employee['id'], 'user_id' => $employee['id'],
'title' => $draft->title, 'title' => $title,
'description' => $draft->description, 'description' => $description,
'deadline' => $draft->deadline, 'deadline' => $deadline,
'estimated_time' => $employee['duration'], 'estimated_time' => $employee['duration'],
'created_by' => $draft->created_by, 'created_by' => $draft->created_by,
'is_draft' => false, 'is_draft' => false,
@@ -485,9 +500,15 @@ class SubTaskController extends Controller
$newSubtask = $mastertask->subtasks()->create($subtaskData); $newSubtask = $mastertask->subtasks()->create($subtaskData);
// Sync timeblocks ak existujú // Sync timeblocks ak existujú - DÔLEŽITÉ: odstránime ID aby sa vytvorili nové záznamy
if (isset($employee['timeblocks']) && ! empty($employee['timeblocks'])) { if (isset($employee['timeblocks']) && ! empty($employee['timeblocks'])) {
$newSubtask->syncTimeblocks($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 // Skopírujeme attachmenty z pôvodného draftu
@@ -508,10 +529,26 @@ class SubTaskController extends Controller
$draft->attachments()->delete(); // attachmenty sú už skopírované $draft->attachments()->delete(); // attachmenty sú už skopírované
$draft->delete(); $draft->delete();
DB::commit();
return response()->json([ return response()->json([
'message' => 'Draft published successfully', 'message' => 'Draft published successfully',
'subtasks' => SubTaskResource::collection($createdSubtasks), 'subtasks' => SubTaskResource::collection($createdSubtasks),
], 201); ], 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);
}
} }
public function delete($id) public function delete($id)
+16
View File
@@ -44,6 +44,22 @@ class SubTaskResource extends JsonResource
// Pre drafty pridáme employees dáta // Pre drafty pridáme employees dáta
if ($this->is_draft && $this->draft_data) { if ($this->is_draft && $this->draft_data) {
$data['employees'] = $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; return $data;
+61 -7
View File
@@ -84,21 +84,75 @@ class SubTask extends Model
$this->touch(); $this->touch();
} }
/**
* Synchronizácia timeblocks - aktualizuje existujúce, vytvorí nové, zmaže nepoužité
*/
public function syncTimeblocks(Array $timeblocks) public function syncTimeblocks(Array $timeblocks)
{ {
if (empty($timeblocks)) { if (empty($timeblocks)) {
return $this->timeblocks()->delete(); 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; $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); }, $timeblocks);
// zmazanie vykazov, ktore neboli poslane z frontendu $this->timeblocks()->createMany($timeblocksToCreate);
$this->timeblocks()->whereNotIn('id', collect($timeblocks)->pluck('id')->filter())->delete();
$this->timeblocks()->upsert($timeblocks, ['id']);
} }
public function deleteAttachments() public function deleteAttachments()