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:
*  2 z předobjednávky s ID=1 a 1 z předobjednávky s ID=2
* Používám jenom ty z předobjednávky s ID=1
. * * 1) Přidam nějaký produkty do obou termínů, ale abych nepřekročil do první slevový hladiny.
* 2) Pak do jednoho termínu přidam přes PreorderItemsUpdater::updateItems nějakej produkt, abych tu hladinu překročil.
* * 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); } }