Completed
Push — gocardless-upgrade ( ab99fa )
by Arthur
02:58
created

PaymentController::create()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php namespace BB\Http\Controllers;
2
3
use BB\Entities\Induction;
4
use BB\Entities\Payment;
5
use BB\Entities\User;
6
use BB\Exceptions\NotImplementedException;
7
use Illuminate\Database\Eloquent\ModelNotFoundException;
8
use Illuminate\Http\Request;
9
10
class PaymentController extends Controller
11
{
12
13
14
    /**
15
     *
16
     * @TODO: Workout exactly what this is used for - I think most of the functionality has been moved elsewhere
17
     *
18
     */
19
20
21
    /**
22
     * @var \BB\Repo\EquipmentRepository
23
     */
24
    private $equipmentRepository;
25
    /**
26
     * @var \BB\Repo\PaymentRepository
27
     */
28
    private $paymentRepository;
29
    /**
30
     * @var \BB\Repo\UserRepository
31
     */
32
    private $userRepository;
33
    /**
34
     * @var \BB\Repo\SubscriptionChargeRepository
35
     */
36
    private $subscriptionChargeRepository;
37
38
    function __construct(
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
39
        \BB\Helpers\GoCardlessHelper $goCardless,
40
        \BB\Repo\EquipmentRepository $equipmentRepository,
41
        \BB\Repo\PaymentRepository $paymentRepository,
42
        \BB\Repo\UserRepository $userRepository,
43
        \BB\Repo\SubscriptionChargeRepository $subscriptionChargeRepository
44
    ) {
45
        $this->goCardless                   = $goCardless;
0 ignored issues
show
Bug introduced by
The property goCardless does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
46
        $this->equipmentRepository          = $equipmentRepository;
47
        $this->paymentRepository            = $paymentRepository;
48
        $this->userRepository               = $userRepository;
49
        $this->subscriptionChargeRepository = $subscriptionChargeRepository;
50
51
        $this->middleware('role:member', array('only' => ['create', 'destroy']));
52
53
    }
54
55
56
    public function index()
57
    {
58
        $sortBy       = \Request::get('sortBy', 'created_at');
59
        $direction    = \Request::get('direction', 'desc');
60
        $dateFilter   = \Request::get('date_filter', '');
61
        $memberFilter = \Request::get('member_filter', '');
62
        $reasonFilter = \Request::get('reason_filter', '');
63
        $this->paymentRepository->setPerPage(50);
64
65
        if ($dateFilter) {
66
            $startDate = \Carbon\Carbon::createFromFormat('Y-m-d', $dateFilter)->setTime(0, 0, 0);
67
            $this->paymentRepository->dateFilter($startDate, $startDate->copy()->addMonth());
68
        }
69
70
        if ($memberFilter) {
71
            $this->paymentRepository->memberFilter($memberFilter);
72
        }
73
74
        if ($reasonFilter) {
75
            $this->paymentRepository->reasonFilter($reasonFilter);
76
        }
77
78
        $payments = $this->paymentRepository->getPaginated(compact('sortBy', 'direction'));
79
80
        $paymentTotal = $this->paymentRepository->getTotalAmount();
81
82
        $dateRangeEarliest = \Carbon\Carbon::create(2009, 07, 01);
83
        $dateRangeStart    = \Carbon\Carbon::now();
84
        $dateRange         = [];
85
        while ($dateRangeStart->gt($dateRangeEarliest)) {
86
            $dateRange[$dateRangeStart->toDateString()] = $dateRangeStart->format('F Y');
87
            $dateRangeStart->subMonth();
88
        }
89
90
        $memberList = $this->userRepository->getAllAsDropdown();
91
92
        $reasonList = [
93
            'subscription'  => 'Subscription',
94
            'induction'     => 'Equipment Access Fee',
95
            'balance'       => 'Balance',
96
            'door-key'      => 'Key Deposit',
97
            'storage-box'   => 'Storage Box Deposit',
98
            'equipment-fee' => 'Equipment Costs'
99
        ];
100
101
        return \View::make('payments.index')->with('payments', $payments)->with('dateRange', $dateRange)
102
            ->with('memberList', $memberList)->with('reasonList', $reasonList)->with('paymentTotal', $paymentTotal);
103
    }
104
105
106
    /**
107
     * Start the creation of a new gocardless payment
108
     *   Details get posted into this method and the redirected to gocardless
109
     *
110
     * @depreciated
111
     * @param $userId
112
     * @throws \BB\Exceptions\AuthenticationException
113
     * @throws \BB\Exceptions\FormValidationException
114
     * @throws \BB\Exceptions\NotImplementedException
115
     */
116
    public function create($userId)
117
    {
118
        throw new \BB\Exceptions\NotImplementedException();
119
    }
120
121
122
    /**
123
     * Store a manual payment
124
     *
125
     * @param $userId
126
     * @throws \BB\Exceptions\AuthenticationException
127
     * @throws \BB\Exceptions\FormValidationException
128
     * @throws \BB\Exceptions\NotImplementedException
129
     * @return Illuminate\Http\RedirectResponse
130
     * @deprecated
131
     */
132
    public function store($userId)
133
    {
134
        $user = User::findWithPermission($userId);
135
136
        if ( ! \Auth::user()->hasRole('admin') &&  ! \Auth::user()->hasRole('finance')) {
137
            throw new \BB\Exceptions\AuthenticationException;
138
        }
139
140
        \Log::debug('Manual payment endpoint getting hit. account/{id}/payment. paymentController@store '.json_encode(\Input::all()));
141
142
        $reason = \Input::get('reason');
143
144
        if ($reason == 'subscription') {
145
            $payment = new Payment([
146
                'reason'           => $reason,
147
                'source'           => \Input::get('source'),
148
                'source_id'        => '',
149
                'amount'           => $user->monthly_subscription,
0 ignored issues
show
Documentation introduced by
The property monthly_subscription does not exist on object<BB\Entities\User>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
150
                'amount_minus_fee' => $user->monthly_subscription,
0 ignored issues
show
Documentation introduced by
The property monthly_subscription does not exist on object<BB\Entities\User>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
151
                'status'           => 'paid'
152
            ]);
153
            $user->payments()->save($payment);
154
155
            $user->extendMembership(\Input::get('source'), \Carbon\Carbon::now()->addMonth());
156
157
        } elseif ($reason == 'induction') {
158
            if (\Input::get('source') == 'manual') {
159
                $ref = \Input::get('induction_key');
160
                ($item = $this->equipmentRepository->findBySlug($ref)) || App::abort(404);
161
                $payment = new Payment([
162
                    'reason'           => $reason,
163
                    'source'           => 'manual',
164
                    'source_id'        => '',
165
                    'amount'           => $item->cost,
0 ignored issues
show
Documentation introduced by
The property cost does not exist on object<BB\Entities\Equipment>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
166
                    'amount_minus_fee' => $item->cost,
0 ignored issues
show
Documentation introduced by
The property cost does not exist on object<BB\Entities\Equipment>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
167
                    'status'           => 'paid'
168
                ]);
169
                $payment = $user->payments()->save($payment);
170
                Induction::create([
171
                    'user_id'    => $user->id,
172
                    'key'        => $ref,
173
                    'paid'       => true,
174
                    'payment_id' => $payment->id
175
                ]);
176
            } else {
177
                throw new \BB\Exceptions\NotImplementedException();
178
            }
179
        } elseif ($reason == 'door-key') {
180
            $payment = new Payment([
181
                'reason'           => $reason,
182
                'source'           => \Input::get('source'),
183
                'source_id'        => '',
184
                'amount'           => 10,
185
                'amount_minus_fee' => 10,
186
                'status'           => 'paid'
187
            ]);
188
            $user->payments()->save($payment);
189
190
            $user->key_deposit_payment_id = $payment->id;
0 ignored issues
show
Documentation introduced by
The property key_deposit_payment_id does not exist on object<BB\Entities\User>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property id does not exist on object<BB\Entities\Payment>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
191
            $user->save();
192
193
        } elseif ($reason == 'storage-box') {
194
            $payment = new Payment([
195
                'reason'           => $reason,
196
                'source'           => \Input::get('source'),
197
                'source_id'        => '',
198
                'amount'           => 5,
199
                'amount_minus_fee' => 5,
200
                'status'           => 'paid'
201
            ]);
202
            $user->payments()->save($payment);
203
204
            $user->storage_box_payment_id = $payment->id;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<BB\Entities\Payment>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
205
            $user->save();
206
        } elseif ($reason == 'balance') {
207
            $amount = \Input::get('amount') * 1; //convert the users amount into a number
208
            if ( ! is_numeric($amount)) {
209
                $exceptionErrors = new \Illuminate\Support\MessageBag(['amount' => 'Invalid amount']);
210
                throw new \BB\Exceptions\FormValidationException('Not a valid amount', $exceptionErrors);
211
            }
212
            $payment = new Payment([
213
                'reason'           => 'balance',
214
                'source'           => \Input::get('source'),
215
                'source_id'        => '',
216
                'amount'           => $amount,
217
                'amount_minus_fee' => $amount,
218
                'status'           => 'paid'
219
            ]);
220
            $user->payments()->save($payment);
221
222
            $memberCreditService = \App::make('\BB\Services\Credit');
223
            $memberCreditService->setUserId($user->id);
224
            $memberCreditService->recalculate();
225
226
            //This needs to be improved
227
            \Notification::success('Payment recorded');
228
229
            return \Redirect::route('account.bbcredit.index', $user->id);
230
        } else {
231
            throw new \BB\Exceptions\NotImplementedException();
232
        }
233
        \Notification::success('Payment recorded');
234
235
        return \Redirect::route('account.show', [$user->id]);
236
    }
237
238
239
    /**
240
     * Display the specified resource.
241
     *
242
     * @param  int $id
243
     * @return Response
244
     */
245
    public function show($id)
246
    {
247
        //
248
    }
249
250
251
    /**
252
     * Show the form for editing the specified resource.
253
     *
254
     * @param  int $id
255
     * @return Response
256
     */
257
    public function edit($id)
258
    {
259
        //
260
    }
261
262
263
    /**
264
     * Update a payment
265
     * Change where the money goes by altering the original record or creating a secondary payment
266
     *
267
     * @param Request $request
268
     * @param  int    $paymentId
269
     *
270
     * @return Illuminate\Http\RedirectResponse
271
     * @throws NotImplementedException
272
     * @throws \BB\Exceptions\PaymentException
273
     */
274
    public function update(Request $request, $paymentId)
275
    {
276
        $payment = $this->paymentRepository->getById($paymentId);
277
278
        switch($request->get('change')) {
279
            case 'assign-unknown-to-user':
280
                $newUserId = $request->get('user_id');
281
                try {
282
                    $newUser = $this->userRepository->getById($newUserId);
283
                } catch (ModelNotFoundException $e) {
284
                    \Notification::error('User not found');
285
                    break;
286
                }
287
288
                $this->paymentRepository->assignPaymentToUser($paymentId, $newUser->id);
289
290
                \Notification::success('Payment updated');
291
292
                break;
293
294
            case 'refund-to-balance':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
295
296
                if ($payment->reason === 'induction') {
297
                    throw new NotImplementedException('Please refund via the member induction list');
298
                }
299
300
                $this->paymentRepository->refundPaymentToBalance($paymentId);
301
302
                \Notification::success('Payment updated');
303
304
                break;
305
306
            default:
307
                throw new NotImplementedException('This hasn\'t been built yet');
308
        }
309
310
        return \Redirect::back();
311
    }
312
313
314
    /**
315
     * Remove the specified payment
316
     *
317
     * @param  int $id
318
     * @return Illuminate\Http\RedirectResponse
319
     * @throws \BB\Exceptions\ValidationException
320
     */
321
    public function destroy($id)
322
    {
323
        $payment = $this->paymentRepository->getById($id);
324
325
        //we can only allow some records to get deleted, only cash payments can be removed, everything else must be refunded off
326
        if ($payment->source != 'cash') {
327
            throw new \BB\Exceptions\ValidationException('Only cash payments can be deleted');
328
        }
329
        if ($payment->reason != 'balance') {
330
            throw new \BB\Exceptions\ValidationException('Currently only payments to the members balance can be deleted');
331
        }
332
333
        //The delete event will broadcast an event and allow related actions to occur
334
        $this->paymentRepository->delete($id);
335
336
        \Notification::success('Payment deleted');
337
338
        return \Redirect::back();
339
    }
340
341
342
    /**
343
     * This is a method for migrating user to the variable gocardless subscription
344
     * It will cancel the existing direct debit and direct the user to setup a pre auth
345
     *
346
     * @return Illuminate\Http\RedirectResponse
347
     */
348
    public function migrateDD()
349
    {
350
        $user = \Auth::user();
351
352
        //cancel the existing dd
353
        try {
354
            $subscription = $this->goCardless->cancelSubscription($user->subscription_id);
355
            if ($subscription->status != 'cancelled') {
356
                \Notification::error('Could not cancel the existing subscription');
357
358
                return \Redirect::back();
359
            }
360
        } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
361
362
        }
363
364
        $user->payment_method  = '';
365
        $user->subscription_id = '';
366
        $user->save();
367
368
        $payment_details = array(
369
            'redirect_uri' => route('account.subscription.store', $user->id),
370
            'user'         => [
371
                'first_name'       => $user->given_name,
372
                'last_name'        => $user->family_name,
373
                'billing_address1' => $user->address->line_1,
374
                'billing_address2' => $user->address->line_2,
375
                'billing_town'     => $user->address->line_3,
376
                'billing_postcode' => $user->address->postcode,
377
                'country_code'     => 'GB'
378
            ]
379
        );
380
381
        return \Redirect::to($this->goCardless->newPreAuthUrl($payment_details));
382
    }
383
384
}
385