339 lines
12 KiB
PHP
339 lines
12 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KupShop\PreordersBundle\Tests;
|
|
|
|
use KupShop\DevelopmentBundle\Util\Tests\CartTestTrait;
|
|
use KupShop\KupShopBundle\Context\PriceLevelContext;
|
|
use KupShop\OrderingBundle\Util\Purchase\PurchaseUtil;
|
|
use KupShop\PreordersBundle\Entity\UserPreorder;
|
|
use KupShop\PreordersBundle\Service\DynamicContexts;
|
|
use KupShop\PreordersBundle\Service\DynamicPrices;
|
|
use KupShop\PreordersBundle\Service\OrderCreator;
|
|
use KupShop\PreordersBundle\Service\PreorderItemsUpdater;
|
|
use KupShop\PreordersBundle\Service\PreorderUtil;
|
|
use KupShop\PricelistBundle\Context\PricelistContext;
|
|
use Query\Operator;
|
|
use Query\QueryBuilder;
|
|
|
|
class PreordersTest extends \DatabaseTestCase
|
|
{
|
|
use PreordersTestHelper;
|
|
use CartTestTrait;
|
|
|
|
private OrderCreator $orderService;
|
|
private PreorderItemsUpdater $itemsUpdater;
|
|
private DynamicContexts $contextsService;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->orderService = $this->get(OrderCreator::class);
|
|
$this->itemsUpdater = $this->get(PreorderItemsUpdater::class);
|
|
$this->contextsService = $this->get(DynamicContexts::class);
|
|
}
|
|
|
|
public function testItemsUpdater()
|
|
{
|
|
$userId = 1;
|
|
$this->loginUser($userId);
|
|
$dateId = $this->createDate(1);
|
|
|
|
$userPreorder = new UserPreorder($userId, $dateId);
|
|
|
|
$this->assertEmpty($userPreorder->getItems(true));
|
|
|
|
$this->itemsUpdater->updateItems($userPreorder, [
|
|
['id_product' => 4, 'id_variation' => '1', 'pieces' => 1],
|
|
['id_product' => 4, 'id_variation' => '2', 'pieces' => 2],
|
|
['id_product' => 10, 'id_variation' => null, 'pieces' => 3],
|
|
]);
|
|
|
|
$expected = [
|
|
[
|
|
'id_product' => 10,
|
|
'id_variation' => null,
|
|
'id_user' => 1,
|
|
'piece_price' => '1539.1304',
|
|
'pieces' => 3,
|
|
'pieces_sent' => 0,
|
|
'vat' => 2,
|
|
'product_title' => 'Black and Decker Core EGBL108K aku vrtačka',
|
|
'variation_title' => null,
|
|
'title' => 'Black and Decker Core EGBL108K aku vrtačka',
|
|
'price_total' => '4617.3912',
|
|
'price_remaining' => '4617.3912',
|
|
'currency' => 'CZK',
|
|
],
|
|
[
|
|
'id_product' => 4,
|
|
'id_variation' => 2,
|
|
'id_user' => 1,
|
|
'piece_price' => '3636.3636',
|
|
'pieces' => 2,
|
|
'pieces_sent' => 0,
|
|
'vat' => 1,
|
|
'product_title' => 'Columbia Lay D Down',
|
|
'variation_title' => 'Barva: modrá',
|
|
'title' => 'Columbia Lay D Down Barva: modrá',
|
|
'price_total' => '7272.7272',
|
|
'price_remaining' => '7272.7272',
|
|
'currency' => 'CZK',
|
|
],
|
|
[
|
|
'id_product' => 4,
|
|
'id_variation' => 1,
|
|
'id_user' => 1,
|
|
'piece_price' => '3636.3636',
|
|
'pieces' => 1,
|
|
'pieces_sent' => 0,
|
|
'vat' => 1,
|
|
'product_title' => 'Columbia Lay D Down',
|
|
'variation_title' => 'Barva: bílá',
|
|
'title' => 'Columbia Lay D Down Barva: bílá',
|
|
'price_total' => '3636.3636',
|
|
'price_remaining' => '3636.3636',
|
|
'currency' => 'CZK',
|
|
],
|
|
];
|
|
|
|
$items = $userPreorder->getItems(true);
|
|
foreach ($items as &$item) {
|
|
unset($item['id']);
|
|
unset($item['id_preorder_date']);
|
|
unset($item['has_variations']);
|
|
}
|
|
|
|
$this->assertEquals($expected, $items);
|
|
}
|
|
|
|
public function testCreateOrderFromPreorder()
|
|
{
|
|
$userPreorder = $this->createTestUserPreorder();
|
|
|
|
$itemsToAdd = [];
|
|
foreach ($userPreorder->getItems(true) as $item) {
|
|
$itemsToAdd[$item['id']] = (int) $item['pieces'] - 1;
|
|
}
|
|
|
|
$orderCreated = $this->orderService->createOrder($userPreorder, $itemsToAdd);
|
|
|
|
$order = new \Order();
|
|
$order->createFromDB($orderCreated->id);
|
|
|
|
$orderItems = [];
|
|
foreach ($order->getPurchaseState()->getProducts() as $product) {
|
|
$orderItems[] = [
|
|
'id_product' => $product->id_product,
|
|
'id_variation' => $product->id_variation,
|
|
'pieces' => $product->getPieces(),
|
|
'price' => $product->getPrice()->getPriceWithoutVat(),
|
|
'piece_price' => $product->getPiecePriceWithoutVat(),
|
|
];
|
|
}
|
|
|
|
$expected = [
|
|
[
|
|
'id_product' => 4,
|
|
'id_variation' => 2,
|
|
'pieces' => 1,
|
|
'price' => \Decimal::create('3636.36363636', 8),
|
|
'piece_price' => \Decimal::create('3636.36363636', 8),
|
|
],
|
|
[
|
|
'id_product' => 10,
|
|
'id_variation' => null,
|
|
'pieces' => 2,
|
|
'price' => \Decimal::create('3078.26086957', 8),
|
|
'piece_price' => \Decimal::create('1539.13043479', 8),
|
|
],
|
|
];
|
|
|
|
$this->assertEquals($expected, $orderItems);
|
|
|
|
$expectedPreorderItems = [
|
|
[
|
|
'id_product' => 4,
|
|
'id_variation' => 1,
|
|
'id_user' => 1,
|
|
'piece_price' => '3636.3636',
|
|
'pieces' => 1,
|
|
'pieces_sent' => 0,
|
|
'vat' => 1,
|
|
'product_title' => 'Columbia Lay D Down',
|
|
'variation_title' => 'Barva: bílá',
|
|
'title' => 'Columbia Lay D Down Barva: bílá',
|
|
'price_total' => '3636.3636',
|
|
'price_remaining' => '3636.3636',
|
|
'currency' => 'CZK',
|
|
],
|
|
[
|
|
'id_product' => 4,
|
|
'id_variation' => 2,
|
|
'id_user' => 1,
|
|
'piece_price' => '3636.3636',
|
|
'pieces' => 2,
|
|
'pieces_sent' => 1,
|
|
'vat' => 1,
|
|
'product_title' => 'Columbia Lay D Down',
|
|
'variation_title' => 'Barva: modrá',
|
|
'title' => 'Columbia Lay D Down Barva: modrá',
|
|
'price_total' => '7272.7272',
|
|
'price_remaining' => '3636.3636',
|
|
'currency' => 'CZK',
|
|
],
|
|
[
|
|
'id_product' => 10,
|
|
'id_variation' => null,
|
|
'id_user' => 1,
|
|
'piece_price' => '1539.1304',
|
|
'pieces' => 3,
|
|
'pieces_sent' => 2,
|
|
'vat' => 2,
|
|
'product_title' => 'Black and Decker Core EGBL108K aku vrtačka',
|
|
'variation_title' => null,
|
|
'title' => 'Black and Decker Core EGBL108K aku vrtačka',
|
|
'price_total' => '4617.3912',
|
|
'price_remaining' => '1539.1304',
|
|
'currency' => 'CZK',
|
|
],
|
|
];
|
|
|
|
$itemsToAdd = $userPreorder->getItems(true);
|
|
// each time - different ids
|
|
foreach ($itemsToAdd as &$item) {
|
|
unset($item['id']);
|
|
unset($item['id_preorder_date']);
|
|
unset($item['has_variations']);
|
|
}
|
|
|
|
$this->assertEquals($expectedPreorderItems, $itemsToAdd);
|
|
}
|
|
|
|
public function testCreateProductList()
|
|
{
|
|
$userPreorder = $this->createTestUserPreorder();
|
|
|
|
$list = $this->get(PreorderUtil::class)->getPreorderProductList($userPreorder->getItems(true), false);
|
|
|
|
$this->contextsService->withDynamicPrices(
|
|
$userPreorder->getPreorder(),
|
|
$userPreorder->getItems(true),
|
|
function () use ($list, $userPreorder, &$products, &$purchaseState) {
|
|
$products = $list->getProducts();
|
|
|
|
$refList = (new \ProductList(true))
|
|
->andSpec(function (QueryBuilder $qb) use ($products) {
|
|
$qb->andWhere(Operator::inIntArray($products->getProductIds(), 'p.id'));
|
|
});
|
|
|
|
$this->get(DynamicPrices::class)->inject($products, $refList, $userPreorder->getPreorder());
|
|
|
|
$this->assertEquals([4, 10], $products->getProductIds());
|
|
|
|
$purchaseState = PreorderUtil::toPurchaseState($products);
|
|
$this->assertEquals(
|
|
self::PRICE_LEVEL_12,
|
|
(int) $this->get(PriceLevelContext::class)->getActiveId(),
|
|
);
|
|
|
|
$this->assertEquals(
|
|
self::PRICELIST_BASE,
|
|
(int) $this->get(PricelistContext::class)->getActiveId(),
|
|
);
|
|
|
|
$this->get(PurchaseUtil::class)->recalculateTotalPrices($purchaseState);
|
|
},
|
|
);
|
|
|
|
$this->assertEqualsWithDelta(
|
|
\Decimal::create('15525.8173', 4)->asFloat(),
|
|
$purchaseState->getTotalPrice()->getPriceWithoutVat()->asFloat(),
|
|
0.01,
|
|
);
|
|
|
|
foreach ($products as /* @var \Product $product */ $product) {
|
|
if (!empty($product->variations)) {
|
|
foreach ($product->variations as $variation) {
|
|
$this->assertEquals(
|
|
$variation['dynamic_prices'][2]['price']->getPriceWithoutVat(),
|
|
$variation['preorder_piece_price']->getPriceWithoutVat(),
|
|
);
|
|
|
|
$this->assertEqualsWithDelta(
|
|
$variation['dynamic_prices'][2]['price']->getPriceWithoutVat()->asFloat(),
|
|
$variation['productPrice']->getPriceWithoutVat()->asFloat(),
|
|
0.01,
|
|
);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
$this->assertEquals(
|
|
$product['dynamic_prices'][2]['price']->getPriceWithoutVat(),
|
|
$product->getProductPrice()->getPriceWithoutVat(),
|
|
);
|
|
|
|
$this->assertEquals(
|
|
$product['dynamic_prices'][2]['price']->getPriceWithoutVat(),
|
|
$product['preorder_piece_price']->getPriceWithoutVat(),
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 3 otevřené termíny: <br>
|
|
* <i> 2 z předobjednávky s ID=1 a 1 z předobjednávky s ID=2</i><br>
|
|
* Používám jenom ty z předobjednávky s ID=1<br>.
|
|
*
|
|
* 1) Přidam nějaký produkty do obou termínů, ale abych nepřekročil do první slevový hladiny.<br>
|
|
* 2) Pak do jednoho termínu přidam přes PreorderItemsUpdater::updateItems nějakej produkt, abych tu hladinu překročil. <br>
|
|
*
|
|
* Co se stane: měly by se přepočítat ceny v OBOU TERMÍNECH (tzn. i v tom, do kterýho jsem nic nepřidal v kroku 2)
|
|
*/
|
|
public function testUpdatesPricesOfAllDatesWhileUsingMultipleDates(): void
|
|
{
|
|
$this->setUseMultipleDates();
|
|
$dates = $this->createTestMultipleDates();
|
|
$user = $this->getUserWithAllPreorders();
|
|
$openDateIds = array_column(PreorderUtil::getOpenDates($user), 'id');
|
|
|
|
[$firstDate, $secondDate] = array_filter(
|
|
$dates,
|
|
fn (array $d) => $d['id_preorder'] == 1 && in_array($d['id'], $openDateIds),
|
|
);
|
|
|
|
$first = new UserPreorder($user->id, $firstDate['id']);
|
|
$second = new UserPreorder($user->id, $secondDate['id']);
|
|
|
|
$updater = $this->get(PreorderItemsUpdater::class);
|
|
|
|
$updater->updateItems($first, [
|
|
['id_product' => 11, 'id_variation' => 22, 'pieces' => 1],
|
|
]);
|
|
|
|
$updater->updateItems($second, [
|
|
['id_product' => 11, 'id_variation' => 22, 'pieces' => 1],
|
|
]);
|
|
|
|
// Nic se neaktivovalo -> ceny jsou stejné jako v DB
|
|
$this->assertEqualsWithDelta(275, $this->sumUserPreorderItems($first), 1);
|
|
$this->assertEqualsWithDelta(275, $this->sumUserPreorderItems($second), 1);
|
|
|
|
// Přidám produkt, co stojí 2400 -> dostanu se do 1. slevové hladiny
|
|
$updater->updateItems($first, [
|
|
['id_product' => 6, 'id_variation' => 17, 'pieces' => 1],
|
|
]);
|
|
|
|
$this->assertEqualsWithDelta(252, $this->sumUserPreorderItems($second), 1);
|
|
|
|
// Počítání pouze přes jeden termín -> cena se vrátí na původní úroveň
|
|
$this->setUseMultipleDates(false);
|
|
$updater->recalculatePiecePrices($second);
|
|
$this->assertEqualsWithDelta(275, $this->sumUserPreorderItems($second), 1);
|
|
}
|
|
}
|