HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/vhost/disk-apps/qas.sports-crowd.com/app/Core/Order/Application/OrderService.php
<?php

declare(strict_types=1);

namespace App\Core\Order\Application;

use App\AcademyUser;
use App\Core\Order\OrderStatusEnum;
use App\Core\Payment\Entities\Amount;
use App\Core\Payment\Entities\Payment;
use App\Core\Payment\Entities\PaymentRetrieveResponse;
use App\Core\Payment\Entities\Student;
use App\Core\Payment\PaymentMethodContext;
use App\Core\Payment\PaymentStatusEnum;
use App\Core\User\Application\UserService;
use App\Events\Order\OrderProcessesEvent;
use App\Events\Payment\PaymentConfirmed;
use App\Http\Controllers\Api\LealPayController;
use App\Http\Controllers\CollectionInvoiceController;
use App\Http\Controllers\OrderController;
use App\Order;
use App\OrderProduct;
use App\ProductTagAssign;
use App\UserTag;
use Carbon\Carbon;

class OrderService
{
    private $userService;

    public function __construct()
    {
        $this->userService = new UserService();
    }

    public function find(int $id)
    {
        return Order::findOrFail($id);
    }

    public function getByReference(string $reference)
    {
        return Order::where('gw_code_transaction', $reference)->first();
    }

    public function getByPin(string $pin)
    {
        return Order::where("code", $pin)->first();
    }

    public function getByPaymentGatewayTxId(string $txId)
    {
        return Order::where('payment_transaction_id', $txId)->first();
    }

    public function setOrderAsConfirmed($order)
    {
        $order->gw_state = OrderStatusEnum::CONFIRMED;
        $order->update();
    }

    public function setOrderAsPending($order)
    {
        $order->gw_code_transaction = strtoupper(hash("md5", (string) $order->id)) . '_' . $order->code;
        $order->gw_state = OrderStatusEnum::PENDING;
        $order->update();
    }

    public function setPaymentGatewayTxId($order, $paymentGatewayTxId)
    {
        $order->payment_transaction_id = $paymentGatewayTxId;
        $order->update();
    }

    public function setPaymentGatewayId($order, int $paymentGatewayId)
    {
        $order->gateway_payments_id = $paymentGatewayId;
        $order->update();
    }

    public function buildPayment($order): Payment
    {
        $customer = $this->userService->buildCustomerFromUserId($order->client_id);
        $payment = new Payment(
            $order->id,
            $order->code,
            $order->gw_code_transaction,
            "Pago de producto de tienda",
            new Amount($order->total_price),
            $customer
        );
        $payment->setPaymentGatewayId($order->gateway_payments_id);
        $payment->setPaymentGatewayTxId($order->payment_transaction_id);
        $payment->setPaymentGatewayStatus($order->gw_state);

        if ($order->extra_params) {
            $extraParams = json_decode($order->extra_params);
            if ($extraParams->academyUserId) {
                $academyUser = AcademyUser::find($extraParams->academyUserId);
                if ($academyUser) {
                    $payment->setStudent(new Student(
                        $academyUser->user_id,
                        $academyUser->identification,
                        $academyUser->student_academy_code,
                        $academyUser->academy_category->academy_location->name
                    ));
                }
            }
        }

        return $payment;
    }

    public function validatePayment($order): PaymentRetrieveResponse
    {
        $this->increasePaymentAttemps($order);

        $payment = $this->buildPayment($order);

        if ($payment->paymentGatewayStatus() == PaymentStatusEnum::CONFIRMED) {
            $retrieveResponse = new PaymentRetrieveResponse(
                (string) $payment->id(),
                $payment->paymentGatewayStatus(),
                $order->payment_comment
            );

            $retrieveResponse->setRawData(json_decode($order->gateway_response ?? ''));
            return $retrieveResponse;
        }

        $paymentContext = PaymentMethodContext::init($order->gateway_payments_id);
        $paymentMethodResponse = $paymentContext->retrieveOrderPayment($order);

        if ($paymentMethodResponse->status() == PaymentStatusEnum::CONFIRMED) {
            $this->confirmPayment($order, $paymentMethodResponse);
            event(new PaymentConfirmed($payment));
        } else {
            $this->voidPayment($order, $paymentMethodResponse);
        }

        $order->gateway_response = json_encode($paymentMethodResponse->rawData());
        $order->save();

        return $paymentMethodResponse;
    }

