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/alq-cali.bikenow.co/app/Core/Membership/Application/MembershipService.php
<?php

declare(strict_types=1);

namespace App\Core\Membership\Application;

use App\Address;
use App\CorporateIdentity;
use App\Core\Academy\Application\MembershipPaymentService;
use App\Core\Membership\Domain\ValueObjects\MembershipOrderStatus;
use App\Core\Membership\Domain\ValueObjects\MembershipStatus;
use App\Core\Parameter\Application\ParameterService;
use App\Core\Payment\Application\PaymentTransactionService;
use App\Core\Servientrega\Application\ServientregaService;
use App\Core\User\Application\UserService;
use App\Erp;
use App\ErpLog;
use App\ErpParameter;
use App\ErpCustomItem;
use App\Events\Memberships\SubscriptionRevoked;
use App\Events\Memberships\SubscriptionConfirmed;
use App\Http\Controllers\UtilController;
use App\Models\Membership\Membership;
use App\Models\Membership\MembershipSubscriber;
use App\PaymentTransaction;
use Carbon\Carbon;
use Exception;
use PHPMailer\PHPMailer\PHPMailer;
use Illuminate\Support\Facades\DB;

// TODO: think in MembershipSubscriptionService
class MembershipService
{
    private $ERPPrefix = 'M';
    private $membershipPaymentService;
    private $userService;
    private $servientregaService;
    private $paymentTransactionService;
    private $parameterService;

    public function __construct()
    {
        $this->membershipPaymentService = new MembershipPaymentService();
        $this->userService = new UserService();
        $this->servientregaService = new ServientregaService();
        $this->paymentTransactionService = new PaymentTransactionService();
        $this->parameterService = new ParameterService();
    }

    public function find(int $membershipSubscriberId)
    {
        return MembershipSubscriber::findOrFail($membershipSubscriberId);
    }

    public function createMembershipSubscription($membership, $user, $startDate = null, $deliveryPrice = null, $dependent = false)
    {
        if (!$deliveryPrice && $membership->deliverable) {
            $lastUsedAddress = $this->userService->getLastUsedAddress($user);
            $deliveryPrice = $this->servientregaService->getDeliveryPrice($lastUsedAddress)->price;
        }

        $membershipSubscriber = new MembershipSubscriber();
        $membershipSubscriber->membership_id = $membership->id;
        $membershipSubscriber->user_id = $user->id;
        $membershipSubscriber->dependent_id = $dependent;
        $membershipSubscriber->status = MembershipStatus::PENDING;
        $membershipSubscriber->price = $membership->price;
        $membershipSubscriber->delivery = $deliveryPrice ?? 0;
        $membershipSubscriber->start_date = $startDate ?? now();
        $membershipSubscriber->end_date = $this->calculateEndDate(
            $membershipSubscriber->start_date,
            $membershipSubscriber->membership->billing_interval
        );
        $membershipSubscriber->auto_renew = false;
        $membershipSubscriber->is_renewal = false;
        $membershipSubscriber->save();

        return $membershipSubscriber;
    }

    public function createFromMembershipSubscription($membershipSubscription)
    {
        $newMembershipSubscription = new MembershipSubscriber();
        $newMembershipSubscription->membership_id = $membershipSubscription->membership_id;
        $newMembershipSubscription->user_id = $membershipSubscription->user_id;
        $newMembershipSubscription->status = MembershipStatus::PENDING;
        $newMembershipSubscription->price = $membershipSubscription->membership->price;
        $newMembershipSubscription->start_date = now();
        $newMembershipSubscription->end_date = $this->calculateEndDate(
            now(),
            $membershipSubscription->membership->billing_interval
        );
        $newMembershipSubscription->is_renewal = true;
        $newMembershipSubscription->save();

        $paymentTransaction = $this->membershipPaymentService->getPaymentTransaction(
            $newMembershipSubscription
        );

        $this->paymentTransactionService->setPaymentGatewayId(
            $paymentTransaction,
            $membershipSubscription->payment_transaction->gateway_payments_id,
        );

        return $newMembershipSubscription;
    }

    public function confirmMembershipOrder($membershipOrder)
    {
        if ($membershipOrder->status != MembershipOrderStatus::PENDING) {
            throw new Exception("You can not confirm this membership", 1);
        }

        foreach ($membershipOrder->items as $item) {
            $membershipSubscription = $this->createMembershipSubscription($item->membership, $item->subscriber, null, null, $item->dependent_id);
            $this->confirmMembership($membershipSubscription);
            $membershipSubscription->payment_transaction_id = $membershipOrder->payment_transaction_id;
            $membershipSubscription->membership_order_id = $membershipOrder->id;
            $membershipSubscription->save();
        }

        $membershipOrder->status = MembershipOrderStatus::CONFIRMED;
        $membershipOrder->save();
    }

