working repository v1

mail@pastecode.io avatar
unknown
php
a year ago
14 kB
1
Indexable
<?php
namespace Modules\Groovesell\Repositories;

use Illuminate\Database\Eloquent\ModelNotFoundException;
use App\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Modules\Groovesell\Entities\AffiliateAnalytic;
use Modules\Groovesell\Entities\AffiliateLink;
use Modules\Groovesell\Entities\Domain;
use Modules\Groovesell\Entities\Funnel;
use Modules\Groovesell\Entities\FunnelAffiliate;
use Modules\Groovesell\Entities\FunnelResource;
use Modules\Groovesell\Entities\PricePoint;
use Modules\Groovesell\Entities\Product;
use Modules\Groovesell\Entities\SecondTierLink;
use Modules\Groovesell\Entities\Transaction;
use Modules\Groovesell\Entities\AffiliateLog;

class PromosRepository
{
    public function getDashboardStats(User $user, $funnelId, $request)
    {
        $dateRange = $this->getFromToDates($request);
        list($fromDate, $toDate) = $dateRange;

        // Calculate impressions and uniques using MongoDB aggregation
        $impressionsData = $this->calculateImpressionsAndUniques($funnelId, $user, $fromDate, $toDate);
        list($uniques, $impressions) = $this->extractImpressionData($impressionsData);

        // Calculate other statistics
        $stats = $this->calculateStatistics($user, $funnelId, $fromDate, $toDate);

        $optins = $stats->signup_count ?? 0;
        $transactions = $stats->sales_count ?? 0;
        $commissions = ($stats->commission_amount ?? 0) / 100;

        // Retrieve the funnel and checkout domain information
        list($funnel, $checkoutDomain) = $this->getFunnelAndDomain($funnelId);

        // Generate affiliate links
        $affiliateLinks = $this->generateAffiliateLinks($user, $funnel, $funnelId, $checkoutDomain);

        // Retrieve funnel resource
        $funnelResource = FunnelResource::where([
            ['funnel_id', $funnelId],
            ['is_default', 1],
        ])->first();

        $response = [
            'impressions' => $impressions,
            'uniques' => $uniques,
            'optins' => $optins,
            'sales' => $transactions,
            'commissions' => '$' . $commissions,
            'affiliate_links' => $affiliateLinks,
            'resource_permalink' => $funnelResource->permalink,
        ];

        return $response;
    }

    public function getMainDashboardStats(User $user, $request)
    {
        $dateRange = $this->getFromToDates($request);
        list($fromDate, $toDate) = $dateRange;

        $funnels = FunnelAffiliate::where('user_id', $user->id)->get();
        $promosArray = [];
        $hasPromos = 0;
        $hasData = 0;

        foreach ($funnels as $singleFunnel) {
            $funnelId = $singleFunnel->funnel_id;
            $fetchedFunnel = Funnel::find($funnelId);

            if (!$fetchedFunnel) {
                continue;
            }

            $hasPromos = 1;

            // Calculate impressions and uniques using MongoDB aggregation
            $impressionsData = $this->calculateImpressionsAndUniques($funnelId, $user, $fromDate, $toDate);
            list($uniques, $impressions) = $this->extractImpressionData($impressionsData);

            // Calculate other statistics
            $stats = $this->calculateStatistics($user, $funnelId, $fromDate, $toDate);

            $optins = $stats->signup_count ?? 0;
            $transactions = $stats->sales_count ?? 0;
            $commissions = ($stats->commission_amount ?? 0) / 100;

            if ($impressions > 0 || $uniques > 0 || $commissions > 0 || $transactions > 0 || $optins > 0) {
                $hasData = 1;
            }

            $singlePromoResource = [
                'id' => $funnelId,
                'name' => $fetchedFunnel->name,
                'impressions' => $impressions,
                'uniques' => $uniques,
                'commissions' => number_format((float) $commissions, 2, '.', ''),
                'conversions' => $transactions,
                'optins' => $optins,
            ];

            $promosArray[] = $singlePromoResource;
        }

        return ['data' => $promosArray, 'has_used' => $hasPromos, 'has_data' => $hasData];
    }

    private function getFromToDates($request)
    {
        if ($request->has('fromDate') && $request->has('toDate')) {
            $fromDate = Carbon::createFromFormat('m/d/Y', $request->fromDate, 'US/Eastern')->startOfDay()->setTimezone('UTC');
            $toDate = Carbon::createFromFormat('m/d/Y', $request->toDate, 'US/Eastern')->endOfDay()->setTimezone('UTC');
        } else {
            $fromDate = Carbon::now('US/Eastern')->startOfDay()->setTimezone('UTC');
            $toDate = Carbon::now('US/Eastern')->endOfDay()->setTimezone('UTC');
        }

        return [$fromDate, $toDate];
    }

