From e687edd69271332092c651caa00eae2300290589 Mon Sep 17 00:00:00 2001 From: Bart Potmalnik <20015942+bpotmalnik@users.noreply.github.com> Date: Fri, 29 May 2026 14:05:39 +0200 Subject: [PATCH] fix(attributes): expose and apply default_value in the admin panel Fixes: https://github.com/lunarphp/lunar/issues/1958 --- .../admin/resources/lang/ar/attribute.php | 6 +- .../admin/resources/lang/bg/attribute.php | 6 +- .../admin/resources/lang/de/attribute.php | 6 +- .../admin/resources/lang/en/attribute.php | 4 ++ .../admin/resources/lang/es/attribute.php | 6 +- .../admin/resources/lang/fa/attribute.php | 6 +- .../admin/resources/lang/fr/attribute.php | 6 +- .../admin/resources/lang/hr/attribute.php | 6 +- .../admin/resources/lang/hu/attribute.php | 6 +- .../admin/resources/lang/mn/attribute.php | 6 +- .../admin/resources/lang/nl/attribute.php | 6 +- .../admin/resources/lang/pl/attribute.php | 6 +- .../admin/resources/lang/pt_BR/attribute.php | 6 +- .../admin/resources/lang/ro/attribute.php | 6 +- .../admin/resources/lang/tr/attribute.php | 6 +- .../admin/resources/lang/vi/attribute.php | 6 +- .../AttributesRelationManager.php | 8 +++ .../admin/src/Support/Forms/AttributeData.php | 6 +- .../AttributesRelationManagerTest.php | 57 +++++++++++++++++++ .../ProductResource/Pages/EditProductTest.php | 48 ++++++++++++++++ 20 files changed, 197 insertions(+), 16 deletions(-) diff --git a/packages/admin/resources/lang/ar/attribute.php b/packages/admin/resources/lang/ar/attribute.php index fee62f2551..1e456472f8 100644 --- a/packages/admin/resources/lang/ar/attribute.php +++ b/packages/admin/resources/lang/ar/attribute.php @@ -51,5 +51,9 @@ 'label' => 'قواعد التحقق', 'helper' => 'القواعد الخاصة بحقل السمة، مثال: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'القيمة الافتراضية', + 'helper' => 'يُطبَّق كقيمة ابتدائية عند إنشاء سجل جديد بهذه السمة.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/bg/attribute.php b/packages/admin/resources/lang/bg/attribute.php index c0aeb82442..f37e2f111c 100644 --- a/packages/admin/resources/lang/bg/attribute.php +++ b/packages/admin/resources/lang/bg/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Правила за валидация', 'helper' => 'Правила за поле на атрибут, пример: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Стойност по подразбиране', + 'helper' => 'Прилага се като начална стойност при създаване на нов запис с този атрибут.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/de/attribute.php b/packages/admin/resources/lang/de/attribute.php index 81854e887e..cd7cf753d7 100644 --- a/packages/admin/resources/lang/de/attribute.php +++ b/packages/admin/resources/lang/de/attribute.php @@ -50,5 +50,9 @@ 'validation_rules' => [ 'label' => 'Validierungsregeln', ], + 'default_value' => [ + 'label' => 'Standardwert', + 'helper' => 'Wird als Anfangswert beim Erstellen eines neuen Eintrags mit diesem Attribut verwendet.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/en/attribute.php b/packages/admin/resources/lang/en/attribute.php index 45e6a96beb..33ef16d4b6 100644 --- a/packages/admin/resources/lang/en/attribute.php +++ b/packages/admin/resources/lang/en/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Validation Rules', 'helper' => 'Rules for attribute field, example: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Default Value', + 'helper' => 'Applied as the initial value when creating a new record with this attribute.', + ], ], ]; diff --git a/packages/admin/resources/lang/es/attribute.php b/packages/admin/resources/lang/es/attribute.php index 5d6945f42f..32cf624d7b 100644 --- a/packages/admin/resources/lang/es/attribute.php +++ b/packages/admin/resources/lang/es/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Reglas de validación', 'helper' => 'Reglas para el campo de atributo, ejemplo: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Valor predeterminado', + 'helper' => 'Se aplica como valor inicial al crear un nuevo registro con este atributo.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/fa/attribute.php b/packages/admin/resources/lang/fa/attribute.php index 45e6a96beb..0383fc2d62 100644 --- a/packages/admin/resources/lang/fa/attribute.php +++ b/packages/admin/resources/lang/fa/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Validation Rules', 'helper' => 'Rules for attribute field, example: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'مقدار پیش‌فرض', + 'helper' => 'به عنوان مقدار اولیه هنگام ایجاد یک رکورد جدید با این ویژگی اعمال می‌شود.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/fr/attribute.php b/packages/admin/resources/lang/fr/attribute.php index e0b10e35d3..62d0dd2612 100644 --- a/packages/admin/resources/lang/fr/attribute.php +++ b/packages/admin/resources/lang/fr/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Règles de validation', 'helper' => 'Règles pour le champ attribut, exemple : min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Valeur par défaut', + 'helper' => 'Appliquée comme valeur initiale lors de la création d\'un nouvel enregistrement avec cet attribut.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/hr/attribute.php b/packages/admin/resources/lang/hr/attribute.php index f45e15b1c6..aadff8ecd3 100644 --- a/packages/admin/resources/lang/hr/attribute.php +++ b/packages/admin/resources/lang/hr/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Pravila validacije', 'helper' => 'Pravila za polje atributa, primjer: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Zadana vrijednost', + 'helper' => 'Primjenjuje se kao početna vrijednost pri stvaranju novog zapisa s ovim atributom.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/hu/attribute.php b/packages/admin/resources/lang/hu/attribute.php index 7d9c496f2a..3691d26220 100644 --- a/packages/admin/resources/lang/hu/attribute.php +++ b/packages/admin/resources/lang/hu/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Érvényesítési szabályok', 'helper' => 'Szabályok az attribútum mezőhöz, pl.: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Alapértelmezett érték', + 'helper' => 'Kezdeti értékként kerül alkalmazásra új rekord létrehozásakor ezzel az attribútummal.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/mn/attribute.php b/packages/admin/resources/lang/mn/attribute.php index 84f83d9d09..509549d67b 100644 --- a/packages/admin/resources/lang/mn/attribute.php +++ b/packages/admin/resources/lang/mn/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Баталгаажуулах дүрэм', 'helper' => 'Атрибутын талбарын дүрэм, жишээ: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Өгөгдмөл утга', + 'helper' => 'Энэ атрибуттай шинэ бичлэг үүсгэхэд анхны утга болгон хэрэглэгдэнэ.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/nl/attribute.php b/packages/admin/resources/lang/nl/attribute.php index 9ac83854d6..cf9c58e972 100644 --- a/packages/admin/resources/lang/nl/attribute.php +++ b/packages/admin/resources/lang/nl/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Validatieregels', 'helper' => 'Regels voor attribuutveld, voorbeeld: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Standaardwaarde', + 'helper' => 'Toegepast als beginwaarde bij het aanmaken van een nieuw record met dit attribuut.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/pl/attribute.php b/packages/admin/resources/lang/pl/attribute.php index c178f427f7..1df2fb05db 100644 --- a/packages/admin/resources/lang/pl/attribute.php +++ b/packages/admin/resources/lang/pl/attribute.php @@ -50,5 +50,9 @@ 'validation_rules' => [ 'label' => 'Reguły walidacji', ], + 'default_value' => [ + 'label' => 'Wartość domyślna', + 'helper' => 'Stosowana jako wartość początkowa podczas tworzenia nowego rekordu z tym atrybutem.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/pt_BR/attribute.php b/packages/admin/resources/lang/pt_BR/attribute.php index 0ed27a0822..8e39170a8f 100644 --- a/packages/admin/resources/lang/pt_BR/attribute.php +++ b/packages/admin/resources/lang/pt_BR/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Regras de validação', 'helper' => 'Regras para o campo do atributo, exemplo: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Valor padrão', + 'helper' => 'Aplicado como valor inicial ao criar um novo registro com este atributo.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/ro/attribute.php b/packages/admin/resources/lang/ro/attribute.php index 2ed68dd12d..6ff764ea86 100644 --- a/packages/admin/resources/lang/ro/attribute.php +++ b/packages/admin/resources/lang/ro/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Reguli de validare', 'helper' => 'Reguli pentru câmpul atribut, de ex.: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Valoare implicită', + 'helper' => 'Aplicată ca valoare inițială la crearea unui nou înregistrări cu acest atribut.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/tr/attribute.php b/packages/admin/resources/lang/tr/attribute.php index ad46c19cfc..44c6fa49e8 100644 --- a/packages/admin/resources/lang/tr/attribute.php +++ b/packages/admin/resources/lang/tr/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Doğrulama Kuralları', 'helper' => 'Özellik alanı için kurallar, örnek: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Varsayılan değer', + 'helper' => 'Bu özellikle yeni bir kayıt oluşturulurken başlangıç değeri olarak uygulanır.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/resources/lang/vi/attribute.php b/packages/admin/resources/lang/vi/attribute.php index ab66653938..464fa43a51 100644 --- a/packages/admin/resources/lang/vi/attribute.php +++ b/packages/admin/resources/lang/vi/attribute.php @@ -51,5 +51,9 @@ 'label' => 'Quy tắc xác thực', 'helper' => 'Quy tắc cho trường thuộc tính, ví dụ: min:1|max:10|...', ], + 'default_value' => [ + 'label' => 'Giá trị mặc định', + 'helper' => 'Được áp dụng làm giá trị ban đầu khi tạo bản ghi mới với thuộc tính này.', + ], ], -]; +]; \ No newline at end of file diff --git a/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php b/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php index 230dfbe965..4e3d4ab1b2 100644 --- a/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php +++ b/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php @@ -123,6 +123,14 @@ class_basename($fieldType) ->helperText( __('lunarpanel::attribute.form.validation_rules.helper') ), + TextInput::make('default_value')->label( + __('lunarpanel::attribute.form.default_value.label') + ) + ->string() + ->nullable() + ->helperText( + __('lunarpanel::attribute.form.default_value.helper') + ), Grid::make(1) ->schema(function (Get $get) { return AttributeData::getConfigurationFields($get('type')); diff --git a/packages/admin/src/Support/Forms/AttributeData.php b/packages/admin/src/Support/Forms/AttributeData.php index ce2ad59333..8199ae8895 100644 --- a/packages/admin/src/Support/Forms/AttributeData.php +++ b/packages/admin/src/Support/Forms/AttributeData.php @@ -59,7 +59,11 @@ public function getFilamentComponent(Attribute $attribute): Component $value = $this->unwrapFieldValue($state); if ($value === null) { - $value = $this->unwrapFieldValue((new $attribute->type)->getValue()); + if (filled($attribute->default_value)) { + $value = $attribute->default_value; + } else { + $value = $this->unwrapFieldValue((new $attribute->type)->getValue()); + } } if ($attribute->type === TranslatedTextFieldType::class) { diff --git a/tests/admin/Feature/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManagerTest.php b/tests/admin/Feature/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManagerTest.php index b32e0e704f..01d1623885 100644 --- a/tests/admin/Feature/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManagerTest.php +++ b/tests/admin/Feature/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManagerTest.php @@ -172,6 +172,63 @@ ])->assertHasNoTableActionErrors(); }); +it('can create an attribute with a default value', function () { + $lang = Language::factory()->create([ + 'default' => true, + 'code' => 'en', + ]); + + $this->asStaff(); + + $attributeGroup = AttributeGroup::factory()->create(); + + Livewire::test(AttributesRelationManager::class, [ + 'ownerRecord' => $attributeGroup, + 'pageClass' => EditAttributeGroup::class, + ])->callTableAction(CreateAction::class, data: [ + 'name.'.$lang->code => 'Price', + 'type' => Number::class, + 'handle' => 'price', + 'default_value' => '99', + 'configuration' => [], + ])->assertHasNoTableActionErrors(); + + $this->assertDatabaseHas((new Attribute)->getTable(), [ + 'attribute_group_id' => $attributeGroup->id, + 'handle' => 'price', + 'default_value' => '99', + ]); +}); + +it('can edit an attribute default value', function () { + Language::factory()->create([ + 'default' => true, + 'code' => 'en', + ]); + + $this->asStaff(); + + $attributeGroup = AttributeGroup::factory()->create(); + + $attribute = Attribute::factory()->create([ + 'attribute_group_id' => $attributeGroup->id, + 'type' => Number::class, + 'default_value' => null, + ]); + + Livewire::test(AttributesRelationManager::class, [ + 'ownerRecord' => $attributeGroup, + 'pageClass' => EditAttributeGroup::class, + ])->callTableAction(EditAction::class, $attribute, data: [ + 'default_value' => '42', + ])->assertHasNoTableActionErrors(); + + $this->assertDatabaseHas((new Attribute)->getTable(), [ + 'id' => $attribute->id, + 'default_value' => '42', + ]); +}); + it('hydrates dropdown lookups when editing attributes', function () { Language::factory()->create([ 'default' => true, diff --git a/tests/admin/Feature/Filament/Resources/ProductResource/Pages/EditProductTest.php b/tests/admin/Feature/Filament/Resources/ProductResource/Pages/EditProductTest.php index 89da4a052f..ee9552eb96 100644 --- a/tests/admin/Feature/Filament/Resources/ProductResource/Pages/EditProductTest.php +++ b/tests/admin/Feature/Filament/Resources/ProductResource/Pages/EditProductTest.php @@ -421,3 +421,51 @@ function createTranslatedRichTextProductAttribute(Product $product, string $hand ->assertDontSee(__('lunarpanel::product.status.availability.hidden_from_guests')) ->assertDontSee(__('lunarpanel::product.status.availability.no_default_customer_group')); }); + +it('applies attribute default_value when product has no value for that attribute', function () { + Language::factory()->create(['default' => true]); + + TaxClass::factory()->create(['default' => true]); + + $product = Product::factory()->create(); + ProductVariant::factory()->create(['product_id' => $product->id]); + + $group = AttributeGroup::factory()->create([ + 'attributable_type' => 'product', + 'name' => ['en' => 'Details'], + 'handle' => 'details', + 'position' => 1, + ]); + + $attribute = Attribute::factory()->create([ + 'attribute_type' => 'product', + 'attribute_group_id' => $group->id, + 'position' => 1, + 'name' => ['en' => 'Quantity'], + 'handle' => 'quantity', + 'type' => Number::class, + 'default_value' => '99', + 'required' => false, + 'system' => false, + 'searchable' => false, + ]); + + DB::table('lunar_attributables')->insert([ + 'attribute_id' => $attribute->id, + 'attributable_type' => 'product_type', + 'attributable_id' => $product->productType->id, + ]); + + // The product has no value for 'quantity' yet + expect($product->attr('quantity'))->toBeNull(); + + $this->asStaff(admin: true); + + // Saving without explicitly setting quantity should persist the default value + Livewire::test(EditProduct::class, [ + 'record' => $product->getRouteKey(), + 'pageClass' => 'productEdit', + ])->call('save')->assertHasNoFormErrors(); + + expect($product->refresh()->attr('quantity'))->toBe(99); +});