    public function confirmMembership($membershipSubscription)
    {
        if ($membershipSubscription->status != MembershipStatus::PENDING) {
            throw new Exception("You can not confirm this membership", 1);
        }

        if (is_null($membershipSubscription->dependent_id)) {
            $previousMembership = $this->userService->hasMembership(
                $membershipSubscription->user,
                $membershipSubscription
            );
        } else {
            $previousMembership = $this->userService->dependentHasMembership(
                $membershipSubscription
            );
        }

        if ($previousMembership) {
            $startDate =  max($previousMembership->end_date, $membershipSubscription->start_date);
            $membershipSubscription->end_date = $this->calculateEndDate(
                $startDate,
                $membershipSubscription->membership->billing_interval
            );
            $membershipSubscription->is_renewal = true;
            $previousMembership->status = MembershipStatus::EXPIRED;
            $previousMembership->auto_renew = false;
            $previousMembership->save();
        }

        $membershipSubscription->status = MembershipStatus::CONFIRMED;
        $membershipSubscription->save();

        SubscriptionConfirmed::dispatch($membershipSubscription);
    }

    public function sendConfirmationEmail($membershipSubscription)
    {
        $tags = $membershipSubscription->membership->tags;
        $appStoreUrl = $this->parameterService->appStoreUrl();
        $playStoreUrl = $this->parameterService->playStoreUrl();
        $corporateIdentity = CorporateIdentity::first();

        $customer = $membershipSubscription->user;
        $buyer = $membershipSubscription->order->buyer;
        $order = $membershipSubscription->order;
        $subject = $tags->first()->name;
        $params = [
            'appStoreUrl'   => $appStoreUrl,
            'playStoreUrl'  => $playStoreUrl,
            'corporateIdentity' => $corporateIdentity,
            'membershipName' => $membershipSubscription->membership->name,
            'startDate'    => $membershipSubscription->start_date,
            'endDate'      => $membershipSubscription->end_date,
            'buyerFirstName' => $order->buyer->first_name,
            'buyerLastName' => $order->buyer->last_name,
            'subscriberFirstName' => $customer->first_name,
            'subscriberLastName' => $customer->last_name,
            'subscriberEmail' => $customer->email,
        ];

        try {
            if ($customer->id == $order->buyer_user_id) {
                $this->sendConfirmationEmailUser($buyer, $subject, $params);
            } else {
                $this->sendConfirmationEmailBuyer($buyer, $subject, $params);

                if (!is_null($membershipSubscription->dependent_id)) {
                    $this->sendConfirmationEmailDependent($customer, $subject, $params);
                } else {
                    $this->sendConfirmationEmailOther($customer, $subject, $params);
                }
            }
        } catch (Exception $e) {
            $error = [
                'customer'              => $customer,
                'subject'               => $subject,
                'params'                => $params,
                'message'               => $e->getMessage(),
                'getFile'               => $e->getFile(),
                'getLine'               => $e->getLine(),
            ];
            $utilController = new UtilController();
            $utilController->logFile(json_encode($error));
            echo "Message could not be sent. Mailer Error: " . $e->getMessage();
        }
    }

    public function sendConfirmationEmailUser($customer, $subject, $params)
    {
        $mail = new PHPMailer(true);

        // $mail->SMTPDebug = SMTP::DEBUG_SERVER;      //Enable verbose debug output
        $mail->isSMTP();                               //Send using SMTP
        $mail->Host       = env('MAIL_HOST_HED');      //Set the SMTP server to send through
        $mail->SMTPAuth   = true;                      //Enable SMTP authentication
        $mail->Username   = env('MAIL_USERNAME_HED');  //SMTP username
        $mail->Password   = env('MAIL_PASSWORD_HED');  //SMTP password
        $mail->SMTPSecure = env('MAIL_ENCRYPTION');    //Enable implicit TLS encryption
        $mail->Port       = env('MAIL_PORT');
        $mail->CharSet = 'UTF-8';

        $mail->setFrom(env('MAIL_USERNAME_HED'), env('MAIL_FROM_NAME'));
        $mail->addAddress($customer['email'], $customer['first_name']);

        $mail->isHTML(true);
        $mail->Subject = $subject;
        $mail->Body    = view('mails.membership.confirmMembershipSubscriptionUser')->with($params)->render();

        $mail->send();
    }