    private function calculateImpressionsAndUniques($funnelId, $user, $fromDate, $toDate)
    {
        $result = AffiliateLog::where('funnel_id', $funnelId)
            ->where('affiliate_id', $user->id)
            ->whereBetween('created_timestamp', [$fromDate->timestamp, $toDate->timestamp])
            ->aggregate([
                ['$group' => [
                    '_id' => '$affiliate_id',
                    'impressions' => ['$sum' => 1],
                    'uniqueIps' => ['$addToSet' => '$client_ip']
                ]],
                ['$project' => [
                    'impressions' => '$impressions',
                    'uniques' => ['$size' => '$uniqueIps']
                ]]
            ])->first();
    
        return [
            'impressions' => $result->impressions ?? 0,
            'uniques' => $result->uniques ?? 0,
        ];
    }

    private function extractImpressionData($impressionsData)
    {
        return [$impressionsData->uniques ?? 0, $impressionsData->impressions ?? 0];
    }

    private function calculateStatistics($user, $funnelId, $fromDate, $toDate)
    {
        return Transaction::where('affiliate_id', $user->id)
            ->where('computed_status', 2)
            ->where('funnel_id', $funnelId)
            ->whereBetween('created_timestamp', [$fromDate->timestamp, $toDate->timestamp])
            ->select(
                DB::raw("SUM(CASE WHEN gateway_type = 'FREE' THEN 1 ELSE 0 END) AS signup_count"),
                DB::raw("SUM(CASE WHEN gateway_type != 'FREE' AND gateway_type != 'test' AND is_refunded = 0 THEN 1 ELSE 0 END) AS sales_count"),
                DB::raw("SUM(CASE WHEN gateway_type != 'FREE' AND gateway_type != 'test' AND is_refunded = 0 AND commission > 0 THEN commission ELSE 0 END) AS commission_amount")
            )
            ->first();
    }

    private function getFunnelAndDomain($funnelId)
    {
        $fetchedFunnel = Funnel::find($funnelId);

        if ($fetchedFunnel && $fetchedFunnel->cross_aff_program_id > 0) {
            $funnel = Funnel::find($fetchedFunnel->cross_aff_program_id);
            $affFunnelId = $fetchedFunnel->cross_aff_program_id;
        } else {
            $funnel = $fetchedFunnel;
            $affFunnelId = $funnelId;
        }

        $checkoutDomain = Domain::where([
            ['type', 1],
            ['funnel_assigned_to', $funnel->id],
        ])->first();

        return [$funnel, $checkoutDomain];
    }

