mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-04 10:04:36 -04:00
Working on gateway fees across multiple invoices
This commit is contained in:
parent
ff5d8ad871
commit
1a7d0d3cbd
@ -14,6 +14,7 @@ namespace App\Http\Controllers\ClientPortal;
|
|||||||
|
|
||||||
use App\Filters\PaymentFilters;
|
use App\Filters\PaymentFilters;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||||
use App\Jobs\Invoice\InjectSignature;
|
use App\Jobs\Invoice\InjectSignature;
|
||||||
use App\Models\CompanyGateway;
|
use App\Models\CompanyGateway;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
@ -142,17 +143,18 @@ class PaymentController extends Controller
|
|||||||
$payment_methods = auth()->user()->client->getPaymentMethods(array_sum(array_column($payable_invoices, 'amount_with_fee')));
|
$payment_methods = auth()->user()->client->getPaymentMethods(array_sum(array_column($payable_invoices, 'amount_with_fee')));
|
||||||
$payment_method_id = request()->input('payment_method_id');
|
$payment_method_id = request()->input('payment_method_id');
|
||||||
|
|
||||||
$payment_hash = new PaymentHash;
|
|
||||||
$payment_hash->hash = Str::random(128);
|
|
||||||
$payment_hash->data = $payable_invoices;
|
|
||||||
$payment_hash->save();
|
|
||||||
|
|
||||||
$invoice_totals = array_sum(array_column($payable_invoices,'amount'));
|
$invoice_totals = array_sum(array_column($payable_invoices,'amount'));
|
||||||
$fee_totals = $gateway->calcGatewayFee($invoice_totals);
|
$fee_totals = $gateway->calcGatewayFee($invoice_totals);
|
||||||
|
|
||||||
|
$payment_hash = new PaymentHash;
|
||||||
|
$payment_hash->hash = Str::random(128);
|
||||||
|
$payment_hash->data = $payable_invoices;
|
||||||
|
$payment_hash->fees = $fee_totals;
|
||||||
|
$payment_hash->save();
|
||||||
|
|
||||||
$totals = [
|
$totals = [
|
||||||
'invoice_totals' => $invoice_totals,
|
'invoice_totals' => $invoice_totals,
|
||||||
'fee_totals' => $fee_totals,
|
'fee_total' => $fee_totals,
|
||||||
'amount_with_fee' => $invoice_totals + $fee_totals,
|
'amount_with_fee' => $invoice_totals + $fee_totals,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -170,10 +172,17 @@ class PaymentController extends Controller
|
|||||||
->processPaymentView($data);
|
->processPaymentView($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function response(Request $request)
|
public function response(PaymentResponseRequest $request)
|
||||||
{
|
{
|
||||||
$gateway = CompanyGateway::find($request->input('company_gateway_id'));
|
$gateway = CompanyGateway::find($request->input('company_gateway_id'))->firstOrFail();
|
||||||
|
|
||||||
|
$payment_hash = $request->getPaymentHash();
|
||||||
|
$payment_invoices = $payment_hash->invoices();
|
||||||
|
$fee_total = $payment_hash->fee_total;
|
||||||
|
|
||||||
|
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($payable_invoices, 'invoice_id')))->get();
|
||||||
|
|
||||||
|
$invoice_count = $invoices->count();
|
||||||
//REFACTOR - Entry point for the gateway response - we don't need to do anything at this point.
|
//REFACTOR - Entry point for the gateway response - we don't need to do anything at this point.
|
||||||
//
|
//
|
||||||
// - Inside each gateway driver, we should use have a generic code path (in BaseDriver.php)for successful/failed payment
|
// - Inside each gateway driver, we should use have a generic code path (in BaseDriver.php)for successful/failed payment
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\ClientPortal\Payments;
|
||||||
|
|
||||||
|
use App\Models\PaymentHash;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class PaymentResponseRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'company_gateway_id' => 'required',
|
||||||
|
'payment_hash' => 'required',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPaymentHash()
|
||||||
|
{
|
||||||
|
$input = $this->all();
|
||||||
|
|
||||||
|
return PaymentHash::whereRaw("BINARY `hash`= ?", [$input['payment_hash']])->first();
|
||||||
|
}
|
||||||
|
}
|
@ -91,6 +91,7 @@ class EmailInvoice extends BaseMailerJob implements ShouldQueue
|
|||||||
catch (\Swift_TransportException $e) {
|
catch (\Swift_TransportException $e) {
|
||||||
|
|
||||||
event(new InvoiceWasEmailedAndFailed($this->invoice_invitation->invoice, $this->company, $e->getMessage(), Ninja::eventVars()));
|
event(new InvoiceWasEmailedAndFailed($this->invoice_invitation->invoice, $this->company, $e->getMessage(), Ninja::eventVars()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count(Mail::failures()) > 0) {
|
if (count(Mail::failures()) > 0) {
|
||||||
|
@ -393,7 +393,7 @@ class Company extends BaseModel
|
|||||||
|
|
||||||
public function system_logs()
|
public function system_logs()
|
||||||
{
|
{
|
||||||
return $this->hasMany(SystemLog::class);
|
return $this->hasMany(SystemLog::class)->orderBy('id', 'DESC')->take(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tokens_hashed()
|
public function tokens_hashed()
|
||||||
|
@ -293,6 +293,34 @@ class CompanyGateway extends BaseModel
|
|||||||
return $fee;
|
return $fee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function calcGatewayFeeObject($amount, $invoice_count)
|
||||||
|
{
|
||||||
|
$total_gateway_fee = $this->calcGatewayFee($amount);
|
||||||
|
|
||||||
|
$fee_object = new \stdClass;
|
||||||
|
|
||||||
|
$fees_and_limits = $this->getFeesAndLimits();
|
||||||
|
|
||||||
|
if(!$fees_and_limits)
|
||||||
|
return $fee_object;
|
||||||
|
|
||||||
|
$fee_component_amount = $fees_and_limits->fee_amount ?: 0;
|
||||||
|
$fee_component_percent = $fees_and_limits->fee_percent ? ($amount * $fees_and_limits->fee_percent / 100) : 0;
|
||||||
|
|
||||||
|
$combined_fee_component = $fee_component_amount + $fee_component_percent;
|
||||||
|
|
||||||
|
$fee_component_tax_name1 = $fees_and_limits->fee_tax_name1 ?: '';
|
||||||
|
$fee_component_tax_rate1 = $fees_and_limits->fee_tax_rate1 ? ($combined_fee_component * $fees_and_limits->fee_tax_rate1 / 100) : 0;
|
||||||
|
|
||||||
|
$fee_component_tax_name2 = $fees_and_limits->fee_tax_name2 ?: '';
|
||||||
|
$fee_component_tax_rate2 = $fees_and_limits->fee_tax_rate2 ? ($combined_fee_component * $fees_and_limits->fee_tax_rate2 / 100) : 0;
|
||||||
|
|
||||||
|
$fee_component_tax_name3 = $fees_and_limits->fee_tax_name3 ?: '';
|
||||||
|
$fee_component_tax_rate3 = $fees_and_limits->fee_tax_rate3 ? ($combined_fee_component * $fees_and_limits->fee_tax_rate3 / 100) : 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function resolveRouteBinding($value)
|
public function resolveRouteBinding($value)
|
||||||
{
|
{
|
||||||
return $this
|
return $this
|
||||||
|
@ -20,7 +20,6 @@ class PaymentHash extends Model
|
|||||||
'data' => 'object'
|
'data' => 'object'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
public function invoices()
|
public function invoices()
|
||||||
{
|
{
|
||||||
return $this->data->invoices;
|
return $this->data->invoices;
|
||||||
|
@ -38,6 +38,7 @@ class AddIsPublicToDocumentsTable extends Migration
|
|||||||
Schema::create('payment_hashes', function ($table) {
|
Schema::create('payment_hashes', function ($table) {
|
||||||
$table->increments('id');
|
$table->increments('id');
|
||||||
$table->string('hash', 255);
|
$table->string('hash', 255);
|
||||||
|
$table->decimal('fee_total', 16, 4);
|
||||||
$table->mediumText('data');
|
$table->mediumText('data');
|
||||||
$table->timestamps(6);
|
$table->timestamps(6);
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,11 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
|
/* fix for blurry fonts */
|
||||||
|
flt-glass-pane {
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
|
||||||
/* https://projects.lukehaas.me/css-loaders/ */
|
/* https://projects.lukehaas.me/css-loaders/ */
|
||||||
.loader,
|
.loader,
|
||||||
.loader:before,
|
.loader:before,
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
{{ ctrans('texts.gateway_fees') }}
|
{{ ctrans('texts.gateway_fees') }}
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
{{ App\Utils\Number::formatMoney($total['fee_totals'], $client) }}
|
{{ App\Utils\Number::formatMoney($total['fee_total'], $client) }}
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="text-sm leading-5 font-medium text-gray-500">
|
<dt class="text-sm leading-5 font-medium text-gray-500">
|
||||||
{{ ctrans('texts.total') }}
|
{{ ctrans('texts.total') }}
|
||||||
@ -87,7 +87,7 @@
|
|||||||
{{ ctrans('texts.gateway_fees') }}
|
{{ ctrans('texts.gateway_fees') }}
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
{{ App\Utils\Number::formatMoney($total['fee_totals'], $client) }}
|
{{ App\Utils\Number::formatMoney($total['fee_total'], $client) }}
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="text-sm leading-5 font-medium text-gray-500">
|
<dt class="text-sm leading-5 font-medium text-gray-500">
|
||||||
{{ ctrans('texts.amount') }}
|
{{ ctrans('texts.amount') }}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user