ArthurGuy/BBMembershipSystem

View on GitHub
app/Http/Controllers/PaymentController.php

Summary

Maintainability
C
7 hrs
Test Coverage
<?php namespace BB\Http\Controllers;

use BB\Entities\Induction;
use BB\Entities\Payment;
use BB\Entities\User;
use BB\Exceptions\NotImplementedException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;

class PaymentController extends Controller
{


    /**
     *
     * @TODO: Workout exactly what this is used for - I think most of the functionality has been moved elsewhere
     *
     */


    /**
     * @var \BB\Repo\EquipmentRepository
     */
    private $equipmentRepository;
    /**
     * @var \BB\Repo\PaymentRepository
     */
    private $paymentRepository;
    /**
     * @var \BB\Repo\UserRepository
     */
    private $userRepository;
    /**
     * @var \BB\Repo\SubscriptionChargeRepository
     */
    private $subscriptionChargeRepository;

    function __construct(
        \BB\Helpers\GoCardlessHelper $goCardless,
        \BB\Repo\EquipmentRepository $equipmentRepository,
        \BB\Repo\PaymentRepository $paymentRepository,
        \BB\Repo\UserRepository $userRepository,
        \BB\Repo\SubscriptionChargeRepository $subscriptionChargeRepository
    ) {
        $this->goCardless                   = $goCardless;
        $this->equipmentRepository          = $equipmentRepository;
        $this->paymentRepository            = $paymentRepository;
        $this->userRepository               = $userRepository;
        $this->subscriptionChargeRepository = $subscriptionChargeRepository;

        $this->middleware('role:member', array('only' => ['create', 'destroy']));

    }


    public function index()
    {
        $sortBy       = \Request::get('sortBy', 'created_at');
        $direction    = \Request::get('direction', 'desc');
        $dateFilter   = \Request::get('date_filter', '');
        $memberFilter = \Request::get('member_filter', '');
        $reasonFilter = \Request::get('reason_filter', '');
        $this->paymentRepository->setPerPage(50);

        if ($dateFilter) {
            $startDate = \Carbon\Carbon::createFromFormat('Y-m-d', $dateFilter)->setTime(0, 0, 0);
            $this->paymentRepository->dateFilter($startDate, $startDate->copy()->addMonth());
        }

        if ($memberFilter) {
            $this->paymentRepository->memberFilter($memberFilter);
        }

        if ($reasonFilter) {
            $this->paymentRepository->reasonFilter($reasonFilter);
        }

        $payments = $this->paymentRepository->getPaginated(compact('sortBy', 'direction'));

        $paymentTotal = $this->paymentRepository->getTotalAmount();

        $dateRangeEarliest = \Carbon\Carbon::create(2009, 07, 01);
        $dateRangeStart    = \Carbon\Carbon::now();
        $dateRange         = [];
        while ($dateRangeStart->gt($dateRangeEarliest)) {
            $dateRange[$dateRangeStart->toDateString()] = $dateRangeStart->format('F Y');
            $dateRangeStart->subMonth();
        }

        $memberList = $this->userRepository->getAllAsDropdown();

        $reasonList = [
            'subscription'  => 'Subscription',
            'induction'     => 'Equipment Access Fee',
            'balance'       => 'Balance',
            'door-key'      => 'Key Deposit',
            'storage-box'   => 'Storage Box Payment',
            'equipment-fee' => 'Equipment Costs'
        ];

        return \View::make('payments.index')->with('payments', $payments)->with('dateRange', $dateRange)
            ->with('memberList', $memberList)->with('reasonList', $reasonList)->with('paymentTotal', $paymentTotal);
    }


    /**
     * Start the creation of a new gocardless payment
     *   Details get posted into this method and the redirected to gocardless
     *
     * @depreciated
     * @param $userId
     * @throws \BB\Exceptions\AuthenticationException
     * @throws \BB\Exceptions\FormValidationException
     * @throws \BB\Exceptions\NotImplementedException
     */
    public function create($userId)
    {
        throw new \BB\Exceptions\NotImplementedException();
    }