    public function sendConfirmationEmailBuyer($customer, $subject, $params)
    {
        $mail = new PHPMailer(true);

        // $mail->SMTPDebug = SMTP::DEBUG_SERVER;      //Enable verbose debug output
        $mail->isSMTP();                               //Send using SMTP
        $mail->Host       = env('MAIL_HOST_HED');      //Set the SMTP server to send through
        $mail->SMTPAuth   = true;                      //Enable SMTP authentication
        $mail->Username   = env('MAIL_USERNAME_HED');  //SMTP username
        $mail->Password   = env('MAIL_PASSWORD_HED');  //SMTP password
        $mail->SMTPSecure = env('MAIL_ENCRYPTION');    //Enable implicit TLS encryption
        $mail->Port       = env('MAIL_PORT');
        $mail->CharSet = 'UTF-8';

        $mail->setFrom(env('MAIL_USERNAME_HED'), env('MAIL_FROM_NAME'));
        $mail->addAddress($customer['email'], $customer['first_name']);

        $mail->isHTML(true);
        $mail->Subject = $subject;
        $mail->Body    = view('mails.membership.confirmMembershipSubscriptionBuyer')->with($params)->render();

        $mail->send();
    }

    public function sendConfirmationEmailDependent($customer, $subject, $params)
    {
        $mail = new PHPMailer(true);

        // $mail->SMTPDebug = SMTP::DEBUG_SERVER;      //Enable verbose debug output
        $mail->isSMTP();                               //Send using SMTP
        $mail->Host       = env('MAIL_HOST_HED');      //Set the SMTP server to send through
        $mail->SMTPAuth   = true;                      //Enable SMTP authentication
        $mail->Username   = env('MAIL_USERNAME_HED');  //SMTP username
        $mail->Password   = env('MAIL_PASSWORD_HED');  //SMTP password
        $mail->SMTPSecure = env('MAIL_ENCRYPTION');    //Enable implicit TLS encryption
        $mail->Port       = env('MAIL_PORT');
        $mail->CharSet = 'UTF-8';

        $mail->setFrom(env('MAIL_USERNAME_HED'), env('MAIL_FROM_NAME'));
        $mail->addAddress($customer['email'], $customer['first_name']);

        $mail->isHTML(true);
        $mail->Subject = $subject;
        $mail->Body    = view('mails.membership.confirmMembershipSubscriptionDependent')->with($params)->render();

        $mail->send();
    }

    public function sendConfirmationEmailOther($customer, $subject, $params)
    {
        $mail = new PHPMailer(true);

        // $mail->SMTPDebug = SMTP::DEBUG_SERVER;      //Enable verbose debug output
        $mail->isSMTP();                               //Send using SMTP
        $mail->Host       = env('MAIL_HOST_HED');      //Set the SMTP server to send through
        $mail->SMTPAuth   = true;                      //Enable SMTP authentication
        $mail->Username   = env('MAIL_USERNAME_HED');  //SMTP username
        $mail->Password   = env('MAIL_PASSWORD_HED');  //SMTP password
        $mail->SMTPSecure = env('MAIL_ENCRYPTION');    //Enable implicit TLS encryption
        $mail->Port       = env('MAIL_PORT');
        $mail->CharSet = 'UTF-8';

        $mail->setFrom(env('MAIL_USERNAME_HED'), env('MAIL_FROM_NAME'));
        $mail->addAddress($customer['email'], $customer['first_name']);

        $mail->isHTML(true);
        $mail->Subject = $subject;
        $mail->Body    = view('mails.membership.confirmMembershipSubscriptionOther')->with($params)->render();

        $mail->send();
    }

    public function revokeMembership($membershipSubscription)
    {
        $membershipSubscription->update([
            'status' => MembershipStatus::EXPIRED,
            'auto_renew' => false
        ]);

        SubscriptionRevoked::dispatch($membershipSubscription);

        $this->syncERP($membershipSubscription);
    }

    public function setAsNoRenewable($membershipSubscription)
    {
        $membershipSubscription->auto_renew = false;
        $membershipSubscription->save();
    }

