createFromDB($idOrder); } $payments = []; foreach ($order->getPaymentsArray() as $payment) { $payments[] = new PosOrderPayment(payment: $payment); } return new PosOrderPaymentsCollection( items: $payments ); } public function setPaymentStatus(int $idOrder, array $payments): PosPaymentsStatusUpdate { $order = new \Order(); $order->createFromDB($idOrder); $classPayment = $order->getDeliveryType()->getPayment(); $classPayment->setOrder($order); foreach ($payments as $payment) { if (in_array($payment->status, [\Payment::STATUS_PENDING, \Payment::STATUS_FINISHED, \Payment::STATUS_CREATED, \Payment::STATUS_STORNO])) { $classPayment->setStatus($payment->status, $payment->uuid); if ($payment->terminal ?? false) { if (!$classPayment->paymentId) { throw new ValidationException('Proběhlo potvrzení platby, ale není nastaveno ID platby'); } sqlQueryBuilder() ->update('order_payments') ->set('payment_data', 'JSON_MERGE(payment_data, :terminalData)') ->setParameter('terminalData', json_encode(['terminal' => $payment->terminal])) ->andWhere(Operator::equals(['id' => $classPayment->paymentId])) ->execute(); } } } $results = []; $paymentArray = null; $isPaid = null; $remainingPayment = null; QueryHint::withRouteToMaster(function () use ($order, &$paymentArray, &$isPaid, &$remainingPayment) { $paymentArray = $order->getPaymentsArray(); $isPaid = $order->isPaid(); $remainingPayment = $order->getRemainingPayment(); }); foreach ($paymentArray as $payment) { $results[] = new PosOrderPayment(payment: $payment); } return new PosPaymentsStatusUpdate( isPaid: $isPaid, remainingPayment: $remainingPayment, posOrderPayments: new PosOrderPaymentsCollection($results), ); } public function confirmPayment(int $idOrder, string $uuidPayment, string $paidPrice, string $methodPayment, ?string $terminal = null): PosConfirmPayment { $order = new \Order(); $order->createFromDB($idOrder); $order->fetchItems(); $exceptionMessage = null; if ($uuidPayment != 'UNDEFINED') { $classPayment = $order->getDeliveryType()->getPayment(); $classPayment->setOrder($order); // Pokud spadne generování unikátního čísla faktury, tak se nesmí zahodit nic co se stane po přepnutí statusu platby try { $classPayment->setStatus(\Payment::STATUS_FINISHED, $uuidPayment); } catch (OrderingException $exception) { $exceptionMessage = $exception->getMessage(); } if ($terminal) { if (!$classPayment->paymentId) { throw new ValidationException('Proběhlo potvrzení platby, ale není nastaveno ID platby'); } sqlQueryBuilder() ->update('order_payments') ->set('payment_data', 'JSON_MERGE(payment_data, :terminalData)') ->setParameter('terminalData', json_encode(['terminal' => $terminal])) ->andWhere(Operator::equals(['id' => $classPayment->paymentId])) ->execute(); } } if ($order->isPaid()) { $this->eventDispatcher->dispatch(new PosOrderEvent($order->getPurchaseState(), $this->posContext->getActiveId(), $order), PosOrderEvent::ORDER_PAID_BY_POS); } if ($order->isPaid() && toDecimal($paidPrice)->isZero() && !$order->getDeliveryId()) { $this->changeOrderDelivery( posId: $this->posContext->getActiveId(), order: $order, paymentMethod: $methodPayment, ); } return new PosConfirmPayment( posOrderResponse: new PosOrderResponse( idOrder: $order->id, noOrder: $order['order_no'], isPaid: $order->isPaid(), remainingPayment: $order->getRemainingPayment(), status: $order->status, uuidPayment: $uuidPayment ), saved: true, exception: $exceptionMessage ); } public function createNonOrderPayment(int $idPos, string $price, string $note, $method): int { global $adminID; return sqlGetConnection()->transactional(function () use ($adminID, $idPos, $price, $note, $method) { $this->insertSQL('order_payments', [ 'price' => $price, 'method' => $method, 'note' => $note, 'date' => date('Y-m-d H:i:s'), 'admin' => !empty($adminID) ? $adminID : null, ]); $id_payment = sqlInsertId(); $this->insertSQL('pos_payments_relation', [ 'id_pos' => $idPos, 'id_payment' => $id_payment, ]); return 200; }); } public function getPosPaymentList(int $idPos, int $pageDivide, int $page, ?string $method = null): PosPaymentCollection { return QueryHint::withRouteToMaster(function () use ($idPos, $pageDivide, $page, $method) { $qb = $this->getQueryPaymentLoader($idPos, $pageDivide, $page); $next = $this->getQueryPaymentLoader($idPos, $pageDivide, $page + 1)->execute()->fetchAll(); if (!empty($method)) { $qb->where('pos.method = ?')->setParameter(0, $method); } $qb2 = sqlQueryBuilder() ->select('SUM(price) as in_pos') ->from('order_payments', 'op') ->andWhere(Operator::orX( Operator::equals(['op.method' => \Payment::METHOD_CASH]), Operator::equals(['op.method' => \Payment::METHOD_CASH_INSERTION]), Operator::equals(['op.method' => \Payment::METHOD_CASH_SELECTION]), Operator::equals(['op.method' => \Payment::METHOD_EET_INVOICE_CASH]), )) ->leftJoin('op', 'pos_payments_relation', 'ppr', 'ppr.id_payment = op.id') ->andWhere(Operator::equals(['op.status' => \Payment::STATUS_FINISHED])) ->andWhere('ppr.id_pos = :pos_id') ->setParameter('pos_id', $idPos); $dataCollection = []; $baseCurrencySymbol = $this->currencyContext->getDefault()->getSymbol(); foreach ($qb->execute()->fetchAll() as $row) { $dataCollection[] = new PosPayment( $row['id'], ApiUtil::prepareDateTimeFromDB($row['date'])->format('H:i:s d.m.Y'), $row['id_order'], $row['price'], '', \Pos::METHODS[$row['method']], $row['note'], $row['admin'], $row['currency_symbol'] ?: $baseCurrencySymbol ); } return new PosPaymentCollection( $dataCollection, sqlFetchArray($qb2->execute())['in_pos'], $page, ($page - 1) > 0, count($next) > 0 ); }); } private function getQueryPaymentLoader($idPos, $pageDivide, $page) { $qb = sqlQueryBuilder() ->select('pos.id', 'pos.note', 'pos.price', 'a.login as admin', 'pos.method', 'pos.id_order', 'date') ->from('order_payments', 'pos') ->leftJoin('pos', 'admins', 'a', 'pos.admin=a.id') ->leftJoin('pos', 'pos_payments_relation', 'ppr', 'ppr.id_payment = pos.id') ->andWhere('ppr.id_pos = :pos_id') ->andWhere(Operator::equals(['pos.status' => \Payment::STATUS_FINISHED])) ->orderBy('pos.date', 'DESC') ->setParameter('pos_id', $idPos) ->setMaxResults($pageDivide) ->setFirstResult($pageDivide * ($page - 1)); if (findModule(\Modules::CURRENCIES)) { $qb->addSelect('c.symbol as currency_symbol') ->leftJoin('pos', 'orders', 'o', 'o.id=pos.id_order') ->leftJoin('o', 'currencies', 'c', 'o.currency=c.id'); } else { $qb->addSelect('null as currency_symbol'); } return $qb; } public function changeOrderDelivery(int $posId, \Order $order, string $paymentMethod): void { $deliveryType = $this->posUtil->getPosDeliveryType($posId, $paymentMethod); $order->id_delivery = $deliveryType['id']; $order->delivery_type = $deliveryType['name']; $order->updateSQL('orders', ['id_delivery' => $deliveryType['id'], 'delivery_type' => $deliveryType['name']], ['id' => $order->id]); } public function createOrderPayment(\Order $order, PurchaseState $purchaseState, bool $purchase = false): ?string { $methodPayment = $purchaseState->getCustomData('methodPayment'); if ($methodPayment == 'UNDEFINED' || $methodPayment == 'INVOICE') { return null; } $paidPrice = $purchaseState->getCustomData('paidPrice'); try { return sqlGetConnection()->transactional(function () use ($order, $paidPrice, $methodPayment) { $idPos = $this->posContext->getActiveId(); $this->changeOrderDelivery(posId: $idPos, order: $order, paymentMethod: $methodPayment); $classPayment = $order->getDeliveryType()->getPayment(); $classPayment->setOrder($order); $uuid = UUID::v4(); $classPayment->createPayment($uuid, toDecimal($paidPrice)); if ($classPayment->paymentId) { sqlQueryBuilder() ->insert('pos_payments_relation') ->values([ 'id_pos' => $idPos, 'id_payment' => $classPayment->paymentId, ]) ->execute(); return $uuid; } return null; }); } catch (\Exception|\Throwable $e) { $id = addActivityLog(ActivityLog::SEVERITY_NOTICE, ActivityLog::TYPE_COMMUNICATION, "POS API: vytvoření platby selhalo s chybou: {$e->getMessage()}"); $order->logHistory(" Vytvoření platby z pokladny skončilo s chybou."); throw $e; } } }