    /**
     * Store a manual payment
     *
     * @param $userId
     * @throws \BB\Exceptions\AuthenticationException
     * @throws \BB\Exceptions\FormValidationException
     * @throws \BB\Exceptions\NotImplementedException
     * @return Illuminate\Http\RedirectResponse
     * @deprecated
     */
    public function store($userId)
    {
        $user = User::findWithPermission($userId);

        if ( ! \Auth::user()->hasRole('admin') &&  ! \Auth::user()->hasRole('finance')) {
            throw new \BB\Exceptions\AuthenticationException;
        }

        \Log::debug('Manual payment endpoint getting hit. account/{id}/payment. paymentController@store '.json_encode(\Input::all()));

        $reason = \Input::get('reason');

        if ($reason == 'subscription') {
            $payment = new Payment([
                'reason'           => $reason,
                'source'           => \Input::get('source'),
                'source_id'        => '',
                'amount'           => $user->monthly_subscription,
                'amount_minus_fee' => $user->monthly_subscription,
                'status'           => 'paid'
            ]);
            $user->payments()->save($payment);

            $user->extendMembership(\Input::get('source'), \Carbon\Carbon::now()->addMonth());

        } elseif ($reason == 'induction') {
            if (\Input::get('source') == 'manual') {
                $ref = \Input::get('induction_key');
                ($item = $this->equipmentRepository->findBySlug($ref)) || App::abort(404);
                $payment = new Payment([
                    'reason'           => $reason,
                    'source'           => 'manual',
                    'source_id'        => '',
                    'amount'           => $item->cost,
                    'amount_minus_fee' => $item->cost,
                    'status'           => 'paid'
                ]);
                $payment = $user->payments()->save($payment);
                Induction::create([
                    'user_id'    => $user->id,
                    'key'        => $ref,
                    'paid'       => true,
                    'payment_id' => $payment->id
                ]);
            } else {
                throw new \BB\Exceptions\NotImplementedException();
            }
        } elseif ($reason == 'door-key') {
            $payment = new Payment([
                'reason'           => $reason,
                'source'           => \Input::get('source'),
                'source_id'        => '',
                'amount'           => 15,
                'amount_minus_fee' => 15,
                'status'           => 'paid'
            ]);
            $user->payments()->save($payment);

            $user->key_deposit_payment_id = $payment->id;
            $user->save();

        } elseif ($reason == 'storage-box') {
            $payment = new Payment([
                'reason'           => $reason,
                'source'           => \Input::get('source'),
                'source_id'        => '',
                'amount'           => 5,
                'amount_minus_fee' => 5,
                'status'           => 'paid'
            ]);
            $user->payments()->save($payment);

            $user->storage_box_payment_id = $payment->id;
            $user->save();
        } elseif ($reason == 'balance') {
            $amount = \Input::get('amount') * 1; //convert the users amount into a number
            if ( ! is_numeric($amount)) {
                $exceptionErrors = new \Illuminate\Support\MessageBag(['amount' => 'Invalid amount']);
                throw new \BB\Exceptions\FormValidationException('Not a valid amount', $exceptionErrors);
            }
            $payment = new Payment([
                'reason'           => 'balance',
                'source'           => \Input::get('source'),
                'source_id'        => '',
                'amount'           => $amount,
                'amount_minus_fee' => $amount,
                'status'           => 'paid'
            ]);
            $user->payments()->save($payment);

            $memberCreditService = \App::make('\BB\Services\Credit');
            $memberCreditService->setUserId($user->id);
            $memberCreditService->recalculate();

            //This needs to be improved
            \Notification::success('Payment recorded');

            return \Redirect::route('account.bbcredit.index', $user->id);
        } else {
            throw new \BB\Exceptions\NotImplementedException();
        }
        \Notification::success('Payment recorded');

        return \Redirect::route('account.show', [$user->id]);
    }


    /**
     * Display the specified resource.
     *
     * @param  int $id
     * @return Response
     */
    public function show($id)
    {
        //
    }


    /**
     * Show the form for editing the specified resource.
     *
     * @param  int $id
     * @return Response
     */
    public function edit($id)
    {
        //
    }


    /**
     * Update a payment
     * Change where the money goes by altering the original record or creating a secondary payment
     *
     * @param Request $request
     * @param  int    $paymentId
     *
     * @return Illuminate\Http\RedirectResponse
     * @throws NotImplementedException
     * @throws \BB\Exceptions\PaymentException
     */
    public function update(Request $request, $paymentId)
    {
        $payment = $this->paymentRepository->getById($paymentId);

        switch($request->get('change')) {
            case 'assign-unknown-to-user':
                $newUserId = $request->get('user_id');
                try {
                    $newUser = $this->userRepository->getById($newUserId);
                } catch (ModelNotFoundException $e) {
                    \Notification::error('User not found');
                    break;
                }

                $this->paymentRepository->assignPaymentToUser($paymentId, $newUser->id);

                \Notification::success('Payment updated');

                break;

            case 'refund-to-balance':

                if ($payment->reason === 'induction') {
                    throw new NotImplementedException('Please refund via the member induction list');
                }

                $this->paymentRepository->refundPaymentToBalance($paymentId);

                \Notification::success('Payment updated');

                break;

            default:
                throw new NotImplementedException('This hasn\'t been built yet');
        }

        return \Redirect::back();
    }


    /**
     * Remove the specified payment
     *
     * @param  int $id
     * @return Illuminate\Http\RedirectResponse
     * @throws \BB\Exceptions\ValidationException
     */
    public function destroy($id)
    {
        $payment = $this->paymentRepository->getById($id);

        //we can only allow some records to get deleted, only cash payments can be removed, everything else must be refunded off
        if ($payment->source != 'cash') {
            throw new \BB\Exceptions\ValidationException('Only cash payments can be deleted');
        }
        if ($payment->reason != 'balance') {
            throw new \BB\Exceptions\ValidationException('Currently only payments to the members balance can be deleted');
        }

        //The delete event will broadcast an event and allow related actions to occur
        $this->paymentRepository->delete($id);

        \Notification::success('Payment deleted');

        return \Redirect::back();
    }


    /**
     * This is a method for migrating user to the variable gocardless subscription
     * It will cancel the existing direct debit and direct the user to setup a pre auth
     *
     * @return Illuminate\Http\RedirectResponse
     */
    public function migrateDD()
    {
        $user = \Auth::user();

        //cancel the existing dd
        try {
            $subscription = $this->goCardless->cancelSubscription($user->subscription_id);
            if ($subscription->status != 'cancelled') {
                \Notification::error('Could not cancel the existing subscription');

                return \Redirect::back();
            }
        } catch (\Exception $e) {

        }

        $user->payment_method  = '';
        $user->subscription_id = '';
        $user->save();

        $payment_details = array(
            'redirect_uri' => route('account.subscription.store', $user->id),
            'user'         => [
                'first_name'       => $user->given_name,
                'last_name'        => $user->family_name,
                'billing_address1' => $user->address->line_1,
                'billing_address2' => $user->address->line_2,
                'billing_town'     => $user->address->line_3,
                'billing_postcode' => $user->address->postcode,
                'country_code'     => 'GB'
            ]
        );

        return \Redirect::to($this->goCardless->newPreAuthUrl($payment_details));
    }

}