GrafiteInc/Commerce

View on GitHub
src/Services/CouponService.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace Grafite\Commerce\Services;

use App\Models\UserMeta;
use App\Services\UserService;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\Schema;
use Laravel\Cashier\Subscription;
use Grafite\Cms\Services\CmsService;
use Grafite\Commerce\Models\Coupon;

class CouponService
{
    public function __construct(
        Coupon $coupon,
        StripeService $stripeService,
        UserService $userService
    ) {
        $this->model = $coupon;
        $this->stripeService = $stripeService;
        $this->userService = $userService;
    }

    /**
     * Get all Coupons.
     *
     * @return Collection
     */
    public function all()
    {
        return $this->model->all();
    }

    /**
     * Get all enabled coupons.
     *
     * @return Collection
     */
    public function allEnabled()
    {
        return $this->model->where('enabled', true)->get();
    }

    /**
     * Collect the new coupons.
     */
    public function collectNewCoupons()
    {
        $stripeCoupons = $this->stripeService->collectStripeCoupons()->data;

        foreach ($stripeCoupons as $coupon) {
            $localCoupon = $this->model->getCouponsByStripeId($coupon->id);

            if (!$localCoupon) {
                $endDate = null;
                $discount_type = 'percentage';

                if (!is_null($coupon->redeem_by)) {
                    $endDate = Carbon::parse($coupon->redeem_by);
                }
                if (is_null($coupon->percent_off)) {
                    $discount_type = 'dollar';
                }

                $this->model->create([
                    'stripe_id' => $coupon->id,
                    'start_date' => Carbon::createFromTimestamp($coupon->created),
                    'end_date' => $endDate,
                    'discount_type' => $discount_type,
                    'code' => $coupon->id,
                    'amount' => $coupon->amount_off,
                    'limit' => $coupon->max_redemptions ?? 1,
                    'currency' => config('commerce.currency'),
                    'for_subscriptions' => true,
                ]);
            }
        }
    }

    /**
     * Get paginated coupons.
     *
     * @return Collection
     */
    public function paginated()
    {
        return $this->model->paginate(config('cms.pagination', 25));
    }

    /**
     * Search all the coupons.
     *
     * @param array $payload
     *
     * @return Collection
     */
    public function search($payload)
    {
        $query = $this->model->orderBy('created_at', 'desc');

        $columns = Schema::getColumnListing('coupons');

        foreach ($columns as $attribute) {
            $query->orWhere($attribute, 'LIKE', '%'.$payload.'%');
        }

        return $query->paginate(config('cms.pagination', 25));
    }

    /**
     * Create a coupon.
     *
     * @param array $payload
     *
     * @return Coupon
     */
    public function create($payload)
    {
        try {
            $payload['stripe_id'] = $payload['code'];
            $payload['currency'] = config('commerce.currency');

            if (empty($payload['start_date'])) {
                $payload['start_date'] = Carbon::now();
            }

            if (empty($payload['end_date'])) {
                $payload['end_date'] = Carbon::now()->addDays(30);
            }

            if (isset($payload['for_subscriptions'])) {
                $payload['for_subscriptions'] = true;
            } else {
                $payload['for_subscriptions'] = false;
            }

            if ($payload['for_subscriptions']) {
                $this->stripeService->createCoupon($payload);
            }

            return $this->model->create($payload);
        } catch (Exception $e) {
            throw new Exception('Could not generate new coupon', 1);
        }

        return false;
    }

    /**
     * Find a coupon.
     *
     * @param int $id
     *
     * @return Coupon
     */
    public function find($id)
    {
        return $this->model->find($id);
    }

    /**
     * Get coupons by stripe ID.
     *
     * @param int $id
     *
     * @return Coupon
     */
    public function findByStripeId($id)
    {
        return $this->model->where('stripe_id', $id)->first();
    }

    /**
     * Destroy a coupon.
     *
     * @param int $id
     *
     * @return bool
     */
    public function destroy($id)
    {
        try {
            $localCoupon = $this->model->find($id);

            try {
                $couponIsDeleted = $this->stripeService->deleteCoupon($localCoupon->stripe_id);
            } catch (\Stripe\Error\InvalidRequest $e) {
                $localCoupon->delete();

                return true;
            }

            return $this->model->destroy($id);
        } catch (Exception $e) {
            throw new Exception('Could not delete your coupon', 1);
        }

        return false;
    }
}