From b6bea31646e5d4524816caa07e674e916bff9184 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 10 Oct 2020 21:57:28 +1100 Subject: [PATCH 1/5] Working on gateway fee slippage --- app/Console/Commands/CreateSingleAccount.php | 2 +- app/Helpers/Invoice/InvoiceSum.php | 2 ++ app/Helpers/Invoice/InvoiceSumInclusive.php | 1 + app/Models/CompanyGateway.php | 8 ++++---- app/Services/Invoice/AddGatewayFee.php | 3 +++ app/Services/Invoice/InvoiceService.php | 4 +++- app/Services/Payment/PaymentService.php | 6 +++++- ...0_09_27_215800_update_gateway_table_visible_column.php | 1 - 8 files changed, 19 insertions(+), 8 deletions(-) diff --git a/app/Console/Commands/CreateSingleAccount.php b/app/Console/Commands/CreateSingleAccount.php index ee489b53d7b7..fba9fcb378cf 100644 --- a/app/Console/Commands/CreateSingleAccount.php +++ b/app/Console/Commands/CreateSingleAccount.php @@ -236,7 +236,7 @@ class CreateSingleAccount extends Command $client->id_number = $this->getNextClientNumber($client); $settings = $client->settings; - $settings->currency_id = (string) rand(1, 79); + $settings->currency_id = "1"; $client->settings = $settings; $country = Country::all()->random(); diff --git a/app/Helpers/Invoice/InvoiceSum.php b/app/Helpers/Invoice/InvoiceSum.php index cde944a98828..561f9480a1cc 100644 --- a/app/Helpers/Invoice/InvoiceSum.php +++ b/app/Helpers/Invoice/InvoiceSum.php @@ -287,4 +287,6 @@ class InvoiceSum { return $this->getTotalTaxes(); } + + } diff --git a/app/Helpers/Invoice/InvoiceSumInclusive.php b/app/Helpers/Invoice/InvoiceSumInclusive.php index 924fb7098e36..b84d4090935b 100644 --- a/app/Helpers/Invoice/InvoiceSumInclusive.php +++ b/app/Helpers/Invoice/InvoiceSumInclusive.php @@ -301,4 +301,5 @@ class InvoiceSumInclusive { return $this->getTotalTaxes(); } + } diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index 6ebf2371e213..d569f26b96b1 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -286,7 +286,7 @@ class CompanyGateway extends BaseModel } if ($fees_and_limits->fee_percent) { - $fee += $amount * $fees_and_limits->fee_percent / 100; + $fee += round(($amount * $fees_and_limits->fee_percent / 100),2); info("fee after adding fee percent = {$fee}"); } @@ -300,17 +300,17 @@ class CompanyGateway extends BaseModel /**/ if ($include_taxes) { if ($fees_and_limits->fee_tax_rate1) { - $fee += $pre_tax_fee * $fees_and_limits->fee_tax_rate1 / 100; + $fee += round(($pre_tax_fee * $fees_and_limits->fee_tax_rate1 / 100),2); info("fee after adding fee tax 1 = {$fee}"); } if ($fees_and_limits->fee_tax_rate2) { - $fee += $pre_tax_fee * $fees_and_limits->fee_tax_rate2 / 100; + $fee += round(($pre_tax_fee * $fees_and_limits->fee_tax_rate2 / 100),2); info("fee after adding fee tax 2 = {$fee}"); } if ($fees_and_limits->fee_tax_rate3) { - $fee += $pre_tax_fee * $fees_and_limits->fee_tax_rate3 / 100; + $fee += round(($pre_tax_fee * $fees_and_limits->fee_tax_rate3 / 100),2); info("fee after adding fee tax 3 = {$fee}"); } } diff --git a/app/Services/Invoice/AddGatewayFee.php b/app/Services/Invoice/AddGatewayFee.php index 18e3937aac1e..bc88092d3048 100644 --- a/app/Services/Invoice/AddGatewayFee.php +++ b/app/Services/Invoice/AddGatewayFee.php @@ -44,6 +44,9 @@ class AddGatewayFee extends AbstractService { $gateway_fee = round($this->company_gateway->calcGatewayFee($this->amount), $this->invoice->client->currency()->precision); + if((int)$gateway_fee == 0) + return; + $this->cleanPendingGatewayFees(); if ($gateway_fee > 0) { diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index 51a98d161675..d814e382f7e8 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -212,6 +212,8 @@ class InvoiceService public function updateStatus() { + info("invoice balance = {$this->invoice->balance}"); + if((int)$this->invoice->balance == 0) $this->setStatus(Invoice::STATUS_PAID); @@ -232,7 +234,7 @@ class InvoiceService return $item; })->toArray(); - $this->invoice = $this->invoice->calc()->getInvoice(); + //$this->invoice = $this->invoice->calc()->getInvoice(); $this->deletePdf(); diff --git a/app/Services/Payment/PaymentService.php b/app/Services/Payment/PaymentService.php index 5f253b09ff50..764b465eea41 100644 --- a/app/Services/Payment/PaymentService.php +++ b/app/Services/Payment/PaymentService.php @@ -67,12 +67,16 @@ class PaymentService } }); - $this->payment->ledger()->updatePaymentBalance($this->payment->amount); + $this->payment + ->ledger() + ->updatePaymentBalance($this->payment->amount); $client->service() ->updateBalance($this->payment->amount) ->updatePaidToDate($this->payment->amount * -1) ->save(); + + return $this; } public function refundPayment(array $data) :?Payment diff --git a/database/migrations/2020_09_27_215800_update_gateway_table_visible_column.php b/database/migrations/2020_09_27_215800_update_gateway_table_visible_column.php index c870ead51551..c5b029f921f8 100644 --- a/database/migrations/2020_09_27_215800_update_gateway_table_visible_column.php +++ b/database/migrations/2020_09_27_215800_update_gateway_table_visible_column.php @@ -31,7 +31,6 @@ class UpdateGatewayTableVisibleColumn extends Migration }); - Schema::table('expenses', function ($t){ $t->renameColumn('invoice_category_id', 'category_id'); }); From a13b97b0cb673ef9a91c33167c450f1253ea68ec Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 10 Oct 2020 23:07:52 +1100 Subject: [PATCH 2/5] Fixes for api docs --- app/Http/Controllers/Auth/LoginController.php | 13 +------------ app/Http/Controllers/OpenAPI/AccountSchema.php | 2 +- app/Http/Controllers/OpenAPI/ActivitySchema.php | 2 +- app/Http/Controllers/OpenAPI/BulkActionSchema.php | 2 +- .../Controllers/OpenAPI/ClientContactSchema.php | 2 +- app/Http/Controllers/OpenAPI/ClientGatewayToken.php | 2 +- app/Http/Controllers/OpenAPI/ClientSchema.php | 2 +- .../Controllers/OpenAPI/CompanyGatewaySchema.php | 2 +- .../Controllers/OpenAPI/CompanyLedgerSchema.php | 2 +- app/Http/Controllers/OpenAPI/CompanySchema.php | 2 +- .../Controllers/OpenAPI/CompanySettingsSchema.php | 2 +- app/Http/Controllers/OpenAPI/CompanyTokenSchema.php | 2 +- app/Http/Controllers/OpenAPI/CompanyUserSchema.php | 2 +- .../Controllers/OpenAPI/CreditPaymentableSchema.php | 2 +- app/Http/Controllers/OpenAPI/CreditSchema.php | 2 +- app/Http/Controllers/OpenAPI/DesignSchema.php | 2 +- app/Http/Controllers/OpenAPI/ErrorSchema.php | 2 +- app/Http/Controllers/OpenAPI/ExpenseSchema.php | 2 +- .../Controllers/OpenAPI/FeesAndLimitsSchema.php | 2 +- app/Http/Controllers/OpenAPI/GroupSettingSchema.php | 2 +- app/Http/Controllers/OpenAPI/Headers.php | 2 +- .../OpenAPI/InvoicePaymentableSchema.php | 2 +- app/Http/Controllers/OpenAPI/InvoiceSchema.php | 2 +- app/Http/Controllers/OpenAPI/Parameters.php | 2 +- app/Http/Controllers/OpenAPI/PaymentSchema.php | 2 +- app/Http/Controllers/OpenAPI/PaymentTermSchema.php | 2 +- app/Http/Controllers/OpenAPI/PaymentableSchema.php | 2 +- app/Http/Controllers/OpenAPI/ProductSchema.php | 2 +- app/Http/Controllers/OpenAPI/ProjectSchema.php | 9 +++++++++ app/Http/Controllers/OpenAPI/QuoteSchema.php | 2 +- app/Http/Controllers/OpenAPI/RecurringInvoice.php | 2 +- app/Http/Controllers/OpenAPI/RecurringQuote.php | 2 +- app/Http/Controllers/OpenAPI/SystemLogSchema.php | 2 +- app/Http/Controllers/OpenAPI/TaxRateSchema.php | 2 +- app/Http/Controllers/OpenAPI/TemplateSchema.php | 2 +- app/Http/Controllers/OpenAPI/UserSchema.php | 2 +- .../Controllers/OpenAPI/ValidationErrorSchema.php | 2 +- app/Http/Controllers/OpenAPI/VendorContact.php | 2 +- app/Http/Controllers/OpenAPI/VendorSchema.php | 2 +- app/Http/Controllers/OpenAPI/WebhookSchema.php | 2 +- app/Http/Controllers/OpenAPI/swagger-v3.php | 6 +++--- 41 files changed, 51 insertions(+), 53 deletions(-) create mode 100644 app/Http/Controllers/OpenAPI/ProjectSchema.php diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 8d909ef93bb2..82ff104c4e03 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -34,18 +34,7 @@ use Turbo124\Beacon\Facades\LightLogs; class LoginController extends BaseController { - /* - |-------------------------------------------------------------------------- - | Login Controller - |-------------------------------------------------------------------------- - | - | This controller handles authenticating users for the application and - | redirecting them to your home screen. The controller uses a trait - | to conveniently provide its functionality to your applications. - | - */ - - /* + /** * @OA\Tag( * name="login", * description="Authentication", diff --git a/app/Http/Controllers/OpenAPI/AccountSchema.php b/app/Http/Controllers/OpenAPI/AccountSchema.php index 79400ecb6e91..b78df617bf6a 100644 --- a/app/Http/Controllers/OpenAPI/AccountSchema.php +++ b/app/Http/Controllers/OpenAPI/AccountSchema.php @@ -1,5 +1,5 @@ Date: Sat, 10 Oct 2020 23:29:00 +1100 Subject: [PATCH 3/5] Fixes for docs --- app/Http/Controllers/OpenAPI/SystemLogSchema.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/OpenAPI/SystemLogSchema.php b/app/Http/Controllers/OpenAPI/SystemLogSchema.php index 878b05177dd9..56b002cb029d 100644 --- a/app/Http/Controllers/OpenAPI/SystemLogSchema.php +++ b/app/Http/Controllers/OpenAPI/SystemLogSchema.php @@ -7,9 +7,9 @@ * @OA\Property(property="company_id", type="string", example="AS3df3A", description="The company hashed id"), * @OA\Property(property="user_id", type="string", example="AS3df3A", description="The user_id hashed id"), * @OA\Property(property="client_id", type="string", example="AS3df3A", description="The client_id hashed id"), - * @OA\Property(property="event_id", type="int", example="1", description="The Log Type ID"), - * @OA\Property(property="category_id", type="int", example="1", description="The Category Type ID"), - * @OA\Property(property="type_id", type="int", example="1", description="The Type Type ID"), + * @OA\Property(property="event_id", type="integer", example=1, description="The Log Type ID"), + * @OA\Property(property="category_id", type="integer", example=1, description="The Category Type ID"), + * @OA\Property(property="type_id", type="integer", example=1, description="The Type Type ID"), * @OA\Property(property="log", type="object", example="{'key':'value'}", description="The json object of the error"), * @OA\Property(property="updated_at", type="string", example="2", description="______"), * @OA\Property(property="created_at", type="string", example="2", description="______"), From 8b48f26c7924efa19020816ff569a7a3e3678d52 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 11 Oct 2020 08:31:50 +1100 Subject: [PATCH 4/5] Fixes for calcuting gateway fees and for removing unpaid gateway fees appropriately --- .../ClientPortal/InvoiceController.php | 1 + .../ClientPortal/PaymentController.php | 26 +++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/ClientPortal/InvoiceController.php b/app/Http/Controllers/ClientPortal/InvoiceController.php index 72d1c1680dae..85289b87c533 100644 --- a/app/Http/Controllers/ClientPortal/InvoiceController.php +++ b/app/Http/Controllers/ClientPortal/InvoiceController.php @@ -95,6 +95,7 @@ class InvoiceController extends Controller } $invoices->map(function ($invoice) { + $invoice->service()->removeUnpaidGatewayFees()->save(); $invoice->balance = Number::formatValue($invoice->balance, $invoice->client->currency()); $invoice->partial = Number::formatValue($invoice->partial, $invoice->client->currency()); diff --git a/app/Http/Controllers/ClientPortal/PaymentController.php b/app/Http/Controllers/ClientPortal/PaymentController.php index bdbb69a6f86c..c74d6721e7e5 100644 --- a/app/Http/Controllers/ClientPortal/PaymentController.php +++ b/app/Http/Controllers/ClientPortal/PaymentController.php @@ -163,19 +163,29 @@ class PaymentController extends Controller $first_invoice = $invoices->first(); - $fee_totals = round($gateway->calcGatewayFee($invoice_totals, true), $first_invoice->client->currency()->precision); + $starting_invoice_amount = $first_invoice->amount; - if (!$first_invoice->uses_inclusive_taxes) { - $fee_tax = 0; - $fee_tax += round(($first_invoice->tax_rate1 / 100) * $fee_totals, $first_invoice->client->currency()->precision); - $fee_tax += round(($first_invoice->tax_rate2 / 100) * $fee_totals, $first_invoice->client->currency()->precision); - $fee_tax += round(($first_invoice->tax_rate3 / 100) * $fee_totals, $first_invoice->client->currency()->precision); + // $fee_totals = round($gateway->calcGatewayFee($invoice_totals, true), $first_invoice->client->currency()->precision); - $fee_totals += $fee_tax; - } + // if (!$first_invoice->uses_inclusive_taxes) { + // $fee_tax = 0; + // $fee_tax += round(($first_invoice->tax_rate1 / 100) * $fee_totals, $first_invoice->client->currency()->precision); + // $fee_tax += round(($first_invoice->tax_rate2 / 100) * $fee_totals, $first_invoice->client->currency()->precision); + // $fee_tax += round(($first_invoice->tax_rate3 / 100) * $fee_totals, $first_invoice->client->currency()->precision); + + // $fee_totals += $fee_tax; + // } $first_invoice->service()->addGatewayFee($gateway, $invoice_totals)->save(); + /** + * + * The best way to determine the exact gateway fee is to not calculate it in isolation (due to rounding) + * but to simply add it as a line item, and then subtract the starting and finishing amounts of + * the invoice. + */ + $fee_totals = $first_invoice->amount - $starting_invoice_amount; + $payment_hash = new PaymentHash; $payment_hash->hash = Str::random(128); $payment_hash->data = $payable_invoices; From bfa2e4d5d0a31f9a21eeba6a62a2b4ffb1fd59ee Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 11 Oct 2020 20:17:33 +1100 Subject: [PATCH 5/5] Refactor Gateway options --- app/Models/Gateway.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index 595078dbbcf0..978838a98182 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -104,19 +104,22 @@ class Gateway extends StaticModel { switch ($this->id) { case 1: - return ['methods' => [GatewayType::CREDIT_CARD], 'refund' => true, 'token_billing' => true ]; //Authorize.net + return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//Authorize.net break; case 15: - return ['methods' => [GatewayType::PAYPAL], 'refund' => true, 'token_billing' => false ]; //Paypal + return [GatewayType::PAYPAL => ['refund' => true, 'token_billing' => false]]; //Paypal break; case 20: - return ['methods' => [GatewayType::CREDIT_CARD, GatewayType::BANK_TRANSFER, GatewayType::ALIPAY, GatewayType::APPLE_PAY], 'refund' => true, 'token_billing' => true ]; //Stripe + return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true], + GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true], + GatewayType::ALIPAY => ['refund' => false, 'token_billing' => false], + GatewayType::APPLE_PAY => ['refund' => false, 'token_billing' => false]]; //Stripe break; case 39: - return ['methods' => [GatewayType::CREDIT_CARD], 'refund' => true, 'token_billing' => true ]; //Checkout + return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Checkout break; default: - return ['methods' => [], 'refund' => false, 'token_billing' => false]; + return []; break; } }