getId() ?? false) { $userDB = \User::createFromId($user->getId()); $userDB->activateUser(); $this->userContext->activate($userDB); } $purchaseState = new PurchaseState(); $purchaseState->setSource(OrderInfo::ORDER_SOURCE_POS); foreach ($purchaseItems as $key => $inputItem) { $rawItem = $inputItem->item->getItem(); $isProduct = $rawItem['idProduct'] ?? false; $isCharge = $rawItem['idCharge'] ?? false; if ($isProduct) { $price = null; if (!empty($rawItem['idOrderItem'])) { $price = new Price( toDecimal($rawItem['priceWithoutVat'])->mul(toDecimal($rawItem['pieces'])), $this->currencyContext->getActive(), $rawItem['vat'] ); } $newProductItem = $this->purchaseUtil->createProductPurchaseItem( $rawItem['idProduct'], $rawItem['idVariation'], $rawItem['pieces'], $price, ['uuid' => $rawItem['uuid'] ?? null] ); if ($rawItem['discount'] ?? false) { $this->purchaseUtil->applyDiscountToPurchaseItem($newProductItem, $rawItem['discount']->getDiscount()); } if (findModule(\Modules::PRODUCTS_SERIAL_NUMBERS) && !empty($rawItem['serialNumbers'] ?? []) && $isOrderNew) { $availableSerialNumbers = sqlQueryBuilder() ->select('serial_number, id') ->from('products_serial_numbers', 'psn') ->andWhere(Operator::inStringArray($rawItem['serialNumbers'], 'psn.serial_number')) ->andWhere('id_order_item IS NULL') ->execute() ->fetchAllAssociativeIndexed(); $checkedNumbers = []; foreach ($rawItem['serialNumbers'] as $sNumber) { $checkedNumbers[$sNumber] = new PosSerialNumber($sNumber, array_key_exists($sNumber, $availableSerialNumbers)); } $newProductItem->addNote('serial_numbers', $checkedNumbers); } $newProductItem->setId($rawItem['idOrderItem'] ?? $key); $purchaseState->addProduct($newProductItem); } elseif ($isCharge) { $newChargeItem = new ChargePurchaseItem( name: $rawItem['title'], price: new Price(toDecimal($rawItem['priceWithoutVat'])->mul(toDecimal($rawItem['pieces'])), $this->currencyContext->getActive(), $rawItem['vat'] ), id_charge: $rawItem['idCharge'], note: ['uuid' => $rawItem['uuid'] ?? null] ); $newChargeItem->setId($rawItem['idOrderItem'] ?? $key); $purchaseState->addCharge($newChargeItem); } else { $newTextItem = new TextPurchaseItem( $rawItem['title'], $rawItem['pieces'], new Price(toDecimal($rawItem['priceWithoutVat'])->mul(toDecimal($rawItem['pieces'])), $this->currencyContext->getActive(), $rawItem['vat'] ), $rawItem['vat'], ['uuid' => $rawItem['uuid'] ?? null] ); if ($rawItem['discount'] ?? false) { $this->purchaseUtil->applyDiscountToPurchaseItem($newTextItem, $rawItem['discount']->getDiscount()); } $newTextItem->setId($rawItem['idOrderItem'] ?? $key); $purchaseState->addProduct($newTextItem); } } $filterForDiscounts = []; $purchaseState = $this->purchaseUtil->recalculateTotalPrices($purchaseState); $order_discounts = []; // Nenačítaly se kupony v pokladně foreach ($couponItems ?? [] as $item) { $purchaseState->addCoupon($item->getCode()); $this->discountManager->couponNumberExists($item->getCode(), $order_discounts); $filterForDiscounts = array_merge($filterForDiscounts, array_keys($order_discounts)); } $this->discountManager->setPurchaseState($purchaseState); $this->posOrderDiscounts->applyBonusDataToPurchaseState( purchaseState: $purchaseState, filter: $filterForDiscounts, bonusPoints: $bonusPoints, ); if ($discounts = $this->discountManager->getDiscountForCheck()) { // Při editaci uplatním pouze slevy pro kupony a bonusové body if (!$isOrderNew) { $discounts = array_intersect_key($discounts, array_flip($filterForDiscounts)); } $purchaseState = $this->discountManager->recalculate($discounts); if ($handlers = $this->discountManager->getActionHandlers()) { $purchaseState->setDiscountHandlers($handlers); } $this->purchaseUtil->ensureTotalIsNotNegative($purchaseState); } $data['order'] = [ 'order_no' => '_'.rand(0, 999999), 'status' => 0, 'date_created' => date('Y-m-d H:i:s'), 'date_updated' => date('Y-m-d H:i:s'), 'status_payed' => 0, 'status_dispatch' => 0, 'status_storno' => 0, ]; if (isset($userDB)) { $data['order'] = array_merge($data['order'], $this->getUserDBArray($userDB)); } elseif ($isOrderNew) { $countryContext = Contexts::get(CountryContext::class); $data['order'] = array_merge($data['order'], $this->getUserDBArray(), [ 'invoice_name' => 'Maloobchodní prodej', 'invoice_country' => $countryContext->getActiveId() ?? '', 'delivery_country' => $countryContext->getActiveId() ?? '', ]); } if (findModule(\Modules::CURRENCIES)) { $data['order'] = array_merge($data['order'], [ 'id_language' => $this->languageContext->getActiveId(), 'currency' => $this->currencyContext->getActiveId(), 'currency_rate' => $this->currencyContext->getActive()->getRate()->asString(), ]); } if ($methodPayment) { $data['payment'] = true; $data['methodPayment'] = $methodPayment; $data['paidPrice'] = $paidPrice; $data['order']['delivery_complete'] = 0; } $purchaseState->setCustomData($data); return $this->purchaseUtil->recalculateTotalPrices($purchaseState); } private function getUserDBArray($userDB = null): array { return [ 'id_user' => $userDB->id ?? null, 'invoice_name' => $userDB['name'] ?? 'Maloobchodní prodej', 'invoice_surname' => $userDB['surname'] ?? '', 'invoice_firm' => $userDB['firm'] ?? '', 'invoice_ico' => $userDB['ico'] ?? '', 'invoice_dic' => $userDB['dic'] ?? '', 'invoice_street' => $userDB['street'] ?? '', 'invoice_city' => $userDB['city'] ?? '', 'invoice_zip' => $userDB['zip'] ?? '', 'invoice_country' => $userDB['country'] ?? '', 'invoice_phone' => $userDB['phone'] ?? '', 'invoice_email' => $userDB['email'] ?? '', 'invoice_state' => $userDB['state'] ?? '', 'invoice_custom_address' => $userDB['custom_address'] ?? '', 'delivery_name' => $userDB['delivery_name'] ?? '', 'delivery_surname' => $userDB['delivery_surname'] ?? '', 'delivery_firm' => $userDB['delivery_firm'] ?? '', 'delivery_street' => $userDB['delivery_street'] ?? '', 'delivery_city' => $userDB['delivery_city'] ?? '', 'delivery_zip' => $userDB['delivery_zip'] ?? '', 'delivery_country' => $userDB['delivery_country'] ?? '', 'delivery_state' => $userDB['delivery_state'] ?? '', 'delivery_custom_address' => $userDB['delivery_custom_address'] ?? '', 'delivery_phone' => $userDB['delivery_phone'] ?? '', 'note_user' => '', ]; } public function getChargesFromPurchaseState(PurchaseState $purchaseState): array { $charges = []; foreach ($purchaseState->getCharges() as $charge) { $charges[] = new PosPurchaseCharge($charge); } return $charges; } public function getDiscountItemsFromPurchaseState(PurchaseState $purchaseState): array { $discounts = []; // valid discounts foreach ($purchaseState->getDiscounts() as $discount) { $discounts[] = new PosPurchaseDiscount($discount, true, note: $discount->getNote()); } if (($invalidCoupons = $purchaseState->getCustomData('invalidCoupons')) && is_array($invalidCoupons)) { foreach ($invalidCoupons as $invalidCoupon) { $discounts[] = new PosInvalidDiscountCoupon($invalidCoupon); } } return $discounts; } public function getPurchaseItemsFromOrder(PosEntity $pos, \Order $order): array { $order->fetchItemsPhoto(); $items = []; foreach ($order->items ?? [] as $item) { // Map item to purchase state, then load actual uuid $mappedPurchaseItem = array_reduce($this->getPurchaseStateProducts($order->getPurchaseState()), static function ($carry, $purchaseItem) use ($item) { return $carry ?? ($purchaseItem->getId() === $item['id'] ? $purchaseItem : $carry); }, null); $photo = null; $stores = null; $warehouse = null; $stockIn = null; $serialNumberRequire = null; $serialNumberCheck = null; if ($item['id_product'] ?? false) { if ($mappedPurchaseItem && $mappedPurchaseItem->getIdProduct()) { $product = $mappedPurchaseItem->getProduct(); } else { // Vytvoří se produkt například dárek, v pstatu je pod discount a teda nemám nafetchované informace o skladech atd.., // v dalším přepočítání už přijde v products a musí se namapovat takže se tohle nestane $collection = new ProductCollection([$item['product']['id'] => $item['product']]); $collection->fetchVariations(); $collection->fetchStoresInStore(findModule(\Modules::PRODUCTS_VARIATIONS)); $product = $collection->get($item['product']['id']); $product->fetchImages(1); } $photo = $product->image['src'] ?? null; $stores = $this->posStoreUtil->getStoresCollection($product); $warehouse = $this->posWarehouseUtil->getWarehouseItem($pos, $product); $stockIn = $this->posWarehouseUtil->loadOverallInStoreForPos($product, $pos); $serialNumberRequire = $product->serial_number_require ?? null; $serialNumberCheck = new PosSerialNumberCollection($mappedPurchaseItem?->getNote()['serial_numbers'] ?? []); } $items[] = new PosPurchaseItem([ 'uuid' => !empty($mappedPurchaseItem) ? $mappedPurchaseItem->getNote()['uuid'] ?? null : $item['note']['uuid'] ?? null, 'id_charge' => $item['note']['id_charge'] ?? null, 'id' => $item['id'], 'title' => $item['descr'], 'id_product' => $item['id_product'], 'id_variation' => $item['id_variation'], 'pieces' => $item['pieces'], 'vat' => $item['vat'], 'piece_price' => $item['piece_price']['value_without_vat']->asString(), 'code' => $item['code'] ?? $item['note']['coupon'] ?? null, 'photo' => $photo, 'ean' => $item['ean'], 'stores' => $stores, 'warehouse' => $warehouse, 'stockIn' => $stockIn, 'serial_number_require' => $serialNumberRequire, 'serial_number_check' => $serialNumberCheck, 'variationTitle' => $item['variation_title'] ?? null, ]); } return $items; } public function getPurchaseItemsFromPurchaseState(PosEntity $pos, PurchaseState $purchaseState): array { $items = []; foreach ($this->getPurchaseStateProducts($purchaseState) as $purchaseItem) { $code = null; $photo = null; $ean = null; $stores = null; $warehouse = null; $stockIn = null; $serialNumberRequire = null; if ($purchaseItem->getIdProduct()) { $code = ($purchaseItem->getIdVariation()) ? $purchaseItem->getProduct()['variations'][$purchaseItem->getIdVariation()]['code'] : $purchaseItem->getProduct()->code; $photo = $purchaseItem->getProduct()->image['src'] ?? null; $ean = ($purchaseItem->getIdVariation()) ? ($purchaseItem->getProduct()['variations'][$purchaseItem->getIdVariation()]['ean'] ?? '') : $purchaseItem->getProduct()->ean; $stores = $this->posStoreUtil->getStoresCollection($purchaseItem->getProduct()); $warehouse = $this->posWarehouseUtil->getWarehouseItem($pos, $purchaseItem->getProduct()); $stockIn = $this->posWarehouseUtil->loadOverallInStoreForPos($purchaseItem->getProduct(), $pos); $serialNumberRequire = $purchaseItem->getProduct()->serial_number_require ?? null; } $items[] = new PosPurchaseItem([ 'uuid' => $purchaseItem->getNote()['uuid'] ?? null, 'id' => $purchaseItem->getId() ?? null, 'title' => $purchaseItem->getName() ?? null, 'id_product' => ($purchaseItem->id_product ?? false) ? strval($purchaseItem->getIdProduct()) : null, 'id_variation' => ($purchaseItem->id_variation ?? false) ? strval($purchaseItem->getIdVariation()) : null, 'pieces' => $purchaseItem->getPieces(), 'vat' => $purchaseItem->getPrice()->getVat(), 'piece_price' => $purchaseItem->getPiecePriceWithoutVat(), 'code' => $code ?? null, 'photo' => $photo ?? null, 'ean' => $ean ?? null, 'stores' => $stores ?? null, 'warehouse' => $warehouse ?? null, 'stockIn' => $stockIn ?? null, 'serial_number_require' => $serialNumberRequire ?? null, 'serial_number_check' => new PosSerialNumberCollection($purchaseItem->getNote()['serial_numbers'] ?? []), 'variationTitle' => ($purchaseItem->id_variation ?? false) ? $purchaseItem->getProduct()->variations[$purchaseItem->getProduct()->variationId]['title'] : null, ]); } return $items; } public function getPurchaseStateProducts(PurchaseState $purchaseState): array { return QueryHint::withRouteToMaster(function () use ($purchaseState) { $purchaseState->getProductList() ->fetchVariations(true, false) ->fetchImages(1) ->getProducts() ->fetchStoresInStore(findModule(\Modules::PRODUCTS_VARIATIONS)); return $purchaseState->getProducts(); }); } }