    // TODO: Candidate to be a MembershipQueryService
    public function queryDashboard($request)
    {
        $page = ($request->start / $request->length) + 1;
        $request->merge(['page' => $page]);

        $orderBy = $request->columns[$request->order[0]['column']]['name'];
        $orderDirection = $request->order[0]['dir'];

        if ($orderBy == 'users.name') {
            $orderBy = 'users.first_name';
        }

        $response = MembershipSubscriber::select([
            'membership_subscribers.*',
            'memberships.*',
            'users.first_name',
            'users.last_name',
            'users.document',
            'dependents.first_name as dependent_first_name',
            'dependents.last_name as dependent_last_name',
            'membership_orders.buyer_user_id',
            'membership_orders.first_name as buyer_first_name',
            'membership_orders.last_name as buyer_last_name',
            'membership_orders.document as buyer_document',
            'membership_orders.email as buyer_email',
            'membership_orders.phone as buyer_phone',
            'payment_transactions.*',
            'membership_subscribers.id',
            'membership_subscribers.created_at',
        ])
            ->leftJoin('memberships', function ($join) {
                $join->on('memberships.id', '=', 'membership_subscribers.membership_id');
            })
            ->leftJoin('membership_orders', function ($join) {
                $join->on('membership_orders.id', '=', 'membership_subscribers.membership_order_id');
            })
            ->leftJoin('users', function ($join) {
                $join->on('users.id', '=', 'membership_subscribers.user_id');
            })
            ->leftJoin('dependents', function ($join) {
                $join->on('dependents.id', '=', 'membership_subscribers.dependent_id');
            })
            ->leftJoin('payment_transactions', function ($join) {
                $join->on('payment_transactions.id', '=', 'membership_subscribers.payment_transaction_id');
            })
            ->when($request->search['value'], function ($query) use ($request) {
                $query->where(function ($query) use ($request) {
                    $query->orWhere('state', 'like', '%' . $request->search['value'] . '%');
                    $query->orWhere('name', 'like', '%' . $request->search['value'] . '%');
                    $query->orWhere('first_name', 'like', '%' . $request->search['value'] . '%');
                    $query->orWhere('last_name', 'like', '%' . $request->search['value'] . '%');
                    $query->orWhere('document', 'like', '%' . $request->search['value'] . '%');
                    $query->orWhere('reference', 'like', '%' . $request->search['value'] . '%');
                    $query->orWhere('gateway_transaction_id', 'like', '%' . $request->search['value'] . '%');
                });
            })
            ->when(!is_null($request->states), function ($query) use ($request) {
                $query->whereIn('membership_subscribers.status', $request->states);
            })
            ->when(!is_null($request->is_renewal), function ($query) use ($request) {
                $query->whereIn('membership_subscribers.is_renewal', $request->is_renewal);
            })
            ->when(!is_null($request->start_date), function ($query) use ($request) {
                $query->where('membership_subscribers.start_date', '>=', $request->start_date);
            })
            ->when(!is_null($request->end_date), function ($query) use ($request) {
                $query->where('membership_subscribers.end_date', '<=', $request->end_date);
            })
            ->orderBy($orderBy, $orderDirection)
            ->paginate();

        return response()->json($response);
    }

    public function queryDownloadReport($request)
    {
        $response = MembershipSubscriber::select([
            'membership_subscribers.id',
            DB::raw('IF(membership_subscribers.dependent_id IS NOT NULL, dependents.first_name, users.first_name) AS first_name'),
            DB::raw('IF(membership_subscribers.dependent_id IS NOT NULL, dependents.last_name, users.last_name) AS last_name'),
            'users.document',
            DB::raw('IF(membership_orders.buyer_user_id != users.id OR membership_subscribers.dependent_id IS NOT NULL, "Beneficiario", "Compra propia") AS user_type'),
            'membership_orders.first_name as buyer_first_name',
            'membership_orders.last_name as buyer_last_name',
            'membership_orders.document as buyer_document',
            'membership_orders.email as buyer_email',
            'membership_orders.phone as buyer_phone',
            'memberships.name AS membership',
            'membership_subscribers.start_date',
            'membership_subscribers.end_date',
            'membership_subscribers.is_renewal',
            'membership_subscribers.status AS membership_status',
            'payment_transactions.state AS payment_status',
            'membership_subscribers.price',
            'payment_transactions.reference AS payment_reference',
            'payment_transactions.gateway_transaction_id AS payment_transaction_id',
            'membership_subscribers.created_at',
            'membership_subscribers.tracking_code',
            'membership_subscribers.auto_renew',
        ])
            ->leftJoin('memberships', function ($join) {
                $join->on('memberships.id', '=', 'membership_subscribers.membership_id');
            })
            ->leftJoin('membership_orders', function ($join) {
                $join->on('membership_orders.id', '=', 'membership_subscribers.membership_order_id');
            })
            ->leftJoin('users', function ($join) {
                $join->on('users.id', '=', 'membership_subscribers.user_id');
            })
            ->leftJoin('dependents', function ($join) {
                $join->on('dependents.id', '=', 'membership_subscribers.dependent_id');
            })
            ->leftJoin('payment_transactions', function ($join) {
                $join->on('payment_transactions.id', '=', 'membership_subscribers.payment_transaction_id');
            })
            ->when(!is_null($request->states), function ($query) use ($request) {
                $query->whereIn('membership_subscribers.status', $request->states);
            })
            ->when(!is_null($request->is_renewal), function ($query) use ($request) {
                $query->whereIn('membership_subscribers.is_renewal', $request->is_renewal);
            })
            ->when(!is_null($request->start_date), function ($query) use ($request) {
                $query->where('membership_subscribers.start_date', '>=', $request->start_date);
            })
            ->when(!is_null($request->end_date), function ($query) use ($request) {
                $query->where('membership_subscribers.end_date', '<=', $request->end_date);
            })
            ->orderBy('membership_subscribers.id', 'DESC')
            ->get();

        return $response;
    }