    private function generateAffiliateLinks($user, $funnel, $affFunnelId, $checkoutDomain)
    {
        $affiliateLinks = [];

        $mainProduct = Product::where([
            ['funnel_id', $affFunnelId],
            ['affiliates_enabled', 1],
            ['is_main', 1],
        ])->first();

        if ($mainProduct && $mainProduct->affiliate_landing_pages && count($mainProduct->affiliate_landing_pages) > 0) {
            foreach ($mainProduct->affiliate_landing_pages as $singleAffiliateLandingPage) {
                if ($this->isLandingPageAssignedToAffiliate($singleAffiliateLandingPage, $user)) {
                    $affiliateLinkForThisLandingPage = AffiliateLink::where([
                        ['affiliate_id', $user->id],
                        ['funnel_id', $affFunnelId],
                        ['product_id', $mainProduct->id],
                        ['landing_page_id', $singleAffiliateLandingPage['id']],
                    ])->orderBy('id', 'desc')->first();

                    if (!$affiliateLinkForThisLandingPage) {
                        $affiliateLinkForThisLandingPage = new AffiliateLink;
                        $affiliateLinkForThisLandingPage->affiliate_id = $user->id;
                        $affiliateLinkForThisLandingPage->funnel_id = $affFunnelId;
                        $affiliateLinkForThisLandingPage->product_id = $mainProduct->id;
                        $affiliateLinkForThisLandingPage->landing_page_id = $singleAffiliateLandingPage['id'];
                        $affiliateLinkForThisLandingPage->permalink = str_random(12);
                        $affiliateLinkForThisLandingPage->save();
                    }

                    $singleAffiliateLink['name'] = $singleAffiliateLandingPage['description'];
                    $urlArray = parse_url(env('GROOVESELL_FRONTEND_URL'));

                    if ($checkoutDomain) {
                        $singleAffiliateLink['link'] = 'https://' . $checkoutDomain->name . '/a/' . $affiliateLinkForThisLandingPage->permalink;
                    } else {
                        $singleAffiliateLink['link'] = 'https://' . $funnel->slug . '.groovesell.com/a/' . $affiliateLinkForThisLandingPage->permalink;
                    }

                    $singleAffiliateLink['type'] = 'affiliate';
                    $affiliateLinks[] = $singleAffiliateLink;
                }
            }

            $has2ndTier = $this->has2ndTier($user, $affFunnelId);

            if ($has2ndTier == 1) {
                $secondTierLinkForThisFunnel = SecondTierLink::where([
                    ['affiliate_id', $user->id],
                    ['funnel_id', $affFunnelId],
                ])->orderBy('id', 'desc')->first();

                if (!$secondTierLinkForThisFunnel) {
                    $secondTierLinkForThisFunnel = new SecondTierLink;
                    $secondTierLinkForThisFunnel->affiliate_id = $user->id;
                    $secondTierLinkForThisFunnel->funnel_id = $affFunnelId;
                    $secondTierLinkForThisFunnel->permalink = str_random(12);
                    $secondTierLinkForThisFunnel->save();
                }

                $singleSecondTierLink = [];
                $singleSecondTierLink['name'] = '2nd Tier Affiliate Link';
                $urlArray = parse_url(env('GROOVESELL_FRONTEND_URL'));

                if ($checkoutDomain) {
                    $singleSecondTierLink['link'] = 'https://' . $checkoutDomain->name . '/jv/' . $secondTierLinkForThisFunnel->permalink;
                } else {
                    $singleSecondTierLink['link'] = 'https://' . $funnel->slug . '.groovesell.com/jv/' . $secondTierLinkForThisFunnel->permalink;
                }

                $affiliateLinks[] = $singleSecondTierLink;
            }
        }

        return $affiliateLinks;
    }

    private function isLandingPageAssignedToAffiliate($landingPage, $user)
    {
        foreach ($landingPage['assigned_to'] as $singleAssignedTo) {
            if ($singleAssignedTo['id'] == 0 || $singleAssignedTo['id'] == $user->id) {
                return true;
            }
        }

        return false;
    }
    private function has2ndTier($user, $affFunnelId)
    {
        $has2ndTier = 0;
        $allAffiliateEnabledProducts = Product::where([
            ['funnel_id', $affFunnelId],
            ['affiliates_enabled', 1],
        ])->get();
    
        foreach ($allAffiliateEnabledProducts as $product) {
            if ($this->productHasSecondTier($product, $user)) {
                $has2ndTier = 1;
                break;
            }
        }
    
        return $has2ndTier;
    }
    
    private function productHasSecondTier($product, $user)
    {
        $pricePoints = PricePoint::where('product_id', $product->id)->get();
        
        foreach ($pricePoints as $pricePoint) {
            $commissionDetails = $pricePoint->commission_details;
    
            if ($this->hasSecondTierCommission($commissionDetails, $user)) {
                return true;
            }
        }
    
        return false;
    }
    
    private function hasSecondTierCommission($commissionDetails, $user)
    {
        foreach ($commissionDetails as $commissionTier) {
            if (
                empty($commissionTier['assigned_to']) ||
                in_array($user->id, $commissionTier['assigned_to'])
            ) {
                if (
                    $this->hasSecondTierTrialCommission($commissionTier) ||
                    $this->hasSecondTierSalesCommission($commissionTier) ||
                    $this->hasSecondTierRebillCommission($commissionTier)
                ) {
                    return true;
                }
            }
        }
    
        return false;
    }
    
    private function hasSecondTierTrialCommission($commissionTier)
    {
        return $commissionTier['trial_commission']['jv_broker_commission'] > 0;
    }
    
    private function hasSecondTierSalesCommission($commissionTier)
    {
        return (
            ($commissionTier['sales_commission']['jv_broker_commission'] > 0) &&
            ($commissionTier['sales_commission']['jv_broker_commission'] > 0)
        );
    }
    
    private function hasSecondTierRebillCommission($commissionTier)
    {
        foreach ($commissionTier['rebill_commissions'] as $rebillCommission) {
            if ($rebillCommission['jv_broker_commission'] > 0) {
                return true;
            }
        }
    
        return false;
    }
}