232 lines
9.2 KiB
PHP
232 lines
9.2 KiB
PHP
<?php
|
||
|
||
use App\Models\Country;
|
||
use App\Models\Setting;
|
||
use App\Models\Shipping;
|
||
use App\Models\ShippingCountry;
|
||
use App\Models\ShippingPrice;
|
||
use App\Models\UserAboItem;
|
||
use App\Models\UserAboOneTimeItem;
|
||
use App\Services\AboOneTimeService;
|
||
use App\Services\AboOrderCart;
|
||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
uses(Tests\TestCase::class, RefreshDatabase::class);
|
||
|
||
/**
|
||
* Versandland mit zwei Gewichtsstufen: 1–1000 g (4,90 €) und 1001–2000 g (9,90 €).
|
||
* Maximalgewicht = 2000 g.
|
||
*/
|
||
function makeShopEnvWithWeightTiers(): ShippingCountry
|
||
{
|
||
$country = Country::create([
|
||
'code' => 'DE', 'phone' => '49', 'en' => 'Germany', 'de' => 'Deutschland',
|
||
'es' => 'Alemania', 'fr' => 'Allemagne', 'it' => 'Germania', 'ru' => 'Германия',
|
||
]);
|
||
$shipping = Shipping::create(['name' => 'Standard', 'active' => true]);
|
||
|
||
ShippingPrice::create([
|
||
'shipping_id' => $shipping->id, 'price' => 4.90, 'price_comp' => 0, 'num_comp' => 0,
|
||
'tax_rate' => 19, 'weight_from' => 1, 'weight_to' => 1000,
|
||
]);
|
||
ShippingPrice::create([
|
||
'shipping_id' => $shipping->id, 'price' => 9.90, 'price_comp' => 0, 'num_comp' => 0,
|
||
'tax_rate' => 19, 'weight_from' => 1001, 'weight_to' => 2000,
|
||
]);
|
||
|
||
return ShippingCountry::create(['shipping_id' => $shipping->id, 'country_id' => $country->id]);
|
||
}
|
||
|
||
function makeShopEnvWithCompWeightTiers(): ShippingCountry
|
||
{
|
||
$country = Country::create([
|
||
'code' => 'DE', 'phone' => '49', 'en' => 'Germany', 'de' => 'Deutschland',
|
||
'es' => 'Alemania', 'fr' => 'Allemagne', 'it' => 'Germania', 'ru' => 'Германия',
|
||
]);
|
||
$shipping = Shipping::create(['name' => 'Standard', 'active' => true]);
|
||
|
||
ShippingPrice::create([
|
||
'shipping_id' => $shipping->id, 'price' => 4.90, 'price_comp' => 4.90, 'num_comp' => 0,
|
||
'tax_rate' => 19, 'weight_from' => 1, 'weight_to' => 1000,
|
||
]);
|
||
ShippingPrice::create([
|
||
'shipping_id' => $shipping->id, 'price' => 9.90, 'price_comp' => 9.90, 'num_comp' => 2,
|
||
'tax_rate' => 19, 'weight_from' => 1001, 'weight_to' => 2000,
|
||
]);
|
||
|
||
return ShippingCountry::create(['shipping_id' => $shipping->id, 'country_id' => $country->id]);
|
||
}
|
||
|
||
describe('Yard Maximalgewicht', function () {
|
||
beforeEach(function () {
|
||
$this->shippingCountry = makeShopEnvWithWeightTiers();
|
||
});
|
||
|
||
it('liefert das höchste weight_to als Maximalgewicht', function () {
|
||
$yard = Yard::instance('test-maxweight');
|
||
$yard->destroy();
|
||
$yard->setShippingCountryWithPrice($this->shippingCountry->id);
|
||
|
||
expect($yard->getMaxWeight())->toBe(2000);
|
||
|
||
$yard->destroy();
|
||
});
|
||
|
||
it('erkennt das Überschreiten des Maximalgewichts', function () {
|
||
$yard = Yard::instance('test-maxweight');
|
||
$yard->destroy();
|
||
$yard->setShippingCountryWithPrice($this->shippingCountry->id);
|
||
|
||
$yard->add(1, 'A', 1, 10.0, false, false, ['weight' => 1500]);
|
||
|
||
expect($yard->exceedsMaxWeight(0))->toBeFalse()
|
||
->and($yard->exceedsMaxWeight(500))->toBeFalse()
|
||
->and($yard->exceedsMaxWeight(501))->toBeTrue();
|
||
|
||
$yard->destroy();
|
||
});
|
||
|
||
it('nutzt bei Überschreitung die teuerste Stufe statt der günstigsten', function () {
|
||
$yard = Yard::instance('test-maxweight');
|
||
$yard->destroy();
|
||
$yard->setShippingCountryWithPrice($this->shippingCountry->id);
|
||
|
||
// Gewicht 3000 g liegt über der höchsten Stufe (2000 g)
|
||
$yard->add(1, 'A', 1, 10.0, false, false, ['weight' => 3000]);
|
||
$yard->reCalculateShippingPrice();
|
||
|
||
expect((float) $yard->getShippingPrice())->toBe(9.90);
|
||
|
||
$yard->destroy();
|
||
});
|
||
});
|
||
|
||
describe('AboOrderCart Maximalgewicht', function () {
|
||
beforeEach(function () {
|
||
makeShopEnvWithWeightTiers();
|
||
$this->service = new AboOneTimeService;
|
||
});
|
||
|
||
it('berechnet das kombinierte Gewicht aus Einmal-Artikeln', function () {
|
||
$abo = makeMeAbo();
|
||
$product = makeProduct(['2']); // weight 500
|
||
|
||
$this->service->handleAction($abo, ['action' => 'add', 'product_id' => $product->id]);
|
||
|
||
expect(AboOrderCart::combinedWeight($abo->fresh()))->toBe(500);
|
||
});
|
||
|
||
it('stoppt das Hinzufügen, wenn das Maximalgewicht überschritten würde', function () {
|
||
$abo = makeMeAbo();
|
||
$product = makeProduct(['2']); // weight 500, max 2000 => max 4 Stück
|
||
|
||
for ($i = 0; $i < 4; $i++) {
|
||
$message = $this->service->handleAction($abo, ['action' => 'add', 'product_id' => $product->id]);
|
||
expect($message)->toBeNull();
|
||
}
|
||
|
||
// 5. Stück => 2500 g > 2000 g
|
||
$message = $this->service->handleAction($abo, ['action' => 'add', 'product_id' => $product->id]);
|
||
|
||
expect($message)->toBe(__('msg.cart_max_weight_reached'))
|
||
->and(UserAboOneTimeItem::where('user_abo_id', $abo->id)->first()->qty)->toBe(4);
|
||
});
|
||
|
||
it('stoppt das Hochsetzen der Menge bei Überschreitung, erlaubt aber gültige Mengen', function () {
|
||
$abo = makeMeAbo();
|
||
$product = makeProduct(['2']); // weight 500
|
||
$this->service->handleAction($abo, ['action' => 'add', 'product_id' => $product->id]);
|
||
$item = UserAboOneTimeItem::where('user_abo_id', $abo->id)->first();
|
||
|
||
// qty 4 => 2000 g (ok)
|
||
$okMessage = $this->service->handleAction($abo, ['action' => 'update', 'one_time_item_id' => $item->id, 'qty' => 4]);
|
||
expect($okMessage)->toBeNull()
|
||
->and($item->fresh()->qty)->toBe(4);
|
||
|
||
// qty 5 => 2500 g (zu schwer)
|
||
$failMessage = $this->service->handleAction($abo, ['action' => 'update', 'one_time_item_id' => $item->id, 'qty' => 5]);
|
||
expect($failMessage)->toBe(__('msg.cart_max_weight_reached'))
|
||
->and($item->fresh()->qty)->toBe(4);
|
||
});
|
||
|
||
it('erlaubt das Reduzieren der Menge immer', function () {
|
||
$abo = makeMeAbo();
|
||
$product = makeProduct(['2']);
|
||
$this->service->handleAction($abo, ['action' => 'add', 'product_id' => $product->id]);
|
||
$item = UserAboOneTimeItem::where('user_abo_id', $abo->id)->first();
|
||
$this->service->handleAction($abo, ['action' => 'update', 'one_time_item_id' => $item->id, 'qty' => 4]);
|
||
|
||
$message = $this->service->handleAction($abo, ['action' => 'update', 'one_time_item_id' => $item->id, 'qty' => 2]);
|
||
|
||
expect($message)->toBeNull()
|
||
->and($item->fresh()->qty)->toBe(2);
|
||
});
|
||
});
|
||
|
||
describe('AboOrderCart Kompensationsprodukte', function () {
|
||
beforeEach(function () {
|
||
$this->shippingCountry = makeShopEnvWithCompWeightTiers();
|
||
Setting::setContentBySlug('is_comp_me_abo', true, 'bool');
|
||
});
|
||
|
||
it('erhöht die Kompensationsprodukte, wenn die höhere Versandstufe mehr verlangt', function () {
|
||
$abo = makeMeAbo();
|
||
$compProduct = makeProduct(['12']);
|
||
DB::table('products')->where('id', $compProduct->id)->update(['shipping_addon' => true, 'pos' => 100]);
|
||
|
||
$yard = Yard::instance(AboOrderCart::INSTANCE);
|
||
$yard->destroy();
|
||
$yard->setShippingCountryWithPrice($this->shippingCountry->id, 'abo-me');
|
||
$yard->add(1, 'Abo-Produkt', 1, 10.0, false, false, ['weight' => 1500]);
|
||
$yard->reCalculateShippingPrice();
|
||
|
||
AboOrderCart::checkNumOfCompProducts($abo);
|
||
|
||
expect(UserAboItem::where('user_abo_id', $abo->id)->where('comp', '>', 0)->count())->toBe(2)
|
||
->and(UserAboItem::where('user_abo_id', $abo->id)->where('comp', '>', 0)->pluck('comp')->all())->toBe([1, 2]);
|
||
|
||
$yard->destroy();
|
||
});
|
||
|
||
it('entfernt Kompensationsprodukte wieder, wenn keine mehr benötigt werden', function () {
|
||
$abo = makeMeAbo();
|
||
$compProduct = makeProduct(['12']);
|
||
DB::table('products')->where('id', $compProduct->id)->update(['shipping_addon' => true, 'pos' => 100]);
|
||
|
||
UserAboItem::create(['user_abo_id' => $abo->id, 'product_id' => $compProduct->id, 'comp' => 1, 'qty' => 1, 'status' => 1]);
|
||
UserAboItem::create(['user_abo_id' => $abo->id, 'product_id' => $compProduct->id, 'comp' => 2, 'qty' => 1, 'status' => 1]);
|
||
|
||
$yard = Yard::instance(AboOrderCart::INSTANCE);
|
||
$yard->destroy();
|
||
$yard->setShippingCountryWithPrice($this->shippingCountry->id, 'abo-me');
|
||
$yard->add(1, 'Abo-Produkt', 1, 10.0, false, false, ['weight' => 500]);
|
||
$yard->reCalculateShippingPrice();
|
||
|
||
AboOrderCart::checkNumOfCompProducts($abo);
|
||
|
||
expect(UserAboItem::where('user_abo_id', $abo->id)->where('comp', '>', 0)->count())->toBe(0);
|
||
|
||
$yard->destroy();
|
||
});
|
||
|
||
it('zeigt einen Hinweis für Kompensationsprodukte aus Zusatzprodukten', function () {
|
||
$compProduct = makeProduct(['12']);
|
||
|
||
$yard = Yard::instance(AboOrderCart::INSTANCE);
|
||
$yard->destroy();
|
||
$yard->setShippingCountryWithPrice($this->shippingCountry->id, 'abo-me');
|
||
$yard->add(1, 'Abo-Produkt', 1, 10.0, false, false, ['weight' => 1500]);
|
||
$yard->reCalculateShippingPrice();
|
||
|
||
$html = view('user.order.comp_product', [
|
||
'comp_products' => collect([$compProduct]),
|
||
'cart_instance' => AboOrderCart::INSTANCE,
|
||
'base_comp_count' => 0,
|
||
])->render();
|
||
|
||
expect($html)->toContain(__('order.comp_required_by_additional_products'));
|
||
|
||
$yard->destroy();
|
||
});
|
||
});
|