    public function createConfirmedMembershipSubscription($params)
    {
        $previousMembershipSubscription = MembershipSubscriber::select('membership_subscribers.id')
            ->join('payment_transactions', 'payment_transactions.id', '=', 'membership_subscribers.payment_transaction_id')
            ->where('payment_transactions.reference', $params->transactionReference)
            ->first();

        if ($previousMembershipSubscription) {
            return;
        }

        $membershipSubscription = $this->createMembershipSubscription(
            $params->membership,
            $params->user,
            $params->startDate,
            $params->deliveryPrice
        );

        $paymentTransaction = PaymentTransaction::create([
            'state' => 'CONFIRMED',
            'origin_class' => get_class($this),
            'gateway_transaction_id' =>  $params->transactionReference
        ]);

        $membershipSubscription->payment_transaction_id = $paymentTransaction->id;
        $membershipSubscription->sync_with_erp = true;
        $membershipSubscription->update();

        $this->confirmMembership($membershipSubscription);
    }

    public function syncERP($membershipSubscription, $action = null)
    {
        try {
            $erpSync = ErpParameter::where('key', 'shop_sync')->first();
            if (!$erpSync || $erpSync->value == 'false') {
                return;
            }

            $erps = Erp::select('id', 'class')->where('active', true)->get();
            foreach ($erps as $index => $erp) {
                $classPath = $erp->class;
                $ERPRepository = new $classPath($erp->id);

                if ($membershipSubscription->status != MembershipStatus::EXPIRED) {
                    if (!$this->validateSyncWithERPPayment($membershipSubscription)) {
                        return;
                    }

                    $previousBill = $ERPRepository->getBill($this->ERPPrefix . $membershipSubscription->id);
                    if ($previousBill['r'] && count($previousBill['d']->detalle->Table)) {
                        return;
                    }
                }

                switch ($action) {
                    case 'createOrder':
                        $this->createOrderERP(
                            $membershipSubscription,
                            $ERPRepository
                        );
                        break;
                    case 'createRC':
                        $this->createRCERP(
                            $membershipSubscription,
                            $ERPRepository
                        );
                        break;
                    case 'createBill':
                        $this->createBillERP(
                            $membershipSubscription,
                            $ERPRepository
                        );
                        break;
                    default:
                        $this->createThirdClientERP(
                            $membershipSubscription,
                            $ERPRepository
                        );
                        break;
                }
            }
        } catch (Exception $e) {
            $error = [
                'message'               => $e->getMessage(),
                'getFile'               => $e->getFile(),
                'getLine'               => $e->getLine(),
            ];
            $this->saveERPLog($membershipSubscription->id, json_encode($error), 'syncERP');
        }
    }

