tenant admin startseite schicker gestaltet und super-admin und tenant admin (filament) aufgesplittet.
Es gibt nun task collections und vordefinierte tasks für alle. Onboarding verfeinert und webseite-carousel gefixt (logging später entfernen!)
This commit is contained in:
161
app/Services/Tenant/TaskCollectionImportService.php
Normal file
161
app/Services/Tenant/TaskCollectionImportService.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Tenant;
|
||||
|
||||
use App\Models\Event;
|
||||
use App\Models\Task;
|
||||
use App\Models\TaskCollection;
|
||||
use Illuminate\Database\DatabaseManager;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
class TaskCollectionImportService
|
||||
{
|
||||
public function __construct(private readonly DatabaseManager $db)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{collection: TaskCollection, created_task_ids: array<int>, attached_task_ids: array<int>}
|
||||
*/
|
||||
public function import(TaskCollection $collection, Event $event): array
|
||||
{
|
||||
if ($collection->tenant_id && $collection->tenant_id !== $event->tenant_id) {
|
||||
throw new RuntimeException('Task collection is not accessible for this tenant.');
|
||||
}
|
||||
|
||||
$collection->loadMissing('tasks');
|
||||
|
||||
return $this->db->transaction(function () use ($collection, $event) {
|
||||
$tenantId = $event->tenant_id;
|
||||
|
||||
$targetCollection = $this->resolveTenantCollection($collection, $tenantId);
|
||||
|
||||
$createdTaskIds = [];
|
||||
$attachedTaskIds = [];
|
||||
|
||||
foreach ($collection->tasks as $task) {
|
||||
$tenantTask = $this->resolveTenantTask($task, $targetCollection, $tenantId);
|
||||
|
||||
if ($tenantTask->wasRecentlyCreated) {
|
||||
$createdTaskIds[] = $tenantTask->id;
|
||||
}
|
||||
|
||||
if (! $tenantTask->assignedEvents()->where('event_id', $event->id)->exists()) {
|
||||
$tenantTask->assignedEvents()->attach($event->id);
|
||||
$attachedTaskIds[] = $tenantTask->id;
|
||||
}
|
||||
}
|
||||
|
||||
$event->taskCollections()->syncWithoutDetaching([
|
||||
$targetCollection->id => ['sort_order' => $targetCollection->position ?? 0],
|
||||
]);
|
||||
|
||||
return [
|
||||
'collection' => $targetCollection->fresh(),
|
||||
'created_task_ids' => $createdTaskIds,
|
||||
'attached_task_ids' => $attachedTaskIds,
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
protected function resolveTenantCollection(TaskCollection $collection, int $tenantId): TaskCollection
|
||||
{
|
||||
if ($collection->tenant_id === $tenantId) {
|
||||
return $collection;
|
||||
}
|
||||
|
||||
$existing = TaskCollection::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('source_collection_id', $collection->id)
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
return $existing;
|
||||
}
|
||||
|
||||
return TaskCollection::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'source_collection_id' => $collection->id,
|
||||
'event_type_id' => $collection->event_type_id,
|
||||
'slug' => $this->buildCollectionSlug($collection->slug, $tenantId),
|
||||
'name_translations' => $collection->name_translations,
|
||||
'description_translations' => $collection->description_translations,
|
||||
'is_default' => false,
|
||||
'position' => $collection->position,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function resolveTenantTask(Task $templateTask, TaskCollection $targetCollection, int $tenantId): Task
|
||||
{
|
||||
if ($templateTask->tenant_id === $tenantId) {
|
||||
if ($templateTask->collection_id !== $targetCollection->id) {
|
||||
$templateTask->update(['collection_id' => $targetCollection->id]);
|
||||
}
|
||||
|
||||
return $templateTask;
|
||||
}
|
||||
|
||||
$sourceId = $templateTask->source_task_id ?: $templateTask->id;
|
||||
|
||||
$existing = Task::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('source_task_id', $sourceId)
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
$existing->update([
|
||||
'collection_id' => $targetCollection->id,
|
||||
'source_collection_id' => $templateTask->source_collection_id ?: $targetCollection->source_collection_id ?: $targetCollection->id,
|
||||
]);
|
||||
|
||||
return tap($existing)->refresh();
|
||||
}
|
||||
|
||||
$slugBase = $templateTask->slug ?: ($templateTask->title['en'] ?? $templateTask->title['de'] ?? 'task');
|
||||
$slug = $this->buildTaskSlug($slugBase);
|
||||
|
||||
$cloned = Task::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'slug' => $slug,
|
||||
'emotion_id' => $templateTask->emotion_id,
|
||||
'event_type_id' => $templateTask->event_type_id,
|
||||
'title' => $templateTask->title,
|
||||
'description' => $templateTask->description,
|
||||
'example_text' => $templateTask->example_text,
|
||||
'due_date' => null,
|
||||
'is_completed' => false,
|
||||
'priority' => $templateTask->priority,
|
||||
'collection_id' => $targetCollection->id,
|
||||
'difficulty' => $templateTask->difficulty,
|
||||
'sort_order' => $templateTask->sort_order,
|
||||
'is_active' => true,
|
||||
'source_task_id' => $sourceId,
|
||||
'source_collection_id' => $templateTask->source_collection_id ?: $templateTask->collection_id,
|
||||
]);
|
||||
|
||||
return $cloned;
|
||||
}
|
||||
|
||||
protected function buildCollectionSlug(?string $slug, int $tenantId): string
|
||||
{
|
||||
$base = Str::slug(($slug ?: 'collection') . '-' . $tenantId);
|
||||
|
||||
do {
|
||||
$candidate = $base . '-' . Str::random(4);
|
||||
} while (TaskCollection::where('slug', $candidate)->exists());
|
||||
|
||||
return $candidate;
|
||||
}
|
||||
|
||||
protected function buildTaskSlug(string $base): string
|
||||
{
|
||||
$slugBase = Str::slug($base) ?: 'task';
|
||||
|
||||
do {
|
||||
$candidate = $slugBase . '-' . Str::random(6);
|
||||
} while (Task::where('slug', $candidate)->exists());
|
||||
|
||||
return $candidate;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user