coupon code system eingeführt. coupons werden vom super admin gemanaged. coupons werden mit paddle synchronisiert und dort validiert. plus: einige mobil-optimierungen im tenant admin pwa.
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Marketing;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Package;
|
||||
use App\Services\Coupons\CouponService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CouponPreviewController extends Controller
|
||||
{
|
||||
public function __construct(private readonly CouponService $coupons) {}
|
||||
|
||||
public function __invoke(Request $request): JsonResponse
|
||||
{
|
||||
$data = $request->validate([
|
||||
'code' => ['required', 'string', 'max:64'],
|
||||
'package_id' => ['required', 'integer', 'exists:packages,id'],
|
||||
]);
|
||||
|
||||
$package = Package::findOrFail($data['package_id']);
|
||||
|
||||
if (! $package->paddle_price_id) {
|
||||
throw ValidationException::withMessages([
|
||||
'code' => __('marketing.coupon.errors.package_not_configured'),
|
||||
]);
|
||||
}
|
||||
|
||||
$tenant = Auth::user()?->tenant;
|
||||
|
||||
try {
|
||||
$preview = $this->coupons->preview($data['code'], $package, $tenant);
|
||||
} catch (ValidationException $exception) {
|
||||
Log::warning('Coupon preview denied', [
|
||||
'code' => $data['code'],
|
||||
'package_id' => $package->id,
|
||||
'tenant_id' => $tenant?->id,
|
||||
'errors' => $exception->errors(),
|
||||
]);
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
Log::info('Coupon preview success', [
|
||||
'code' => $preview['coupon']->code,
|
||||
'package_id' => $package->id,
|
||||
'tenant_id' => $tenant?->id,
|
||||
'discount' => $preview['pricing']['discount'] ?? null,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'coupon' => [
|
||||
'id' => $preview['coupon']->id,
|
||||
'code' => $preview['coupon']->code,
|
||||
'type' => $preview['coupon']->type?->value,
|
||||
'amount' => (float) $preview['coupon']->amount,
|
||||
'currency' => $preview['coupon']->currency,
|
||||
'description' => $preview['coupon']->description,
|
||||
'expires_at' => $preview['coupon']->ends_at?->toIso8601String(),
|
||||
'is_stackable' => $preview['coupon']->is_stackable,
|
||||
],
|
||||
'pricing' => $preview['pricing'],
|
||||
'package' => [
|
||||
'id' => $package->id,
|
||||
'name' => $package->name,
|
||||
'price' => (float) $package->price,
|
||||
'currency' => $package->currency ?? 'EUR',
|
||||
],
|
||||
'source' => $preview['source'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ use App\Http\Requests\Tenant\EmotionStoreRequest;
|
||||
use App\Http\Requests\Tenant\EmotionUpdateRequest;
|
||||
use App\Http\Resources\Tenant\EmotionResource;
|
||||
use App\Models\Emotion;
|
||||
use App\Models\Tenant;
|
||||
use App\Support\TenantRequestResolver;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
@@ -16,7 +18,7 @@ class EmotionController extends Controller
|
||||
{
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$tenantId = $request->tenant->id;
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
$query = Emotion::query()
|
||||
->whereNull('tenant_id')
|
||||
@@ -41,9 +43,10 @@ class EmotionController extends Controller
|
||||
public function store(EmotionStoreRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->validated();
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
$payload = [
|
||||
'tenant_id' => $request->tenant->id,
|
||||
'tenant_id' => $tenantId,
|
||||
'name' => $this->localizeValue($data['name']),
|
||||
'description' => $this->localizeValue($data['description'] ?? null, allowNull: true),
|
||||
'icon' => $data['icon'] ?? 'lucide-smile',
|
||||
@@ -70,7 +73,9 @@ class EmotionController extends Controller
|
||||
|
||||
public function update(EmotionUpdateRequest $request, Emotion $emotion): JsonResponse
|
||||
{
|
||||
if ($emotion->tenant_id && $emotion->tenant_id !== $request->tenant->id) {
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($emotion->tenant_id && $emotion->tenant_id !== $tenantId) {
|
||||
abort(403, 'Emotion gehört nicht zu diesem Tenant.');
|
||||
}
|
||||
|
||||
@@ -139,6 +144,7 @@ class EmotionController extends Controller
|
||||
|
||||
if (is_string($value) && $value !== '') {
|
||||
$locale = app()->getLocale() ?: 'de';
|
||||
|
||||
return [$locale => $value];
|
||||
}
|
||||
|
||||
@@ -149,9 +155,14 @@ class EmotionController extends Controller
|
||||
{
|
||||
$normalized = ltrim($color, '#');
|
||||
if (strlen($normalized) === 6) {
|
||||
return '#' . strtolower($normalized);
|
||||
return '#'.strtolower($normalized);
|
||||
}
|
||||
|
||||
return '#6366f1';
|
||||
}
|
||||
|
||||
protected function currentTenant(Request $request): Tenant
|
||||
{
|
||||
return TenantRequestResolver::resolve($request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
$taken = Tenant::where('custom_domain', $domain)
|
||||
->where('id', '!=', $request->tenant->id)
|
||||
->where('id', '!=', $this->resolveTenant($request)->id)
|
||||
->exists();
|
||||
|
||||
return response()->json([
|
||||
|
||||
@@ -6,17 +6,19 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\Tenant\TaskCollectionResource;
|
||||
use App\Models\Event;
|
||||
use App\Models\TaskCollection;
|
||||
use App\Models\Tenant;
|
||||
use App\Services\Tenant\TaskCollectionImportService;
|
||||
use App\Support\TenantRequestResolver;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class TaskCollectionController extends Controller
|
||||
{
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$tenantId = $request->tenant->id;
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
$query = TaskCollection::query()
|
||||
->forTenant($tenantId)
|
||||
@@ -68,11 +70,11 @@ class TaskCollectionController extends Controller
|
||||
$this->authorizeAccess($request, $collection);
|
||||
|
||||
$data = $request->validate([
|
||||
'event_slug' => ['required', 'string', Rule::exists('events', 'slug')->where('tenant_id', $request->tenant->id)],
|
||||
'event_slug' => ['required', 'string', Rule::exists('events', 'slug')->where('tenant_id', $this->currentTenant($request)->id)],
|
||||
]);
|
||||
|
||||
$event = Event::where('slug', $data['event_slug'])
|
||||
->where('tenant_id', $request->tenant->id)
|
||||
->where('tenant_id', $this->currentTenant($request)->id)
|
||||
->firstOrFail();
|
||||
|
||||
$result = $importService->import($collection, $event);
|
||||
@@ -87,8 +89,13 @@ class TaskCollectionController extends Controller
|
||||
|
||||
protected function authorizeAccess(Request $request, TaskCollection $collection): void
|
||||
{
|
||||
if ($collection->tenant_id && $collection->tenant_id !== $request->tenant->id) {
|
||||
if ($collection->tenant_id && $collection->tenant_id !== $this->currentTenant($request)->id) {
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
|
||||
protected function currentTenant(Request $request): Tenant
|
||||
{
|
||||
return TenantRequestResolver::resolve($request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ use App\Http\Resources\Tenant\TaskResource;
|
||||
use App\Models\Event;
|
||||
use App\Models\Task;
|
||||
use App\Models\TaskCollection;
|
||||
use App\Models\Tenant;
|
||||
use App\Support\ApiError;
|
||||
use App\Support\TenantRequestResolver;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
@@ -22,14 +24,14 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$tenantId = $request->tenant->id;
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
$query = Task::query()
|
||||
->where(function ($inner) use ($tenantId) {
|
||||
$inner->whereNull('tenant_id')
|
||||
->orWhere('tenant_id', $tenantId);
|
||||
})
|
||||
->with(['taskCollection', 'assignedEvents'])
|
||||
->with(['taskCollection', 'assignedEvents', 'eventType'])
|
||||
->orderByRaw('tenant_id is null desc')
|
||||
->orderBy('sort_order')
|
||||
->orderBy('created_at', 'desc');
|
||||
@@ -64,11 +66,12 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function store(TaskStoreRequest $request): JsonResponse
|
||||
{
|
||||
$tenant = $this->currentTenant($request);
|
||||
$collectionId = $request->input('collection_id');
|
||||
$collection = $collectionId ? $this->resolveAccessibleCollection($request, $collectionId) : null;
|
||||
|
||||
$payload = $this->prepareTaskPayload($request->validated(), $request->tenant->id);
|
||||
$payload['tenant_id'] = $request->tenant->id;
|
||||
$payload = $this->prepareTaskPayload($request->validated(), $tenant->id);
|
||||
$payload['tenant_id'] = $tenant->id;
|
||||
|
||||
if ($collection) {
|
||||
$payload['collection_id'] = $collection->id;
|
||||
@@ -77,7 +80,7 @@ class TaskController extends Controller
|
||||
|
||||
$task = Task::create($payload);
|
||||
|
||||
$task->load(['taskCollection', 'assignedEvents']);
|
||||
$task->load(['taskCollection', 'assignedEvents', 'eventType']);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Task erfolgreich erstellt.',
|
||||
@@ -90,11 +93,11 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function show(Request $request, Task $task): JsonResponse
|
||||
{
|
||||
if ($task->tenant_id && $task->tenant_id !== $request->tenant->id) {
|
||||
if ($task->tenant_id && $task->tenant_id !== $this->currentTenant($request)->id) {
|
||||
abort(404, 'Task nicht gefunden.');
|
||||
}
|
||||
|
||||
$task->load(['taskCollection', 'assignedEvents']);
|
||||
$task->load(['taskCollection', 'assignedEvents', 'eventType']);
|
||||
|
||||
return response()->json(new TaskResource($task));
|
||||
}
|
||||
@@ -104,14 +107,16 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function update(TaskUpdateRequest $request, Task $task): JsonResponse
|
||||
{
|
||||
if ($task->tenant_id !== $request->tenant->id) {
|
||||
$tenant = $this->currentTenant($request);
|
||||
|
||||
if ($task->tenant_id !== $tenant->id) {
|
||||
abort(404, 'Task nicht gefunden.');
|
||||
}
|
||||
|
||||
$collectionId = $request->input('collection_id');
|
||||
$collection = $collectionId ? $this->resolveAccessibleCollection($request, $collectionId) : null;
|
||||
|
||||
$payload = $this->prepareTaskPayload($request->validated(), $request->tenant->id, $task);
|
||||
$payload = $this->prepareTaskPayload($request->validated(), $tenant->id, $task);
|
||||
|
||||
if ($collection) {
|
||||
$payload['collection_id'] = $collection->id;
|
||||
@@ -133,7 +138,7 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function destroy(Request $request, Task $task): JsonResponse
|
||||
{
|
||||
if ($task->tenant_id !== $request->tenant->id) {
|
||||
if ($task->tenant_id !== $this->currentTenant($request)->id) {
|
||||
abort(404, 'Task nicht gefunden.');
|
||||
}
|
||||
|
||||
@@ -149,7 +154,9 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function assignToEvent(Request $request, Task $task, Event $event): JsonResponse
|
||||
{
|
||||
if ($task->tenant_id !== $request->tenant->id || $event->tenant_id !== $request->tenant->id) {
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($task->tenant_id !== $tenantId || $event->tenant_id !== $tenantId) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
@@ -169,7 +176,9 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function bulkAssignToEvent(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
if ($event->tenant_id !== $request->tenant->id) {
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($event->tenant_id !== $tenantId) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
@@ -184,7 +193,7 @@ class TaskController extends Controller
|
||||
}
|
||||
|
||||
$tasks = Task::whereIn('id', $taskIds)
|
||||
->where('tenant_id', $request->tenant->id)
|
||||
->where('tenant_id', $tenantId)
|
||||
->get();
|
||||
|
||||
$attached = 0;
|
||||
@@ -205,12 +214,12 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function forEvent(Request $request, Event $event): AnonymousResourceCollection
|
||||
{
|
||||
if ($event->tenant_id !== $request->tenant->id) {
|
||||
if ($event->tenant_id !== $this->currentTenant($request)->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$tasks = Task::whereHas('assignedEvents', fn ($q) => $q->where('event_id', $event->id))
|
||||
->with(['taskCollection'])
|
||||
->with(['taskCollection', 'eventType'])
|
||||
->orderBy('created_at', 'desc')
|
||||
->paginate($request->get('per_page', 15));
|
||||
|
||||
@@ -222,12 +231,12 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function fromCollection(Request $request, TaskCollection $collection): AnonymousResourceCollection
|
||||
{
|
||||
if ($collection->tenant_id && $collection->tenant_id !== $request->tenant->id) {
|
||||
if ($collection->tenant_id && $collection->tenant_id !== $this->currentTenant($request)->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$tasks = $collection->tasks()
|
||||
->with(['assignedEvents'])
|
||||
->with(['assignedEvents', 'eventType'])
|
||||
->orderBy('created_at', 'desc')
|
||||
->paginate($request->get('per_page', 15));
|
||||
|
||||
@@ -240,13 +249,20 @@ class TaskController extends Controller
|
||||
->where(function ($query) use ($request) {
|
||||
$query->whereNull('tenant_id');
|
||||
|
||||
if ($request->tenant?->id) {
|
||||
$query->orWhere('tenant_id', $request->tenant->id);
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($tenantId) {
|
||||
$query->orWhere('tenant_id', $tenantId);
|
||||
}
|
||||
})
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
protected function currentTenant(Request $request): Tenant
|
||||
{
|
||||
return TenantRequestResolver::resolve($request);
|
||||
}
|
||||
|
||||
protected function prepareTaskPayload(array $data, int $tenantId, ?Task $original = null): array
|
||||
{
|
||||
if (array_key_exists('title', $data)) {
|
||||
|
||||
@@ -9,12 +9,14 @@ use App\Models\Package;
|
||||
use App\Models\PackagePurchase;
|
||||
use App\Models\TenantPackage;
|
||||
use App\Services\Checkout\CheckoutSessionService;
|
||||
use App\Services\Coupons\CouponService;
|
||||
use App\Services\Paddle\PaddleCheckoutService;
|
||||
use App\Support\Concerns\PresentsPackages;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Inertia\Inertia;
|
||||
use League\CommonMark\Environment\Environment;
|
||||
@@ -32,6 +34,7 @@ class MarketingController extends Controller
|
||||
public function __construct(
|
||||
private readonly CheckoutSessionService $checkoutSessions,
|
||||
private readonly PaddleCheckoutService $paddleCheckout,
|
||||
private readonly CouponService $coupons,
|
||||
) {}
|
||||
|
||||
public function index()
|
||||
@@ -107,8 +110,10 @@ class MarketingController extends Controller
|
||||
Log::info('Buy packages called', ['auth' => Auth::check(), 'locale' => $locale, 'package_id' => $packageId]);
|
||||
$package = Package::findOrFail($packageId);
|
||||
|
||||
$couponCode = $this->rememberCouponFromRequest($request, $package);
|
||||
|
||||
if (! Auth::check()) {
|
||||
return redirect()->route('register', ['package_id' => $package->id])
|
||||
return redirect()->route('register', ['package_id' => $package->id, 'coupon' => $couponCode])
|
||||
->with('message', __('marketing.packages.register_required'));
|
||||
}
|
||||
|
||||
@@ -167,6 +172,19 @@ class MarketingController extends Controller
|
||||
|
||||
$this->checkoutSessions->selectProvider($session, CheckoutSession::PROVIDER_PADDLE);
|
||||
|
||||
$appliedDiscountId = null;
|
||||
|
||||
if ($couponCode) {
|
||||
try {
|
||||
$preview = $this->coupons->preview($couponCode, $package, $tenant);
|
||||
$this->checkoutSessions->applyCoupon($session, $preview['coupon'], $preview['pricing']);
|
||||
$appliedDiscountId = $preview['coupon']->paddle_discount_id;
|
||||
$request->session()->forget('marketing.checkout.coupon');
|
||||
} catch (ValidationException $exception) {
|
||||
$request->session()->flash('coupon_error', $exception->errors()['code'][0] ?? __('marketing.coupon.errors.generic'));
|
||||
}
|
||||
}
|
||||
|
||||
$checkout = $this->paddleCheckout->createCheckout($tenant, $package, [
|
||||
'success_url' => route('marketing.success', [
|
||||
'locale' => app()->getLocale(),
|
||||
@@ -178,7 +196,9 @@ class MarketingController extends Controller
|
||||
]),
|
||||
'metadata' => [
|
||||
'checkout_session_id' => $session->id,
|
||||
'coupon_code' => $couponCode,
|
||||
],
|
||||
'discount_id' => $appliedDiscountId,
|
||||
]);
|
||||
|
||||
$session->forceFill([
|
||||
@@ -210,6 +230,34 @@ class MarketingController extends Controller
|
||||
return Inertia::render('marketing/Success', compact('packageId'));
|
||||
}
|
||||
|
||||
protected function rememberCouponFromRequest(Request $request, Package $package): ?string
|
||||
{
|
||||
$input = Str::upper(trim((string) $request->input('coupon')));
|
||||
|
||||
if ($input !== '') {
|
||||
$request->session()->put('marketing.checkout.coupon', [
|
||||
'package_id' => $package->id,
|
||||
'code' => $input,
|
||||
]);
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
if ($request->has('coupon')) {
|
||||
$request->session()->forget('marketing.checkout.coupon');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$stored = $request->session()->get('marketing.checkout.coupon');
|
||||
|
||||
if ($stored && (int) ($stored['package_id'] ?? 0) === (int) $package->id) {
|
||||
return $stored['code'] ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function blogIndex(Request $request)
|
||||
{
|
||||
$locale = $request->get('locale', app()->getLocale());
|
||||
|
||||
@@ -5,10 +5,12 @@ namespace App\Http\Controllers;
|
||||
use App\Models\CheckoutSession;
|
||||
use App\Models\Package;
|
||||
use App\Services\Checkout\CheckoutSessionService;
|
||||
use App\Services\Coupons\CouponService;
|
||||
use App\Services\Paddle\PaddleCheckoutService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class PaddleCheckoutController extends Controller
|
||||
@@ -16,6 +18,7 @@ class PaddleCheckoutController extends Controller
|
||||
public function __construct(
|
||||
private readonly PaddleCheckoutService $checkout,
|
||||
private readonly CheckoutSessionService $sessions,
|
||||
private readonly CouponService $coupons,
|
||||
) {}
|
||||
|
||||
public function create(Request $request): JsonResponse
|
||||
@@ -25,6 +28,7 @@ class PaddleCheckoutController extends Controller
|
||||
'success_url' => ['nullable', 'url'],
|
||||
'return_url' => ['nullable', 'url'],
|
||||
'inline' => ['sometimes', 'boolean'],
|
||||
'coupon_code' => ['nullable', 'string', 'max:64'],
|
||||
]);
|
||||
|
||||
$user = Auth::user();
|
||||
@@ -46,7 +50,16 @@ class PaddleCheckoutController extends Controller
|
||||
|
||||
$this->sessions->selectProvider($session, CheckoutSession::PROVIDER_PADDLE);
|
||||
|
||||
if ($request->boolean('inline')) {
|
||||
$couponCode = Str::upper(trim((string) ($data['coupon_code'] ?? '')));
|
||||
$discountId = null;
|
||||
|
||||
if ($couponCode !== '') {
|
||||
$preview = $this->coupons->preview($couponCode, $package, $tenant);
|
||||
$this->sessions->applyCoupon($session, $preview['coupon'], $preview['pricing']);
|
||||
$discountId = $preview['coupon']->paddle_discount_id;
|
||||
}
|
||||
|
||||
if ($request->boolean('inline') && $discountId === null) {
|
||||
$metadata = array_merge($session->provider_metadata ?? [], [
|
||||
'mode' => 'inline',
|
||||
]);
|
||||
@@ -80,7 +93,9 @@ class PaddleCheckoutController extends Controller
|
||||
'return_url' => $data['return_url'] ?? null,
|
||||
'metadata' => [
|
||||
'checkout_session_id' => $session->id,
|
||||
'coupon_code' => $couponCode ?: null,
|
||||
],
|
||||
'discount_id' => $discountId,
|
||||
]);
|
||||
|
||||
$session->forceFill([
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Requests\Tenant;
|
||||
|
||||
use App\Support\TenantRequestResolver;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
@@ -22,12 +23,12 @@ class TaskStoreRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$tenantId = TenantRequestResolver::resolve($this)->id;
|
||||
|
||||
return [
|
||||
'title' => ['required', 'string', 'max:255'],
|
||||
'description' => ['nullable', 'string'],
|
||||
'collection_id' => ['nullable', 'exists:task_collections,id', function ($attribute, $value, $fail) {
|
||||
$tenantId = request()->tenant?->id;
|
||||
|
||||
'collection_id' => ['nullable', 'exists:task_collections,id', function ($attribute, $value, $fail) use ($tenantId) {
|
||||
$accessible = \App\Models\TaskCollection::where('id', $value)
|
||||
->where(function ($query) use ($tenantId) {
|
||||
$query->whereNull('tenant_id');
|
||||
@@ -45,9 +46,8 @@ class TaskStoreRequest extends FormRequest
|
||||
'priority' => ['nullable', Rule::in(['low', 'medium', 'high', 'urgent'])],
|
||||
'due_date' => ['nullable', 'date', 'after:now'],
|
||||
'is_completed' => ['nullable', 'boolean'],
|
||||
'assigned_to' => ['nullable', 'exists:users,id', function ($attribute, $value, $fail) {
|
||||
$tenantId = request()->tenant?->id;
|
||||
if ($tenantId && !\App\Models\User::where('id', $value)->where('tenant_id', $tenantId)->exists()) {
|
||||
'assigned_to' => ['nullable', 'exists:users,id', function ($attribute, $value, $fail) use ($tenantId) {
|
||||
if ($tenantId && ! \App\Models\User::where('id', $value)->where('tenant_id', $tenantId)->exists()) {
|
||||
$fail('Der Benutzer gehört nicht zu diesem Tenant.');
|
||||
}
|
||||
}],
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Requests\Tenant;
|
||||
|
||||
use App\Support\TenantRequestResolver;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
@@ -22,12 +23,12 @@ class TaskUpdateRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$tenantId = TenantRequestResolver::resolve($this)->id;
|
||||
|
||||
return [
|
||||
'title' => ['sometimes', 'required', 'string', 'max:255'],
|
||||
'description' => ['sometimes', 'nullable', 'string'],
|
||||
'collection_id' => ['sometimes', 'nullable', 'exists:task_collections,id', function ($attribute, $value, $fail) {
|
||||
$tenantId = request()->tenant?->id;
|
||||
|
||||
'collection_id' => ['sometimes', 'nullable', 'exists:task_collections,id', function ($attribute, $value, $fail) use ($tenantId) {
|
||||
$accessible = \App\Models\TaskCollection::where('id', $value)
|
||||
->where(function ($query) use ($tenantId) {
|
||||
$query->whereNull('tenant_id');
|
||||
@@ -45,9 +46,8 @@ class TaskUpdateRequest extends FormRequest
|
||||
'priority' => ['sometimes', 'nullable', Rule::in(['low', 'medium', 'high', 'urgent'])],
|
||||
'due_date' => ['sometimes', 'nullable', 'date'],
|
||||
'is_completed' => ['sometimes', 'boolean'],
|
||||
'assigned_to' => ['sometimes', 'nullable', 'exists:users,id', function ($attribute, $value, $fail) {
|
||||
$tenantId = request()->tenant?->id;
|
||||
if ($tenantId && !\App\Models\User::where('id', $value)->where('tenant_id', $tenantId)->exists()) {
|
||||
'assigned_to' => ['sometimes', 'nullable', 'exists:users,id', function ($attribute, $value, $fail) use ($tenantId) {
|
||||
if ($tenantId && ! \App\Models\User::where('id', $value)->where('tenant_id', $tenantId)->exists()) {
|
||||
$fail('Der Benutzer gehört nicht zu diesem Tenant.');
|
||||
}
|
||||
}],
|
||||
|
||||
@@ -36,6 +36,11 @@ class TaskResource extends JsonResource
|
||||
'difficulty' => $this->difficulty,
|
||||
'due_date' => $this->due_date?->toISOString(),
|
||||
'is_completed' => (bool) $this->is_completed,
|
||||
'event_type_id' => $this->event_type_id,
|
||||
'event_type' => $this->whenLoaded(
|
||||
'eventType',
|
||||
fn () => new EventTypeResource($this->eventType)
|
||||
),
|
||||
'collection_id' => $this->collection_id,
|
||||
'source_task_id' => $this->source_task_id,
|
||||
'source_collection_id' => $this->source_collection_id,
|
||||
|
||||
Reference in New Issue
Block a user