1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 08:21:34 +02:00

Refactor for determining gateway fees

This commit is contained in:
David Bomba 2020-10-12 15:10:34 +11:00
parent c8a9997a98
commit c8770f09ca
7 changed files with 84 additions and 40 deletions

View File

@ -467,7 +467,8 @@ class Client extends BaseModel implements HasLocalePreference
$company_gateways = $this->getSetting('company_gateway_ids');
if ($company_gateways || $company_gateways == '0') { //we need to check for "0" here as we disable a payment gateway for a client with the number "0"
//we need to check for "0" here as we disable a payment gateway for a client with the number "0"
if ($company_gateways || $company_gateways == '0') {
$transformed_ids = $this->transformKeys(explode(',', $company_gateways));
$gateways = $this->company
@ -480,32 +481,46 @@ class Client extends BaseModel implements HasLocalePreference
$gateways = $this->company->company_gateways->where('is_deleted', false);
}
$valid_gateways = $gateways->filter(function ($method) use ($amount) {
if (isset($method->fees_and_limits)) {
//sometimes the key value of the fees and limits object are not static,
//we have to harvest the key value as follows
$properties = array_keys(get_object_vars($method->fees_and_limits));
$fees_and_limits = $method->fees_and_limits->{$properties[0]};
} else {
return true;
}
if ((property_exists($fees_and_limits, 'min_limit')) && $fees_and_limits->min_limit !== null && $fees_and_limits->min_limit != -1 && $amount < $fees_and_limits->min_limit) {
return false;
}
if ((property_exists($fees_and_limits, 'max_limit')) && $fees_and_limits->max_limit !== null && $fees_and_limits->max_limit != -1 && $amount > $fees_and_limits->max_limit) {
return false;
}
// $valid_gateways = $gateways->filter(function ($method) use ($amount) {
// if (isset($method->fees_and_limits)) {
// //sometimes the key value of the fees and limits object are not static,
// //we have to harvest the key value as follows
// //Update!!! apparently we use the gateway_type_id
// $properties = array_keys(get_object_vars($method->fees_and_limits));
// $fees_and_limits = $method->fees_and_limits->{$properties[0]}; //need to iterate over the $properties array as there may be many fees_and_limits
// } else {
// return true;
// }
// if ((property_exists($fees_and_limits, 'min_limit')) && $fees_and_limits->min_limit !== null && $fees_and_limits->min_limit != -1 && $amount < $fees_and_limits->min_limit) {
// return false;
// }
// if ((property_exists($fees_and_limits, 'max_limit')) && $fees_and_limits->max_limit !== null && $fees_and_limits->max_limit != -1 && $amount > $fees_and_limits->max_limit) {
// return false;
// }
// return true;
// })->all();
return true;
})->all();
$payment_methods = [];
foreach ($valid_gateways as $gateway) {
foreach ($gateways as $gateway) {
foreach ($gateway->driver($this)->gatewayTypes() as $type) {
$payment_methods[] = [$gateway->id => $type];
if(property_exists($gateway, 'fees_and_limits') property_exists($gateway->fees_and_limits, $type)){
$fees_and_limits_for_payment_type = $gateway->fees_and_limits->{$type};
}
else
continue;
if($this->validGatewayForAmount($fees_and_limits_for_payment_type, $amount))
$payment_methods[] = [$gateway->id => $type];
}
}
@ -533,6 +548,25 @@ class Client extends BaseModel implements HasLocalePreference
return $payment_urls;
}
private function validateFeesAndLimits($fees_and_limits_for_payment_type, $amount) :bool
{
if (isset($fees_and_limits_for_payment_type)) {
$fees_and_limits = $fees_and_limits_for_payment_type;
} else {
return true;
}
if ((property_exists($fees_and_limits, 'min_limit')) && $fees_and_limits->min_limit !== null && $fees_and_limits->min_limit != -1 && $amount < $fees_and_limits->min_limit) {
return false;
}
if ((property_exists($fees_and_limits, 'max_limit')) && $fees_and_limits->max_limit !== null && $fees_and_limits->max_limit != -1 && $amount > $fees_and_limits->max_limit) {
return false;
}
return true;
}
public function preferredLocale()
{
$languages = Cache::get('languages');

View File

@ -228,7 +228,7 @@ class CompanyGateway extends BaseModel
public function getFeesAndLimits()
{
if (is_null($this->fees_and_limits)) {
if (is_null($this->fees_and_limits) || empty($this->fees_and_limits)) {
return false;
}
@ -269,6 +269,9 @@ class CompanyGateway extends BaseModel
public function calcGatewayFee($amount, $include_taxes = false)
{
$fees_and_limits = $this->getFeesAndLimits();
//dd($fees_and_limits);
//
// info(var_dump($$fees_and_limits));
if (! $fees_and_limits) {
return 0;

View File

@ -72,8 +72,8 @@ class BaseDriver extends AbstractPaymentDriver
* Authorize a payment method.
*
* Returns a reusable token for storage for future payments
* @param const $payment_method the GatewayType::constant
* @return view Return a view for collecting payment method information
* @param const $payment_method The GatewayType::constant
* @return view Return a view for collecting payment method information
*/
public function authorize($payment_method)
{
@ -82,8 +82,8 @@ class BaseDriver extends AbstractPaymentDriver
/**
* Executes purchase attempt for a given amount.
*
* @param float $amount The amount to be collected
* @param bool $return_client_response Whether the method needs to return a response (otherwise we assume an unattended payment)
* @param float $amount The amount to be collected
* @param bool $return_client_response Whether the method needs to return a response (otherwise we assume an unattended payment)
* @return mixed
*/
public function purchase($amount, $return_client_response = false)
@ -95,7 +95,7 @@ class BaseDriver extends AbstractPaymentDriver
*
* @param Payment $payment The Payment Object
* @param float $amount The amount to be refunded
* @param bool $return_client_response Whether the method needs to return a response (otherwise we assume an unattended payment)
* @param bool $return_client_response Whether the method needs to return a response (otherwise we assume an unattended payment)
* @return mixed
*/
public function refund(Payment $payment, $amount, $return_client_response = false)

View File

@ -47,11 +47,11 @@ class Alipay
{
return route('client.payments.response', [
'company_gateway_id' => $this->stripe->company_gateway->id,
'gateway_type_id' => GatewayType::SOFORT,
'gateway_type_id' => GatewayType::ALIPAY,
'hashed_ids' => implode(',', $data['hashed_ids']),
'amount' => $data['amount'],
'fee' => $data['fee'],
'payment_method_id' => GatewayType::SOFORT,
'payment_method_id' => GatewayType::ALIPAY,
]);
}

View File

@ -15,6 +15,7 @@ use App\DataMapper\InvoiceItem;
use App\Events\Payment\PaymentWasCreated;
use App\Factory\PaymentFactory;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\PaymentHash;
@ -56,6 +57,9 @@ class AutoBillInvoice extends AbstractService
//if the credits cover the payments, we stop here, build the payment with credits and exit early
$this->applyCreditPayment();
info("partial = {$this->invoice->partial}");
info("balance = {$this->invoice->balance}");
/* Determine $amount */
if ($this->invoice->partial > 0)
$amount = $this->invoice->partial;
@ -64,6 +68,8 @@ class AutoBillInvoice extends AbstractService
else
return $this->finalizePaymentUsingCredits();
info("balance remains to be paid!!");
$gateway_token = $this->getGateway($amount);
/* Bail out if no payment methods available */
@ -103,6 +109,7 @@ class AutoBillInvoice extends AbstractService
$payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
$payment->amount = $amount;
$payment->applied = $amount;
$payment->client_id = $this->invoice->client_id;
$payment->currency_id = $this->invoice->client->getSetting('currency_id');
$payment->date = now();
@ -113,10 +120,12 @@ class AutoBillInvoice extends AbstractService
$this->invoice->service()->setStatus(Invoice::STATUS_PAID)->save();
foreach($this->used_credit as $credit)
{
$payment->credits()->attach($credit['credit_id'], ['amount' => $credit['amount']]);
}
foreach($this->used_credit as $credit)
{
$current_credit = Credit::find($credit['credit_id']);
$payment->credits()->attach($current_credit->id, ['amount' => $credit['amount']]);
$this->applyPaymentToCredit($current_credit, $credit['amount']);
}
$payment->ledger()
->updatePaymentBalance($amount * -1)
@ -210,7 +219,7 @@ class AutoBillInvoice extends AbstractService
private function applyPaymentToCredit($credit, $amount)
private function applyPaymentToCredit($credit, $amount) :Credit
{
$credit_item = new InvoiceItem;
@ -226,7 +235,9 @@ class AutoBillInvoice extends AbstractService
$credit->line_items = $credit_items;
$credit = $credit->calc()->getCredit();
$credit->save();
return $credit;
}
/**

View File

@ -34,24 +34,19 @@ class AutoBillInvoiceTest extends TestCase
public function testAutoBillFunctionality()
{
// info("client balance = {$this->client->balance}");
// info("invoice balance = {$this->invoice->balance}");
$this->assertEquals($this->client->balance, 10);
$this->assertEquals($this->client->paid_to_date, 0);
$this->assertEquals($this->client->credit_balance, 10);
$this->invoice->service()->markSent()->autoBill()->save();
// info(print_r($this->invoice->payments()->first()->toArray(),1));
$this->assertNotNull($this->invoice->payments());
$this->assertEquals(10, $this->invoice->payments()->sum('payments.amount'));
//info(print_r($this->invoice->payments()->get(),1));
$this->assertEquals($this->client->balance, 0);
$this->assertEquals($this->client->paid_to_date, 10);
$this->assertEquals($this->client->credit_balance, 0);
}
}

View File

@ -36,7 +36,8 @@ class FeesAndLimitsTest extends TestCase
$data['fee_tax_rate2'] = '';
$data['fee_tax_name3'] = '';
$data['fee_tax_rate3'] = 0;
$data['fee_cap'] = 0;
$fees_and_limits_array = [];
$fees_and_limits_array[] = $data;