mivita/tests/Feature/CartMaxWeightTest.php
Kevin 2269ce031f Abo Einmalprodukte und Bestätigung abschließen
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-05 15:28:08 +00:00

232 lines
9.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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: 11000 g (4,90 €) und 10012000 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();
});
});