1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 00:11:35 +02:00
invoiceninja/app/Services/PaymentService.php

229 lines
7.2 KiB
PHP
Raw Normal View History

2017-01-30 20:40:43 +01:00
<?php
namespace App\Services;
use App\Models\Account;
2016-05-26 21:22:09 +02:00
use App\Models\Activity;
2017-01-30 20:40:43 +01:00
use App\Models\Client;
2017-10-24 12:16:46 +02:00
use App\Models\Credit;
2017-01-30 20:40:43 +01:00
use App\Models\Invoice;
2016-05-23 18:52:20 +02:00
use App\Ninja\Datatables\PaymentDatatable;
2017-01-30 20:40:43 +01:00
use App\Ninja\Repositories\AccountRepository;
use App\Ninja\Repositories\PaymentRepository;
use Auth;
use Exception;
use Utils;
2015-10-28 20:22:07 +01:00
class PaymentService extends BaseService
{
/**
* PaymentService constructor.
*
* @param PaymentRepository $paymentRepo
* @param AccountRepository $accountRepo
2017-01-30 20:40:43 +01:00
* @param DatatableService $datatableService
*/
public function __construct(
PaymentRepository $paymentRepo,
AccountRepository $accountRepo,
DatatableService $datatableService
2017-01-30 17:05:31 +01:00
) {
2015-11-05 23:37:04 +01:00
$this->datatableService = $datatableService;
2015-10-28 20:22:07 +01:00
$this->paymentRepo = $paymentRepo;
$this->accountRepo = $accountRepo;
}
/**
* @return PaymentRepository
*/
2015-10-28 20:22:07 +01:00
protected function getRepo()
{
return $this->paymentRepo;
}
/**
* @param Invoice $invoice
2017-01-30 20:40:43 +01:00
*
* @return bool
*/
public function autoBillInvoice(Invoice $invoice)
{
2017-01-30 17:05:31 +01:00
if (! $invoice->canBePaid()) {
2017-01-29 12:30:57 +01:00
return false;
}
/** @var \App\Models\Client $client */
$client = $invoice->client;
/** @var \App\Models\Account $account */
2016-06-20 16:14:43 +02:00
$account = $client->account;
/** @var \App\Models\Invitation $invitation */
$invitation = $invoice->invitations->first();
2017-01-30 17:05:31 +01:00
if (! $invitation) {
return false;
}
$invoice->markSentIfUnsent();
2016-07-19 19:12:28 +02:00
if ($credits = $client->credits->sum('balance')) {
$balance = $invoice->balance;
$amount = min($credits, $balance);
$data = [
'payment_type_id' => PAYMENT_TYPE_CREDIT,
'invoice_id' => $invoice->id,
'client_id' => $client->id,
'amount' => $amount,
];
$payment = $this->paymentRepo->save($data);
if ($amount == $balance) {
return $payment;
}
}
2016-06-20 16:14:43 +02:00
$paymentDriver = $account->paymentDriver($invitation, GATEWAY_TYPE_TOKEN);
2016-07-19 19:15:03 +02:00
2017-01-30 17:05:31 +01:00
if (! $paymentDriver) {
2016-07-19 19:15:03 +02:00
return false;
}
2016-06-20 16:14:43 +02:00
$customer = $paymentDriver->customer();
2017-01-30 17:05:31 +01:00
if (! $customer) {
return false;
}
2016-06-20 16:14:43 +02:00
$paymentMethod = $customer->default_payment_method;
2017-02-02 07:53:40 +01:00
if (! $paymentMethod) {
return false;
}
2016-06-20 16:14:43 +02:00
if ($paymentMethod->requiresDelayedAutoBill()) {
2016-05-26 21:22:09 +02:00
$invoiceDate = \DateTime::createFromFormat('Y-m-d', $invoice->invoice_date);
2016-05-25 04:49:06 +02:00
$minDueDate = clone $invoiceDate;
$minDueDate->modify('+10 days');
2016-05-26 21:22:09 +02:00
if (date_create() < $minDueDate) {
2016-05-25 04:49:06 +02:00
// Can't auto bill now
return false;
}
2016-05-26 21:22:09 +02:00
if ($invoice->partial > 0) {
// The amount would be different than the amount in the email
return false;
}
$firstUpdate = Activity::where('invoice_id', '=', $invoice->id)
2016-05-25 04:49:06 +02:00
->where('activity_type_id', '=', ACTIVITY_TYPE_UPDATE_INVOICE)
->first();
if ($firstUpdate) {
$backup = json_decode($firstUpdate->json_backup);
if ($backup->balance != $invoice->balance || $backup->due_date != $invoice->due_date) {
// It's changed since we sent the email can't bill now
return false;
}
}
2016-05-26 21:22:09 +02:00
if ($invoice->payments->count()) {
2016-05-25 04:49:06 +02:00
// ACH requirements are strict; don't auto bill this
return false;
}
}
try {
return $paymentDriver->completeOnsitePurchase(false, $paymentMethod);
} catch (Exception $exception) {
2018-03-11 07:50:11 +01:00
$subject = trans('texts.auto_bill_failed', ['invoice_number' => $invoice->invoice_number]);
$message = sprintf('%s: %s', ucwords($paymentDriver->providerName()), $exception->getMessage());
2018-03-11 11:36:24 +01:00
//$message .= $exception->getTraceAsString();
2018-03-11 07:50:11 +01:00
Utils::logError($message, 'PHP', true);
2017-03-23 14:55:46 +01:00
if (! Auth::check()) {
$mailer = app('App\Ninja\Mailers\UserMailer');
2017-07-19 11:59:56 +02:00
$mailer->sendMessage($invoice->user, $subject, $message, [
'invoice' => $invoice
]);
2017-03-23 14:55:46 +01:00
}
return false;
}
}
2017-10-24 12:16:46 +02:00
public function save($input, $payment = null, $invoice = null)
{
2017-10-24 12:16:46 +02:00
// if the payment amount is more than the balance create a credit
2018-02-16 10:58:07 +01:00
if ($invoice && Utils::parseFloat($input['amount']) > $invoice->balance) {
2017-10-24 12:16:46 +02:00
$credit = Credit::createNew();
$credit->client_id = $invoice->client_id;
$credit->credit_date = date_create()->format('Y-m-d');
$credit->amount = $credit->balance = $input['amount'] - $invoice->balance;
$credit->private_notes = trans('texts.credit_created_by', ['transaction_reference' => isset($input['transaction_reference']) ? $input['transaction_reference'] : '']);
$credit->save();
$input['amount'] = $invoice->balance;
}
return $this->paymentRepo->save($input, $payment);
}
2015-11-05 23:37:04 +01:00
public function getDatatable($clientPublicId, $search)
{
$datatable = new PaymentDatatable(true, $clientPublicId);
2015-11-05 23:37:04 +01:00
$query = $this->paymentRepo->find($clientPublicId, $search);
if (! Utils::hasPermission('view_payment')) {
2016-03-16 00:08:00 +01:00
$query->where('payments.user_id', '=', Auth::user()->id);
}
2016-05-23 18:52:20 +02:00
return $this->datatableService->createDatatable($datatable, $query);
2015-11-05 23:37:04 +01:00
}
public function bulk($ids, $action, $params = [])
2016-04-23 22:40:19 +02:00
{
if ($action == 'refund') {
2017-01-30 17:05:31 +01:00
if (! $ids) {
2016-04-23 22:40:19 +02:00
return 0;
}
2015-11-05 23:37:04 +01:00
2016-04-23 22:40:19 +02:00
$payments = $this->getRepo()->findByPublicIdsWithTrashed($ids);
2016-05-06 23:05:42 +02:00
$successful = 0;
2015-11-05 23:37:04 +01:00
2016-04-23 22:40:19 +02:00
foreach ($payments as $payment) {
2016-06-20 16:14:43 +02:00
if (Auth::user()->can('edit', $payment)) {
2017-02-09 13:34:26 +01:00
$amount = ! empty($params['refund_amount']) ? floatval($params['refund_amount']) : null;
$sendEmail = ! empty($params['refund_email']) ? boolval($params['refund_email']) : false;
$paymentDriver = false;
$refunded = false;
2016-10-06 07:44:19 +02:00
if ($accountGateway = $payment->account_gateway) {
$paymentDriver = $accountGateway->paymentDriver();
}
if ($paymentDriver && $paymentDriver->canRefundPayments) {
2016-10-06 07:44:19 +02:00
if ($paymentDriver->refundPayment($payment, $amount)) {
$successful++;
$refunded = true;
2016-10-06 07:44:19 +02:00
}
2017-01-16 13:51:43 +01:00
} else {
$payment->recordRefund($amount);
$successful++;
$refunded = true;
}
if ($refunded && $sendEmail) {
$mailer = app('App\Ninja\Mailers\ContactMailer');
$mailer->sendPaymentConfirmation($payment, $amount);
2016-05-17 17:32:17 +02:00
}
2016-04-23 22:40:19 +02:00
}
}
2016-05-06 23:05:42 +02:00
return $successful;
2016-04-23 22:40:19 +02:00
} else {
return parent::bulk($ids, $action);
}
}
}