feat(website-type): add new color fields and update related methods in WebsiteType model and service

This commit is contained in:
2026-07-31 12:55:40 -03:00
parent 6858b387c3
commit b478c23f3b
7 changed files with 164 additions and 18 deletions

View File

@@ -17,6 +17,12 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
'secondary_color',
'danger_color',
'success_color',
'warning_color',
'body_color',
'darker_body_color',
'surface_color',
'background_color',
'border_color',
'login_header_footer_color',
'site_logo',
])]

View File

@@ -21,27 +21,58 @@ class WebsiteTypeService
*/
public function create(array $data): WebsiteType
{
return DB::transaction(function () use ($data): WebsiteType {
return $this->save(new WebsiteType, $data);
}
/**
* Create or update a website type and replace its site logo when provided.
*
* @param array<string, mixed> $attributes
* @param array<string, mixed> $values
*/
public function updateOrCreate(array $attributes, array $values = []): WebsiteType
{
/** @var WebsiteType $websiteType */
$websiteType = WebsiteType::query()->firstOrNew($attributes);
return $this->save($websiteType, [...$attributes, ...$values]);
}
/**
* @param array<string, mixed> $data
*/
private function save(WebsiteType $websiteType, array $data): WebsiteType
{
return DB::transaction(function () use ($websiteType, $data): WebsiteType {
$hasSiteLogo = array_key_exists('site_logo', $data);
$siteLogo = $data['site_logo'] ?? null;
$previousSiteLogo = $websiteType->exists
? $websiteType->siteLogo()->first()
: null;
unset($data['site_logo']);
$siteLogoAttachmentId = null;
if ($hasSiteLogo) {
$attachment = null;
if ($siteLogo) {
$attachment = Str::isUuid($siteLogo)
? Attachment::query()->where('key', $siteLogo)->first()
: $this->attachmentService->store($siteLogo, 'website-types');
if ($attachment) {
$siteLogoAttachmentId = $attachment->id;
if ($siteLogo) {
$attachment = is_string($siteLogo) && Str::isUuid($siteLogo)
? Attachment::query()->where('key', $siteLogo)->first()
: $this->attachmentService->store($siteLogo, 'website-types');
}
$data['site_logo'] = $attachment?->id;
}
$data['site_logo'] = $siteLogoAttachmentId;
$websiteType->fill($data)->save();
/** @var WebsiteType $websiteType */
$websiteType = WebsiteType::query()->create($data);
if (
$hasSiteLogo
&& $previousSiteLogo instanceof Attachment
&& $previousSiteLogo->id !== $websiteType->site_logo
) {
$this->attachmentService->delete($previousSiteLogo);
}
return $websiteType;
});

View File

@@ -14,7 +14,13 @@ return new class extends Migration
$table->string('secondary_color')->nullable()->after('primary_color');
$table->string('danger_color')->nullable()->after('secondary_color');
$table->string('success_color')->nullable()->after('danger_color');
$table->string('login_header_footer_color')->nullable()->after('success_color');
$table->string('warning_color')->nullable()->after('success_color');
$table->string('body_color')->nullable()->after('warning_color');
$table->string('darker_body_color')->nullable()->after('body_color');
$table->string('surface_color')->nullable()->after('darker_body_color');
$table->string('background_color')->nullable()->after('surface_color');
$table->string('border_color')->nullable()->after('background_color');
$table->string('login_header_footer_color')->nullable()->after('border_color');
$table->unsignedBigInteger('site_logo')->nullable()->after('login_header_footer_color');
$table->foreign('site_logo')
@@ -37,6 +43,12 @@ return new class extends Migration
'secondary_color',
'danger_color',
'success_color',
'warning_color',
'body_color',
'darker_body_color',
'surface_color',
'background_color',
'border_color',
'login_header_footer_color',
'site_logo',
]);

View File

@@ -2,16 +2,37 @@
namespace Database\Seeders;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Services\WebsiteTypeService;
use Illuminate\Database\Seeder;
use Illuminate\Http\UploadedFile;
use RuntimeException;
class WebsiteTypeSeeder extends Seeder
{
private const PRESENTATION = [
'primary_color' => '#FF7006',
'secondary_color' => '#777777',
'danger_color' => '#E04A4A',
'success_color' => '#81BC73',
'warning_color' => '#81BC73',
'body_color' => '#666666',
'darker_body_color' => '#333333',
'surface_color' => '#ffffff',
'background_color' => '#f8f8f8',
'border_color' => '#f8f8f8',
];
public function __construct(private readonly WebsiteTypeService $websiteTypeService) {}
public function run(): void
{
$shopIt = WebsiteType::query()->updateOrCreate(
$shopIt = $this->websiteTypeService->updateOrCreate(
['codigo' => 'shopit'],
['nombre' => 'ShopIt'],
[
'nombre' => 'ShopIt',
...self::PRESENTATION,
'site_logo' => $this->onTicketLogo(),
],
);
$shopIt->extras()->updateOrCreate(
@@ -35,9 +56,13 @@ class WebsiteTypeSeeder extends Seeder
],
);
$onTicket = WebsiteType::query()->updateOrCreate(
$onTicket = $this->websiteTypeService->updateOrCreate(
['codigo' => 'onticket'],
['nombre' => 'OnTicket'],
[
'nombre' => 'OnTicket',
...self::PRESENTATION,
'site_logo' => $this->onTicketLogo(),
],
);
$onTicket->extras()->updateOrCreate(
@@ -85,4 +110,21 @@ class WebsiteTypeSeeder extends Seeder
],
);
}
private function onTicketLogo(): UploadedFile
{
$path = public_path('images/website_types/shopit_logo.png');
if (! file_exists($path)) {
throw new RuntimeException("OnTicket logo not found at path: {$path}");
}
return new UploadedFile(
$path,
'onticket_logo.png',
'image/png',
null,
true,
);
}
}

View File

@@ -2,9 +2,11 @@
namespace Tests\Feature\Seeders;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Tenant\Models\WebsiteType;
use Database\Seeders\WebsiteTypeSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class WebsiteTypeSeederTest extends TestCase
@@ -13,10 +15,26 @@ class WebsiteTypeSeederTest extends TestCase
public function test_it_seeds_website_types_and_their_config_schemas_idempotently(): void
{
Storage::fake('s3');
$this->seed(WebsiteTypeSeeder::class);
$this->seed(WebsiteTypeSeeder::class);
$this->assertSame(2, WebsiteType::query()->count());
$this->assertSame(2, Attachment::query()->count());
$expectedPresentation = [
'primary_color' => '#FF7006',
'secondary_color' => '#777777',
'danger_color' => '#E04A4A',
'success_color' => '#81BC73',
'warning_color' => '#81BC73',
'body_color' => '#666666',
'darker_body_color' => '#333333',
'surface_color' => '#ffffff',
'background_color' => '#f8f8f8',
'border_color' => '#f8f8f8',
];
$shopIt = WebsiteType::query()
->where('codigo', 'shopit')
@@ -24,6 +42,9 @@ class WebsiteTypeSeederTest extends TestCase
->sole();
$this->assertSame('ShopIt', $shopIt->nombre);
$this->assertSame($expectedPresentation, $shopIt->only(array_keys($expectedPresentation)));
$this->assertSame('onticket_logo.png', $shopIt->siteLogo->filename);
Storage::disk('s3')->assertExists($shopIt->siteLogo->path);
$this->assertSame(['carousel'], $shopIt->extras->pluck('codigo')->all());
$this->assertSame('Carrusel principal', $shopIt->extras->sole()->nombre);
$this->assertSame([
@@ -45,6 +66,10 @@ class WebsiteTypeSeederTest extends TestCase
->sole();
$this->assertSame('OnTicket', $onTicket->nombre);
$this->assertSame($expectedPresentation, $onTicket->only(array_keys($expectedPresentation)));
$this->assertSame('onticket_logo.png', $onTicket->siteLogo->filename);
Storage::disk('s3')->assertExists($onTicket->siteLogo->path);
$this->assertNotSame($shopIt->site_logo, $onTicket->site_logo);
$this->assertEqualsCanonicalizing(
['heroConfig', 'eventConfig'],
$onTicket->extras->pluck('codigo')->all(),

View File

@@ -27,6 +27,12 @@ class WebsiteExtrasTest extends TestCase
'secondary_color',
'danger_color',
'success_color',
'warning_color',
'body_color',
'darker_body_color',
'surface_color',
'background_color',
'border_color',
'login_header_footer_color',
'site_logo',
'created_at',
@@ -73,6 +79,12 @@ class WebsiteExtrasTest extends TestCase
'secondary_color' => '#222222',
'danger_color' => '#ff0000',
'success_color' => '#00aa55',
'warning_color' => '#ffaa00',
'body_color' => '#666666',
'darker_body_color' => '#333333',
'surface_color' => '#ffffff',
'background_color' => '#f8f8f8',
'border_color' => '#dddddd',
'login_header_footer_color' => '#333333',
'site_logo' => $siteLogo->id,
]);
@@ -100,6 +112,12 @@ class WebsiteExtrasTest extends TestCase
$this->assertSame('#222222', $type->secondary_color);
$this->assertSame('#ff0000', $type->danger_color);
$this->assertSame('#00aa55', $type->success_color);
$this->assertSame('#ffaa00', $type->warning_color);
$this->assertSame('#666666', $type->body_color);
$this->assertSame('#333333', $type->darker_body_color);
$this->assertSame('#ffffff', $type->surface_color);
$this->assertSame('#f8f8f8', $type->background_color);
$this->assertSame('#dddddd', $type->border_color);
$this->assertSame('#333333', $type->login_header_footer_color);
$this->assertTrue($type->siteLogo()->firstOrFail()->is($siteLogo));
$this->assertSame($type->codigo, $typeExtra->website_type_code);

View File

@@ -24,6 +24,12 @@ class WebsiteTypeServiceTest extends TestCase
'secondary_color' => '#222222',
'danger_color' => '#ff0000',
'success_color' => '#00aa55',
'warning_color' => '#ffaa00',
'body_color' => '#666666',
'darker_body_color' => '#333333',
'surface_color' => '#ffffff',
'background_color' => '#f8f8f8',
'border_color' => '#dddddd',
'login_header_footer_color' => '#333333',
'site_logo' => UploadedFile::fake()->image('site-logo.png'),
]);
@@ -37,6 +43,12 @@ class WebsiteTypeServiceTest extends TestCase
$this->assertDatabaseHas('website_type', [
'codigo' => 'marketplace',
'dominio' => 'marketplace.test',
'warning_color' => '#ffaa00',
'body_color' => '#666666',
'darker_body_color' => '#333333',
'surface_color' => '#ffffff',
'background_color' => '#f8f8f8',
'border_color' => '#dddddd',
'login_header_footer_color' => '#333333',
'site_logo' => $siteLogo->id,
]);