Compare commits
6 Commits
b0702b7e15
...
14c81fec1b
| Author | SHA1 | Date | |
|---|---|---|---|
| 14c81fec1b | |||
| 9a14b8fbbd | |||
| c665222837 | |||
| d61a5d459d | |||
| 8395c7f24d | |||
| 79d402e210 |
@@ -37,7 +37,8 @@ class TenantBootstrapService
|
|||||||
'roles',
|
'roles',
|
||||||
fn ($query) => $query->where('codigo', RoleCode::User->value)
|
fn ($query) => $query->where('codigo', RoleCode::User->value)
|
||||||
),
|
),
|
||||||
'categories' => fn ($query) => $query->orderBy('nombre'),
|
$tenant->storefront_website_type_code === 'onticket_multi_event'
|
||||||
|
? 'eventCategories' : 'categories' => fn ($query) => $query->orderBy('nombre'),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use App\Domains\Core\Client\Models\Client;
|
|||||||
use App\Domains\Ticketing\Event\Models\EventDate;
|
use App\Domains\Ticketing\Event\Models\EventDate;
|
||||||
use App\Domains\Ticketing\Event\Models\EventDateChange;
|
use App\Domains\Ticketing\Event\Models\EventDateChange;
|
||||||
use App\Domains\Ticketing\Event\Models\Event;
|
use App\Domains\Ticketing\Event\Models\Event;
|
||||||
|
use App\Domains\Ticketing\Event\Models\EventCategory;
|
||||||
use App\Domains\Core\Menu\Models\Menu;
|
use App\Domains\Core\Menu\Models\Menu;
|
||||||
use App\Domains\Core\Menu\Models\TenantMenu;
|
use App\Domains\Core\Menu\Models\TenantMenu;
|
||||||
use App\Domains\Core\Tenant\Enums\CartEditingPolicy;
|
use App\Domains\Core\Tenant\Enums\CartEditingPolicy;
|
||||||
@@ -265,6 +266,12 @@ class Tenant extends Model
|
|||||||
return $this->hasMany(Category::class, 'tenant_code', 'codigo');
|
return $this->hasMany(Category::class, 'tenant_code', 'codigo');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return HasMany<EventCategory, $this> */
|
||||||
|
public function eventCategories(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(EventCategory::class, 'tenant_code', 'codigo');
|
||||||
|
}
|
||||||
|
|
||||||
/** @return HasMany<ScanAttempt, $this> */
|
/** @return HasMany<ScanAttempt, $this> */
|
||||||
public function scanAttempts(): HasMany
|
public function scanAttempts(): HasMany
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Domains\Core\Tenant\Resources;
|
namespace App\Domains\Core\Tenant\Resources;
|
||||||
|
|
||||||
use App\Shared\Attachable\Models\Attachment;
|
|
||||||
use App\Shared\Attachable\Models\AttachmentCrop;
|
|
||||||
use App\Domains\Commerce\Catalog\Models\Category;
|
use App\Domains\Commerce\Catalog\Models\Category;
|
||||||
use App\Domains\Ticketing\Event\Models\EventDate;
|
|
||||||
use App\Domains\Ticketing\Event\Models\Event;
|
|
||||||
use App\Domains\Ticketing\Event\Services\EventDateInfoFormatter;
|
|
||||||
use App\Domains\Core\Menu\Models\Menu;
|
use App\Domains\Core\Menu\Models\Menu;
|
||||||
use App\Domains\Core\Tenant\Models\Tenant;
|
use App\Domains\Core\Tenant\Models\Tenant;
|
||||||
|
use App\Domains\Ticketing\Event\Models\Event;
|
||||||
|
use App\Domains\Ticketing\Event\Models\EventDate;
|
||||||
|
use App\Domains\Ticketing\Event\Services\EventDateInfoFormatter;
|
||||||
|
use App\Shared\Attachable\Models\Attachment;
|
||||||
|
use App\Shared\Attachable\Models\AttachmentCrop;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@@ -99,9 +99,18 @@ class TenantResource extends JsonResource
|
|||||||
'menues',
|
'menues',
|
||||||
fn () => $this->menuTree($this->menues)
|
fn () => $this->menuTree($this->menues)
|
||||||
),
|
),
|
||||||
'categories' => $this->whenLoaded(
|
'categories' => $this->when(
|
||||||
'categories',
|
$this->storefront_website_type_code !== 'onticket_multi_event',
|
||||||
fn () => $this->categoryTree($this->categories)
|
fn () => $this->whenLoaded('categories', fn () => $this->categoryTree($this->categories))
|
||||||
|
),
|
||||||
|
'event_categories' => $this->when(
|
||||||
|
$this->storefront_website_type_code === 'onticket_multi_event',
|
||||||
|
fn () => $this->whenLoaded('eventCategories', fn () => $this->eventCategories
|
||||||
|
->map(fn ($category) => [
|
||||||
|
'id' => $category->id,
|
||||||
|
'nombre' => $category->nombre,
|
||||||
|
'subcategories' => [],
|
||||||
|
])->values())
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ class PublicEventController extends Controller
|
|||||||
abort_unless($tenant->storefront_website_type_code === 'onticket_multi_event', 404);
|
abort_unless($tenant->storefront_website_type_code === 'onticket_multi_event', 404);
|
||||||
|
|
||||||
$term = trim((string) $request->validated('q', ''));
|
$term = trim((string) $request->validated('q', ''));
|
||||||
return PublicEventResource::collection($events->list($tenant, $term, (int) $request->validated('page', 1)));
|
return PublicEventResource::collection($events->list(
|
||||||
|
$tenant,
|
||||||
|
$term,
|
||||||
|
(int) $request->validated('page', 1),
|
||||||
|
$request->validated('category_id', null) === null ? null : (int) $request->validated('category_id'),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show(Tenant $tenant, Event $event, PublicEventService $events): PublicEventResource
|
public function show(Tenant $tenant, Event $event, PublicEventService $events): PublicEventResource
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
#[Fillable(['tenant_code', 'title', 'subtitle', 'description', 'location', 'exact_location', 'date_text', 'published_at', 'attachment_id'])]
|
#[Fillable(['tenant_code', 'event_category_id', 'title', 'subtitle', 'description', 'location', 'exact_location', 'date_text', 'published_at', 'attachment_id'])]
|
||||||
class Event extends Model
|
class Event extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
@@ -29,6 +29,12 @@ class Event extends Model
|
|||||||
return $this->belongsTo(Tenant::class, 'tenant_code', 'codigo');
|
return $this->belongsTo(Tenant::class, 'tenant_code', 'codigo');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return BelongsTo<EventCategory, $this> */
|
||||||
|
public function eventCategory(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(EventCategory::class);
|
||||||
|
}
|
||||||
|
|
||||||
/** @return BelongsTo<Attachment, $this> */
|
/** @return BelongsTo<Attachment, $this> */
|
||||||
public function attachment(): BelongsTo
|
public function attachment(): BelongsTo
|
||||||
{
|
{
|
||||||
|
|||||||
25
app/Domains/Ticketing/Event/Models/EventCategory.php
Normal file
25
app/Domains/Ticketing/Event/Models/EventCategory.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Ticketing\Event\Models;
|
||||||
|
|
||||||
|
use App\Domains\Core\Tenant\Models\Tenant;
|
||||||
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
|
#[Fillable(['tenant_code', 'nombre'])]
|
||||||
|
class EventCategory extends Model
|
||||||
|
{
|
||||||
|
/** @return BelongsTo<Tenant, $this> */
|
||||||
|
public function tenant(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Tenant::class, 'tenant_code', 'codigo');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return HasMany<Event, $this> */
|
||||||
|
public function events(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(Event::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ class ListPublicEventsRequest extends FormRequest
|
|||||||
return [
|
return [
|
||||||
'q' => ['sometimes', 'string', 'max:120'],
|
'q' => ['sometimes', 'string', 'max:120'],
|
||||||
'page' => ['sometimes', 'integer', 'min:1'],
|
'page' => ['sometimes', 'integer', 'min:1'],
|
||||||
|
'category_id' => ['sometimes', 'integer', 'min:1'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class PublicEventResource extends JsonResource
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
|
'event_category_id' => $this->event_category_id,
|
||||||
'title' => $this->title,
|
'title' => $this->title,
|
||||||
'subtitle' => $this->subtitle,
|
'subtitle' => $this->subtitle,
|
||||||
'description' => $this->description,
|
'description' => $this->description,
|
||||||
|
|||||||
@@ -8,12 +8,17 @@ use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
|||||||
|
|
||||||
class PublicEventService
|
class PublicEventService
|
||||||
{
|
{
|
||||||
public function list(Tenant $tenant, string $term, int $page): LengthAwarePaginator
|
public function list(Tenant $tenant, string $term, int $page, ?int $categoryId = null): LengthAwarePaginator
|
||||||
{
|
{
|
||||||
$query = $tenant->events()
|
$query = $tenant->events()
|
||||||
->whereNotNull('published_at')
|
->whereNotNull('published_at')
|
||||||
->where('published_at', '<=', now());
|
->where('published_at', '<=', now());
|
||||||
|
|
||||||
|
if ($categoryId !== null) {
|
||||||
|
abort_unless($tenant->eventCategories()->whereKey($categoryId)->exists(), 404);
|
||||||
|
$query->where('event_category_id', $categoryId);
|
||||||
|
}
|
||||||
|
|
||||||
if ($term !== '') {
|
if ($term !== '') {
|
||||||
$query->where(function ($query) use ($term): void {
|
$query->where(function ($query) use ($term): void {
|
||||||
$query->where('title', 'like', '%'.$term.'%')
|
$query->where('title', 'like', '%'.$term.'%')
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('event_categories', function (Blueprint $table): void {
|
||||||
|
$table->id();
|
||||||
|
$table->string('tenant_code');
|
||||||
|
$table->string('nombre');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->foreign('tenant_code')->references('codigo')->on('tenants')->cascadeOnUpdate()->cascadeOnDelete();
|
||||||
|
$table->unique(['tenant_code', 'nombre']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('events', function (Blueprint $table): void {
|
||||||
|
$table->foreignId('event_category_id')->nullable()->constrained('event_categories')->nullOnDelete();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (DB::table('tenants')->where('codigo', 'onticket')->exists()) {
|
||||||
|
$now = now();
|
||||||
|
foreach (['Música', 'Teatro', 'Deportes', 'Infantiles', 'Otros'] as $nombre) {
|
||||||
|
DB::table('event_categories')->insert([
|
||||||
|
'tenant_code' => 'onticket', 'nombre' => $nombre,
|
||||||
|
'created_at' => $now, 'updated_at' => $now,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('events', fn (Blueprint $table) => $table->dropConstrainedForeignId('event_category_id'));
|
||||||
|
Schema::dropIfExists('event_categories');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
private const TENANT_CODE = 'onticket';
|
||||||
|
|
||||||
|
private const EVENT_MENUS = [
|
||||||
|
'event.index' => [
|
||||||
|
'label' => 'Eventos',
|
||||||
|
'route' => '/',
|
||||||
|
],
|
||||||
|
'event.detail' => [
|
||||||
|
'label' => 'Detalle de evento',
|
||||||
|
'route' => '/evento/:id',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
private const EXCLUDED_MENU_CODES = [
|
||||||
|
'product.detail',
|
||||||
|
'help',
|
||||||
|
'help.faq',
|
||||||
|
'help.contact',
|
||||||
|
'help.payment-methods',
|
||||||
|
'help.shipping',
|
||||||
|
'help.terms-and-conditions',
|
||||||
|
'adminapp.tickets',
|
||||||
|
'adminapp.fiesta-futbol-infantil.entradas',
|
||||||
|
'adminapp.fiesta-futbol-infantil.alojamientos',
|
||||||
|
'adminapp.fiesta-futbol-infantil.merchandising',
|
||||||
|
'adminapp.fiesta-futbol-infantil.comida',
|
||||||
|
'adminapp.desfile.entradas',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$now = now();
|
||||||
|
|
||||||
|
DB::transaction(function () use ($now): void {
|
||||||
|
foreach (self::EVENT_MENUS as $code => $menu) {
|
||||||
|
DB::table('menues')->updateOrInsert(
|
||||||
|
['code' => $code],
|
||||||
|
[
|
||||||
|
'label' => $menu['label'],
|
||||||
|
'parent_menu_code' => null,
|
||||||
|
'content_type' => 'dynamic',
|
||||||
|
'static_content_schema' => null,
|
||||||
|
'route' => $menu['route'],
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::table('roles')
|
||||||
|
->whereIn('codigo', ['admin', 'adminapp', 'user'])
|
||||||
|
->pluck('codigo')
|
||||||
|
->each(function (string $roleCode): void {
|
||||||
|
foreach (array_keys(self::EVENT_MENUS) as $menuCode) {
|
||||||
|
DB::table('roles_menues')->updateOrInsert([
|
||||||
|
'rol_codigo' => $roleCode,
|
||||||
|
'menu_codigo' => $menuCode,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (! DB::table('tenants')->where('codigo', self::TENANT_CODE)->exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::table('menues')
|
||||||
|
->whereNotIn('code', self::EXCLUDED_MENU_CODES)
|
||||||
|
->pluck('code')
|
||||||
|
->each(function (string $menuCode) use ($now): void {
|
||||||
|
DB::table('tenants_menues')->updateOrInsert(
|
||||||
|
[
|
||||||
|
'tenant_code' => self::TENANT_CODE,
|
||||||
|
'menu_code' => $menuCode,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'static_content' => null,
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
DB::transaction(function (): void {
|
||||||
|
$assignedMenuCodes = DB::table('menues')
|
||||||
|
->whereNotIn('code', self::EXCLUDED_MENU_CODES)
|
||||||
|
->pluck('code');
|
||||||
|
|
||||||
|
DB::table('tenants_menues')
|
||||||
|
->where('tenant_code', self::TENANT_CODE)
|
||||||
|
->whereIn('menu_code', $assignedMenuCodes)
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
DB::table('roles_menues')
|
||||||
|
->whereIn('menu_codigo', array_keys(self::EVENT_MENUS))
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
DB::table('menues')
|
||||||
|
->whereIn('code', array_keys(self::EVENT_MENUS))
|
||||||
|
->delete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
private const MENUS = [
|
||||||
|
'event.category' => [
|
||||||
|
'label' => 'Categoría de eventos',
|
||||||
|
'route' => '/eventos/categoria/:id',
|
||||||
|
],
|
||||||
|
'product.category' => [
|
||||||
|
'label' => 'Categoría de productos',
|
||||||
|
'route' => '/categoria/:id',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$now = now();
|
||||||
|
|
||||||
|
DB::transaction(function () use ($now): void {
|
||||||
|
foreach (self::MENUS as $code => $menu) {
|
||||||
|
DB::table('menues')->updateOrInsert(
|
||||||
|
['code' => $code],
|
||||||
|
[
|
||||||
|
'label' => $menu['label'],
|
||||||
|
'parent_menu_code' => null,
|
||||||
|
'content_type' => 'dynamic',
|
||||||
|
'static_content_schema' => null,
|
||||||
|
'route' => $menu['route'],
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::table('roles')
|
||||||
|
->whereIn('codigo', ['admin', 'adminapp', 'user'])
|
||||||
|
->pluck('codigo')
|
||||||
|
->each(function (string $roleCode): void {
|
||||||
|
foreach (array_keys(self::MENUS) as $menuCode) {
|
||||||
|
DB::table('roles_menues')->updateOrInsert([
|
||||||
|
'rol_codigo' => $roleCode,
|
||||||
|
'menu_codigo' => $menuCode,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
DB::table('tenants')
|
||||||
|
->pluck('codigo')
|
||||||
|
->each(function (string $tenantCode) use ($now): void {
|
||||||
|
$menuCode = $tenantCode === 'onticket' ? 'event.category' : 'product.category';
|
||||||
|
|
||||||
|
DB::table('tenants_menues')->updateOrInsert(
|
||||||
|
[
|
||||||
|
'tenant_code' => $tenantCode,
|
||||||
|
'menu_code' => $menuCode,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'static_content' => null,
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
DB::transaction(function (): void {
|
||||||
|
$menuCodes = array_keys(self::MENUS);
|
||||||
|
|
||||||
|
DB::table('tenants_menues')->whereIn('menu_code', $menuCodes)->delete();
|
||||||
|
DB::table('roles_menues')->whereIn('menu_codigo', $menuCodes)->delete();
|
||||||
|
DB::table('menues')->whereIn('code', $menuCodes)->delete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
private const CLIENT_CODE = 'pyme_rural';
|
||||||
|
|
||||||
|
private const CLIENT_NAME = 'Pyme Rural';
|
||||||
|
|
||||||
|
private const PREVIOUS_CLIENT_CODE = 'onticket';
|
||||||
|
|
||||||
|
private const TENANT_CODES = [
|
||||||
|
'fiesta_futbol_infantil',
|
||||||
|
'desfile_pura_tendencia',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
DB::transaction(function (): void {
|
||||||
|
$clientId = $this->clientId(self::CLIENT_CODE, self::CLIENT_NAME);
|
||||||
|
$sourceClientIds = DB::table('tenants')
|
||||||
|
->whereIn('codigo', self::TENANT_CODES)
|
||||||
|
->pluck('client_id')
|
||||||
|
->unique();
|
||||||
|
|
||||||
|
$this->copyIntegrations($sourceClientIds, $clientId);
|
||||||
|
|
||||||
|
DB::table('tenants')
|
||||||
|
->whereIn('codigo', self::TENANT_CODES)
|
||||||
|
->update(['client_id' => $clientId]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
DB::transaction(function (): void {
|
||||||
|
$previousClientId = $this->clientId(self::PREVIOUS_CLIENT_CODE, 'OnTicket');
|
||||||
|
$pymeRuralClientId = DB::table('clients')
|
||||||
|
->where('code', self::CLIENT_CODE)
|
||||||
|
->value('id');
|
||||||
|
|
||||||
|
if ($pymeRuralClientId !== null) {
|
||||||
|
$this->copyIntegrations(collect([$pymeRuralClientId]), $previousClientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::table('tenants')
|
||||||
|
->whereIn('codigo', self::TENANT_CODES)
|
||||||
|
->update(['client_id' => $previousClientId]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private function clientId(string $code, string $name): int
|
||||||
|
{
|
||||||
|
$clientId = DB::table('clients')->where('code', $code)->value('id');
|
||||||
|
|
||||||
|
if ($clientId === null) {
|
||||||
|
return (int) DB::table('clients')->insertGetId([
|
||||||
|
'code' => $code,
|
||||||
|
'name' => $name,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::table('clients')->where('id', $clientId)->update([
|
||||||
|
'name' => $name,
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (int) $clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function copyIntegrations(iterable $sourceClientIds, int $targetClientId): void
|
||||||
|
{
|
||||||
|
foreach ($sourceClientIds as $sourceClientId) {
|
||||||
|
DB::table('client_integrations')
|
||||||
|
->where('client_id', $sourceClientId)
|
||||||
|
->orderBy('id')
|
||||||
|
->get()
|
||||||
|
->each(function (object $integration) use ($targetClientId): void {
|
||||||
|
DB::table('client_integrations')->insertOrIgnore([
|
||||||
|
'client_id' => $targetClientId,
|
||||||
|
'integration_code' => $integration->integration_code,
|
||||||
|
'integration_instance_id' => $integration->integration_instance_id,
|
||||||
|
'created_at' => $integration->created_at,
|
||||||
|
'updated_at' => $integration->updated_at,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -12,9 +12,9 @@ use App\Domains\Commerce\Catalog\Models\CatalogItem;
|
|||||||
use App\Domains\Commerce\Catalog\Models\FeaturedGroup;
|
use App\Domains\Commerce\Catalog\Models\FeaturedGroup;
|
||||||
use App\Domains\Commerce\Catalog\Services\CatalogService;
|
use App\Domains\Commerce\Catalog\Services\CatalogService;
|
||||||
use App\Domains\Core\Client\Models\Client;
|
use App\Domains\Core\Client\Models\Client;
|
||||||
use App\Domains\Ticketing\Desfile\Services\InvitationPurchaseProvisioner;
|
|
||||||
use App\Domains\Core\Tenant\Models\Tenant;
|
use App\Domains\Core\Tenant\Models\Tenant;
|
||||||
use App\Domains\Core\Tenant\Services\TenantService;
|
use App\Domains\Core\Tenant\Services\TenantService;
|
||||||
|
use App\Domains\Ticketing\Desfile\Services\InvitationPurchaseProvisioner;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@@ -22,7 +22,7 @@ use RuntimeException;
|
|||||||
|
|
||||||
class DesfilePuraTendenciaSeeder extends Seeder
|
class DesfilePuraTendenciaSeeder extends Seeder
|
||||||
{
|
{
|
||||||
private const ONTICKET_CLIENT_CODE = 'onticket';
|
private const PYME_RURAL_CLIENT_CODE = 'pyme_rural';
|
||||||
|
|
||||||
private const TENANT_CODE = 'desfile_pura_tendencia';
|
private const TENANT_CODE = 'desfile_pura_tendencia';
|
||||||
|
|
||||||
@@ -34,9 +34,9 @@ class DesfilePuraTendenciaSeeder extends Seeder
|
|||||||
|
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
$client = Client::query()->firstOrCreate(
|
$client = Client::query()->updateOrCreate(
|
||||||
['code' => self::ONTICKET_CLIENT_CODE],
|
['code' => self::PYME_RURAL_CLIENT_CODE],
|
||||||
['name' => 'OnTicket'],
|
['name' => 'Pyme Rural'],
|
||||||
);
|
);
|
||||||
|
|
||||||
$tenant = Tenant::query()->where('codigo', self::TENANT_CODE)->first();
|
$tenant = Tenant::query()->where('codigo', self::TENANT_CODE)->first();
|
||||||
|
|||||||
@@ -17,6 +17,22 @@ class MenuSeeder extends Seeder
|
|||||||
{
|
{
|
||||||
$menus = [
|
$menus = [
|
||||||
['code' => 'index', 'label' => 'Inicio', 'route' => '/'],
|
['code' => 'index', 'label' => 'Inicio', 'route' => '/'],
|
||||||
|
['code' => 'event.index', 'label' => 'Eventos', 'route' => '/'],
|
||||||
|
[
|
||||||
|
'code' => 'event.category',
|
||||||
|
'label' => 'Categoría de eventos',
|
||||||
|
'route' => '/eventos/categoria/:id',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'event.detail',
|
||||||
|
'label' => 'Detalle de evento',
|
||||||
|
'route' => '/evento/:id',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'product.category',
|
||||||
|
'label' => 'Categoría de productos',
|
||||||
|
'route' => '/categoria/:id',
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'code' => 'product.detail',
|
'code' => 'product.detail',
|
||||||
'label' => 'Detalle de producto',
|
'label' => 'Detalle de producto',
|
||||||
@@ -291,6 +307,14 @@ class MenuSeeder extends Seeder
|
|||||||
$desfileMenuCodes = [
|
$desfileMenuCodes = [
|
||||||
'adminapp.desfile.entradas',
|
'adminapp.desfile.entradas',
|
||||||
];
|
];
|
||||||
|
$onTicketMenuCodes = [
|
||||||
|
'event.index',
|
||||||
|
'event.category',
|
||||||
|
'event.detail',
|
||||||
|
];
|
||||||
|
$catalogMenuCodes = [
|
||||||
|
'product.category',
|
||||||
|
];
|
||||||
$frequentlyAskedQuestions = [
|
$frequentlyAskedQuestions = [
|
||||||
[
|
[
|
||||||
'pregunta' => '¿Hay algún límite de compra?',
|
'pregunta' => '¿Hay algún límite de compra?',
|
||||||
@@ -358,6 +382,12 @@ class MenuSeeder extends Seeder
|
|||||||
$menuCodes = array_diff($menuCodes, $desfileMenuCodes);
|
$menuCodes = array_diff($menuCodes, $desfileMenuCodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($tenant->codigo !== 'onticket') {
|
||||||
|
$menuCodes = array_diff($menuCodes, $onTicketMenuCodes);
|
||||||
|
} else {
|
||||||
|
$menuCodes = array_diff($menuCodes, $catalogMenuCodes);
|
||||||
|
}
|
||||||
|
|
||||||
// Usar sync para asociar los menues al tenant
|
// Usar sync para asociar los menues al tenant
|
||||||
$tenant->menues()->sync($menuCodes);
|
$tenant->menues()->sync($menuCodes);
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
namespace Database\Seeders;
|
namespace Database\Seeders;
|
||||||
|
|
||||||
use App\Shared\Attachable\Models\Attachment;
|
|
||||||
use App\Shared\Attachable\Services\AttachmentService;
|
|
||||||
use App\Domains\Core\Client\Models\Client;
|
use App\Domains\Core\Client\Models\Client;
|
||||||
use App\Domains\Core\Tenant\Models\Tenant;
|
|
||||||
use App\Domains\Core\Tenant\Models\AdminWebsiteType;
|
use App\Domains\Core\Tenant\Models\AdminWebsiteType;
|
||||||
|
use App\Domains\Core\Tenant\Models\Tenant;
|
||||||
use App\Domains\Core\Tenant\Services\TenantService;
|
use App\Domains\Core\Tenant\Services\TenantService;
|
||||||
use App\Domains\Core\Tenant\Services\WebsiteExtraService;
|
use App\Domains\Core\Tenant\Services\WebsiteExtraService;
|
||||||
|
use App\Shared\Attachable\Models\Attachment;
|
||||||
|
use App\Shared\Attachable\Services\AttachmentService;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
@@ -18,6 +18,8 @@ class TenantSeeder extends Seeder
|
|||||||
{
|
{
|
||||||
private const ONTICKET_CLIENT_CODE = 'onticket';
|
private const ONTICKET_CLIENT_CODE = 'onticket';
|
||||||
|
|
||||||
|
private const PYME_RURAL_CLIENT_CODE = 'pyme_rural';
|
||||||
|
|
||||||
private const SONDER_CLIENT_CODE = 'sonder';
|
private const SONDER_CLIENT_CODE = 'sonder';
|
||||||
|
|
||||||
private const SOCIAL_MEDIA = [
|
private const SOCIAL_MEDIA = [
|
||||||
@@ -60,6 +62,11 @@ class TenantSeeder extends Seeder
|
|||||||
['name' => 'OnTicket'],
|
['name' => 'OnTicket'],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$pymeRuralClient = Client::query()->updateOrCreate(
|
||||||
|
['code' => self::PYME_RURAL_CLIENT_CODE],
|
||||||
|
['name' => 'Pyme Rural'],
|
||||||
|
);
|
||||||
|
|
||||||
$onTicketType = AdminWebsiteType::query()->where('codigo', 'onticket')->firstOrFail();
|
$onTicketType = AdminWebsiteType::query()->where('codigo', 'onticket')->firstOrFail();
|
||||||
|
|
||||||
$onTicketTenant = Tenant::query()->where('codigo', 'onticket')->first();
|
$onTicketTenant = Tenant::query()->where('codigo', 'onticket')->first();
|
||||||
@@ -76,7 +83,7 @@ class TenantSeeder extends Seeder
|
|||||||
'danger_color' => $onTicketType->danger_color,
|
'danger_color' => $onTicketType->danger_color,
|
||||||
'success_color' => $onTicketType->success_color,
|
'success_color' => $onTicketType->success_color,
|
||||||
'header_bg_color' => $onTicketType->surface_color,
|
'header_bg_color' => $onTicketType->surface_color,
|
||||||
'footer_bg_color' => $onTicketType->surface_color,
|
'footer_bg_color' => $onTicketType->primary_color,
|
||||||
'display_categories' => true,
|
'display_categories' => true,
|
||||||
'display_seach_bar' => true,
|
'display_seach_bar' => true,
|
||||||
'admin_website_type_code' => $onTicketType->codigo,
|
'admin_website_type_code' => $onTicketType->codigo,
|
||||||
@@ -113,6 +120,10 @@ class TenantSeeder extends Seeder
|
|||||||
|
|
||||||
$onTicketTenant = Tenant::query()->where('codigo', 'onticket')->firstOrFail();
|
$onTicketTenant = Tenant::query()->where('codigo', 'onticket')->firstOrFail();
|
||||||
|
|
||||||
|
foreach (['Música', 'Teatro', 'Deportes', 'Infantiles', 'Otros'] as $nombre) {
|
||||||
|
$onTicketTenant->eventCategories()->firstOrCreate(['nombre' => $nombre]);
|
||||||
|
}
|
||||||
|
|
||||||
if ($onTicketTenant->storefront_website_type_code === 'onticket_multi_event' && ! $onTicketTenant->display_seach_bar) {
|
if ($onTicketTenant->storefront_website_type_code === 'onticket_multi_event' && ! $onTicketTenant->display_seach_bar) {
|
||||||
$onTicketTenant->update(['display_seach_bar' => true]);
|
$onTicketTenant->update(['display_seach_bar' => true]);
|
||||||
}
|
}
|
||||||
@@ -146,7 +157,7 @@ class TenantSeeder extends Seeder
|
|||||||
'danger_color' => '#FF8888',
|
'danger_color' => '#FF8888',
|
||||||
'success_color' => '#198754',
|
'success_color' => '#198754',
|
||||||
'header_bg_color' => '#ffffff',
|
'header_bg_color' => '#ffffff',
|
||||||
'footer_bg_color' => '#313131',
|
'footer_bg_color' => '#6376F3',
|
||||||
'display_categories' => true,
|
'display_categories' => true,
|
||||||
'display_seach_bar' => true,
|
'display_seach_bar' => true,
|
||||||
'display_cart' => true,
|
'display_cart' => true,
|
||||||
@@ -195,7 +206,7 @@ class TenantSeeder extends Seeder
|
|||||||
->delete();
|
->delete();
|
||||||
|
|
||||||
$this->tenantService->create([
|
$this->tenantService->create([
|
||||||
'client_id' => $onTicketClient->id,
|
'client_id' => $pymeRuralClient->id,
|
||||||
'codigo' => 'fiesta_futbol_infantil',
|
'codigo' => 'fiesta_futbol_infantil',
|
||||||
'nombre' => 'Fiesta Fútbol Infantil',
|
'nombre' => 'Fiesta Fútbol Infantil',
|
||||||
'dominio' => $fiestaDomain,
|
'dominio' => $fiestaDomain,
|
||||||
@@ -205,7 +216,7 @@ class TenantSeeder extends Seeder
|
|||||||
'danger_color' => '#FF8888',
|
'danger_color' => '#FF8888',
|
||||||
'success_color' => '#198754',
|
'success_color' => '#198754',
|
||||||
'header_bg_color' => '#ffffff',
|
'header_bg_color' => '#ffffff',
|
||||||
'footer_bg_color' => '#015327',
|
'footer_bg_color' => '#00973F',
|
||||||
'display_categories' => false,
|
'display_categories' => false,
|
||||||
'display_seach_bar' => false,
|
'display_seach_bar' => false,
|
||||||
'display_cart' => true,
|
'display_cart' => true,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class TestEventsSeeder extends Seeder
|
|||||||
$events = [
|
$events = [
|
||||||
[
|
[
|
||||||
'title' => '[Prueba] Noche de Música en Vivo',
|
'title' => '[Prueba] Noche de Música en Vivo',
|
||||||
|
'category' => 'Música',
|
||||||
'subtitle' => 'Una noche para cantar y bailar',
|
'subtitle' => 'Una noche para cantar y bailar',
|
||||||
'description' => 'Evento de prueba para explorar la cartelera de OnTicket.',
|
'description' => 'Evento de prueba para explorar la cartelera de OnTicket.',
|
||||||
'location' => 'Teatro Broadway, Rosario',
|
'location' => 'Teatro Broadway, Rosario',
|
||||||
@@ -30,6 +31,7 @@ class TestEventsSeeder extends Seeder
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'title' => '[Prueba] Festival de Sabores',
|
'title' => '[Prueba] Festival de Sabores',
|
||||||
|
'category' => 'Otros',
|
||||||
'subtitle' => 'Gastronomía y música para toda la familia',
|
'subtitle' => 'Gastronomía y música para toda la familia',
|
||||||
'description' => 'Evento de prueba con dos jornadas disponibles.',
|
'description' => 'Evento de prueba con dos jornadas disponibles.',
|
||||||
'location' => 'Parque de España, Rosario',
|
'location' => 'Parque de España, Rosario',
|
||||||
@@ -41,6 +43,7 @@ class TestEventsSeeder extends Seeder
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'title' => '[Prueba] Stand Up en el Centro',
|
'title' => '[Prueba] Stand Up en el Centro',
|
||||||
|
'category' => 'Teatro',
|
||||||
'subtitle' => 'Humor para compartir',
|
'subtitle' => 'Humor para compartir',
|
||||||
'description' => 'Evento de prueba para visualizar distintas propuestas.',
|
'description' => 'Evento de prueba para visualizar distintas propuestas.',
|
||||||
'location' => 'Centro Cultural La Comedia, Rosario',
|
'location' => 'Centro Cultural La Comedia, Rosario',
|
||||||
@@ -60,9 +63,16 @@ class TestEventsSeeder extends Seeder
|
|||||||
'description' => $definition['description'],
|
'description' => $definition['description'],
|
||||||
'location' => $definition['location'],
|
'location' => $definition['location'],
|
||||||
'published_at' => now(),
|
'published_at' => now(),
|
||||||
|
'event_category_id' => $tenant->eventCategories()
|
||||||
|
->where('nombre', $definition['category'])->value('id'),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($event->event_category_id === null) {
|
||||||
|
$event->update(['event_category_id' => $tenant->eventCategories()
|
||||||
|
->where('nombre', $definition['category'])->value('id')]);
|
||||||
|
}
|
||||||
|
|
||||||
if ($event->attachment_id === null) {
|
if ($event->attachment_id === null) {
|
||||||
$path = public_path('images/tennants/onticket/test-events/'.$definition['image']);
|
$path = public_path('images/tennants/onticket/test-events/'.$definition['image']);
|
||||||
|
|
||||||
|
|||||||
130
storage/framework/lsp-52251fd8d9839a2d.php
Normal file
130
storage/framework/lsp-52251fd8d9839a2d.php
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<?php
|
||||||
|
error_reporting(error_reporting() & ~(E_WARNING | E_CORE_WARNING | E_COMPILE_WARNING | E_USER_WARNING | E_DEPRECATED | E_USER_DEPRECATED));
|
||||||
|
class LspHelper
|
||||||
|
{
|
||||||
|
public static function relativePath($path)
|
||||||
|
{
|
||||||
|
if (!str_contains($path, base_path())) {
|
||||||
|
return (string) $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ltrim(str_replace(base_path(), '', realpath($path) ?: $path), DIRECTORY_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isVendor($path)
|
||||||
|
{
|
||||||
|
return str_contains($path, base_path('vendor'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function propertyDefault(ReflectionProperty $property, ?ReflectionParameter $parameter = null): array
|
||||||
|
{
|
||||||
|
if ($property->hasDefaultValue()) {
|
||||||
|
return ['default' => $property->getDefaultValue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($parameter?->isDefaultValueAvailable()) {
|
||||||
|
return ['default' => $parameter->getDefaultValue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function formatDefaultValue(mixed $value): mixed
|
||||||
|
{
|
||||||
|
return match (true) {
|
||||||
|
is_array($value) => 'array(...)',
|
||||||
|
$value instanceof UnitEnum => get_class($value) . '::' . $value->name,
|
||||||
|
$value instanceof Closure => 'Closure',
|
||||||
|
is_object($value) => get_class($value),
|
||||||
|
is_string($value) => var_export($value, true),
|
||||||
|
is_null($value) => 'null',
|
||||||
|
is_bool($value) => $value ? 'true' : 'false',
|
||||||
|
default => $value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use Pest\Expectation;
|
||||||
|
use Pest\TestSuite;
|
||||||
|
|
||||||
|
$pest = new class
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if ($this->isInstalled()) {
|
||||||
|
$this->boot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isInstalled(): bool
|
||||||
|
{
|
||||||
|
return class_exists(TestSuite::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function boot(): void
|
||||||
|
{
|
||||||
|
require_once base_path('vendor/pestphp/pest/overrides/Runner/TestSuiteLoader.php');
|
||||||
|
|
||||||
|
TestSuite::getInstance(base_path(), 'tests');
|
||||||
|
|
||||||
|
if (file_exists($pestFile = base_path('tests/Pest.php'))) {
|
||||||
|
require_once $pestFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function config(): ?array
|
||||||
|
{
|
||||||
|
if (!$this->isInstalled()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'uses' => $this->uses(),
|
||||||
|
'expectations' => $this->expectations(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function uses(): array
|
||||||
|
{
|
||||||
|
if (is_null($instance = TestSuite::getInstance())) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$reflection = new ReflectionProperty($instance->tests, 'uses');
|
||||||
|
$uses = $reflection->getValue($instance->tests);
|
||||||
|
|
||||||
|
return collect($uses)->map(function (array $use, string $path) {
|
||||||
|
[$classOrTraits] = $use;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'path' => LspHelper::relativePath($path),
|
||||||
|
'classes' => array_values(array_filter($classOrTraits, fn ($c) => class_exists($c))),
|
||||||
|
'traits' => array_values(array_filter($classOrTraits, fn ($c) => trait_exists($c))),
|
||||||
|
];
|
||||||
|
})->values()->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function expectations(): array
|
||||||
|
{
|
||||||
|
$reflection = new ReflectionProperty(Expectation::class, 'extends');
|
||||||
|
$extends = $reflection->getValue();
|
||||||
|
|
||||||
|
return collect($extends)->map(function (Closure $closure, string $name) {
|
||||||
|
$parameters = collect((new ReflectionFunction($closure))->getParameters())
|
||||||
|
->map(function (ReflectionParameter $param) {
|
||||||
|
$type = $param->hasType() ? $param->getType() . ' ' : '';
|
||||||
|
|
||||||
|
$default = $param->isOptional() && $param->isDefaultValueAvailable()
|
||||||
|
? ' = ' . var_export($param->getDefaultValue(), true)
|
||||||
|
: '';
|
||||||
|
|
||||||
|
return $type . '$' . $param->getName() . $default;
|
||||||
|
})
|
||||||
|
->join(', ');
|
||||||
|
|
||||||
|
return compact('name', 'parameters');
|
||||||
|
})->values()->all();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
echo json_encode($pest->config());
|
||||||
130
storage/framework/lsp-cd371f347782ba98.php
Normal file
130
storage/framework/lsp-cd371f347782ba98.php
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<?php
|
||||||
|
error_reporting(error_reporting() & ~(E_WARNING | E_CORE_WARNING | E_COMPILE_WARNING | E_USER_WARNING | E_DEPRECATED | E_USER_DEPRECATED));
|
||||||
|
class LspHelper
|
||||||
|
{
|
||||||
|
public static function relativePath($path)
|
||||||
|
{
|
||||||
|
if (!str_contains($path, base_path())) {
|
||||||
|
return (string) $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ltrim(str_replace(base_path(), '', realpath($path) ?: $path), DIRECTORY_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isVendor($path)
|
||||||
|
{
|
||||||
|
return str_contains($path, base_path('vendor'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function propertyDefault(ReflectionProperty $property, ?ReflectionParameter $parameter = null): array
|
||||||
|
{
|
||||||
|
if ($property->hasDefaultValue()) {
|
||||||
|
return ['default' => $property->getDefaultValue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($parameter?->isDefaultValueAvailable()) {
|
||||||
|
return ['default' => $parameter->getDefaultValue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function formatDefaultValue(mixed $value): mixed
|
||||||
|
{
|
||||||
|
return match (true) {
|
||||||
|
is_array($value) => 'array(...)',
|
||||||
|
$value instanceof UnitEnum => get_class($value) . '::' . $value->name,
|
||||||
|
$value instanceof Closure => 'Closure',
|
||||||
|
is_object($value) => get_class($value),
|
||||||
|
is_string($value) => var_export($value, true),
|
||||||
|
is_null($value) => 'null',
|
||||||
|
is_bool($value) => $value ? 'true' : 'false',
|
||||||
|
default => $value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use Pest\Expectation;
|
||||||
|
use Pest\TestSuite;
|
||||||
|
|
||||||
|
$pest = new class
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if ($this->isInstalled()) {
|
||||||
|
$this->boot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isInstalled(): bool
|
||||||
|
{
|
||||||
|
return class_exists(TestSuite::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function boot(): void
|
||||||
|
{
|
||||||
|
require_once base_path('vendor/pestphp/pest/overrides/Runner/TestSuiteLoader.php');
|
||||||
|
|
||||||
|
TestSuite::getInstance(base_path(), 'tests');
|
||||||
|
|
||||||
|
if (file_exists($pestFile = base_path('tests/Pest.php'))) {
|
||||||
|
require_once $pestFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function config(): ?array
|
||||||
|
{
|
||||||
|
if (!$this->isInstalled()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'uses' => $this->uses(),
|
||||||
|
'expectations' => $this->expectations(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function uses(): array
|
||||||
|
{
|
||||||
|
if (is_null($instance = TestSuite::getInstance())) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$reflection = new ReflectionProperty($instance->tests, 'uses');
|
||||||
|
$uses = $reflection->getValue($instance->tests);
|
||||||
|
|
||||||
|
return collect($uses)->map(function (array $use, string $path) {
|
||||||
|
[$classOrTraits] = $use;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'path' => LspHelper::relativePath($path),
|
||||||
|
'classes' => array_values(array_filter($classOrTraits, fn ($c) => class_exists($c))),
|
||||||
|
'traits' => array_values(array_filter($classOrTraits, fn ($c) => trait_exists($c))),
|
||||||
|
];
|
||||||
|
})->values()->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function expectations(): array
|
||||||
|
{
|
||||||
|
$reflection = new ReflectionProperty(Expectation::class, 'extends');
|
||||||
|
$extends = $reflection->getValue();
|
||||||
|
|
||||||
|
return collect($extends)->map(function (Closure $closure, string $name) {
|
||||||
|
$parameters = collect((new ReflectionFunction($closure))->getParameters())
|
||||||
|
->map(function (ReflectionParameter $param) {
|
||||||
|
$type = $param->hasType() ? $param->getType() . ' ' : '';
|
||||||
|
|
||||||
|
$default = $param->isOptional() && $param->isDefaultValueAvailable()
|
||||||
|
? ' = ' . var_export($param->getDefaultValue(), true)
|
||||||
|
: '';
|
||||||
|
|
||||||
|
return $type . '$' . $param->getName() . $default;
|
||||||
|
})
|
||||||
|
->join(', ');
|
||||||
|
|
||||||
|
return compact('name', 'parameters');
|
||||||
|
})->values()->all();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
echo json_encode($pest->config());
|
||||||
109
tests/Feature/Migrations/GroupPymeRuralTenantsTest.php
Normal file
109
tests/Feature/Migrations/GroupPymeRuralTenantsTest.php
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Migrations;
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class GroupPymeRuralTenantsTest extends TestCase
|
||||||
|
{
|
||||||
|
public function test_it_groups_the_futbol_and_desfile_tenants_under_pyme_rural(): void
|
||||||
|
{
|
||||||
|
$this->createSchema();
|
||||||
|
|
||||||
|
$now = now();
|
||||||
|
$onTicketClientId = DB::table('clients')->insertGetId([
|
||||||
|
'code' => 'onticket',
|
||||||
|
'name' => 'OnTicket',
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
]);
|
||||||
|
DB::table('tenants')->insert([
|
||||||
|
['client_id' => $onTicketClientId, 'codigo' => 'onticket'],
|
||||||
|
['client_id' => $onTicketClientId, 'codigo' => 'fiesta_futbol_infantil'],
|
||||||
|
['client_id' => $onTicketClientId, 'codigo' => 'desfile_pura_tendencia'],
|
||||||
|
]);
|
||||||
|
DB::table('integrations')->insert([
|
||||||
|
'integration_code' => 'email',
|
||||||
|
'name' => 'Email',
|
||||||
|
]);
|
||||||
|
$instanceId = DB::table('integration_instances')->insertGetId([
|
||||||
|
'integration_code' => 'email',
|
||||||
|
'name' => 'OnTicket email',
|
||||||
|
'integration_data' => null,
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
]);
|
||||||
|
DB::table('client_integrations')->insert([
|
||||||
|
'client_id' => $onTicketClientId,
|
||||||
|
'integration_code' => 'email',
|
||||||
|
'integration_instance_id' => $instanceId,
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$migration = require database_path(
|
||||||
|
'migrations/2026_09_21_020000_group_pyme_rural_tenants.php'
|
||||||
|
);
|
||||||
|
$migration->up();
|
||||||
|
|
||||||
|
$pymeRuralClient = DB::table('clients')->where('code', 'pyme_rural')->sole();
|
||||||
|
$this->assertSame('Pyme Rural', $pymeRuralClient->name);
|
||||||
|
$this->assertSame(2, DB::table('tenants')
|
||||||
|
->whereIn('codigo', ['fiesta_futbol_infantil', 'desfile_pura_tendencia'])
|
||||||
|
->where('client_id', $pymeRuralClient->id)
|
||||||
|
->count());
|
||||||
|
$this->assertSame($onTicketClientId, DB::table('tenants')
|
||||||
|
->where('codigo', 'onticket')
|
||||||
|
->value('client_id'));
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('client_integrations', [
|
||||||
|
'client_id' => $pymeRuralClient->id,
|
||||||
|
'integration_code' => 'email',
|
||||||
|
'integration_instance_id' => $instanceId,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$migration->down();
|
||||||
|
|
||||||
|
$this->assertSame(2, DB::table('tenants')
|
||||||
|
->whereIn('codigo', ['fiesta_futbol_infantil', 'desfile_pura_tendencia'])
|
||||||
|
->where('client_id', $onTicketClientId)
|
||||||
|
->count());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createSchema(): void
|
||||||
|
{
|
||||||
|
Schema::create('clients', function (Blueprint $table): void {
|
||||||
|
$table->id();
|
||||||
|
$table->string('code')->unique();
|
||||||
|
$table->string('name');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
Schema::create('tenants', function (Blueprint $table): void {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('client_id');
|
||||||
|
$table->string('codigo')->unique();
|
||||||
|
});
|
||||||
|
Schema::create('integrations', function (Blueprint $table): void {
|
||||||
|
$table->string('integration_code')->unique();
|
||||||
|
$table->string('name');
|
||||||
|
});
|
||||||
|
Schema::create('integration_instances', function (Blueprint $table): void {
|
||||||
|
$table->id();
|
||||||
|
$table->string('integration_code');
|
||||||
|
$table->string('name');
|
||||||
|
$table->longText('integration_data')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
Schema::create('client_integrations', function (Blueprint $table): void {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('client_id');
|
||||||
|
$table->string('integration_code');
|
||||||
|
$table->foreignId('integration_instance_id');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->unique(['client_id', 'integration_code']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,6 +55,14 @@ class DesfilePuraTendenciaSeederTest extends TestCase
|
|||||||
'site_title' => 'Fiesta Fútbol Infantil',
|
'site_title' => 'Fiesta Fútbol Infantil',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$pymeRuralClientId = DB::table('clients')->where('code', 'pyme_rural')->value('id');
|
||||||
|
$this->assertNotNull($pymeRuralClientId);
|
||||||
|
$this->assertSame('Pyme Rural', DB::table('clients')->where('id', $pymeRuralClientId)->value('name'));
|
||||||
|
$this->assertSame(2, DB::table('tenants')
|
||||||
|
->whereIn('codigo', ['fiesta_futbol_infantil', 'desfile_pura_tendencia'])
|
||||||
|
->where('client_id', $pymeRuralClientId)
|
||||||
|
->count());
|
||||||
|
|
||||||
foreach ([
|
foreach ([
|
||||||
'fiesta_futbol_infantil' => 'futbol_infantil_favicon.png',
|
'fiesta_futbol_infantil' => 'futbol_infantil_favicon.png',
|
||||||
'desfile_pura_tendencia' => 'pura_tendencia_favicon.png',
|
'desfile_pura_tendencia' => 'pura_tendencia_favicon.png',
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
namespace Tests\Feature\Seeders;
|
namespace Tests\Feature\Seeders;
|
||||||
|
|
||||||
use App\Shared\Attachable\Enums\AttachmentType;
|
|
||||||
use App\Shared\Attachable\Models\Attachment;
|
|
||||||
use App\Domains\Core\Authorization\Enums\RoleCode;
|
use App\Domains\Core\Authorization\Enums\RoleCode;
|
||||||
use App\Domains\Core\Authorization\Models\Role;
|
use App\Domains\Core\Authorization\Models\Role;
|
||||||
use App\Domains\Core\Menu\Models\Menu;
|
use App\Domains\Core\Menu\Models\Menu;
|
||||||
use App\Domains\Core\Tenant\Models\Tenant;
|
use App\Domains\Core\Tenant\Models\Tenant;
|
||||||
|
use App\Shared\Attachable\Enums\AttachmentType;
|
||||||
|
use App\Shared\Attachable\Models\Attachment;
|
||||||
use Database\Seeders\AuthorizationSeeder;
|
use Database\Seeders\AuthorizationSeeder;
|
||||||
use Database\Seeders\MenuSeeder;
|
use Database\Seeders\MenuSeeder;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
@@ -183,6 +183,49 @@ class MenuSeederTest extends TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_it_assigns_event_menus_only_to_onticket(): void
|
||||||
|
{
|
||||||
|
$onTicket = $this->createTenant('onticket');
|
||||||
|
$otherTenant = $this->createTenant('other');
|
||||||
|
|
||||||
|
$this->seed(AuthorizationSeeder::class);
|
||||||
|
$this->seed(MenuSeeder::class);
|
||||||
|
|
||||||
|
foreach ([
|
||||||
|
'event.index' => '/',
|
||||||
|
'event.category' => '/eventos/categoria/:id',
|
||||||
|
'event.detail' => '/evento/:id',
|
||||||
|
] as $code => $route) {
|
||||||
|
$menu = Menu::query()->where('code', $code)->firstOrFail();
|
||||||
|
|
||||||
|
$this->assertSame($route, $menu->route);
|
||||||
|
$this->assertTrue($onTicket->menues()->where('menues.code', $code)->exists());
|
||||||
|
$this->assertFalse($otherTenant->menues()->where('menues.code', $code)->exists());
|
||||||
|
$this->assertTrue(
|
||||||
|
Role::query()
|
||||||
|
->where('codigo', RoleCode::User->value)
|
||||||
|
->firstOrFail()
|
||||||
|
->menus()
|
||||||
|
->where('menues.code', $code)
|
||||||
|
->exists()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$productCategory = Menu::query()->where('code', 'product.category')->firstOrFail();
|
||||||
|
|
||||||
|
$this->assertSame('/categoria/:id', $productCategory->route);
|
||||||
|
$this->assertFalse($onTicket->menues()->where('menues.code', 'product.category')->exists());
|
||||||
|
$this->assertTrue($otherTenant->menues()->where('menues.code', 'product.category')->exists());
|
||||||
|
$this->assertTrue(
|
||||||
|
Role::query()
|
||||||
|
->where('codigo', RoleCode::User->value)
|
||||||
|
->firstOrFail()
|
||||||
|
->menus()
|
||||||
|
->where('menues.code', 'product.category')
|
||||||
|
->exists()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_it_seeds_the_account_menu_hierarchy(): void
|
public function test_it_seeds_the_account_menu_hierarchy(): void
|
||||||
{
|
{
|
||||||
$tenant = $this->createTenant('account_tenant');
|
$tenant = $this->createTenant('account_tenant');
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace Tests\Feature\Seeders;
|
namespace Tests\Feature\Seeders;
|
||||||
|
|
||||||
use App\Shared\Attachable\Models\Attachment;
|
|
||||||
use App\Domains\Core\Tenant\Models\Tenant;
|
|
||||||
use App\Domains\Core\Tenant\Models\AdminWebsiteType;
|
use App\Domains\Core\Tenant\Models\AdminWebsiteType;
|
||||||
|
use App\Domains\Core\Tenant\Models\Tenant;
|
||||||
|
use App\Shared\Attachable\Models\Attachment;
|
||||||
use Database\Seeders\SocialMediaSeeder;
|
use Database\Seeders\SocialMediaSeeder;
|
||||||
use Database\Seeders\TenantSeeder;
|
use Database\Seeders\TenantSeeder;
|
||||||
use Database\Seeders\WebsiteTypeSeeder;
|
use Database\Seeders\WebsiteTypeSeeder;
|
||||||
@@ -150,6 +150,8 @@ class TenantSeederTest extends TestCase
|
|||||||
->with('websiteExtras.websiteTypeExtra')
|
->with('websiteExtras.websiteTypeExtra')
|
||||||
->sole();
|
->sole();
|
||||||
|
|
||||||
|
$this->assertSame('pyme_rural', $fiesta->client->code);
|
||||||
|
$this->assertSame('Pyme Rural', $fiesta->client->name);
|
||||||
$this->assertSame('onticket', $fiesta->storefront_website_type_code);
|
$this->assertSame('onticket', $fiesta->storefront_website_type_code);
|
||||||
$this->assertSame('onticket', $fiesta->admin_website_type_code);
|
$this->assertSame('onticket', $fiesta->admin_website_type_code);
|
||||||
$this->assertSame('full', $fiesta->cart_editing_policy->value);
|
$this->assertSame('full', $fiesta->cart_editing_policy->value);
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
namespace Tests\Feature\Tenant;
|
namespace Tests\Feature\Tenant;
|
||||||
|
|
||||||
|
use App\Domains\Commerce\Catalog\Models\Category;
|
||||||
|
use App\Domains\Core\Authorization\Enums\RoleCode;
|
||||||
|
use App\Domains\Core\Authorization\Models\Role;
|
||||||
|
use App\Domains\Core\Menu\Models\Menu;
|
||||||
|
use App\Domains\Core\Tenant\Models\AdminWebsiteType;
|
||||||
|
use App\Domains\Core\Tenant\Models\StorefrontWebsiteType;
|
||||||
|
use App\Domains\Core\Tenant\Models\Tenant;
|
||||||
use App\Shared\Attachable\Enums\AttachmentType;
|
use App\Shared\Attachable\Enums\AttachmentType;
|
||||||
use App\Shared\Attachable\Models\Attachment;
|
use App\Shared\Attachable\Models\Attachment;
|
||||||
use App\Shared\Attachable\Models\AttachmentCrop;
|
use App\Shared\Attachable\Models\AttachmentCrop;
|
||||||
use App\Domains\Core\Authorization\Enums\RoleCode;
|
|
||||||
use App\Domains\Core\Authorization\Models\Role;
|
|
||||||
use App\Domains\Commerce\Catalog\Models\Category;
|
|
||||||
use App\Domains\Core\Menu\Models\Menu;
|
|
||||||
use App\Domains\Core\Tenant\Models\Tenant;
|
|
||||||
use App\Domains\Core\Tenant\Models\AdminWebsiteType;
|
|
||||||
use App\Domains\Core\Tenant\Models\StorefrontWebsiteType;
|
|
||||||
use Database\Seeders\WebsiteTypeSeeder;
|
use Database\Seeders\WebsiteTypeSeeder;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
@@ -23,6 +23,23 @@ class BootstrapTenantControllerTest extends TestCase
|
|||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
public function test_multi_event_bootstrap_returns_event_categories_instead_of_catalog_categories(): void
|
||||||
|
{
|
||||||
|
$this->seed(WebsiteTypeSeeder::class);
|
||||||
|
$tenant = $this->createTenant();
|
||||||
|
$tenant->update(['storefront_website_type_code' => 'onticket_multi_event']);
|
||||||
|
$tenant->categories()->create(['nombre' => 'Producto']);
|
||||||
|
$eventCategory = $tenant->eventCategories()->create(['nombre' => 'Música']);
|
||||||
|
|
||||||
|
$this->getJson('/api/tenants/bootstrap?dominio=acme.com&path=%2F')
|
||||||
|
->assertOk()
|
||||||
|
->assertJsonMissingPath('data.categories')
|
||||||
|
->assertJsonCount(1, 'data.event_categories')
|
||||||
|
->assertJsonPath('data.event_categories.0.id', $eventCategory->id)
|
||||||
|
->assertJsonPath('data.event_categories.0.nombre', 'Música')
|
||||||
|
->assertJsonPath('data.event_categories.0.subcategories', []);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_it_bootstraps_a_tenant_by_domain(): void
|
public function test_it_bootstraps_a_tenant_by_domain(): void
|
||||||
{
|
{
|
||||||
$hdrKey = (string) Str::uuid();
|
$hdrKey = (string) Str::uuid();
|
||||||
|
|||||||
Reference in New Issue
Block a user