    private function createThirdClientERP($membershipSubscription, $ERPRepository)
    {
        $addressObj = Address::with('city')
            ->where('user_id', $membershipSubscription->user->id)
            ->where('last_used', true)
            ->first();

        if (!$addressObj) {
            $address   = 'Calle 90 #19-41';
            $shortAddress  = $address;
            $country    = 'Colombia';
            $province   = 'Bogotá';
            $city       = 'Bogotá, D.C.';
        } else {
            $address   = $addressObj->direction . ' | ' . $addressObj->district;
            $shortAddress  = $addressObj->direction;

            if ($addressObj->city) {
                $country    = $addressObj->city->state->country->name;
                $province   = $addressObj->city->state->name;
                $city       = $addressObj->city->name;
            }
        }

        $user = $membershipSubscription->user;
        $siesaThirdClient = $ERPRepository->thirdClientValidate($user->document);
        $expired = $membershipSubscription->status == MembershipStatus::EXPIRED;

        $params = new \stdClass();
        $third  = new \stdClass();
        $client = new \stdClass();

        $third->document            = $user->document;
        $third->firstName           = $user->first_name;
        $third->lastName            = $user->last_name;
        $third->contact             = $user->last_name . ' ' . $user->first_name;
        $third->phone               = $user->phone;
        $third->email               = $user->email;
        $third->isNew               = count($siesaThirdClient) == 0;
        $third->documentType        = $ERPRepository->mapDocumentType($user->documentType->alias);
        $third->birthDate           = Carbon::parse($user->userInfo->dob)->format('Ymd');
        $third->typeThird           = 'NATURAL_PERSON';
        $third->gender              = $ERPRepository->mapGender($user->userInfo->sex);
        $third->socialReason        = $third->contact;
        $third->establishmentName   = $third->contact;
        $third->ciiu                = null;

        $client->document       = $user->document;
        $client->contact        = $user->last_name . ' ' . $user->first_name;
        $client->phone          = $user->phone;
        $client->email          = $user->email;

        $params->third          = $third;
        $params->client         = $client;
        $params->address        = $address;
        $params->shortAddress   = $shortAddress;
        $params->country        = $country ?? null;
        $params->province       = $province ?? null;
        $params->city           = $city ?? null;
        $params->sucursal       = '001';
        $params->price_list     = '001';
        $params->typeClient     =  $expired ? 'CTDS' : 'CHED';
        $params->hasTaxes       = '1';
        $params->createThirdPos = true;
        $params->idCriteria     = $expired ? '103' : '105';
        $params->criteria       = $expired ? '1032' : '1051';
        $params->currency       = 'COP';
        $params->latitude       = $addressObj ? $addressObj->lat : null;
        $params->longitude       = $addressObj ? $addressObj->long : null;

        $response = $ERPRepository->createThirdClient($params);
        if (!$response['r']) {
            $this->saveERPLog($membershipSubscription->id, json_encode($response['d']), 'createThirdClient');
            return;
        }

        if (!$expired) {
            $this->createOrderERP($membershipSubscription, $ERPRepository);
        }
    }

