mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-01 06:34:35 -04:00
Refactor for determining gateway fees
This commit is contained in:
parent
c8a9997a98
commit
c8770f09ca
@ -467,7 +467,8 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
|
|
||||||
$company_gateways = $this->getSetting('company_gateway_ids');
|
$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));
|
$transformed_ids = $this->transformKeys(explode(',', $company_gateways));
|
||||||
$gateways = $this->company
|
$gateways = $this->company
|
||||||
@ -480,32 +481,46 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
$gateways = $this->company->company_gateways->where('is_deleted', false);
|
$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) {
|
// $valid_gateways = $gateways->filter(function ($method) use ($amount) {
|
||||||
return false;
|
// 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 = [];
|
$payment_methods = [];
|
||||||
|
|
||||||
foreach ($valid_gateways as $gateway) {
|
foreach ($gateways as $gateway) {
|
||||||
foreach ($gateway->driver($this)->gatewayTypes() as $type) {
|
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;
|
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()
|
public function preferredLocale()
|
||||||
{
|
{
|
||||||
$languages = Cache::get('languages');
|
$languages = Cache::get('languages');
|
||||||
|
@ -228,7 +228,7 @@ class CompanyGateway extends BaseModel
|
|||||||
|
|
||||||
public function getFeesAndLimits()
|
public function getFeesAndLimits()
|
||||||
{
|
{
|
||||||
if (is_null($this->fees_and_limits)) {
|
if (is_null($this->fees_and_limits) || empty($this->fees_and_limits)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,6 +269,9 @@ class CompanyGateway extends BaseModel
|
|||||||
public function calcGatewayFee($amount, $include_taxes = false)
|
public function calcGatewayFee($amount, $include_taxes = false)
|
||||||
{
|
{
|
||||||
$fees_and_limits = $this->getFeesAndLimits();
|
$fees_and_limits = $this->getFeesAndLimits();
|
||||||
|
//dd($fees_and_limits);
|
||||||
|
//
|
||||||
|
// info(var_dump($$fees_and_limits));
|
||||||
|
|
||||||
if (! $fees_and_limits) {
|
if (! $fees_and_limits) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -72,8 +72,8 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
* Authorize a payment method.
|
* Authorize a payment method.
|
||||||
*
|
*
|
||||||
* Returns a reusable token for storage for future payments
|
* Returns a reusable token for storage for future payments
|
||||||
* @param const $payment_method the GatewayType::constant
|
* @param const $payment_method The GatewayType::constant
|
||||||
* @return view Return a view for collecting payment method information
|
* @return view Return a view for collecting payment method information
|
||||||
*/
|
*/
|
||||||
public function authorize($payment_method)
|
public function authorize($payment_method)
|
||||||
{
|
{
|
||||||
@ -82,8 +82,8 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
/**
|
/**
|
||||||
* Executes purchase attempt for a given amount.
|
* Executes purchase attempt for a given amount.
|
||||||
*
|
*
|
||||||
* @param float $amount The amount to be collected
|
* @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 bool $return_client_response Whether the method needs to return a response (otherwise we assume an unattended payment)
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function purchase($amount, $return_client_response = false)
|
public function purchase($amount, $return_client_response = false)
|
||||||
@ -95,7 +95,7 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
*
|
*
|
||||||
* @param Payment $payment The Payment Object
|
* @param Payment $payment The Payment Object
|
||||||
* @param float $amount The amount to be refunded
|
* @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
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function refund(Payment $payment, $amount, $return_client_response = false)
|
public function refund(Payment $payment, $amount, $return_client_response = false)
|
||||||
|
@ -47,11 +47,11 @@ class Alipay
|
|||||||
{
|
{
|
||||||
return route('client.payments.response', [
|
return route('client.payments.response', [
|
||||||
'company_gateway_id' => $this->stripe->company_gateway->id,
|
'company_gateway_id' => $this->stripe->company_gateway->id,
|
||||||
'gateway_type_id' => GatewayType::SOFORT,
|
'gateway_type_id' => GatewayType::ALIPAY,
|
||||||
'hashed_ids' => implode(',', $data['hashed_ids']),
|
'hashed_ids' => implode(',', $data['hashed_ids']),
|
||||||
'amount' => $data['amount'],
|
'amount' => $data['amount'],
|
||||||
'fee' => $data['fee'],
|
'fee' => $data['fee'],
|
||||||
'payment_method_id' => GatewayType::SOFORT,
|
'payment_method_id' => GatewayType::ALIPAY,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ use App\DataMapper\InvoiceItem;
|
|||||||
use App\Events\Payment\PaymentWasCreated;
|
use App\Events\Payment\PaymentWasCreated;
|
||||||
use App\Factory\PaymentFactory;
|
use App\Factory\PaymentFactory;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
|
use App\Models\Credit;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Models\PaymentHash;
|
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
|
//if the credits cover the payments, we stop here, build the payment with credits and exit early
|
||||||
$this->applyCreditPayment();
|
$this->applyCreditPayment();
|
||||||
|
|
||||||
|
info("partial = {$this->invoice->partial}");
|
||||||
|
info("balance = {$this->invoice->balance}");
|
||||||
|
|
||||||
/* Determine $amount */
|
/* Determine $amount */
|
||||||
if ($this->invoice->partial > 0)
|
if ($this->invoice->partial > 0)
|
||||||
$amount = $this->invoice->partial;
|
$amount = $this->invoice->partial;
|
||||||
@ -64,6 +68,8 @@ class AutoBillInvoice extends AbstractService
|
|||||||
else
|
else
|
||||||
return $this->finalizePaymentUsingCredits();
|
return $this->finalizePaymentUsingCredits();
|
||||||
|
|
||||||
|
info("balance remains to be paid!!");
|
||||||
|
|
||||||
$gateway_token = $this->getGateway($amount);
|
$gateway_token = $this->getGateway($amount);
|
||||||
|
|
||||||
/* Bail out if no payment methods available */
|
/* 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 = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
||||||
$payment->amount = $amount;
|
$payment->amount = $amount;
|
||||||
|
$payment->applied = $amount;
|
||||||
$payment->client_id = $this->invoice->client_id;
|
$payment->client_id = $this->invoice->client_id;
|
||||||
$payment->currency_id = $this->invoice->client->getSetting('currency_id');
|
$payment->currency_id = $this->invoice->client->getSetting('currency_id');
|
||||||
$payment->date = now();
|
$payment->date = now();
|
||||||
@ -113,10 +120,12 @@ class AutoBillInvoice extends AbstractService
|
|||||||
|
|
||||||
$this->invoice->service()->setStatus(Invoice::STATUS_PAID)->save();
|
$this->invoice->service()->setStatus(Invoice::STATUS_PAID)->save();
|
||||||
|
|
||||||
foreach($this->used_credit as $credit)
|
foreach($this->used_credit as $credit)
|
||||||
{
|
{
|
||||||
$payment->credits()->attach($credit['credit_id'], ['amount' => $credit['amount']]);
|
$current_credit = Credit::find($credit['credit_id']);
|
||||||
}
|
$payment->credits()->attach($current_credit->id, ['amount' => $credit['amount']]);
|
||||||
|
$this->applyPaymentToCredit($current_credit, $credit['amount']);
|
||||||
|
}
|
||||||
|
|
||||||
$payment->ledger()
|
$payment->ledger()
|
||||||
->updatePaymentBalance($amount * -1)
|
->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;
|
$credit_item = new InvoiceItem;
|
||||||
@ -226,7 +235,9 @@ class AutoBillInvoice extends AbstractService
|
|||||||
$credit->line_items = $credit_items;
|
$credit->line_items = $credit_items;
|
||||||
|
|
||||||
$credit = $credit->calc()->getCredit();
|
$credit = $credit->calc()->getCredit();
|
||||||
|
$credit->save();
|
||||||
|
|
||||||
|
return $credit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,24 +34,19 @@ class AutoBillInvoiceTest extends TestCase
|
|||||||
public function testAutoBillFunctionality()
|
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->balance, 10);
|
||||||
$this->assertEquals($this->client->paid_to_date, 0);
|
$this->assertEquals($this->client->paid_to_date, 0);
|
||||||
$this->assertEquals($this->client->credit_balance, 10);
|
$this->assertEquals($this->client->credit_balance, 10);
|
||||||
|
|
||||||
$this->invoice->service()->markSent()->autoBill()->save();
|
$this->invoice->service()->markSent()->autoBill()->save();
|
||||||
|
|
||||||
// info(print_r($this->invoice->payments()->first()->toArray(),1));
|
|
||||||
$this->assertNotNull($this->invoice->payments());
|
$this->assertNotNull($this->invoice->payments());
|
||||||
$this->assertEquals(10, $this->invoice->payments()->sum('payments.amount'));
|
$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->balance, 0);
|
||||||
$this->assertEquals($this->client->paid_to_date, 10);
|
$this->assertEquals($this->client->paid_to_date, 10);
|
||||||
$this->assertEquals($this->client->credit_balance, 0);
|
$this->assertEquals($this->client->credit_balance, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,8 @@ class FeesAndLimitsTest extends TestCase
|
|||||||
$data['fee_tax_rate2'] = '';
|
$data['fee_tax_rate2'] = '';
|
||||||
$data['fee_tax_name3'] = '';
|
$data['fee_tax_name3'] = '';
|
||||||
$data['fee_tax_rate3'] = 0;
|
$data['fee_tax_rate3'] = 0;
|
||||||
|
$data['fee_cap'] = 0;
|
||||||
|
|
||||||
$fees_and_limits_array = [];
|
$fees_and_limits_array = [];
|
||||||
$fees_and_limits_array[] = $data;
|
$fees_and_limits_array[] = $data;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user