    public function isPaymentConfirmed($order)
    {
        return $order->gw_state == OrderStatusEnum::CONFIRMED;
    }

    public function dispatchOrderProcesses($order)
    {
        OrderProcessesEvent::dispatch($order);
    }

    public function executeOrderProcesses($order)
    {
        $this->validateUserPointsAccumulation($order);
        $this->validateCreditCollectionInvoice($order);
        $this->validateProductSegmentationOrder($order);
    }

    private function validateCreditCollectionInvoice($order)
    {
        $invoice = new CollectionInvoiceController();
        $invoice->validateCreditCollectionInvoice($order->gateway_payments_id, $order->gw_code_transaction, $order->payment_transaction_id, 'order', $order->total_price);
    }

    private function validateUserPointsAccumulation($order)
    {
        $pay = new LealPayController();
        $pay->validateUserPointsAccumulation($order);
    }

    private function validateProductSegmentationOrder($order)
    {
        $products = OrderProduct::where('order_id', $order->id)->get();
        foreach ($products as $product) {
            $tags = ProductTagAssign::where('product_id', $product->product_id)->pluck('tag_id');
            if (count($tags) > 0) {
                $this->assignProductTags($order, $tags);
            }
        }
    }

    private function assignProductTags($order, $tags)
    {
        $academyUserId = $this->validateExtraParamsOrder($order);
        foreach ($tags as $tag) {
            UserTag::updateOrCreate(
                ['tag_id' => $tag, 'user_id' => $order->client_id, 'academy_user_id' => $academyUserId],
                ['tag_id' => $tag, 'user_id' => $order->client_id, 'academy_user_id' => $academyUserId]
            );
        }
    }

    private function validateExtraParamsOrder($order)
    {
        $academyUserId = null;
        if ($order->extra_params) {
            $extraParams = json_decode($order->extra_params, true);
            if (isset($extraParams['academyUserId'])) {
                $academyUserId = $extraParams['academyUserId'];
            }
        }
        return $academyUserId;
    }

    private function confirmPayment($order, PaymentRetrieveResponse $paymentMethodResponse)
    {
        $this->updatePayment(
            $order->gw_code_transaction,
            $paymentMethodResponse->status(),
            2,
            $paymentMethodResponse->message(),
            $paymentMethodResponse->id()
        );
    }

    private function voidPayment($order, PaymentRetrieveResponse $paymentMethodResponse)
    {
        $this->updatePayment(
            $order->gw_code_transaction,
            $paymentMethodResponse->status(),
            7,
            $paymentMethodResponse->message(),
            $paymentMethodResponse->id()
        );
    }

    // TODO: check for refactor
    private function updatePayment(
        $paymentReference,
        $paymentState,
        $orderStateId,
        $paymentComment,
        $paymentTransactionId
    ) {
        $orderController = new OrderController();
        $orderController->updateOrderByPaymentReference(
            $paymentReference,
            $paymentState,
            $orderStateId,
            $paymentComment,
            $paymentTransactionId
        );
    }

    private function increasePaymentAttemps($order)
    {
        $order->payment_attempts = $order->payment_attempts + 1;
        $order->update();
    }

    public function isProcessingPayment($order)
    {
        return $order->gw_state == OrderStatusEnum::PENDING && $order->gw_code_transaction != PaymentStatusEnum::PENDING && Carbon::now()->lessThan(Carbon::parse($order->updated_at)->addMinutes(30));
    }
}