    private function createOrderERP($membershipSubscription, $ERPRepository)
    {
        $paymentTransaction = PaymentTransaction::where('id', $membershipSubscription->payment_transaction_id)->first();
        $response = $ERPRepository->getOrder($this->ERPPrefix . $membershipSubscription->id);
        if ($response['r']) {
            $previousOrders = array_filter($response['d']->detalle->Table, function ($siesaOrder) use ($paymentTransaction) {
                $match = str_contains($siesaOrder->Notas, $paymentTransaction->gateway_transaction_id) ||
                    str_contains($siesaOrder->Notas, $paymentTransaction->reference);
                return $match;
            }, ARRAY_FILTER_USE_BOTH);

            if (count($previousOrders)) {
                $this->createRCERP($membershipSubscription, $ERPRepository);
                return;
            }
        }

        $orderParams                    = new \stdClass();
        $orderParams->operationCenter   = '601';
        $orderParams->document          = $membershipSubscription->user->document;
        $orderParams->sucursal          = '001';
        $orderParams->costCenter        = '4001';
        $orderParams->date              = Carbon::parse($paymentTransaction->payment_date)->format('Ymd');
        $orderParams->customerType      = 'CHED';
        $orderParams->note              = $membershipSubscription->membership->name . '-' . $paymentTransaction->reference;
        $orderParams->reference         = $this->ERPPrefix . $membershipSubscription->id;

        $orderParams->items = [
            array(
                'f431_id_co'                => $orderParams->operationCenter,
                'f431_consec_docto'         => '1',
                'f431_nro_registro'         => '1',
                'f431_referencia_item'      => '', //$productVariant['sku'],
                'f431_codigo_barras'        => $membershipSubscription->is_renewal ? '3103144520224' : '1104424520023',
                'f431_id_bodega'            => 'BDHED',
                'f431_id_motivo'            => '60',
                'f431_id_co_movto'          => '601',
                'f431_id_un_movto'          => '104',
                'f431_id_ccosto_movto'      => '1201',
                'f431_fecha_entrega'        => $orderParams->date,
                'f431_id_lista_precio'      => '001',
                'f431_id_unidad_medida'     => 'UND',
                'f431_cant_pedida_base'     => 1,
                'f431_precio_unitario'      => $membershipSubscription->membership->price,
                'f431_ind_precio'           => '1',
                'f431_ind_obsequio'         => '0',
                'f431_ind_impto_asumido'    => '0'
            )
        ];

        if ($membershipSubscription->delivery > 0) {
            $delivery = array(
                'f431_id_co'                => $orderParams->operationCenter,
                'f431_consec_docto'         => '1',
                'f431_nro_registro'         => '1',
                'f431_referencia_item'      => '110440022',
                'f431_codigo_barras'        => '',
                'f431_id_bodega'            => 'BDHED',
                'f431_id_motivo'            => '05',
                'f431_id_co_movto'          => $orderParams->operationCenter,
                'f431_id_un_movto'          => '102',
                'f431_id_ccosto_movto'      => '4001',
                'f431_fecha_entrega'        => $orderParams->date,
                'f431_id_lista_precio'      => '005',
                'f431_id_unidad_medida'     => 'UND',
                'f431_cant_pedida_base'     => '1',
                'f431_precio_unitario'      => (int) $membershipSubscription->delivery,
                'f431_ind_precio'           => '2',
                'f431_ind_obsequio'         => '0',
                'f431_ind_impto_asumido'    => '0'
            );
            array_push($orderParams->items, $delivery);
        }

        $erpCustomItems = ErpCustomItem::where('active', true)
            ->where('amount', '>', 0)
            ->where('modules', 'like', '%membership%')
            ->where(function ($query) {
                $query->orWhereNull('labels');
                $query->orWhere('labels', '');
            })
            ->get();

        foreach ($erpCustomItems as $erpCustomItem) {
            $customItem = array(
                'f431_id_co'                => $orderParams->operationCenter,
                'f431_consec_docto'         => '1',
                'f431_nro_registro'         => count($orderParams->items) + 1,
                'f431_referencia_item'      => $erpCustomItem->reference ?? '',
                'f431_codigo_barras'        => $erpCustomItem->barcode ?? '',
                'f431_id_bodega'            => 'BDHED',
                'f431_id_motivo'            => $erpCustomItem->is_gift ? '08' : '60',
                'f431_id_co_movto'          => '601',
                'f431_id_un_movto'          => '104',
                'f431_id_ccosto_movto'      => '1201',
                'f431_fecha_entrega'        => $orderParams->date,
                'f431_id_lista_precio'      => $erpCustomItem->is_gift ? '015' : '001',
                'f431_id_unidad_medida'     => 'UND',
                'f431_cant_pedida_base'     => $erpCustomItem->amount,
                'f431_precio_unitario'      => 1,
                'f431_ind_precio'           => '1',
                'f431_ind_obsequio'         => $erpCustomItem->is_gift ? '1' : '0',
                'f431_ind_impto_asumido'    => $erpCustomItem->is_gift ? '1' : '0'
            );
            array_push($orderParams->items, $customItem);
        }

        $discounts = [];
        $orderParams->discounts = $discounts;

        $response = $ERPRepository->createOrder($orderParams);
        if (!$response['r']) {
            $this->saveERPLog($membershipSubscription->id, json_encode($response['d']), 'createOrder');
            return;
        }
        $this->createRCERP($membershipSubscription, $ERPRepository);
    }

