From e8c6eb8c4051ba178bd3a54cf25d64c34ff0c4f3 Mon Sep 17 00:00:00 2001 From: Glenn Jacobs Date: Wed, 14 Feb 2024 21:48:35 +0000 Subject: [PATCH 01/12] Improved dashboard KPIs --- packages/admin/resources/lang/en/widgets.php | 32 +++++++++---------- .../Dashboard/Orders/OrderStatsOverview.php | 28 ++++++++-------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/admin/resources/lang/en/widgets.php b/packages/admin/resources/lang/en/widgets.php index 71e042746f..83f2f3e09f 100644 --- a/packages/admin/resources/lang/en/widgets.php +++ b/packages/admin/resources/lang/en/widgets.php @@ -11,16 +11,16 @@ 'neutral' => 'No change compared to yesterday', ], 'stat_two' => [ - 'label' => 'Orders this week', - 'increase' => ':percentage% increase from :count last week', - 'decrease' => ':percentage% decrease from :count last week', - 'neutral' => 'No change compared to last week', + 'label' => 'Orders past 7 days', + 'increase' => ':percentage% increase from :count last period', + 'decrease' => ':percentage% decrease from :count last period', + 'neutral' => 'No change compared to last period', ], 'stat_three' => [ - 'label' => 'Orders this month', - 'increase' => ':percentage% increase from :count last month', - 'decrease' => ':percentage% decrease from :count last month', - 'neutral' => 'No change compared to last month', + 'label' => 'Orders past 30 days', + 'increase' => ':percentage% increase from :count last period', + 'decrease' => ':percentage% decrease from :count last period', + 'neutral' => 'No change compared to last period', ], 'stat_four' => [ 'label' => 'Sales today', @@ -29,16 +29,16 @@ 'neutral' => 'No change compared to yesterday', ], 'stat_five' => [ - 'label' => 'Sales this week', - 'increase' => ':percentage% increase from :total last week', - 'decrease' => ':percentage% decrease from :total last week', - 'neutral' => 'No change compared to last week', + 'label' => 'Sales past 7 days', + 'increase' => ':percentage% increase from :total last period', + 'decrease' => ':percentage% decrease from :total last period', + 'neutral' => 'No change compared to last period', ], 'stat_six' => [ - 'label' => 'Sales this month', - 'increase' => ':percentage% increase from :total last month', - 'decrease' => ':percentage% decrease from :total last month', - 'neutral' => 'No change compared to last month', + 'label' => 'Sales past 30 days', + 'increase' => ':percentage% increase from :total last period', + 'decrease' => ':percentage% decrease from :total last period', + 'neutral' => 'No change compared to last period', ], ], 'order_totals_chart' => [ diff --git a/packages/admin/src/Filament/Widgets/Dashboard/Orders/OrderStatsOverview.php b/packages/admin/src/Filament/Widgets/Dashboard/Orders/OrderStatsOverview.php index ae8be594a6..b56dbad367 100644 --- a/packages/admin/src/Filament/Widgets/Dashboard/Orders/OrderStatsOverview.php +++ b/packages/admin/src/Filament/Widgets/Dashboard/Orders/OrderStatsOverview.php @@ -25,24 +25,24 @@ protected function getStats(): array 'monthOverflow' => false, ]); - $currentMonth = $this->getOrderQuery( - from: $date->clone()->startOfMonth(), + $current30Days = $this->getOrderQuery( + from: $date->clone()->subDays(30), to: $date->clone(), ); - $previousMonth = $this->getOrderQuery( - from: $date->clone()->subMonth()->startOfMonth(), - to: $date->clone(), + $previous30Days = $this->getOrderQuery( + from: $date->clone()->subDays(60), + to: $date->clone()->subDays(30), ); - $currentWeek = $this->getOrderQuery( - from: $date->clone()->startOfWeek(), + $current7Days = $this->getOrderQuery( + from: $date->clone()->subDays(7), to: $date->clone(), ); - $previousWeek = $this->getOrderQuery( - from: $date->clone()->subWeek()->startOfWeek(), - to: $date->clone()->subWeek(), + $previous7Days = $this->getOrderQuery( + from: $date->clone()->subDays(14), + to: $date->clone()->subDays(7), ); $today = $this->getOrderQuery( @@ -57,11 +57,11 @@ protected function getStats(): array return [ $this->getStatCount($today, $yesterday, 'stat_one'), - $this->getStatCount($currentWeek, $previousWeek, 'stat_two'), - $this->getStatCount($currentMonth, $previousMonth, 'stat_three'), + $this->getStatCount($current7Days, $previous7Days, 'stat_two'), + $this->getStatCount($current30Days, $previous30Days, 'stat_three'), $this->getStatTotal($today, $yesterday, 'stat_four'), - $this->getStatTotal($currentWeek, $previousWeek, 'stat_five'), - $this->getStatTotal($currentMonth, $previousMonth, 'stat_six'), + $this->getStatTotal($current7Days, $previous7Days, 'stat_five'), + $this->getStatTotal($current30Days, $previous30Days, 'stat_six'), ]; } From 40cbf1b1e6298c4b063b79dc06e2f87467f9f9d8 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Wed, 14 Feb 2024 22:41:47 +0000 Subject: [PATCH 02/12] Feature - Pricing management (#1515) Co-authored-by: Glenn Jacobs --- .phpunit.cache/test-results | 1 + docs/core/reference/pricing.md | 2 +- docs/core/reference/products.md | 18 +- docs/core/upgrading.md | 10 +- packages/admin/resources/dist/lunar-panel.css | 20 +- packages/admin/resources/lang/en/product.php | 11 + .../resources/lang/en/productvariant.php | 3 + .../resources/lang/en/relationmanagers.php | 42 +++- .../Filament/Resources/ProductResource.php | 2 + .../ProductResource/Pages/ListProducts.php | 2 +- .../Pages/ManageProductPricing.php | 87 ++++---- .../Resources/ProductVariantResource.php | 22 ++ .../Pages/ManageVariantPricing.php | 120 ++--------- packages/admin/src/LunarPanelManager.php | 1 + .../Products/ManagesProductPricing.php | 202 ++++++++++++++++++ .../RelationManagers/PriceRelationManager.php | 161 ++++++++++++++ ..._tier_to_min_quantity_on_prices_table.php} | 6 +- .../DataTransferObjects/PricingResponse.php | 2 +- packages/core/src/Base/Traits/HasPrices.php | 6 +- packages/core/src/Managers/PricingManager.php | 16 +- packages/core/src/Models/Price.php | 2 +- .../resources/lang/en/relationmanagers.php | 8 +- .../views/shipping-methods/ship-by.blade.php | 14 +- .../src/Drivers/ShippingMethods/ShipBy.php | 6 +- .../Pages/ManageShippingRates.php | 18 +- .../Pages/ManageProductPricingTest.php | 35 --- .../PriceRelationManagerTest.php | 26 +++ .../Carts/AddOrUpdatePurchasableTest.php | 6 +- .../Unit/Actions/Carts/CalculateLineTest.php | 10 +- .../Unit/Actions/Carts/CreateOrderTest.php | 4 +- .../Actions/Carts/GenerateFingerprintTest.php | 2 +- .../Actions/Carts/GetExistingCartLineTest.php | 4 +- .../core/Unit/Actions/Carts/MergeCartTest.php | 4 +- .../Actions/Carts/RemovePurchasableTest.php | 2 +- .../Unit/Actions/Carts/UpdateCartLineTest.php | 2 +- .../Collections/SortProductsByPriceTest.php | 2 +- tests/core/Unit/Base/ShippingManifestTest.php | 2 +- .../Unit/Base/Traits/CachesPropertiesTest.php | 2 +- .../core/Unit/DiscountTypes/AmountOffTest.php | 66 +++--- .../core/Unit/DiscountTypes/BuyXGetYTest.php | 26 +-- .../UpdateProductPositionsTest.php | 2 +- .../Unit/Managers/DiscountManagerTest.php | 2 +- .../core/Unit/Managers/PricingManagerTest.php | 32 +-- tests/core/Unit/Models/CartTest.php | 26 +-- tests/core/Unit/Models/PriceTest.php | 28 +-- tests/core/Unit/Models/ProductVariantTest.php | 20 +- .../Unit/Pipelines/Cart/ApplyShippingTest.php | 4 +- .../Pipelines/Cart/CalculateLinesTest.php | 2 +- .../Order/Creation/CleanUpOrderLinesTest.php | 4 +- .../Order/Creation/CreateOrderLinesTest.php | 2 +- .../Order/Creation/FillOrderFromCartTest.php | 2 +- tests/shipping/TestUtils.php | 2 +- .../Drivers/ShippingMethods/FlatRateTest.php | 2 +- .../Drivers/ShippingMethods/ShipByTest.php | 10 +- .../Unit/Managers/ShippingManagerTest.php | 6 +- .../Resolvers/ShippingOptionResolverTest.php | 6 +- .../Resolvers/ShippingRateResolverTest.php | 26 +-- 57 files changed, 733 insertions(+), 418 deletions(-) create mode 100644 .phpunit.cache/test-results create mode 100644 packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php create mode 100644 packages/admin/src/Support/RelationManagers/PriceRelationManager.php rename packages/core/database/migrations/{2024_01_31_100000_update_tier_to_quantity_break_on_prices_table.php => 2024_01_31_100000_update_tier_to_min_quantity_on_prices_table.php} (67%) create mode 100644 tests/admin/Feature/Support/RelationManagers/PriceRelationManagerTest.php diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results new file mode 100644 index 0000000000..b43cbdfa87 --- /dev/null +++ b/.phpunit.cache/test-results @@ -0,0 +1 @@ +{"version":"pest_2.33.1","defects":[],"times":{"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_render":0.084,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_customer":0.078,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_order":0.084,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_collection":0.06,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_brand":0.061,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_product":0.065,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\Pages\\EditAttributeGroupTest::__pest_evaluable_it_can_render_attribute_group_edit_page":0.124,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\Pages\\EditAttributeGroupTest::__pest_evaluable_it_can_retrieve_attribute_group_data":0.068,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_render_relation_manager":0.077,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"text\"":0.245,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"richtext\"":0.224,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"dropdown\"":0.234,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"dropdown-with-lookups\"":0.263,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"number\"":0.233,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"number-with-min-max\"":0.26,"P\\Tests\\admin\\Feature\\Filament\\Resources\\BrandResource\\Actions\\SearchTest::__pest_evaluable_it_can_search_brand_by_name_on_brand_list":0.163,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CollectionResources\\Pages\\ManageCollectionChildrenTest::__pest_evaluable_it_can_render_the_collection_children_page":0.092,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CollectionResources\\Pages\\ManageCollectionChildrenTest::__pest_evaluable_it_can_create_child_categories":0.13,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\CreateCustomerTest::__pest_evaluable_it_can_render_customer_create_page":0.092,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\CreateCustomerTest::__pest_evaluable_it_can_create_customer":0.148,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\EditCustomerTest::__pest_evaluable_it_can_render_customer_edit_page":0.111,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\EditCustomerTest::__pest_evaluable_it_can_retrieve_customer_data":0.075,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\EditCustomerTest::__pest_evaluable_it_can_save_customer_data":0.12,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\ListCustomersTest::__pest_evaluable_it_can_render_customer_index_page":0.084,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\ListCustomersTest::__pest_evaluable_it_can_list_customers":0.094,"P\\Tests\\admin\\Feature\\Filament\\Resources\\OrderResource\\Pages\\ManageOrderTest::__pest_evaluable_it_can_render_order_manage_page":0.256,"P\\Tests\\admin\\Feature\\Filament\\Resources\\OrderResource\\Pages\\ManageOrderTest::__pest_evaluable_it_can_download_order_pdf":0.204,"P\\Tests\\admin\\Feature\\Filament\\Resources\\OrderResource\\Pages\\ManageOrderTest::__pest_evaluable_it_can_update_order_status":0.281,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Actions\\SearchTest::__pest_evaluable_it_can_search_product_by_name_on_list":0.117,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\ListProductsTest::__pest_evaluable_it_can_create_product":0.23,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductIdentifiersTest::__pest_evaluable_it_can_render_product_identifiers_page":0.099,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductIdentifiersTest::__pest_evaluable_it_will_show_in_navigation_when_only_one_variant_exists":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductIdentifiersTest::__pest_evaluable_it_will_not_show_in_navigation_when_multiple_variants_exist":0.102,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductIdentifiersTest::__pest_evaluable_it_can_update_variant_identifiers":0.161,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductInventoryTest::__pest_evaluable_it_can_render_product_inventory_page":0.1,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductInventoryTest::__pest_evaluable_it_will_show_in_navigation_when_only_one_variant_exists":0.1,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductInventoryTest::__pest_evaluable_it_will_not_show_in_navigation_when_multiple_variants_exist":0.1,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductInventoryTest::__pest_evaluable_it_can_update_variant_stock_figures":0.153,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductPricingTest::__pest_evaluable_it_can_render_product_prices_create_page":0.103,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductPricingTest::__pest_evaluable_it_will_show_in_navigation_when_only_one_variant_exists":0.104,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductPricingTest::__pest_evaluable_it_will_not_show_in_navigation_when_multiple_variants_exist":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_can_render_product_shipping_page":0.107,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_will_show_in_navigation_when_only_one_variant_exists":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_will_not_show_in_navigation_when_multiple_variants_exist":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_can_update_variant_shipping":0.311,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_can_set_shipping_volume_automatically":0.333,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductUrlsTest::__pest_evaluable_it_can_render_product_urls_create_page":0.108,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_mount_widget":0.062,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_render_collection_tree":0.071,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_create_root_collection":0.085,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_toggle_collection_children":0.099,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_create_child_collection":0.184,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_set_child_collection_as_root":0.107,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_reorder_collections":0.088,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductTypeResource\\Pages\\CreateProductTypeTest::__pest_evaluable_it_can_render_product_type_create_page":0.089,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductTypeResource\\Pages\\CreateProductTypeTest::__pest_evaluable_it_can_create_product_type":0.085,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductTypeResource\\Pages\\CreateProductTypeTest::__pest_evaluable_it_can_associate_attributes":0.112,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductTypeResource\\Pages\\EditProductTypeTest::__pest_evaluable_it_can_associate_attributes":0.135,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\AccessControlTest::__pest_evaluable_it_can_render_acl_page":0.116,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\AccessControlTest::__pest_evaluable_it_can_add_role":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\AccessControlTest::__pest_evaluable_it_can_delete_role":0.108,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\AccessControlTest::__pest_evaluable_it_can_set_permission_to_role":0.086,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\CreateStaffTest::__pest_evaluable_it_can_render_staff_create_page":0.094,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\CreateStaffTest::__pest_evaluable_it_can_create_staff":0.273,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\EditStaffTest::__pest_evaluable_it_can_render_staff_edit_page":0.093,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\EditStaffTest::__pest_evaluable_it_can_retrieve_staff_data":0.071,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\EditStaffTest::__pest_evaluable_it_can_save_staff_data":0.147,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\EditStaffTest::__pest_evaluable_it_can_assign_staff_role_and_permissions":0.203,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\ListStaffTest::__pest_evaluable_it_can_render_staff_index_page":0.093,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\ListStaffTest::__pest_evaluable_it_can_list_staff":0.095,"P\\Tests\\admin\\Feature\\Support\\Extending\\CreatePageExtensionTest::__pest_evaluable_it_can_change_data_before_creation":0.133,"P\\Tests\\admin\\Feature\\Support\\Extending\\CreatePageExtensionTest::__pest_evaluable_it_can_manipulate_model_after_creation":0.13,"P\\Tests\\admin\\Feature\\Support\\Extending\\EditPageExtensionTest::__pest_evaluable_it_can_change_data_before_fill":0.08,"P\\Tests\\admin\\Feature\\Support\\Extending\\EditPageExtensionTest::__pest_evaluable_it_can_change_data_before_save":0.079,"P\\Tests\\admin\\Feature\\Support\\RelationManagers\\MediaRelationManagerTest::__pest_evaluable_it_can_render_relation_manager#dataset \"product\"":0.07,"P\\Tests\\admin\\Feature\\Support\\RelationManagers\\MediaRelationManagerTest::__pest_evaluable_it_can_render_relation_manager#dataset \"brand\"":0.066,"P\\Tests\\admin\\Feature\\Support\\RelationManagers\\PriceRelationManagerTest::__pest_evaluable_it_can_render_relation_manager#dataset \"product\"":0.073,"P\\Tests\\admin\\Unit\\Actions\\Products\\MapVariantsToProductOptionsTest::__pest_evaluable_it_can_map_variants_given_one_set_of_option_values":0.026,"P\\Tests\\admin\\Unit\\Actions\\Products\\MapVariantsToProductOptionsTest::__pest_evaluable_it_can_map_variants_given_three_sets_of_option_values":0.024,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_roles":0.026,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_refreshed_roles":0.026,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_permissions":0.024,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_refreshed_permissions":0.025,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_grouped_permissions":0.024,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_refreshed_grouped_permissions":0.026,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_set_admin":0.023,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_roles_without_admin":0.021,"P\\Tests\\admin\\Unit\\Filament\\Resources\\BrandResource\\Pages\\ManageBrandMediaTest::__pest_evaluable_it_can_return_configured_relation_managers":0.081,"P\\Tests\\admin\\Unit\\Filament\\Resources\\ProductResource\\Pages\\ManageProductMediaTest::__pest_evaluable_it_can_return_configured_relation_managers":0.08,"P\\Tests\\admin\\Unit\\Filament\\Resources\\ProductResource\\RelationManagers\\CustomerGroupRelationManagerTest::__pest_evaluable_it_can_render_relationship_manager":0.065,"P\\Tests\\admin\\Unit\\Livewire\\ActivityLogFeedTest::__pest_evaluable__activity_feed_component__\u2192_can_render":0.056,"P\\Tests\\admin\\Unit\\Livewire\\ActivityLogFeedTest::__pest_evaluable__activity_feed_component__\u2192_can_add_comment":0.074,"P\\Tests\\admin\\Unit\\Livewire\\ActivityLogFeedTest::__pest_evaluable__activity_feed_component__\u2192_can_render_in_infolist":0.056,"P\\Tests\\admin\\Unit\\Support\\Extending\\CreatePageExtensionTest::__pest_evaluable_it_can_extend_header_actions":0.071,"P\\Tests\\admin\\Unit\\Support\\Extending\\CreatePageExtensionTest::__pest_evaluable_it_can_extend_form_actions":0.065,"P\\Tests\\admin\\Unit\\Support\\Extending\\EditPageExtensionTest::__pest_evaluable_it_can_extend_header_actions":0.077,"P\\Tests\\admin\\Unit\\Support\\Extending\\EditPageExtensionTest::__pest_evaluable_it_can_extend_form_actions":0.073,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_relationship_managers":0.023,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_table_columns#dataset \"ListCurrencies\"":0.061,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_table_columns#dataset \"ListLanguages\"":0.058,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_table_columns#dataset \"ListActivities\"":0.067,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_table_columns#dataset \"ListAttributeGroups\"":0.063,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_form_schema#dataset \"CurrencyResource\"":0.066,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_form_schema#dataset \"LanguageResource\"":0.063,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\DropdownConverterTest::__pest_evaluable__dropdown_converter__\u2192_can_convert_attribute_to_form_input_component":0.023,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\DropdownConverterTest::__pest_evaluable__dropdown_converter__\u2192_can_render_dropdown_options":0.023,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\ListFieldConverterTest::__pest_evaluable__list_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\NumberConverterTest::__pest_evaluable__list_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\TextConverterTest::__pest_evaluable__list_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.025,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\TextConverterTest::__pest_evaluable__list_field_converter__\u2192_can_return_richtext_component":0.026,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\ToggleConverterTest::__pest_evaluable__toggle_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.025,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\TranslatedTextConverterTest::__pest_evaluable__list_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.025,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\YouTubeConverterTest::__pest_evaluable__youtube_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.023,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\Text', 'Filament\\Forms\\Components\\TextInput')":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\Text', 'Filament\\Forms\\Components\\RichEditor', [true])":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\Dropdown', 'Filament\\Forms\\Components\\Select')":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\ListField', 'Filament\\Forms\\Components\\KeyValue')":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\YouTube', 'Lunar\\Admin\\Support\\Forms\\Com\u2026ouTube')":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\Number', 'Filament\\Forms\\Components\\TextInput')":0.021,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_can_extend_converters":0.021,"P\\Tests\\admin\\Unit\\Support\\RelationManagers\\ChannelRelationManagerTest::__pest_evaluable_it_can_render_relationship_manager":0.071}} \ No newline at end of file diff --git a/docs/core/reference/pricing.md b/docs/core/reference/pricing.md index 0c7d20c871..db07dfb176 100644 --- a/docs/core/reference/pricing.md +++ b/docs/core/reference/pricing.md @@ -55,7 +55,7 @@ them, first we'll create a standard price model. $priceModel = \Lunar\Models\Price::create([ // ... 'price' => 1000, // Price is an int and should be in the lowest common denominator - 'quantity_break' => 1, + 'min_quantity' => 1, ]); // Lunar\DataTypes\Price diff --git a/docs/core/reference/products.md b/docs/core/reference/products.md index 599d08deef..647c486d68 100644 --- a/docs/core/reference/products.md +++ b/docs/core/reference/products.md @@ -440,7 +440,7 @@ front end. | `price` | A integer value for the price | `null` | yes | | `compare_price` | For display purposes, allows you to show a comparison price, e.g. RRP. | `null` | no | | `currency_id` | The ID of the related currency | `null` | yes | -| `quantity_break` | The lower limit to get this price, 1 is the default for base pricing. | `1` | no | +| `min_quantity` | The minimum quantity required to get this price. | `1` | no | | `customer_group_id` | The customer group this price relates to, leaving as `null` means any customer group | `null` | no | | `priceable_type` | This is the class reference to the related model which owns the price | `null` | yes | | `priceable_id` | This is the id of the related model which owns the price | `null` | yes | @@ -450,7 +450,7 @@ $price = \Lunar\Models\Price::create([ 'price' => 199, 'compare_price' => 299, 'currency_id' => 1, - 'quantity_break' => 1, + 'min_quantity' => 1, 'customer_group_id' => null, 'priceable_type' => 'Lunar\Models\ProductVariant', 'priceable_id' => 1, @@ -476,7 +476,7 @@ relationship method. 'price' => 199, 'compare_price' => 299, 'currency_id' => 1, - 'quantity_break' => 1, + 'min_quantity' => 1, 'customer_group_id' => null, 'priceable_type' => 'Lunar\Models\ProductVariant', 'priceable_id' => 1, @@ -493,24 +493,24 @@ You can specify which customer group the price applies to by setting the `custom the price will apply to all customer groups. This is useful if you want to have different pricing for certain customer groups and also different price quantity breaks per customer group. -### Quantity Break Pricing +### Price Break Pricing -Quantity Break pricing is a concept in which when you buy in bulk, the cost per item will change (usually go down). With Pricing -on Lunar, this is determined by the `quantity_break` column when creating prices. For example: +Price Break pricing is a concept in which when you buy in bulk, the cost per item will change (usually go down). With Pricing +on Lunar, this is determined by the `min_quantity` column when creating prices. For example: ```php Price::create([ // ... 'price' => 199, 'compare_price' => 399, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); Price::create([ // ... 'price' => 150, 'compare_price' => 399, - 'quantity_break' => 10, + 'min_quantity' => 10, ]); ``` @@ -607,7 +607,7 @@ $pricing->base; /** * A collection of all the price quantity breaks available for the given criteria. */ -$pricing->quantityBreaks; +$pricing->priceBreaks; /** * All customer group pricing available for the given criteria. diff --git a/docs/core/upgrading.md b/docs/core/upgrading.md index b879138ebc..c78bc84a4d 100644 --- a/docs/core/upgrading.md +++ b/docs/core/upgrading.md @@ -31,9 +31,9 @@ for further information. The `position` field has been removed from the `product_options` table and is now found on the `product_product_option` pivot table. Any position data will be automatically adjusted when running migrations. -#### Tiers renamed to Quantity Breaks +#### Tiers renamed to Price Breaks -The `tier` column on pricing has been renamed to `quantity_break`, any references in code to `tiers` needs to be updated. +The `tier` column on pricing has been renamed to `min_quantity`, any references in code to `tiers` needs to be updated. ##### Price Model @@ -41,12 +41,12 @@ The `tier` column on pricing has been renamed to `quantity_break`, any reference // Old $priceModel->tier // New -$priceModel->quantity_break +$priceModel->min_quantity // Old $priceModel->tiers // New -$priceModel->quantityBreaks +$priceModel->priceBreaks ``` ##### Lunar\Base\DataTransferObjects\PricingResponse @@ -55,7 +55,7 @@ $priceModel->quantityBreaks // Old public Collection $tiered, // New -public Collection $quantityBreaks, +public Collection $priceBreaks, ``` ## 0.7 diff --git a/packages/admin/resources/dist/lunar-panel.css b/packages/admin/resources/dist/lunar-panel.css index c9914e7c44..963299f73d 100644 --- a/packages/admin/resources/dist/lunar-panel.css +++ b/packages/admin/resources/dist/lunar-panel.css @@ -1263,6 +1263,11 @@ select { border-color: rgb(253 186 116 / var(--tw-border-opacity)); } +.border-primary-500 { + --tw-border-opacity: 1; + border-color: rgba(var(--primary-500), var(--tw-border-opacity)); +} + .border-sky-300 { --tw-border-opacity: 1; border-color: rgb(125 211 252 / var(--tw-border-opacity)); @@ -1272,16 +1277,6 @@ select { border-color: rgb(255 255 255 / 0.1); } -.border-blue-500 { - --tw-border-opacity: 1; - border-color: rgb(59 130 246 / var(--tw-border-opacity)); -} - -.border-primary-500 { - --tw-border-opacity: 1; - border-color: rgba(var(--primary-500), var(--tw-border-opacity)); -} - .bg-gray-200 { --tw-bg-opacity: 1; background-color: rgba(var(--gray-200), var(--tw-bg-opacity)); @@ -1340,11 +1335,6 @@ select { background-color: rgb(255 255 255 / 0.7); } -.bg-custom-600 { - --tw-bg-opacity: 1; - background-color: rgba(var(--c-600), var(--tw-bg-opacity)); -} - .\!p-0 { padding: 0px !important; } diff --git a/packages/admin/resources/lang/en/product.php b/packages/admin/resources/lang/en/product.php index 2b36e83e8a..8aca2524f0 100644 --- a/packages/admin/resources/lang/en/product.php +++ b/packages/admin/resources/lang/en/product.php @@ -91,6 +91,17 @@ 'inventory' => [ 'label' => 'Inventory', ], + 'pricing' => [ + 'form' => [ + 'tax_class_id' => [ + 'label' => 'Tax Class', + ], + 'tax_ref' => [ + 'label' => 'Tax Reference', + 'helper_text' => 'Optional, for integration with 3rd party systems.', + ], + ], + ], 'shipping' => [ 'label' => 'Shipping', ], diff --git a/packages/admin/resources/lang/en/productvariant.php b/packages/admin/resources/lang/en/productvariant.php index 116ecda864..73cf4dac4a 100644 --- a/packages/admin/resources/lang/en/productvariant.php +++ b/packages/admin/resources/lang/en/productvariant.php @@ -71,6 +71,9 @@ 'label' => 'Quantity Increment', 'helper_text' => 'The product variant must be purchased in multiples of this quantity.', ], + 'tax_class_id' => [ + 'label' => 'Tax Class', + ], 'shippable' => [ 'label' => 'Shippable', ], diff --git a/packages/admin/resources/lang/en/relationmanagers.php b/packages/admin/resources/lang/en/relationmanagers.php index 3d332b713c..dcebc30753 100644 --- a/packages/admin/resources/lang/en/relationmanagers.php +++ b/packages/admin/resources/lang/en/relationmanagers.php @@ -125,14 +125,25 @@ 'title' => 'Pricing', 'title_plural' => 'Pricing', 'table' => [ + 'heading' => 'Price Breaks', + 'description' => 'Reduce the price when a customer purchases in larger quantities.', + 'empty_state' => [ + 'label' => 'No price breaks exist.', + ], + 'actions' => [ + 'create' => [ + 'label' => 'Add Price Break', + ], + ], 'price' => [ 'label' => 'Price', ], 'customer_group' => [ 'label' => 'Customer Group', + 'placeholder' => 'All Customer Groups', ], - 'quantity_break' => [ - 'label' => 'Quantity Break', + 'min_quantity' => [ + 'label' => 'Minimum Quantity', ], 'currency' => [ 'label' => 'Currency', @@ -141,15 +152,38 @@ 'form' => [ 'price' => [ 'label' => 'Price', + 'helper_text' => 'The purchase price, before discounts.', ], 'customer_group_id' => [ 'label' => 'Customer Group', + 'placeholder' => 'All Customer Groups', + 'helper_text' => 'Select which customer group to apply this price to.', ], - 'quantity_break' => [ - 'label' => 'Quantity Break', + 'min_quantity' => [ + 'label' => 'Minimum Quantity', + 'helper_text' => 'Select the minimum quantity this price will be available for.', ], 'currency_id' => [ 'label' => 'Currency', + 'helper_text' => 'Select the currency for this price.', + ], + 'compare_price' => [ + 'label' => 'Comparison Price', + 'helper_text' => 'The original price or RRP, for comparison with its purchase price.', + ], + 'basePrices' => [ + 'title' => 'Prices', + 'form' => [ + 'price' => [ + 'label' => 'Price', + 'helper_text' => 'The purchase price, before discounts.', + ], + 'compare_price' => [ + 'label' => 'Comparison Price', + 'helper_text' => 'The original price or RRP, for comparison with its purchase price.', + ], + ], + 'tooltip' => 'Automatically generated based on currency exchange rates.', ], ], ], diff --git a/packages/admin/src/Filament/Resources/ProductResource.php b/packages/admin/src/Filament/Resources/ProductResource.php index 9c7369c9bf..34c7cfd442 100644 --- a/packages/admin/src/Filament/Resources/ProductResource.php +++ b/packages/admin/src/Filament/Resources/ProductResource.php @@ -24,6 +24,7 @@ use Lunar\Admin\Support\Forms\Components\Tags as TagsComponent; use Lunar\Admin\Support\RelationManagers\ChannelRelationManager; use Lunar\Admin\Support\RelationManagers\MediaRelationManager; +use Lunar\Admin\Support\RelationManagers\PriceRelationManager; use Lunar\Admin\Support\Resources\BaseResource; use Lunar\Models\Currency; use Lunar\Models\Product; @@ -308,6 +309,7 @@ public static function getDefaultRelations(): array CustomerGroupRelationManager::class, ]), MediaRelationManager::class, + PriceRelationManager::class, ]; } diff --git a/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php b/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php index 3434203ecd..e8f26219f3 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php @@ -78,7 +78,7 @@ public static function createRecord(array $data, string $model): Model 'sku' => $data['sku'], ]); $variant->prices()->create([ - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'price' => (int) bcmul($data['base_price'], $currency->factor), ]); diff --git a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php index 5a674cefed..a2991256eb 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php @@ -4,35 +4,29 @@ use Filament\Forms; use Filament\Forms\Form; -use Filament\Resources\Pages\ManageRelatedRecords; use Filament\Support\Facades\FilamentIcon; use Filament\Tables; use Filament\Tables\Table; -use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Model; -use Illuminate\Validation\Rules\Unique; use Lunar\Admin\Filament\Resources\ProductResource; +use Lunar\Admin\Filament\Resources\ProductVariantResource; +use Lunar\Admin\Support\Concerns\Products\ManagesProductPricing; +use Lunar\Admin\Support\Pages\BaseEditRecord; +use Lunar\Admin\Support\RelationManagers\PriceRelationManager; use Lunar\Models\Currency; use Lunar\Models\Price; -class ManageProductPricing extends ManageRelatedRecords +class ManageProductPricing extends BaseEditRecord { - protected static string $resource = ProductResource::class; - - protected static string $relationship = 'prices'; + use ManagesProductPricing; - protected static ?string $title = 'Pricing'; + protected static string $resource = ProductResource::class; public static function getNavigationIcon(): ?string { return FilamentIcon::resolve('lunar::product-pricing'); } - public function getTitle(): string|Htmlable - { - return __('lunarpanel::relationmanagers.pricing.title'); - } - public static function shouldRegisterNavigation(array $parameters = []): bool { return $parameters['record']->variants()->count() == 1; @@ -43,41 +37,36 @@ public function getOwnerRecord(): Model return $this->getRecord()->variants()->first(); } - public static function getNavigationLabel(): string + public function form(Form $form): Form { - return __('lunarpanel::relationmanagers.pricing.title'); + if (! count($this->basePrices)) { + $this->basePrices = $this->getBasePrices(); + } + + return $form->schema([ + Forms\Components\Section::make() + ->schema([ + Forms\Components\Group::make([ + ProductVariantResource::getTaxClassIdFormComponent(), + ProductVariantResource::getTaxRefFormComponent(), + ])->columns(2), + ]), + $this->getBasePriceFormSection(), + ])->statePath(''); } - public function form(Form $form): Form + public function getRelationManagers(): array { - return $form - ->schema([ - Forms\Components\TextInput::make('price')->formatStateUsing( - fn ($state) => $state?->decimal(rounding: false) - )->numeric()->unique( - modifyRuleUsing: function (Unique $rule, Forms\Get $get) { - $owner = $this->getOwnerRecord(); - - return $rule->where('customer_group_id', $get('customer_group_id')) - ->where('quantity_break', $get('quantity_break')) - ->where('currency_id', $get('currency_id')) - ->where('priceable_type', get_class($owner)) - ->where('priceable_id', $owner->id); - } - )->required(), - Forms\Components\TextInput::make('quantity_break') - ->label( - __('lunarpanel::relationmanagers.pricing.form.quantity_break.label') - )->numeric()->minValue(1)->required(), - Forms\Components\Select::make('currency_id') - ->label( - __('lunarpanel::relationmanagers.pricing.form.currency_id.label') - )->relationship(name: 'currency', titleAttribute: 'name')->required(), - Forms\Components\Select::make('customer_group_id') - ->label( - __('lunarpanel::relationmanagers.pricing.form.customer_group_id.label') - )->relationship(name: 'customerGroup', titleAttribute: 'name'), - ]); + return [ + PriceRelationManager::make([ + 'ownerRecord' => $this->getOwnerRecord(), + ]), + ]; + } + + public static function getNavigationLabel(): string + { + return __('lunarpanel::relationmanagers.pricing.title'); } public function table(Table $table): Table @@ -85,7 +74,7 @@ public function table(Table $table): Table return $table ->recordTitleAttribute('name') ->modifyQueryUsing( - fn ($query) => $query->orderBy('quantity_break', 'asc') + fn ($query) => $query->orderBy('min_quantity', 'asc') ) ->columns([ Tables\Columns\TextColumn::make('price') @@ -97,8 +86,8 @@ public function table(Table $table): Table Tables\Columns\TextColumn::make('currency.code')->label( __('lunarpanel::relationmanagers.pricing.table.currency.label') ), - Tables\Columns\TextColumn::make('quantity_break')->label( - __('lunarpanel::relationmanagers.pricing.table.quantity_break.label') + Tables\Columns\TextColumn::make('min_quantity')->label( + __('lunarpanel::relationmanagers.pricing.table.min_quantity.label') ), Tables\Columns\TextColumn::make('customerGroup.name')->label( __('lunarpanel::relationmanagers.pricing.table.customer_group.label') @@ -108,11 +97,11 @@ public function table(Table $table): Table Tables\Filters\SelectFilter::make('currency') ->relationship(name: 'currency', titleAttribute: 'name') ->preload(), - Tables\Filters\SelectFilter::make('quantity_break')->options( + Tables\Filters\SelectFilter::make('min_quantity')->options( Price::where('priceable_id', $this->getOwnerRecord()->id) ->where('priceable_type', get_class($this->getOwnerRecord())) ->get() - ->pluck('quantity_break', 'quantity_break') + ->pluck('min_quantity', 'min_quantity') ), ]) ->headerActions([ diff --git a/packages/admin/src/Filament/Resources/ProductVariantResource.php b/packages/admin/src/Filament/Resources/ProductVariantResource.php index de29b30f15..f3240e225d 100644 --- a/packages/admin/src/Filament/Resources/ProductVariantResource.php +++ b/packages/admin/src/Filament/Resources/ProductVariantResource.php @@ -15,6 +15,7 @@ use Lunar\Admin\Support\Forms\Components\Attributes; use Lunar\Admin\Support\Resources\BaseResource; use Lunar\Models\ProductVariant; +use Lunar\Models\TaxClass; use Marvinosswald\FilamentInputSelectAffix\TextInputSelectAffix; class ProductVariantResource extends BaseResource @@ -169,6 +170,27 @@ public static function getMinQuantityFormComponent(): Forms\Components\TextInput )->numeric(); } + public static function getTaxClassIdFormComponent(): Forms\Components\Select + { + return Forms\Components\Select::make('tax_class_id') + ->label( + __('lunarpanel::productvariant.form.tax_class_id.label') + ) + ->options( + TaxClass::all()->pluck('name', 'id') + )->required(); + } + + public static function getTaxRefFormComponent(): Forms\Components\TextInput + { + return Forms\Components\TextInput::make('tax_ref') + ->label( + __('lunarpanel::product.pages.pricing.form.tax_ref.label') + )->helperText( + __('lunarpanel::product.pages.pricing.form.tax_ref.helper_text') + ); + } + public static function getShippableFormComponent(): Forms\Components\Toggle { return Forms\Components\Toggle::make('shippable')->label( diff --git a/packages/admin/src/Filament/Resources/ProductVariantResource/Pages/ManageVariantPricing.php b/packages/admin/src/Filament/Resources/ProductVariantResource/Pages/ManageVariantPricing.php index bbf6e3c205..652acfa794 100644 --- a/packages/admin/src/Filament/Resources/ProductVariantResource/Pages/ManageVariantPricing.php +++ b/packages/admin/src/Filament/Resources/ProductVariantResource/Pages/ManageVariantPricing.php @@ -3,39 +3,28 @@ namespace Lunar\Admin\Filament\Resources\ProductVariantResource\Pages; use Filament\Actions\Action; -use Filament\Forms; -use Filament\Forms\Form; -use Filament\Resources\Pages\ManageRelatedRecords; use Filament\Support\Facades\FilamentIcon; -use Filament\Tables; -use Filament\Tables\Table; -use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Model; -use Illuminate\Validation\Rules\Unique; use Lunar\Admin\Filament\Resources\ProductResource; use Lunar\Admin\Filament\Resources\ProductVariantResource; -use Lunar\Models\Currency; -use Lunar\Models\Price; +use Lunar\Admin\Support\Concerns\Products\ManagesProductPricing; +use Lunar\Admin\Support\Pages\BaseEditRecord; +use Lunar\Admin\Support\RelationManagers\PriceRelationManager; -class ManageVariantPricing extends ManageRelatedRecords +class ManageVariantPricing extends BaseEditRecord { - protected static string $resource = ProductVariantResource::class; - - protected static string $relationship = 'prices'; + use ManagesProductPricing; - public static function getNavigationIcon(): ?string - { - return FilamentIcon::resolve('lunar::product-pricing'); - } + protected static string $resource = ProductVariantResource::class; - public function getTitle(): string|Htmlable + public function getOwnerRecord() { - return __('lunarpanel::relationmanagers.pricing.title'); + return $this->getRecord(); } - public static function getNavigationLabel(): string + public static function getNavigationIcon(): ?string { - return __('lunarpanel::relationmanagers.pricing.title'); + return FilamentIcon::resolve('lunar::product-pricing'); } protected function getHeaderActions(): array @@ -68,91 +57,10 @@ public function getBreadcrumbs(): array ]; } - public function form(Form $form): Form + public function getRelationManagers(): array { - return $form - ->schema([ - Forms\Components\TextInput::make('price')->formatStateUsing( - fn ($state) => $state?->decimal(rounding: false) - )->numeric()->unique( - modifyRuleUsing: function (Unique $rule, Forms\Get $get) { - $owner = $this->getOwnerRecord(); - - return $rule->where('customer_group_id', $get('customer_group_id')) - ->where('quantity_break', $get('quantity_break')) - ->where('currency_id', $get('currency_id')) - ->where('priceable_type', get_class($owner)) - ->where('priceable_id', $owner->id); - } - )->required(), - Forms\Components\TextInput::make('quantity_break') - ->label( - __('lunarpanel::relationmanagers.pricing.form.quantity_break.label') - )->numeric()->minValue(1)->required(), - Forms\Components\Select::make('currency_id') - ->label( - __('lunarpanel::relationmanagers.pricing.form.currency_id.label') - )->relationship(name: 'currency', titleAttribute: 'name')->required(), - Forms\Components\Select::make('customer_group_id') - ->label( - __('lunarpanel::relationmanagers.pricing.form.customer_group_id.label') - )->relationship(name: 'customerGroup', titleAttribute: 'name'), - ]); - } - - public function table(Table $table): Table - { - return $table - ->recordTitleAttribute('name') - ->modifyQueryUsing( - fn ($query) => $query->orderBy('quantity_break', 'asc') - ) - ->columns([ - Tables\Columns\TextColumn::make('price') - ->label( - __('lunarpanel::relationmanagers.pricing.table.price.label') - )->formatStateUsing( - fn ($state) => $state->formatted, - ), - Tables\Columns\TextColumn::make('currency.code')->label( - __('lunarpanel::relationmanagers.pricing.table.currency.label') - ), - Tables\Columns\TextColumn::make('quantity_break')->label( - __('lunarpanel::relationmanagers.pricing.table.quantity_break.label') - ), - Tables\Columns\TextColumn::make('customerGroup.name')->label( - __('lunarpanel::relationmanagers.pricing.table.customer_group.label') - ), - ]) - ->filters([ - Tables\Filters\SelectFilter::make('currency') - ->relationship(name: 'currency', titleAttribute: 'name') - ->preload(), - Tables\Filters\SelectFilter::make('quantity_break')->options( - Price::where('priceable_id', $this->getOwnerRecord()->id) - ->where('priceable_type', get_class($this->getOwnerRecord())) - ->get() - ->pluck('quantity_break', 'quantity_break') - ), - ]) - ->headerActions([ - Tables\Actions\CreateAction::make()->mutateFormDataUsing(function (array $data) { - $currencyModel = Currency::find($data['currency_id']); - - $data['price'] = (int) ($data['price'] * $currencyModel->factor); - - return $data; - }), - ]) - ->actions([ - Tables\Actions\EditAction::make()->mutateFormDataUsing(function (array $data): array { - $currencyModel = Currency::find($data['currency_id']); - - $data['price'] = (int) ($data['price'] * $currencyModel->factor); - - return $data; - }), - Tables\Actions\DeleteAction::make(), - ]); + return [ + PriceRelationManager::class, + ]; } } diff --git a/packages/admin/src/LunarPanelManager.php b/packages/admin/src/LunarPanelManager.php index bbf7592b80..4972c5e0e1 100644 --- a/packages/admin/src/LunarPanelManager.php +++ b/packages/admin/src/LunarPanelManager.php @@ -111,6 +111,7 @@ public function register(): self 'lunar::customer-groups' => 'lucide-users', 'lunar::dashboard' => 'lucide-bar-chart-big', 'lunar::discounts' => 'lucide-percent-circle', + 'lunar::info' => 'lucide-info', 'lunar::languages' => 'lucide-languages', 'lunar::media' => 'lucide-image', 'lunar::orders' => 'lucide-inbox', diff --git a/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php b/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php new file mode 100644 index 0000000000..1b3dbd1cb6 --- /dev/null +++ b/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php @@ -0,0 +1,202 @@ +getOwnerRecord(); + + $this->tax_class_id = $variant->tax_class_id; + $this->tax_ref = $variant->tax_ref; + } + + public function getTitle(): string|Htmlable + { + return __('lunarpanel::relationmanagers.pricing.title'); + } + + public static function getNavigationLabel(): string + { + return __('lunarpanel::relationmanagers.pricing.title'); + } + + protected function handleRecordUpdate(Model $record, array $data): Model + { + $variant = $this->getOwnerRecord(); + + $prices = collect($data['basePrices']); + unset($data['basePrices']); + $variant->update($data); + + $prices->filter( + fn ($price) => ! $price['id'] + )->each(fn ($price) => $variant->prices()->create([ + 'currency_id' => $price['currency_id'], + 'price' => (int) ($price['value'] * $price['factor']), + 'compare_price' => (int) ($price['compare_price'] * $price['factor']), + 'min_quantity' => 1, + 'customer_group_id' => null, + ]) + ); + + $prices->filter( + fn ($price) => $price['id'] + )->each(fn ($price) => Price::whereId($price['id'])->update([ + 'price' => (int) ($price['value'] * $price['factor']), + 'compare_price' => (int) ($price['compare_price'] * $price['factor']), + ]) + ); + + $this->basePrices = $this->getBasePrices($variant); + + return $record; + } + + public function getBasePriceFormSection(): Section + { + return Forms\Components\Section::make( + __('lunarpanel::relationmanagers.pricing.form.basePrices.title') + ) + ->schema( + collect($this->basePrices)->map(function ($price, $index): Forms\Components\Fieldset { + return Forms\Components\Fieldset::make($price['label'])->schema([ + Forms\Components\TextInput::make('value') + ->label('') + ->statePath($index.'.value') + ->label( + __('lunarpanel::relationmanagers.pricing.form.basePrices.form.price.label') + ) + ->helperText( + __('lunarpanel::relationmanagers.pricing.form.basePrices.form.price.helper_text') + ) + ->hintColor('warning') + ->extraInputAttributes([ + 'class' => '', + ]) + ->hintIcon(function (Forms\Get $get, Forms\Components\TextInput $component) use ($index) { + if ($get('basePrices.'.$index.'.id', true)) { + return null; + } + + return FilamentIcon::resolve('lunar::info'); + })->hintIconTooltip(function (Forms\Get $get, Forms\Components\TextInput $component) use ($index) { + if ($get('basePrices.'.$index.'.id', true)) { + return null; + } + + return __('lunarpanel::relationmanagers.pricing.form.basePrices.tooltip'); + })->live(), + Forms\Components\TextInput::make('compare_price') + ->label('') + ->statePath($index.'.compare_price') + ->label( + __('lunarpanel::relationmanagers.pricing.form.basePrices.form.compare_price.label') + ) + ->helperText( + __('lunarpanel::relationmanagers.pricing.form.basePrices.form.compare_price.helper_text') + ) + ->hintColor('warning') + ->extraInputAttributes([ + 'class' => '', + ]) + ->hintIcon(function (Forms\Get $get, Forms\Components\TextInput $component) use ($index) { + if ($get('basePrices.'.$index.'.id', true)) { + return null; + } + + return FilamentIcon::resolve('lunar::info'); + })->hintIconTooltip(function (Forms\Get $get, Forms\Components\TextInput $component) use ($index) { + if ($get('basePrices.'.$index.'.id', true)) { + return null; + } + + return __('lunarpanel::relationmanagers.pricing.form.basePrices.tooltip'); + })->live(), + ])->columns(2); + })->toArray() + )->statePath('basePrices')->columns(1); + } + + public function form(Forms\Form $form): Forms\Form + { + if (! count($this->basePrices)) { + $this->basePrices = $this->getBasePrices(); + } + + return $form->schema([ + Forms\Components\Section::make()->schema([ + Forms\Components\Group::make([ + ProductVariantResource::getTaxClassIdFormComponent(), + ProductVariantResource::getTaxRefFormComponent(), + ])->columns(2), + ]), + $this->getBasePriceFormSection(), + ])->statePath(''); + } + + protected function getBasePrices(): array + { + // Get enabled currencies + $currencies = Currency::whereEnabled(true)->get(); + + $prices = collect([]); + + foreach ($this->getOwnerRecord()->basePrices()->get() as $price) { + $prices->put( + $price->currency->code, + [ + 'id' => $price->id, + 'value' => $price->price->decimal(rounding: false), + 'compare_price' => $price->compare_price->decimal(rounding: false), + 'factor' => $price->currency->factor, + 'label' => $price->currency->name, + 'currency_code' => $price->currency->code, + 'default_currency' => $price->currency->default, + 'currency_id' => $price->currency_id, + ] + ); + } + + $defaultCurrencyPrice = $prices->first( + fn ($price) => $price['default_currency'] + ); + + foreach ($currencies as $currency) { + if (! $prices->get($currency->code)) { + $prices->put($currency->code, [ + 'id' => null, + 'value' => round(($defaultCurrencyPrice['value'] ?? 0) * $currency->exchange_rate, $currency->decimal_places), + 'compare_price' => round(($defaultCurrencyPrice['compare_price'] ?? 0) * $currency->exchange_rate, $currency->decimal_places), + 'factor' => $currency->factor, + 'label' => $currency->name, + 'currency_code' => $currency->code, + 'default_currency' => $currency->default, + 'currency_id' => $currency->id, + ]); + } + } + + return $prices->values()->toArray(); + } +} diff --git a/packages/admin/src/Support/RelationManagers/PriceRelationManager.php b/packages/admin/src/Support/RelationManagers/PriceRelationManager.php new file mode 100644 index 0000000000..47db4eba18 --- /dev/null +++ b/packages/admin/src/Support/RelationManagers/PriceRelationManager.php @@ -0,0 +1,161 @@ +schema([ + Forms\Components\Group::make([ + Forms\Components\Select::make('currency_id') + ->label( + __('lunarpanel::relationmanagers.pricing.form.currency_id.label') + )->relationship(name: 'currency', titleAttribute: 'name') + ->default(function () { + return Currency::getDefault()?->id; + }) + ->helperText( + __('lunarpanel::relationmanagers.pricing.form.currency_id.helper_text') + )->required(), + Forms\Components\Select::make('customer_group_id') + ->label( + __('lunarpanel::relationmanagers.pricing.form.customer_group_id.label') + )->placeholder( + __('lunarpanel::relationmanagers.pricing.form.customer_group_id.placeholder') + )->helperText( + __('lunarpanel::relationmanagers.pricing.form.customer_group_id.helper_text') + )->relationship(name: 'customerGroup', titleAttribute: 'name'), + Forms\Components\TextInput::make('min_quantity') + ->label( + __('lunarpanel::relationmanagers.pricing.form.min_quantity.label') + )->default(1)->helperText( + __('lunarpanel::relationmanagers.pricing.form.min_quantity.helper_text') + )->numeric()->minValue(1)->required(), + ])->columns(3), + + Forms\Components\Group::make([ + Forms\Components\TextInput::make('price')->formatStateUsing( + fn ($state) => $state?->decimal(rounding: false) + )->numeric()->unique( + modifyRuleUsing: function (Unique $rule, Forms\Get $get) { + $owner = $this->getOwnerRecord(); + + return $rule->where('customer_group_id', $get('customer_group_id')) + ->where('min_quantity', 1) + ->where('currency_id', 1) + ->where('priceable_type', get_class($owner)) + ->where('priceable_id', $owner->id); + } + )->helperText( + __('lunarpanel::relationmanagers.pricing.form.price.helper_text') + )->required(), + Forms\Components\TextInput::make('compare_price')->formatStateUsing( + fn ($state) => $state?->decimal(rounding: false) + )->label( + __('lunarpanel::relationmanagers.pricing.form.compare_price.label') + )->helperText( + __('lunarpanel::relationmanagers.pricing.form.compare_price.helper_text') + )->numeric(), + ])->columns(2), + ])->columns(1); + } + + public function table(Table $table): Table + { + $priceTable = (new Price)->getTable(); + + return $table + ->recordTitleAttribute('name') + ->description( + __('lunarpanel::relationmanagers.pricing.table.description') + ) + ->modifyQueryUsing( + fn ($query) => $query + ->where("{$priceTable}.min_quantity", '>', 1) + ->orderBy("{$priceTable}.min_quantity", 'asc') + )->emptyStateHeading( + __('lunarpanel::relationmanagers.pricing.table.empty_state.label') + ) + ->columns([ + Tables\Columns\TextColumn::make('price') + ->label( + __('lunarpanel::relationmanagers.pricing.table.price.label') + )->formatStateUsing( + fn ($state) => $state->formatted, + )->sortable(), + Tables\Columns\TextColumn::make('currency.code')->label( + __('lunarpanel::relationmanagers.pricing.table.currency.label') + )->sortable(), + Tables\Columns\TextColumn::make('min_quantity')->label( + __('lunarpanel::relationmanagers.pricing.table.min_quantity.label') + )->sortable(), + Tables\Columns\TextColumn::make('customerGroup.name')->label( + __('lunarpanel::relationmanagers.pricing.table.customer_group.label') + )->placeholder( + __('lunarpanel::relationmanagers.pricing.table.customer_group.placeholder') + )->sortable(), + ]) + ->filters([ + Tables\Filters\SelectFilter::make('currency') + ->relationship(name: 'currency', titleAttribute: 'name') + ->preload() + ->label( + __('lunarpanel::relationmanagers.pricing.table.currency.label') + ), + Tables\Filters\SelectFilter::make('min_quantity')->options( + Price::where('priceable_id', $this->getOwnerRecord()->id) + ->where('priceable_type', get_class($this->getOwnerRecord())) + ->get() + ->pluck('min_quantity', 'min_quantity') + )->label( + __('lunarpanel::relationmanagers.pricing.table.min_quantity.label') + ), + ]) + ->headerActions([ + Tables\Actions\CreateAction::make()->mutateFormDataUsing(function (array $data) { + $currencyModel = Currency::find($data['currency_id']); + + $data['price'] = (int) ($data['price'] * $currencyModel->factor); + + return $data; + })->label( + __('lunarpanel::relationmanagers.pricing.table.actions.create.label') + ), + ]) + ->actions([ + Tables\Actions\EditAction::make()->mutateFormDataUsing(function (array $data): array { + $currencyModel = Currency::find($data['currency_id']); + + $data['price'] = (int) ($data['price'] * $currencyModel->factor); + + return $data; + }), + Tables\Actions\DeleteAction::make(), + ]); + } +} diff --git a/packages/core/database/migrations/2024_01_31_100000_update_tier_to_quantity_break_on_prices_table.php b/packages/core/database/migrations/2024_01_31_100000_update_tier_to_min_quantity_on_prices_table.php similarity index 67% rename from packages/core/database/migrations/2024_01_31_100000_update_tier_to_quantity_break_on_prices_table.php rename to packages/core/database/migrations/2024_01_31_100000_update_tier_to_min_quantity_on_prices_table.php index 43582f3963..82a79abc07 100644 --- a/packages/core/database/migrations/2024_01_31_100000_update_tier_to_quantity_break_on_prices_table.php +++ b/packages/core/database/migrations/2024_01_31_100000_update_tier_to_min_quantity_on_prices_table.php @@ -4,19 +4,19 @@ use Illuminate\Support\Facades\Schema; use Lunar\Base\Migration; -class UpdateTierToQuantityBreakOnPricesTable extends Migration +class UpdateTierToMinQuantityOnPricesTable extends Migration { public function up() { Schema::table($this->prefix.'prices', function (Blueprint $table) { - $table->renameColumn('tier', 'quantity_break'); + $table->renameColumn('tier', 'min_quantity'); }); } public function down() { Schema::table($this->prefix.'prices', function (Blueprint $table) { - $table->renameColumn('quantity_break', 'tier'); + $table->renameColumn('min_quantity', 'tier'); }); } } diff --git a/packages/core/src/Base/DataTransferObjects/PricingResponse.php b/packages/core/src/Base/DataTransferObjects/PricingResponse.php index 18e84a39e6..8458943429 100644 --- a/packages/core/src/Base/DataTransferObjects/PricingResponse.php +++ b/packages/core/src/Base/DataTransferObjects/PricingResponse.php @@ -10,7 +10,7 @@ class PricingResponse public function __construct( public Price $matched, public Price $base, - public Collection $quantityBreaks, + public Collection $priceBreaks, public Collection $customerGroupPrices, ) { // diff --git a/packages/core/src/Base/Traits/HasPrices.php b/packages/core/src/Base/Traits/HasPrices.php index a3f20963ce..9a46887743 100644 --- a/packages/core/src/Base/Traits/HasPrices.php +++ b/packages/core/src/Base/Traits/HasPrices.php @@ -25,12 +25,12 @@ public function prices(): MorphMany */ public function basePrices(): MorphMany { - return $this->prices()->whereQuantityBreak(1)->whereNull('customer_group_id'); + return $this->prices()->whereMinQuantity(1)->whereNull('customer_group_id'); } - public function quantityBreaks(): MorphMany + public function priceBreaks(): MorphMany { - return $this->prices()->where('quantity_break', '>', 1); + return $this->prices()->where('min_quantity', '>', 1); } /** diff --git a/packages/core/src/Managers/PricingManager.php b/packages/core/src/Managers/PricingManager.php index a63e7d7282..112985a125 100644 --- a/packages/core/src/Managers/PricingManager.php +++ b/packages/core/src/Managers/PricingManager.php @@ -195,25 +195,25 @@ public function get() })->sortBy('price'); // Get our base price - $basePrice = $prices->first(fn ($price) => $price->quantity_break == 1 && ! $price->customer_group_id); + $basePrice = $prices->first(fn ($price) => $price->min_quantity == 1 && ! $price->customer_group_id); // To start, we'll set the matched price to the base price. $matched = $basePrice; // If we have customer group prices, we should find the cheapest one and send that back. $potentialGroupPrice = $prices->filter(function ($price) { - return (bool) $price->customer_group_id && ($price->quantity_break == 1); + return (bool) $price->customer_group_id && ($price->min_quantity == 1); })->sortBy('price'); $matched = $potentialGroupPrice->first() ?: $matched; - // Get all quantity breaks that match for the given quantity. These take priority over the other steps + // Get all price breaks that match for the given quantity. These take priority over the other steps // as we could be bulk purchasing. - $quantityBreaks = $prices->filter(function ($price) { - return $price->quantity_break > 1 && $this->qty >= $price->quantity_break; + $priceBreaks = $prices->filter(function ($price) { + return $price->min_quantity > 1 && $this->qty >= $price->min_quantity; })->sortBy('price'); - $matched = $quantityBreaks->first() ?: $matched; + $matched = $priceBreaks->first() ?: $matched; if (! $matched) { throw new \ErrorException('No price set.'); @@ -221,8 +221,8 @@ public function get() $this->pricing = new PricingResponse( matched: $matched, - base: $prices->first(fn ($price) => $price->quantity_break == 1), - quantityBreaks: $prices->filter(fn ($price) => $price->quantity_break > 1), + base: $prices->first(fn ($price) => $price->min_quantity == 1), + priceBreaks: $prices->filter(fn ($price) => $price->min_quantity > 1), customerGroupPrices: $prices->filter(fn ($price) => (bool) $price->customer_group_id) ); diff --git a/packages/core/src/Models/Price.php b/packages/core/src/Models/Price.php index 3807b77e3b..c1d11f62e1 100644 --- a/packages/core/src/Models/Price.php +++ b/packages/core/src/Models/Price.php @@ -19,7 +19,7 @@ * @property int $priceable_id * @property int $price * @property ?int $compare_price - * @property int $quantity_break + * @property int $min_quantity * @property ?\Illuminate\Support\Carbon $created_at * @property ?\Illuminate\Support\Carbon $updated_at */ diff --git a/packages/table-rate-shipping/resources/lang/en/relationmanagers.php b/packages/table-rate-shipping/resources/lang/en/relationmanagers.php index f24eb5b3b3..e6e7032b2f 100644 --- a/packages/table-rate-shipping/resources/lang/en/relationmanagers.php +++ b/packages/table-rate-shipping/resources/lang/en/relationmanagers.php @@ -20,7 +20,7 @@ 'label' => 'Price', ], 'prices' => [ - 'label' => 'Quantity Breaks', + 'label' => 'Price Breaks', 'repeater' => [ 'customer_group_id' => [ 'label' => 'Customer Group', @@ -29,7 +29,7 @@ 'currency_id' => [ 'label' => 'Currency', ], - 'quantity_break' => [ + 'min_quantity' => [ 'label' => 'Min. Spend', ], 'price' => [ @@ -45,8 +45,8 @@ 'price' => [ 'label' => 'Price', ], - 'quantity_breaks_count' => [ - 'label' => 'Quantity Breaks', + 'price_breaks_count' => [ + 'label' => 'Price Breaks', ], ], ], diff --git a/packages/table-rate-shipping/resources/views/shipping-methods/ship-by.blade.php b/packages/table-rate-shipping/resources/views/shipping-methods/ship-by.blade.php index 84d46ef218..903a3c2149 100644 --- a/packages/table-rate-shipping/resources/views/shipping-methods/ship-by.blade.php +++ b/packages/table-rate-shipping/resources/views/shipping-methods/ship-by.blade.php @@ -50,7 +50,7 @@
- @if(count($quantityBreaks)) + @if(count($priceBreaks))
@if(!$this->currency->default) @@ -74,11 +74,11 @@
- @foreach($quantityBreaks as $index => $quantityBreak) + @foreach($priceBreaks as $index => $priceBreak)
- + @foreach($this->customerGroups as $group) @@ -86,18 +86,18 @@ - +
diff --git a/packages/table-rate-shipping/src/Drivers/ShippingMethods/ShipBy.php b/packages/table-rate-shipping/src/Drivers/ShippingMethods/ShipBy.php index db076d9af8..f9313b9fdd 100644 --- a/packages/table-rate-shipping/src/Drivers/ShippingMethods/ShipBy.php +++ b/packages/table-rate-shipping/src/Drivers/ShippingMethods/ShipBy.php @@ -77,7 +77,7 @@ public function resolve(ShippingOptionRequest $shippingOptionRequest): ?Shipping // Do we have a suitable tier price? $pricing = Pricing::for($shippingRate)->customerGroups($customerGroups)->qty($tier)->get(); - $prices = $pricing->quantityBreaks; + $prices = $pricing->priceBreaks; // If there are customer group prices, they need to take priority. if (! $pricing->customerGroupPrices->isEmpty()) { @@ -85,8 +85,8 @@ public function resolve(ShippingOptionRequest $shippingOptionRequest): ?Shipping } $matched = $prices->filter(function ($price) use ($tier) { - return $tier >= $price->quantity_break; - })->sortByDesc('quantity_break')->first() ?: $pricing->base; + return $tier >= $price->min_quantity; + })->sortByDesc('min_quantity')->first() ?: $pricing->base; if (! $matched) { return null; diff --git a/packages/table-rate-shipping/src/Filament/Resources/ShippingZoneResource/Pages/ManageShippingRates.php b/packages/table-rate-shipping/src/Filament/Resources/ShippingZoneResource/Pages/ManageShippingRates.php index 8269a33380..792ba6ab76 100644 --- a/packages/table-rate-shipping/src/Filament/Resources/ShippingZoneResource/Pages/ManageShippingRates.php +++ b/packages/table-rate-shipping/src/Filament/Resources/ShippingZoneResource/Pages/ManageShippingRates.php @@ -97,9 +97,9 @@ function () { )->default( Currency::getDefault()->id )->required()->preload(), - Forms\Components\TextInput::make('quantity_break') + Forms\Components\TextInput::make('min_quantity') ->label( - __('lunarpanel.shipping::relationmanagers.shipping_rates.form.prices.repeater.quantity_break.label') + __('lunarpanel.shipping::relationmanagers.shipping_rates.form.prices.repeater.min_quantity.label') ) ->numeric() ->required(), @@ -113,12 +113,12 @@ function () { static function (Forms\Components\Repeater $component, Model $record = null): void { if ($record) { $component->state( - $record->quantityBreaks->map(function ($price) { + $record->priceBreaks->map(function ($price) { return [ 'customer_group_id' => $price->customer_group_id, 'price' => $price->price->decimal, 'currency_id' => $price->currency_id, - 'quantity_break' => $price->quantity_break / 100, + 'min_quantity' => $price->min_quantity / 100, ]; })->toArray() ); @@ -140,10 +140,10 @@ public function table(Table $table): Table )->label( __('lunarpanel.shipping::relationmanagers.shipping_rates.table.price.label') ), - TextColumn::make('quantity_breaks_count') + TextColumn::make('price_breaks_count') ->label( - __('lunarpanel.shipping::relationmanagers.shipping_rates.table.quantity_breaks_count.label') - )->counts('quantityBreaks'), + __('lunarpanel.shipping::relationmanagers.shipping_rates.table.price_breaks_count.label') + )->counts('priceBreaks'), ])->headerActions([ Tables\Actions\CreateAction::make()->label( __('lunarpanel.shipping::relationmanagers.shipping_rates.actions.create.label') @@ -177,11 +177,11 @@ protected static function saveShippingRate(ShippingRate $shippingRate = null, ar $basePrice->customer_group_id = null; $basePrice->save(); - $shippingRate->quantityBreaks()->delete(); + $shippingRate->priceBreaks()->delete(); $tiers = collect($data['prices'] ?? [])->map( function ($price) { - $price['quantity_break'] = $price['quantity_break'] * 100; + $price['min_quantity'] = $price['min_quantity'] * 100; return $price; } diff --git a/tests/admin/Feature/Filament/Resources/ProductResource/Pages/ManageProductPricingTest.php b/tests/admin/Feature/Filament/Resources/ProductResource/Pages/ManageProductPricingTest.php index f087c53e0c..869a991f4a 100644 --- a/tests/admin/Feature/Filament/Resources/ProductResource/Pages/ManageProductPricingTest.php +++ b/tests/admin/Feature/Filament/Resources/ProductResource/Pages/ManageProductPricingTest.php @@ -74,38 +74,3 @@ __('lunarpanel::relationmanagers.pricing.title') ); }); - -it('can create product price', function () { - $language = \Lunar\Models\Language::factory()->create([ - 'default' => true, - ]); - - $currency = \Lunar\Models\Currency::factory()->create([ - 'default' => true, - 'decimal_places' => 2, - ]); - - $record = \Lunar\Models\Product::factory()->create(); - - \Lunar\Models\ProductVariant::factory()->create([ - 'product_id' => $record->id, - ]); - - $this->asStaff(); - - \Livewire\Livewire::test( - \Lunar\Admin\Filament\Resources\ProductResource\Pages\ManageProductPricing::class, [ - 'record' => $record->getRouteKey(), - ])->callTableAction('create', data: [ - 'price' => 10.99, - 'currency_id' => $currency->id, - 'quantity_break' => 1, - ])->assertHasNoErrors(); - - $this->assertDatabaseHas((new \Lunar\Models\Price())->getTable(), [ - 'price' => 1099, - 'quantity_break' => 1, - 'currency_id' => $currency->id, - 'customer_group_id' => null, - ]); -}); diff --git a/tests/admin/Feature/Support/RelationManagers/PriceRelationManagerTest.php b/tests/admin/Feature/Support/RelationManagers/PriceRelationManagerTest.php new file mode 100644 index 0000000000..a0a4eee380 --- /dev/null +++ b/tests/admin/Feature/Support/RelationManagers/PriceRelationManagerTest.php @@ -0,0 +1,26 @@ +group('support.relation-managers'); + +it('can render relation manager', function ($model, $page) { + $this->asStaff(); + + \Lunar\Models\Language::factory()->create([ + 'default' => true, + ]); + + $model = $model::factory()->create(); + + Livewire::test(\Lunar\Admin\Support\RelationManagers\PriceRelationManager::class, [ + 'ownerRecord' => $model, + 'pageClass' => $page, + ])->assertSuccessful(); +})->with([ + 'product' => [ + 'model' => \Lunar\Models\Product::class, + 'page' => \Lunar\Admin\Filament\Resources\ProductResource\Pages\ManageProductPricing::class, + ], +]); diff --git a/tests/core/Unit/Actions/Carts/AddOrUpdatePurchasableTest.php b/tests/core/Unit/Actions/Carts/AddOrUpdatePurchasableTest.php index dad27ad3f2..31b6da7d31 100644 --- a/tests/core/Unit/Actions/Carts/AddOrUpdatePurchasableTest.php +++ b/tests/core/Unit/Actions/Carts/AddOrUpdatePurchasableTest.php @@ -23,7 +23,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -49,7 +49,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -75,7 +75,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Actions/Carts/CalculateLineTest.php b/tests/core/Unit/Actions/Carts/CalculateLineTest.php index 2850b3d6ea..ae197fbc10 100644 --- a/tests/core/Unit/Actions/Carts/CalculateLineTest.php +++ b/tests/core/Unit/Actions/Carts/CalculateLineTest.php @@ -44,7 +44,7 @@ Price::factory()->create([ 'price' => 100, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, ]); @@ -108,7 +108,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -173,7 +173,7 @@ Price::factory()->create([ 'price' => 1000, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -238,7 +238,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -305,7 +305,7 @@ function check_for_know_rounding_error_on_unit_price_with_unit_quantity_of_one() Price::factory()->create([ 'price' => 912, //Known failing value 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, ]); diff --git a/tests/core/Unit/Actions/Carts/CreateOrderTest.php b/tests/core/Unit/Actions/Carts/CreateOrderTest.php index 9c5b02dad3..7a0a07fc7d 100644 --- a/tests/core/Unit/Actions/Carts/CreateOrderTest.php +++ b/tests/core/Unit/Actions/Carts/CreateOrderTest.php @@ -159,7 +159,7 @@ function can_update_draft_order() Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -291,7 +291,7 @@ function can_update_draft_order() Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Actions/Carts/GenerateFingerprintTest.php b/tests/core/Unit/Actions/Carts/GenerateFingerprintTest.php index 620acf03a5..7f12068663 100644 --- a/tests/core/Unit/Actions/Carts/GenerateFingerprintTest.php +++ b/tests/core/Unit/Actions/Carts/GenerateFingerprintTest.php @@ -28,7 +28,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($variant), 'priceable_id' => $variant->id, diff --git a/tests/core/Unit/Actions/Carts/GetExistingCartLineTest.php b/tests/core/Unit/Actions/Carts/GetExistingCartLineTest.php index 07c86bb23d..a6ed030958 100644 --- a/tests/core/Unit/Actions/Carts/GetExistingCartLineTest.php +++ b/tests/core/Unit/Actions/Carts/GetExistingCartLineTest.php @@ -22,7 +22,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -54,7 +54,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Actions/Carts/MergeCartTest.php b/tests/core/Unit/Actions/Carts/MergeCartTest.php index 8e33a24ddc..c73363bb02 100644 --- a/tests/core/Unit/Actions/Carts/MergeCartTest.php +++ b/tests/core/Unit/Actions/Carts/MergeCartTest.php @@ -51,7 +51,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, ]); @@ -122,7 +122,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, ]); diff --git a/tests/core/Unit/Actions/Carts/RemovePurchasableTest.php b/tests/core/Unit/Actions/Carts/RemovePurchasableTest.php index 53361a4140..e21518130a 100644 --- a/tests/core/Unit/Actions/Carts/RemovePurchasableTest.php +++ b/tests/core/Unit/Actions/Carts/RemovePurchasableTest.php @@ -21,7 +21,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Actions/Carts/UpdateCartLineTest.php b/tests/core/Unit/Actions/Carts/UpdateCartLineTest.php index b94237ba4a..62f15cc6bb 100644 --- a/tests/core/Unit/Actions/Carts/UpdateCartLineTest.php +++ b/tests/core/Unit/Actions/Carts/UpdateCartLineTest.php @@ -22,7 +22,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Actions/Collections/SortProductsByPriceTest.php b/tests/core/Unit/Actions/Collections/SortProductsByPriceTest.php index 666312157c..5425a3bcd1 100644 --- a/tests/core/Unit/Actions/Collections/SortProductsByPriceTest.php +++ b/tests/core/Unit/Actions/Collections/SortProductsByPriceTest.php @@ -33,7 +33,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, 'price' => $prices[$index], ]); } diff --git a/tests/core/Unit/Base/ShippingManifestTest.php b/tests/core/Unit/Base/ShippingManifestTest.php index cc6001343e..909a096e17 100644 --- a/tests/core/Unit/Base/ShippingManifestTest.php +++ b/tests/core/Unit/Base/ShippingManifestTest.php @@ -43,7 +43,7 @@ PriceModel::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Base/Traits/CachesPropertiesTest.php b/tests/core/Unit/Base/Traits/CachesPropertiesTest.php index 77fb306e88..a84ea4fd25 100644 --- a/tests/core/Unit/Base/Traits/CachesPropertiesTest.php +++ b/tests/core/Unit/Base/Traits/CachesPropertiesTest.php @@ -21,7 +21,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/DiscountTypes/AmountOffTest.php b/tests/core/Unit/DiscountTypes/AmountOffTest.php index 565a686a81..f5dee5f4ca 100644 --- a/tests/core/Unit/DiscountTypes/AmountOffTest.php +++ b/tests/core/Unit/DiscountTypes/AmountOffTest.php @@ -71,7 +71,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -85,7 +85,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -173,7 +173,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -187,7 +187,7 @@ Price::factory()->create([ 'price' => 2000, // £20 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -271,7 +271,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -285,7 +285,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -368,7 +368,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -382,7 +382,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -465,7 +465,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -479,7 +479,7 @@ Price::factory()->create([ 'price' => 2000, // £20 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -562,7 +562,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -576,7 +576,7 @@ Price::factory()->create([ 'price' => 2000, // £20 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -642,7 +642,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -707,7 +707,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -715,7 +715,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -723,7 +723,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableC), 'priceable_id' => $purchasableC->id, @@ -801,7 +801,7 @@ Price::factory()->create([ 'price' => 1000, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -879,7 +879,7 @@ Price::factory()->create([ 'price' => 1000, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -956,7 +956,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1018,7 +1018,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1080,7 +1080,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1143,7 +1143,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1205,7 +1205,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1273,7 +1273,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1335,7 +1335,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1420,7 +1420,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1498,7 +1498,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1570,7 +1570,7 @@ Price::factory()->create([ 'price' => 15, // £0.15 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -1578,7 +1578,7 @@ Price::factory()->create([ 'price' => 20, // £0.20 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -1586,7 +1586,7 @@ Price::factory()->create([ 'price' => 40, // £0.40 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableC), 'priceable_id' => $purchasableC->id, @@ -1594,7 +1594,7 @@ Price::factory()->create([ 'price' => 40, // £0.40 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableD), 'priceable_id' => $purchasableD->id, @@ -1602,7 +1602,7 @@ Price::factory()->create([ 'price' => 40, // £0.40 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableE), 'priceable_id' => $purchasableE->id, @@ -1702,7 +1702,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, diff --git a/tests/core/Unit/DiscountTypes/BuyXGetYTest.php b/tests/core/Unit/DiscountTypes/BuyXGetYTest.php index e887f34236..45478994c1 100644 --- a/tests/core/Unit/DiscountTypes/BuyXGetYTest.php +++ b/tests/core/Unit/DiscountTypes/BuyXGetYTest.php @@ -146,7 +146,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -160,7 +160,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -245,7 +245,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -253,7 +253,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -341,7 +341,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -349,7 +349,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -453,7 +453,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -461,7 +461,7 @@ Price::factory()->create([ 'price' => 500, // £5 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -588,7 +588,7 @@ Price::factory()->create([ 'price' => 1064, // $10.64 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -596,7 +596,7 @@ Price::factory()->create([ 'price' => 2280, // $22.80 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -725,7 +725,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, @@ -733,7 +733,7 @@ Price::factory()->create([ 'price' => 500, // £5 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, @@ -741,7 +741,7 @@ Price::factory()->create([ 'price' => 200, // £2 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableC), 'priceable_id' => $purchasableC->id, diff --git a/tests/core/Unit/Jobs/Collections/UpdateProductPositionsTest.php b/tests/core/Unit/Jobs/Collections/UpdateProductPositionsTest.php index 74461f262a..43edb96eef 100644 --- a/tests/core/Unit/Jobs/Collections/UpdateProductPositionsTest.php +++ b/tests/core/Unit/Jobs/Collections/UpdateProductPositionsTest.php @@ -33,7 +33,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, 'price' => $prices[$index], ]); } diff --git a/tests/core/Unit/Managers/DiscountManagerTest.php b/tests/core/Unit/Managers/DiscountManagerTest.php index ad825cf688..5b0d80ff45 100644 --- a/tests/core/Unit/Managers/DiscountManagerTest.php +++ b/tests/core/Unit/Managers/DiscountManagerTest.php @@ -298,7 +298,7 @@ Price::factory()->create([ 'price' => 1000, // £10 - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableA), 'priceable_id' => $purchasableA->id, diff --git a/tests/core/Unit/Managers/PricingManagerTest.php b/tests/core/Unit/Managers/PricingManagerTest.php index cf5451778d..73a5447b79 100644 --- a/tests/core/Unit/Managers/PricingManagerTest.php +++ b/tests/core/Unit/Managers/PricingManagerTest.php @@ -40,7 +40,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); Price::factory()->create([ @@ -48,7 +48,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 10, + 'min_quantity' => 10, ]); Price::factory()->create([ @@ -56,7 +56,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, 'customer_group_id' => CustomerGroup::factory(), ]); @@ -64,7 +64,7 @@ expect($pricing)->toBeInstanceOf(PricingResponse::class); expect($pricing->customerGroupPrices)->toHaveCount(0); - expect($pricing->quantityBreaks)->toHaveCount(1); + expect($pricing->priceBreaks)->toHaveCount(1); expect($pricing->base->id)->toEqual($base->id); expect($pricing->matched->id)->toEqual($base->id); }); @@ -90,7 +90,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); $pricing = $manager->for($variant)->get(); @@ -123,7 +123,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); $customerGroupPrice = Price::factory()->create([ @@ -131,7 +131,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, 'customer_group_id' => $customerGroups->first()->id, ]); @@ -173,7 +173,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); $break10 = Price::factory()->create([ @@ -181,7 +181,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 10, + 'min_quantity' => 10, ]); $break20 = Price::factory()->create([ @@ -189,7 +189,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 20, + 'min_quantity' => 20, ]); $break30 = Price::factory()->create([ @@ -197,7 +197,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 30, + 'min_quantity' => 30, ]); $pricing = $manager->qty(1)->for($variant)->get(); @@ -267,7 +267,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $defaultCurrency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); $additional = Price::factory()->create([ @@ -275,7 +275,7 @@ 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $secondCurrency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); $pricing = $manager->qty(1)->for($variant)->get(); @@ -318,7 +318,7 @@ function can_fetch_correct_price_for_user() 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $defaultCurrency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); $groupPrice = Price::factory()->create([ @@ -326,7 +326,7 @@ function can_fetch_correct_price_for_user() 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $defaultCurrency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, 'customer_group_id' => $group->id, ]); @@ -372,7 +372,7 @@ function can_fetch_correct_price_for_user() 'priceable_type' => ProductVariant::class, 'priceable_id' => $variant->id, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); $pricing = $manager->for($variant)->get(); diff --git a/tests/core/Unit/Models/CartTest.php b/tests/core/Unit/Models/CartTest.php index 58ad5642c7..198eb82868 100644 --- a/tests/core/Unit/Models/CartTest.php +++ b/tests/core/Unit/Models/CartTest.php @@ -398,7 +398,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -419,7 +419,7 @@ Price::factory()->create([ 'price' => 158, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -468,7 +468,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -489,7 +489,7 @@ Price::factory()->create([ 'price' => 158, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -531,7 +531,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -555,7 +555,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -583,7 +583,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -607,7 +607,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -684,7 +684,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -773,7 +773,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($variant), 'priceable_id' => $variant->id, @@ -812,7 +812,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($variant), 'priceable_id' => $variant->id, @@ -871,7 +871,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -932,7 +932,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Models/PriceTest.php b/tests/core/Unit/Models/PriceTest.php index 23aaeeed82..1488dc2eda 100644 --- a/tests/core/Unit/Models/PriceTest.php +++ b/tests/core/Unit/Models/PriceTest.php @@ -23,7 +23,7 @@ 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 123, - 'quantity_break' => 1, + 'min_quantity' => 1, ]; Price::factory()->create($data); @@ -43,7 +43,7 @@ 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 123, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); expect($price->price)->toBeInstanceOf(DataTypesPrice::class); @@ -64,7 +64,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 12.99, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); expect($price->price->value)->toEqual(1299); @@ -81,7 +81,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 12.995, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); expect($price->price->value)->toEqual(12995); @@ -93,7 +93,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 1299, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); expect($price->price->value)->toEqual(1299); @@ -110,7 +110,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => '1,250.950', - 'quantity_break' => 1, + 'min_quantity' => 1, ]); expect($price->price->value)->toEqual(1250950); @@ -122,7 +122,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => '1,250.955', - 'quantity_break' => 1, + 'min_quantity' => 1, ]); expect($price->price->value)->toEqual(1250955); @@ -144,7 +144,7 @@ function can_handle_non_int_values() 'priceable_type' => ProductVariant::class, 'price' => 12.99, 'compare_price' => 13.99, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); expect($price->compare_price)->toBeInstanceOf(DataTypesPrice::class); @@ -177,7 +177,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 123, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); Price::factory()->create([ @@ -185,7 +185,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 99, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); Price::factory()->create([ @@ -193,7 +193,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 101, - 'quantity_break' => 5, + 'min_quantity' => 5, ]); Price::factory()->create([ @@ -202,7 +202,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 75, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); // Check we get the default currency price @@ -242,7 +242,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 999, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); expect($price->priceExTax()->value)->toEqual(833); @@ -264,7 +264,7 @@ function can_handle_non_int_values() 'priceable_id' => $variant->id, 'priceable_type' => ProductVariant::class, 'price' => 833, - 'quantity_break' => 1, + 'min_quantity' => 1, ]); expect($price->priceIncTax()->value)->toEqual(1000); diff --git a/tests/core/Unit/Models/ProductVariantTest.php b/tests/core/Unit/Models/ProductVariantTest.php index 2b4ccaca64..dca61718cf 100644 --- a/tests/core/Unit/Models/ProductVariantTest.php +++ b/tests/core/Unit/Models/ProductVariantTest.php @@ -58,30 +58,30 @@ [ 'price' => 100, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ], [ 'price' => 90, 'currency_id' => $currency->id, 'customer_group_id' => $groupA->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ], [ 'price' => 80, 'currency_id' => $currency->id, 'customer_group_id' => $groupB->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ], [ 'price' => 30, 'currency_id' => $currency->id, 'customer_group_id' => $groupB->id, - 'quantity_break' => 5, + 'min_quantity' => 5, ], [ 'price' => 60, 'currency_id' => $currency->id, - 'quantity_break' => 5, + 'min_quantity' => 5, ], ]); @@ -119,12 +119,12 @@ [ 'price' => 100, 'currency_id' => $currencyA->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ], [ 'price' => 200, 'currency_id' => $currencyB->id, - 'quantity_break' => 1, + 'min_quantity' => 1, ], ]); @@ -210,21 +210,21 @@ Price::factory()->create([ 'price' => 10000, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, 'priceable_type' => ProductVariant::class, 'priceable_id' => $genericProductVariant->id, ]); Price::factory()->create([ 'price' => 8000, 'currency_id' => $currency->id, - 'quantity_break' => 10, + 'min_quantity' => 10, 'priceable_type' => ProductVariant::class, 'priceable_id' => $genericProductVariant->id, ]); Price::factory()->create([ 'price' => 400, 'currency_id' => $currency->id, - 'quantity_break' => 1, + 'min_quantity' => 1, 'priceable_type' => ProductVariant::class, 'priceable_id' => $foodProductVariant->id, ]); diff --git a/tests/core/Unit/Pipelines/Cart/ApplyShippingTest.php b/tests/core/Unit/Pipelines/Cart/ApplyShippingTest.php index 12a60bbd72..4075c4adb6 100644 --- a/tests/core/Unit/Pipelines/Cart/ApplyShippingTest.php +++ b/tests/core/Unit/Pipelines/Cart/ApplyShippingTest.php @@ -28,7 +28,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -108,7 +108,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Pipelines/Cart/CalculateLinesTest.php b/tests/core/Unit/Pipelines/Cart/CalculateLinesTest.php index f8f2af2c89..c32944f7fe 100644 --- a/tests/core/Unit/Pipelines/Cart/CalculateLinesTest.php +++ b/tests/core/Unit/Pipelines/Cart/CalculateLinesTest.php @@ -23,7 +23,7 @@ Price::factory()->create([ 'price' => $incomingUnitPrice, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Pipelines/Order/Creation/CleanUpOrderLinesTest.php b/tests/core/Unit/Pipelines/Order/Creation/CleanUpOrderLinesTest.php index cbcb172e87..83c79a0111 100644 --- a/tests/core/Unit/Pipelines/Order/Creation/CleanUpOrderLinesTest.php +++ b/tests/core/Unit/Pipelines/Order/Creation/CleanUpOrderLinesTest.php @@ -48,7 +48,7 @@ \Lunar\Models\Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, @@ -56,7 +56,7 @@ \Lunar\Models\Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasableB), 'priceable_id' => $purchasableB->id, diff --git a/tests/core/Unit/Pipelines/Order/Creation/CreateOrderLinesTest.php b/tests/core/Unit/Pipelines/Order/Creation/CreateOrderLinesTest.php index 641fffc4fa..44b3020400 100644 --- a/tests/core/Unit/Pipelines/Order/Creation/CreateOrderLinesTest.php +++ b/tests/core/Unit/Pipelines/Order/Creation/CreateOrderLinesTest.php @@ -22,7 +22,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/core/Unit/Pipelines/Order/Creation/FillOrderFromCartTest.php b/tests/core/Unit/Pipelines/Order/Creation/FillOrderFromCartTest.php index 340dda9d96..b7859a3942 100644 --- a/tests/core/Unit/Pipelines/Order/Creation/FillOrderFromCartTest.php +++ b/tests/core/Unit/Pipelines/Order/Creation/FillOrderFromCartTest.php @@ -22,7 +22,7 @@ Price::factory()->create([ 'price' => 100, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/shipping/TestUtils.php b/tests/shipping/TestUtils.php index bc20010335..663a9f33ad 100644 --- a/tests/shipping/TestUtils.php +++ b/tests/shipping/TestUtils.php @@ -26,7 +26,7 @@ public function createCart($currency = null, $price = 100, $quantity = 1) Price::factory()->create([ 'price' => $price, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, diff --git a/tests/shipping/Unit/Drivers/ShippingMethods/FlatRateTest.php b/tests/shipping/Unit/Drivers/ShippingMethods/FlatRateTest.php index 2b8d3619b5..6f3741219f 100644 --- a/tests/shipping/Unit/Drivers/ShippingMethods/FlatRateTest.php +++ b/tests/shipping/Unit/Drivers/ShippingMethods/FlatRateTest.php @@ -44,7 +44,7 @@ $shippingRate->prices()->createMany([ [ 'price' => 600, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, ], ]); diff --git a/tests/shipping/Unit/Drivers/ShippingMethods/ShipByTest.php b/tests/shipping/Unit/Drivers/ShippingMethods/ShipByTest.php index a4c9ebdadf..554df5da50 100644 --- a/tests/shipping/Unit/Drivers/ShippingMethods/ShipByTest.php +++ b/tests/shipping/Unit/Drivers/ShippingMethods/ShipByTest.php @@ -42,12 +42,12 @@ $shippingRate->prices()->createMany([ [ 'price' => 1000, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, ], [ 'price' => 500, - 'quantity_break' => 700, + 'min_quantity' => 700, 'currency_id' => $currency->id, ], ]); @@ -117,12 +117,12 @@ $shippingRate->prices()->createMany([ [ 'price' => 1000, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, ], [ 'price' => 500, - 'quantity_break' => 700, + 'min_quantity' => 700, 'currency_id' => $currency->id, ], ]); @@ -176,7 +176,7 @@ $shippingRate->prices()->createMany([ [ 'price' => 500, - 'quantity_break' => 700, + 'min_quantity' => 700, 'currency_id' => $currency->id, ], ]); diff --git a/tests/shipping/Unit/Managers/ShippingManagerTest.php b/tests/shipping/Unit/Managers/ShippingManagerTest.php index a2e28e71c5..f6cb140bd2 100644 --- a/tests/shipping/Unit/Managers/ShippingManagerTest.php +++ b/tests/shipping/Unit/Managers/ShippingManagerTest.php @@ -54,17 +54,17 @@ $shippingRate->prices()->createMany([ [ 'price' => 600, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, ], [ 'price' => 500, - 'quantity_break' => 700, + 'min_quantity' => 700, 'currency_id' => $currency->id, ], [ 'price' => 0, - 'quantity_break' => 800, + 'min_quantity' => 800, 'currency_id' => $currency->id, ], ]); diff --git a/tests/shipping/Unit/Resolvers/ShippingOptionResolverTest.php b/tests/shipping/Unit/Resolvers/ShippingOptionResolverTest.php index 0f51e1de3a..b491e1c93f 100644 --- a/tests/shipping/Unit/Resolvers/ShippingOptionResolverTest.php +++ b/tests/shipping/Unit/Resolvers/ShippingOptionResolverTest.php @@ -49,17 +49,17 @@ $shippingRate->prices()->createMany([ [ 'price' => 600, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, ], [ 'price' => 500, - 'quantity_break' => 700, + 'min_quantity' => 700, 'currency_id' => $currency->id, ], [ 'price' => 0, - 'quantity_break' => 800, + 'min_quantity' => 800, 'currency_id' => $currency->id, ], ]); diff --git a/tests/shipping/Unit/Resolvers/ShippingRateResolverTest.php b/tests/shipping/Unit/Resolvers/ShippingRateResolverTest.php index cc5d5329f5..1e20d77713 100644 --- a/tests/shipping/Unit/Resolvers/ShippingRateResolverTest.php +++ b/tests/shipping/Unit/Resolvers/ShippingRateResolverTest.php @@ -50,17 +50,17 @@ $shippingRate->prices()->createMany([ [ 'price' => 600, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, ], [ 'price' => 500, - 'quantity_break' => 700, + 'min_quantity' => 700, 'currency_id' => $currency->id, ], [ 'price' => 0, - 'quantity_break' => 800, + 'min_quantity' => 800, 'currency_id' => $currency->id, ], ]); @@ -137,17 +137,17 @@ $shippingRate->prices()->createMany([ [ 'price' => 600, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, ], [ 'price' => 500, - 'quantity_break' => 700, + 'min_quantity' => 700, 'currency_id' => $currency->id, ], [ 'price' => 0, - 'quantity_break' => 800, + 'min_quantity' => 800, 'currency_id' => $currency->id, ], ]); @@ -207,17 +207,17 @@ $shippingRate->prices()->createMany([ [ 'price' => 600, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, ], [ 'price' => 500, - 'quantity_break' => 700, + 'min_quantity' => 700, 'currency_id' => $currency->id, ], [ 'price' => 0, - 'quantity_break' => 800, + 'min_quantity' => 800, 'currency_id' => $currency->id, ], ]); @@ -279,17 +279,17 @@ $shippingRate->prices()->createMany([ [ 'price' => 600, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, ], [ 'price' => 500, - 'quantity_break' => 700, + 'min_quantity' => 700, 'currency_id' => $currency->id, ], [ 'price' => 0, - 'quantity_break' => 800, + 'min_quantity' => 800, 'currency_id' => $currency->id, ], ]); @@ -301,7 +301,7 @@ Price::factory()->create([ 'price' => 200, - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'priceable_type' => get_class($purchasable), 'priceable_id' => $purchasable->id, From 8b8babe9cd15d7b2e66aa8b1bbc777e2fd6d449d Mon Sep 17 00:00:00 2001 From: Glenn Jacobs Date: Wed, 14 Feb 2024 23:23:23 +0000 Subject: [PATCH 03/12] Quantity break fixes --- .../resources/lang/en/relationmanagers.php | 8 ++++---- .../ProductResource/Pages/ListProducts.php | 2 +- .../Pages/ManageProductPricing.php | 8 ++++---- .../Products/ManagesProductPricing.php | 2 +- .../RelationManagers/PriceRelationManager.php | 18 +++++++++--------- packages/core/src/Base/Traits/HasPrices.php | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/admin/resources/lang/en/relationmanagers.php b/packages/admin/resources/lang/en/relationmanagers.php index dcebc30753..1c50c068be 100644 --- a/packages/admin/resources/lang/en/relationmanagers.php +++ b/packages/admin/resources/lang/en/relationmanagers.php @@ -142,8 +142,8 @@ 'label' => 'Customer Group', 'placeholder' => 'All Customer Groups', ], - 'min_quantity' => [ - 'label' => 'Minimum Quantity', + 'quantity_break' => [ + 'label' => 'Quantity Break', ], 'currency' => [ 'label' => 'Currency', @@ -159,8 +159,8 @@ 'placeholder' => 'All Customer Groups', 'helper_text' => 'Select which customer group to apply this price to.', ], - 'min_quantity' => [ - 'label' => 'Minimum Quantity', + 'quantity_break' => [ + 'label' => 'Quantity Break', 'helper_text' => 'Select the minimum quantity this price will be available for.', ], 'currency_id' => [ diff --git a/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php b/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php index e8f26219f3..3434203ecd 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php @@ -78,7 +78,7 @@ public static function createRecord(array $data, string $model): Model 'sku' => $data['sku'], ]); $variant->prices()->create([ - 'min_quantity' => 1, + 'quantity_break' => 1, 'currency_id' => $currency->id, 'price' => (int) bcmul($data['base_price'], $currency->factor), ]); diff --git a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php index a2991256eb..9c05f03534 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php @@ -74,7 +74,7 @@ public function table(Table $table): Table return $table ->recordTitleAttribute('name') ->modifyQueryUsing( - fn ($query) => $query->orderBy('min_quantity', 'asc') + fn ($query) => $query->orderBy('quantity_break', 'asc') ) ->columns([ Tables\Columns\TextColumn::make('price') @@ -86,7 +86,7 @@ public function table(Table $table): Table Tables\Columns\TextColumn::make('currency.code')->label( __('lunarpanel::relationmanagers.pricing.table.currency.label') ), - Tables\Columns\TextColumn::make('min_quantity')->label( + Tables\Columns\TextColumn::make('quantity_break')->label( __('lunarpanel::relationmanagers.pricing.table.min_quantity.label') ), Tables\Columns\TextColumn::make('customerGroup.name')->label( @@ -97,11 +97,11 @@ public function table(Table $table): Table Tables\Filters\SelectFilter::make('currency') ->relationship(name: 'currency', titleAttribute: 'name') ->preload(), - Tables\Filters\SelectFilter::make('min_quantity')->options( + Tables\Filters\SelectFilter::make('quantity_break')->options( Price::where('priceable_id', $this->getOwnerRecord()->id) ->where('priceable_type', get_class($this->getOwnerRecord())) ->get() - ->pluck('min_quantity', 'min_quantity') + ->pluck('quantity_break', 'quantity_break') ), ]) ->headerActions([ diff --git a/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php b/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php index 1b3dbd1cb6..dbcd64174b 100644 --- a/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php +++ b/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php @@ -55,7 +55,7 @@ protected function handleRecordUpdate(Model $record, array $data): Model 'currency_id' => $price['currency_id'], 'price' => (int) ($price['value'] * $price['factor']), 'compare_price' => (int) ($price['compare_price'] * $price['factor']), - 'min_quantity' => 1, + 'quantity_break' => 1, 'customer_group_id' => null, ]) ); diff --git a/packages/admin/src/Support/RelationManagers/PriceRelationManager.php b/packages/admin/src/Support/RelationManagers/PriceRelationManager.php index 47db4eba18..798f8d8a1d 100644 --- a/packages/admin/src/Support/RelationManagers/PriceRelationManager.php +++ b/packages/admin/src/Support/RelationManagers/PriceRelationManager.php @@ -50,11 +50,11 @@ public function form(Form $form): Form )->helperText( __('lunarpanel::relationmanagers.pricing.form.customer_group_id.helper_text') )->relationship(name: 'customerGroup', titleAttribute: 'name'), - Forms\Components\TextInput::make('min_quantity') + Forms\Components\TextInput::make('quantity_break') ->label( - __('lunarpanel::relationmanagers.pricing.form.min_quantity.label') + __('lunarpanel::relationmanagers.pricing.form.quantity_break.label') )->default(1)->helperText( - __('lunarpanel::relationmanagers.pricing.form.min_quantity.helper_text') + __('lunarpanel::relationmanagers.pricing.form.quantity_break.helper_text') )->numeric()->minValue(1)->required(), ])->columns(3), @@ -66,7 +66,7 @@ public function form(Form $form): Form $owner = $this->getOwnerRecord(); return $rule->where('customer_group_id', $get('customer_group_id')) - ->where('min_quantity', 1) + ->where('quantity_break', 1) ->where('currency_id', 1) ->where('priceable_type', get_class($owner)) ->where('priceable_id', $owner->id); @@ -96,8 +96,8 @@ public function table(Table $table): Table ) ->modifyQueryUsing( fn ($query) => $query - ->where("{$priceTable}.min_quantity", '>', 1) - ->orderBy("{$priceTable}.min_quantity", 'asc') + ->where("{$priceTable}.quantity_break", '>', 1) + ->orderBy("{$priceTable}.quantity_break", 'asc') )->emptyStateHeading( __('lunarpanel::relationmanagers.pricing.table.empty_state.label') ) @@ -111,7 +111,7 @@ public function table(Table $table): Table Tables\Columns\TextColumn::make('currency.code')->label( __('lunarpanel::relationmanagers.pricing.table.currency.label') )->sortable(), - Tables\Columns\TextColumn::make('min_quantity')->label( + Tables\Columns\TextColumn::make('quantity_break')->label( __('lunarpanel::relationmanagers.pricing.table.min_quantity.label') )->sortable(), Tables\Columns\TextColumn::make('customerGroup.name')->label( @@ -131,9 +131,9 @@ public function table(Table $table): Table Price::where('priceable_id', $this->getOwnerRecord()->id) ->where('priceable_type', get_class($this->getOwnerRecord())) ->get() - ->pluck('min_quantity', 'min_quantity') + ->pluck('quantity_break', 'quantity_break') )->label( - __('lunarpanel::relationmanagers.pricing.table.min_quantity.label') + __('lunarpanel::relationmanagers.pricing.table.quantity_break.label') ), ]) ->headerActions([ diff --git a/packages/core/src/Base/Traits/HasPrices.php b/packages/core/src/Base/Traits/HasPrices.php index 9a46887743..a71909c9f4 100644 --- a/packages/core/src/Base/Traits/HasPrices.php +++ b/packages/core/src/Base/Traits/HasPrices.php @@ -25,12 +25,12 @@ public function prices(): MorphMany */ public function basePrices(): MorphMany { - return $this->prices()->whereMinQuantity(1)->whereNull('customer_group_id'); + return $this->prices()->whereQuantityBreak(1)->whereNull('customer_group_id'); } public function priceBreaks(): MorphMany { - return $this->prices()->where('min_quantity', '>', 1); + return $this->prices()->where('quantity_break', '>', 1); } /** From ad1fd2d3d7e5c972b60c08d5d9f9168787984b89 Mon Sep 17 00:00:00 2001 From: Glenn Jacobs Date: Wed, 14 Feb 2024 23:36:26 +0000 Subject: [PATCH 04/12] Revert "Quantity break fixes" This reverts commit 8b8babe9cd15d7b2e66aa8b1bbc777e2fd6d449d. --- .../resources/lang/en/relationmanagers.php | 8 ++++---- .../ProductResource/Pages/ListProducts.php | 2 +- .../Pages/ManageProductPricing.php | 8 ++++---- .../Products/ManagesProductPricing.php | 2 +- .../RelationManagers/PriceRelationManager.php | 18 +++++++++--------- packages/core/src/Base/Traits/HasPrices.php | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/admin/resources/lang/en/relationmanagers.php b/packages/admin/resources/lang/en/relationmanagers.php index 1c50c068be..dcebc30753 100644 --- a/packages/admin/resources/lang/en/relationmanagers.php +++ b/packages/admin/resources/lang/en/relationmanagers.php @@ -142,8 +142,8 @@ 'label' => 'Customer Group', 'placeholder' => 'All Customer Groups', ], - 'quantity_break' => [ - 'label' => 'Quantity Break', + 'min_quantity' => [ + 'label' => 'Minimum Quantity', ], 'currency' => [ 'label' => 'Currency', @@ -159,8 +159,8 @@ 'placeholder' => 'All Customer Groups', 'helper_text' => 'Select which customer group to apply this price to.', ], - 'quantity_break' => [ - 'label' => 'Quantity Break', + 'min_quantity' => [ + 'label' => 'Minimum Quantity', 'helper_text' => 'Select the minimum quantity this price will be available for.', ], 'currency_id' => [ diff --git a/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php b/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php index 3434203ecd..e8f26219f3 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php @@ -78,7 +78,7 @@ public static function createRecord(array $data, string $model): Model 'sku' => $data['sku'], ]); $variant->prices()->create([ - 'quantity_break' => 1, + 'min_quantity' => 1, 'currency_id' => $currency->id, 'price' => (int) bcmul($data['base_price'], $currency->factor), ]); diff --git a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php index 9c05f03534..a2991256eb 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductPricing.php @@ -74,7 +74,7 @@ public function table(Table $table): Table return $table ->recordTitleAttribute('name') ->modifyQueryUsing( - fn ($query) => $query->orderBy('quantity_break', 'asc') + fn ($query) => $query->orderBy('min_quantity', 'asc') ) ->columns([ Tables\Columns\TextColumn::make('price') @@ -86,7 +86,7 @@ public function table(Table $table): Table Tables\Columns\TextColumn::make('currency.code')->label( __('lunarpanel::relationmanagers.pricing.table.currency.label') ), - Tables\Columns\TextColumn::make('quantity_break')->label( + Tables\Columns\TextColumn::make('min_quantity')->label( __('lunarpanel::relationmanagers.pricing.table.min_quantity.label') ), Tables\Columns\TextColumn::make('customerGroup.name')->label( @@ -97,11 +97,11 @@ public function table(Table $table): Table Tables\Filters\SelectFilter::make('currency') ->relationship(name: 'currency', titleAttribute: 'name') ->preload(), - Tables\Filters\SelectFilter::make('quantity_break')->options( + Tables\Filters\SelectFilter::make('min_quantity')->options( Price::where('priceable_id', $this->getOwnerRecord()->id) ->where('priceable_type', get_class($this->getOwnerRecord())) ->get() - ->pluck('quantity_break', 'quantity_break') + ->pluck('min_quantity', 'min_quantity') ), ]) ->headerActions([ diff --git a/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php b/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php index dbcd64174b..1b3dbd1cb6 100644 --- a/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php +++ b/packages/admin/src/Support/Concerns/Products/ManagesProductPricing.php @@ -55,7 +55,7 @@ protected function handleRecordUpdate(Model $record, array $data): Model 'currency_id' => $price['currency_id'], 'price' => (int) ($price['value'] * $price['factor']), 'compare_price' => (int) ($price['compare_price'] * $price['factor']), - 'quantity_break' => 1, + 'min_quantity' => 1, 'customer_group_id' => null, ]) ); diff --git a/packages/admin/src/Support/RelationManagers/PriceRelationManager.php b/packages/admin/src/Support/RelationManagers/PriceRelationManager.php index 798f8d8a1d..47db4eba18 100644 --- a/packages/admin/src/Support/RelationManagers/PriceRelationManager.php +++ b/packages/admin/src/Support/RelationManagers/PriceRelationManager.php @@ -50,11 +50,11 @@ public function form(Form $form): Form )->helperText( __('lunarpanel::relationmanagers.pricing.form.customer_group_id.helper_text') )->relationship(name: 'customerGroup', titleAttribute: 'name'), - Forms\Components\TextInput::make('quantity_break') + Forms\Components\TextInput::make('min_quantity') ->label( - __('lunarpanel::relationmanagers.pricing.form.quantity_break.label') + __('lunarpanel::relationmanagers.pricing.form.min_quantity.label') )->default(1)->helperText( - __('lunarpanel::relationmanagers.pricing.form.quantity_break.helper_text') + __('lunarpanel::relationmanagers.pricing.form.min_quantity.helper_text') )->numeric()->minValue(1)->required(), ])->columns(3), @@ -66,7 +66,7 @@ public function form(Form $form): Form $owner = $this->getOwnerRecord(); return $rule->where('customer_group_id', $get('customer_group_id')) - ->where('quantity_break', 1) + ->where('min_quantity', 1) ->where('currency_id', 1) ->where('priceable_type', get_class($owner)) ->where('priceable_id', $owner->id); @@ -96,8 +96,8 @@ public function table(Table $table): Table ) ->modifyQueryUsing( fn ($query) => $query - ->where("{$priceTable}.quantity_break", '>', 1) - ->orderBy("{$priceTable}.quantity_break", 'asc') + ->where("{$priceTable}.min_quantity", '>', 1) + ->orderBy("{$priceTable}.min_quantity", 'asc') )->emptyStateHeading( __('lunarpanel::relationmanagers.pricing.table.empty_state.label') ) @@ -111,7 +111,7 @@ public function table(Table $table): Table Tables\Columns\TextColumn::make('currency.code')->label( __('lunarpanel::relationmanagers.pricing.table.currency.label') )->sortable(), - Tables\Columns\TextColumn::make('quantity_break')->label( + Tables\Columns\TextColumn::make('min_quantity')->label( __('lunarpanel::relationmanagers.pricing.table.min_quantity.label') )->sortable(), Tables\Columns\TextColumn::make('customerGroup.name')->label( @@ -131,9 +131,9 @@ public function table(Table $table): Table Price::where('priceable_id', $this->getOwnerRecord()->id) ->where('priceable_type', get_class($this->getOwnerRecord())) ->get() - ->pluck('quantity_break', 'quantity_break') + ->pluck('min_quantity', 'min_quantity') )->label( - __('lunarpanel::relationmanagers.pricing.table.quantity_break.label') + __('lunarpanel::relationmanagers.pricing.table.min_quantity.label') ), ]) ->headerActions([ diff --git a/packages/core/src/Base/Traits/HasPrices.php b/packages/core/src/Base/Traits/HasPrices.php index a71909c9f4..9a46887743 100644 --- a/packages/core/src/Base/Traits/HasPrices.php +++ b/packages/core/src/Base/Traits/HasPrices.php @@ -25,12 +25,12 @@ public function prices(): MorphMany */ public function basePrices(): MorphMany { - return $this->prices()->whereQuantityBreak(1)->whereNull('customer_group_id'); + return $this->prices()->whereMinQuantity(1)->whereNull('customer_group_id'); } public function priceBreaks(): MorphMany { - return $this->prices()->where('quantity_break', '>', 1); + return $this->prices()->where('min_quantity', '>', 1); } /** From 62af43ef147ab6ca51da448bcb386770a2e4ddae Mon Sep 17 00:00:00 2001 From: Glenn Jacobs Date: Wed, 14 Feb 2024 23:38:58 +0000 Subject: [PATCH 05/12] Fix tests --- .gitignore | 1 + .phpunit.cache/test-results | 1 - phpunit.xml | 7 ------- 3 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 .phpunit.cache/test-results diff --git a/.gitignore b/.gitignore index 20283ccc21..19d8b246d4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ composer.lock /vendor .phpunit.result.cache +.phpunit.cache/ /.idea /.vscode node_modules/ diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results deleted file mode 100644 index b43cbdfa87..0000000000 --- a/.phpunit.cache/test-results +++ /dev/null @@ -1 +0,0 @@ -{"version":"pest_2.33.1","defects":[],"times":{"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_render":0.084,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_customer":0.078,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_order":0.084,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_collection":0.06,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_brand":0.061,"P\\Tests\\admin\\Feature\\Filament\\Panel\\GlobalSearch\\GlobalSearchTest::__pest_evaluable_it_can_search_product":0.065,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\Pages\\EditAttributeGroupTest::__pest_evaluable_it_can_render_attribute_group_edit_page":0.124,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\Pages\\EditAttributeGroupTest::__pest_evaluable_it_can_retrieve_attribute_group_data":0.068,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_render_relation_manager":0.077,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"text\"":0.245,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"richtext\"":0.224,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"dropdown\"":0.234,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"dropdown-with-lookups\"":0.263,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"number\"":0.233,"P\\Tests\\admin\\Feature\\Filament\\Resources\\AttributeGroupResource\\RelationManagers\\AttributesRelationManagerTest::__pest_evaluable_it_can_create_attributes#dataset \"number-with-min-max\"":0.26,"P\\Tests\\admin\\Feature\\Filament\\Resources\\BrandResource\\Actions\\SearchTest::__pest_evaluable_it_can_search_brand_by_name_on_brand_list":0.163,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CollectionResources\\Pages\\ManageCollectionChildrenTest::__pest_evaluable_it_can_render_the_collection_children_page":0.092,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CollectionResources\\Pages\\ManageCollectionChildrenTest::__pest_evaluable_it_can_create_child_categories":0.13,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\CreateCustomerTest::__pest_evaluable_it_can_render_customer_create_page":0.092,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\CreateCustomerTest::__pest_evaluable_it_can_create_customer":0.148,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\EditCustomerTest::__pest_evaluable_it_can_render_customer_edit_page":0.111,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\EditCustomerTest::__pest_evaluable_it_can_retrieve_customer_data":0.075,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\EditCustomerTest::__pest_evaluable_it_can_save_customer_data":0.12,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\ListCustomersTest::__pest_evaluable_it_can_render_customer_index_page":0.084,"P\\Tests\\admin\\Feature\\Filament\\Resources\\CustomerResource\\Pages\\ListCustomersTest::__pest_evaluable_it_can_list_customers":0.094,"P\\Tests\\admin\\Feature\\Filament\\Resources\\OrderResource\\Pages\\ManageOrderTest::__pest_evaluable_it_can_render_order_manage_page":0.256,"P\\Tests\\admin\\Feature\\Filament\\Resources\\OrderResource\\Pages\\ManageOrderTest::__pest_evaluable_it_can_download_order_pdf":0.204,"P\\Tests\\admin\\Feature\\Filament\\Resources\\OrderResource\\Pages\\ManageOrderTest::__pest_evaluable_it_can_update_order_status":0.281,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Actions\\SearchTest::__pest_evaluable_it_can_search_product_by_name_on_list":0.117,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\ListProductsTest::__pest_evaluable_it_can_create_product":0.23,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductIdentifiersTest::__pest_evaluable_it_can_render_product_identifiers_page":0.099,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductIdentifiersTest::__pest_evaluable_it_will_show_in_navigation_when_only_one_variant_exists":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductIdentifiersTest::__pest_evaluable_it_will_not_show_in_navigation_when_multiple_variants_exist":0.102,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductIdentifiersTest::__pest_evaluable_it_can_update_variant_identifiers":0.161,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductInventoryTest::__pest_evaluable_it_can_render_product_inventory_page":0.1,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductInventoryTest::__pest_evaluable_it_will_show_in_navigation_when_only_one_variant_exists":0.1,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductInventoryTest::__pest_evaluable_it_will_not_show_in_navigation_when_multiple_variants_exist":0.1,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductInventoryTest::__pest_evaluable_it_can_update_variant_stock_figures":0.153,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductPricingTest::__pest_evaluable_it_can_render_product_prices_create_page":0.103,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductPricingTest::__pest_evaluable_it_will_show_in_navigation_when_only_one_variant_exists":0.104,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductPricingTest::__pest_evaluable_it_will_not_show_in_navigation_when_multiple_variants_exist":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_can_render_product_shipping_page":0.107,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_will_show_in_navigation_when_only_one_variant_exists":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_will_not_show_in_navigation_when_multiple_variants_exist":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_can_update_variant_shipping":0.311,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductShippingTest::__pest_evaluable_it_can_set_shipping_volume_automatically":0.333,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Pages\\ManageProductUrlsTest::__pest_evaluable_it_can_render_product_urls_create_page":0.108,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_mount_widget":0.062,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_render_collection_tree":0.071,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_create_root_collection":0.085,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_toggle_collection_children":0.099,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_create_child_collection":0.184,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_set_child_collection_as_root":0.107,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductResource\\Widgets\\CollectionTreeViewTest::__pest_evaluable_it_can_reorder_collections":0.088,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductTypeResource\\Pages\\CreateProductTypeTest::__pest_evaluable_it_can_render_product_type_create_page":0.089,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductTypeResource\\Pages\\CreateProductTypeTest::__pest_evaluable_it_can_create_product_type":0.085,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductTypeResource\\Pages\\CreateProductTypeTest::__pest_evaluable_it_can_associate_attributes":0.112,"P\\Tests\\admin\\Feature\\Filament\\Resources\\ProductTypeResource\\Pages\\EditProductTypeTest::__pest_evaluable_it_can_associate_attributes":0.135,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\AccessControlTest::__pest_evaluable_it_can_render_acl_page":0.116,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\AccessControlTest::__pest_evaluable_it_can_add_role":0.101,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\AccessControlTest::__pest_evaluable_it_can_delete_role":0.108,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\AccessControlTest::__pest_evaluable_it_can_set_permission_to_role":0.086,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\CreateStaffTest::__pest_evaluable_it_can_render_staff_create_page":0.094,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\CreateStaffTest::__pest_evaluable_it_can_create_staff":0.273,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\EditStaffTest::__pest_evaluable_it_can_render_staff_edit_page":0.093,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\EditStaffTest::__pest_evaluable_it_can_retrieve_staff_data":0.071,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\EditStaffTest::__pest_evaluable_it_can_save_staff_data":0.147,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\EditStaffTest::__pest_evaluable_it_can_assign_staff_role_and_permissions":0.203,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\ListStaffTest::__pest_evaluable_it_can_render_staff_index_page":0.093,"P\\Tests\\admin\\Feature\\Filament\\Resources\\StaffResource\\Pages\\ListStaffTest::__pest_evaluable_it_can_list_staff":0.095,"P\\Tests\\admin\\Feature\\Support\\Extending\\CreatePageExtensionTest::__pest_evaluable_it_can_change_data_before_creation":0.133,"P\\Tests\\admin\\Feature\\Support\\Extending\\CreatePageExtensionTest::__pest_evaluable_it_can_manipulate_model_after_creation":0.13,"P\\Tests\\admin\\Feature\\Support\\Extending\\EditPageExtensionTest::__pest_evaluable_it_can_change_data_before_fill":0.08,"P\\Tests\\admin\\Feature\\Support\\Extending\\EditPageExtensionTest::__pest_evaluable_it_can_change_data_before_save":0.079,"P\\Tests\\admin\\Feature\\Support\\RelationManagers\\MediaRelationManagerTest::__pest_evaluable_it_can_render_relation_manager#dataset \"product\"":0.07,"P\\Tests\\admin\\Feature\\Support\\RelationManagers\\MediaRelationManagerTest::__pest_evaluable_it_can_render_relation_manager#dataset \"brand\"":0.066,"P\\Tests\\admin\\Feature\\Support\\RelationManagers\\PriceRelationManagerTest::__pest_evaluable_it_can_render_relation_manager#dataset \"product\"":0.073,"P\\Tests\\admin\\Unit\\Actions\\Products\\MapVariantsToProductOptionsTest::__pest_evaluable_it_can_map_variants_given_one_set_of_option_values":0.026,"P\\Tests\\admin\\Unit\\Actions\\Products\\MapVariantsToProductOptionsTest::__pest_evaluable_it_can_map_variants_given_three_sets_of_option_values":0.024,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_roles":0.026,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_refreshed_roles":0.026,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_permissions":0.024,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_refreshed_permissions":0.025,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_grouped_permissions":0.024,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_refreshed_grouped_permissions":0.026,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_set_admin":0.023,"P\\Tests\\admin\\Unit\\Auth\\ManifestTest::__pest_evaluable_manifest_can_get_roles_without_admin":0.021,"P\\Tests\\admin\\Unit\\Filament\\Resources\\BrandResource\\Pages\\ManageBrandMediaTest::__pest_evaluable_it_can_return_configured_relation_managers":0.081,"P\\Tests\\admin\\Unit\\Filament\\Resources\\ProductResource\\Pages\\ManageProductMediaTest::__pest_evaluable_it_can_return_configured_relation_managers":0.08,"P\\Tests\\admin\\Unit\\Filament\\Resources\\ProductResource\\RelationManagers\\CustomerGroupRelationManagerTest::__pest_evaluable_it_can_render_relationship_manager":0.065,"P\\Tests\\admin\\Unit\\Livewire\\ActivityLogFeedTest::__pest_evaluable__activity_feed_component__\u2192_can_render":0.056,"P\\Tests\\admin\\Unit\\Livewire\\ActivityLogFeedTest::__pest_evaluable__activity_feed_component__\u2192_can_add_comment":0.074,"P\\Tests\\admin\\Unit\\Livewire\\ActivityLogFeedTest::__pest_evaluable__activity_feed_component__\u2192_can_render_in_infolist":0.056,"P\\Tests\\admin\\Unit\\Support\\Extending\\CreatePageExtensionTest::__pest_evaluable_it_can_extend_header_actions":0.071,"P\\Tests\\admin\\Unit\\Support\\Extending\\CreatePageExtensionTest::__pest_evaluable_it_can_extend_form_actions":0.065,"P\\Tests\\admin\\Unit\\Support\\Extending\\EditPageExtensionTest::__pest_evaluable_it_can_extend_header_actions":0.077,"P\\Tests\\admin\\Unit\\Support\\Extending\\EditPageExtensionTest::__pest_evaluable_it_can_extend_form_actions":0.073,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_relationship_managers":0.023,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_table_columns#dataset \"ListCurrencies\"":0.061,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_table_columns#dataset \"ListLanguages\"":0.058,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_table_columns#dataset \"ListActivities\"":0.067,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_table_columns#dataset \"ListAttributeGroups\"":0.063,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_form_schema#dataset \"CurrencyResource\"":0.066,"P\\Tests\\admin\\Unit\\Support\\Extending\\ResourceExtensionTest::__pest_evaluable_it_can_extend_form_schema#dataset \"LanguageResource\"":0.063,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\DropdownConverterTest::__pest_evaluable__dropdown_converter__\u2192_can_convert_attribute_to_form_input_component":0.023,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\DropdownConverterTest::__pest_evaluable__dropdown_converter__\u2192_can_render_dropdown_options":0.023,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\ListFieldConverterTest::__pest_evaluable__list_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\NumberConverterTest::__pest_evaluable__list_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\TextConverterTest::__pest_evaluable__list_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.025,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\TextConverterTest::__pest_evaluable__list_field_converter__\u2192_can_return_richtext_component":0.026,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\ToggleConverterTest::__pest_evaluable__toggle_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.025,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\TranslatedTextConverterTest::__pest_evaluable__list_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.025,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeConverters\\YouTubeConverterTest::__pest_evaluable__youtube_field_converter__\u2192_can_convert_attribute_to_form_input_component":0.023,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\Text', 'Filament\\Forms\\Components\\TextInput')":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\Text', 'Filament\\Forms\\Components\\RichEditor', [true])":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\Dropdown', 'Filament\\Forms\\Components\\Select')":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\ListField', 'Filament\\Forms\\Components\\KeyValue')":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\YouTube', 'Lunar\\Admin\\Support\\Forms\\Com\u2026ouTube')":0.022,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_correct_form_components_are_returned#('Lunar\\FieldTypes\\Number', 'Filament\\Forms\\Components\\TextInput')":0.021,"P\\Tests\\admin\\Unit\\Support\\Forms\\AttributeDataTest::__pest_evaluable__attribute_data_test__\u2192_can_extend_converters":0.021,"P\\Tests\\admin\\Unit\\Support\\RelationManagers\\ChannelRelationManagerTest::__pest_evaluable_it_can_render_relationship_manager":0.071}} \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index 3a2cc8e943..931eb8f5e6 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -14,10 +14,6 @@ tests/core/Feature tests/core/Unit - - tests/opayo/Feature - tests/opayo/Unit - tests/stripe/Unit @@ -29,9 +25,6 @@ tests/shipping/Feature tests/shipping/Unit - - packages/core/tests/Unit - From e32d2cca4f9d1e81cb23e9dd857fb1a69cbd11bb Mon Sep 17 00:00:00 2001 From: Lionel Guichard Date: Thu, 15 Feb 2024 00:46:12 +0100 Subject: [PATCH 06/12] Feature - Field translated text (#1505) This PR fix definitely the TranslatedText component for the MVP. It's a same UX approach that legacy version. Let's get a simple solution working and consider a better solution later. The issue related to #1425 --------- Co-authored-by: Alec Ritson Co-authored-by: Glenn Jacobs --- .../admin/resources/lang/en/fieldtypes.php | 1 + .../components/translated-text.blade.php | 65 ++++++++++--- .../Resources/AttributeGroupResource.php | 2 +- .../AttributesRelationManager.php | 6 +- .../Resources/ProductOptionResource.php | 5 +- .../ValuesRelationManager.php | 4 +- .../Filament/Resources/ProductResource.php | 3 +- .../ProductResource/Pages/ListProducts.php | 14 +-- .../Collections/CreateChildCollection.php | 4 +- .../Collections/CreateRootCollection.php | 20 +--- .../Traits/CreatesChildCollections.php | 18 +--- .../src/Support/FieldTypes/TranslatedText.php | 6 +- .../Forms/Components/TranslatedRichEditor.php | 15 +++ .../Forms/Components/TranslatedText.php | 97 ++++++++++++++++++- .../Forms/Components/TranslatedTextInput.php | 15 +++ .../Synthesizers/TranslatedTextSynth.php | 10 +- .../Collections/CreateChildCollection.php | 4 +- packages/core/src/Models/ProductOption.php | 18 ---- .../Pages/EditAttributeGroupTest.php | 13 ++- .../AttributesRelationManagerTest.php | 9 +- .../Pages/ManageCollectionChildrenTest.php | 4 +- .../ProductResource/ListProductsTest.php | 2 +- .../Widgets/CollectionTreeViewTest.php | 18 ++-- 23 files changed, 246 insertions(+), 107 deletions(-) create mode 100644 packages/admin/src/Support/Forms/Components/TranslatedRichEditor.php create mode 100644 packages/admin/src/Support/Forms/Components/TranslatedTextInput.php diff --git a/packages/admin/resources/lang/en/fieldtypes.php b/packages/admin/resources/lang/en/fieldtypes.php index 8cecb4b0b3..df36e57660 100644 --- a/packages/admin/resources/lang/en/fieldtypes.php +++ b/packages/admin/resources/lang/en/fieldtypes.php @@ -26,6 +26,7 @@ 'richtext' => [ 'label' => 'Rich Text', ], + 'locales' => 'Locales', ], ], 'toggle' => [ diff --git a/packages/admin/resources/views/forms/components/translated-text.blade.php b/packages/admin/resources/views/forms/components/translated-text.blade.php index cfc5a78c28..537849cfce 100644 --- a/packages/admin/resources/views/forms/components/translated-text.blade.php +++ b/packages/admin/resources/views/forms/components/translated-text.blade.php @@ -1,21 +1,54 @@ - + -
- @foreach ($getLanguages() as $language) - -
- - - -
+
+
+ @if ($getMoreLanguages()->count()) + + {{ Str::upper($getDefaultLanguage()->code) }} + + @endif + + {{ $getComponentByLanguage($getDefaultLanguage()) }} + +
+ @if ($getMoreLanguages()->count()) + @foreach ($getMoreLanguages() as $language) +
+ + {{ Str::upper($language->code) }} + + + {{ $getComponentByLanguage($language) }} + +
@endforeach + @endif +
+ + @if ($getMoreLanguages()->count()) +
+ + + + {{ __('lunarpanel::fieldtypes.translatedtext.form.locales') }} + + +
+ @endif - + \ No newline at end of file diff --git a/packages/admin/src/Filament/Resources/AttributeGroupResource.php b/packages/admin/src/Filament/Resources/AttributeGroupResource.php index c6f3e323c8..85d1a62d6f 100644 --- a/packages/admin/src/Filament/Resources/AttributeGroupResource.php +++ b/packages/admin/src/Filament/Resources/AttributeGroupResource.php @@ -72,7 +72,7 @@ protected static function getAttributableTypeFormComponent(): Component protected static function getNameFormComponent(): Component { - return \Lunar\Admin\Support\Forms\Components\TranslatedText::make('name') // TODO: we need a custom field type for this + return \Lunar\Admin\Support\Forms\Components\TranslatedText::make('name') ->label(__('lunarpanel::attributegroup.form.name.label')) ->required() ->maxLength(255) diff --git a/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php b/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php index 332703a358..09ca8a6beb 100644 --- a/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php +++ b/packages/admin/src/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManager.php @@ -11,6 +11,8 @@ use Illuminate\Support\Str; use Illuminate\Validation\Rules\Unique; use Lunar\Admin\Support\Facades\AttributeData; +use Lunar\Admin\Support\Forms\Components\TranslatedText; +use Lunar\Models\Language; class AttributesRelationManager extends RelationManager { @@ -27,7 +29,7 @@ public function form(Form $form): Form { return $form ->schema([ - Forms\Components\TextInput::make('name.en') // TODO: localise + TranslatedText::make('name') ->label( __('lunarpanel::attribute.form.name.label') ) @@ -38,7 +40,7 @@ public function form(Form $form): Form if ($operation !== 'create') { return; } - $set('handle', Str::slug($state)); + $set('handle', Str::slug($state[Language::getDefault()->code])); // TODO : create new global variable on LunarPanelManager with default language ? }), Forms\Components\TextInput::make('description.en') // TODO: localise ->label( diff --git a/packages/admin/src/Filament/Resources/ProductOptionResource.php b/packages/admin/src/Filament/Resources/ProductOptionResource.php index 871ee8e6b0..a231c84fac 100644 --- a/packages/admin/src/Filament/Resources/ProductOptionResource.php +++ b/packages/admin/src/Filament/Resources/ProductOptionResource.php @@ -9,6 +9,7 @@ use Filament\Tables\Table; use Lunar\Admin\Filament\Resources\ProductOptionResource\Pages; use Lunar\Admin\Filament\Resources\ProductOptionResource\RelationManagers; +use Lunar\Admin\Support\Forms\Components\TranslatedText; use Lunar\Admin\Support\Resources\BaseResource; use Lunar\Models\ProductOption; @@ -51,7 +52,7 @@ protected static function getMainFormComponents(): array protected static function getNameFormComponent(): Component { - return \Lunar\Admin\Support\Forms\Components\TranslatedText::make('name') // TODO: we need a custom field type for this + return TranslatedText::make('name') ->label(__('lunarpanel::productoption.form.name.label')) ->required() ->maxLength(255) @@ -60,7 +61,7 @@ protected static function getNameFormComponent(): Component protected static function getLabelFormComponent(): Component { - return \Lunar\Admin\Support\Forms\Components\TranslatedText::make('label') // TODO: we need a custom field type for this + return TranslatedText::make('label') ->label(__('lunarpanel::productoption.form.label.label')) ->required() ->maxLength(255) diff --git a/packages/admin/src/Filament/Resources/ProductOptionResource/RelationManagers/ValuesRelationManager.php b/packages/admin/src/Filament/Resources/ProductOptionResource/RelationManagers/ValuesRelationManager.php index 12e130a4e6..c4660de451 100644 --- a/packages/admin/src/Filament/Resources/ProductOptionResource/RelationManagers/ValuesRelationManager.php +++ b/packages/admin/src/Filament/Resources/ProductOptionResource/RelationManagers/ValuesRelationManager.php @@ -2,12 +2,12 @@ namespace Lunar\Admin\Filament\Resources\ProductOptionResource\RelationManagers; -use Filament\Forms; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; use Filament\Tables; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Model; +use Lunar\Admin\Support\Forms\Components\TranslatedText; use Lunar\Models\ProductOptionValue; class ValuesRelationManager extends RelationManager @@ -23,7 +23,7 @@ public function form(Form $form): Form { return $form ->schema([ - Forms\Components\TextInput::make('name.en') + TranslatedText::make('name') ->required() ->maxLength(255), ]); diff --git a/packages/admin/src/Filament/Resources/ProductResource.php b/packages/admin/src/Filament/Resources/ProductResource.php index 34c7cfd442..acd3e16f70 100644 --- a/packages/admin/src/Filament/Resources/ProductResource.php +++ b/packages/admin/src/Filament/Resources/ProductResource.php @@ -22,6 +22,7 @@ use Lunar\Admin\Filament\Widgets\Products\VariantSwitcherTable; use Lunar\Admin\Support\Forms\Components\Attributes; use Lunar\Admin\Support\Forms\Components\Tags as TagsComponent; +use Lunar\Admin\Support\Forms\Components\TranslatedText; use Lunar\Admin\Support\RelationManagers\ChannelRelationManager; use Lunar\Admin\Support\RelationManagers\MediaRelationManager; use Lunar\Admin\Support\RelationManagers\PriceRelationManager; @@ -169,7 +170,7 @@ public static function getBasePriceFormComponent(): Component public static function getBaseNameFormComponent(): Component { - return Forms\Components\TextInput::make('name') + return TranslatedText::make('name') ->label(__('lunarpanel::product.form.name.label'))->required(); } diff --git a/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php b/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php index e8f26219f3..9846d55f9d 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Pages/ListProducts.php @@ -12,10 +12,8 @@ use Lunar\Admin\Filament\Resources\ProductResource; use Lunar\Admin\Support\Pages\BaseListRecords; use Lunar\Facades\DB; -use Lunar\FieldTypes\TranslatedText; use Lunar\Models\Attribute; use Lunar\Models\Currency; -use Lunar\Models\Language; use Lunar\Models\Product; use Lunar\Models\TaxClass; @@ -52,25 +50,19 @@ public static function createActionFormInputs(): array public static function createRecord(array $data, string $model): Model { - $language = Language::getDefault(); $currency = Currency::getDefault(); $nameAttribute = Attribute::whereAttributeType($model) ->whereHandle('name') - ->first(); - - $name = $data['name']; - - if ($nameAttribute->type == TranslatedText::class) { - $name = [$language->code => $name]; - } + ->first() + ->type; DB::beginTransaction(); $product = $model::create([ 'status' => 'draft', 'product_type_id' => $data['product_type_id'], 'attribute_data' => [ - 'name' => new $nameAttribute->type($name), + 'name' => new $nameAttribute($data['name']), ], ]); $variant = $product->variants()->create([ diff --git a/packages/admin/src/Support/Actions/Collections/CreateChildCollection.php b/packages/admin/src/Support/Actions/Collections/CreateChildCollection.php index a003f7f6b2..a8020eac31 100644 --- a/packages/admin/src/Support/Actions/Collections/CreateChildCollection.php +++ b/packages/admin/src/Support/Actions/Collections/CreateChildCollection.php @@ -3,9 +3,9 @@ namespace Lunar\Admin\Support\Actions\Collections; use Filament\Actions\CreateAction; -use Filament\Forms\Components\TextInput; use Illuminate\Database\Eloquent\Model; use Lunar\Admin\Support\Actions\Traits\CreatesChildCollections; +use Lunar\Admin\Support\Forms\Components\TranslatedText; use Lunar\Models\Collection; class CreateChildCollection extends CreateAction @@ -25,7 +25,7 @@ public function setUp(): void }); $this->form([ - TextInput::make('name')->required(), + TranslatedText::make('name')->required(), ]); $this->label( diff --git a/packages/admin/src/Support/Actions/Collections/CreateRootCollection.php b/packages/admin/src/Support/Actions/Collections/CreateRootCollection.php index 74ac091a35..09c6b03623 100644 --- a/packages/admin/src/Support/Actions/Collections/CreateRootCollection.php +++ b/packages/admin/src/Support/Actions/Collections/CreateRootCollection.php @@ -3,13 +3,11 @@ namespace Lunar\Admin\Support\Actions\Collections; use Filament\Actions\CreateAction; -use Filament\Forms\Components\TextInput; use Filament\Forms\Form; +use Lunar\Admin\Support\Forms\Components\TranslatedText; use Lunar\Facades\DB; -use Lunar\FieldTypes\TranslatedText; use Lunar\Models\Attribute; use Lunar\Models\Collection; -use Lunar\Models\Language; class CreateRootCollection extends CreateAction { @@ -23,22 +21,12 @@ public function setUp(): void DB::beginTransaction(); $record = $this->process(function (array $data) { - $attribute = Attribute::whereHandle('name')->whereAttributeType(Collection::class)->first(); - $nameValue = $data['name']; - - $fieldType = $attribute->type; - - if ($fieldType == TranslatedText::class) { - $language = Language::getDefault(); - $nameValue = collect([ - $language->code => $data['name'], - ]); - } + $attribute = Attribute::whereHandle('name')->whereAttributeType(Collection::class)->first()->type; return Collection::create([ 'collection_group_id' => $data['collection_group_id'], 'attribute_data' => [ - 'name' => new $fieldType($nameValue), + 'name' => new $attribute($data['name']), ], ]); }); @@ -68,7 +56,7 @@ public function setUp(): void }); $this->form([ - TextInput::make('name')->required(), + TranslatedText::make('name')->required(), ]); $this->label( diff --git a/packages/admin/src/Support/Actions/Traits/CreatesChildCollections.php b/packages/admin/src/Support/Actions/Traits/CreatesChildCollections.php index 9f302a47aa..2d8153bbc3 100644 --- a/packages/admin/src/Support/Actions/Traits/CreatesChildCollections.php +++ b/packages/admin/src/Support/Actions/Traits/CreatesChildCollections.php @@ -3,33 +3,21 @@ namespace Lunar\Admin\Support\Actions\Traits; use Lunar\Facades\DB; -use Lunar\FieldTypes\TranslatedText; use Lunar\Models\Attribute; use Lunar\Models\Collection; -use Lunar\Models\Language; trait CreatesChildCollections { - public function createChildCollection(Collection $parent, string $name) + public function createChildCollection(Collection $parent, array $name) { DB::beginTransaction(); - $attribute = Attribute::whereHandle('name')->whereAttributeType(Collection::class)->first(); - - $nameValue = $name; - $fieldType = $attribute->type; - - if ($fieldType == TranslatedText::class) { - $language = Language::getDefault(); - $nameValue = collect([ - $language->code => $name, - ]); - } + $attribute = Attribute::whereHandle('name')->whereAttributeType(Collection::class)->first()->type; $parent->appendNode(Collection::create([ 'collection_group_id' => $parent->collection_group_id, 'attribute_data' => [ - 'name' => new $fieldType($nameValue), + 'name' => new $attribute($name), ], ])); diff --git a/packages/admin/src/Support/FieldTypes/TranslatedText.php b/packages/admin/src/Support/FieldTypes/TranslatedText.php index 5dc3465332..04bbc85966 100644 --- a/packages/admin/src/Support/FieldTypes/TranslatedText.php +++ b/packages/admin/src/Support/FieldTypes/TranslatedText.php @@ -3,7 +3,7 @@ namespace Lunar\Admin\Support\FieldTypes; use Filament\Forms\Components\Component; -use Lunar\Admin\Support\Forms\Components\TranslatedText as TranslatedTextInput; +use Lunar\Admin\Support\Forms\Components\TranslatedText as TranslatedTextComponent; use Lunar\Admin\Support\Synthesizers\TranslatedTextSynth; use Lunar\Models\Attribute; @@ -18,7 +18,9 @@ public static function getConfigurationFields(): array public static function getFilamentComponent(Attribute $attribute): Component { - return TranslatedTextInput::make($attribute->handle) + return TranslatedTextComponent::make($attribute->handle) + ->optionRichtext((bool) $attribute->configuration->get('richtext')) + ->required((bool) $attribute->configuration->get('required')) ->helperText($attribute->translate('description')); } } diff --git a/packages/admin/src/Support/Forms/Components/TranslatedRichEditor.php b/packages/admin/src/Support/Forms/Components/TranslatedRichEditor.php new file mode 100644 index 0000000000..f780804e57 --- /dev/null +++ b/packages/admin/src/Support/Forms/Components/TranslatedRichEditor.php @@ -0,0 +1,15 @@ +hiddenLabel(); + } +} diff --git a/packages/admin/src/Support/Forms/Components/TranslatedText.php b/packages/admin/src/Support/Forms/Components/TranslatedText.php index ae7712191a..8526e43888 100644 --- a/packages/admin/src/Support/Forms/Components/TranslatedText.php +++ b/packages/admin/src/Support/Forms/Components/TranslatedText.php @@ -2,16 +2,109 @@ namespace Lunar\Admin\Support\Forms\Components; +use Filament\Forms\ComponentContainer; +use Filament\Forms\Components\Component; use Filament\Forms\Components\TextInput; +use Illuminate\Support\Collection; use Lunar\Models\Language; class TranslatedText extends TextInput { protected string $view = 'lunarpanel::forms.components.translated-text'; + public bool $expanded = false; + + public bool $optionRichtext = false; + + public Language $defaultLanguage; + + public Collection $components; + + public Collection $languages; + + public function setUp(): void + { + parent::setUp(); + + $this->languages = Language::orderBy('default', 'desc')->get(); + + $this->default(static function (TranslatedText $component): array { + return $component->getLanguageDefaults(); + }); + } + + public function prepareChildComponents() + { + $this->components = collect( + $this->getLanguages()->map(fn ($lang) => $this->getOptionRichtext() ? + TranslatedRichEditor::make($lang->code)->statePath($lang->code) : + TranslatedTextInput::make($lang->code)->statePath($lang->code) + ) + ); + } + + public function prepareTranslateLocaleComponent(Component $component, string $locale) + { + $localeComponent = clone $component; + + $localeComponent->name($component->getName()); + + $localeComponent->statePath($localeComponent->getName()); + + $localeComponent->required($this->isRequired && $locale == $this->getDefaultLanguage()->code); + + return $localeComponent; + } + + public function getComponentByLanguage(Language $language): ComponentContainer + { + $this->prepareChildComponents(); + + return ComponentContainer::make($this->getLivewire()) + ->parentComponent($this) + ->components( + $this->components + ->filter(fn ($component): bool => $component->getName() == $language->code) + ->map(fn ($component) => $this->prepareTranslateLocaleComponent($component, $language->code)) + ->all() + ) + ->getClone(); + } + + public function optionRichtext(bool $optionRichtext): static + { + $this->optionRichtext = $optionRichtext; + + return $this; + } + + public function getOptionRichtext(): bool + { + return $this->optionRichtext; + } + + public function getExpanded() + { + return $this->expanded; + } + + public function getDefaultLanguage() + { + return $this->languages->first(fn ($lang) => $lang->default); + } + + public function getMoreLanguages() + { + return $this->languages->filter(fn ($lang) => ! $lang->default); + } + + public function getLanguageDefaults(): array + { + return $this->getLanguages()->mapWithKeys(fn ($language) => [$language->code => ''])->toArray(); + } + public function getLanguages() { - // TODO: blink + sort - return Language::get(); + return $this->languages; } } diff --git a/packages/admin/src/Support/Forms/Components/TranslatedTextInput.php b/packages/admin/src/Support/Forms/Components/TranslatedTextInput.php new file mode 100644 index 0000000000..5ad233a690 --- /dev/null +++ b/packages/admin/src/Support/Forms/Components/TranslatedTextInput.php @@ -0,0 +1,15 @@ +hiddenLabel(); + } +} diff --git a/packages/admin/src/Support/Synthesizers/TranslatedTextSynth.php b/packages/admin/src/Support/Synthesizers/TranslatedTextSynth.php index 4066677c48..e1f5261478 100644 --- a/packages/admin/src/Support/Synthesizers/TranslatedTextSynth.php +++ b/packages/admin/src/Support/Synthesizers/TranslatedTextSynth.php @@ -2,7 +2,9 @@ namespace Lunar\Admin\Support\Synthesizers; +use Lunar\FieldTypes\Text; use Lunar\FieldTypes\TranslatedText; +use Lunar\Models\Language; class TranslatedTextSynth extends AbstractFieldSynth { @@ -12,7 +14,13 @@ class TranslatedTextSynth extends AbstractFieldSynth public function dehydrate($target) { - return [$target->getValue()->toArray(), []]; + $languages = Language::orderBy('default', 'desc')->get(); + + return [ + $languages->mapWithKeys(fn ($language) => [$language->code => new Text((string) $target->getValue()->get($language->code))] + )->toArray(), + [], + ]; } public function hydrate($value) diff --git a/packages/admin/src/Support/Tables/Actions/Collections/CreateChildCollection.php b/packages/admin/src/Support/Tables/Actions/Collections/CreateChildCollection.php index e1fc7b1a89..d4e3715b21 100644 --- a/packages/admin/src/Support/Tables/Actions/Collections/CreateChildCollection.php +++ b/packages/admin/src/Support/Tables/Actions/Collections/CreateChildCollection.php @@ -2,10 +2,10 @@ namespace Lunar\Admin\Support\Tables\Actions\Collections; -use Filament\Forms\Components\TextInput; use Filament\Tables\Actions\CreateAction; use Filament\Tables\Table; use Lunar\Admin\Support\Actions\Traits\CreatesChildCollections; +use Lunar\Admin\Support\Forms\Components\TranslatedText; class CreateChildCollection extends CreateAction { @@ -25,7 +25,7 @@ public function setUp(): void }); $this->form([ - TextInput::make('name')->required(), + TranslatedText::make('name')->required(), ]); $this->createAnother(false); diff --git a/packages/core/src/Models/ProductOption.php b/packages/core/src/Models/ProductOption.php index b10d97c13e..68c7bc98c1 100644 --- a/packages/core/src/Models/ProductOption.php +++ b/packages/core/src/Models/ProductOption.php @@ -52,24 +52,6 @@ protected static function newFactory(): ProductOptionFactory return ProductOptionFactory::new(); } - public function getNameAttribute(string $value): mixed - { - return json_decode($value); - } - - protected function setNameAttribute(mixed $value): void - { - $this->attributes['name'] = json_encode($value); - } - - protected function label(): Attribute - { - return Attribute::make( - get: fn (string $value) => json_decode($value), - set: fn ($value) => json_encode($value), - ); - } - /** * Define which attributes should be * protected from mass assignment. diff --git a/tests/admin/Feature/Filament/Resources/AttributeGroupResource/Pages/EditAttributeGroupTest.php b/tests/admin/Feature/Filament/Resources/AttributeGroupResource/Pages/EditAttributeGroupTest.php index 09d48b1dab..dd13fc882e 100644 --- a/tests/admin/Feature/Filament/Resources/AttributeGroupResource/Pages/EditAttributeGroupTest.php +++ b/tests/admin/Feature/Filament/Resources/AttributeGroupResource/Pages/EditAttributeGroupTest.php @@ -9,12 +9,23 @@ ->group('resource.attribute-group'); it('can render attribute group edit page', function () { + + \Lunar\Models\Language::factory()->create([ + 'default' => true, + ]); + $this->asStaff(admin: true) ->get(AttributeGroupResource::getUrl('edit', ['record' => AttributeGroup::factory()->create()])) ->assertSuccessful(); }); it('can retrieve attribute group data', function () { + + $lang = \Lunar\Models\Language::factory()->create([ + 'default' => true, + 'code' => 'en', + ]); + $this->asStaff(); $attributeGroup = AttributeGroup::factory()->create(); @@ -23,6 +34,6 @@ 'record' => $attributeGroup->getRouteKey(), ]) ->assertFormSet([ - 'name.en' => $attributeGroup->translate('name'), // TODO: Needs to be translated + 'name.'.$lang->code => $attributeGroup->translate('name', $lang->code), ]); }); diff --git a/tests/admin/Feature/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManagerTest.php b/tests/admin/Feature/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManagerTest.php index be134274d8..1dd7252222 100644 --- a/tests/admin/Feature/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManagerTest.php +++ b/tests/admin/Feature/Filament/Resources/AttributeGroupResource/RelationManagers/AttributesRelationManagerTest.php @@ -9,6 +9,7 @@ ->group('resource.attribute-group'); it('can render relation manager', function () { + $this->asStaff(); $attributeGroup = AttributeGroup::factory()->create(); @@ -20,6 +21,12 @@ }); it('can create attributes', function ($type, $configuration = [], $expectedData = []) { + + $lang = \Lunar\Models\Language::factory()->create([ + 'default' => true, + 'code' => 'en', + ]); + $this->asStaff(); $attributeGroup = AttributeGroup::factory()->create(); @@ -28,7 +35,7 @@ 'ownerRecord' => $attributeGroup, 'pageClass' => EditAttributeGroup::class, ])->callTableAction(\Filament\Actions\CreateAction::class, data: [ - 'name.en' => 'Foobar', // TODO: Use translation + 'name.'.$lang->code => 'Foobar', 'type' => $type, 'handle' => 'foobar', 'configuration' => $configuration, diff --git a/tests/admin/Feature/Filament/Resources/CollectionResources/Pages/ManageCollectionChildrenTest.php b/tests/admin/Feature/Filament/Resources/CollectionResources/Pages/ManageCollectionChildrenTest.php index 20b5162deb..5388347bff 100644 --- a/tests/admin/Feature/Filament/Resources/CollectionResources/Pages/ManageCollectionChildrenTest.php +++ b/tests/admin/Feature/Filament/Resources/CollectionResources/Pages/ManageCollectionChildrenTest.php @@ -20,7 +20,7 @@ }); it('can create child categories', function () { - \Lunar\Models\Language::factory()->create([ + $language = \Lunar\Models\Language::factory()->create([ 'default' => true, ]); @@ -45,7 +45,7 @@ \Livewire\Livewire::test(ManageCollectionChildren::class, [ 'record' => $record->getKey(), ])->callTableAction('createChildCollection', data: [ - 'name' => 'Test Child Category', + 'name' => [$language->code => 'Test Child Category'], ])->assertHasNoErrors(); expect($record->children()->count())->toBe(1); diff --git a/tests/admin/Feature/Filament/Resources/ProductResource/ListProductsTest.php b/tests/admin/Feature/Filament/Resources/ProductResource/ListProductsTest.php index bc0ee2fc21..04f55ccc58 100644 --- a/tests/admin/Feature/Filament/Resources/ProductResource/ListProductsTest.php +++ b/tests/admin/Feature/Filament/Resources/ProductResource/ListProductsTest.php @@ -34,7 +34,7 @@ \Livewire\Livewire::test(ProductResource\Pages\ListProducts::class) ->callAction('create', data: [ - 'name' => 'Foo Bar', + 'name' => [$language->code => 'Foo Bar'], 'base_price' => 10.99, 'sku' => 'ABCABCAB', 'product_type_id' => $productType->id, diff --git a/tests/admin/Feature/Filament/Resources/ProductResource/Widgets/CollectionTreeViewTest.php b/tests/admin/Feature/Filament/Resources/ProductResource/Widgets/CollectionTreeViewTest.php index c464c64956..e85a76ddf2 100644 --- a/tests/admin/Feature/Filament/Resources/ProductResource/Widgets/CollectionTreeViewTest.php +++ b/tests/admin/Feature/Filament/Resources/ProductResource/Widgets/CollectionTreeViewTest.php @@ -36,18 +36,18 @@ \Lunar\Models\Attribute::factory()->create([ 'handle' => 'name', - 'type' => \Lunar\FieldTypes\Text::class, + 'type' => \Lunar\FieldTypes\TranslatedText::class, 'attribute_type' => \Lunar\Models\Collection::class, ]); - \Lunar\Models\Language::factory()->create([ + $language = \Lunar\Models\Language::factory()->create([ 'default' => true, ]); \Livewire\Livewire::test(CollectionTreeView::class, [ 'record' => $group, ])->callAction('createRootCollection', [ - 'name' => 'Foo Bar', + 'name' => [$language->code => 'Foo Bar'], ])->assertSet('nodes.0.name', 'Foo Bar') ->assertHasNoErrors(); }); @@ -86,11 +86,11 @@ \Lunar\Models\Attribute::factory()->create([ 'handle' => 'name', - 'type' => \Lunar\FieldTypes\Text::class, + 'type' => \Lunar\FieldTypes\TranslatedText::class, 'attribute_type' => \Lunar\Models\Collection::class, ]); - \Lunar\Models\Language::factory()->create([ + $language = \Lunar\Models\Language::factory()->create([ 'default' => true, ]); @@ -107,7 +107,7 @@ \Livewire\Livewire::test(CollectionTreeView::class, [ 'record' => $group, ])->callAction('addChildCollection', [ - 'name' => 'Sub Collection', + 'name' => [$language->code => 'Sub Collection'], ], ['id' => $collection->id]) ->assertCount('nodes', 1) ->assertSet('nodes.0.children.0.id', $child->id) @@ -122,11 +122,11 @@ \Lunar\Models\Attribute::factory()->create([ 'handle' => 'name', - 'type' => \Lunar\FieldTypes\Text::class, + 'type' => \Lunar\FieldTypes\TranslatedText::class, 'attribute_type' => \Lunar\Models\Collection::class, ]); - \Lunar\Models\Language::factory()->create([ + $language = \Lunar\Models\Language::factory()->create([ 'default' => true, ]); @@ -137,7 +137,7 @@ \Livewire\Livewire::test(CollectionTreeView::class, [ 'record' => $group, ])->callAction('addChildCollection', [ - 'name' => 'Sub Collection', + 'name' => [$language->code => 'Sub Collection'], ], ['id' => $collection->id]) ->assertSet('nodes.0.children.0.name', 'Sub Collection'); }); From 63b65a1458b775c69af22ee6819842a62965fb3b Mon Sep 17 00:00:00 2001 From: glennjacobs Date: Wed, 14 Feb 2024 23:48:31 +0000 Subject: [PATCH 07/12] chore: fix code style --- packages/core/src/Models/ProductOption.php | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/Models/ProductOption.php b/packages/core/src/Models/ProductOption.php index 68c7bc98c1..581c8a54b7 100644 --- a/packages/core/src/Models/ProductOption.php +++ b/packages/core/src/Models/ProductOption.php @@ -4,7 +4,6 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\AsCollection; -use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; From 80844de0573d7eaf2852642c5c1a66247c11321b Mon Sep 17 00:00:00 2001 From: Lionel Guichard Date: Thu, 15 Feb 2024 00:54:56 +0100 Subject: [PATCH 08/12] Chore - Update larastan/larastan (#1558) Package nunomaduro/larastan is abandoned, you should avoid using it. Use larastan/larastan instead. Co-authored-by: Glenn Jacobs --- composer.json | 2 +- phpstan.neon.dist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 034067d1d2..5a715057ef 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "require-dev": { "laravel/pint": "1.13.1", "mockery/mockery": "^1.4.4", - "nunomaduro/larastan": "^2.0", + "larastan/larastan": "^2.9", "orchestra/testbench": "^8.0", "pestphp/pest": "^2.0", "pestphp/pest-plugin-laravel": "^2.0", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 91345b915d..3cdecfd240 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,5 +1,5 @@ includes: - - ./vendor/nunomaduro/larastan/extension.neon + - ./vendor/larastan/larastan/extension.neon parameters: level: 0 paths: From 02d8e89eb88cd35853338184403120533979366a Mon Sep 17 00:00:00 2001 From: Lionel Guichard Date: Thu, 15 Feb 2024 00:58:50 +0100 Subject: [PATCH 09/12] Feature - Brand urls and tweaks (#1541) This PR add ability to update brand's urls. I fixed unique rules and move the new class ManageUrlsRelatedRecords to avoid duplicate code. --------- Co-authored-by: Alec Ritson Co-authored-by: Glenn Jacobs --- .../src/Filament/Resources/BrandResource.php | 2 + .../BrandResource/Pages/ManageBrandUrls.php | 14 +++ .../Pages/ManageCollectionUrls.php | 103 +--------------- .../Pages/ManageProductUrls.php | 101 +--------------- .../Pages/ManageUrlsRelatedRecords.php | 110 ++++++++++++++++++ 5 files changed, 133 insertions(+), 197 deletions(-) create mode 100644 packages/admin/src/Filament/Resources/BrandResource/Pages/ManageBrandUrls.php create mode 100644 packages/admin/src/Support/Resources/Pages/ManageUrlsRelatedRecords.php diff --git a/packages/admin/src/Filament/Resources/BrandResource.php b/packages/admin/src/Filament/Resources/BrandResource.php index 90e1f326d2..601dd82355 100644 --- a/packages/admin/src/Filament/Resources/BrandResource.php +++ b/packages/admin/src/Filament/Resources/BrandResource.php @@ -55,6 +55,7 @@ public static function getRecordSubNavigation(Page $page): array return $page->generateNavigationItems([ Pages\EditBrand::class, Pages\ManageBrandMedia::class, + Pages\ManageBrandUrls::class, ]); } @@ -143,6 +144,7 @@ public static function getPages(): array 'create' => Pages\CreateBrand::route('/create'), 'edit' => Pages\EditBrand::route('/{record}/edit'), 'media' => Pages\ManageBrandMedia::route('/{record}/media'), + 'urls' => Pages\ManageBrandUrls::route('/{record}/urls'), ]; } diff --git a/packages/admin/src/Filament/Resources/BrandResource/Pages/ManageBrandUrls.php b/packages/admin/src/Filament/Resources/BrandResource/Pages/ManageBrandUrls.php new file mode 100644 index 0000000000..adf975b4d5 --- /dev/null +++ b/packages/admin/src/Filament/Resources/BrandResource/Pages/ManageBrandUrls.php @@ -0,0 +1,14 @@ +schema([ - Forms\Components\Toggle::make('default')->label( - __('lunarpanel::relationmanagers.urls.form.default.label') - )->columnSpan(2), - Forms\Components\Group::make([ - Forms\Components\TextInput::make('slug') - ->label( - __('lunarpanel::relationmanagers.urls.table.slug.label') - ) - ->required() - ->dehydrateStateUsing( - fn ($state) => Str::slug($state) - )->unique( - ignoreRecord: true, - modifyRuleUsing: function (Unique $rule) { - return $rule->where('element_type', Product::class); - } - ) - ->maxLength(255) - ->required(), - Forms\Components\Select::make('language_id')->label( - __('lunarpanel::relationmanagers.urls.table.language.label') - )->relationship(name: 'language', titleAttribute: 'name')->required(), - ])->columns(2)->columnSpan(2), - ]); - } - - public function table(Table $table): Table - { - return $table - ->recordTitleAttribute('name') - ->modifyQueryUsing(fn (Builder $query) => $query->orderBy('language_id')->orderBy('default', 'desc')) - ->columns([ - Tables\Columns\TextColumn::make('slug')->label( - __('lunarpanel::relationmanagers.urls.table.slug.label') - ), - Tables\Columns\TextColumn::make('language.name')->label( - __('lunarpanel::relationmanagers.urls.table.language.label') - ), - Tables\Columns\IconColumn::make('default') - ->label( - __('lunarpanel::relationmanagers.urls.table.default.label') - ) - ->boolean(), - ]) - ->filters([ - Tables\Filters\SelectFilter::make('language_id') - ->label( - __('lunarpanel::relationmanagers.urls.filters.language_id.label') - ) - ->relationship('language', 'name'), - ]) - ->headerActions([ - Tables\Actions\CreateAction::make()->label( - __('lunarpanel::relationmanagers.urls.actions.create.label') - ), - ]) - ->actions([ - Tables\Actions\EditAction::make(), - Tables\Actions\DeleteAction::make(), - ]) - ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make(), - ]), - ]); - } + protected static string $model = Collection::class; } diff --git a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductUrls.php b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductUrls.php index 530acb56b8..80d568869c 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductUrls.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductUrls.php @@ -2,108 +2,13 @@ namespace Lunar\Admin\Filament\Resources\ProductResource\Pages; -use Filament\Forms; -use Filament\Forms\Form; -use Filament\Resources\Pages\ManageRelatedRecords; -use Filament\Support\Facades\FilamentIcon; -use Filament\Tables; -use Filament\Tables\Table; -use Illuminate\Contracts\Support\Htmlable; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Str; -use Illuminate\Validation\Rules\Unique; use Lunar\Admin\Filament\Resources\ProductResource; +use Lunar\Admin\Support\Resources\Pages\ManageUrlsRelatedRecords; use Lunar\Models\Product; -class ManageProductUrls extends ManageRelatedRecords +class ManageProductUrls extends ManageUrlsRelatedRecords { protected static string $resource = ProductResource::class; - protected static string $relationship = 'urls'; - - public function getTitle(): string|Htmlable - { - return __('lunarpanel::relationmanagers.urls.title_plural'); - } - - public static function getNavigationIcon(): ?string - { - return FilamentIcon::resolve('lunar::urls'); - } - - public static function getNavigationLabel(): string - { - return __('lunarpanel::relationmanagers.urls.title_plural'); - } - - public function form(Form $form): Form - { - return $form - ->schema([ - Forms\Components\Toggle::make('default')->label( - __('lunarpanel::relationmanagers.urls.form.default.label') - )->columnSpan(2), - Forms\Components\Group::make([ - Forms\Components\TextInput::make('slug') - ->label( - __('lunarpanel::relationmanagers.urls.table.slug.label') - ) - ->required() - ->dehydrateStateUsing( - fn ($state) => Str::slug($state) - )->unique( - ignoreRecord: true, - modifyRuleUsing: function (Unique $rule) { - return $rule->where('element_type', Product::class); - } - ) - ->maxLength(255) - ->required(), - Forms\Components\Select::make('language_id')->label( - __('lunarpanel::relationmanagers.urls.table.language.label') - )->relationship(name: 'language', titleAttribute: 'name')->required(), - ])->columns(2)->columnSpan(2), - ]); - } - - public function table(Table $table): Table - { - return $table - ->recordTitleAttribute('name') - ->modifyQueryUsing(fn (Builder $query) => $query->orderBy('language_id')->orderBy('default', 'desc')) - ->columns([ - Tables\Columns\TextColumn::make('slug')->label( - __('lunarpanel::relationmanagers.urls.table.slug.label') - ), - Tables\Columns\TextColumn::make('language.name')->label( - __('lunarpanel::relationmanagers.urls.table.language.label') - ), - Tables\Columns\IconColumn::make('default') - ->label( - __('lunarpanel::relationmanagers.urls.table.default.label') - ) - ->boolean(), - ]) - ->filters([ - Tables\Filters\SelectFilter::make('language_id') - ->label( - __('lunarpanel::relationmanagers.urls.filters.language_id.label') - ) - ->relationship('language', 'name'), - ]) - ->headerActions([ - Tables\Actions\CreateAction::make()->label( - __('lunarpanel::relationmanagers.urls.actions.create.label') - ), - ]) - ->actions([ - Tables\Actions\EditAction::make(), - Tables\Actions\DeleteAction::make(), - ]) - ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make(), - ]), - ]); - } + protected static string $model = Product::class; } diff --git a/packages/admin/src/Support/Resources/Pages/ManageUrlsRelatedRecords.php b/packages/admin/src/Support/Resources/Pages/ManageUrlsRelatedRecords.php new file mode 100644 index 0000000000..a8cca3f7ac --- /dev/null +++ b/packages/admin/src/Support/Resources/Pages/ManageUrlsRelatedRecords.php @@ -0,0 +1,110 @@ +schema([ + Forms\Components\Toggle::make('default')->label( + __('lunarpanel::relationmanagers.urls.form.default.label') + )->columnSpan(2), + Forms\Components\Group::make([ + Forms\Components\TextInput::make('slug') + ->label( + __('lunarpanel::relationmanagers.urls.table.slug.label') + ) + ->required() + ->dehydrateStateUsing( + fn ($state) => Str::slug($state) + )->unique( + ignoreRecord: true, + modifyRuleUsing: function (Unique $rule, callable $get) { + return $rule + ->where('element_type', static::$model) + ->where('language_id', $get('language_id')); + } + ) + ->maxLength(255) + ->required(), + Forms\Components\Select::make('language_id')->label( + __('lunarpanel::relationmanagers.urls.table.language.label') + )->relationship(name: 'language', titleAttribute: 'name')->required()->reactive(), + ])->columns(2)->columnSpan(2), + ]); + } + + public function table(Table $table): Table + { + return $table + ->recordTitleAttribute('name') + ->modifyQueryUsing(fn (Builder $query) => $query->orderBy('language_id')->orderBy('default', 'desc')) + ->columns([ + Tables\Columns\TextColumn::make('slug')->label( + __('lunarpanel::relationmanagers.urls.table.slug.label') + ), + Tables\Columns\TextColumn::make('language.name')->label( + __('lunarpanel::relationmanagers.urls.table.language.label') + ), + Tables\Columns\IconColumn::make('default') + ->label( + __('lunarpanel::relationmanagers.urls.table.default.label') + ) + ->boolean(), + ]) + ->filters([ + Tables\Filters\SelectFilter::make('language_id') + ->label( + __('lunarpanel::relationmanagers.urls.filters.language_id.label') + ) + ->relationship('language', 'name'), + ]) + ->headerActions([ + Tables\Actions\CreateAction::make()->label( + __('lunarpanel::relationmanagers.urls.actions.create.label') + ), + ]) + ->actions([ + Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } +} From 1366268134624fdd68f796b64321ef342bba5c9b Mon Sep 17 00:00:00 2001 From: Lionel Guichard Date: Thu, 15 Feb 2024 01:07:21 +0100 Subject: [PATCH 10/12] Feature - Prevent delete action on resources with childs (#1532) Co-authored-by: Alec Ritson Co-authored-by: Glenn Jacobs --- packages/admin/resources/lang/en/attributegroup.php | 7 +++++++ packages/admin/resources/lang/en/brand.php | 7 +++++++ packages/admin/resources/lang/en/collectiongroup.php | 7 +++++++ packages/admin/resources/lang/en/customergroup.php | 7 +++++++ packages/admin/resources/lang/en/producttype.php | 8 ++++++++ .../Pages/EditAttributeGroup.php | 12 +++++++++++- .../Resources/BrandResource/Pages/EditBrand.php | 12 +++++++++++- .../Pages/EditCollectionGroup.php | 12 +++++++++++- .../Pages/EditCustomerGroup.php | 12 +++++++++++- .../ProductTypeResource/Pages/EditProductType.php | 12 +++++++++++- 10 files changed, 91 insertions(+), 5 deletions(-) diff --git a/packages/admin/resources/lang/en/attributegroup.php b/packages/admin/resources/lang/en/attributegroup.php index 0e690217cb..cccb3c5550 100644 --- a/packages/admin/resources/lang/en/attributegroup.php +++ b/packages/admin/resources/lang/en/attributegroup.php @@ -36,4 +36,11 @@ ], ], + 'action' => [ + 'delete' => [ + 'notification' => [ + 'error_protected' => 'This attribute group can not be deleted as there are attributes associated.', + ], + ], + ], ]; diff --git a/packages/admin/resources/lang/en/brand.php b/packages/admin/resources/lang/en/brand.php index 728229b599..500ec75fb4 100644 --- a/packages/admin/resources/lang/en/brand.php +++ b/packages/admin/resources/lang/en/brand.php @@ -21,4 +21,11 @@ ], ], + 'action' => [ + 'delete' => [ + 'notification' => [ + 'error_protected' => 'This brand can not be deleted as there are products associated.', + ], + ], + ], ]; diff --git a/packages/admin/resources/lang/en/collectiongroup.php b/packages/admin/resources/lang/en/collectiongroup.php index 23f1773eb1..117086c97e 100644 --- a/packages/admin/resources/lang/en/collectiongroup.php +++ b/packages/admin/resources/lang/en/collectiongroup.php @@ -27,4 +27,11 @@ ], ], + 'action' => [ + 'delete' => [ + 'notification' => [ + 'error_protected' => 'This collection group can not be deleted as there are collections associated.', + ], + ], + ], ]; diff --git a/packages/admin/resources/lang/en/customergroup.php b/packages/admin/resources/lang/en/customergroup.php index 76be6ea632..0b5ad1ff10 100644 --- a/packages/admin/resources/lang/en/customergroup.php +++ b/packages/admin/resources/lang/en/customergroup.php @@ -30,4 +30,11 @@ ], ], + 'action' => [ + 'delete' => [ + 'notification' => [ + 'error_protected' => 'This customer group can not be deleted as there are customers associated.', + ], + ], + ], ]; diff --git a/packages/admin/resources/lang/en/producttype.php b/packages/admin/resources/lang/en/producttype.php index bad9b06a04..76dbaaf483 100644 --- a/packages/admin/resources/lang/en/producttype.php +++ b/packages/admin/resources/lang/en/producttype.php @@ -41,4 +41,12 @@ 'no_attributes' => 'There are no attributes available.', ], + 'action' => [ + 'delete' => [ + 'notification' => [ + 'error_protected' => 'This product type can not be deleted as there are products associated.', + ], + ], + ], + ]; diff --git a/packages/admin/src/Filament/Resources/AttributeGroupResource/Pages/EditAttributeGroup.php b/packages/admin/src/Filament/Resources/AttributeGroupResource/Pages/EditAttributeGroup.php index 38dbb2639a..e2f2ac6fb4 100644 --- a/packages/admin/src/Filament/Resources/AttributeGroupResource/Pages/EditAttributeGroup.php +++ b/packages/admin/src/Filament/Resources/AttributeGroupResource/Pages/EditAttributeGroup.php @@ -3,6 +3,7 @@ namespace Lunar\Admin\Filament\Resources\AttributeGroupResource\Pages; use Filament\Actions; +use Filament\Notifications\Notification; use Lunar\Admin\Filament\Resources\AttributeGroupResource; use Lunar\Admin\Support\Pages\BaseEditRecord; @@ -13,7 +14,16 @@ class EditAttributeGroup extends BaseEditRecord protected function getDefaultHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->before(function ($record, Actions\DeleteAction $action) { + if ($record->attributes->count() > 0) { + Notification::make() + ->warning() + ->body(__('lunarpanel::attributegroup.action.delete.notification.error_protected')) + ->send(); + $action->cancel(); + } + }), ]; } } diff --git a/packages/admin/src/Filament/Resources/BrandResource/Pages/EditBrand.php b/packages/admin/src/Filament/Resources/BrandResource/Pages/EditBrand.php index 686829ca4e..890aa19725 100644 --- a/packages/admin/src/Filament/Resources/BrandResource/Pages/EditBrand.php +++ b/packages/admin/src/Filament/Resources/BrandResource/Pages/EditBrand.php @@ -3,6 +3,7 @@ namespace Lunar\Admin\Filament\Resources\BrandResource\Pages; use Filament\Actions; +use Filament\Notifications\Notification; use Lunar\Admin\Filament\Resources\BrandResource; use Lunar\Admin\Support\Pages\BaseEditRecord; @@ -13,7 +14,16 @@ class EditBrand extends BaseEditRecord protected function getDefaultHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->before(function ($record, Actions\DeleteAction $action) { + if ($record->products->count() > 0) { + Notification::make() + ->warning() + ->body(__('lunarpanel::brand.action.delete.notification.error_protected')) + ->send(); + $action->cancel(); + } + }), ]; } } diff --git a/packages/admin/src/Filament/Resources/CollectionGroupResource/Pages/EditCollectionGroup.php b/packages/admin/src/Filament/Resources/CollectionGroupResource/Pages/EditCollectionGroup.php index d0e2a25610..06d518d1a2 100644 --- a/packages/admin/src/Filament/Resources/CollectionGroupResource/Pages/EditCollectionGroup.php +++ b/packages/admin/src/Filament/Resources/CollectionGroupResource/Pages/EditCollectionGroup.php @@ -3,6 +3,7 @@ namespace Lunar\Admin\Filament\Resources\CollectionGroupResource\Pages; use Filament\Actions; +use Filament\Notifications\Notification; use Filament\Resources\Pages\EditRecord; use Lunar\Admin\Filament\Resources\CollectionGroupResource; use Lunar\Admin\Filament\Resources\CollectionGroupResource\Widgets; @@ -14,7 +15,16 @@ class EditCollectionGroup extends EditRecord protected function getHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->before(function ($record, Actions\DeleteAction $action) { + if ($record->collections->count() > 0) { + Notification::make() + ->warning() + ->body(__('lunarpanel::collectiongroup.action.delete.notification.error_protected')) + ->send(); + $action->cancel(); + } + }), ]; } diff --git a/packages/admin/src/Filament/Resources/CustomerGroupResource/Pages/EditCustomerGroup.php b/packages/admin/src/Filament/Resources/CustomerGroupResource/Pages/EditCustomerGroup.php index 92e8c688ef..b84019e8db 100644 --- a/packages/admin/src/Filament/Resources/CustomerGroupResource/Pages/EditCustomerGroup.php +++ b/packages/admin/src/Filament/Resources/CustomerGroupResource/Pages/EditCustomerGroup.php @@ -3,6 +3,7 @@ namespace Lunar\Admin\Filament\Resources\CustomerGroupResource\Pages; use Filament\Actions; +use Filament\Notifications\Notification; use Lunar\Admin\Filament\Resources\CustomerGroupResource; use Lunar\Admin\Support\Pages\BaseEditRecord; @@ -13,7 +14,16 @@ class EditCustomerGroup extends BaseEditRecord protected function getDefaultHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->before(function ($record, Actions\DeleteAction $action) { + if ($record->customers->count() > 0) { + Notification::make() + ->warning() + ->body(__('lunarpanel::customergroup.action.delete.notification.error_protected')) + ->send(); + $action->cancel(); + } + }), ]; } diff --git a/packages/admin/src/Filament/Resources/ProductTypeResource/Pages/EditProductType.php b/packages/admin/src/Filament/Resources/ProductTypeResource/Pages/EditProductType.php index db9827894e..4a4e0928e3 100644 --- a/packages/admin/src/Filament/Resources/ProductTypeResource/Pages/EditProductType.php +++ b/packages/admin/src/Filament/Resources/ProductTypeResource/Pages/EditProductType.php @@ -3,6 +3,7 @@ namespace Lunar\Admin\Filament\Resources\ProductTypeResource\Pages; use Filament\Actions; +use Filament\Notifications\Notification; use Lunar\Admin\Filament\Resources\ProductTypeResource; use Lunar\Admin\Support\Pages\BaseEditRecord; @@ -13,7 +14,16 @@ class EditProductType extends BaseEditRecord protected function getDefaultHeaderActions(): array { return [ - Actions\DeleteAction::make(), + Actions\DeleteAction::make() + ->before(function ($record, Actions\DeleteAction $action) { + if ($record->products->count() > 0) { + Notification::make() + ->warning() + ->body(__('lunarpanel::producttype.action.delete.notification.error_protected')) + ->send(); + $action->cancel(); + } + }), ]; } From 4deab57c90956fb5a1782dd31fde6702a701cd47 Mon Sep 17 00:00:00 2001 From: Glenn Jacobs Date: Thu, 15 Feb 2024 00:24:11 +0000 Subject: [PATCH 11/12] Update ManageProductShipping.php --- .../Pages/ManageProductShipping.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductShipping.php b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductShipping.php index fcf9429219..60a5fce55b 100644 --- a/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductShipping.php +++ b/packages/admin/src/Filament/Resources/ProductResource/Pages/ManageProductShipping.php @@ -136,55 +136,55 @@ public function form(Form $form): Form return $form->schema([ Section::make()->schema([ Toggle::make('shippable')->label( - __('lunarpanel::product.pages.shipping.form.shippable.label') + __('lunarpanel::productvariant.form.shippable.label') )->columnSpan(2), TextInputSelectAffix::make('dimensions.length_value') ->label( - __('lunarpanel::product.pages.shipping.form.length_value.label') + __('lunarpanel::productvariant.form.length_value.label') ) ->numeric() ->select( fn () => Select::make('length_unit') ->options($lengths) ->label( - __('lunarpanel::product.pages.shipping.form.length_unit.label') + __('lunarpanel::pproductvariant.form.length_unit.label') )->selectablePlaceholder(false) ), TextInputSelectAffix::make('dimensions.width_value') ->label( - __('lunarpanel::product.pages.shipping.form.width_value.label') + __('lunarpanel::productvariant.form.width_value.label') ) ->numeric() ->select( fn () => Select::make('width_unit') ->options($lengths) ->label( - __('lunarpanel::product.pages.shipping.form.width_unit.label') + __('lunarpanel::productvariant.form.width_unit.label') )->selectablePlaceholder(false) ), TextInputSelectAffix::make('dimensions.height_value') ->label( - __('lunarpanel::product.pages.shipping.form.height_value.label') + __('lunarpanel::productvariant.form.height_value.label') ) ->numeric() ->select( fn () => Select::make('height_unit') ->options($lengths) ->label( - __('lunarpanel::product.pages.shipping.form.height_unit.label') + __('lunarpanel::productvariant.form.height_unit.label') )->selectablePlaceholder(false) ), TextInputSelectAffix::make('dimensions.weight_value') ->label( - __('lunarpanel::product.pages.shipping.form.weight_value.label') + __('lunarpanel::productvariant.form.weight_value.label') ) ->numeric() ->select( fn () => Select::make('weight_unit') ->options($weights) ->label( - __('lunarpanel::product.pages.shipping.form.weight_unit.label') + __('lunarpanel::productvariant.form.weight_unit.label') )->selectablePlaceholder(false) ), ])->columns([ From 5daaccff0be3f22e9e4db1272349146d957b75a5 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Thu, 15 Feb 2024 10:22:21 +0000 Subject: [PATCH 12/12] Feature - Discount editing (#1542) Adds additional discount editing functionality. - [x] Write tests --------- Co-authored-by: alecritson --- packages/admin/resources/lang/en/discount.php | 304 ++++++++++++++++++ .../Filament/Resources/DiscountResource.php | 300 ++++++++++++++++- .../DiscountResource/Pages/EditDiscount.php | 64 ++++ .../DiscountResource/Pages/ListDiscounts.php | 13 +- .../Pages/ManageBuyXGetYDiscount.php | 53 +++ .../Pages/ManageDiscountAvailability.php | 47 +++ .../Pages/ManageDiscountLimitations.php | 53 +++ .../BrandLimitationRelationManager.php | 60 ++++ .../CollectionLimitationRelationManager.php | 64 ++++ .../ProductConditionRelationManager.php | 83 +++++ .../ProductLimitationRelationManager.php | 78 +++++ .../ProductRewardRelationManager.php | 83 +++++ ...roductVariantLimitationRelationManager.php | 88 +++++ packages/admin/src/LunarPanelManager.php | 1 + packages/core/src/Models/Brand.php | 7 + packages/core/src/Models/Currency.php | 5 + packages/core/src/Models/Discount.php | 25 ++ .../Pages/EditDiscountTest.php | 47 +++ .../Pages/ListDiscountsTest.php | 28 ++ .../Pages/ManageDiscountAvailabilityTest.php | 20 ++ .../Pages/ManageDiscountLimitationsTest.php | 20 ++ 21 files changed, 1438 insertions(+), 5 deletions(-) create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/Pages/EditDiscount.php create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageBuyXGetYDiscount.php create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageDiscountAvailability.php create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageDiscountLimitations.php create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/BrandLimitationRelationManager.php create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/CollectionLimitationRelationManager.php create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductConditionRelationManager.php create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductLimitationRelationManager.php create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductRewardRelationManager.php create mode 100644 packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductVariantLimitationRelationManager.php create mode 100644 tests/admin/Feature/Filament/Resources/DiscountResource/Pages/EditDiscountTest.php create mode 100644 tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ListDiscountsTest.php create mode 100644 tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ManageDiscountAvailabilityTest.php create mode 100644 tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ManageDiscountLimitationsTest.php diff --git a/packages/admin/resources/lang/en/discount.php b/packages/admin/resources/lang/en/discount.php index 57ad128850..089b30b67c 100644 --- a/packages/admin/resources/lang/en/discount.php +++ b/packages/admin/resources/lang/en/discount.php @@ -4,13 +4,317 @@ 'plural_label' => 'Discounts', 'label' => 'Discount', 'form' => [ + 'conditions' => [ + 'heading' => 'Conditions', + ], + 'buy_x_get_y' => [ + 'heading' => 'Buy X Get Y', + ], + 'amount_off' => [ + 'heading' => 'Amount Off', + ], 'name' => [ 'label' => 'Name', ], + 'handle' => [ + 'label' => 'Handle', + ], + 'starts_at' => [ + 'label' => 'Start Date', + ], + 'ends_at' => [ + 'label' => 'End Date', + ], + 'priority' => [ + 'label' => 'Priority', + 'helper_text' => 'Discounts with higher priority will be applied first.', + 'options' => [ + 'low' => [ + 'label' => 'Low', + ], + 'medium' => [ + 'label' => 'Low', + ], + 'high' => [ + 'label' => 'High', + ], + ], + ], + 'stop' => [ + 'label' => 'Stop other discounts applying after this one', + ], + 'coupon' => [ + 'label' => 'Coupon', + 'helper_text' => 'Enter the coupon required for the discount to apply, if left blank it will apply automatically.', + ], + 'max_uses' => [ + 'label' => 'Max uses', + 'helper_text' => 'Leave blank for unlimited uses.', + ], + 'max_uses_per_user' => [ + 'label' => 'Max uses per user', + 'helper_text' => 'Leave blank for unlimited uses.', + ], + 'minimum_cart_amount' => [ + 'label' => 'Minimum Cart Amount', + ], + 'min_qty' => [ + 'label' => 'Product Quantity', + 'helper_text' => 'Set how many qualifying products are required for the discount to apply.', + ], + 'reward_qty' => [ + 'label' => 'No. of free items', + 'helper_text' => 'How many of each item are discounted.', + ], + 'max_reward_qty' => [ + 'label' => 'Maximum reward quantity', + 'helper_text' => 'The maximum amount of products which can be discounted, regardless of criteria.', + ], ], 'table' => [ 'name' => [ 'label' => 'Name', ], + 'status' => [ + 'label' => 'Status', + \Lunar\Models\Discount::ACTIVE => [ + 'label' => 'Active', + ], + \Lunar\Models\Discount::PENDING => [ + 'label' => 'Pending', + ], + \Lunar\Models\Discount::EXPIRED => [ + 'label' => 'Expired', + ], + \Lunar\Models\Discount::SCHEDULED => [ + 'label' => 'Scheduled', + ], + ], + 'type' => [ + 'label' => 'Type', + ], + 'starts_at' => [ + 'label' => 'Start Date', + ], + 'ends_at' => [ + 'label' => 'End Date', + ], + ], + 'pages' => [ + 'availability' => [ + 'label' => 'Availability', + ], + 'limitations' => [ + 'label' => 'Limitations', + ], + ], + 'relationmanagers' => [ + 'collections' => [ + 'title' => 'Collections', + 'description' => 'Select which collections this discount should be limited to.', + 'actions' => [ + 'attach' => [ + 'label' => 'Attach Collection', + ], + ], + 'table' => [ + 'name' => [ + 'label' => 'Name', + ], + 'type' => [ + 'label' => 'Type', + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + 'form' => [ + 'type' => [ + 'options' => [ + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + ], + ], + 'brands' => [ + 'title' => 'Brands', + 'description' => 'Select which brands this discount should be limited to.', + 'actions' => [ + 'attach' => [ + 'label' => 'Attach Brand', + ], + ], + 'table' => [ + 'name' => [ + 'label' => 'Name', + ], + 'type' => [ + 'label' => 'Type', + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + 'form' => [ + 'type' => [ + 'options' => [ + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + ], + ], + 'products' => [ + 'title' => 'Products', + 'description' => 'Select which products this discount should be limited to.', + 'actions' => [ + 'attach' => [ + 'label' => 'Add Product', + ], + ], + 'table' => [ + 'name' => [ + 'label' => 'Name', + ], + 'type' => [ + 'label' => 'Type', + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + 'form' => [ + 'type' => [ + 'options' => [ + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + ], + ], + 'rewards' => [ + 'title' => 'Product Rewards', + 'description' => 'Select which products will be discounted if they exist in the cart and the above conditions are met.', + 'actions' => [ + 'attach' => [ + 'label' => 'Add Product', + ], + ], + 'table' => [ + 'name' => [ + 'label' => 'Name', + ], + 'type' => [ + 'label' => 'Type', + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + 'form' => [ + 'type' => [ + 'options' => [ + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + ], + ], + 'conditions' => [ + 'title' => 'Product Conditions', + 'description' => 'Select the products required for the discount to apply.', + 'actions' => [ + 'attach' => [ + 'label' => 'Add Product', + ], + ], + 'table' => [ + 'name' => [ + 'label' => 'Name', + ], + 'type' => [ + 'label' => 'Type', + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + 'form' => [ + 'type' => [ + 'options' => [ + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + ], + ], + 'productvariants' => [ + 'title' => 'Product Variants', + 'description' => 'Select which product variants this discount should be limited to.', + 'actions' => [ + 'attach' => [ + 'label' => 'Add Product Variant', + ], + ], + 'table' => [ + 'name' => [ + 'label' => 'Name', + ], + 'sku' => [ + 'label' => 'SKU', + ], + 'values' => [ + 'label' => 'Option(s)', + ], + ], + 'form' => [ + 'type' => [ + 'options' => [ + 'limitation' => [ + 'label' => 'Limitation', + ], + 'exclusion' => [ + 'label' => 'Exclusion', + ], + ], + ], + ], + ], ], ]; diff --git a/packages/admin/src/Filament/Resources/DiscountResource.php b/packages/admin/src/Filament/Resources/DiscountResource.php index efadd2e4f4..e537486909 100644 --- a/packages/admin/src/Filament/Resources/DiscountResource.php +++ b/packages/admin/src/Filament/Resources/DiscountResource.php @@ -4,12 +4,25 @@ use Filament\Forms; use Filament\Forms\Components\Component; +use Filament\Forms\Form; +use Filament\Pages\Page; use Filament\Pages\SubNavigationPosition; use Filament\Support\Facades\FilamentIcon; use Filament\Tables; use Filament\Tables\Table; +use Illuminate\Support\Str; use Lunar\Admin\Filament\Resources\DiscountResource\Pages; +use Lunar\Admin\Filament\Resources\DiscountResource\RelationManagers\BrandLimitationRelationManager; +use Lunar\Admin\Filament\Resources\DiscountResource\RelationManagers\CollectionLimitationRelationManager; +use Lunar\Admin\Filament\Resources\DiscountResource\RelationManagers\ProductConditionRelationManager; +use Lunar\Admin\Filament\Resources\DiscountResource\RelationManagers\ProductLimitationRelationManager; +use Lunar\Admin\Filament\Resources\DiscountResource\RelationManagers\ProductRewardRelationManager; +use Lunar\Admin\Filament\Resources\DiscountResource\RelationManagers\ProductVariantLimitationRelationManager; use Lunar\Admin\Support\Resources\BaseResource; +use Lunar\DiscountTypes\AmountOff; +use Lunar\DiscountTypes\BuyXGetY; +use Lunar\Facades\Discounts; +use Lunar\Models\Currency; use Lunar\Models\Discount; class DiscountResource extends BaseResource @@ -42,22 +55,259 @@ public static function getNavigationGroup(): ?string return 'Sales'; } + public static function getDefaultForm(Form $form): Form + { + return $form->schema([ + Forms\Components\Section::make('')->schema( + static::getMainFormComponents() + ), + Forms\Components\Section::make('conditions')->schema( + static::getConditionsFormComponents() + )->heading( + __('lunarpanel::discount.form.conditions.heading') + ), + Forms\Components\Section::make('buy_x_get_y') + ->heading( + __('lunarpanel::discount.form.buy_x_get_y.heading') + ) + ->visible( + fn (Forms\Get $get) => $get('type') == BuyXGetY::class + )->schema( + static::getBuyXGetYFormComponents() + ), + Forms\Components\Section::make('amount_off') + ->heading( + __('lunarpanel::discount.form.amount_off.heading') + ) + ->visible( + fn (Forms\Get $get) => $get('type') == AmountOff::class + )->schema( + static::getAmountOffFormComponents() + ), + ]); + } + protected static function getMainFormComponents(): array { return [ - static::getNameFormComponent(), + Forms\Components\Group::make([ + static::getNameFormComponent(), + static::getHandleFormComponent(), + ])->columns(2), + Forms\Components\Group::make([ + static::getStartsAtFormComponent(), + static::getEndsAtFormComponent(), + ])->columns(2), + Forms\Components\Group::make([ + static::getPriorityFormComponent(), + static::getDiscountTypeFormComponent(), + ])->columns(2), + static::getStopFormComponent(), + ]; + } + + protected static function getConditionsFormComponents(): array + { + return [ + Forms\Components\Group::make([ + static::getCouponFormComponent(), + static::getMaxUsesFormComponent(), + static::getMaxUsesPerUserFormComponent(), + ])->columns(3), + Forms\Components\Fieldset::make()->schema( + static::getMinimumCartAmountsFormComponents() + )->label( + __('lunarpanel::discount.form.minimum_cart_amount.label') + ), ]; } - protected static function getNameFormComponent(): Component + public static function getNameFormComponent(): Component { return Forms\Components\TextInput::make('name') ->label(__('lunarpanel::discount.form.name.label')) + ->live(onBlur: true) + ->afterStateUpdated(function (string $operation, $state, Forms\Set $set) { + if ($operation !== 'create') { + return; + } + $set('handle', Str::slug($state)); + }) ->required() ->maxLength(255) ->autofocus(); } + public static function getHandleFormComponent(): Component + { + return Forms\Components\TextInput::make('handle') + ->label(__('lunarpanel::discount.form.handle.label')) + ->required() + ->unique(ignoreRecord: true) + ->maxLength(255) + ->autofocus(); + } + + public static function getStartsAtFormComponent(): Component + { + return Forms\Components\DateTimePicker::make('starts_at') + ->label(__('lunarpanel::discount.form.starts_at.label')) + ->required() + ->before(function (Forms\Get $get) { + return $get('ends_at'); + }); + } + + public static function getEndsAtFormComponent(): Component + { + return Forms\Components\DateTimePicker::make('ends_at') + ->label(__('lunarpanel::discount.form.ends_at.label')); + } + + protected static function getPriorityFormComponent(): Component + { + return Forms\Components\Select::make('priority') + ->label(__('lunarpanel::discount.form.priority.label')) + ->helperText( + __('lunarpanel::discount.form.priority.helper_text') + ) + ->options(function () { + return [ + 1 => __('lunarpanel::discount.form.priority.options.low.label'), + 5 => __('lunarpanel::discount.form.priority.options.medium.label'), + 10 => __('lunarpanel::discount.form.priority.options.high.label'), + ]; + }); + } + + protected static function getStopFormComponent(): Component + { + return Forms\Components\Toggle::make('stop') + ->label( + __('lunarpanel::discount.form.stop.label') + ); + } + + protected static function getCouponFormComponent(): Component + { + return Forms\Components\TextInput::make('coupon') + ->label( + __('lunarpanel::discount.form.coupon.label') + )->helperText( + __('lunarpanel::discount.form.coupon.helper_text') + ); + } + + protected static function getMaxUsesFormComponent(): Component + { + return Forms\Components\TextInput::make('max_uses') + ->label( + __('lunarpanel::discount.form.max_uses.label') + )->helperText( + __('lunarpanel::discount.form.max_uses.helper_text') + ); + } + + protected static function getMaxUsesPerUserFormComponent(): Component + { + return Forms\Components\TextInput::make('max_uses_per_user') + ->label( + __('lunarpanel::discount.form.max_uses_per_user.label') + )->helperText( + __('lunarpanel::discount.form.max_uses_per_user.helper_text') + ); + } + + protected static function getMinimumCartAmountsFormComponents(): array + { + $currencies = Currency::enabled()->get(); + $inputs = []; + + foreach ($currencies as $currency) { + $inputs[] = Forms\Components\TextInput::make('data.min_prices.'.$currency->code)->label( + $currency->code + )->afterStateHydrated(function (Forms\Components\TextInput $component, $state) { + $currencyCode = last(explode('.', $component->getStatePath())); + $currency = Currency::whereCode($currencyCode)->first(); + + if ($currency) { + $component->state($state / $currency->factor); + } + }); + } + + return $inputs; + } + + public static function getDiscountTypeFormComponent(): Component + { + return Forms\Components\Select::make('type')->options( + Discounts::getTypes()->mapWithKeys( + fn ($type) => [get_class($type) => $type->getName()] + ) + )->required()->live(); + } + + protected static function getAmountOffFormComponents(): array + { + $currencies = Currency::get(); + + $currencyInputs = []; + + foreach ($currencies as $currency) { + $currencyInputs[] = Forms\Components\TextInput::make( + 'data.fixed_values.'.$currency->code + )->label($currency->name)->afterStateHydrated(function (Forms\Components\TextInput $component, $state) use ($currencies) { + $currencyCode = last(explode('.', $component->getStatePath())); + $currency = $currencies->first( + fn ($currency) => $currency->code == $currencyCode + ); + + if ($currency) { + $component->state($state / $currency->factor); + } + }); + } + + return [ + Forms\Components\Toggle::make('data.fixed_value')->live(), + Forms\Components\TextInput::make('data.percentage')->visible( + fn (Forms\Get $get) => ! $get('data.fixed_value') + )->numeric(), + Forms\Components\Group::make( + $currencyInputs + )->visible( + fn (Forms\Get $get) => (bool) $get('data.fixed_value') + )->columns(3), + ]; + } + + public static function getBuyXGetYFormComponents(): array + { + return [ + Forms\Components\TextInput::make('data.min_qty') + ->label( + __('lunarpanel::discount.form.min_qty.label') + )->helperText( + __('lunarpanel::discount.form.min_qty.helper_text') + )->numeric(), + Forms\Components\Group::make([ + Forms\Components\TextInput::make('data.reward_qty') + ->label( + __('lunarpanel::discount.form.reward_qty.label') + )->helperText( + __('lunarpanel::discount.form.reward_qty.helper_text') + )->numeric(), + Forms\Components\TextInput::make('data.max_reward_qty') + ->label( + __('lunarpanel::discount.form.max_reward_qty.label') + )->helperText( + __('lunarpanel::discount.form.max_reward_qty.helper_text') + )->numeric(), + ])->columns(2), + ]; + } + public static function getDefaultTable(Table $table): Table { return $table @@ -78,15 +328,54 @@ public static function getDefaultTable(Table $table): Table protected static function getTableColumns(): array { return [ + Tables\Columns\TextColumn::make('status') + ->formatStateUsing(function ($state) { + return __("lunarpanel::discount.table.status.{$state}.label"); + }) + ->label(__('lunarpanel::discount.table.status.label')) + ->badge() + ->color(fn (string $state): string => match ($state) { + Discount::ACTIVE => 'success', + Discount::EXPIRED => 'danger', + Discount::PENDING => 'gray', + Discount::SCHEDULED => 'info', + }), Tables\Columns\TextColumn::make('name') ->label(__('lunarpanel::discount.table.name.label')), + Tables\Columns\TextColumn::make('type') + ->formatStateUsing(function ($state) { + return (new $state)->getName(); + }) + ->label(__('lunarpanel::discount.table.type.label')), + Tables\Columns\TextColumn::make('starts_at') + ->label(__('lunarpanel::discount.table.starts_at.label')) + ->date(), + Tables\Columns\TextColumn::make('ends_at') + ->label(__('lunarpanel::discount.table.ends_at.label')) + ->date(), ]; } - public static function getRelations(): array + public static function getRecordSubNavigation(Page $page): array + { + return $page->generateNavigationItems([ + Pages\EditDiscount::class, + Pages\ManageDiscountAvailability::class, + Pages\ManageDiscountLimitations::class, + ]); + } + + protected static function getDefaultRelations(): array { return [ - // + CollectionLimitationRelationManager::class, + BrandLimitationRelationManager::class, + ProductLimitationRelationManager::class, + ProductVariantLimitationRelationManager::class, + ProductRewardRelationManager::class, + ProductConditionRelationManager::class, + ProductRewardRelationManager::class, + ProductConditionRelationManager::class, ]; } @@ -94,6 +383,9 @@ public static function getPages(): array { return [ 'index' => Pages\ListDiscounts::route('/'), + 'edit' => Pages\EditDiscount::route('/{record}'), + 'limitations' => Pages\ManageDiscountLimitations::route('/{record}/limitations'), + 'availability' => Pages\ManageDiscountAvailability::route('/{record}/availability'), ]; } } diff --git a/packages/admin/src/Filament/Resources/DiscountResource/Pages/EditDiscount.php b/packages/admin/src/Filament/Resources/DiscountResource/Pages/EditDiscount.php new file mode 100644 index 0000000000..754c8fe12b --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/Pages/EditDiscount.php @@ -0,0 +1,64 @@ +get(); + + foreach ($minPrices as $currencyCode => $value) { + $currency = $currencies->first( + fn ($currency) => $currency->code == $currencyCode + ); + + if (! $currency) { + continue; + } + $data['data']['min_prices'][$currencyCode] = (int) round($value * $currency->factor); + } + + foreach ($fixedPrices as $currencyCode => $fixedPrice) { + $currency = $currencies->first( + fn ($currency) => $currency->code == $currencyCode + ); + + if (! $currency) { + continue; + } + $data['data']['fixed_values'][$currencyCode] = (int) round($fixedPrice * $currency->factor); + } + + return $data; + } + + public function getRelationManagers(): array + { + $managers = []; + + if ($this->record->type == BuyXGetY::class) { + $managers[] = DiscountResource\RelationManagers\ProductConditionRelationManager::class; + $managers[] = DiscountResource\RelationManagers\ProductRewardRelationManager::class; + } + + return $managers; + } +} diff --git a/packages/admin/src/Filament/Resources/DiscountResource/Pages/ListDiscounts.php b/packages/admin/src/Filament/Resources/DiscountResource/Pages/ListDiscounts.php index e6ca818968..a19d12b06e 100644 --- a/packages/admin/src/Filament/Resources/DiscountResource/Pages/ListDiscounts.php +++ b/packages/admin/src/Filament/Resources/DiscountResource/Pages/ListDiscounts.php @@ -3,6 +3,7 @@ namespace Lunar\Admin\Filament\Resources\DiscountResource\Pages; use Filament\Actions; +use Filament\Forms; use Lunar\Admin\Filament\Resources\DiscountResource; use Lunar\Admin\Support\Pages\BaseListRecords; @@ -13,7 +14,17 @@ class ListDiscounts extends BaseListRecords protected function getDefaultHeaderActions(): array { return [ - Actions\CreateAction::make(), + Actions\CreateAction::make()->form([ + Forms\Components\Group::make([ + DiscountResource::getNameFormComponent(), + DiscountResource::getHandleFormComponent(), + ])->columns(2), + Forms\Components\Group::make([ + DiscountResource::getStartsAtFormComponent(), + DiscountResource::getEndsAtFormComponent(), + ])->columns(2), + DiscountResource::getDiscountTypeFormComponent(), + ]), ]; } } diff --git a/packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageBuyXGetYDiscount.php b/packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageBuyXGetYDiscount.php new file mode 100644 index 0000000000..78c097e387 --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageBuyXGetYDiscount.php @@ -0,0 +1,53 @@ +schema([]); + } + + protected function getFormActions(): array + { + return []; + } + + public function getRelationManagers(): array + { + return [ + RelationGroup::make('Limitations', [ + DiscountResource\RelationManagers\CollectionLimitationRelationManager::class, + DiscountResource\RelationManagers\BrandLimitationRelationManager::class, + DiscountResource\RelationManagers\ProductLimitationRelationManager::class, + DiscountResource\RelationManagers\ProductVariantLimitationRelationManager::class, + ]), + + ]; + } +} diff --git a/packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageDiscountAvailability.php b/packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageDiscountAvailability.php new file mode 100644 index 0000000000..476d107b4f --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageDiscountAvailability.php @@ -0,0 +1,47 @@ + [ + 'enabled', + 'visible', + ], + ]), + ]), + ]; + } +} diff --git a/packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageDiscountLimitations.php b/packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageDiscountLimitations.php new file mode 100644 index 0000000000..8b6f4919dd --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/Pages/ManageDiscountLimitations.php @@ -0,0 +1,53 @@ +schema([]); + } + + protected function getFormActions(): array + { + return []; + } + + public function getRelationManagers(): array + { + return [ + RelationGroup::make('Limitations', [ + DiscountResource\RelationManagers\CollectionLimitationRelationManager::class, + DiscountResource\RelationManagers\BrandLimitationRelationManager::class, + DiscountResource\RelationManagers\ProductLimitationRelationManager::class, + DiscountResource\RelationManagers\ProductVariantLimitationRelationManager::class, + ]), + + ]; + } +} diff --git a/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/BrandLimitationRelationManager.php b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/BrandLimitationRelationManager.php new file mode 100644 index 0000000000..187bf395d1 --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/BrandLimitationRelationManager.php @@ -0,0 +1,60 @@ +description( + __('lunarpanel::discount.relationmanagers.brands.description') + ) + ->paginated(false) + ->headerActions([ + Tables\Actions\AttachAction::make()->form(fn (Tables\Actions\AttachAction $action): array => [ + $action->getRecordSelect(), + Select::make('type') + ->options( + fn () => [ + 'limitation' => __('lunarpanel::discount.relationmanagers.brands.form.type.options.limitation.label'), + 'exclusion' => __('lunarpanel::discount.relationmanagers.brands.form.type.options.exclusion.label'), + ] + )->default('limitation'), + ])->recordTitle(function ($record) { + return $record->name; + })->preloadRecordSelect() + ->label( + __('lunarpanel::discount.relationmanagers.brands.actions.attach.label') + ), + ])->columns([ + Tables\Columns\TextColumn::make('name') + ->label( + __('lunarpanel::discount.relationmanagers.brands.table.name.label') + ), + Tables\Columns\TextColumn::make('pivot.type') + ->label( + __('lunarpanel::discount.relationmanagers.brands.table.type.label') + )->formatStateUsing( + fn (string $state) => __("lunarpanel::discount.relationmanagers.brands.table.type.{$state}.label") + ), + ])->actions([ + Tables\Actions\DetachAction::make(), + ]); + } +} diff --git a/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/CollectionLimitationRelationManager.php b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/CollectionLimitationRelationManager.php new file mode 100644 index 0000000000..9e0c5d54ed --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/CollectionLimitationRelationManager.php @@ -0,0 +1,64 @@ +description( + __('lunarpanel::discount.relationmanagers.collections.description') + ) + ->paginated(false) + ->headerActions([ + Tables\Actions\AttachAction::make()->form(fn (Tables\Actions\AttachAction $action): array => [ + $action->getRecordSelect(), + Select::make('type') + ->options( + fn () => [ + 'limitation' => __('lunarpanel::discount.relationmanagers.collections.form.type.options.limitation.label'), + 'exclusion' => __('lunarpanel::discount.relationmanagers.collections.form.type.options.exclusion.label'), + ] + )->default('limitation'), + ])->recordTitle(function ($record) { + return $record->attr('name'); + })->preloadRecordSelect() + ->label( + __('lunarpanel::discount.relationmanagers.collections.actions.attach.label') + ), + ])->columns([ + Tables\Columns\TextColumn::make('attribute_data.name') + ->label( + __('lunarpanel::discount.relationmanagers.collections.table.name.label') + ) + ->formatStateUsing( + fn (Model $record) => $record->attr('name') + ), + Tables\Columns\TextColumn::make('pivot.type') + ->label( + __('lunarpanel::discount.relationmanagers.collections.table.type.label') + )->formatStateUsing( + fn (string $state) => __("lunarpanel::discount.relationmanagers.collections.table.type.{$state}.label") + ), + ])->actions([ + Tables\Actions\DetachAction::make(), + ]); + } +} diff --git a/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductConditionRelationManager.php b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductConditionRelationManager.php new file mode 100644 index 0000000000..d642946cc4 --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductConditionRelationManager.php @@ -0,0 +1,83 @@ +heading( + __('lunarpanel::discount.relationmanagers.conditions.title') + ) + ->description( + __('lunarpanel::discount.relationmanagers.conditions.description') + ) + ->paginated(false) + ->modifyQueryUsing( + fn ($query) => $query->whereIn('type', ['condition']) + ->wherePurchasableType(Product::class) + ->whereHas('purchasable') + ) + ->headerActions([ + Tables\Actions\CreateAction::make()->form([ + Forms\Components\MorphToSelect::make('purchasable') + ->searchable(true) + ->types([ + Forms\Components\MorphToSelect\Type::make(Product::class) + ->titleAttribute('name.en') + ->getSearchResultsUsing(static function (Forms\Components\Select $component, string $search): array { + return Product::search($search) + ->get() + ->mapWithKeys(fn (Product $record): array => [$record->getKey() => $record->attr('name')]) + ->all(); + }), + ]), + ])->label( + __('lunarpanel::discount.relationmanagers.conditions.actions.attach.label') + )->mutateFormDataUsing(function (array $data) { + $data['type'] = 'condition'; + + return $data; + }), + ])->columns([ + Tables\Columns\SpatieMediaLibraryImageColumn::make('purchasable.thumbnail') + ->collection('images') + ->conversion('small') + ->limit(1) + ->square() + ->label(''), + Tables\Columns\TextColumn::make('purchasable.attribute_data.name') + ->label( + __('lunarpanel::discount.relationmanagers.conditions.table.name.label') + ) + ->formatStateUsing( + fn (Model $record) => $record->purchasable->attr('name') + ), + ])->actions([ + Tables\Actions\DeleteAction::make(), + ]); + } +} diff --git a/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductLimitationRelationManager.php b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductLimitationRelationManager.php new file mode 100644 index 0000000000..f7430351b9 --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductLimitationRelationManager.php @@ -0,0 +1,78 @@ +heading( + __('lunarpanel::discount.relationmanagers.products.title') + ) + ->description( + __('lunarpanel::discount.relationmanagers.products.description') + ) + ->paginated(false) + ->modifyQueryUsing( + fn ($query) => $query->whereIn('type', ['limitation', 'exclusion']) + ->wherePurchasableType(Product::class) + ->whereHas('purchasable') + ) + ->headerActions([ + Tables\Actions\CreateAction::make()->form([ + Forms\Components\MorphToSelect::make('purchasable') + ->searchable(true) + ->types([ + Forms\Components\MorphToSelect\Type::make(Product::class) + ->titleAttribute('name.en') + ->getSearchResultsUsing(static function (Forms\Components\Select $component, string $search): array { + return Product::search($search) + ->get() + ->mapWithKeys(fn (Product $record): array => [$record->getKey() => $record->attr('name')]) + ->all(); + }), + ]), + ])->label( + __('lunarpanel::discount.relationmanagers.products.actions.attach.label') + )->mutateFormDataUsing(function (array $data) { + $data['type'] = 'limitation'; + + return $data; + }), + ])->columns([ + Tables\Columns\SpatieMediaLibraryImageColumn::make('purchasable.thumbnail') + ->collection('images') + ->conversion('small') + ->limit(1) + ->square() + ->label(''), + Tables\Columns\TextColumn::make('purchasable.attribute_data.name') + ->label( + __('lunarpanel::discount.relationmanagers.products.table.name.label') + ) + ->formatStateUsing( + fn (Model $record) => $record->purchasable->attr('name') + ), + ])->actions([ + Tables\Actions\DeleteAction::make(), + ]); + } +} diff --git a/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductRewardRelationManager.php b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductRewardRelationManager.php new file mode 100644 index 0000000000..e9d0de67aa --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductRewardRelationManager.php @@ -0,0 +1,83 @@ +heading( + __('lunarpanel::discount.relationmanagers.rewards.title') + ) + ->description( + __('lunarpanel::discount.relationmanagers.rewards.description') + ) + ->paginated(false) + ->modifyQueryUsing( + fn ($query) => $query->whereIn('type', ['reward']) + ->wherePurchasableType(Product::class) + ->whereHas('purchasable') + ) + ->headerActions([ + Tables\Actions\CreateAction::make()->form([ + Forms\Components\MorphToSelect::make('purchasable') + ->searchable(true) + ->types([ + Forms\Components\MorphToSelect\Type::make(Product::class) + ->titleAttribute('name.en') + ->getSearchResultsUsing(static function (Forms\Components\Select $component, string $search): array { + return Product::search($search) + ->get() + ->mapWithKeys(fn (Product $record): array => [$record->getKey() => $record->attr('name')]) + ->all(); + }), + ]), + ])->label( + __('lunarpanel::discount.relationmanagers.rewards.actions.attach.label') + )->mutateFormDataUsing(function (array $data) { + $data['type'] = 'reward'; + + return $data; + }), + ])->columns([ + Tables\Columns\SpatieMediaLibraryImageColumn::make('purchasable.thumbnail') + ->collection('images') + ->conversion('small') + ->limit(1) + ->square() + ->label(''), + Tables\Columns\TextColumn::make('purchasable.attribute_data.name') + ->label( + __('lunarpanel::discount.relationmanagers.rewards.table.name.label') + ) + ->formatStateUsing( + fn (Model $record) => $record->purchasable->attr('name') + ), + ])->actions([ + Tables\Actions\DeleteAction::make(), + ]); + } +} diff --git a/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductVariantLimitationRelationManager.php b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductVariantLimitationRelationManager.php new file mode 100644 index 0000000000..8c3802067a --- /dev/null +++ b/packages/admin/src/Filament/Resources/DiscountResource/RelationManagers/ProductVariantLimitationRelationManager.php @@ -0,0 +1,88 @@ +heading( + __('lunarpanel::discount.relationmanagers.productvariants.title') + ) + ->description( + __('lunarpanel::discount.relationmanagers.productvariants.description') + ) + ->paginated(false) + ->modifyQueryUsing( + fn ($query) => $query->whereIn('type', ['limitation', 'exclusion']) + ->wherePurchasableType(ProductVariant::class) + ->whereHas('purchasable') + ) + ->headerActions([ + Tables\Actions\CreateAction::make()->form([ + Forms\Components\MorphToSelect::make('purchasable') + ->searchable(true) + ->types([ + Forms\Components\MorphToSelect\Type::make(ProductVariant::class) + ->titleAttribute('sku') + ->getSearchResultsUsing(static function (Forms\Components\Select $component, string $search): array { + $products = Product::search($search) + ->get(); + + return ProductVariant::whereIn('product_id', $products->pluck('id')) + ->get() + ->mapWithKeys(fn (ProductVariant $record): array => [$record->getKey() => $record->product->attr('name').' - '.$record->sku]) + ->all(); + }), + ]), + ])->label( + __('lunarpanel::discount.relationmanagers.productvariants.actions.attach.label') + )->mutateFormDataUsing(function (array $data) { + $data['type'] = 'limitation'; + + return $data; + }), + ])->columns([ + Tables\Columns\TextColumn::make('purchasable') + ->formatStateUsing( + fn (Model $model) => $model->purchasable->getDescription() + ) + ->label( + __('lunarpanel::discount.relationmanagers.productvariants.table.name.label') + ), + Tables\Columns\TextColumn::make('purchasable.sku') + ->label( + __('lunarpanel::discount.relationmanagers.productvariants.table.sku.label') + ), + Tables\Columns\TextColumn::make('purchasable.values') + ->formatStateUsing(function (Model $record) { + return $record->purchasable->values->map( + fn ($value) => $value->translate('name') + )->join(', '); + })->label( + __('lunarpanel::discount.relationmanagers.productvariants.table.values.label') + ), + ])->actions([ + Tables\Actions\DeleteAction::make(), + ]); + } +} diff --git a/packages/admin/src/LunarPanelManager.php b/packages/admin/src/LunarPanelManager.php index 4972c5e0e1..4a700e6015 100644 --- a/packages/admin/src/LunarPanelManager.php +++ b/packages/admin/src/LunarPanelManager.php @@ -111,6 +111,7 @@ public function register(): self 'lunar::customer-groups' => 'lucide-users', 'lunar::dashboard' => 'lucide-bar-chart-big', 'lunar::discounts' => 'lucide-percent-circle', + 'lunar::discount-limitations' => 'lucide-list-x', 'lunar::info' => 'lucide-info', 'lunar::languages' => 'lucide-languages', 'lunar::media' => 'lucide-image', diff --git a/packages/core/src/Models/Brand.php b/packages/core/src/Models/Brand.php index 3c74434e60..416ac5626b 100644 --- a/packages/core/src/Models/Brand.php +++ b/packages/core/src/Models/Brand.php @@ -76,4 +76,11 @@ public function products(): HasMany { return $this->hasMany(Product::class); } + + public function discounts() + { + $prefix = config('lunar.database.table_prefix'); + + return $this->belongsToMany(Discount::class, "{$prefix}brand_discount"); + } } diff --git a/packages/core/src/Models/Currency.php b/packages/core/src/Models/Currency.php index 416bd511ba..51bb4702be 100644 --- a/packages/core/src/Models/Currency.php +++ b/packages/core/src/Models/Currency.php @@ -44,6 +44,11 @@ protected static function newFactory(): CurrencyFactory return CurrencyFactory::new(); } + public function scopeEnabled($query, $enabled = true) + { + return $query->whereEnabled($enabled); + } + /** * Return the prices relationship */ diff --git a/packages/core/src/Models/Discount.php b/packages/core/src/Models/Discount.php index 88471e58e7..2592fdc3a0 100644 --- a/packages/core/src/Models/Discount.php +++ b/packages/core/src/Models/Discount.php @@ -36,6 +36,14 @@ class Discount extends BaseModel protected $guarded = []; + const ACTIVE = 'active'; + + const PENDING = 'pending'; + + const EXPIRED = 'expired'; + + const SCHEDULED = 'scheduled'; + /** * Define which attributes should be cast. * @@ -55,6 +63,23 @@ protected static function newFactory(): DiscountFactory return DiscountFactory::new(); } + public function getStatusAttribute() + { + $active = $this->starts_at?->isPast() && ! $this->ends_at?->isPast(); + $expired = $this->ends_at?->isPast(); + $future = $this->starts_at?->isFuture(); + + if ($expired) { + return static::EXPIRED; + } + + if ($future) { + return static::SCHEDULED; + } + + return $active ? static::ACTIVE : static::PENDING; + } + public function users(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/EditDiscountTest.php b/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/EditDiscountTest.php new file mode 100644 index 0000000000..b185c850bb --- /dev/null +++ b/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/EditDiscountTest.php @@ -0,0 +1,47 @@ +group('resource.discount'); + +beforeEach(function () { + $this->asStaff(); +}); + +it('can render discount edit page', function () { + get( + \Lunar\Admin\Filament\Resources\DiscountResource::getUrl( + 'edit', + ['record' => \Lunar\Models\Discount::factory()->create()] + ) + )->assertSuccessful(); +}); + +it('can edit discount', function () { + $discount = \Lunar\Models\Discount::factory()->create(); + \Livewire\Livewire::test(\Lunar\Admin\Filament\Resources\DiscountResource\Pages\EditDiscount::class, + ['record' => $discount->getKey()] + )->fillForm([ + 'name' => 'Updated Name', + 'handle' => 'updated_name', + ])->call('save')->assertHasNoErrors(); + + assertDatabaseHas(\Lunar\Models\Discount::class, [ + 'name' => 'Updated Name', + 'handle' => 'updated_name', + ]); +}); + +it('can validate start and end date', function () { + $discount = \Lunar\Models\Discount::factory()->create(); + \Livewire\Livewire::test(\Lunar\Admin\Filament\Resources\DiscountResource\Pages\EditDiscount::class, + ['record' => $discount->getKey()] + )->fillForm([ + 'starts_at' => now(), + 'ends_at' => now()->subWeek(), + ])->call('save')->assertHasFormErrors([ + 'starts_at' => 'before', + ]); +}); diff --git a/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ListDiscountsTest.php b/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ListDiscountsTest.php new file mode 100644 index 0000000000..275a04344a --- /dev/null +++ b/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ListDiscountsTest.php @@ -0,0 +1,28 @@ +group('resource.discount'); + +beforeEach(function () { + $this->asStaff(); +}); + +it('can list discounts', function () { + get( + \Lunar\Admin\Filament\Resources\DiscountResource::getUrl('index') + )->assertSuccessful(); +}); + +it('can create a discount', function () { + $discount = \Lunar\Models\Discount::factory()->create(); + \Livewire\Livewire::test( + \Lunar\Admin\Filament\Resources\DiscountResource\Pages\ListDiscounts::class + )->callAction('create', [ + 'name' => 'Discount A', + 'handle' => 'discount_a', + 'starts_at' => now(), + 'type' => \Lunar\DiscountTypes\BuyXGetY::class, + ])->assertHasNoErrors(); +}); diff --git a/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ManageDiscountAvailabilityTest.php b/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ManageDiscountAvailabilityTest.php new file mode 100644 index 0000000000..b41af193f7 --- /dev/null +++ b/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ManageDiscountAvailabilityTest.php @@ -0,0 +1,20 @@ +group('resource.discount'); + +beforeEach(function () { + $this->asStaff(); +}); + +it('can render discount availability page', function () { + $record = \Lunar\Models\Discount::factory()->create(); + + \Lunar\Models\Channel::factory()->create(['default' => true]); + + get(\Lunar\Admin\Filament\Resources\DiscountResource::getUrl('availability', [ + 'record' => $record, + ]))->assertSuccessful(); +}); diff --git a/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ManageDiscountLimitationsTest.php b/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ManageDiscountLimitationsTest.php new file mode 100644 index 0000000000..229ba2c13d --- /dev/null +++ b/tests/admin/Feature/Filament/Resources/DiscountResource/Pages/ManageDiscountLimitationsTest.php @@ -0,0 +1,20 @@ +group('resource.discount'); + +beforeEach(function () { + $this->asStaff(); +}); + +it('can render discount limitations page', function () { + $record = \Lunar\Models\Discount::factory()->create(); + + \Lunar\Models\Channel::factory()->create(['default' => true]); + + get(\Lunar\Admin\Filament\Resources\DiscountResource::getUrl('limitations', [ + 'record' => $record, + ]))->assertSuccessful(); +});