getJsonDataSetFromFile(); } protected PosPurchaseStateUtil $posPurchaseStateUtil; protected PurchaseUtil $purchaseUtil; protected CurrencyContext $currencyContext; protected PosOrderUtil $posOrderUtil; protected PosWarehouseUtil $posWarehouseUtil; private StoreItemWorker $storeItemWorker; private PosPaymentUtil $posPaymentUtil; protected function setUp(): void { global $adminID; $adminID = null; parent::setUp(); } protected function setEnvironment() { $this->purchaseUtil = ServiceContainer::getService(PurchaseUtil::class); $this->currencyContext = ServiceContainer::getService(CurrencyContext::class); $this->posOrderUtil = ServiceContainer::getService(PosOrderUtil::class); $this->posWarehouseUtil = ServiceContainer::getService(PosWarehouseUtil::class); $this->storeItemWorker = ServiceContainer::getService(StoreItemWorker::class); $this->posEntity = ServiceContainer::getService(PosEntity::class); $this->posPaymentUtil = ServiceContainer::getService(PosPaymentUtil::class); $this->posPurchaseStateUtil = ServiceContainer::getService(PosPurchaseStateUtil::class); } private function getPosEntity(): PosEntity { $posContext = Contexts::get(PosContext::class); $posContext->activate(2); return $posContext->getActive(); } private function getTestOrderItems($idOrderItem1 = null, $idOrderItem2 = null): array { return [ new Types\Order\OrderItem( new OrderItem( [ 'idProduct' => 43866, 'idVariation' => 24004, 'pieces' => 1, 'vat' => '21', 'priceWithoutVat' => 3297.5207, 'discount' => null, 'idOrderItem' => $idOrderItem1, ] ) ), new Types\Order\OrderItem( new OrderItem( [ 'idProduct' => 12145, 'idVariation' => null, 'pieces' => 1, 'vat' => '21', 'priceWithoutVat' => 252.0661, 'discount' => null, 'idOrderItem' => $idOrderItem2, ] ) ), ]; } private function getTestPurchaseState(): PurchaseState { $couponItems = null; return $this->posPurchaseStateUtil->createStateFromApi($this->getTestOrderItems(), $couponItems); } public function testCreatePurchaseStateFromPos() { $this->setEnvironment(); $purchaseState = $this->getTestPurchaseState(); $this->assertEquals(toDecimal('4295.0000')->round(2), $purchaseState->getTotalPrice()->getPriceWithVat()->round(2)); $this->assertEquals(toDecimal('3549.5868')->round(2), $purchaseState->getTotalPrice()->getPriceWithoutVat()->round(2)); $purchaseState->addProduct( new TextPurchaseItem( 'Textová položka', 2, new Price(toDecimal('1239.6694'), $this->currencyContext->getActive(), '21' ), '21') ); $purchaseState = $this->purchaseUtil->recalculateTotalPrices($purchaseState); $this->assertEquals(toDecimal('5795.0000')->round(2), $purchaseState->getTotalPrice()->getPriceWithVat()->round(2)); $this->assertEquals(toDecimal('4789.2562')->round(2), $purchaseState->getTotalPrice()->getPriceWithoutVat()->round(2)); } public function testCreateOrderFromPurchaseState() { $this->setEnvironment(); $this->getPosEntity(); // ---- check before update ----- $inStoreVar = sqlQueryBuilder() ->select('in_store') ->from('products_variations') ->andWhere('id_product = 43866 AND id = 24004') ->execute() ->fetchOne(); $this->assertEquals(2, $inStoreVar); $inStoreStoreItem = sqlQueryBuilder() ->select('quantity') ->from('stores_items') ->andWhere('id = 78') ->execute() ->fetchOne(); $this->assertEquals(20, $inStoreStoreItem); // ------------------------------ $orderResponse = $this->posOrderUtil->recalculateAndUpdateOrder( $this->getTestOrderItems(), [], [], [], null, null, null, true, 'CASH', '1', true ); $this->assertCount(2, $orderResponse->getItems()); $insertedOrder = sqlQueryBuilder() ->select('*') ->from('orders') ->where('id=:id_order') ->setParameter('id_order', $orderResponse->getOrderInfo()->getIdOrder()) ->execute() ->fetch(); $this->assertEquals(toDecimal('4295')->round(2), $insertedOrder['total_price']); $this->assertEquals(toDecimal('3549.5868')->round(2), $insertedOrder['total_price_without_vat']); $orderItems = sqlQueryBuilder() ->select('*') ->from('order_items') ->where('id_order=:id_order') ->setParameter('id_order', $insertedOrder['id']) ->execute() ->fetchAll(); $this->assertCount(2, $orderItems); // ---- after before update ----- $inStoreVar = sqlQueryBuilder() ->select('in_store') ->from('products_variations') ->andWhere('id_product = 43866 AND id = 24004') ->execute() ->fetchOne(); $this->assertEquals(1, $inStoreVar); $inStoreStoreItem = sqlQueryBuilder() ->select('quantity') ->from('stores_items') ->andWhere('id = 78') ->execute() ->fetchOne(); $this->assertEquals(19, $inStoreStoreItem); // ------------------------------ } public function testPurchaseStateStockInItemsCheck() { $this->setEnvironment(); $posEntity = $this->getPosEntity(); $purchaseState = $this->getTestPurchaseState(); $purchaseState->addProduct( new TextPurchaseItem( 'Textová položka', 2, new Price(toDecimal('1239.6694'), $this->currencyContext->getActive(), '21' ), '21') ); $status = 'OK'; try { $this->posWarehouseUtil->checkPurchaseStateItemsStockIn($purchaseState, $posEntity); } catch (\Exception $e) { $status = $e->getMessage(); } $this->assertEquals('OK', $status); $purchaseState->getProducts()[1]->pieces = 2; try { $this->posWarehouseUtil->checkPurchaseStateItemsStockIn($purchaseState, $posEntity); } catch (\Exception $e) { $status = $e->getMessage(); } $this->assertEquals('Produkt Bosch vzduchový filtr Octavia 1Z TSI není v požadovaném množství na skladu.', $status); } public function testMoveProductsToVirtualBox() { $this->removeModule(\Modules::PRODUCTS_BATCHES); $this->setEnvironment(); $posEntity = $this->getPosEntity(); $order = new \Order(); $order->createFromDB(183932); $order->fetchItems(); $this->posWarehouseUtil->checkPurchaseStateItemsStockIn($order->getPurchaseState(), $posEntity); // Check positions before move $positions = $this->storeItemWorker->checkProductByEanAndLocation('8596389006365')['positions']; $this->assertEquals(1, array_values(array_filter($positions, fn ($x) => $x['id_position'] == '1138'))[0]['pieces']); $this->assertEquals(2, array_values(array_filter($positions, fn ($x) => $x['id_position'] == '1139'))[0]['pieces']); // Najde se rozdíl položek mezi boxem a objednávkou $warehouseDiff = $this->storeItemWorker->checkOrderMatchesBoxContent( id_warehouse_order: $warehouseOrder['id'] ?? null, id_order: $order->id, id_box: $posEntity->getVirtualBox() ); // Provede vyrovnání boxu $this->posWarehouseUtil->updateBoxToMatchOrder( order: $order, warehouseDiffs: $warehouseDiff, idBox: $posEntity->getVirtualBox() ); // Check positions after move $positions = $this->storeItemWorker->checkProductByEanAndLocation('8596389006365')['positions']; $this->assertEquals(0, array_values(array_filter($positions, fn ($x) => $x['id_position'] == '1138'))[0]['pieces']); $this->assertEquals(1, array_values(array_filter($positions, fn ($x) => $x['id_position'] == '1139'))[0]['pieces']); } public function getOrderItems() { return [ new \KupShop\GraphQLBundle\ApiAdmin\Types\Order\OrderItem(new \KupShop\OrderingBundle\Entity\Order\OrderItem([ 'discount' => null, 'idCharge' => null, 'idOrderItem' => null, 'idProduct' => 21113, 'idVariation' => null, 'pieces' => 1, 'priceWithoutVat' => '139.0000', 'serialNumbers' => null, 'title' => 'Na kytaru bez not', 'uuid' => '8129826c-21de-47cf-a660-eb8c7309dae7', 'vat' => '0', ])), ]; } /** * @throws Exception */ public function testWholeProcessCreateOrderFromPosWithSeparatePaymentAndCompleting() { $this->setEnvironment(); $posEntity = $this->getPosEntity(); $GLOBALS['adminID'] = 0; // Update And Recalculate pos state (API object simulated) $response = $this->posOrderUtil->recalculateAndUpdateOrder( $this->getTestOrderItems(), [], [], [], null, null, null, false, 'UNDEFINED', '0', true ); // 3297.5207 (Položka 1) + 252.0661 (Položka 2) = 3549.5868 -> 4295.000028 (s DPH) $this->assertEquals(toDecimal('4295.00')->round(2), toDecimal($response->getPriceWithVat())->round(2)); $this->assertEquals(toDecimal('3549.59')->round(2), toDecimal($response->getPriceWithoutVat())->round(2)); $this->assertCount(2, $response->getItems()); // Create order process with not finish payment $response = $this->posOrderUtil->recalculateAndUpdateOrder( $this->getTestOrderItems(), [], [], [], null, null, null, true, 'CASH', '100', true ); $this->assertEquals(-1, $response->getOrderInfo()->getStatus()); $this->assertEquals('4295', $response->getOrderInfo()->getRemainingPayment()); $this->assertFalse($response->getOrderInfo()->getIsPaid()); $this->assertCount(2, $response->getItems()); $this->assertEquals(43866, $response->getItems()[0]->getIdProduct()); $this->assertEquals('3297.5207', $response->getItems()[0]->getPiecePrice()); $idOrder = $response->getOrderInfo()->getIdOrder(); // Mám uloženo (mergnu idOrderItem jinak se bude znova hledat 1 kus na skladu) - tohle udělá pokladna $items = $this->getTestOrderItems($response->getItems()[0]->getId(), $response->getItems()[1]->getId()); // Confirm payment $response = $this->posPaymentUtil->confirmPayment($idOrder, $response->getOrderInfo()->getUuidPayment(), '100', 'CASH'); $this->assertEquals($idOrder, $response->getOrderInfo()->getIdOrder()); $this->assertTrue($response->getSaved()); $this->assertEquals('4195', $response->getOrderInfo()->getRemainingPayment()); // 4295 - 100 = 4195 $this->assertFalse($response->getOrderInfo()->getIsPaid()); // Create payment CARD - 4195 $response = $this->posOrderUtil->recalculateAndUpdateOrder( $items, [], [], [], null, null, $idOrder, true, 'CARD', '4195', true ); $this->assertTrue($response->getSaved()); // STATUS PAID $response = $this->posPaymentUtil->confirmPayment($response->getOrderInfo()->getIdOrder(), $response->getOrderInfo()->getUuidPayment(), '4195', 'CARD'); $this->assertEquals($idOrder, $response->getOrderInfo()->getIdOrder()); $this->assertTrue($response->getSaved()); $this->assertEquals('0', $response->getOrderInfo()->getRemainingPayment()); $this->assertTrue($response->getOrderInfo()->getIsPaid()); // Finish order $response = $this->posOrderUtil->finishOrder($idOrder); $this->assertNull($response->getException()); $this->assertEquals($idOrder, $response->getIdOrder()); // Check order DB data $qb = sqlQueryBuilder() ->select('*') ->from('orders') ->andWhere('id = :idOrder') ->setParameter('idOrder', $idOrder) ->execute() ->fetchAssociative(); $this->assertEquals('POS', $qb['flags']); $this->assertEquals('pos', $qb['source']); $this->assertEquals(1, $qb['status_payed']); $this->assertEquals('Platba kartou na pobočce - Osobní odběr Praha', $qb['delivery_type']); // Saves last one -> CARD $this->assertEquals('Maloobchodní prodej', $qb['invoice_name']); $this->assertEquals(toDecimal('4295')->round(2), toDecimal($qb['total_price'])->round(2)); $this->assertEquals(toDecimal('3549.5868')->round(2), toDecimal($qb['total_price_without_vat'])->round(2)); $qb = sqlQueryBuilder() ->select('*') ->from('pos_payments_relation', 'ppr') ->leftJoin('ppr', 'order_payments', 'op', 'ppr.id_payment = op.id') ->andWhere('ppr.id_pos = :idPos AND op.id_order = :idOrder') ->setParameter('idPos', $posEntity->getId()) ->setParameter('idOrder', $idOrder) ->execute() ->fetchAllAssociative(); $this->assertCount(2, $qb); $this->assertEquals(1, $qb[0]['method']); $this->assertEquals(toDecimal('100')->round(2), toDecimal($qb[0]['price'])->round(2)); $this->assertEquals(2, $qb[1]['method']); $this->assertEquals(toDecimal('4195')->round(2), toDecimal($qb[1]['price'])->round(2)); } /** * @dataProvider data_testFindProduct */ public function testFindProduct(array $testData) { $this->setEnvironment(); $this->getPosEntity(); $response = $this->posOrderUtil->recalculateAndUpdateOrder( $this->getOrderItems(), [], $testData['search'], [], null, null, null, false, 'CARD', '4195', true ); $this->assertEquals($testData['expectedIdProduct'], $response->getItems()[1]->getIdProduct() ?? null); } public function data_testFindProduct() { yield 'code' => [['search' => ['1F0129620/ 1987429405'], 'expectedIdProduct' => '12145']]; yield 'normalEan' => [['search' => ['3165143344057'], 'expectedIdProduct' => '12145']]; yield 'eanWithZero' => [['search' => ['003165143344057'], 'expectedIdProduct' => '12145']]; } }