    private function createRCERP($membershipSubscription, $ERPRepository)
    {
        $paymentTransaction = PaymentTransaction::where('id', $membershipSubscription->payment_transaction_id)->first();
        $response = $ERPRepository->getOrder($this->ERPPrefix . $membershipSubscription->id);
        if (!$response['r']) {
            $this->saveERPLog($membershipSubscription->id, json_encode($response['d']), 'createRC');
            return;
        }

        $user = $membershipSubscription->user;
        $price = $membershipSubscription->membership->price + $membershipSubscription->delivery;
        foreach ($response['d']->detalle->Table as $index => $siesaOrder) {
            $response = $ERPRepository->getRC($user->document, $siesaOrder->CentroDeOperacion);
            if ($response['r']) {
                $previousRC = array_filter($response['d']->detalle->Table, function ($item) use ($paymentTransaction, $price) {
                    return str_contains($item->Notas, $paymentTransaction->reference) && $item->TotalRecibo == $price;
                }, ARRAY_FILTER_USE_BOTH);

                if (count($previousRC)) {
                    $this->createBillERP($membershipSubscription, $ERPRepository);
                    continue;
                }
            }

            $parameters = new \stdClass();
            $parameters->paymentDate = Carbon::parse($paymentTransaction->payment_date)->format('Ymd');
            $parameters->idThird = $user->document;
            $parameters->currency = 'COP';
            $parameters->siesaOrder = $siesaOrder;
            $parameters->fe = '1104';
            $parameters->note = $membershipSubscription->membership->name . '-' . $paymentTransaction->reference;
            $parameters->assistant = '28050507';
            $parameters->sucursal = '001';
            $parameters->paymetMethod = 'WOM';
            $parameters->UN = '104';
            $parameters->price = $price;

            $response = $ERPRepository->createRC($parameters);
            if (!$response['r']) {
                $this->saveERPLog($membershipSubscription->id, json_encode($response['d']), 'createRC');
                return;
            }
            $this->createBillERP($membershipSubscription, $ERPRepository);
        }
    }

    private function createBillERP($membershipSubscription, $ERPRepository)
    {
        $response = $ERPRepository->getOrder($this->ERPPrefix . $membershipSubscription->id);
        if (!$response['r']) {
            $this->saveERPLog($membershipSubscription->id, json_encode($response['d']), 'createBill');
            return;
        }

        $paymentTransaction = PaymentTransaction::where('id', $membershipSubscription->payment_transaction_id)->first();
        foreach ($response['d']->detalle->Table as $index => $siesaOrder) {
            $parameters = new \stdClass();
            $parameters->siesaOrder     = $siesaOrder;
            $parameters->thirdDocument  = $membershipSubscription->user->document;
            $parameters->note           = $membershipSubscription->membership->name . '-' . $paymentTransaction->reference;
            $parameters->price          = $membershipSubscription->membership->price + $membershipSubscription->delivery;
            $parameters->typeDocument   = 'FE1';

            $response = $ERPRepository->createBill($parameters);
            if (!$response['r']) {
                $this->saveERPLog($membershipSubscription->id, json_encode($response['d']), 'createBill');
                return;
            }
        }
        $this->confirmSyncERP($membershipSubscription);
    }

    private function validateSyncWithERPPayment($membershipSubscription)
    {
        return !MembershipSubscriber::select('sync_with_erp')
            ->where('id', $membershipSubscription->id)
            ->first()
            ->sync_with_erp;
    }

    public function saveERPLog($data, $message, $action)
    {
        $transactionId = $data;
        ErpLog::updateOrCreate(
            [
                'origin'         => 'membership',
                'transaction_id' => $transactionId,
                'resolved'       => false
            ],
            [
                'origin'         => 'membership',
                'action'         => $action,
                'origin_class'   => get_class($this),
                'data'           => $data,
                'transaction_id' => $transactionId,
                'message'        => $message,
            ]
        );
    }

    public function confirmSyncERP($membershipSubscription)
    {
        $membershipSubscription->sync_with_erp = true;
        $membershipSubscription->update();
    }

    public function retrySyncERP($data, $action)
    {
        $membershipSubscription = MembershipSubscriber::find($data);
        $this->syncERP($membershipSubscription, $action);
    }

    private function calculateEndDate($date, $interval)
    {
        switch ($interval) {
            case 'yearly':
                return $date->addYear();
                break;

            case 'monthly':
                return $date->addMonth();
                break;

            case 'weekly':
                return $date->addWeek();
                break;

            case 'daily':
                return $date->addDay();
                break;

            default:
                return $date->addDay();
                break;
        }
    }

    public function existBySegementation($segmentation)
    {
        $membership = Membership::select('id', 'active')
            ->join('membership_tags', 'membership_tags.membership_id', '=', 'memberships.id')
            ->whereIn('membership_tags.tag_id', $segmentation)
            ->first();

        return $membership ? true : false;
    }

    public function memershipActiveBySegmentation($segmentation)
    {
        $membership = Membership::select('id')
            ->join('membership_tags', 'membership_tags.membership_id', '=', 'memberships.id')
            ->whereIn('membership_tags.tag_id', $segmentation)
            ->where('memberships.active', true)
            ->first();

        return $membership ? true : false;
    }
}