From 3c596173a3cbcc3dff43d5a22bc1081a1ce5fe23 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Wed, 8 Nov 2023 09:01:14 +0000 Subject: [PATCH 01/26] Empty-Commit From 16a3d8f893912d3a7a1240324dccc44e6aa37116 Mon Sep 17 00:00:00 2001 From: arie-piscator Date: Wed, 8 Nov 2023 10:01:57 +0100 Subject: [PATCH 02/26] Moved dollar sign inside curly braces for all embedded strings (#1323) --- .../core/database/state/ConvertTaxbreakdown.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/core/database/state/ConvertTaxbreakdown.php b/packages/core/database/state/ConvertTaxbreakdown.php index c7df120ac6..45ba637c27 100644 --- a/packages/core/database/state/ConvertTaxbreakdown.php +++ b/packages/core/database/state/ConvertTaxbreakdown.php @@ -19,7 +19,7 @@ public function run() if ($this->canRunOnOrders()) { DB::table("{$prefix}orders") - ->whereJsonContainsKey("${prefix}orders.tax_breakdown->[0]->total") + ->whereJsonContainsKey("{$prefix}orders.tax_breakdown->[0]->total") ->orderBy('id') ->chunk(500, function ($rows) use ($prefix, $updateTime) { foreach ($rows as $row) { @@ -43,14 +43,14 @@ public function run() if ($this->canRunOnOrderLines()) { DB::table("{$prefix}order_lines") - ->whereJsonContainsKey("${prefix}order_lines.tax_breakdown->[0]->total") - ->orderBy("${prefix}order_lines.id") + ->whereJsonContainsKey("{$prefix}order_lines.tax_breakdown->[0]->total") + ->orderBy("{$prefix}order_lines.id") ->select( - "${prefix}order_lines.id", - "${prefix}order_lines.tax_breakdown", - "${prefix}orders.currency_code", + "{$prefix}order_lines.id", + "{$prefix}order_lines.tax_breakdown", + "{$prefix}orders.currency_code", ) - ->join("${prefix}orders", "${prefix}order_lines.order_id", '=', "${prefix}orders.id") + ->join("{$prefix}orders", "{$prefix}order_lines.order_id", '=', "{$prefix}orders.id") ->chunk(500, function ($rows) use ($prefix, $updateTime) { DB::transaction(function () use ($prefix, $updateTime, $rows) { foreach ($rows as $row) { From 53010244aa45519d54a1752c2552ff84eff01925 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Thu, 9 Nov 2023 09:10:01 +0000 Subject: [PATCH 03/26] Tax breakdown state update should use the specified DB connection (#1325) --- .../database/state/ConvertTaxbreakdown.php | 88 ++++++++++--------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/packages/core/database/state/ConvertTaxbreakdown.php b/packages/core/database/state/ConvertTaxbreakdown.php index 45ba637c27..3b5e015210 100644 --- a/packages/core/database/state/ConvertTaxbreakdown.php +++ b/packages/core/database/state/ConvertTaxbreakdown.php @@ -14,49 +14,20 @@ public function prepare() public function run() { - $prefix = config('lunar.database.table_prefix'); - $updateTime = now(); - - if ($this->canRunOnOrders()) { - DB::table("{$prefix}orders") - ->whereJsonContainsKey("{$prefix}orders.tax_breakdown->[0]->total") - ->orderBy('id') - ->chunk(500, function ($rows) use ($prefix, $updateTime) { - foreach ($rows as $row) { - $originalBreakdown = json_decode($row->tax_breakdown, true); - - DB::table("{$prefix}orders")->where('id', '=', $row->id)->update([ - 'tax_breakdown' => collect($originalBreakdown)->map(function ($breakdown) use ($row) { - return [ - 'description' => $breakdown['description'], - 'identifier' => $breakdown['identifier'] ?? $breakdown['description'], - 'percentage' => $breakdown['percentage'], - 'value' => $breakdown['total'], - 'currency_code' => $row->currency_code, - ]; - })->toJson(), - 'updated_at' => $updateTime, - ]); - } - }); - } - - if ($this->canRunOnOrderLines()) { - DB::table("{$prefix}order_lines") - ->whereJsonContainsKey("{$prefix}order_lines.tax_breakdown->[0]->total") - ->orderBy("{$prefix}order_lines.id") - ->select( - "{$prefix}order_lines.id", - "{$prefix}order_lines.tax_breakdown", - "{$prefix}orders.currency_code", - ) - ->join("{$prefix}orders", "{$prefix}order_lines.order_id", '=', "{$prefix}orders.id") - ->chunk(500, function ($rows) use ($prefix, $updateTime) { - DB::transaction(function () use ($prefix, $updateTime, $rows) { + DB::usingConnection(config('lunar.database.connection') ?: DB::getDefaultConnection(), function () { + + $prefix = config('lunar.database.table_prefix'); + $updateTime = now(); + + if ($this->canRunOnOrders()) { + DB::table("{$prefix}orders") + ->whereJsonContainsKey("${prefix}orders.tax_breakdown->[0]->total") + ->orderBy('id') + ->chunk(500, function ($rows) use ($prefix, $updateTime) { foreach ($rows as $row) { $originalBreakdown = json_decode($row->tax_breakdown, true); - DB::table("{$prefix}order_lines")->where('id', '=', $row->id)->update([ + DB::table("{$prefix}orders")->where('id', '=', $row->id)->update([ 'tax_breakdown' => collect($originalBreakdown)->map(function ($breakdown) use ($row) { return [ 'description' => $breakdown['description'], @@ -70,8 +41,41 @@ public function run() ]); } }); - }); - } + } + + if ($this->canRunOnOrderLines()) { + DB::table("{$prefix}order_lines") + ->whereJsonContainsKey("${prefix}order_lines.tax_breakdown->[0]->total") + ->orderBy("${prefix}order_lines.id") + ->select( + "${prefix}order_lines.id", + "${prefix}order_lines.tax_breakdown", + "${prefix}orders.currency_code", + ) + ->join("${prefix}orders", "${prefix}order_lines.order_id", '=', "${prefix}orders.id") + ->chunk(500, function ($rows) use ($prefix, $updateTime) { + DB::transaction(function () use ($prefix, $updateTime, $rows) { + foreach ($rows as $row) { + $originalBreakdown = json_decode($row->tax_breakdown, true); + + DB::table("{$prefix}order_lines")->where('id', '=', $row->id)->update([ + 'tax_breakdown' => collect($originalBreakdown)->map(function ($breakdown) use ($row) { + return [ + 'description' => $breakdown['description'], + 'identifier' => $breakdown['identifier'] ?? $breakdown['description'], + 'percentage' => $breakdown['percentage'], + 'value' => $breakdown['total'], + 'currency_code' => $row->currency_code, + ]; + })->toJson(), + 'updated_at' => $updateTime, + ]); + } + }); + }); + } + + }); } protected function canRunOnOrders() From 6060b235a4fd19340b1cd0803ccf3a03031e9432 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Fri, 10 Nov 2023 12:37:52 +0000 Subject: [PATCH 04/26] Fix bad merge on discount limitations (#1332) --- .../Components/Discounts/AbstractDiscount.php | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php b/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php index 9705c60068..a1527a80a1 100644 --- a/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php +++ b/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php @@ -134,13 +134,6 @@ public function mount() ->map(function ($limitation) { return array_merge($this->mapProductVariantToArray($limitation->purchasable), ['type' => $limitation->type]); }); - - $this->selectedProductVariants = $this->discount->purchasableLimitations() - ->wherePurchasableType(ProductVariant::class) - ->get() - ->map(function ($limitation) { - return $this->mapProductVariantToArray($limitation->purchasable); - }); $this->selectedConditions = $this->discount->purchasableConditions() ->wherePurchasableType(Product::class) @@ -454,20 +447,6 @@ public function save() ]) ->save(); } - - $this->discount->purchasableLimitations() - ->where('purchasable_type', ProductVariant::class) - ->whereNotIn('purchasable_id', $this->selectedProductVariants->pluck('id')) - ->delete(); - - foreach ($this->selectedProductVariants as $variant) { - $this->discount->purchasableLimitations()->firstOrCreate([ - 'discount_id' => $this->discount->id, - 'type' => 'limitation', - 'purchasable_type' => ProductVariant::class, - 'purchasable_id' => $variant['id'], - ]); - } }); $this->emit('discount.saved', $this->discount->id); From 8416c0b3ebebe343c998acaadb12e722a76a8581 Mon Sep 17 00:00:00 2001 From: netzknecht <38781482+netzknecht@users.noreply.github.com> Date: Fri, 10 Nov 2023 15:33:18 +0100 Subject: [PATCH 05/26] Avoid deprecation notices on update to lunar 0.7 (#1333) --- .../core/database/state/ConvertTaxbreakdown.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/core/database/state/ConvertTaxbreakdown.php b/packages/core/database/state/ConvertTaxbreakdown.php index 3b5e015210..e3fbf6a505 100644 --- a/packages/core/database/state/ConvertTaxbreakdown.php +++ b/packages/core/database/state/ConvertTaxbreakdown.php @@ -21,7 +21,7 @@ public function run() if ($this->canRunOnOrders()) { DB::table("{$prefix}orders") - ->whereJsonContainsKey("${prefix}orders.tax_breakdown->[0]->total") + ->whereJsonContainsKey("{$prefix}orders.tax_breakdown->[0]->total") ->orderBy('id') ->chunk(500, function ($rows) use ($prefix, $updateTime) { foreach ($rows as $row) { @@ -45,14 +45,14 @@ public function run() if ($this->canRunOnOrderLines()) { DB::table("{$prefix}order_lines") - ->whereJsonContainsKey("${prefix}order_lines.tax_breakdown->[0]->total") - ->orderBy("${prefix}order_lines.id") + ->whereJsonContainsKey("{$prefix}order_lines.tax_breakdown->[0]->total") + ->orderBy("{$prefix}order_lines.id") ->select( - "${prefix}order_lines.id", - "${prefix}order_lines.tax_breakdown", - "${prefix}orders.currency_code", + "{$prefix}order_lines.id", + "{$prefix}order_lines.tax_breakdown", + "{$prefix}orders.currency_code", ) - ->join("${prefix}orders", "${prefix}order_lines.order_id", '=', "${prefix}orders.id") + ->join("{$prefix}orders", "{$prefix}order_lines.order_id", '=', "{$prefix}orders.id") ->chunk(500, function ($rows) use ($prefix, $updateTime) { DB::transaction(function () use ($prefix, $updateTime, $rows) { foreach ($rows as $row) { From c456c783cde72cb58ea6e588e864883da7b0db4e Mon Sep 17 00:00:00 2001 From: David Date: Wed, 15 Nov 2023 15:20:00 +0100 Subject: [PATCH 06/26] Updating type annotations in models and traits (#1336) --- .../Base/Traits/CanScheduleAvailability.php | 5 +- packages/core/src/Base/Traits/HasPrices.php | 12 +-- packages/core/src/Base/Traits/HasTags.php | 5 +- packages/core/src/Base/Traits/HasUrls.php | 6 +- packages/core/src/Base/Traits/LunarUser.php | 5 +- packages/core/src/Models/Address.php | 9 +- packages/core/src/Models/Asset.php | 5 +- packages/core/src/Models/AttributeGroup.php | 5 +- packages/core/src/Models/Brand.php | 5 +- packages/core/src/Models/Cart.php | 100 +++++------------- packages/core/src/Models/CartAddress.php | 11 +- packages/core/src/Models/CartLine.php | 21 ++-- packages/core/src/Models/Channel.php | 8 +- packages/core/src/Models/Collection.php | 15 +-- packages/core/src/Models/CollectionGroup.php | 6 +- packages/core/src/Models/Country.php | 5 +- packages/core/src/Models/Currency.php | 8 +- packages/core/src/Models/Customer.php | 24 ++--- packages/core/src/Models/CustomerGroup.php | 5 +- packages/core/src/Models/Discount.php | 53 +++++----- .../core/src/Models/DiscountCollection.php | 12 +-- .../core/src/Models/DiscountPurchasable.php | 18 ++-- packages/core/src/Models/Language.php | 4 +- packages/core/src/Models/Order.php | 75 ++++--------- packages/core/src/Models/OrderAddress.php | 9 +- packages/core/src/Models/OrderLine.php | 15 ++- packages/core/src/Models/Price.php | 26 ++--- packages/core/src/Models/Product.php | 57 +++------- .../core/src/Models/ProductAssociation.php | 34 ++---- packages/core/src/Models/ProductOption.php | 9 +- .../core/src/Models/ProductOptionValue.php | 14 +-- packages/core/src/Models/ProductType.php | 18 ++-- packages/core/src/Models/ProductVariant.php | 32 +++--- packages/core/src/Models/State.php | 5 +- packages/core/src/Models/Tag.php | 4 +- packages/core/src/Models/TaxClass.php | 9 +- packages/core/src/Models/TaxRate.php | 10 +- packages/core/src/Models/TaxRateAmount.php | 9 +- packages/core/src/Models/TaxZone.php | 26 ++--- packages/core/src/Models/TaxZoneCountry.php | 9 +- .../core/src/Models/TaxZoneCustomerGroup.php | 9 +- packages/core/src/Models/TaxZonePostcode.php | 9 +- packages/core/src/Models/TaxZoneState.php | 9 +- packages/core/src/Models/Transaction.php | 10 +- packages/core/src/Models/Url.php | 16 ++- 45 files changed, 280 insertions(+), 481 deletions(-) diff --git a/packages/core/src/Base/Traits/CanScheduleAvailability.php b/packages/core/src/Base/Traits/CanScheduleAvailability.php index 0ab9743bf6..b7a9fb7f46 100644 --- a/packages/core/src/Base/Traits/CanScheduleAvailability.php +++ b/packages/core/src/Base/Traits/CanScheduleAvailability.php @@ -83,11 +83,8 @@ protected function unschedule(Relation $relation, $models, array $pivotData = [] /** * Returns the data for the sync update. - * - * @param \Illuminate\Support\Collection $models - * @return \Illuminate\Support\Collection */ - private function getScheduleMapping($models, array $pivotData = null) + private function getScheduleMapping(Collection $models, array $pivotData = null): Collection { return $models->mapWithKeys(function ($model) use ($pivotData) { return [ diff --git a/packages/core/src/Base/Traits/HasPrices.php b/packages/core/src/Base/Traits/HasPrices.php index 7760ac3cf3..b72065b51c 100644 --- a/packages/core/src/Base/Traits/HasPrices.php +++ b/packages/core/src/Base/Traits/HasPrices.php @@ -2,7 +2,9 @@ namespace Lunar\Base\Traits; +use Illuminate\Database\Eloquent\Relations\MorphMany; use Lunar\Facades\Pricing; +use Lunar\Managers\PricingManager; use Lunar\Models\Price; trait HasPrices @@ -10,7 +12,7 @@ trait HasPrices /** * Get all of the models prices. */ - public function prices() + public function prices(): MorphMany { return $this->morphMany( Price::class, @@ -20,20 +22,16 @@ public function prices() /** * Return base prices query. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphMany */ - public function basePrices() + public function basePrices(): MorphMany { return $this->prices()->whereTier(1)->whereNull('customer_group_id'); } /** * Return a PricingManager for this model. - * - * @return \Lunar\Managers\PricingManager */ - public function pricing() + public function pricing(): PricingManager { return Pricing::for($this); } diff --git a/packages/core/src/Base/Traits/HasTags.php b/packages/core/src/Base/Traits/HasTags.php index 5554ee6b35..27a1e35a36 100644 --- a/packages/core/src/Base/Traits/HasTags.php +++ b/packages/core/src/Base/Traits/HasTags.php @@ -2,6 +2,7 @@ namespace Lunar\Base\Traits; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Support\Collection; use Lunar\Jobs\SyncTags; use Lunar\Models\Tag; @@ -10,10 +11,8 @@ trait HasTags { /** * Get the tags - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function tags() + public function tags(): MorphToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Base/Traits/HasUrls.php b/packages/core/src/Base/Traits/HasUrls.php index 642c999a33..a8de3b653f 100644 --- a/packages/core/src/Base/Traits/HasUrls.php +++ b/packages/core/src/Base/Traits/HasUrls.php @@ -3,6 +3,8 @@ namespace Lunar\Base\Traits; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\MorphMany; +use Illuminate\Database\Eloquent\Relations\MorphOne; use Lunar\Models\Url; trait HasUrls @@ -31,7 +33,7 @@ public static function bootHasUrls() /** * Get all of the models urls. */ - public function urls() + public function urls(): MorphMany { return $this->morphMany( Url::class, @@ -39,7 +41,7 @@ public function urls() ); } - public function defaultUrl() + public function defaultUrl(): MorphOne { return $this->morphOne( Url::class, diff --git a/packages/core/src/Base/Traits/LunarUser.php b/packages/core/src/Base/Traits/LunarUser.php index a6171d8762..c365752cd0 100644 --- a/packages/core/src/Base/Traits/LunarUser.php +++ b/packages/core/src/Base/Traits/LunarUser.php @@ -2,20 +2,21 @@ namespace Lunar\Base\Traits; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Models\Customer; use Lunar\Models\Order; trait LunarUser { - public function customers() + public function customers(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); return $this->belongsToMany(Customer::class, "{$prefix}customer_user"); } - public function latestCustomer() + public function latestCustomer(): ?Customer { return $this->customers()->orderBy('created_at', 'desc')->orderBy('id', 'desc')->first(); } diff --git a/packages/core/src/Models/Address.php b/packages/core/src/Models/Address.php index 3baf3bdd9b..0f75f97e1a 100644 --- a/packages/core/src/Models/Address.php +++ b/packages/core/src/Models/Address.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\Addressable; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; @@ -66,20 +67,16 @@ protected static function newFactory(): AddressFactory /** * Return the country relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } /** * Return the customer relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customer() + public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } diff --git a/packages/core/src/Models/Asset.php b/packages/core/src/Models/Asset.php index 260de9817d..1c76200e9c 100644 --- a/packages/core/src/Models/Asset.php +++ b/packages/core/src/Models/Asset.php @@ -2,6 +2,7 @@ namespace Lunar\Models; +use Illuminate\Database\Eloquent\Relations\MorphOne; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMedia as TraitsHasMedia; use Spatie\MediaLibrary\HasMedia; @@ -25,10 +26,8 @@ class Asset extends BaseModel implements HasMedia /** * Get the associated file. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphOne */ - public function file() + public function file(): MorphOne { return $this->morphOne(config('media-library.media_model'), 'model'); } diff --git a/packages/core/src/Models/AttributeGroup.php b/packages/core/src/Models/AttributeGroup.php index 54ceab15cf..5dfdffdb62 100644 --- a/packages/core/src/Models/AttributeGroup.php +++ b/packages/core/src/Models/AttributeGroup.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Casts\AsCollection; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Base\Traits\HasTranslations; @@ -51,10 +52,8 @@ protected static function newFactory(): AttributeGroupFactory /** * Return the attributes relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function attributes() + public function attributes(): HasMany { return $this->hasMany(Attribute::class)->orderBy('position'); } diff --git a/packages/core/src/Models/Brand.php b/packages/core/src/Models/Brand.php index d1aff03b85..3c74434e60 100644 --- a/packages/core/src/Models/Brand.php +++ b/packages/core/src/Models/Brand.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; use Lunar\Base\Traits\HasAttributes; @@ -56,10 +57,8 @@ protected static function newFactory(): BrandFactory /** * Get the mapped attributes relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function mappedAttributes() + public function mappedAttributes(): MorphToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Models/Cart.php b/packages/core/src/Models/Cart.php index 1cebeb8c81..a536616b84 100644 --- a/packages/core/src/Models/Cart.php +++ b/packages/core/src/Models/Cart.php @@ -6,6 +6,9 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Foundation\Auth\User; use Illuminate\Pipeline\Pipeline; use Illuminate\Support\Collection; @@ -194,40 +197,32 @@ protected static function newFactory(): CartFactory /** * Return the cart lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function lines() + public function lines(): HasMany { return $this->hasMany(CartLine::class, 'cart_id', 'id'); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function currency() + public function currency(): BelongsTo { return $this->belongsTo(Currency::class); } /** * Return the user relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function user() + public function user(): BelongsTo { return $this->belongsTo(config('auth.providers.users.model')); } /** * Return the customer relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customer() + public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } @@ -239,40 +234,32 @@ public function scopeUnmerged($query) /** * Return the addresses relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function addresses() + public function addresses(): HasMany { return $this->hasMany(CartAddress::class, 'cart_id'); } /** * Return the shipping address relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function shippingAddress() + public function shippingAddress(): HasOne { return $this->hasOne(CartAddress::class, 'cart_id')->whereType('shipping'); } /** * Return the billing address relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function billingAddress() + public function billingAddress(): HasOne { return $this->hasOne(CartAddress::class, 'cart_id')->whereType('billing'); } /** * Return the order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function orders() + public function orders(): HasMany { return $this->hasMany(Order::class); } @@ -291,10 +278,8 @@ public function scopeActive(Builder $query) /** * Return the draft order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function draftOrder(int $draftOrderId = null) + public function draftOrder(int $draftOrderId = null): HasOne { return $this->hasOne(Order::class) ->when($draftOrderId, function (Builder $query, int $draftOrderId) { @@ -304,10 +289,8 @@ public function draftOrder(int $draftOrderId = null) /** * Return the completed order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function completedOrder(int $completedOrderId = null) + public function completedOrder(int $completedOrderId = null): HasOne { return $this->hasOne(Order::class) ->when($completedOrderId, function (Builder $query, int $completedOrderId) { @@ -317,10 +300,8 @@ public function completedOrder(int $completedOrderId = null) /** * Return the carts completed order. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function completedOrders() + public function completedOrders(): HasMany { return $this->hasMany(Order::class) ->whereNotNull('placed_at'); @@ -328,10 +309,8 @@ public function completedOrders() /** * Return whether the cart has any completed order. - * - * @return bool */ - public function hasCompletedOrders() + public function hasCompletedOrders(): bool { return (bool) $this->completedOrders()->count(); } @@ -375,10 +354,8 @@ public function add(Purchasable $purchasable, int $quantity = 1, array $meta = [ /** * Add cart lines. - * - * @return bool */ - public function addLines(iterable $lines) + public function addLines(iterable $lines): Cart { DB::transaction(function () use ($lines) { collect($lines)->each(function ($line) { @@ -414,10 +391,8 @@ public function remove(int $cartLineId, bool $refresh = true): Cart /** * Update cart line - * - * @param array $meta */ - public function updateLine(int $cartLineId, int $quantity, $meta = null, bool $refresh = true): Cart + public function updateLine(int $cartLineId, int $quantity, array $meta = null, bool $refresh = true): Cart { foreach (config('lunar.cart.validators.update_cart_line', []) as $action) { app($action)->using( @@ -436,10 +411,8 @@ public function updateLine(int $cartLineId, int $quantity, $meta = null, bool $r /** * Update cart lines. - * - * @return \Lunar\Models\Cart */ - public function updateLines(Collection $lines) + public function updateLines(Collection $lines): Cart { DB::transaction(function () use ($lines) { $lines->each(function ($line) { @@ -458,7 +431,7 @@ public function updateLines(Collection $lines) /** * Deletes all cart lines. */ - public function clear() + public function clear(): Cart { $this->lines()->delete(); @@ -467,12 +440,8 @@ public function clear() /** * Associate a user to the cart - * - * @param string $policy - * @param bool $refresh - * @return Cart */ - public function associate(User $user, $policy = 'merge', $refresh = true) + public function associate(User $user, string $policy = 'merge', bool $refresh = true): Cart { if ($this->customer()->exists()) { if (! $user->query() @@ -527,20 +496,16 @@ public function addAddress(array|Addressable $address, string $type, bool $refre /** * Set the shipping address. - * - * @return \Lunar\Models\Cart */ - public function setShippingAddress(array|Addressable $address) + public function setShippingAddress(array|Addressable $address): Cart { return $this->addAddress($address, 'shipping'); } /** * Set the billing address. - * - * @return self */ - public function setBillingAddress(array|Addressable $address) + public function setBillingAddress(array|Addressable $address): Cart { return $this->addAddress($address, 'billing'); } @@ -548,7 +513,7 @@ public function setBillingAddress(array|Addressable $address) /** * Set the shipping option to the shipping address. */ - public function setShippingOption(ShippingOption $option, $refresh = true): Cart + public function setShippingOption(ShippingOption $option, bool $refresh = true): Cart { foreach (config('lunar.cart.validators.set_shipping_option', []) as $action) { app($action)->using( @@ -573,10 +538,8 @@ public function getShippingOption(): ?ShippingOption /** * Returns whether the cart has shippable items. - * - * @return bool */ - public function isShippable() + public function isShippable(): bool { return (bool) $this->lines->filter(function ($line) { return $line->purchasable->isShippable(); @@ -585,8 +548,6 @@ public function isShippable() /** * Create an order from the Cart. - * - * @return Cart */ public function createOrder( bool $allowMultipleOrders = false, @@ -611,10 +572,8 @@ public function createOrder( /** * Returns whether a cart has enough info to create an order. - * - * @return bool */ - public function canCreateOrder() + public function canCreateOrder(): bool { $passes = true; @@ -635,10 +594,8 @@ public function canCreateOrder() /** * Get a unique fingerprint for the cart to identify if the contents have changed. - * - * @return string */ - public function fingerprint() + public function fingerprint(): string { $generator = config('lunar.cart.fingerprint_generator', GenerateFingerprint::class); @@ -648,12 +605,9 @@ public function fingerprint() /** * Check whether a given fingerprint matches the one being generated for the cart. * - * @param string $fingerprint - * @return bool - * * @throws FingerprintMismatchException */ - public function checkFingerprint($fingerprint) + public function checkFingerprint(string $fingerprint): bool { return tap($fingerprint == $this->fingerprint(), function ($result) { throw_unless( diff --git a/packages/core/src/Models/CartAddress.php b/packages/core/src/Models/CartAddress.php index 83c210b317..3843d59105 100644 --- a/packages/core/src/Models/CartAddress.php +++ b/packages/core/src/Models/CartAddress.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\Addressable; use Lunar\Base\BaseModel; use Lunar\Base\Traits\CachesProperties; @@ -79,8 +80,6 @@ class CartAddress extends BaseModel implements Addressable /** * The tax breakdown. - * - * @var TaxBreakdown */ public ?TaxBreakdown $taxBreakdown = null; @@ -129,20 +128,16 @@ protected static function newFactory(): CartAddressFactory /** * Return the cart relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function cart() + public function cart(): BelongsTo { return $this->belongsTo(Cart::class); } /** * Return the country relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/CartLine.php b/packages/core/src/Models/CartLine.php index eea2fb39a7..5a3dc99935 100644 --- a/packages/core/src/Models/CartLine.php +++ b/packages/core/src/Models/CartLine.php @@ -4,6 +4,10 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\CachesProperties; use Lunar\Base\Traits\HasMacros; @@ -112,20 +116,16 @@ protected static function newFactory(): CartLineFactory /** * Return the cart relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function cart() + public function cart(): BelongsTo { return $this->belongsTo(Cart::class); } /** * Return the tax class relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOneThrough */ - public function taxClass() + public function taxClass(): HasOneThrough { return $this->hasOneThrough( TaxClass::class, @@ -135,7 +135,10 @@ public function taxClass() ); } - public function discounts() + /** + * Return the cart line discount. + */ + public function discounts(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -147,10 +150,8 @@ public function discounts() /** * Return the polymorphic relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function purchasable() + public function purchasable(): MorphTo { return $this->morphTo(); } diff --git a/packages/core/src/Models/Channel.php b/packages/core/src/Models/Channel.php index 996a9c82af..a89b613eb3 100644 --- a/packages/core/src/Models/Channel.php +++ b/packages/core/src/Models/Channel.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Str; use Lunar\Base\BaseModel; @@ -47,11 +48,8 @@ protected static function newFactory(): ChannelFactory /** * Mutator for formatting the handle to a slug. - * - * @param string $val - * @return void */ - public function setHandleAttribute($val) + public function setHandleAttribute(?string $val): void { $this->attributes['handle'] = Str::slug($val); } @@ -59,7 +57,7 @@ public function setHandleAttribute($val) /** * Get the parent channelable model. */ - public function channelable() + public function channelable(): MorphTo { return $this->morphTo(); } diff --git a/packages/core/src/Models/Collection.php b/packages/core/src/Models/Collection.php index d80e2505af..830573992a 100644 --- a/packages/core/src/Models/Collection.php +++ b/packages/core/src/Models/Collection.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Kalnoy\Nestedset\NodeTrait; use Lunar\Base\BaseModel; @@ -66,25 +67,21 @@ protected static function newFactory(): CollectionFactory /** * Return the group relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function group() + public function group(): BelongsTo { return $this->belongsTo(CollectionGroup::class, 'collection_group_id'); } - public function scopeInGroup(Builder $builder, $id) + public function scopeInGroup(Builder $builder, int $id): Builder { return $builder->where('collection_group_id', $id); } /** * Return the products relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function products() + public function products(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -98,10 +95,8 @@ public function products() /** * Get the translated name of ancestor collections. - * - * @return Illuminate\Support\Collection */ - public function getBreadcrumbAttribute() + public function getBreadcrumbAttribute(): \Illuminate\Support\Collection { return $this->ancestors->map(function ($ancestor) { return $ancestor->translateAttribute('name'); diff --git a/packages/core/src/Models/CollectionGroup.php b/packages/core/src/Models/CollectionGroup.php index 05b23737be..1b93149dee 100644 --- a/packages/core/src/Models/CollectionGroup.php +++ b/packages/core/src/Models/CollectionGroup.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\CollectionGroupFactory; @@ -29,7 +30,10 @@ protected static function newFactory(): CollectionGroupFactory return CollectionGroupFactory::new(); } - public function collections() + /** + * Return the collections relationship. + */ + public function collections(): HasMany { return $this->hasMany(Collection::class); } diff --git a/packages/core/src/Models/Country.php b/packages/core/src/Models/Country.php index 7c8eb492d0..3b5247d03d 100644 --- a/packages/core/src/Models/Country.php +++ b/packages/core/src/Models/Country.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\CountryFactory; @@ -44,10 +45,8 @@ protected static function newFactory(): CountryFactory /** * Return the states relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function states() + public function states(): HasMany { return $this->hasMany(State::class); } diff --git a/packages/core/src/Models/Currency.php b/packages/core/src/Models/Currency.php index 9a8cd3e646..416bd511ba 100644 --- a/packages/core/src/Models/Currency.php +++ b/packages/core/src/Models/Currency.php @@ -46,10 +46,8 @@ protected static function newFactory(): CurrencyFactory /** * Return the prices relationship - * - * @return HasMany */ - public function prices() + public function prices(): HasMany { return $this->hasMany(Price::class); } @@ -57,10 +55,8 @@ public function prices() /** * Returns the amount we need to multiply or divide the price * for the cents/pence. - * - * @return string */ - public function getFactorAttribute() + public function getFactorAttribute(): string { /** * If we figure out how many decimal places we need, we can work diff --git a/packages/core/src/Models/Customer.php b/packages/core/src/Models/Customer.php index 5acbfafa23..f03c8dbddc 100644 --- a/packages/core/src/Models/Customer.php +++ b/packages/core/src/Models/Customer.php @@ -4,6 +4,9 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; use Lunar\Base\Traits\HasAttributes; @@ -60,10 +63,8 @@ protected static function newFactory(): CustomerFactory /** * Return the customer group relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function customerGroups() + public function customerGroups(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -75,10 +76,8 @@ public function customerGroups() /** * Return the customer group relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function users() + public function users(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -90,25 +89,24 @@ public function users() /** * Return the addresses relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function addresses() + public function addresses(): HasMany { return $this->hasMany(Address::class); } - public function orders() + /** + * Return the orders relationship. + */ + public function orders(): HasMany { return $this->hasMany(Order::class); } /** * Get the mapped attributes relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function mappedAttributes() + public function mappedAttributes(): MorphToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Models/CustomerGroup.php b/packages/core/src/Models/CustomerGroup.php index 5994b92899..b785109082 100644 --- a/packages/core/src/Models/CustomerGroup.php +++ b/packages/core/src/Models/CustomerGroup.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasDefaultRecord; use Lunar\Base\Traits\HasMacros; @@ -37,10 +38,8 @@ protected static function newFactory(): CustomerGroupFactory /** * Return the customer's relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function customers() + public function customers(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Models/Discount.php b/packages/core/src/Models/Discount.php index 3dce32b662..88471e58e7 100644 --- a/packages/core/src/Models/Discount.php +++ b/packages/core/src/Models/Discount.php @@ -55,7 +55,7 @@ protected static function newFactory(): DiscountFactory return DiscountFactory::new(); } - public function users() + public function users(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -67,30 +67,40 @@ public function users() /** * Return the purchasables relationship. - * - * @return HasMany */ - public function purchasables() + public function purchasables(): HasMany { return $this->hasMany(DiscountPurchasable::class); } - public function purchasableConditions() + /** + * Return the purchasable conditions relationship. + */ + public function purchasableConditions(): HasMany { return $this->hasMany(DiscountPurchasable::class)->whereType('condition'); } - - public function purchasableExclusions() + + /** + * Return the purchasable exclusions relationship. + */ + public function purchasableExclusions(): HasMany { return $this->hasMany(DiscountPurchasable::class)->whereType('exclusion'); } - public function purchasableLimitations() + /** + * Return the purchasable limitations relationship. + */ + public function purchasableLimitations(): HasMany { return $this->hasMany(DiscountPurchasable::class)->whereType('limitation'); } - public function purchasableRewards() + /** + * Return the purchasable rewards relationship. + */ + public function purchasableRewards(): HasMany { return $this->hasMany(DiscountPurchasable::class)->whereType('reward'); } @@ -102,10 +112,8 @@ public function getType() /** * Return the collections relationship. - * - * @return HasMany */ - public function collections() + public function collections(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -133,7 +141,7 @@ public function customerGroups(): BelongsToMany ])->withTimestamps(); } - public function brands() + public function brands(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -145,10 +153,8 @@ public function brands() /** * Return the active scope. - * - * @return Builder */ - public function scopeActive(Builder $query) + public function scopeActive(Builder $query): Builder { return $query->whereNotNull('starts_at') ->where('starts_at', '<=', now()) @@ -160,10 +166,8 @@ public function scopeActive(Builder $query) /** * Return the products scope. - * - * @return Builder */ - public function scopeProducts(Builder $query, iterable $productIds = [], string $type = null) + public function scopeProducts(Builder $query, iterable $productIds = [], string $type = null): Builder { if (is_array($productIds)) { $productIds = collect($productIds); @@ -181,13 +185,11 @@ public function scopeProducts(Builder $query, iterable $productIds = [], string ) ); } - + /** * Return the product variants scope. - * - * @return Builder */ - public function scopeProductVariants(Builder $query, iterable $variantIds = [], string $type = null) + public function scopeProductVariants(Builder $query, iterable $variantIds = [], string $type = null): Builder { if (is_array($variantIds)) { $variantIds = collect($variantIds); @@ -206,7 +208,10 @@ public function scopeProductVariants(Builder $query, iterable $variantIds = [], ); } - public function scopeUsable(Builder $query) + /** + * Return when the discount is usable. + */ + public function scopeUsable(Builder $query): Builder { return $query->where(function ($subQuery) { $subQuery->whereRaw('uses < max_uses') diff --git a/packages/core/src/Models/DiscountCollection.php b/packages/core/src/Models/DiscountCollection.php index 07c37170ae..ee971e23a8 100644 --- a/packages/core/src/Models/DiscountCollection.php +++ b/packages/core/src/Models/DiscountCollection.php @@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Database\Factories\DiscountPurchasableFactory; -use Lunar\Discounts\Database\Factories\DiscountFactory; class DiscountCollection extends BaseModel { @@ -26,8 +25,6 @@ class DiscountCollection extends BaseModel /** * Return a new factory instance for the model. - * - * @return DiscountFactory */ protected static function newFactory(): DiscountPurchasableFactory { @@ -36,15 +33,16 @@ protected static function newFactory(): DiscountPurchasableFactory /** * Return the discount relationship. - * - * @return BelongsTo */ - public function discount() + public function discount(): BelongsTo { return $this->belongsTo(Discount::class); } - public function collection() + /** + * Return the collection relationship. + */ + public function collection(): BelongsTo { return $this->belongsTo(Collection::class); } diff --git a/packages/core/src/Models/DiscountPurchasable.php b/packages/core/src/Models/DiscountPurchasable.php index 02c8a79e4b..9c2ac7ef16 100644 --- a/packages/core/src/Models/DiscountPurchasable.php +++ b/packages/core/src/Models/DiscountPurchasable.php @@ -4,9 +4,10 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Database\Factories\DiscountPurchasableFactory; -use Lunar\Discounts\Database\Factories\DiscountFactory; /** * @property int $id @@ -36,8 +37,6 @@ class DiscountPurchasable extends BaseModel /** * Return a new factory instance for the model. - * - * @return DiscountFactory */ protected static function newFactory(): DiscountPurchasableFactory { @@ -46,25 +45,24 @@ protected static function newFactory(): DiscountPurchasableFactory /** * Return the discount relationship. - * - * @return BelongsTo */ - public function discount() + public function discount(): BelongsTo { return $this->belongsTo(Discount::class); } /** * Return the priceable relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function purchasable() + public function purchasable(): MorphTo { return $this->morphTo(); } - public function scopeCondition(Builder $query) + /** + * Scope a query where type is condition. + */ + public function scopeCondition(Builder $query): void { $query->whereType('condition'); } diff --git a/packages/core/src/Models/Language.php b/packages/core/src/Models/Language.php index 5d0e9d2448..4e14d09742 100644 --- a/packages/core/src/Models/Language.php +++ b/packages/core/src/Models/Language.php @@ -41,10 +41,8 @@ protected static function newFactory(): LanguageFactory /** * Return the URLs relationship - * - * @return HasMany */ - public function urls() + public function urls(): HasMany { return $this->hasMany(Url::class); } diff --git a/packages/core/src/Models/Order.php b/packages/core/src/Models/Order.php index b33be914bc..0ec0318acc 100644 --- a/packages/core/src/Models/Order.php +++ b/packages/core/src/Models/Order.php @@ -4,6 +4,9 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOne; use Lunar\Base\BaseModel; use Lunar\Base\Casts\DiscountBreakdown; use Lunar\Base\Casts\Price; @@ -80,10 +83,8 @@ protected static function newFactory(): OrderFactory /** * Getter for status label. - * - * @return string */ - public function getStatusLabelAttribute() + public function getStatusLabelAttribute(): string { $statuses = config('lunar.orders.statuses'); @@ -92,170 +93,136 @@ public function getStatusLabelAttribute() /** * Return the channel relationship. - * - * @return void */ - public function channel() + public function channel(): BelongsTo { return $this->belongsTo(Channel::class); } /** * Return the cart relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function cart() + public function cart(): BelongsTo { return $this->belongsTo(Cart::class); } /** * Return the lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function lines() + public function lines(): HasMany { return $this->hasMany(OrderLine::class); } /** * Return physical product lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function physicalLines() + public function physicalLines(): HasMany { return $this->lines()->whereType('physical'); } /** * Return digital product lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function digitalLines() + public function digitalLines(): HasMany { return $this->lines()->whereType('digital'); } /** * Return shipping lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function shippingLines() + public function shippingLines(): HasMany { return $this->lines()->whereType('shipping'); } /** * Return product lines relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function productLines() + public function productLines(): HasMany { return $this->lines()->where('type', '!=', 'shipping'); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function currency() + public function currency(): BelongsTo { return $this->belongsTo(Currency::class, 'currency_code', 'code'); } /** * Return the addresses relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function addresses() + public function addresses(): HasMany { return $this->hasMany(OrderAddress::class, 'order_id'); } /** * Return the shipping address relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function shippingAddress() + public function shippingAddress(): HasOne { return $this->hasOne(OrderAddress::class, 'order_id')->whereType('shipping'); } /** * Return the billing address relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOne */ - public function billingAddress() + public function billingAddress(): HasOne { return $this->hasOne(OrderAddress::class, 'order_id')->whereType('billing'); } /** * Return the transactions relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function transactions() + public function transactions(): HasMany { return $this->hasMany(Transaction::class); } /** * Return the charges relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function captures() + public function captures(): HasMany { return $this->transactions()->whereType('capture'); } /** * Return the charges relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function intents() + public function intents(): HasMany { return $this->transactions()->whereType('intent'); } /** * Return the refunds relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function refunds() + public function refunds(): HasMany { return $this->transactions()->whereType('refund'); } /** * Return the customer relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customer() + public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } /** * Return the user relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function user() + public function user(): BelongsTo { return $this->belongsTo( config('auth.providers.users.model') diff --git a/packages/core/src/Models/OrderAddress.php b/packages/core/src/Models/OrderAddress.php index 4c94a49ced..e5e285e5a4 100644 --- a/packages/core/src/Models/OrderAddress.php +++ b/packages/core/src/Models/OrderAddress.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\Addressable; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; @@ -86,20 +87,16 @@ protected static function newFactory(): OrderAddressFactory /** * Return the order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function order() + public function order(): BelongsTo { return $this->belongsTo(Order::class); } /** * Return the country relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/OrderLine.php b/packages/core/src/Models/OrderLine.php index ca8ba65176..46890e1849 100644 --- a/packages/core/src/Models/OrderLine.php +++ b/packages/core/src/Models/OrderLine.php @@ -4,6 +4,9 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Base\Casts\Price; use Lunar\Base\Casts\TaxBreakdown; @@ -74,30 +77,24 @@ protected static function newFactory(): OrderLineFactory /** * Return the order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function order() + public function order(): BelongsTo { return $this->belongsTo(Order::class); } /** * Return the polymorphic relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function purchasable() + public function purchasable(): MorphTo { return $this->morphTo(); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOneThrough */ - public function currency() + public function currency(): HasOneThrough { return $this->hasOneThrough( Currency::class, diff --git a/packages/core/src/Models/Price.php b/packages/core/src/Models/Price.php index 47bcdb726c..5554ea0e26 100644 --- a/packages/core/src/Models/Price.php +++ b/packages/core/src/Models/Price.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Base\Casts\Price as CastsPrice; use Lunar\Base\Traits\HasMacros; @@ -49,40 +51,32 @@ protected static function newFactory(): PriceFactory /** * Return the priceable relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function priceable() + public function priceable(): MorphTo { return $this->morphTo(); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function currency() + public function currency(): BelongsTo { return $this->belongsTo(Currency::class); } /** * Return the customer group relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customerGroup() + public function customerGroup(): BelongsTo { return $this->belongsTo(CustomerGroup::class); } /** * Return the price exclusive of tax. - * - * @return \Lunar\DataTypes\Price */ - public function priceExTax() + public function priceExTax(): \Lunar\DataTypes\Price { if (! prices_inc_tax()) { return $this->price; @@ -97,10 +91,8 @@ public function priceExTax() /** * Return the price inclusive of tax. - * - * @return \Lunar\DataTypes\Price */ - public function priceIncTax() + public function priceIncTax(): int|\Lunar\DataTypes\Price { if (prices_inc_tax()) { return $this->price; @@ -114,10 +106,8 @@ public function priceIncTax() /** * Return the total tax rate amount within the predefined tax zone for the related priceable - * - * @return int|float */ - protected function getPriceableTaxRate() + protected function getPriceableTaxRate(): int|float { return Blink::once('price_tax_rate_'.$this->priceable->getTaxClass()->id, function () { $taxZone = TaxZone::where('default', '=', 1)->first(); diff --git a/packages/core/src/Models/Product.php b/packages/core/src/Models/Product.php index 8ff5e753de..795bc197f9 100644 --- a/packages/core/src/Models/Product.php +++ b/packages/core/src/Models/Product.php @@ -4,8 +4,12 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; +use Illuminate\Database\Eloquent\Relations\MorphMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Database\Eloquent\SoftDeletes; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; @@ -79,50 +83,40 @@ protected static function newFactory(): ProductFactory /** * Returns the attributes to be stored against this model. - * - * @return array */ - public function mappedAttributes() + public function mappedAttributes(): Collection { return $this->productType->mappedAttributes; } /** * Return the product type relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function productType() + public function productType(): BelongsTo { return $this->belongsTo(ProductType::class); } /** * Return the product images relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphMany */ - public function images() + public function images(): MorphMany { return $this->media()->where('collection_name', 'images'); } /** * Return the product variants relation. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function variants() + public function variants(): HasMany { return $this->hasMany(ProductVariant::class); } /** * Return the product collections relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function collections() + public function collections(): BelongsToMany { return $this->belongsToMany( Collection::class, @@ -132,44 +126,32 @@ public function collections() /** * Return the associations relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function associations() + public function associations(): HasMany { return $this->hasMany(ProductAssociation::class, 'product_parent_id'); } /** * Return the associations relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function inverseAssociations() + public function inverseAssociations(): HasMany { return $this->hasMany(ProductAssociation::class, 'product_target_id'); } /** * Associate a product to another with a type. - * - * @param mixed $product - * @param string $type - * @return void */ - public function associate($product, $type) + public function associate(mixed $product, string $type): void { Associate::dispatch($this, $product, $type); } /** * Dissociate a product to another with a type. - * - * @param mixed $product - * @param string $type - * @return void */ - public function dissociate($product, $type = null) + public function dissociate(mixed $product, string $type = null): void { Dissociate::dispatch($this, $product, $type); } @@ -195,31 +177,24 @@ public function customerGroups(): BelongsToMany /** * Return the brand relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function brand() + public function brand(): BelongsTo { return $this->belongsTo(Brand::class); } /** * Apply the status scope. - * - * @param string $status - * @return Builder */ - public function scopeStatus(Builder $query, $status) + public function scopeStatus(Builder $query, string $status): Builder { return $query->whereStatus($status); } /** * Return the prices relationship. - * - * @return HasManyThrough */ - public function prices() + public function prices(): HasManyThrough { return $this->hasManyThrough( Price::class, diff --git a/packages/core/src/Models/ProductAssociation.php b/packages/core/src/Models/ProductAssociation.php index c2b6d3f896..285b1623be 100644 --- a/packages/core/src/Models/ProductAssociation.php +++ b/packages/core/src/Models/ProductAssociation.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\ProductAssociationFactory; @@ -22,12 +23,12 @@ class ProductAssociation extends BaseModel use HasMacros; /** - * Define the cross sell type. + * Define the cross-sell type. */ const CROSS_SELL = 'cross-sell'; /** - * Define the up sell type. + * Define the upsell type. */ const UP_SELL = 'up-sell'; @@ -57,61 +58,48 @@ protected static function newFactory(): ProductAssociationFactory /** * Return the parent relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function parent() + public function parent(): BelongsTo { return $this->belongsTo(Product::class, 'product_parent_id'); } /** * Return the parent relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function target() + public function target(): BelongsTo { return $this->belongsTo(Product::class, 'product_target_id'); } /** - * Apply the cross sell scope. - * - * @return void + * Apply the cross-sell scope. */ - public function scopeCrossSell(Builder $query) + public function scopeCrossSell(Builder $query): void { $query->type(self::CROSS_SELL); } /** - * Apply the up sell scope. - * - * @return void + * Apply the upsell scope. */ - public function scopeUpSell(Builder $query) + public function scopeUpSell(Builder $query): void { $query->type(self::UP_SELL); } /** * Apply the up alternate scope. - * - * @return void */ - public function scopeAlternate(Builder $query) + public function scopeAlternate(Builder $query): void { $query->type(self::ALTERNATE); } /** * Apply the type scope. - * - * @param string $type - * @return void */ - public function scopeType(Builder $query, $type) + public function scopeType(Builder $query, string $type): Builder { return $query->whereType($type); } diff --git a/packages/core/src/Models/ProductOption.php b/packages/core/src/Models/ProductOption.php index bb90f21709..8bb7402a66 100644 --- a/packages/core/src/Models/ProductOption.php +++ b/packages/core/src/Models/ProductOption.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Casts\AsCollection; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Base\Traits\HasMedia; @@ -48,12 +49,12 @@ protected static function newFactory(): ProductOptionFactory return ProductOptionFactory::new(); } - public function getNameAttribute($value) + public function getNameAttribute(string $value): mixed { return json_decode($value); } - protected function setNameAttribute($value) + protected function setNameAttribute(mixed $value): void { $this->attributes['name'] = json_encode($value); } @@ -77,9 +78,9 @@ protected function label(): Attribute /** * Get the values. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ - public function values() + public function values(): HasMany { return $this->hasMany(ProductOptionValue::class)->orderBy('position'); } diff --git a/packages/core/src/Models/ProductOptionValue.php b/packages/core/src/Models/ProductOptionValue.php index cb450274c9..0f677b8920 100644 --- a/packages/core/src/Models/ProductOptionValue.php +++ b/packages/core/src/Models/ProductOptionValue.php @@ -4,6 +4,8 @@ use Illuminate\Database\Eloquent\Casts\AsCollection; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Base\Traits\HasMedia; @@ -51,22 +53,22 @@ protected static function newFactory(): ProductOptionValueFactory */ protected $guarded = []; - protected function setNameAttribute($value) + public function getNameAttribute(string $value): mixed { - $this->attributes['name'] = json_encode($value); + return json_decode($value); } - public function getNameAttribute($value) + protected function setNameAttribute(mixed $value): void { - return json_decode($value); + $this->attributes['name'] = json_encode($value); } - public function option() + public function option(): BelongsTo { return $this->belongsTo(ProductOption::class, 'product_option_id'); } - public function variants() + public function variants(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); diff --git a/packages/core/src/Models/ProductType.php b/packages/core/src/Models/ProductType.php index 02106b0baa..3f0baea3df 100644 --- a/packages/core/src/Models/ProductType.php +++ b/packages/core/src/Models/ProductType.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasAttributes; use Lunar\Base\Traits\HasMacros; @@ -38,10 +40,8 @@ protected static function newFactory(): ProductTypeFactory /** * Get the mapped attributes relation. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function mappedAttributes() + public function mappedAttributes(): MorphToMany { $prefix = config('lunar.database.table_prefix'); @@ -54,30 +54,24 @@ public function mappedAttributes() /** * Return the product attributes relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function productAttributes() + public function productAttributes(): MorphToMany { return $this->mappedAttributes()->whereAttributeType(Product::class); } /** * Return the variant attributes relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphToMany */ - public function variantAttributes() + public function variantAttributes(): MorphToMany { return $this->mappedAttributes()->whereAttributeType(ProductVariant::class); } /** * Get the products relation. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function products() + public function products(): HasMany { return $this->hasMany(Product::class); } diff --git a/packages/core/src/Models/ProductVariant.php b/packages/core/src/Models/ProductVariant.php index 53f16d66cb..61c78212cd 100644 --- a/packages/core/src/Models/ProductVariant.php +++ b/packages/core/src/Models/ProductVariant.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Support\Collection; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; @@ -79,30 +81,24 @@ protected static function newFactory(): ProductVariantFactory /** * The related product. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function product() + public function product(): BelongsTo { return $this->belongsTo(Product::class)->withTrashed(); } /** * Return the tax class relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxClass() + public function taxClass(): BelongsTo { return $this->belongsTo(TaxClass::class); } /** * Return the related product option values. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function values() + public function values(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -137,7 +133,7 @@ public function getTaxClass(): TaxClass }); } - public function getTaxReference() + public function getTaxReference(): ?string { return $this->tax_ref; } @@ -145,7 +141,7 @@ public function getTaxReference() /** * {@inheritDoc} */ - public function getType() + public function getType(): string { return $this->shippable ? 'physical' : 'digital'; } @@ -153,7 +149,7 @@ public function getType() /** * {@inheritDoc} */ - public function isShippable() + public function isShippable(): bool { return $this->shippable; } @@ -161,7 +157,7 @@ public function isShippable() /** * {@inheritDoc} */ - public function getDescription() + public function getDescription(): string { return $this->product->translateAttribute('name'); } @@ -169,7 +165,7 @@ public function getDescription() /** * {@inheritDoc} */ - public function getOption() + public function getOption(): string { return $this->values->map(fn ($value) => $value->translate('name'))->join(', '); } @@ -177,7 +173,7 @@ public function getOption() /** * {@inheritDoc} */ - public function getOptions() + public function getOptions(): Collection { return $this->values->map(fn ($value) => $value->translate('name')); } @@ -185,12 +181,12 @@ public function getOptions() /** * {@inheritDoc} */ - public function getIdentifier() + public function getIdentifier(): string { return $this->sku; } - public function images() + public function images(): BelongsToMany { $prefix = config('lunar.database.table_prefix'); @@ -200,7 +196,7 @@ public function images() ->withTimestamps(); } - public function getThumbnail() + public function getThumbnail(): ?Media { return $this->images->first(function ($media) { return (bool) $media->pivot?->primary; diff --git a/packages/core/src/Models/State.php b/packages/core/src/Models/State.php index 87a943ace8..362abf7deb 100644 --- a/packages/core/src/Models/State.php +++ b/packages/core/src/Models/State.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\StateFactory; @@ -38,10 +39,8 @@ protected static function newFactory(): StateFactory /** * Return the country relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/Tag.php b/packages/core/src/Models/Tag.php index 7b50089504..6b69397ff0 100644 --- a/packages/core/src/Models/Tag.php +++ b/packages/core/src/Models/Tag.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TagFactory; @@ -34,9 +35,8 @@ protected static function newFactory(): TagFactory */ protected $guarded = []; - public function taggable() + public function taggable(): MorphTo { return $this->morphTo(); } - } diff --git a/packages/core/src/Models/TaxClass.php b/packages/core/src/Models/TaxClass.php index 5331adc650..9c54609291 100644 --- a/packages/core/src/Models/TaxClass.php +++ b/packages/core/src/Models/TaxClass.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasDefaultRecord; use Lunar\Base\Traits\HasMacros; @@ -58,20 +59,16 @@ protected static function newFactory(): TaxClassFactory /** * Return the tax rate amounts relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function taxRateAmounts() + public function taxRateAmounts(): HasMany { return $this->hasMany(TaxRateAmount::class); } /** * Return the ProductVariants relationship. - * - * @return HasMany */ - public function productVariants() + public function productVariants(): HasMany { return $this->hasMany(ProductVariant::class); } diff --git a/packages/core/src/Models/TaxRate.php b/packages/core/src/Models/TaxRate.php index 7faebfb098..1e04eb33b1 100644 --- a/packages/core/src/Models/TaxRate.php +++ b/packages/core/src/Models/TaxRate.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxRateFactory; @@ -38,20 +40,16 @@ protected static function newFactory(): TaxRateFactory /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } /** * Return the tax rate amounts relation. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function taxRateAmounts() + public function taxRateAmounts(): HasMany { return $this->hasMany(TaxRateAmount::class); } diff --git a/packages/core/src/Models/TaxRateAmount.php b/packages/core/src/Models/TaxRateAmount.php index 90ad50d962..6113145653 100644 --- a/packages/core/src/Models/TaxRateAmount.php +++ b/packages/core/src/Models/TaxRateAmount.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxRateAmountFactory; @@ -45,20 +46,16 @@ protected static function newFactory(): TaxRateAmountFactory /** * Return the tax rate relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxRate() + public function taxRate(): BelongsTo { return $this->belongsTo(TaxRate::class); } /** * Return the tax class relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxClass() + public function taxClass(): BelongsTo { return $this->belongsTo(TaxClass::class); } diff --git a/packages/core/src/Models/TaxZone.php b/packages/core/src/Models/TaxZone.php index 0f653a7c99..0e64d550c1 100644 --- a/packages/core/src/Models/TaxZone.php +++ b/packages/core/src/Models/TaxZone.php @@ -3,6 +3,8 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasDefaultRecord; use Lunar\Base\Traits\HasMacros; @@ -52,60 +54,48 @@ protected static function newFactory(): TaxZoneFactory /** * Return the countries relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function countries() + public function countries(): HasMany { return $this->hasMany(TaxZoneCountry::class); } /** * Return the states relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function states() + public function states(): HasMany { return $this->hasMany(TaxZoneState::class); } /** * Return the postcodes relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function postcodes() + public function postcodes(): HasMany { return $this->hasMany(TaxZonePostcode::class); } /** * Return the customer groups relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function customerGroups() + public function customerGroups(): HasMany { return $this->hasMany(TaxZoneCustomerGroup::class); } /** * Return the tax rates relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function taxRates() + public function taxRates(): HasMany { return $this->hasMany(TaxRate::class); } /** * Return the tax amounts relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough */ - public function taxAmounts() + public function taxAmounts(): HasManyThrough { return $this->hasManyThrough(TaxRateAmount::class, TaxRate::class); } diff --git a/packages/core/src/Models/TaxZoneCountry.php b/packages/core/src/Models/TaxZoneCountry.php index 517ca82548..49fa7f4cd2 100644 --- a/packages/core/src/Models/TaxZoneCountry.php +++ b/packages/core/src/Models/TaxZoneCountry.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxZoneCountryFactory; @@ -37,20 +38,16 @@ protected static function newFactory(): TaxZoneCountryFactory /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } /** * Return the country relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/TaxZoneCustomerGroup.php b/packages/core/src/Models/TaxZoneCustomerGroup.php index 1f94965117..1bd4fa3bcc 100644 --- a/packages/core/src/Models/TaxZoneCustomerGroup.php +++ b/packages/core/src/Models/TaxZoneCustomerGroup.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxZoneCustomerGroupFactory; @@ -37,20 +38,16 @@ protected static function newFactory(): TaxZoneCustomerGroupFactory /** * Return the customer group relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function customerGroup() + public function customerGroup(): BelongsTo { return $this->belongsTo(CustomerGroup::class); } /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } diff --git a/packages/core/src/Models/TaxZonePostcode.php b/packages/core/src/Models/TaxZonePostcode.php index ad2b1c9fa2..a5ce608e09 100644 --- a/packages/core/src/Models/TaxZonePostcode.php +++ b/packages/core/src/Models/TaxZonePostcode.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxZonePostcodeFactory; @@ -38,20 +39,16 @@ protected static function newFactory(): TaxZonePostcodeFactory /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } /** * Return the country relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function country() + public function country(): BelongsTo { return $this->belongsTo(Country::class); } diff --git a/packages/core/src/Models/TaxZoneState.php b/packages/core/src/Models/TaxZoneState.php index 18ae418b55..e0fe32bf52 100644 --- a/packages/core/src/Models/TaxZoneState.php +++ b/packages/core/src/Models/TaxZoneState.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\TaxZoneStateFactory; @@ -37,20 +38,16 @@ protected static function newFactory(): TaxZoneStateFactory /** * Return the tax zone relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function taxZone() + public function taxZone(): BelongsTo { return $this->belongsTo(TaxZone::class); } /** * Return the state relation. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function state() + public function state(): BelongsTo { return $this->belongsTo(State::class); } diff --git a/packages/core/src/Models/Transaction.php b/packages/core/src/Models/Transaction.php index 6e3f03d22c..0386c5396e 100644 --- a/packages/core/src/Models/Transaction.php +++ b/packages/core/src/Models/Transaction.php @@ -4,6 +4,8 @@ use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; use Lunar\Base\BaseModel; use Lunar\Base\Casts\Price; use Lunar\Base\Traits\HasMacros; @@ -59,20 +61,16 @@ protected static function newFactory(): TransactionFactory /** * Return the order relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function order() + public function order(): BelongsTo { return $this->belongsTo(Order::class); } /** * Return the currency relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\HasOneThrough */ - public function currency() + public function currency(): HasOneThrough { return $this->hasOneThrough( Currency::class, diff --git a/packages/core/src/Models/Url.php b/packages/core/src/Models/Url.php index 4b4bed8cf5..caa9c1e8dd 100644 --- a/packages/core/src/Models/Url.php +++ b/packages/core/src/Models/Url.php @@ -3,6 +3,9 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphTo; +use Illuminate\Database\Query\Builder; use Lunar\Base\BaseModel; use Lunar\Base\Traits\HasMacros; use Lunar\Database\Factories\UrlFactory; @@ -49,31 +52,24 @@ protected static function newFactory(): UrlFactory /** * Return the element relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function element() + public function element(): MorphTo { return $this->morphTo(); } /** * Return the language relationship. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function language() + public function language(): BelongsTo { return $this->belongsTo(Language::class); } /** * Return the query scope for default. - * - * @param \Illuminate\Database\Query\Builder $query - * @return \Illuminate\Database\Query\Builder */ - public function scopeDefault($query) + public function scopeDefault(Builder $query): Builder { return $query->whereDefault(true); } From abc1db6cec689fc4a9433863c795c0646b05640a Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Fri, 24 Nov 2023 09:50:25 +0000 Subject: [PATCH 07/26] Fix discount error on deleted products (#1342) Closes #1339 --- .../Components/Discounts/AbstractDiscount.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php b/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php index a1527a80a1..b2f5f3fcc8 100644 --- a/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php +++ b/packages/admin/src/Http/Livewire/Components/Discounts/AbstractDiscount.php @@ -51,7 +51,7 @@ abstract class AbstractDiscount extends Component * @var array */ public Collection $selectedProducts; - + /** * The product variants to restrict the coupon for. * @@ -122,14 +122,16 @@ public function mount() $this->selectedProducts = $this->discount->purchasables() ->whereIn('type', ['limitation', 'exclusion']) ->wherePurchasableType(Product::class) + ->whereHas('purchasable') ->get() ->map(function ($limitation) { return array_merge($this->mapProductToArray($limitation->purchasable), ['type' => $limitation->type]); }); - + $this->selectedProductVariants = $this->discount->purchasables() ->whereIn('type', ['limitation', 'exclusion']) ->wherePurchasableType(ProductVariant::class) + ->whereHas('purchasable') ->get() ->map(function ($limitation) { return array_merge($this->mapProductVariantToArray($limitation->purchasable), ['type' => $limitation->type]); @@ -137,10 +139,12 @@ public function mount() $this->selectedConditions = $this->discount->purchasableConditions() ->wherePurchasableType(Product::class) + ->whereHas('purchasable') ->pluck('purchasable_id')->values()->toArray(); $this->selectedRewards = $this->discount->purchasableRewards() ->wherePurchasableType(Product::class) + ->whereHas('purchasable') ->pluck('purchasable_id')->values()->toArray(); $this->syncAvailability(); @@ -251,7 +255,7 @@ public function selectProducts(array $ids) ? $this->selectedProducts->merge($selectedProducts) : $selectedProducts; } - + /** * Select product variants given an array of IDs * @@ -338,7 +342,7 @@ public function removeProduct($index) { $this->selectedProducts->forget($index); } - + /** * Remove the product variant by it's index. * @@ -407,7 +411,7 @@ public function save() $this->discount->collections()->sync( $this->selectedCollections->mapWithKeys(fn ($collection) => [$collection['id'] => ['type' => $collection['type']]]) ); - + $this->discount->purchasables() ->whereIn('type', ['exclusion', 'limitation']) ->where('purchasable_type', Product::class) @@ -427,7 +431,7 @@ public function save() ]) ->save(); } - + $this->discount->purchasables() ->whereIn('type', ['exclusion', 'limitation']) ->where('purchasable_type', ProductVariant::class) @@ -558,7 +562,7 @@ private function mapProductToArray($product) 'thumbnail' => optional($product->thumbnail)->getUrl('small'), ]; } - + /** * Return the data we need from a product variant * From b520dde83c770b92675cf0a7533fbd5da21f65cc Mon Sep 17 00:00:00 2001 From: Glenn Jacobs Date: Tue, 19 Dec 2023 09:13:48 +0000 Subject: [PATCH 08/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da4a8de7d7..7fecaf3ee4 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ This repository serves as a monorepo for the main packages that make up Lunar. ## Community - [Join our discord server](https://discord.gg/v6qVWaf) and chat to the developers and people using Lunar. -- [We have a roadmap](https://github.com/orgs/lunarphp/projects/1) where we will be detailing which features are next. +- [We have a roadmap](https://github.com/orgs/lunarphp/projects/8) where we will be detailing which features are next. ## Packages in this monorepo From 049954ca4a01f6d7396412023bd78323f3a662ca Mon Sep 17 00:00:00 2001 From: Glenn Jacobs Date: Tue, 19 Dec 2023 09:41:37 +0000 Subject: [PATCH 09/26] Update bug-report.md --- .github/ISSUE_TEMPLATE/bug-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 8a4d7affaf..a4433edf11 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -2,7 +2,7 @@ name: "\U0001F41B Bug report" about: Report something that's broken. title: '' -labels: bug +labels: bug,unconfirmed assignees: '' --- From fa8fcaff640e4f3813a6660c6569646dbed7024a Mon Sep 17 00:00:00 2001 From: Dominik Nguyen Date: Wed, 20 Dec 2023 13:10:58 +0100 Subject: [PATCH 10/26] Fix creating product options in hub (#1394) --- .../Product/ProductOptionCreateTest.php | 45 +++++++++++++++++++ packages/core/src/Models/ProductOption.php | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php new file mode 100644 index 0000000000..d06bb3639a --- /dev/null +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php @@ -0,0 +1,45 @@ +create([ + 'default' => true, + 'code' => 'en', + ]); + } + + /** + * @test + * */ + public function can_populate_product_option_data() + { + $staff = Staff::factory()->create([ + 'admin' => true, + ]); + + LiveWire::actingAs($staff, 'staff') + ->test(OptionsIndex::class) + ->set('newProductOption.name.' . Language::getDefault()->code, 'Size') + ->call('createOption'); + + $this->assertDatabaseHas((new ProductOption())->getTable(), [ + 'name' => json_encode([Language::getDefault()->code => 'Size']), + ]); + } +} diff --git a/packages/core/src/Models/ProductOption.php b/packages/core/src/Models/ProductOption.php index 8bb7402a66..bbc05abf6c 100644 --- a/packages/core/src/Models/ProductOption.php +++ b/packages/core/src/Models/ProductOption.php @@ -49,7 +49,7 @@ protected static function newFactory(): ProductOptionFactory return ProductOptionFactory::new(); } - public function getNameAttribute(string $value): mixed + public function getNameAttribute(string $value = null): mixed { return json_decode($value); } From 380012adbf56feb68e3074b61f195f35b852a139 Mon Sep 17 00:00:00 2001 From: Jakub Theimer <5587309+theimerj@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:18:14 +0100 Subject: [PATCH 11/26] Make explicit binding for products conditional in hub context (#1312) --- .../admin/src/AdminHubServiceProvider.php | 8 +++-- .../Pages/Products/ProductShowTest.php | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/admin/src/AdminHubServiceProvider.php b/packages/admin/src/AdminHubServiceProvider.php index 762fb9b7c4..129e3a7e1d 100644 --- a/packages/admin/src/AdminHubServiceProvider.php +++ b/packages/admin/src/AdminHubServiceProvider.php @@ -219,8 +219,12 @@ public function boot() $this->registerPublishables(); $this->registerStateListeners(); - Route::bind('product', function ($id) { - return Product::withTrashed()->findOrFail($id); + Route::bind('product', function (mixed $value, \Illuminate\Routing\Route $route) { + if (in_array(\Lunar\Hub\Http\Middleware\Authenticate::class, $route->middleware())) { + return Product::withTrashed()->findOrFail($value); + } + + return $value; }); // Commands diff --git a/packages/admin/tests/Feature/Http/Livewire/Pages/Products/ProductShowTest.php b/packages/admin/tests/Feature/Http/Livewire/Pages/Products/ProductShowTest.php index 394bb192c6..86d9334d74 100644 --- a/packages/admin/tests/Feature/Http/Livewire/Pages/Products/ProductShowTest.php +++ b/packages/admin/tests/Feature/Http/Livewire/Pages/Products/ProductShowTest.php @@ -99,6 +99,40 @@ public function can_view_page_with_correct_permission() ->assertSeeLivewire('hub.components.products.show'); } + /** @test */ + public function cant_view_soft_deleted_products() + { + $this->setupRolesPermissions(); + + $staff = Staff::factory()->create([ + 'admin' => false, + ]); + + $staff->givePermissionTo('catalogue:manage-products'); + + $this->actingAs($staff, 'staff'); + + $product = Product::factory()->create([ + 'deleted_at' => now(), + ]); + + $variant = ProductVariant::factory()->create([ + 'product_id' => $product->id, + ]); + + foreach (Currency::get() as $currency) { + Price::factory()->create([ + 'priceable_type' => ProductVariant::class, + 'priceable_id' => $variant->id, + 'currency_id' => $currency->id, + 'tier' => 1, + ]); + } + + $this->get(route('hub.products.show', $product->id)) + ->assertSeeLivewire('hub.components.products.show'); + } + /** @test */ public function product_with_one_variant_has_variant_components_visible() { From 7f41cf66ebc96ee7465a84c8a4c4dd24228bf47d Mon Sep 17 00:00:00 2001 From: Lionel Guichard Date: Fri, 22 Dec 2023 11:37:47 +0100 Subject: [PATCH 12/26] Fix creating product options values in hub (#1402) --- .../Product/ProductOptionValueCreateTest.php | 49 +++++++++++++++++++ .../core/src/Models/ProductOptionValue.php | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php new file mode 100644 index 0000000000..46ac803a35 --- /dev/null +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php @@ -0,0 +1,49 @@ +create([ + 'default' => true, + 'code' => 'en', + ]); + } + + /** + * @test + * */ + public function can_populate_product_option_data() + { + ProductOption::factory(1)->create()->each(function ($option) { + $staff = Staff::factory()->create([ + 'admin' => true, + ]); + + LiveWire::actingAs($staff, 'staff') + ->test(OptionEdit::class, ['productOption' => $option]) + ->set('newProductOptionValue.name.' . Language::getDefault()->code, 'Size') + ->call('createOptionValue'); + + $this->assertDatabaseHas((new ProductOptionValue())->getTable(), [ + 'product_option_id' => $option->id, + 'name' => json_encode([Language::getDefault()->code => 'Size']) + ]); + }); + } +} diff --git a/packages/core/src/Models/ProductOptionValue.php b/packages/core/src/Models/ProductOptionValue.php index 0f677b8920..d9f164ab7b 100644 --- a/packages/core/src/Models/ProductOptionValue.php +++ b/packages/core/src/Models/ProductOptionValue.php @@ -53,7 +53,7 @@ protected static function newFactory(): ProductOptionValueFactory */ protected $guarded = []; - public function getNameAttribute(string $value): mixed + public function getNameAttribute(string $value = null): mixed { return json_decode($value); } From 8f58c2210009ea4b6e924aaf52d4a32a0b37508f Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Thu, 11 Jan 2024 09:27:24 +0000 Subject: [PATCH 13/26] Fix doc building (#1466) --- docs/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/package.json b/docs/package.json index 8e351840d2..33cb2768df 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,4 +1,5 @@ { + "type": "module", "devDependencies": { "vitepress": "^1.0.0-beta.7" }, From 53571f8b1af529dc95e0a692c9662b3d1dc970a4 Mon Sep 17 00:00:00 2001 From: Andrea De Luca <53230888+se09deluca@users.noreply.github.com> Date: Thu, 11 Jan 2024 10:40:12 +0100 Subject: [PATCH 14/26] Fix: use session's customer groups correctly (#1453) --- .../core/src/Managers/StorefrontSessionManager.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/core/src/Managers/StorefrontSessionManager.php b/packages/core/src/Managers/StorefrontSessionManager.php index 04b8bc93db..9e3fa9e04a 100644 --- a/packages/core/src/Managers/StorefrontSessionManager.php +++ b/packages/core/src/Managers/StorefrontSessionManager.php @@ -80,7 +80,7 @@ public function initCustomerGroups() ); if ($this->customerGroups?->count()) { - if (! $groupHandles) { + if ($groupHandles->isEmpty()) { return $this->setCustomerGroups( $this->customerGroups ); @@ -89,16 +89,14 @@ public function initCustomerGroups() return $this->customerGroups; } - if (! $this->customerGroups?->count()) { - return $this->setCustomerGroups( - collect([ - CustomerGroup::getDefault(), - ]) - ); + if (! $groupHandles->isEmpty()) { + return $this->customerGroups = CustomerGroup::whereIn('handle', $groupHandles)->get(); } return $this->setCustomerGroups( - CustomerGroup::whereIn('handle', $groupHandles)->get() + collect([ + CustomerGroup::getDefault(), + ]) ); } From f33011ab92147ab3642a327c7bc4186a3061be1b Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Thu, 11 Jan 2024 09:45:49 +0000 Subject: [PATCH 15/26] Pint fixes (#1467) --- packages/admin/resources/lang/en/partials.php | 1 - .../Components/Orders/OrderStatus.php | 4 +- .../Attributes/AttributeGroupEdit.php | 5 +- .../Components/Orders/OrderShowTest.php | 2 +- .../Product/ProductOptionCreateTest.php | 60 +++++++++---------- .../Product/ProductOptionValueCreateTest.php | 4 +- ...00010_add_type_to_brand_discount_table.php | 2 +- ..._add_type_to_collection_discount_table.php | 2 +- .../database/state/ConvertTaxbreakdown.php | 10 ++-- .../src/Actions/Taxes/GetTaxZoneCountry.php | 3 +- packages/core/src/Base/Casts/TaxBreakdown.php | 9 +-- packages/core/src/DiscountTypes/AmountOff.php | 22 +++---- .../core/src/Managers/DiscountManager.php | 10 ++-- packages/core/src/Models/Product.php | 1 - .../src/Pipelines/Cart/CalculateLines.php | 2 +- .../Unit/Actions/Taxes/GetTaxZoneTest.php | 1 - .../Unit/DiscountTypes/AmountOffTest.php | 14 ++--- packages/core/tests/Unit/Models/CartTest.php | 1 + packages/core/tests/Unit/Models/OrderTest.php | 2 +- .../Pipelines/Cart/CalculateLinesTest.php | 4 +- .../tests/Unit/Search/OrderIndexerTest.php | 2 +- .../src/DatabaseEngine.php | 2 +- 22 files changed, 80 insertions(+), 83 deletions(-) diff --git a/packages/admin/resources/lang/en/partials.php b/packages/admin/resources/lang/en/partials.php index 1a40812a24..3440c54d23 100644 --- a/packages/admin/resources/lang/en/partials.php +++ b/packages/admin/resources/lang/en/partials.php @@ -97,7 +97,6 @@ 'discounts.limitations.limitation' => 'Limitation', 'discounts.limitations.exclusion' => 'Exclusion', /** - * Product Collections. */ 'products.collections.heading' => 'Collections', diff --git a/packages/admin/src/Http/Livewire/Components/Orders/OrderStatus.php b/packages/admin/src/Http/Livewire/Components/Orders/OrderStatus.php index ccbd82f88e..0ee274e773 100644 --- a/packages/admin/src/Http/Livewire/Components/Orders/OrderStatus.php +++ b/packages/admin/src/Http/Livewire/Components/Orders/OrderStatus.php @@ -133,7 +133,7 @@ public function getPreviewHtmlProperty() { $mailer = $this->availableMailers[$this->previewTemplate] ?? null; - if (!$mailer) { + if (! $mailer) { return 'Unable to load preview'; } @@ -169,7 +169,7 @@ public function updateStatus() if (method_exists($mailable, 'render')) { } - $storedPath = 'orders/activity/' . Str::random() . '.html'; + $storedPath = 'orders/activity/'.Str::random().'.html'; $storedMailer = Storage::put( $storedPath, diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Attributes/AttributeGroupEdit.php b/packages/admin/src/Http/Livewire/Components/Settings/Attributes/AttributeGroupEdit.php index 6c256b2fec..70b6128be3 100644 --- a/packages/admin/src/Http/Livewire/Components/Settings/Attributes/AttributeGroupEdit.php +++ b/packages/admin/src/Http/Livewire/Components/Settings/Attributes/AttributeGroupEdit.php @@ -76,16 +76,15 @@ public function create() $handle = Str::handle("{$this->typeHandle}_{$this->attributeGroup->translate('name')}"); $this->attributeGroup->handle = $handle; - $uniquenessConstraint = 'unique:' . get_class($this->attributeGroup) . ',handle'; + $uniquenessConstraint = 'unique:'.get_class($this->attributeGroup).',handle'; if ($this->attributeGroup->id) { - $uniquenessConstraint .= ',' . $this->attributeGroup->id; + $uniquenessConstraint .= ','.$this->attributeGroup->id; } $this->validate([ 'attributeGroup.handle' => $uniquenessConstraint, ]); - if ($this->attributeGroup->id) { $this->attributeGroup->save(); $this->emit('attribute-group-edit.updated', $this->attributeGroup->id); diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Orders/OrderShowTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Orders/OrderShowTest.php index 3724884e98..111652e89f 100644 --- a/packages/admin/tests/Unit/Http/Livewire/Components/Orders/OrderShowTest.php +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Orders/OrderShowTest.php @@ -51,7 +51,7 @@ public function can_mount_component() 'currency_code' => Currency::getDefault()->code, 'meta' => [ 'foo' => 'bar', - ] + ], ]); $this->assertCount(0, $order->lines); diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php index d06bb3639a..19da7abd13 100644 --- a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionCreateTest.php @@ -12,34 +12,34 @@ class ProductOptionCreateTest extends TestCase { - use RefreshDatabase; - - public function setUp(): void - { - parent::setUp(); - - Language::factory()->create([ - 'default' => true, - 'code' => 'en', - ]); - } - - /** - * @test - * */ - public function can_populate_product_option_data() - { - $staff = Staff::factory()->create([ - 'admin' => true, - ]); - - LiveWire::actingAs($staff, 'staff') - ->test(OptionsIndex::class) - ->set('newProductOption.name.' . Language::getDefault()->code, 'Size') - ->call('createOption'); - - $this->assertDatabaseHas((new ProductOption())->getTable(), [ - 'name' => json_encode([Language::getDefault()->code => 'Size']), - ]); - } + use RefreshDatabase; + + public function setUp(): void + { + parent::setUp(); + + Language::factory()->create([ + 'default' => true, + 'code' => 'en', + ]); + } + + /** + * @test + * */ + public function can_populate_product_option_data() + { + $staff = Staff::factory()->create([ + 'admin' => true, + ]); + + LiveWire::actingAs($staff, 'staff') + ->test(OptionsIndex::class) + ->set('newProductOption.name.'.Language::getDefault()->code, 'Size') + ->call('createOption'); + + $this->assertDatabaseHas((new ProductOption())->getTable(), [ + 'name' => json_encode([Language::getDefault()->code => 'Size']), + ]); + } } diff --git a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php index 46ac803a35..21fb1b0e36 100644 --- a/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php +++ b/packages/admin/tests/Unit/Http/Livewire/Components/Settings/Product/ProductOptionValueCreateTest.php @@ -37,12 +37,12 @@ public function can_populate_product_option_data() LiveWire::actingAs($staff, 'staff') ->test(OptionEdit::class, ['productOption' => $option]) - ->set('newProductOptionValue.name.' . Language::getDefault()->code, 'Size') + ->set('newProductOptionValue.name.'.Language::getDefault()->code, 'Size') ->call('createOptionValue'); $this->assertDatabaseHas((new ProductOptionValue())->getTable(), [ 'product_option_id' => $option->id, - 'name' => json_encode([Language::getDefault()->code => 'Size']) + 'name' => json_encode([Language::getDefault()->code => 'Size']), ]); }); } diff --git a/packages/core/database/migrations/2023_10_06_100010_add_type_to_brand_discount_table.php b/packages/core/database/migrations/2023_10_06_100010_add_type_to_brand_discount_table.php index e6e75585a9..0155fec8ae 100644 --- a/packages/core/database/migrations/2023_10_06_100010_add_type_to_brand_discount_table.php +++ b/packages/core/database/migrations/2023_10_06_100010_add_type_to_brand_discount_table.php @@ -17,6 +17,6 @@ public function down() { Schema::table($this->prefix.'brand_discount', function ($table) { $table->dropColumn('type'); - }); + }); } } diff --git a/packages/core/database/migrations/2023_10_06_100010_add_type_to_collection_discount_table.php b/packages/core/database/migrations/2023_10_06_100010_add_type_to_collection_discount_table.php index ffd424e2b8..ee6e60477e 100644 --- a/packages/core/database/migrations/2023_10_06_100010_add_type_to_collection_discount_table.php +++ b/packages/core/database/migrations/2023_10_06_100010_add_type_to_collection_discount_table.php @@ -17,6 +17,6 @@ public function down() { Schema::table($this->prefix.'collection_discount', function ($table) { $table->dropColumn('type'); - }); + }); } } diff --git a/packages/core/database/state/ConvertTaxbreakdown.php b/packages/core/database/state/ConvertTaxbreakdown.php index e3fbf6a505..a623b8743c 100644 --- a/packages/core/database/state/ConvertTaxbreakdown.php +++ b/packages/core/database/state/ConvertTaxbreakdown.php @@ -15,10 +15,10 @@ public function prepare() public function run() { DB::usingConnection(config('lunar.database.connection') ?: DB::getDefaultConnection(), function () { - + $prefix = config('lunar.database.table_prefix'); $updateTime = now(); - + if ($this->canRunOnOrders()) { DB::table("{$prefix}orders") ->whereJsonContainsKey("{$prefix}orders.tax_breakdown->[0]->total") @@ -42,7 +42,7 @@ public function run() } }); } - + if ($this->canRunOnOrderLines()) { DB::table("{$prefix}order_lines") ->whereJsonContainsKey("{$prefix}order_lines.tax_breakdown->[0]->total") @@ -57,7 +57,7 @@ public function run() DB::transaction(function () use ($prefix, $updateTime, $rows) { foreach ($rows as $row) { $originalBreakdown = json_decode($row->tax_breakdown, true); - + DB::table("{$prefix}order_lines")->where('id', '=', $row->id)->update([ 'tax_breakdown' => collect($originalBreakdown)->map(function ($breakdown) use ($row) { return [ @@ -74,7 +74,7 @@ public function run() }); }); } - + }); } diff --git a/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php b/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php index 892097a4fc..a73c444e90 100644 --- a/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php +++ b/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php @@ -14,7 +14,7 @@ public function execute($countryId) return $taxZone; } - if (!$taxZone) { + if (! $taxZone) { return null; } } @@ -22,7 +22,6 @@ public function execute($countryId) /** * Return the zone or zones which match this country. * - * @param int $countryId * @return TaxZoneCountry|null */ protected function getZone(int $countryId) diff --git a/packages/core/src/Base/Casts/TaxBreakdown.php b/packages/core/src/Base/Casts/TaxBreakdown.php index 06faf834f2..fd61b3cd6b 100644 --- a/packages/core/src/Base/Casts/TaxBreakdown.php +++ b/packages/core/src/Base/Casts/TaxBreakdown.php @@ -26,9 +26,9 @@ public function get($model, $key, $value, $attributes) $breakdown->amounts = collect( json_decode($value, false) - )->mapWithKeys(function ($amount, $key) use ($model) { + )->mapWithKeys(function ($amount, $key) { $currency = BlinkFacade::once("currency_{$amount->currency_code}", function () use ($amount) { - return Currency::whereCode($amount->currency_code)->first(); + return Currency::whereCode($amount->currency_code)->first(); }); return [ @@ -51,8 +51,9 @@ public function get($model, $key, $value, $attributes) * @param string $key * @param Price $value * @param array $attributes - * @throws \Exception * @return array + * + * @throws \Exception */ public function set($model, $key, $value, $attributes) { @@ -82,7 +83,7 @@ public function set($model, $key, $value, $attributes) * * @param \Illuminate\Database\Eloquent\Model $model * @param string $key - * @param mixed $value + * @param mixed $value * @param array $attributes */ public function serialize($model, $key, $value, $attributes) diff --git a/packages/core/src/DiscountTypes/AmountOff.php b/packages/core/src/DiscountTypes/AmountOff.php index 7219a809a7..2c098e4f95 100644 --- a/packages/core/src/DiscountTypes/AmountOff.php +++ b/packages/core/src/DiscountTypes/AmountOff.php @@ -110,28 +110,28 @@ private function applyFixedValue(array $values, Cart $cart): Cart $lines->filter(function ($line) { return $line->subTotalDiscounted->value > 0; }) - ->each(function($line) use ($affectedLines, $cart, &$remaining) { + ->each(function ($line) use ($affectedLines, $cart, &$remaining) { if ($remaining <= 0) { return; } - + $amountAvailable = min($line->subTotalDiscounted->value, $remaining); $remaining -= $amountAvailable; $newDiscountTotal = $line->discountTotal->value + $amountAvailable; - + $line->discountTotal = new Price( $newDiscountTotal, $cart->currency, 1 ); - + $line->subTotalDiscounted = new Price( $line->subTotal->value - $newDiscountTotal, $cart->currency, 1 ); - + if (! $affectedLines->first(function ($breakdownLine) use ($line) { return $breakdownLine->line == $line; })) { @@ -165,14 +165,14 @@ protected function getEligibleLines(Cart $cart): \Illuminate\Support\Collection { $collectionIds = $this->discount->collections->where('pivot.type', 'limitation')->pluck('id'); $collectionExclusionIds = $this->discount->collections->where('pivot.type', 'exclusion')->pluck('id'); - + $brandIds = $this->discount->brands->where('pivot.type', 'limitation')->pluck('id'); $brandExclusionIds = $this->discount->brands->where('pivot.type', 'exclusion')->pluck('id'); - + $productIds = $this->discount->purchasableLimitations ->reject(fn ($limitation) => ! $limitation->purchasable) ->map(fn ($limitation) => get_class($limitation->purchasable).'::'.$limitation->purchasable->id); - + $productExclusionIds = $this->discount->purchasableExclusions ->reject(fn ($limitation) => ! $limitation->purchasable) ->map(fn ($limitation) => get_class($limitation->purchasable).'::'.$limitation->purchasable->id); @@ -186,7 +186,7 @@ protected function getEligibleLines(Cart $cart): \Illuminate\Support\Collection })->exists(); }); } - + if ($collectionExclusionIds->count()) { $lines = $lines->reject(function ($line) use ($collectionExclusionIds) { return $line->purchasable->product()->whereHas('collections', function ($query) use ($collectionExclusionIds) { @@ -200,7 +200,7 @@ protected function getEligibleLines(Cart $cart): \Illuminate\Support\Collection return ! $brandIds->contains($line->purchasable->product->brand_id); }); } - + if ($brandExclusionIds->count()) { $lines = $lines->reject(function ($line) use ($brandExclusionIds) { return $brandExclusionIds->contains($line->purchasable->product->brand_id); @@ -212,7 +212,7 @@ protected function getEligibleLines(Cart $cart): \Illuminate\Support\Collection return $productIds->contains(get_class($line->purchasable).'::'.$line->purchasable->id) || $productIds->contains(get_class($line->purchasable->product).'::'.$line->purchasable->product->id); }); } - + if ($productExclusionIds->count()) { $lines = $lines->reject(function ($line) use ($productExclusionIds) { return $productExclusionIds->contains(get_class($line->purchasable).'::'.$line->purchasable->id) || $productExclusionIds->contains(get_class($line->purchasable->product).'::'.$line->purchasable->product->id); diff --git a/packages/core/src/Managers/DiscountManager.php b/packages/core/src/Managers/DiscountManager.php index 153883304c..0f629aafce 100644 --- a/packages/core/src/Managers/DiscountManager.php +++ b/packages/core/src/Managers/DiscountManager.php @@ -138,12 +138,12 @@ public function getDiscounts(Cart $cart = null): Collection function ($query, $value) { return $query->where(function ($query) use ($value) { return $query->where(fn ($query) => $query->products( - $value->lines->pluck('purchasable.product_id')->filter()->values() - ) - ) + $value->lines->pluck('purchasable.product_id')->filter()->values() + ) + ) ->orWhere(fn ($query) => $query->productVariants( - $value->lines->pluck('purchasable.id')->filter()->values() - ) + $value->lines->pluck('purchasable.id')->filter()->values() + ) ); }); } diff --git a/packages/core/src/Models/Product.php b/packages/core/src/Models/Product.php index 795bc197f9..01d4ea17a8 100644 --- a/packages/core/src/Models/Product.php +++ b/packages/core/src/Models/Product.php @@ -9,7 +9,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Eloquent\Relations\MorphMany; -use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Database\Eloquent\SoftDeletes; use Lunar\Base\BaseModel; use Lunar\Base\Casts\AsAttributeData; diff --git a/packages/core/src/Pipelines/Cart/CalculateLines.php b/packages/core/src/Pipelines/Cart/CalculateLines.php index 04b7806872..06599eb189 100644 --- a/packages/core/src/Pipelines/Cart/CalculateLines.php +++ b/packages/core/src/Pipelines/Cart/CalculateLines.php @@ -26,7 +26,7 @@ public function handle(Cart $cart, Closure $next) return $cartLine; }); - + $unitPrice = $cartLine->unitPrice->unitDecimal(false) * $cart->currency->factor; $subTotal = (int) round($unitPrice * $cartLine->quantity, $cart->currency->decimal_places); diff --git a/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php b/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php index 632888a346..94e0c3781f 100644 --- a/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php +++ b/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php @@ -4,7 +4,6 @@ use Illuminate\Foundation\Testing\RefreshDatabase; use Lunar\Actions\Taxes\GetTaxZone; -use Lunar\Actions\Taxes\GetTaxZoneCountry; use Lunar\Models\Address; use Lunar\Models\Country; use Lunar\Models\State; diff --git a/packages/core/tests/Unit/DiscountTypes/AmountOffTest.php b/packages/core/tests/Unit/DiscountTypes/AmountOffTest.php index 55c9b944c7..857ac3b068 100644 --- a/packages/core/tests/Unit/DiscountTypes/AmountOffTest.php +++ b/packages/core/tests/Unit/DiscountTypes/AmountOffTest.php @@ -147,7 +147,7 @@ public function will_only_apply_to_lines_with_correct_brand() $this->assertEquals(100, $cart->discountTotal->value); $this->assertEquals(2280, $cart->total->value); } - + /** @test */ public function will_not_apply_to_lines_with_excluded_brand() { @@ -350,7 +350,7 @@ public function will_only_apply_to_lines_with_correct_product() $this->assertEquals(100, $cart->discountTotal->value); $this->assertEquals(2280, $cart->total->value); } - + /** @test */ public function will_only_apply_to_lines_with_correct_product_variant() { @@ -449,7 +449,7 @@ public function will_only_apply_to_lines_with_correct_product_variant() $this->assertEquals(100, $cart->discountTotal->value); $this->assertEquals(2280, $cart->total->value); } - + /** @test */ public function will_not_apply_to_lines_with_excluded_product() { @@ -544,11 +544,11 @@ public function will_not_apply_to_lines_with_excluded_product() ]); $cart = $cart->calculate(); - + $this->assertEquals(200, $cart->discountTotal->value); $this->assertEquals(3360, $cart->total->value); } - + /** @test */ public function will_not_apply_to_lines_with_excluded_product_variant() { @@ -643,7 +643,7 @@ public function will_not_apply_to_lines_with_excluded_product_variant() ]); $cart = $cart->calculate(); - + $this->assertEquals(200, $cart->discountTotal->value); $this->assertEquals(3360, $cart->total->value); } @@ -1619,7 +1619,7 @@ public function cannot_apply_discount_with_max_user_uses() $this->assertEquals(2400, $cart->total->value); $this->assertEquals(2000, $cart->subTotal->value); } - + /** * @test */ diff --git a/packages/core/tests/Unit/Models/CartTest.php b/packages/core/tests/Unit/Models/CartTest.php index 5d992f6952..411fd1ccbf 100644 --- a/packages/core/tests/Unit/Models/CartTest.php +++ b/packages/core/tests/Unit/Models/CartTest.php @@ -966,6 +966,7 @@ public function can_override_shipping_calculation() /** * @test + * * @group foofoo */ public function can_get_estimated_shipping() diff --git a/packages/core/tests/Unit/Models/OrderTest.php b/packages/core/tests/Unit/Models/OrderTest.php index 933c036366..5f693bf887 100644 --- a/packages/core/tests/Unit/Models/OrderTest.php +++ b/packages/core/tests/Unit/Models/OrderTest.php @@ -105,7 +105,7 @@ public function can_create_lines() 'placed_at' => now(), 'meta' => [ 'foo' => 'bar', - ] + ], ]); $this->assertCount(0, $order->lines); diff --git a/packages/core/tests/Unit/Pipelines/Cart/CalculateLinesTest.php b/packages/core/tests/Unit/Pipelines/Cart/CalculateLinesTest.php index 04ce64e440..c57d8f607b 100644 --- a/packages/core/tests/Unit/Pipelines/Cart/CalculateLinesTest.php +++ b/packages/core/tests/Unit/Pipelines/Cart/CalculateLinesTest.php @@ -19,6 +19,7 @@ class CalculateLinesTest extends TestCase /** * @test + * * @dataProvider providePurchasableData */ public function can_calculate_lines($expectedUnitPrice, $incomingUnitPrice, $unitQuantity) @@ -47,7 +48,6 @@ public function can_calculate_lines($expectedUnitPrice, $incomingUnitPrice, $uni 'quantity' => 1, ]); - $cart = app(CalculateLines::class)->handle($cart, function ($cart) { return $cart; }); @@ -79,7 +79,7 @@ public function providePurchasableData() '0.55', '5503', '100', - ] + ], ]; } } diff --git a/packages/core/tests/Unit/Search/OrderIndexerTest.php b/packages/core/tests/Unit/Search/OrderIndexerTest.php index 1ffaa3387a..722041e782 100644 --- a/packages/core/tests/Unit/Search/OrderIndexerTest.php +++ b/packages/core/tests/Unit/Search/OrderIndexerTest.php @@ -29,7 +29,7 @@ public function can_return_correct_searchable_data() 'placed_at' => now(), 'meta' => [ 'foo' => 'bar', - ] + ], ]); $data = app(OrderIndexer::class)->toSearchableArray($order); diff --git a/utils/scout-database-engine/src/DatabaseEngine.php b/utils/scout-database-engine/src/DatabaseEngine.php index d23f78b729..9448e67bf3 100644 --- a/utils/scout-database-engine/src/DatabaseEngine.php +++ b/utils/scout-database-engine/src/DatabaseEngine.php @@ -121,7 +121,7 @@ protected function getSearchQuery(Builder $builder) return SearchIndex::where('index', '=', $index) ->when( $builder->query, - fn ($query) => $query ->whereFullText('content', $builder->query.'*', ['mode' => 'boolean']) + fn ($query) => $query->whereFullText('content', $builder->query.'*', ['mode' => 'boolean']) ); } From 950587f19f232106f89366c801aecfe8ffe7fe59 Mon Sep 17 00:00:00 2001 From: Andrea De Luca <53230888+se09deluca@users.noreply.github.com> Date: Thu, 11 Jan 2024 10:47:09 +0100 Subject: [PATCH 16/26] Fix: missing order address attribute (#1426) --- packages/core/src/Models/OrderAddress.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/src/Models/OrderAddress.php b/packages/core/src/Models/OrderAddress.php index e5e285e5a4..59bb73908f 100644 --- a/packages/core/src/Models/OrderAddress.php +++ b/packages/core/src/Models/OrderAddress.php @@ -72,8 +72,9 @@ protected static function newFactory(): OrderAddressFactory 'delivery_instructions', 'contact_email', 'contact_phone', - 'meta', 'type', + 'shipping_option', + 'meta', ]; /** From ff999fefcdd48c97f910d83b1e413c4036ff7d73 Mon Sep 17 00:00:00 2001 From: Andrea De Luca <53230888+se09deluca@users.noreply.github.com> Date: Thu, 11 Jan 2024 10:55:42 +0100 Subject: [PATCH 17/26] Fix: Error selecting applicable discounts (#1434) --- packages/core/src/Managers/DiscountManager.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/core/src/Managers/DiscountManager.php b/packages/core/src/Managers/DiscountManager.php index 0f629aafce..9337b57a61 100644 --- a/packages/core/src/Managers/DiscountManager.php +++ b/packages/core/src/Managers/DiscountManager.php @@ -149,7 +149,13 @@ function ($query, $value) { } )->when( $cart?->coupon_code, - fn ($query, $value) => $query->where('coupon', '=', $value)->orWhere(fn ($query) => $query->whereNull('coupon')->orWhere('coupon', '')), + function ($query, $value) { + return $query->where(function ($query) use ($value) { + $query->where('coupon', $value) + ->orWhereNull('coupon') + ->orWhere('coupon', ''); + }); + }, fn ($query, $value) => $query->whereNull('coupon')->orWhere('coupon', '') )->orderBy('priority', 'desc') ->orderBy('id') From f7919a4fdd650353e19989c91e6a461a12412c1f Mon Sep 17 00:00:00 2001 From: Andrea De Luca <53230888+se09deluca@users.noreply.github.com> Date: Thu, 11 Jan 2024 10:56:54 +0100 Subject: [PATCH 18/26] Docs: fix example usage of addLines (#1429) Fixes a typo in the example of CartSession::addLines usage. The implementation of [addLines](https://github.com/lunarphp/lunar/blob/7f41cf66ebc96ee7465a84c8a4c4dd24228bf47d/packages/core/src/Models/Cart.php#L337C10-L337C10) currently expects a purchasable instance as below: ```php public function add(Purchasable $purchasable, int $quantity = 1, array $meta = [], bool $refresh = true): Cart { foreach (config('lunar.cart.validators.add_to_cart', []) as $action) { // Throws a validation exception? app($action)->using( cart: $this, purchasable: $purchasable, quantity: $quantity, meta: $meta )->validate(); } return app( config('lunar.cart.actions.add_to_cart', AddOrUpdatePurchasable::class) )->execute($this, $purchasable, $quantity, $meta) ->then(fn () => $refresh ? $this->refresh()->calculate() : $this); } public function addLines(iterable $lines): Cart { DB::transaction(function () use ($lines) { collect($lines)->each(function ($line) { $this->add( purchasable: $line['purchasable'], quantity: $line['quantity'], meta: (array) ($line['meta'] ?? null), refresh: false ); }); }); return $this->refresh()->calculate(); } ``` Co-authored-by: Alec Ritson --- docs/core/reference/carts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/reference/carts.md b/docs/core/reference/carts.md index 2074df3e1b..b28bf3625c 100644 --- a/docs/core/reference/carts.md +++ b/docs/core/reference/carts.md @@ -279,7 +279,7 @@ CartSession::add($purchasable, $quantity); ```php CartSession::addLines([ [ - 'id' => 1, + 'purchasable' => \Lunar\Models\ProductVariant::find(123), 'quantity' => 25, 'meta' => ['foo' => 'bar'], ], From faeb6db89f129065e17f11fb67d9e6a9a7031498 Mon Sep 17 00:00:00 2001 From: wychoong <67364036+wychoong@users.noreply.github.com> Date: Fri, 12 Jan 2024 21:45:04 +0800 Subject: [PATCH 19/26] Fix order activity timeline blank entries (#1317) --- .../core/src/Base/Traits/LogsActivity.php | 25 +++++++++++++++++-- packages/core/src/Models/Order.php | 7 ++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/core/src/Base/Traits/LogsActivity.php b/packages/core/src/Base/Traits/LogsActivity.php index c43da2754f..72a81a9eb8 100644 --- a/packages/core/src/Base/Traits/LogsActivity.php +++ b/packages/core/src/Base/Traits/LogsActivity.php @@ -2,6 +2,7 @@ namespace Lunar\Base\Traits; +use Illuminate\Support\Arr; use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\Traits\LogsActivity as SpatieLogsActivity; @@ -9,6 +10,8 @@ trait LogsActivity { use SpatieLogsActivity; + public static array $logExcept = []; + /** * Get the log options for the activity log. */ @@ -17,7 +20,25 @@ public function getActivitylogOptions(): LogOptions return LogOptions::defaults() ->useLogName('lunar') ->logAll() - ->dontSubmitEmptyLogs() - ->logExcept(['updated_at']); + ->logExcept(array_merge(['updated_at'], static::getActivitylogExcept())) + ->logOnlyDirty() + ->dontSubmitEmptyLogs(); + } + + public static function addActivitylogExcept(array|string $fields) + { + $fields = Arr::wrap($fields); + + static::$logExcept = array_merge(static::$logExcept, $fields); + } + + public static function getDefaultLogExcept(): array + { + return []; + } + + public static function getActivitylogExcept(): array + { + return array_merge(static::getDefaultLogExcept(), static::$logExcept); } } diff --git a/packages/core/src/Models/Order.php b/packages/core/src/Models/Order.php index 0ec0318acc..e2f3a25023 100644 --- a/packages/core/src/Models/Order.php +++ b/packages/core/src/Models/Order.php @@ -244,4 +244,11 @@ public function isPlaced(): bool { return ! blank($this->placed_at); } + + public static function getDefaultLogExcept(): array + { + return [ + 'status', + ]; + } } From b342878ea1fd7613f00a3a10544adfc3c9c7c582 Mon Sep 17 00:00:00 2001 From: Tuvshu Date: Mon, 15 Jan 2024 22:29:57 +0800 Subject: [PATCH 20/26] Fix - null safe operator for Dashboard Order Total (#1471) --- .../Components/Products/Tables/ProductVariantsTable.php | 2 +- packages/admin/src/Http/Livewire/Dashboard.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/admin/src/Http/Livewire/Components/Products/Tables/ProductVariantsTable.php b/packages/admin/src/Http/Livewire/Components/Products/Tables/ProductVariantsTable.php index 532f69dac0..ddcf459ed5 100644 --- a/packages/admin/src/Http/Livewire/Components/Products/Tables/ProductVariantsTable.php +++ b/packages/admin/src/Http/Livewire/Components/Products/Tables/ProductVariantsTable.php @@ -63,7 +63,7 @@ public function build() TextColumn::make('price', function ($record) { $price = $record->basePrices->first(fn ($price) => $price->currency->default); - return $price->price->formatted; + return $price->price->formatted ?? 0; }), TextColumn::make('stock'), TextColumn::make('backorder'), diff --git a/packages/admin/src/Http/Livewire/Dashboard.php b/packages/admin/src/Http/Livewire/Dashboard.php index 6715d5dcbe..8a7f5c0b07 100644 --- a/packages/admin/src/Http/Livewire/Dashboard.php +++ b/packages/admin/src/Http/Livewire/Dashboard.php @@ -115,7 +115,7 @@ public function getOrderTotalProperty() DB::RAW('SUM(sub_total) as total') )->first(); - return new Price($query->total->value, $this->defaultCurrency, 1); + return new Price($query->total->value ?? 0, $this->defaultCurrency, 1); } /** From 5dc55c0dffcc565db71543711f07ab3b4c3ea6f2 Mon Sep 17 00:00:00 2001 From: Bert Brunekreeft Date: Fri, 26 Jan 2024 13:30:55 +0100 Subject: [PATCH 21/26] fix: property definition for currency_code in Order model (#1482) --- packages/core/src/Models/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/Models/Order.php b/packages/core/src/Models/Order.php index e2f3a25023..fc6f8247c8 100644 --- a/packages/core/src/Models/Order.php +++ b/packages/core/src/Models/Order.php @@ -35,7 +35,7 @@ * @property int $tax_total * @property int $total * @property ?string $notes - * @property string $currency + * @property string $currency_code * @property ?string $compare_currency_code * @property float $exchange_rate * @property ?\Illuminate\Support\Carbon $placed_at From bbb0956d3b0ac27f1dcf5f63526fc6b6e547ff31 Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Tue, 30 Jan 2024 13:24:20 +0000 Subject: [PATCH 22/26] Hotifx - Fix mapped attributes return type (#1517) Closes #1513 --- packages/core/src/Models/Product.php | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/Models/Product.php b/packages/core/src/Models/Product.php index 01d4ea17a8..4986da671c 100644 --- a/packages/core/src/Models/Product.php +++ b/packages/core/src/Models/Product.php @@ -3,6 +3,7 @@ namespace Lunar\Models; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; From 4c356f027cbe1c6be73a99d26c85290373ab1a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bour?= Date: Tue, 30 Jan 2024 15:59:36 +0100 Subject: [PATCH 23/26] Add french language for admin (#1489) --- packages/admin/resources/lang/en/global.php | 1 + packages/admin/resources/lang/fr/account.php | 10 + packages/admin/resources/lang/fr/auth.php | 46 +++ .../admin/resources/lang/fr/catalogue.php | 139 ++++++++ .../admin/resources/lang/fr/components.php | 307 ++++++++++++++++++ .../admin/resources/lang/fr/fieldtypes.php | 26 ++ packages/admin/resources/lang/fr/global.php | 131 ++++++++ packages/admin/resources/lang/fr/inputs.php | 115 +++++++ .../admin/resources/lang/fr/licensing.php | 6 + packages/admin/resources/lang/fr/menu.php | 50 +++ .../admin/resources/lang/fr/notifications.php | 68 ++++ packages/admin/resources/lang/fr/orders.php | 21 ++ packages/admin/resources/lang/fr/partials.php | 219 +++++++++++++ packages/admin/resources/lang/fr/settings.php | 180 ++++++++++ packages/admin/resources/lang/fr/tables.php | 55 ++++ .../admin/resources/lang/fr/validation.php | 16 + .../views/partials/navigation/taxes.blade.php | 4 +- packages/admin/src/Menu/SettingsMenu.php | 28 +- 18 files changed, 1406 insertions(+), 16 deletions(-) create mode 100644 packages/admin/resources/lang/fr/account.php create mode 100644 packages/admin/resources/lang/fr/auth.php create mode 100644 packages/admin/resources/lang/fr/catalogue.php create mode 100644 packages/admin/resources/lang/fr/components.php create mode 100644 packages/admin/resources/lang/fr/fieldtypes.php create mode 100644 packages/admin/resources/lang/fr/global.php create mode 100644 packages/admin/resources/lang/fr/inputs.php create mode 100644 packages/admin/resources/lang/fr/licensing.php create mode 100644 packages/admin/resources/lang/fr/menu.php create mode 100644 packages/admin/resources/lang/fr/notifications.php create mode 100644 packages/admin/resources/lang/fr/orders.php create mode 100644 packages/admin/resources/lang/fr/partials.php create mode 100644 packages/admin/resources/lang/fr/settings.php create mode 100644 packages/admin/resources/lang/fr/tables.php create mode 100644 packages/admin/resources/lang/fr/validation.php diff --git a/packages/admin/resources/lang/en/global.php b/packages/admin/resources/lang/en/global.php index 42d394f9d5..f73d1d35be 100644 --- a/packages/admin/resources/lang/en/global.php +++ b/packages/admin/resources/lang/en/global.php @@ -127,4 +127,5 @@ 'not_provided' => 'Not Provided', 'billing_email' => 'Billing Email', 'add_new' => 'Add new', + 'store' => 'Store', ]; diff --git a/packages/admin/resources/lang/fr/account.php b/packages/admin/resources/lang/fr/account.php new file mode 100644 index 0000000000..860331c7af --- /dev/null +++ b/packages/admin/resources/lang/fr/account.php @@ -0,0 +1,10 @@ + 'Compte', + 'save_btn' => 'Enregistrer', + 'avatar_notice' => 'Votre avatar est généré à l\'aide de Gravatar via votre adresse email.', + 'view-profile' => 'Voir mon profil', + 'update_password' => 'Modifier mon mot de passe', + 'logout' => 'Déconnexion', +]; diff --git a/packages/admin/resources/lang/fr/auth.php b/packages/admin/resources/lang/fr/auth.php new file mode 100644 index 0000000000..c9fdf11a33 --- /dev/null +++ b/packages/admin/resources/lang/fr/auth.php @@ -0,0 +1,46 @@ + 'Collections', + 'permissions.catalogue.collections.description' => 'Autoriser le membre du personnel à modifier les collections et leurs groupes.', + 'permissions.settings.name' => 'Paramètres', + 'permissions.settings.description' => 'Donne accès à la zone des paramètres du hub.', + 'permissions.settings.core.name' => 'Paramètres de base', + 'permissions.settings.core.description' => 'Accédez aux paramètres fondamentaux de la boutique, tels que les chaînes, les langues, les devises, etc.', + 'permissions.settings.staff.name' => 'Gérer le personnel', + 'permissions.settings.staff.description' => 'Autoriser le membre du personnel à gérer les autres membres du personnel.', + 'permissions.settings.attributes.name' => 'Gérer les attributs', + 'permissions.settings.attributes.description' => 'Autoriser le membre du personnel à gérer les attributs.', + 'permissions.catalogue.products.name' => 'Gérer les produits', + 'permissions.catalogue.products.description' => 'Autoriser le membre du personnel à gérer les produits.', + 'permissions.catalogue.orders.name' => 'Gérer les commandes', + 'permissions.catalogue.orders.description' => 'Autoriser le membre du personnel à gérer les commandes.', + 'permissions.catalogue.customers.name' => 'Gérer les clients', + 'permissions.catalogue.customers.description' => 'Autoriser le membre du personnel à gérer les clients.', + 'permissions.discounts.name' => 'Gérer les remises', + 'permissions.discounts.description' => 'Autoriser le membre du personnel à gérer les remises.', + /** + * Reset password. + */ + 'reset-password.title' => 'Réinitialiser le mot de passe', + 'reset-your-password' => 'Réinitialiser votre mot de passe', + 'reset-password.invalid' => 'Cette page n\'est plus valide.', + 'reset-password.back_link' => 'Retour connexion', + 'reset-password.send_btn' => 'Envoyer un e-mail de réinitialisation', + 'reset-password.update_btn' => 'Mettre à jour le mot de passe et l\'identifiant', + 'forgot-password.message' => 'Mot de passe oublié ?', + 'forgot-password.remember' => 'Se souvenir de votre mot de passe ?', + 'forgot-password.link' => 'Réinitialiser le mot de passe', + 'follow-link.reset' => 'Veuillez suivre ce lien pour réinitialiser votre mot de passe :', + 'click-here.reset' => 'Cliquez ici pour réinitialiser', + 'reset-link.not_working' => 'Le lien ne fonctionne pas ? Copiez ceci dans votre navigateur', + /** + * Login. + */ + 'sign-in.btn' => 'Se connecter', + 'welcome' => 'Bienvenue :name', + 'prompt' => 'Connectez-vous pour administrer votre boutique e-commerce.', +]; diff --git a/packages/admin/resources/lang/fr/catalogue.php b/packages/admin/resources/lang/fr/catalogue.php new file mode 100644 index 0000000000..62010d011a --- /dev/null +++ b/packages/admin/resources/lang/fr/catalogue.php @@ -0,0 +1,139 @@ + 'Créer un groupe de collections', + 'collections.sidemenu.modal.title' => 'Créer un groupe de collections', + 'collections.sidemenu.modal.btn' => 'Créer un groupe de collections', + 'collections.sidemenu.menu_title' => 'Groupes de collections', + 'collections.groups.delete_group_btn' => 'Supprimer le groupe de collections', + 'collections.groups.add_collection_btn' => 'Ajouter une collection', + 'collections.groups.delete.title' => 'Supprimer le groupe de collections', + 'collections.groups.delete.strapline' => 'Êtes-vous sûr de vouloir supprimer ce groupe de collections ?', + 'collections.groups.delete.warning' => 'Toutes les collections de ce groupe seront également supprimées.', + 'collections.groups.delete.confirm' => 'Confirmez que vous souhaitez supprimer le groupe de collections et toutes les collections associées', + 'collections.groups.delete.btn' => 'Supprimer le groupe de collections', + 'collections.groups.move.title' => 'Déplacer la collection', + 'collections.groups.move.search_placeholder' => 'Rechercher une collection à utiliser comme parent', + 'collections.groups.move.alert' => 'Cela déplacera :source dans :target.', + 'collections.groups.move.btn' => 'Déplacer la collection', + 'collections.groups.node.make_root' => 'Rendre la racine', + 'collections.groups.node.move' => 'Déplacer la collection', + 'collections.groups.node.edit' => 'Modifier la collection', + 'collections.groups.node.add_child' => 'Ajouter une collection enfant', + 'collections.groups.node.delete' => 'Supprimer la collection', + 'collections.groups.no_groups' => 'Il semble que vous n\'ayez pas encore configuré de groupes de collections.', + 'collections.create.child.title' => 'Ajouter une collection à :parent.', + 'collections.create.root.title' => 'Ajouter une collection de premier niveau', + 'collections.create.btn' => 'Créer la collection', + 'collections.delete.title' => 'Supprimer la collection', + 'collections.delete.btn' => 'Supprimer la collection', + 'collections.delete.warning' => 'Toutes les collections enfants seront également supprimées.', + 'collections.delete.child.warning' => 'Cette collection a :count collections enfants, elles seront également perdues.', + 'collections.delete.root.warning' => 'Êtes-vous sûr de vouloir supprimer cette collection ?', + 'collections.index.title' => 'Collections', + 'collections.show.save_btn' => 'Enregistrer la collection', + 'collections.show.sort.base_price_asc' => 'Prix de base croissant', + 'collections.show.sort.base_price_desc' => 'Prix de base décroissant', + 'collections.show.sort.sku_asc' => 'SKU croissant', + 'collections.show.sort.sku_desc' => 'SKU décroissant', + 'collections.show.sort.custom' => 'Personnalisé', + 'collections.show.no_products' => 'Cette collection n\'a aucun produit associé.', + 'collections.show.no_children' => 'Cette collection n\'a pas de collections enfant.', + 'collections.associate_to_other_products' => 'Choisissez les produits à associer et à relier à ce produit.', + 'collections.static_collections' => 'Collections statiques', + 'collections.summer_seasonal' => 'Saison estivale', + /** + * Product show. + */ + 'products.show.back_link_title' => 'Revenir à la liste des produits', + 'products.show.save_btn' => 'Enregistrer le produit', + 'products.show.no_channel_availability' => 'Ce produit n\'est pas disponible sur tous les canaux.', + 'products.show.delete_title' => 'Supprimer le produit', + 'products.show.delete_strapline' => 'Cela enverra le produit dans la corbeille, vous pourrez le restaurer plus tard', + 'products.show.restore_strapline' => 'Restaurez ce produit pour qu\'il soit disponible sur votre boutique.', + 'products.show.delete_btn' => 'Confirmation de la suppression', + 'products.show.restore_title' => 'Restaurer le produit', + 'products.show.restore_btn' => 'Confirmer la restauration', + + /** + * Product variant. + */ + 'product-variants.delete_confirm.title' => 'Confirmer la suppression de la variante', + 'product-variants.delete_confirm.strapline' => 'Cette action ne peut pas être annulée.', + 'product-variants.delete_confirm.btn' => 'Supprimer la variante', + 'product-variants.add_variant.btn' => 'Ajouter une variante', + 'product-variants.add_variant.already_exists' => 'Cette variante existe déjà.', + 'product-variants.add_variant.null_option' => 'Choisissez une option', + 'product-variants.add_variant.title' => 'Ajouter une variante supplémentaire', + 'product-variants.add_variant.add_new_option' => 'Ajouter une nouvelle option', + /** + * Product type listing. + */ + 'product-types.index.title' => 'Types de produits', + 'product-types.index.create_btn' => 'Créer un type de produit', + /** + * Product type editing. + */ + 'product-types.show.updated_message' => 'Type de produit mis à jour', + 'product-types.create.btn_text' => 'Créer un type de produit', + 'product-types.show.btn_text' => 'Mettre à jour le type de produit', + 'product-types.attribute.search.empty' => 'Il semble que vous n\'ayez plus d\'attributs à attribuer.', + 'product-types.attribute.search.no_results' => 'Impossible de trouver les attributs correspondants ":search"', + 'product-types.show.title' => 'Modifier le type de produit', + 'product-types.show.delete.btn_text' => 'Supprimer le type de produit', + 'product-types.show.delete.message' => 'Êtes-vous sûr de vouloir supprimer définitivement ce type de produit ?', + 'product-types.show.delete.disabled_message' => 'Vous ne pouvez pas supprimer un type de produit auquel des produits sont associés.', + 'product-types.show.delete.delete_notification' => 'Type de produit supprimé', + 'product-types.show.delete.confirm_text' => 'Confirmer la suppression', + 'product-types.show.delete.minimum_required' => 'Vous ne pouvez pas supprimer le seul type de produit.', + 'product-types.attribute.no_attributes' => 'Il n\'y a aucun attribut à sélectionner dans ce groupe', + /** + * Brands. + */ + 'brands.index.title' => 'Marques', + 'brands.create.title' => 'Créer une marque', + 'brands.show.back_link_title' => 'Revenir à la liste des marques', + /** + * Customers. + */ + 'customers.index.title' => 'Clients', + 'customers.index.placeholder' => 'Rechercher un client', + 'customers.show.save_btn' => 'Enregistrer le client', + 'customers.show.customer_groups_updated' => 'Groupes de clients mis à jour', + 'customer.show.customer_groups' => 'Groupes de clients', + 'customer.dashboard.returning_customers' => 'Clients fidèles', + 'customer.dashboard.no_of_orders' => 'Nombre de commandes', + 'customer.dashboard.turnover' => 'Chiffre d\'affaires', + 'customer.dashboard.sales_performance' => 'Performance des ventes', + 'customer.dashboard.customer_group_orders' => 'Commandes par groupe de clients', + 'customer.dashboard.top_selling_products' => 'Produits les plus vendus', + /** + * Customer Groups Editing. + */ + 'editing.customer-groups.select_groups' => 'Sélectionnez les groupes de clients pour lesquels ce produit est disponible.', + 'editing.customer-groups.publish_on' => 'Ce produit devrait être publié le', + 'editing.customer-groups.schedule_availability' => 'Disponibilité des horaires', + /** + * Orders. + */ + 'orders.show.customer_reference' => 'Référence client', + 'orders.show.shipping_option' => 'Option de livraison', + 'orders.show.shipping_address' => 'Adresse de livraison', + 'orders.show.billing_address' => 'Adresse de facturation', + 'orders.show.order_lines' => 'Lignes de commande', + 'orders.show.transactions' => 'Transactions', + 'orders.dashboard.recent_orders' => 'Commandes récentes', + /** + * Stock. + */ + 'stock' => 'Stock', + /** + * Addons. + */ + 'addons.show.addon_details' => 'Détails du module complémentaire', + 'addons.show.developer' => 'Développeur', + 'addons.show.marketplace' => 'Place de marché', +]; diff --git a/packages/admin/resources/lang/fr/components.php b/packages/admin/resources/lang/fr/components.php new file mode 100644 index 0000000000..b9e999de82 --- /dev/null +++ b/packages/admin/resources/lang/fr/components.php @@ -0,0 +1,307 @@ + 'Dernier :period jours', + 'products.option-manager.add_btn' => 'Ajouter une option', + 'products.option-manager.toggle_btn' => 'Tout basculer', + 'products.product-selector.select_btn' => 'Sélectionnez les options', + 'products.product-selector.title' => 'Sélectionnez les options', + 'products.product-selector.available_tab' => 'Options disponibles', + 'products.product-selector.selected_tab' => 'Options sélectionnées', + 'products.product-selector.selected_empty' => 'Impossible de trouver des options avec le terme de recherche donné.', + 'products.product-selector.no_results' => 'Impossible de trouver des options avec le terme de recherche donné.', + 'products.product-selector.no_options' => 'Aucune option disponible, créez une nouvelle option pour la voir ici.', + 'products.product-selector.add_new_btn' => 'Créer une nouvelle option', + 'products.product-selector.use_selected_btn' => 'Utiliser les options sélectionnées', + 'products.option-creator.option_placeholder' => 'Par exemple: Couleur', + 'products.option-creator.value_placeholder' => 'Par exemple: Bleu', + 'products.option-creator.min_values_notice' => 'Vous devez avoir au moins :min valeurs.', + 'products.option-creator.values_title' => 'Valeurs des options de produit', + 'products.option-creator.title' => 'Créer une nouvelle option', + 'products.option-creator.add_value_btn' => 'Ajouter la valeur', + 'products.option-creator.create_option_btn' => 'Créer une option', + 'products.option-creator.values_strapline' => 'Ajoutez toutes les différentes valeurs possibles disponibles pour cette option de produit.', + 'product-search.btn' => 'Ajouter des produits', + 'product-search.first_tab' => 'Recherche de produits', + 'product-search.second_tab' => 'Produits sélectionnés', + 'product-search.max_results_exceeded' => 'Affichage de :max sur :total produits. Essayez d\'être plus précis dans votre recherche.', + 'product-search.exists_in_collection' => 'Déjà associé', + 'product-search.no_results' => 'Aucun résultat trouvé.', + 'product-search.pre_search_message' => 'Recherchez des produits par attribut ou SKU.', + 'product-search.select_empty' => 'Lorsque vous sélectionnez des produits, ils apparaîtront ici.', + 'product-search.title' => 'Rechercher des produits', + 'product-search.associate_self' => 'Vous ne pouvez pas associer le même produit', + 'product-search.commit_btn' => 'Sélectionner des produits', + 'product-variant-search.btn' => 'Ajouter des variantes', + 'product-variant-search.first_tab' => 'Rechercher des variantes', + 'product-variant-search.second_tab' => 'Variantes sélectionnées', + 'product-variant-search.max_results_exceeded' => 'Affichage de :max sur :total variantes. Essayez d\'être plus précis dans votre recherche.', + 'product-variant-search.exists_in_collection' => 'Déjà associé', + 'product-variant-search.no_results' => 'Aucun résultat trouvé.', + 'product-variant-search.pre_search_message' => 'Rechercher des variantes par SKU.', + 'product-variant-search.select_empty' => 'Lorsque vous sélectionnez des variantes, elles apparaîtront ici.', + 'product-variant-search.title' => 'Rechercher des variantes', + 'product-variant-search.associate_self' => 'Vous ne pouvez pas associer les mêmes variantes', + 'product-variant-search.commit_btn' => 'Sélectionnez des variantes', + /** + * Option Value Create Modal. + */ + 'ovcm.title' => 'Ajouter une nouvelle option à :name', + /** + * Attribute group create. + */ + 'attribute-group-edit.name.placeholder' => 'Détails supplémentaires', + 'attribute-group-edit.create_btn' => 'Créer un groupe d\'attributs', + 'attribute-group-edit.update_btn' => 'Mettre à jour le groupe d\'attributs', + 'attribute-group-edit.non_unique_handle' => 'Le nom du groupe d\'attributs doit être unique.', + /** + * Attribute show. + */ + 'attributes.show.create_group_btn' => 'Créer un groupe d\'attributs', + 'attributes.show.create_attribute' => 'Créer un attribut', + 'attributes.show.edit_group_btn' => 'Modifier le groupe d\'attributs', + 'attributes.show.edit_attribute_btn' => 'Modifier l\'attribut', + 'attributes.show.delete_group_btn' => 'Supprimer le groupe d\'attributs', + 'attributes.show.edit_title' => 'Modifier le groupe d\'attributs', + 'attributes.show.create_title' => 'Créer un groupe d\'attributs', + 'attributes.show.delete_title' => 'Supprimer le groupe d\'attributs', + 'attributes.show.delete_warning' => 'La suppression de ce groupe de clients supprimera également tous les attributs qui lui sont associés. Cette action ne peut pas être annulée.', + 'attributes.show.group_protected' => 'Ce groupe contient des attributs requis par le système et ne peut donc pas être supprimé.', + 'attributes.show.no_attributes_text' => 'Aucun attribut existant, glissez des attributs existants ou ajoutez-en de nouveaux ici.', + 'attributes.show.delete_attribute_btn' => 'Supprimer l’attribut', + 'attributes.show.delete_attribute_title' => 'Supprimer l’attribut', + 'attributes.show.delete_attribute_warning' => 'Êtes-vous sûr de vouloir supprimer cet attribut ?', + 'attributes.show.delete_attribute_protected' => 'Vous ne pouvez pas supprimer un attribut système.', + 'attributes.show.no_groups' => 'Aucun groupe d’attributs trouvé, ajoutez votre premier groupe avant de pouvoir y ajouter des attributs.', + /** + * Attribute edit. + */ + 'attribute-edit.create_title' => 'Créer un attribut', + 'attribute-edit.update_title' => 'Mettre à jour l’attribut', + 'attribute-edit.system_locked' => 'Cet attribut est requis par le système, donc certains champs sont désactivés.', + 'attribute-edit.name.placeholder' => 'ex. Nom', + 'attribute-edit.required.instructions' => 'Cet attribut est-il obligatoire lors de la modification/création ?', + 'attribute-edit.searchable.instructions' => 'Les utilisateurs doivent-ils pouvoir rechercher via cet attribut ?', + 'attribute-edit.filterable.instructions' => 'Les utilisateurs doivent-ils pouvoir filtrer les résultats en fonction de cet attribut ?', + 'attribute-edit.validation.instructions' => 'Spécifiez toutes les règles de validation Laravel pour cette entrée.', + 'attribute-edit.cancel_btn' => 'Annuler', + 'attribute-edit.save_attribute_btn' => 'Sauvegarder l’attribut', + + /** + * Brand search. + */ + 'brand-search.btn' => 'Ajouter des marques', + 'brand-search.first_tab' => 'Rechercher des marques', + 'brand-search.second_tab' => 'Marques sélectionnées', + 'brand-search.max_results_exceeded' => 'Affichage des premières :max marques sur :total. Essayez d’être plus précis dans votre recherche.', + 'brand-search.exists_in_collection' => 'Déjà associé', + 'brand-search.no_results' => 'Aucun résultat trouvé.', + 'brand-search.pre_search_message' => 'Rechercher des marques par attribut.', + 'brand-search.select_empty' => 'Lorsque vous sélectionnez des marques, elles apparaîtront ici.', + 'brand-search.title' => 'Recherche de marques', + 'brand-search.commit_btn' => 'Sélectionner des marques', + + /** + * Recherche de collections. + */ + 'collection-search.btn' => 'Ajouter des collections', + 'collection-search.first_tab' => 'Rechercher des collections', + 'collection-search.second_tab' => 'Collections sélectionnées', + 'collection-search.max_results_exceeded' => 'Affichage des premières :max collections sur :total. Essayez d’être plus précis dans votre recherche.', + 'collection-search.exists_in_collection' => 'Déjà associé', + 'collection-search.no_results' => 'Aucun résultat trouvé.', + 'collection-search.pre_search_message' => 'Rechercher des collections par attribut.', + 'collection-search.select_empty' => 'Lorsque vous sélectionnez des collections, elles apparaîtront ici.', + 'collection-search.title' => 'Recherche de collections', + 'collection-search.commit_btn' => 'Sélectionner des collections', + + /** + * Clients. + */ + 'customers.show.metrics.total_orders' => 'Total des commandes', + 'customers.show.metrics.avg_spend' => 'Dépense moyenne', + 'customers.show.metrics.total_spend' => 'Dépense totale', + 'customers.show.year_spending' => 'Dépenses de l’année passée', + 'customers.show.purchase_history' => 'Historique d’achat', + 'customers.show.order_history' => 'Historique de commandes', + 'customers.show.users' => 'Utilisateurs', + 'customers.show.addresses' => 'Adresses des clients', + 'customers.show.customer_groups' => 'Groupes de clients', + 'customers.show.save_customer' => 'Sauvegarder le client', + 'customers.show.no_purchase_history' => 'Ce client n’a pas d’historique d’achat.', + 'customers.show.no_order_history' => 'Ce client n’a pas d’historique de commandes.', + 'customers.show.no_users' => 'Ce client n’a pas d’utilisateurs associés.', + 'customers.show.no_addresses' => 'Ce client n’a pas d’adresses.', + 'customers.show.remove_address_btn' => 'Retirer', + 'customers.show.remove_address.title' => 'Retirer l’adresse', + 'customers.show.remove_address.confirm' => 'Êtes-vous sûr de vouloir retirer cette adresse ?', + /** + * Index des commandes + */ + 'orders.index.returning_customer' => 'Client fidèle', + 'orders.index.new_customer' => 'Nouveau client', + /** + * Affichage de la commande. + */ + 'orders.show.title' => 'Commande', + 'orders.show.save_shipping_btn' => 'Sauvegarder l’adresse', + 'orders.show.save_billing_btn' => 'Sauvegarder l’adresse', + 'orders.show.print_btn' => 'Imprimer', + 'orders.show.refund_btn' => 'Rembourser', + 'orders.show.refund_lines_btn' => 'Lignes de remboursement', + 'orders.show.update_status_btn' => 'Mettre à jour le statut', + 'orders.show.more_actions_btn' => 'Plus d’actions', + 'orders.show.show_all_lines_btn' => 'Afficher toutes les lignes', + 'orders.show.additional_lines_text' => ':count lignes supplémentaires sont cachées', + 'orders.show.collapse_lines_btn' => 'Réduire les lignes', + 'orders.show.transactions_header' => 'Transactions', + 'orders.show.timeline_header' => 'Chronologie', + 'orders.show.additional_fields_header' => 'Informations supplémentaires', + 'orders.show.billing_matches_shipping' => 'Identique à l’adresse de livraison', + 'orders.show.billing_header' => 'Adresse de facturation', + 'orders.show.shipping_header' => 'Adresse de livraison', + 'orders.show.requires_capture' => 'Cette commande nécessite encore la capture du paiement.', + 'orders.show.capture_payment_btn' => 'Capturer le paiement', + 'orders.show.partially_refunded' => 'Cette commande a été partiellement remboursée.', + 'orders.show.refunded' => 'Cette commande a été remboursée.', + 'orders.show.view_customer' => 'Voir le client', + 'orders.show.tags_header' => 'Étiquettes', + 'orders.show.download_pdf' => 'Télécharger le PDF', + + /** + * Remboursement de la commande. + */ + 'orders.refund.confirm_text' => 'CONFIRMER', + 'orders.refund.confirm_message' => 'Veuillez confirmer que vous souhaitez rembourser ce montant.', + 'orders.refund.no_charges' => 'Il n’y a pas de frais remboursables sur cette commande', + 'orders.refund.select_transaction' => 'Sélectionner une transaction', + 'orders.refund.refund_btn' => 'Envoyer le remboursement', + 'orders.refund.fully_refunded' => 'Les captures de cette commande ont été remboursées', + /** + * Index des marques. + */ + 'brands.index.title' => 'Marques', + 'brands.index.create_brand' => 'Créer une marque', + 'brands.index.table_row_action_text' => 'Modifier la marque', + 'brands.index.table_count_header_text' => 'Nombre de produits', + 'brands.choose_brand_default_option' => 'Sans marque', + /** + * Index des produits. + */ + 'products.index.title' => 'Produits', + 'products.index.create_product' => 'Créer un produit', + 'products.index.selected_products' => 'Vous avez sélectionné :count produits, voulez-vous sélectionner tous', + 'products.index.you_have_selected_all' => 'Vous avez sélectionné tous les :count produits.', + 'products.index.select_all_btn' => 'Sélectionner tout', + 'products.index.deselect_all_btn' => 'Désélectionner tout', + 'products.index.draft' => 'Brouillon', + 'products.index.published' => 'Publié', + 'products.index.deleted' => 'Supprimé', + 'products.index.only_deleted_visible' => 'Seuls les produits supprimés sont actuellement affichés', + 'products.index.products_empty' => 'Impossible de trouver des produits correspondant à la recherche/filtres.', + + /** + * Capture de commande. + */ + 'orders.capture.confirm_text' => 'CONFIRMER', + 'orders.capture.confirm_message' => 'Veuillez confirmer que vous souhaitez capturer ce paiement', + 'orders.capture.no_intents' => 'Il n’y a pas de transactions disponibles pour la capture', + 'orders.capture.select_transaction' => 'Sélectionner une transaction', + 'orders.capture.capture_btn' => 'Capturer le paiement', + + /** + * Statut de la commande. + */ + 'orders.status.update_btn' => 'Mettre à jour le statut', + 'orders.status.select_new' => 'Sélectionner un nouveau statut', + 'orders.status.preview.title' => 'Aperçu du modèle', + 'orders.status.preview.alert' => 'Ceci est un aperçu de l’apparence de votre e-mail.', + 'orders.status.no_status_selected_alert' => 'Sélectionnez un statut de commande pour voir les expéditeurs disponibles.', + 'orders.status.additional-content.label' => 'Contenu supplémentaire', + 'orders.status.additional-content.instructions' => 'Si pris en charge, ajoutez un message supplémentaire à la notification ou à l’expéditeur.', + 'orders.status.mailers.label' => 'Expéditeurs', + 'orders.status.mailers.instructions' => 'Sélectionnez les expéditeurs que vous souhaitez envoyer.', + 'orders.status.mailers.empty' => 'Il n’y a pas d’expéditeurs disponibles pour ce statut.', + 'orders.status.notifications.label' => 'Notifications', + 'orders.status.notifications.instructions' => 'Sélectionnez les notifications que vous souhaitez envoyer.', + 'orders.status.notifications.empty' => 'Il n’y a pas de notifications disponibles pour ce statut.', + 'orders.status.email_addresses.label' => 'Adresses email', + 'orders.status.email_addresses.instructions' => 'Sélectionnez les adresses email que vous souhaitez utiliser', + 'orders.status.additional_email.label' => 'Adresse email supplémentaire', + 'orders.status.additional_email.instructions' => 'Si vous devez utiliser une adresse email personnalisée, saisissez-la ici.', + + /** + * Journal d'activité. + */ + 'activity-log.system' => 'Système', + 'activity-log.orders.status_change' => 'Statut mis à jour', + 'activity-log.orders.order_created' => 'Commande créée', + 'activity-log.orders.capture' => 'Paiement de :amount sur carte se terminant par :last_four', + 'activity-log.orders.authorized' => 'Autorisation de :amount sur carte se terminant par :last_four', + 'activity-log.orders.refund' => 'remboursement de :amount sur carte se terminant par :last_four', + /** + * Modification de la valeur d'option. + */ + 'option.value.edit.create_title' => 'Créer une valeur d’option', + 'option.value.edit.update_title' => 'Mettre à jour la valeur d’option', + 'option.value.edit.delete_locked' => 'Cette valeur d’option ne peut pas être supprimée car elle est requise par :count variantes de produit', + 'option.value.edit.system_locked' => 'Cette valeur d’option est requise par le système, donc certains champs sont désactivés.', + 'option.value.edit.name.placeholder' => 'ex. Nom', + 'option.value.edit.required.instructions' => 'Cette valeur d’option est-elle obligatoire lors de la modification/création ?', + 'option.value.edit.searchable.instructions' => 'Les utilisateurs doivent-ils pouvoir rechercher via cette option.value ?', + 'option.value.edit.filterable.instructions' => 'Les utilisateurs doivent-ils pouvoir filtrer les résultats en fonction de cette option.value ?', + 'option.value.edit.validation.instructions' => 'Spécifiez toutes les règles de validation Laravel pour cette entrée.', + 'option.value.edit.cancel_btn' => 'Annuler', + 'option.value.edit.save_feature.value.btn' => 'Sauvegarder la valeur d’option', + + /** + * Affichage de la valeur d'option. + */ + 'option.create_group_btn' => 'Créer une option', + 'option.create_option_value' => 'Créer une valeur d’option', + 'option.update_option_value' => 'Mettre à jour la valeur d’option', + 'option.value_title' => 'Valeurs d’option de produit', + 'option.save_positions' => 'Sauvegarder les positions', + 'option.edit_group_btn' => 'Modifier l’option', + 'option.edit_option.value.btn' => 'Modifier la valeur d’option', + 'option.delete_group_btn' => 'Supprimer l’option', + 'option.edit_title' => 'Modifier l’option', + 'option.create_title' => 'Créer une option', + 'option.delete_title' => 'Supprimer une option', + 'option.delete_warning' => 'Vous ne pouvez pas supprimer une option qui a des valeurs associées.', + 'option.group_protected' => 'Ce groupe contient des valeurs d’option requises par le système et ne peut donc pas être supprimé.', + 'option.no_option_values_text' => 'Aucune valeur d’option existante.', + 'option.delete_option.value.btn' => 'Supprimer la valeur d’option', + 'option.delete_option.value.title' => 'Supprimer la valeur de caractéristique', + 'option.delete_option.value.warning' => 'Êtes-vous sûr de vouloir supprimer cette valeur d’option ?', + 'option.delete_option.value.protected' => 'Vous ne pouvez pas supprimer une option.value système.', + 'option.no_groups' => 'Aucune option trouvée, ajoutez la première avant de pouvoir y ajouter des valeurs d’option.', + + /** + * Modification d'option. + */ + 'option-edit.create_btn' => 'Créer une option', + 'option-edit.update_btn' => 'Mettre à jour l’option', + 'option.value.edit.save_option.value.btn' => 'Sauvegarder la valeur d’option', + /** + * Réductions. + */ + 'discounts.index.title' => 'Réductions', + 'discounts.index.status.pending' => 'En attente', + 'discounts.index.status.active' => 'Actif', + 'discounts.index.status.scheduled' => 'Planifié', + 'discounts.index.status.expired' => 'Expiré', + 'discounts.index.create_discount' => 'Créer une réduction', + 'discounts.create.title' => 'Créer une réduction', + 'discounts.create_btn' => 'Créer une réduction', + 'discounts.save_btn' => 'Sauvegarder la réduction', + 'discounts.show.stop.label' => 'Arrêter l’application d’autres réductions après celle-ci', + 'discounts.show.danger_zone.label' => 'Supprimer la réduction', + 'discounts.show.danger_zone.instructions' => 'Entrez le nom de la réduction pour confirmer la suppression.', + + /** + * Composant URL du modèle + */ + 'model-url.preview' => 'Aperçu', + 'model-url.view' => 'Voir', +]; diff --git a/packages/admin/resources/lang/fr/fieldtypes.php b/packages/admin/resources/lang/fr/fieldtypes.php new file mode 100644 index 0000000000..63d00ad8c7 --- /dev/null +++ b/packages/admin/resources/lang/fr/fieldtypes.php @@ -0,0 +1,26 @@ + 'Texte', + 'translated-text.label' => 'Texte traduit', + 'number.label' => 'Nombre', + 'list.label' => 'Liste', + 'dropdown.label' => 'Menu déroulant', + 'dropdown.missing_labels' => 'Vous devez vous assurer que chaque ligne a une étiquette', + 'dropdown.value_placeholder' => 'Laisser vide pour utiliser l’étiquette', + 'file.label' => 'Téléchargement de fichier', + 'file.max_files.label' => 'Nombre maximum de fichiers', + 'file.choose_assets' => 'Choisir des ressources', + 'file.uploads_empty' => 'Les fichiers que vous téléchargez apparaîtront ici.', + 'file.select_files' => 'Sélectionner des fichiers', + 'dropdown.label_heading' => 'Étiquette', + 'dropdown.value_heading' => 'Valeur', + 'dropdown.add_row_btn' => 'Ajouter une ligne', + 'dropdown.empty_selection' => 'Sélectionner une valeur', + 'toggle.label' => 'Bascule', + 'toggle.empty_notice' => 'Laisser vide pour utiliser les valeurs booléennes par défaut', + 'toggle.on_label' => 'Valeur activée', + 'toggle.off_label' => 'Valeur désactivée', + 'youtube.label' => 'Vidéo YouTube', + 'richtext.config' => 'Vous pouvez entrer toute configuration disponible ci-dessous prise en charge par :url.', +]; diff --git a/packages/admin/resources/lang/fr/global.php b/packages/admin/resources/lang/fr/global.php new file mode 100644 index 0000000000..22751946b3 --- /dev/null +++ b/packages/admin/resources/lang/fr/global.php @@ -0,0 +1,131 @@ + 'Prénom', + 'lastname' => 'Nom de famille', + 'name' => 'Nom', + 'handle' => 'Identifiant', + 'url' => 'URL', + 'version' => 'Version', + 'verified' => 'Vérifié', + 'author' => 'Auteur', + 'current_version' => 'Version actuelle', + 'latest_version' => 'Dernière version', + 'email' => 'Adresse email', + 'active' => 'Actif', + 'code' => 'Code', + 'default' => 'Par défaut', + 'exchange_rate' => 'Taux de change', + 'format' => 'Format', + 'decimal_point' => 'Point décimal', + 'thousand_point' => 'Séparateur de milliers', + 'enabled' => 'Activé', + 'info_link' => 'Qu’est-ce que c’est ?', + 'licensed' => 'Sous licence', + 'primary' => 'Principal', + 'thumbnail' => 'Vignette', + 'alt_text' => 'Texte alt.', + 'delete' => 'Supprimer', + 'restore' => 'Restaurer', + 'options' => 'Options', + 'sku' => 'SKU', + 'unit_price_inc_tax' => 'Prix unitaire (TTC)', + 'unit_price_excl_tax' => 'Prix unitaire (HT)', + 'stock_incoming' => 'Stock (entrée)', + 'attribute_type' => 'Type d’attribut', + 'type' => 'Type', + 'required' => 'Requis', + 'no_of_products' => 'Nb de produits', + 'no_of_attributes' => 'Nb d’attributs', + 'cancel' => 'Annuler', + 'add' => 'Ajouter', + 'remove' => 'Retirer', + 'customer_group' => 'Groupe de clients', + 'lower_limit' => 'Limite inférieure', + 'language' => 'Langue', + 'slug' => 'Slug', + 'edit' => 'Modifier', + 'deselect' => 'Désélectionner', + 'select' => 'Sélectionner', + 'deleting' => 'Suppression', + 'company_name' => 'Nom de l’entreprise', + 'vat_no' => 'N° de TVA', + 'view' => 'Voir', + 'save' => 'Sauvegarder', + 'current_password' => 'Mot de passe actuel', + 'new_password' => 'Nouveau mot de passe', + 'confirm_password' => 'Confirmer le mot de passe', + 'attribute_groups' => 'Groupes d’attributs', + 'attributes' => 'Attributs', + 'product' => 'Produit', + 'id' => 'ID', + 'user' => 'Utilisateur', + 'status' => 'Statut', + 'reference' => 'Référence', + 'date' => 'Date', + 'filter' => 'Filtrer', + 'clear' => 'Effacer', + 'time' => 'Heure', + 'notes' => 'Notes', + 'hi' => 'Salut,', + 'users' => 'Utilisateurs', + 'orders' => 'Commandes', + 'order' => 'Commande', + 'update_status' => 'Mettre à jour le statut', + 'description' => 'Description', + 'option' => 'Option', + 'quantity' => 'Quantité', + 'sub_total' => 'Sous-total', + 'tax' => 'Taxe', + 'discount' => 'Remise', + 'total' => 'Total', + 'identifier' => 'Identifiant', + 'success' => 'Succès', + 'refund' => 'Remboursement', + 'amount' => 'Montant', + 'card_type' => 'Type de carte', + 'last_four' => 'Quatre derniers chiffres', + 'guest' => 'Invité', + 'retail' => 'Détail', + 'trade' => 'Commerce', + 'in_stock' => 'En stock', + 'always' => 'Toujours', + 'expected' => 'Attendu', + 'inventory' => 'Inventaire', + 'edit_stock' => 'Modifier le stock', + '45_units_in_transfer' => '45 unités en transfert', + '500_units_in_stock' => '500 unités en stock', + 'published' => 'Publié', + 'any' => 'N’importe quel', + 'draft' => 'Brouillon', + 'system' => 'Système', + 'dashboard' => 'Tableau de bord', + 'to' => 'à', + 'new_products' => 'Nouveaux produits', + 'new_product' => 'Nouveau produit', + 'order_ref' => 'Réf. de commande', + 'customer' => 'Client', + 'no_items' => 'Nb d’articles', + 'placed_at' => 'Passé à', + 'settings' => 'Paramètres', + 'admin' => 'Admin', + 'under_construction' => 'En construction', + 'building_hub' => 'Nous construisons actuellement cette partie du hub, merci de votre patience !', + 'reach_out' => 'N’hésitez pas à nous contacter sur notre', + 'discord_server' => 'serveur Discord', + 'for_updates' => 'pour des mises à jour.', + 'export' => 'Exporter', + 'brand' => 'Marque', + 'stock' => 'Stock', + 'show_deleted' => 'Afficher supprimés', + 'starts_at' => 'Commence à', + 'ends_at' => 'Finit à', + 'priority' => 'Priorité', + 'stop' => 'Arrêter', + 'preview' => 'Aperçu', + 'delivery_instructions' => 'Instructions de livraison', + 'not_provided' => 'Non fourni', + 'billing_email' => 'Email de facturation', + 'add_new' => 'Ajouter nouveau', + 'store' => 'Boutique', +]; diff --git a/packages/admin/resources/lang/fr/inputs.php b/packages/admin/resources/lang/fr/inputs.php new file mode 100644 index 0000000000..f0066178b3 --- /dev/null +++ b/packages/admin/resources/lang/fr/inputs.php @@ -0,0 +1,115 @@ + 'Titre', + 'firstname' => __('adminhub::global.firstname'), + 'lastname' => __('adminhub::global.lastname'), + 'name' => 'Nom', + 'label' => 'Étiquette', + 'handle' => 'Identifiant', + 'code' => 'Code', + 'min' => 'Min', + 'max' => 'Max', + 'url' => __('adminhub::global.url'), + 'email' => __('adminhub::global.email'), + 'remember_me' => 'Se souvenir de moi', + 'new_password' => 'Nouveau mot de passe', + 'new_password_confirmation' => 'Confirmer le nouveau mot de passe', + 'password' => 'Mot de passe', + 'password_confirmation' => 'Confirmation du mot de passe', + 'danger_zone.title' => 'Zone de danger !', + 'danger_zone.label' => 'Supprimer :model', + 'danger_zone.instructions' => 'Entrez le :attribute du :model pour le supprimer.', + 'restore_zone.title' => 'Restaurer l’enregistrement', + 'restore_zone.label' => 'Restaurer :model', + 'decimal_places' => 'Décimales', + 'exchange_rate' => __('adminhub::global.exchange_rate'), + 'format' => __('adminhub::global.format'), + 'decimal_point' => __('adminhub::global.decimal_point'), + 'thousand_point' => __('adminhub::global.thousand_point'), + 'enabled.label' => __('adminhub::global.enabled'), + 'default.label' => 'Par défaut', + 'default.instructions' => 'Définir si ce :model est le défaut, cela remplacera le défaut actuel.', + 'attribute_group' => 'Groupe d’attributs', + 'attribute_type.label' => 'Type d’attribut', + 'attribute_type.instructions' => 'Cela déterminera quels modèles peuvent utiliser cet attribut.', + 'type.label' => 'Type', + 'type.instructions' => 'Choisissez quel type d’attribut cela sera.', + 'required' => 'Requis', + 'tags.label' => 'Étiquettes', + 'base_price_inc_tax.label' => 'Prix de base (TTC)', + 'base_price_inc_tax.instructions' => 'Le prix de base du produit, taxes incluses', + 'base_price_excl_tax.label' => 'Prix de base (HT)', + 'base_price_excl_tax.instructions' => 'Le prix de base du produit, hors taxes', + 'compare_at_price_excl_tax.label' => 'Comparer au prix (HT)', + 'compare_at_price_excl_tax.instructions' => 'À des fins d’affichage, vous permet de montrer un prix de comparaison, par ex. RRP.', + 'compare_at_price_inc_tax.label' => 'Comparer au prix (TTC)', + 'compare_at_price_inc_tax.instructions' => 'À des fins d’affichage, vous permet de montrer un prix de comparaison, par ex. RRP.', + 'unit_quantity.label' => 'Quantité unitaire', + 'unit_quantity.instructions' => 'Entrez combien d’unités individuelles composent ce prix.', + 'sku.label' => 'SKU', + 'gtin.label' => 'Numéro Global de l’Article Commercial (GTIN)', + 'mpn.label' => 'Numéro de pièce du fabricant (MPN)', + 'ean.label' => 'UPC/EAN', + 'brand.label' => 'Marque', + 'product-type.label' => 'Type de produit', + 'stock.label' => 'Stock', + 'purchasable.label' => 'Achetable', + 'backorder.label' => 'Commande en attente', + 'requires_shipping.label' => 'Nécessite une livraison', + 'length.label' => 'Longueur', + 'width.label' => 'Largeur', + 'height.label' => 'Hauteur', + 'weight.label' => 'Poids', + 'volume.label' => 'Volume', + 'language.label' => 'Langue', + 'slug.label' => 'Slug', + 'tax_class.label' => 'Classe de taxe', + 'value' => 'Valeur', + 'searchable.label' => 'Recherchable', + 'required.label' => 'Requis', + 'filterable.label' => 'Filtrable', + 'validation_rules.label' => 'Règles de validation', + 'min.label' => 'Min.', + 'max.label' => 'Max.', + 'tax_ref.label' => 'Référence fiscale', + 'tax_ref.instructions' => 'Ajoutez la référence fiscale tierce, si nécessaire.', + 'company_name.label' => 'Nom de l’entreprise', + 'vat_no.label' => 'N° de TVA', + 'account_ref.label' => 'Référence de compte', + 'from_date.label' => 'À partir de la date', + 'to_date.label' => 'Jusqu’à la date', + 'select_option.label' => 'Sélectionner une option', + 'status.label' => 'Statut', + 'phone.label' => 'Téléphone', + 'address_line_one.label' => 'Adresse ligne 1', + 'address_line_two.label' => 'Adresse ligne 2', + 'address_line_three.label' => 'Adresse ligne 3', + 'city.label' => 'Ville', + 'state.label' => 'État / Province', + 'postcode.label' => 'Code postal', + 'country.label' => 'Pays', + 'country.search_placeholder' => 'Rechercher un pays par nom', + 'country.empty_selected' => 'Les pays que vous sélectionnez apparaîtront ici', + 'states.label' => 'États', + 'states.search_placeholder' => 'Rechercher un état par nom', + 'states.empty_selected' => 'Les états que vous sélectionnez apparaîtront ici', + 'amount.label' => 'Montant', + 'notes.label' => 'Notes', + 'confirm.label' => 'Confirmer', + 'select_attribute_group' => 'Sélectionner un groupe d’attributs', + 'select_field_type' => 'Sélectionner un type de champ', + 'text' => 'Texte', + 'richtext' => 'Texte riche', + 'transaction.label' => 'Transaction', + 'starts_at.label' => 'Commence à', + 'ends_at.label' => 'Se termine à', + 'tag.label' => 'Étiquette', + 'active.label' => 'Actif', + 'priority.label' => 'Priorité', + 'postcodes.label' => 'Codes postaux', + 'postcodes.instructions' => 'Lister chaque code postal sur une nouvelle ligne. Prend en charge les jokers comme NW*', + 'max_uses.label' => 'Utilisations max', + 'max_uses_per_user.label' => 'Utilisations max par utilisateur', + 'size.placeholder' => 'Taille', +]; diff --git a/packages/admin/resources/lang/fr/licensing.php b/packages/admin/resources/lang/fr/licensing.php new file mode 100644 index 0000000000..b92d37cd34 --- /dev/null +++ b/packages/admin/resources/lang/fr/licensing.php @@ -0,0 +1,6 @@ + "Oups ! Il semble que vous n'ayez pas de licence pour utiliser le Lunar Hub, ou qu'elle soit invalide et nécessite une correction.", + 'banner.unlicensed.btn_text' => 'Obtenir une licence', +]; diff --git a/packages/admin/resources/lang/fr/menu.php b/packages/admin/resources/lang/fr/menu.php new file mode 100644 index 0000000000..46b9ab564a --- /dev/null +++ b/packages/admin/resources/lang/fr/menu.php @@ -0,0 +1,50 @@ + 'Tableau de bord', + 'sidebar.catalogue-manager' => 'Gestionnaire de catalogue', + 'sidebar.products' => 'Produits', + 'sidebar.product-types' => 'Types de produits', + 'sidebar.brands' => 'Marques', + 'sidebar.collections' => 'Collections', + 'sidebar.order-processing' => 'Traitement des commandes', + 'sidebar.orders' => 'Commandes', + 'sidebar.customers' => 'Clients', + 'sidebar.catalogue' => 'Catalogue', + 'sidebar.sales' => 'Ventes', + 'sidebar.discounts' => 'Réductions', + /** + * Menu latéral du produit. + */ + 'product.basic-information' => 'Informations de base', + 'product.choose-existing-btn' => 'Choisir existant', + 'product.attributes' => 'Attributs', + 'product.images' => 'Images', + 'product.image' => 'Image', + 'product.availability' => 'Disponibilité', + 'product.variants' => 'Variantes', + 'product.pricing' => 'Tarification', + 'product.inventory' => 'Inventaire', + 'product.shipping' => 'Livraison', + 'product.associations' => 'Associations', + 'product.urls' => 'URLs', + 'product.associations.title' => 'Associations de produits', + 'product.associations.explain' => 'Les associations de produits vous permettent de relier des produits entre eux.', + 'product.identifiers' => 'Identifiants', + 'product.collections' => 'Collections', + 'product.select-product-image' => 'Sélectionner une image de produit existante', + 'product.choose-image' => 'Choisir une image', + /** + * Éléments de menu génériques. + */ + 'attributes' => 'Attributs', + 'basic-information' => 'Informations de base', + 'images' => 'Images', + 'availability' => 'Disponibilité', + 'urls' => 'URLs', + 'products' => 'Produits', + 'collections' => 'Collections enfants', + 'dropdown-options' => 'Ouvrir les options', + 'open-sidebar' => 'Ouvrir le menu latéral', + 'close-sidebar' => 'Fermer le menu latéral', +]; diff --git a/packages/admin/resources/lang/fr/notifications.php b/packages/admin/resources/lang/fr/notifications.php new file mode 100644 index 0000000000..6b498920b1 --- /dev/null +++ b/packages/admin/resources/lang/fr/notifications.php @@ -0,0 +1,68 @@ + 'Produit supprimé', + 'urls.deleted' => 'URL supprimée', + 'urls.updated' => 'URL mise à jour', + 'urls.created' => 'URL créée', + 'variants.deleted' => 'Variante supprimée', + 'variants.created' => 'Variante créée', + 'variants.minimum_reached' => 'Vous devez avoir au moins une variante', + 'brands.added' => 'Marque ajoutée', + 'brands.updated' => 'Marque mise à jour.', + 'brands.deleted' => 'Marque supprimée.', + 'brands.delete_protected' => 'Cette marque ne peut pas être supprimée car il y a des produits associés.', + 'collections.moved_child' => 'Collection déplacée dans :target', + 'collections.moved_root' => 'Collection déplacée en haut', + 'collections.added' => 'Collection ajoutée', + 'collections.deleted' => 'Collection supprimée', + 'collections.reordered' => 'Collections réordonnées', + 'collection-groups.updated' => 'Groupe de collections mis à jour', + 'collection-groups.deleted' => 'Groupe de collections supprimé', + 'option-values.created' => 'Valeur d’option créée', + 'product-options.created' => 'Option de produit créée', + 'product-options.deleted' => 'Option de produit supprimée', + 'product-options.reordered' => 'Option de produit réordonnée', + 'product-options.not.deleted' => 'Option de produit non supprimée car il y a des valeurs associées', + 'password-reset.invalid_token' => 'Jeton de réinitialisation invalide', + 'password-reset.password_updated' => 'Mot de passe mis à jour', + 'password-reset.email_sent' => 'Réinitialisation du mot de passe envoyée', + 'account.updated' => 'Compte mis à jour', + 'attribute-groups.reordered' => 'Groupes d’attributs réordonnés', + 'attributes.reordered' => 'Attributs réordonnés', + 'attribute-groups.created' => 'Groupe d’attributs créé', + 'attribute-groups.updated' => 'Groupe d’attributs mis à jour', + 'attribute-groups.deleted' => 'Groupe d’attributs supprimé', + 'attribute-groups.delete_protected' => 'Vous ne pouvez pas supprimer un groupe avec des attributs système', + 'attribute-edit.created' => 'Attribut créé', + 'attribute-edit.updated' => 'Attribut mis à jour', + 'attributes.deleted' => 'Attribut supprimé', + 'customers.user_removed' => 'Utilisateur supprimé', + 'customers.reset_failed' => 'Impossible d’envoyer la réinitialisation du mot de passe', + 'customers.address_updated' => 'Adresse mise à jour', + 'customers.address_removed' => 'Adresse supprimée', + 'customer.updated' => 'Client mis à jour', + 'saved_searches.saved' => 'Recherche sauvegardée', + 'saved_searches.deleted' => 'Recherche supprimée', + 'billing_address.saved' => 'Adresse de facturation sauvegardée', + 'shipping_address.saved' => 'Adresse de livraison sauvegardée', + 'order.status_updated' => 'Statut de la commande mis à jour', + 'order.comment_added' => 'Commentaire ajouté', + 'image.deleted' => 'Image supprimée', + 'sorry' => 'Désolé !', + 'search-results.none' => 'Nous n’avons trouvé aucun résultat basé sur votre recherche.', + 'addon.not_licensed' => 'Cette extension n’est pas sous licence, veuillez vérifier la configuration de cette extension.', + 'product.no-images-associated' => 'Le produit n’a aucune image associée', + 'products.product_restored' => 'Produit restauré', + 'tax_class.saved' => 'Classe fiscale sauvegardée', + 'tax_class.deleted' => 'Classe fiscale supprimée', + 'clipboard.copied' => 'Copié dans le presse-papier', + 'clipboard.failed_copy' => 'Impossible de copier dans le presse-papier', + 'discount.saved' => 'Réduction sauvegardée', + 'discount.deleted' => 'Réduction supprimée', + 'tags.updated' => 'Étiquettes mises à jour', + 'staff.restored' => 'Membre du personnel restauré', + 'default_url_protected' => 'Impossible de supprimer l’URL par défaut', + 'product_option_value.deleted' => 'Valeur d’option de produit supprimée', + 'product_option_value.updated' => 'Valeur d’option de produit mise à jour', +]; diff --git a/packages/admin/resources/lang/fr/orders.php b/packages/admin/resources/lang/fr/orders.php new file mode 100644 index 0000000000..438c075d8c --- /dev/null +++ b/packages/admin/resources/lang/fr/orders.php @@ -0,0 +1,21 @@ + 'Commandes', + 'index.export_btn' => 'Exporter les commandes', + 'index.save_search.title' => 'Enregistrer la recherche', + 'index.save_search.btn' => 'Enregistrer la recherche', + 'index.all_orders' => 'Toutes les commandes', + 'index.search_placeholder' => 'Rechercher...', + 'index.update_status.btn' => 'Mettre à jour le statut', + 'index.update_status.title' => 'Mettre à jour le statut', + 'index.delete_saved_search.title' => 'Supprimer la recherche enregistrée', + 'index.delete_saved_search.confirm' => 'Êtes-vous sûr de vouloir supprimer cette recherche enregistrée ?', + 'index.delete_saved_search.btn' => 'Confirmer la suppression', + 'update_status.btn' => 'Mettre à jour le statut', + 'update_status.title' => 'Mettre à jour le statut', + 'show.title' => 'Commande n°:id', +]; diff --git a/packages/admin/resources/lang/fr/partials.php b/packages/admin/resources/lang/fr/partials.php new file mode 100644 index 0000000000..32a5fffa00 --- /dev/null +++ b/packages/admin/resources/lang/fr/partials.php @@ -0,0 +1,219 @@ + 'Ajouté :count images', + 'activity-log.system.system' => 'Système', + 'activity-log.update.updated' => 'Mis à jour', + 'activity-log.create.created' => 'Créé', + /** + * Associations. + */ + 'products.associations.heading' => 'Associations', + 'products.associations.cross-sell' => 'Vente croisée', + 'products.associations.up-sell' => 'Vente incitative', + 'products.associations.alternate' => 'Alternatif', + 'products.associations.show_inverse' => 'Montrer inverse', + 'products.associations.add_inverse' => 'Ajouter une association inverse', + 'products.associations.add_association' => 'Ajouter une association', + 'products.associations.up-sell_selecting_products' => 'Ajouter des produits de vente incitative en recherchant ci-dessus et en sélectionnant des produits.', + /** + * Disponibilité. + */ + 'availability.heading' => 'Disponibilité', + 'availability.schedule_notice' => "Lorsque vous planifiez la disponibilité, ce :type ne sera pas disponible pour le canal/groupe de clients jusqu'à ce que la date soit passée et que le :type soit actif.", + 'availability.channel_heading' => 'Canaux', + 'availability.channel_strapline' => 'Sélectionnez sur quels canaux ce :type est disponible.', + 'availability.channels.hidden' => 'Caché', + 'availability.channels.purchasable' => 'Achetable', + 'availability.channels.strapline' => 'Planifiez pour quels groupes de clients ce :type est disponible.', + 'availability.channels.scheduled_from' => 'Planifié à partir du :datetime', + 'availability.channels.scheduled_to' => 'Disponible jusqu’au :datetime', + 'availability.channels.scheduled_range' => 'De :from jusqu’à :to', + 'availability.channels.scheduled_always' => 'Toujours disponible', + 'availability.channels.scheduled_never' => 'Jamais disponible', + 'availability.channels.schedule_modal.title' => 'Planifier la disponibilité', + 'availability.channels.schedule_modal.starts_at.label' => 'Commence à', + 'availability.channels.schedule_modal.starts_at.instructions' => 'Définir quand ce groupe de clients sera disponible à partir de, aucune date indique toujours disponible.', + 'availability.channels.schedule_modal.ends_at.label' => 'Se termine à', + 'availability.channels.schedule_modal.ends_at.instructions' => 'Définir quand ce groupe de clients sera disponible jusqu’à, aucune date indique toujours disponible.', + 'availability.channels.schedule_modal.btn_text' => 'Accepter & Fermer', + 'availability.scheduled_text' => 'Ce :type est planifié pour être publié le :date.', + 'availability.schedule_placeholder' => 'Planifier la date de publication.', + 'availability.schedule_btn_text' => 'Planifier la disponibilité', + 'availability.clear_btn' => 'Effacer', + 'availability.customer_groups.title' => 'Groupes de clients', + 'availability.customer_groups.visible' => 'Visible', + 'availability.customer_groups.hidden' => 'Caché', + 'availability.customer_groups.purchasable' => 'Achetable', + 'availability.customer_groups.strapline' => 'Planifiez pour quels groupes de clients ce :type est disponible.', + 'availability.customer_groups.scheduled_from' => 'Planifié à partir du :datetime', + 'availability.customer_groups.scheduled_to' => 'Disponible jusqu’au :datetime', + 'availability.customer_groups.scheduled_range' => 'De :from jusqu’à :to', + 'availability.customer_groups.scheduled_always' => 'Toujours disponible', + 'availability.customer_groups.scheduled_never' => 'Jamais disponible', + 'availability.customer_groups.schedule_modal.title' => 'Planifier la disponibilité', + 'availability.customer_groups.schedule_modal.starts_at.label' => 'Commence à', + 'availability.customer_groups.schedule_modal.starts_at.instructions' => 'Définir quand ce groupe de clients sera disponible à partir de, aucune date indique toujours disponible.', + 'availability.customer_groups.schedule_modal.ends_at.label' => 'Se termine à', + 'availability.customer_groups.schedule_modal.ends_at.instructions' => 'Définir quand ce groupe de clients sera disponible jusqu’à, aucune date indique toujours disponible.', + 'availability.customer_groups.schedule_modal.btn_text' => 'Accepter & Fermer', + /** + * Informations de base. + */ + 'products.basic-information.heading' => 'Informations de base', + /** + * Gestionnaire d'images. + */ + 'image-manager.generic_upload_error' => 'Problème lors du téléchargement, veuillez vérifier que vous avez sélectionné uniquement des images.', + 'image-manager.heading' => 'Images', + 'image-manager.download_original_btn' => 'Télécharger l’originale', + 'image-manager.remake_transforms' => 'Refabriquer les transformations', + 'image-manager.remake_transforms.notify.success' => 'Les transformations d’image ont été régénérées', + 'image-manager.save_btn' => 'Sauvegarder l’image', + 'image-manager.edit_row_btn' => 'Modifier', + 'image-manager.delete_row_btn' => 'Supprimer', + 'image-manager.delete_primary' => 'Vous ne pouvez pas supprimer l’image principale.', + 'image-manager.delete_message' => 'Cette image sera supprimée à l’enregistrement,', + 'image-manager.undo_btn' => 'annuler', + 'image-manager.no_results' => 'Aucune image existante pour ce produit, ajoutez votre première image ci-dessus.', + 'image-manager.upload_file' => 'Téléchargez un fichier ou glissez et déposez', + 'image-manager.file_format' => 'PNG, JPG, GIF jusqu’à 10 Mo', + 'image-manager.select_images' => 'Sélectionner des images', + 'image-manager.select_images_btn' => 'Sélectionner des images', + /** + * Réductions + */ + 'discounts.limitations.heading' => 'Limitations et exclusions', + 'discounts.limitations.by_collection' => 'Par collection', + 'discounts.limitations.by_brand' => 'Par marque', + 'discounts.limitations.by_product' => 'Par produit', + 'discounts.limitations.by_product_variant' => 'Par variante de produit', + 'discounts.limitations.view_brand' => 'Voir la marque', + 'discounts.limitations.view_product' => 'Voir le produit', + 'discounts.limitations.view_product_variant' => 'Voir la variante de produit', + 'discounts.limitations.limitation' => 'Limitation', + 'discounts.limitations.exclusion' => 'Exclusion', + /** + * Collections de produits. + */ + 'products.collections.heading' => 'Collections', + 'products.collections.view_collection' => 'Voir la collection', + /** + * Barre de statut du produit. + */ + 'products.status-bar.published.label' => 'Publié', + 'products.status-bar.published.description' => 'Ce produit sera disponible sur tous les canaux et groupes de clients activés.', + 'products.status-bar.draft.label' => 'Brouillon', + 'products.status-bar.draft.description' => 'Ce produit sera caché de tous les canaux et groupes de clients.', + /** + * Variantes. + */ + 'products.variants.heading' => 'Variantes', + 'products.variants.strapline' => 'Ce produit a plusieurs options, comme différentes tailles ou couleurs.', + 'products.variants.table_row_action_text' => 'Modifier', + 'products.variants.table_row_delete_text' => 'Supprimer', + 'products.variants.removal_message' => 'Cela supprimera toutes les variantes de ce produit', + /** + * Type de produit. + */ + 'product-type.available_title' => 'Attributs disponibles', + 'product-type.selected_title' => 'Attributs sélectionnés (:count)', + 'product-type.attribute_search_placeholder' => 'Rechercher un attribut par nom', + 'product-type.attribute_system_required' => 'Cet attribut est requis par le système', + 'product-type.product_attributes_btn' => 'Attributs du produit', + 'product-type.variant_attributes_btn' => 'Attributs de la variante', + /** + * Tarification. + */ + 'pricing.title' => 'Tarification', + 'pricing.customer_groups.title' => 'Tarification par groupe de clients', + 'pricing.customer_groups.strapline' => 'Détermine si vous souhaitez des prix différents pour les différents groupes de clients.', + 'pricing.tiers.title' => 'Tarification par paliers', + 'pricing.tiers.strapline' => 'La tarification par paliers vous permet d\'offrir une tarification réduite en fonction des unités vendues.', + 'pricing.non_default_currency_alert' => 'Certains champs ne peuvent être modifiés que lors de l\'utilisation de la devise par défaut.', + 'pricing.tiers.add_tier_btn' => 'Ajouter un palier', + /** + * Identifiants. + */ + 'identifiers.title' => 'Identifiants de produit', + /** + * URLs. + */ + 'urls.title' => 'URLs', + 'urls.create_btn' => 'Ajouter une URL', + /** + * Inventaire. + */ + 'inventory.title' => 'Inventaire', + 'inventory.maintenance_notice' => 'Cette section est encore en développement et est susceptible de changer dans une prochaine version.', + 'inventory.options.in_stock' => 'En stock', + 'inventory.options.always' => 'Toujours', + 'inventory.options.backorder' => 'En commande', + 'inventory.purchasable.in_stock' => 'Cet article ne peut être acheté que s\'il est en stock.', + 'inventory.purchasable.always' => 'Cet article peut toujours être acheté.', + 'inventory.purchasable.backorder' => 'Cet article peut être acheté lorsque le stock est attendu.', + /** + * Expédition. + */ + 'shipping.title' => 'Expédition', + 'shipping.calculated_volume' => 'Calculé à :value.', + 'shipping.manual_volume_btn' => 'Cliquez pour définir manuellement', + 'shipping.auto_volume_btn' => 'Utiliser le volume généré', + /** + * Adresses des clients. + */ + 'customers.addresses.billing_default' => 'Par défaut pour la facturation', + 'customers.addresses.shipping_default' => 'Par défaut pour l\'expédition', + /** + * Clients. + */ + 'customers.purchase-history.purchasable' => 'Achetable', + 'customers.purchase-history.identifier' => 'Identifiant', + 'customers.purchase-history.quantity' => 'Quantité', + 'customers.purchase-history.revenue' => 'Revenu', + 'customers.purchase-history.order_count' => 'N° de commandes', + 'customers.purchase-history.last_ordered' => 'Dernière commande', + /** + * Commandes. + */ + 'orders.totals.sub_total' => 'Sous-total', + 'orders.totals.shipping_total' => 'Total expédition', + 'orders.totals.total' => 'Total', + 'orders.totals.notes_empty' => 'Pas de notes sur cette commande', + 'orders.totals.discount_total' => 'Total de réduction', + 'orders.lines.unit_price' => 'Prix unitaire', + 'orders.lines.quantity' => 'Quantité', + 'orders.lines.sub_total' => 'Sous-total', + 'orders.lines.discount_total' => 'Total de réduction', + 'orders.lines.total' => 'Total', + 'orders.lines.current_stock_level' => 'Niveau de stock actuel : :count', + 'orders.lines.purchase_stock_level' => 'au moment de la commande : :count', + 'orders.details.status' => 'Statut', + 'orders.details.reference' => 'Référence', + 'orders.details.customer_reference' => 'Référence client', + 'orders.details.channel' => 'Canal', + 'orders.details.date_created' => 'Date de création', + 'orders.details.date_placed' => 'Date de commande', + 'orders.details.new_returning' => 'Nouveau / Retour', + 'orders.details.new_customer' => 'Nouveau client', + 'orders.details.returning_customer' => 'Client existant', + 'orders.address.not_set' => 'Aucune adresse définie', + /** + * Formulaires. + */ + 'forms.channel.delete_channel' => 'Supprimer le canal', + 'forms.channel.channel_name_delete' => 'Entrez le nom du canal à supprimer', + 'forms.brand_delete_brand' => 'Supprimer la marque', + 'forms.brand_name_delete' => 'Entrez le nom de la marque à supprimer', + 'forms.customer-group.delete_customer_group' => 'Supprimer le groupe de clients', + 'forms.customer-group.customer_group_name_delete' => 'Entrez le nom du groupe de clients à supprimer', + /** + * Transactions. + */ + 'orders.transactions.capture' => 'Capturé', + 'orders.transactions.intent' => 'Intention', + 'orders.transactions.refund' => 'Remboursé', +]; diff --git a/packages/admin/resources/lang/fr/settings.php b/packages/admin/resources/lang/fr/settings.php new file mode 100644 index 0000000000..cef9b48589 --- /dev/null +++ b/packages/admin/resources/lang/fr/settings.php @@ -0,0 +1,180 @@ + 'Canaux', + 'channels.index.create_btn' => 'Créer un canal', + 'channels.index.table_row_action_text' => 'Modifier le canal', + /** + * Page de détail des canaux. + */ + 'channels.show.title' => 'Modifier le canal', + /** + * Page de création de canaux. + */ + 'channels.create.title' => 'Créer un canal', + /** + * Mise en page des paramètres. + */ + 'layout.menu_btn' => 'Menu des paramètres', + /** + * Page de liste du personnel. + */ + 'staff.index.title' => 'Personnel', + 'staff.index.search_placeholder' => 'Rechercher du personnel', + 'staff.index.active_filter' => 'Afficher les inactifs', + 'staff.index.create_btn' => 'Ajouter un membre du personnel', + 'staff.index.table_row_action_text' => 'Modifier le personnel', + /** + * Page de détail du personnel. + */ + 'staff.show.title' => 'Modifier le personnel', + 'staff.show.delete_btn' => 'Désactiver le compte', + 'staff.show.delete_title' => 'Supprimer le personnel', + 'staff.show.restore_title' => 'Restaurer le personnel', + /** + * Page de création du personnel. + */ + 'staff.create.title' => 'Créer un membre du personnel', + /** + * Formulaire du personnel. + */ + 'staff.form.create_btn' => 'Créer un membre du personnel', + 'staff.form.update_btn' => 'Mettre à jour le membre du personnel', + 'staff.form.permissions_heading' => 'Permissions', + 'staff.form.permissions_description' => 'Gérer les permissions individuelles d\'un membre du personnel.', + 'staff.form.admin_message' => 'Un utilisateur administrateur a accès à toutes les permissions.', + 'staff.form.danger_zone.label' => 'Supprimer le membre du personnel', + 'staff.form.danger_zone.delete_strapline' => 'La suppression d\'un membre du personnel arrêtera tout accès au hub, vous pourrez le restaurer ultérieurement.', + 'staff.form.danger_zone.restore_strapline' => 'Restaurer le compte de ce membre du personnel afin qu\'il puisse accéder au hub.', + 'staff.form.danger_zone.own_account' => 'La suppression de votre propre compte vous déconnectera instantanément.', + /** + * Page de liste des modules complémentaires. + */ + 'addons.index.title' => 'Modules complémentaires', + 'addons.index.table_row_action_text' => 'Voir', + /** + * Page de détail des modules complémentaires. + */ + 'addons.show.title' => 'Module complémentaire', + /* + * Page de liste des langues. + */ + 'languages.index.title' => 'Langues', + 'languages.index.create_btn' => 'Créer une langue', + 'languages.index.table_row_action_text' => 'Modifier la langue', + /** + * Page de création des langues. + */ + 'languages.create.title' => 'Créer une langue', + /** + * Page de détail des langues. + */ + 'languages.show.title' => 'Modifier la langue', + /** + * Formulaire de langue. + */ + 'languages.form.create_btn' => 'Créer une langue', + 'languages.form.update_btn' => 'Mettre à jour la langue', + 'languages.form.default_instructions' => 'Définir si cette langue est la langue par défaut, cela remplacera la langue actuelle par défaut.', + /** + * Tableau des devises. + */ + 'currencies.index.title' => 'Devises', + 'currencies.index.table_row_action_text' => 'Modifier', + 'currencies.index.no_results' => 'Vous n\'avez actuellement aucune devise dans le système.', + /** + * Page de détail des devises. + */ + 'currencies.show.title' => 'Modifier la devise', + /** + * Page de création de devises. + */ + 'currencies.create.title' => 'Créer une devise', + 'currencies.index.create_currency_btn' => 'Créer une devise', + /** + * Formulaire de devises. + */ + 'currencies.form.update_btn' => 'Mettre à jour la devise', + 'currencies.form.create_btn' => 'Créer une devise', + 'currencies.form.notify.created' => 'Devise créée', + 'currencies.form.format_help_text' => [ + 'Cela vous permet de spécifier le format que les champs de prix doivent utiliser pour cette devise.', + 'Lors de l\'affichage, Lunar remplacera {value} par le prix formaté. Par exemple, £{value}.', + 'Vous devez toujours inclure {value} pour que cela fonctionne correctement.', + ], + /** + * Attributs. + */ + 'attributes.index.title' => 'Attributs', + 'attributes.show.title' => 'Modification des attributs de :type', + 'attributes.show.locked' => 'Cet attribut est requis par le système et a donc été verrouillé en modification.', + 'attributes.create.title' => 'Créer un attribut', + 'attributes.form.update_btn' => 'Mettre à jour l\'attribut', + 'attributes.form.create_btn' => 'Créer un attribut', + 'attributes.form.notify.created' => 'Attribut créé', + /** + * Tags. + */ + 'tags.show.title' => 'Modifier le tag', + 'tags.index.title' => 'Tags', + 'tags.index.table_row_action_text' => 'Modifier', + 'tags.form.update_btn' => 'Mettre à jour le tag', + 'tags.form.create_btn' => 'Créer un tag', + 'tags.form.notify.updated' => 'Tag mis à jour', + /** + * Page de journal d'activité. + */ + 'activity_log.index.title' => 'Journal d\'activité', + /* + * Options de produit + */ + 'product.options.index.title' => 'Options', + 'product.options.index.create_btn' => 'Créer une option', + 'product.options.index.table_row_action_text' => 'Modifier l\'option', + /** + * Taxes. + */ + 'taxes.tax-zones.index.title' => 'Zones fiscales', + 'taxes.tax-zones.confirm_delete.title' => 'Confirmer la suppression', + 'taxes.tax-zones.confirm_delete.message' => 'Êtes-vous sûr de vouloir supprimer cette zone fiscale ? Cela pourrait entraîner une perte de données.', + 'taxes.tax-zones.customer_groups.title' => 'Restreindre aux groupes de clients', + 'taxes.tax-zones.customer_groups.instructions' => 'Sélectionnez les groupes de clients auxquels vous souhaitez restreindre cette zone. Laissez décoché pour aucune restriction.', + 'taxes.tax-zones.create_title' => 'Créer une zone fiscale', + 'taxes.tax-zones.create_btn' => 'Créer une zone fiscale', + 'taxes.tax-zones.delete_btn' => 'Supprimer la zone fiscale', + 'taxes.tax-zones.index.table_row_action_text' => 'Gérer', + 'taxes.tax-classes.index.title' => 'Classes de taxes', + 'taxes.tax-classes.index.create.title' => 'Créer une classe de taxe', + 'taxes.tax-classes.index.update.title' => 'Mettre à jour la classe de taxe', + 'taxes.tax-classes.create_btn' => 'Créer une classe de taxe', + 'taxes.tax-zones.price_display.label' => 'Affichage du prix', + 'taxes.tax-zones.price_display.excl_tax' => 'Hors taxe', + 'taxes.tax-zones.price_display.incl_tax' => 'Toutes taxes comprises', + 'taxes.tax-zones.zone_type.countries' => 'Limite aux pays', + 'taxes.tax-zones.zone_type.states' => 'Limite aux États / provinces', + 'taxes.tax-zones.zone_type.postcodes' => 'Limite aux codes postaux', + 'taxes.tax-zones.tax_rates.title' => 'Taux de taxe', + 'taxes.tax-zones.tax_rates.create_button' => 'Ajouter un taux de taxe', + 'taxes.tax-zones.save_btn' => 'Enregistrer la zone fiscale', + 'taxes.tax-classes.index.delete_message' => 'Êtes-vous sûr ? Cela pourrait entraîner une perte de données.', + 'taxes.tax-classes.index.delete_message_disabled' => 'Vous ne pouvez pas supprimer une classe de taxe associée à des variantes de produits', + 'taxes.tax-classes.index.delete_message_default' => 'Vous devez sélectionner une nouvelle valeur par défaut avant de supprimer', + /** + * Groupes de clients. + */ + 'customer-groups.index.title' => 'Groupes de clients', + 'customer-groups.index.create_btn' => 'Créer un groupe de clients', + 'customer-groups.index.table_row_action_text' => 'Modifier le groupe', + /** + * Page de détail des groupes de clients. + */ + 'customer-groups.show.title' => 'Modifier le groupe de clients', + /** + * Page de création des groupes de clients. + */ + 'customer-groups.create.title' => 'Créer un groupe de clients', + 'customer-groups.form.default_instructions' => 'Définissez si ce groupe de clients doit être le groupe par défaut.', +]; diff --git a/packages/admin/resources/lang/fr/tables.php b/packages/admin/resources/lang/fr/tables.php new file mode 100644 index 0000000000..8d2bf0ab99 --- /dev/null +++ b/packages/admin/resources/lang/fr/tables.php @@ -0,0 +1,55 @@ + 'Supprimé', + 'headings.status' => 'Statut', + 'headings.reference' => 'Référence', + 'headings.customer' => 'Client', + 'headings.postcode' => 'Code postal', + 'headings.email' => 'Email', + 'headings.active' => 'Actif', + 'headings.phone' => 'Téléphone', + 'headings.total' => 'Total', + 'headings.date' => 'Date', + 'headings.handle' => 'Gestion', + 'headings.zone_type' => 'Type de zone', + 'headings.url' => 'URL', + 'headings.price' => 'Prix', + 'headings.options' => 'Options', + 'headings.backorder' => 'Rétro-commande', + 'headings.account_ref' => 'Référence du compte', + 'headings.vat_no' => 'Numéro de TVA', + 'headings.company_name' => 'Nom de l\'entreprise', + 'headings.name' => 'Nom', + 'headings.brand' => 'Marque', + 'headings.sku' => 'SKU', + 'headings.product_type' => 'Type de produit', + 'headings.stock' => 'Stock', + 'headings.product_count' => 'Nombre de produits', + 'headings.mapped_attributes_count' => 'Nombre d\'attributs mappés', + 'headings.attribute_type' => 'Type d\'attribut', + 'headings.attribute_groups' => 'Groupes d\'attributs', + 'headings.attributes' => 'Attributs', + 'headings.default' => 'Par défaut', + 'headings.code' => 'Code', + 'headings.exchange_rate' => 'Taux de change', + 'headings.enabled' => 'Activé', + 'headings.value' => 'Valeur', + 'headings.event' => 'Événement', + 'headings.subject_id' => 'ID du sujet', + 'headings.subject_type' => 'Type de sujet', + 'headings.causer.email' => 'Effectué par', + 'headings.verified' => 'Vérifié', + 'headings.licensed' => 'Licencié', + 'headings.version' => 'Version', + 'headings.latest_version' => 'Dernière version', + 'headings.author' => 'Auteur', + 'headings.products_count' => 'N° de produits', + 'headings.empty' => 'Aucune entrée trouvée', + 'headings.starts_at' => 'Débute à', + 'headings.ends_at' => 'Se termine à', + 'headings.type' => 'Type', + 'headings.tags' => 'Tags', + 'headings.new_customer' => 'Nouveau client', + 'headings.new_returning' => 'Nouveaux/anciens clients', +]; diff --git a/packages/admin/resources/lang/fr/validation.php b/packages/admin/resources/lang/fr/validation.php new file mode 100644 index 0000000000..c13aa15a4b --- /dev/null +++ b/packages/admin/resources/lang/fr/validation.php @@ -0,0 +1,16 @@ + 'Veuillez vérifier tous les champs car certains semblent invalides ou manquants.', + 'generic_required' => 'Ce champ est requis', + 'tier_required' => 'Le niveau doit être d\'au moins 2', + 'max_price_currency' => 'Le prix en :currency ne doit pas dépasser :max', + 'min_price_currency' => 'Le prix en :currency doit être d\'au moins :min', + 'required_price_currency' => 'Le prix en :currency est requis.', + 'numeric_price_currency' => 'Le prix en :currency doit être numérique.', + 'max_decimals_currency' => 'Le prix en :currency ne doit pas dépasser :decimals décimale(s).', + 'url_default_unique' => 'Vous ne pouvez avoir qu\'un seul par défaut par langue.', + 'url_slug_unique' => 'Le slug doit être unique pour cette langue.', + 'variant_option_required' => 'Vous devez sélectionner une valeur d\'option', + 'name_taken' => 'Ce nom est déjà pris', +]; diff --git a/packages/admin/resources/views/partials/navigation/taxes.blade.php b/packages/admin/resources/views/partials/navigation/taxes.blade.php index a2805a3f80..60c140ca83 100644 --- a/packages/admin/resources/views/partials/navigation/taxes.blade.php +++ b/packages/admin/resources/views/partials/navigation/taxes.blade.php @@ -6,7 +6,7 @@ 'hover:text-gray-700 text-gray-500' => request()->route()->getName() != 'hub.taxes.index' ]) > - Tax Zones + {{ __('adminhub::settings.taxes.tax-zones.index.title') }} request()->route()->getName() != 'hub.taxes.tax-classes.index' ]) > - Tax Classes + {{ __('adminhub::settings.tax-classes.index.title') }} diff --git a/packages/admin/src/Menu/SettingsMenu.php b/packages/admin/src/Menu/SettingsMenu.php index f7e6857020..9b00077ca8 100644 --- a/packages/admin/src/Menu/SettingsMenu.php +++ b/packages/admin/src/Menu/SettingsMenu.php @@ -36,10 +36,10 @@ protected function makeTopLevel(): static */ protected function makeStoreSection(): void { - $storeSection = $this->slot->section('store')->name('Store'); + $storeSection = $this->slot->section('store')->name(__('adminhub::global.store')); $storeSection->addItem(function (MenuLink $item) { - $item->name('Attributes') + $item->name(__('adminhub::settings.attributes.index.title')) ->handle('hub.attributes') ->route('hub.attributes.index') ->gate('settings:manage-attributes') @@ -47,7 +47,7 @@ protected function makeStoreSection(): void }); $storeSection->addItem(function (MenuLink $item) { - $item->name('Channels') + $item->name(__('adminhub::settings.channels.index.title')) ->handle('hub.channels') ->route('hub.channels.index') ->gate('settings:core') @@ -55,7 +55,7 @@ protected function makeStoreSection(): void }); $storeSection->addItem(function (MenuLink $item) { - $item->name('Currencies') + $item->name(__('adminhub::settings.currencies.index.title')) ->handle('hub.currencies') ->route('hub.currencies.index') ->gate('settings:core') @@ -63,7 +63,7 @@ protected function makeStoreSection(): void }); $storeSection->addItem(function (MenuLink $item) { - $item->name('Customer Groups') + $item->name(__('adminhub::settings.customer-groups.index.title')) ->handle('hub.customer-groups') ->route('hub.customer-groups.index') ->gate('settings:manage-staff') @@ -71,7 +71,7 @@ protected function makeStoreSection(): void }); $storeSection->addItem(function ($item) { - $item->name('Languages') + $item->name(__('adminhub::settings.languages.index.title')) ->handle('hub.languages') ->route('hub.languages.index') ->gate('settings:core') @@ -79,7 +79,7 @@ protected function makeStoreSection(): void }); $storeSection->addItem(function (MenuLink $item) { - $item->name('Tags') + $item->name(__('adminhub::settings.tags.index.title')) ->handle('hub.tags') ->route('hub.tags.index') ->gate('settings:core') @@ -87,7 +87,7 @@ protected function makeStoreSection(): void }); $storeSection->addItem(function (MenuLink $item) { - $item->name('Taxes') + $item->name(__('adminhub::settings.taxes.tax-zones.index.title')) ->handle('hub.taxes') ->route('hub.taxes.index') ->gate('settings:core') @@ -100,10 +100,10 @@ protected function makeStoreSection(): void */ protected function makeProductSection(): void { - $productSection = $this->slot->section('product')->name('Product'); + $productSection = $this->slot->section('product')->name(__('adminhub::global.product')); $productSection->addItem(function (MenuLink $item) { - $item->name('Options') + $item->name(__('adminhub::settings.product.options.index.title')) ->handle('hub.product.options') ->route('hub.product.options.index') ->gate('settings:core') @@ -116,10 +116,10 @@ protected function makeProductSection(): void */ protected function makeAdminSection(): void { - $adminSection = $this->slot->section('admin')->name('Admin'); + $adminSection = $this->slot->section('admin')->name(__('adminhub::global.admin')); $adminSection->addItem(function (MenuLink $item) { - $item->name('Activity Log') + $item->name(__('adminhub::settings.activity_log.index.title')) ->handle('hub.activity-log') ->route('hub.activity-log.index') ->gate('settings:core') @@ -127,7 +127,7 @@ protected function makeAdminSection(): void }); $adminSection->addItem(function (MenuLink $item) { - $item->name('Addons') + $item->name(__('adminhub::settings.addons.index.title')) ->handle('hub.addons') ->route('hub.addons.index') ->gate('settings:core') @@ -135,7 +135,7 @@ protected function makeAdminSection(): void }); $adminSection->addItem(function (MenuLink $item) { - $item->name('Staff') + $item->name(__('adminhub::settings.staff.index.title')) ->handle('hub.staff') ->route('hub.staff.index') ->gate('settings:manage-staff') From 5d1881eb978bf8e280506fa9aefd38e5d28d66bb Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Wed, 31 Jan 2024 08:00:02 +0000 Subject: [PATCH 24/26] Patch collection class reference --- packages/core/src/Models/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/Models/Product.php b/packages/core/src/Models/Product.php index 4986da671c..79318d4f65 100644 --- a/packages/core/src/Models/Product.php +++ b/packages/core/src/Models/Product.php @@ -119,7 +119,7 @@ public function variants(): HasMany public function collections(): BelongsToMany { return $this->belongsToMany( - Collection::class, + \Lunar\Models\Collection::class, config('lunar.database.table_prefix').'collection_product' )->withPivot(['position'])->withTimestamps(); } From b1dc7bdf2c95a19543fdfb479f3c6a330f33643f Mon Sep 17 00:00:00 2001 From: dewebdesigns Date: Wed, 31 Jan 2024 11:05:27 -0500 Subject: [PATCH 25/26] Add null for transaction order check (#1518) I am getting an error when the transaction model is null when viewing an order with only an intent transaction. Adding this null check fixes the error. Co-authored-by: Glenn Jacobs --- .../views/livewire/components/orders/capture.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/admin/resources/views/livewire/components/orders/capture.blade.php b/packages/admin/resources/views/livewire/components/orders/capture.blade.php index 2340c87027..836178c698 100644 --- a/packages/admin/resources/views/livewire/components/orders/capture.blade.php +++ b/packages/admin/resources/views/livewire/components/orders/capture.blade.php @@ -23,7 +23,7 @@ /> - @if($this->transactionModel->amount->decimal > $amount) + @if(! is_null($this->transactionModel) && $this->transactionModel->amount->decimal > $amount) You're about to capture an amount less than the total transaction value. From 65a84acc6806ef402be0a8a675fb93a1aa067f3c Mon Sep 17 00:00:00 2001 From: Alec Ritson Date: Wed, 31 Jan 2024 16:14:53 +0000 Subject: [PATCH 26/26] Add test for product relations (#1523) Regression test to ensure that `mappedAttributes` returns the correct class and also the `collections` relationship on products has the correct model referenced Co-authored-by: Glenn Jacobs --- .../core/tests/Unit/Models/ProductTest.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/core/tests/Unit/Models/ProductTest.php b/packages/core/tests/Unit/Models/ProductTest.php index 4daaaa343d..3bc17e255c 100644 --- a/packages/core/tests/Unit/Models/ProductTest.php +++ b/packages/core/tests/Unit/Models/ProductTest.php @@ -533,4 +533,32 @@ public function can_retrieve_prices() $this->assertCount(1, $product->refresh()->prices); } + + /** @test */ + public function can_retrieve_correct_models_and_relationships() + { + $attribute_data = collect([ + 'meta_title' => new \Lunar\FieldTypes\Text('I like cake'), + 'pack_qty' => new \Lunar\FieldTypes\Number(12345), + 'description' => new \Lunar\FieldTypes\TranslatedText(collect([ + 'en' => new \Lunar\FieldTypes\Text('Blue'), + 'fr' => new \Lunar\FieldTypes\Text('Bleu'), + ])), + ]); + + $collection = Collection::factory()->create(); + + $product = Product::factory() + ->for(ProductType::factory()) + ->create([ + 'attribute_data' => $attribute_data, + ]); + + $product->collections()->attach($collection); + + $this->assertInstanceOf(\Illuminate\Database\Eloquent\Collection::class, $product->mappedAttributes()); + $this->assertInstanceOf(Collection::class, $product->collections()->getRelated()); + $this->assertCount(1, $product->collections()->get()); + $this->assertEquals($collection->id, $product->collections()->get()->first()->id); + } }