/**
  * @param $user
  * @param $amount
  * @return void
  */
 private function setupNewMember(User $user, $amount)
 {
     //At this point the day of the month hasn't been set for the user, set it now
     $user->updateSubscription('paypal', Carbon::now()->day);
     //if this is blank then the user hasn't been setup yet
     $subCharge = $this->subscriptionChargeRepository->createCharge($user->id, Carbon::now(), $amount);
 }
 /**
  * The bill has been cancelled or failed, update the user records to compensate
  *
  * @param $existingPayment
  */
 private function handleFailedCancelledBill(Payment $existingPayment)
 {
     if ($existingPayment->reason == 'subscription') {
         //If the payment is a subscription payment then we need to take action and warn the user
         $user = $existingPayment->user()->first();
         $user->status = 'suspended';
         //Rollback the users subscription expiry date or set it to today
         $expiryDate = \BB\Helpers\MembershipPayments::lastUserPaymentExpires($user->id);
         if ($expiryDate) {
             $user->subscription_expires = $expiryDate;
         } else {
             $user->subscription_expires = new Carbon();
         }
         $user->save();
         //Update the subscription charge to reflect the payment failure
         $subCharge = $this->subscriptionChargeRepository->getById($existingPayment->reference);
         if ($subCharge) {
             $this->subscriptionChargeRepository->paymentFailed($subCharge->id);
         }
     } elseif ($existingPayment->reason == 'induction') {
         //We still need to collect the payment from the user
     } elseif ($existingPayment->reason == 'box-deposit') {
     } elseif ($existingPayment->reason == 'key-deposit') {
     }
 }
 private function updateSubPayment($paymentId, $userId, $status)
 {
     $payment = $this->paymentRepository->getById($paymentId);
     $subCharge = $this->subscriptionChargeRepository->findCharge($userId);
     if (!$subCharge) {
         \Log::warning('Subscription payment without a sub charge. Payment ID:' . $paymentId);
         return;
     }
     //The sub charge record id gets saved onto the payment
     if (empty($payment->reference)) {
         $payment->reference = $subCharge->id;
         $payment->save();
     } else {
         if ($payment->reference != $subCharge->id) {
             throw new PaymentException('Attempting to update sub charge (' . $subCharge->id . ') but payment (' . $payment->id . ') doesn\'t match. Sub charge has an existing reference on it.');
         }
     }
     if ($status == 'paid') {
         $this->subscriptionChargeRepository->markChargeAsPaid($subCharge->id);
     } else {
         if ($status == 'pending') {
             $this->subscriptionChargeRepository->markChargeAsProcessing($subCharge->id);
         }
     }
     //The amount isn't stored on the sub charge record until its paid or processing
     if ($payment->amount != $subCharge->amount) {
         $this->subscriptionChargeRepository->updateAmount($subCharge->id, $payment->amount);
     }
 }
 /**
  * The member has left, disable their account and cancel any out stand sub charge records
  * The payment day is also cleared so when they start again the payment is charge happens at restart time
  *
  * @param $userId
  */
 public function memberLeft($userId)
 {
     $user = $this->getById($userId);
     $user->active = false;
     $user->status = 'left';
     $user->payment_day = '';
     $user->save();
     $this->subscriptionChargeRepository->cancelOutstandingCharges($userId);
 }
 /**
  * Bill members based on the sub charges that are due
  */
 public function billMembers()
 {
     $subCharges = $this->subscriptionChargeRepository->getDue();
     foreach ($subCharges as $charge) {
         if ($charge->user->payment_method == 'gocardless-variable') {
             //Look the the previous attempts - there may be multiple failures
             $existingPayments = $this->paymentRepository->getPaymentsByReference($charge->id);
             if ($existingPayments->count() > 0) {
                 //We will let the user retry the payment if it fails
                 continue;
             }
             $bill = $this->goCardless->newBill($charge->user->subscription_id, $charge->user->monthly_subscription, $this->goCardless->getNameFromReason('subscription'));
             if ($bill) {
                 $this->paymentRepository->recordSubscriptionPayment($charge->user->id, 'gocardless-variable', $bill->id, $bill->amount, $bill->status, $bill->gocardless_fees, $charge->id);
             }
         }
     }
 }
 /**
  * Bill members based on the sub charges that are due
  */
 public function billMembers()
 {
     $subCharges = $this->subscriptionChargeRepository->getDue();
     //Check each of the due charges, if they have previous attempted payments ignore them
     // we don't want to retry failed payments as for DD's this will generate bank charges
     $subCharges->reject(function ($charge) {
         return $this->paymentRepository->getPaymentsByReference($charge->id)->count() > 0;
     });
     //Filter the list into two gocardless and balance subscriptions
     $goCardlessUsers = $subCharges->filter(function ($charge) {
         return $charge->user->payment_method == 'gocardless-variable';
     });
     $balanceUsers = $subCharges->filter(function ($charge) {
         return $charge->user->payment_method == 'balance';
     });
     //Charge the balance users
     foreach ($balanceUsers as $charge) {
         if ($charge->user->monthly_subscription * 100 > $charge->user->cash_balance) {
             //user doesn't have enough money
             //If they have a secondary payment method of gocardless try that
             if ($charge->user->secondary_payment_method == 'gocardless-variable') {
                 //Add the charge to the gocardless list for processing
                 $goCardlessUsers->push($charge);
                 event(new SubscriptionPayment\InsufficientFundsTryingDirectDebit($charge->user->id, $charge->id));
             } else {
                 event(new SubscriptionPayment\FailedInsufficientFunds($charge->user->id, $charge->id));
             }
             continue;
         }
         $this->paymentRepository->recordSubscriptionPayment($charge->user->id, 'balance', '', $charge->user->monthly_subscription, 'paid', 0, $charge->id);
         event(new MemberBalanceChanged($charge->user->id));
     }
     //Charge the gocardless users
     foreach ($goCardlessUsers as $charge) {
         $bill = $this->goCardless->newBill($charge->user->subscription_id, $charge->user->monthly_subscription, $this->goCardless->getNameFromReason('subscription'));
         if ($bill) {
             $this->paymentRepository->recordSubscriptionPayment($charge->user->id, 'gocardless-variable', $bill->id, $bill->amount, $bill->status, $bill->gocardless_fees, $charge->id);
         }
     }
 }
 /**
  * Display the specified resource.
  *
  * @param  int  $id
  * @return Response
  */
 public function show($id)
 {
     $user = User::findWithPermission($id);
     $inductions = $this->equipmentRepository->getRequiresInduction();
     $userInductions = $user->inductions()->get();
     foreach ($inductions as $i => $induction) {
         $inductions[$i]->userInduction = false;
         foreach ($userInductions as $userInduction) {
             if ($userInduction->key == $induction->induction_category) {
                 $inductions[$i]->userInduction = $userInduction;
             }
         }
     }
     //get pending address if any
     $newAddress = $this->addressRepository->getNewUserAddress($id);
     //Get the member subscription payments
     $subscriptionCharges = $this->subscriptionChargeRepository->getMemberChargesPaginated($id);
     return \View::make('account.show')->with('user', $user)->with('inductions', $inductions)->with('newAddress', $newAddress)->with('subscriptionCharges', $subscriptionCharges);
 }
 public function listCharges()
 {
     $charges = $this->subscriptionChargeRepository->getChargesPaginated();
     return \View::make('payments.sub-charges')->with('charges', $charges);
 }
 /**
  * Store a newly created resource in storage.
  *
  * @return Response
  */
 public function store()
 {
     $spreadsheetPath = \Input::file('statement')->getRealPath();
     $testProcess = \Request::get('test');
     if ($testProcess) {
         $testProcess = true;
         echo "Test Mode - no payment records are being created<br /><br />";
     } else {
         $testProcess = false;
         echo "Live Mode - Payments have been created<br /><br />";
     }
     $reader = new SpreadsheetReader($spreadsheetPath);
     $reader->ChangeSheet(0);
     $stringMatchUsers = User::active()->where('import_match_string', '!=', '')->get();
     $users = User::active()->get();
     echo '<br />' . PHP_EOL;
     echo '<table width="100%">';
     foreach ($reader as $i => $row) {
         echo "<tr>";
         $subPayment = false;
         $balancePayment = false;
         $paymentReference = null;
         //print_r($row);
         //If the payment isn't a credit then we don't care about it
         //if (($row[1] != 'CR') && ($row[1]) != 'BP')
         if ($row[1] != 'CR') {
             continue;
         }
         if (strpos(strtoupper($row[2]), 'GC C1 BUILDBRIGHTO') !== false) {
             continue;
         }
         if (strpos(strtoupper($row[2]), 'STRIPE TRANSFER') !== false) {
             continue;
         }
         if (strpos(strtoupper($row[2]), 'EVENTBRITE') !== false) {
             continue;
         }
         $date = new \Carbon\Carbon($row[0]);
         echo "<td>" . $date->format('d/m/y') . '</td>';
         //echo "<td>".$row[1].'</td>';
         if (strpos(strtoupper($row[2]), 'SUB') !== false) {
             $subPayment = true;
         } elseif (strpos($row[2], 'MEMBERSHIP') !== false) {
             $subPayment = true;
         } elseif (strpos($row[2], '-BALANCE-') !== false) {
             $balancePayment = true;
             $descriptionParts = explode('-BALANCE-', $row[2]);
             if (is_array($descriptionParts) && count($descriptionParts) > 1) {
                 $paymentReference = strtolower($descriptionParts[1]);
             }
         }
         if ($subPayment) {
             echo '<td>SUB</td>';
             $reasonString = 'subscription';
         } elseif ($balancePayment) {
             echo '<td>Balance</td>';
             $reasonString = 'balance';
         } else {
             echo '<td></td>';
             $reasonString = 'unknown';
         }
         $matchedUser = false;
         $paymentDescription = strtolower($row[2]);
         //Try matching against specific match strings first
         foreach ($stringMatchUsers as $user) {
             if (strpos($paymentDescription, strtolower($user->import_match_string)) !== false) {
                 $matchedUser = $user;
                 break;
             }
         }
         //If there was no match do a general surname match
         if (!$matchedUser) {
             foreach ($users as $user) {
                 if (strpos($paymentDescription, strtolower($user->family_name)) !== false) {
                     $matchedUser = $user;
                     break;
                 }
             }
         }
         if ($matchedUser) {
             echo '<td>' . $matchedUser->name . '</td>';
             if ($subPayment) {
                 $subCharge = $this->subscriptionChargeRepository->findCharge($matchedUser->id, $date);
                 if ($subCharge) {
                     echo '<td>Subscription Payment</td>';
                 } else {
                     echo '<td style="background-color: #ff8c14;">Unknown: Recording as balance top up</td>';
                     $subPayment = false;
                     $reasonString = 'balance';
                 }
             }
         } else {
             echo '<td style="background-color: #F00;">Unknown</td><td></td>';
         }
         echo '<td>' . $row[2] . '</td>';
         //echo '<td>'.$row[3].'</td>';
         echo '<td>' . $row[4] . '</td>';
         echo "</tr>";
         if (!$testProcess && $matchedUser) {
             if ($subPayment) {
                 if (isset($subCharge) && $subCharge) {
                     $paymentReference = $subCharge->id;
                     $this->subscriptionChargeRepository->markChargeAsPaid($subCharge->id, $date, $row[4]);
                 }
             }
             Payment::create(['created_at' => $date, 'reason' => $reasonString, 'source' => 'standing-order', 'user_id' => $matchedUser->id, 'amount' => $row[4], 'fee' => 0, 'amount_minus_fee' => $row[4], 'status' => 'paid', 'reference' => $paymentReference]);
             if ($subPayment) {
                 if ($matchedUser->payment_method == 'standing-order') {
                     $matchedUser->monthly_subscription = $row[4];
                 }
                 $matchedUser->save();
             }
         }
     }
     echo "</table>";
     exit;
 }