From c8770f09caffed8f010046551619a2b06a4769b0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 12 Oct 2020 15:10:34 +1100 Subject: [PATCH] Refactor for determining gateway fees --- app/Models/Client.php | 74 ++++++++++++++++------ app/Models/CompanyGateway.php | 5 +- app/PaymentDrivers/BaseDriver.php | 10 +-- app/PaymentDrivers/Stripe/Alipay.php | 4 +- app/Services/Invoice/AutoBillInvoice.php | 21 ++++-- tests/Unit/AutoBillInvoiceTest.php | 7 +- tests/Unit/Migration/FeesAndLimitsTest.php | 3 +- 7 files changed, 84 insertions(+), 40 deletions(-) diff --git a/app/Models/Client.php b/app/Models/Client.php index f651ca1f77..41fa0b2b88 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -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'); diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index 3091a66247..3d43a5c51c 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -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; diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index d6089437a2..678d2728ba 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -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) diff --git a/app/PaymentDrivers/Stripe/Alipay.php b/app/PaymentDrivers/Stripe/Alipay.php index c2f77cf490..06a3769206 100644 --- a/app/PaymentDrivers/Stripe/Alipay.php +++ b/app/PaymentDrivers/Stripe/Alipay.php @@ -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, ]); } diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index f94a4d98ef..8ca46609e9 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -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; } /** diff --git a/tests/Unit/AutoBillInvoiceTest.php b/tests/Unit/AutoBillInvoiceTest.php index e31ddd2f15..5b7e4c89e0 100644 --- a/tests/Unit/AutoBillInvoiceTest.php +++ b/tests/Unit/AutoBillInvoiceTest.php @@ -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); + } } diff --git a/tests/Unit/Migration/FeesAndLimitsTest.php b/tests/Unit/Migration/FeesAndLimitsTest.php index 7550bf1a64..ef737f075d 100644 --- a/tests/Unit/Migration/FeesAndLimitsTest.php +++ b/tests/Unit/Migration/FeesAndLimitsTest.php @@ -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;