Skip to content

Commit

Permalink
Merge branch '1.x' into 1.x
Browse files Browse the repository at this point in the history
  • Loading branch information
glennjacobs authored Nov 20, 2024
2 parents abb3bb6 + b7df5d0 commit ffcf451
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 10 deletions.
12 changes: 6 additions & 6 deletions packages/core/config/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
return [

'definitions' => [
Lunar\Models\Asset::class => StandardMediaDefinitions::class,
Lunar\Models\Brand::class => StandardMediaDefinitions::class,
Lunar\Models\Collection::class => StandardMediaDefinitions::class,
Lunar\Models\Product::class => StandardMediaDefinitions::class,
Lunar\Models\ProductOption::class => StandardMediaDefinitions::class,
Lunar\Models\ProductOptionValue::class => StandardMediaDefinitions::class,
'asset' => StandardMediaDefinitions::class,
'brand' => StandardMediaDefinitions::class,
'collection' => StandardMediaDefinitions::class,
'product' => StandardMediaDefinitions::class,
'product-option' => StandardMediaDefinitions::class,
'product-option-value' => StandardMediaDefinitions::class,
],

'collection' => 'images',
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/Base/Traits/HasMedia.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ protected function getDefinitionClass()
{
$conversionClasses = config('lunar.media.definitions', []);

return $conversionClasses[static::class] ?? StandardMediaDefinitions::class;
$alias = \Illuminate\Support\Str::snake(class_basename(static::class));

return $conversionClasses[$alias]
?? $conversionClasses[static::class] // fallback for published config
?? $conversionClasses[get_parent_class(static::class)] // fallback use parent class
?? StandardMediaDefinitions::class;
}
}
3 changes: 2 additions & 1 deletion packages/core/src/Search/ScoutIndexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class ScoutIndexer implements ScoutIndexerInterface
{
public function searchableAs(Model $model): string
{
$name = str_replace('lunar_', '', $model->getTable());
$tablePrefix = config('lunar.database.table_prefix');
$name = str_replace($tablePrefix, '', $model->getTable());

return config('scout.prefix').$name;
}
Expand Down
7 changes: 7 additions & 0 deletions packages/table-rate-shipping/config/shipping-tables.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@

return [
'enabled' => env('LUNAR_SHIPPING_TABLES_ENABLED', true),

/*
* What method should we use for a shipping rate tax calculation?
* Options are 'default' for the system-wide default tax rate,
* or 'highest' to select the highest tax rate in the cart
*/
'shipping_rate_tax_calculation' => 'default',
];
27 changes: 26 additions & 1 deletion packages/table-rate-shipping/src/Models/ShippingRate.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class ShippingRate extends BaseModel implements Contracts\ShippingRate, Purchasa
*/
protected $guarded = [];

private ?TaxClass $resolvedTaxClass;

protected static function booted()
{
self::deleting(function (self $shippingRate) {
Expand Down Expand Up @@ -73,7 +75,7 @@ public function getUnitQuantity(): int
*/
public function getTaxClass(): TaxClass
{
return TaxClass::getDefault();
return $this->resolvedTaxClass ?? TaxClass::getDefault();
}

public function getTaxReference(): ?string
Expand Down Expand Up @@ -139,6 +141,10 @@ public function getThumbnail(): ?string
*/
public function getShippingOption(Cart $cart): ?ShippingOption
{
if (config('lunar.shipping-tables.shipping_rate_tax_calculation') == 'highest') {
$this->resolvedTaxClass = $this->resolveHighestTaxRateInCart($cart);
}

return $this->shippingMethod->driver()->resolve(
new ShippingOptionRequest(
shippingRate: $this,
Expand All @@ -156,4 +162,23 @@ public function getTotalInventory(): int
{
return 1;
}

private function resolveHighestTaxRateInCart(Cart $cart): ?TaxClass
{
$highestRate = false;
$highestTaxClass = null;

foreach ($cart->lines as $cartLine) {
if ($cartLine->purchasable->taxClass) {
foreach ($cartLine->purchasable->taxClass->taxRateAmounts as $amount) {
if ($highestRate === false || $amount->percentage > $highestRate) {
$highestRate = $amount->percentage;
$highestTaxClass = $cartLine->purchasable->taxClass;
}
}
}
}

return $highestTaxClass;
}
}
7 changes: 7 additions & 0 deletions tests/core/Stubs/TestStandardMediaDefinitions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Lunar\Tests\Core\Stubs;

use Lunar\Base\StandardMediaDefinitions;

class TestStandardMediaDefinitions extends StandardMediaDefinitions {}
29 changes: 28 additions & 1 deletion tests/core/Unit/Traits/HasMediaTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

uses(\Lunar\Tests\Core\TestCase::class);
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Config;
use Lunar\Base\StandardMediaDefinitions;
use Lunar\Models\Product;
use Lunar\Tests\Core\Stubs\TestStandardMediaDefinitions;

uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);

Expand All @@ -12,7 +14,7 @@

expect($definitions)->toHaveCount(6);

expect($definitions[Product::class])->toEqual(StandardMediaDefinitions::class);
expect($definitions['product'])->toEqual(StandardMediaDefinitions::class);

$file = UploadedFile::fake()->image('avatar.jpg');

Expand All @@ -28,6 +30,31 @@
expect($image->hasGeneratedConversion('zoom'))->toBeTrue();
});

test('custom conversions are loaded', function () {
Config::set('lunar.media.definitions', [
'product' => TestStandardMediaDefinitions::class,
]);

$product = invade(new Product);

expect($product->getDefinitionClass())->toEqual(TestStandardMediaDefinitions::class);
});

test('custom conversions are loaded for extended model', function () {
\Lunar\Facades\ModelManifest::replace(
\Lunar\Models\Contracts\Product::class,
\Lunar\Tests\Core\Stubs\Models\Product::class
);

Config::set('lunar.media.definitions', [
'product' => TestStandardMediaDefinitions::class,
]);

$product = invade(app(\Lunar\Models\Contracts\Product::class));

expect($product->getDefinitionClass())->toEqual(TestStandardMediaDefinitions::class);
});

test('images can have fallback url', function () {
$testImageUrl = 'https://picsum.photos/200';
config()->set('lunar.media.fallback.url', $testImageUrl);
Expand Down
118 changes: 118 additions & 0 deletions tests/shipping/Unit/Resolvers/ShippingOptionResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
use Lunar\Models\CartAddress;
use Lunar\Models\Country;
use Lunar\Models\Currency;
use Lunar\Models\Price;
use Lunar\Models\ProductVariant;
use Lunar\Models\TaxClass;
use Lunar\Models\TaxRateAmount;
use Lunar\Shipping\DataTransferObjects\ShippingOptionLookup;
use Lunar\Shipping\Facades\Shipping;
use Lunar\Shipping\Models\ShippingMethod;
Expand Down Expand Up @@ -94,3 +97,118 @@

$this->assertcount(1, $options);
});

test('sets tax rate to the highest basket rate', function () {
config()->set('lunar.shipping-tables.shipping_rate_tax_calculation', 'highest');

$currency = Currency::factory()->create([
'default' => true,
]);

$country = Country::factory()->create();

TaxClass::factory()->create([
'default' => true,
'name' => 'default',
]);

$higherRate = TaxClass::factory()->create([
'default' => false,
'name' => 'higher',
]);

$taxAmount = TaxRateAmount::factory()->create();
$taxAmount->percentage = 90;

$higherRate->taxRateAmounts()->save($taxAmount);

$customerGroup = \Lunar\Models\CustomerGroup::factory()->create([
'default' => true,
]);

$shippingZone = ShippingZone::factory()->create([
'type' => 'countries',
]);

$shippingZone->countries()->attach($country);

$shippingMethod = ShippingMethod::factory()->create([
'driver' => 'ship-by',
'data' => [
'minimum_spend' => [
"{$currency->code}" => 200,
],
],
]);

$shippingMethod->customerGroups()->sync([
$customerGroup->id => ['enabled' => true, 'visible' => true, 'starts_at' => now(), 'ends_at' => null],
]);

$shippingRate = \Lunar\Shipping\Models\ShippingRate::factory()
->create([
'shipping_method_id' => $shippingMethod->id,
'shipping_zone_id' => $shippingZone->id,
]);

$shippingRate->prices()->createMany([
[
'price' => 600,
'min_quantity' => 1,
'currency_id' => $currency->id,
],
[
'price' => 500,
'min_quantity' => 700,
'currency_id' => $currency->id,
],
[
'price' => 0,
'min_quantity' => 800,
'currency_id' => $currency->id,
],
]);

$cart = $this->createCart($currency, 500);

$purchasable = ProductVariant::factory()->create();
$purchasable->stock = 50;
$purchasable->tax_class_id = $higherRate->id;
$purchasable->save();

Price::factory()->create([
'price' => 300,
'min_quantity' => 1,
'currency_id' => $currency->id,
'priceable_type' => $purchasable->getMorphClass(),
'priceable_id' => $purchasable->id,
]);

$cart->lines()->create([
'purchasable_type' => $purchasable->getMorphClass(),
'purchasable_id' => $purchasable->id,
'quantity' => 1,
]);

$cart->shippingAddress()->create(
CartAddress::factory()->make([
'country_id' => $country->id,
'state' => null,
])->toArray()
);

$shippingRates = Shipping::shippingRates(
$cart->refresh()->calculate()
)->get();

$options = Shipping::shippingOptions()->cart(
$cart->refresh()->calculate()
)->get(
new ShippingOptionLookup(
shippingRates: $shippingRates
)
);

$this->assertcount(1, $options);
$this->assertSame($options->first()->option->taxClass->id, $higherRate->id);
});

0 comments on commit ffcf451

Please sign in to comment.