1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-05 18:52:44 +01:00

Refactor for payments via client portal

This commit is contained in:
David Bomba 2020-10-13 21:32:15 +11:00
parent f58ba0b502
commit 96750d5fdb
9 changed files with 84 additions and 38 deletions

View File

@ -71,18 +71,25 @@ class PaymentController extends Controller
{
$gateway = CompanyGateway::findOrFail(request()->input('company_gateway_id'));
/*find invoices*/
/**
* find invoices
*
* ['invoice_id' => xxx, 'amount' => 22.00]
*
*/
$payable_invoices = request()->payable_invoices;
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($payable_invoices, 'invoice_id')))->get();
$payable_invoices = collect(request()->payable_invoices);
$invoices = Invoice::whereIn('id', $this->transformKeys($payable_invoices->pluck('invoice_id')->toArray()))->get();
/* pop non payable invoice from the $payable_invoices array */
$payable_invoices = $payable_invoices->filter(function ($payable_invoice) use ($invoices){
return $invoices->where('hashed_id', $payable_invoice['invoice_id'])->first()->isPayable();
/*filter only payable invoices*/
$invoices = $invoices->filter(function ($invoice) {
return $invoice->isPayable();
});
/*return early if no invoices*/
if ($invoices->count() == 0) {
if ($payable_invoices->count() == 0) {
return redirect()
->route('client.invoices.index')
->with(['warning' => 'No payable invoices selected.']);
@ -91,10 +98,10 @@ class PaymentController extends Controller
$settings = auth()->user()->client->getMergedSettings();
/*iterate through invoices and add gateway fees and other payment metadata*/
foreach ($payable_invoices as $key => $payable_invoice) {
$payable_invoices = $payable_invoices->map(function($payable_invoice) use($invoices, $settings){
$payable_invoices[$key]['amount'] = Number::parseFloat($payable_invoice['amount']);
$payable_invoice['amount'] = $payable_invoices[$key]['amount'];
$payable_invoice['amount'] = Number::parseFloat($payable_invoice['amount']);
$invoice = $invoices->first(function ($inv) use ($payable_invoice) {
return $payable_invoice['invoice_id'] == $inv->hashed_id;
@ -135,8 +142,8 @@ class PaymentController extends Controller
}
} // Make sure 'amount' from form is not higher than 'amount' from invoice.
$payable_invoices[$key]['due_date'] = $this->formatDate($invoice->due_date, $invoice->client->date_format());
$payable_invoices[$key]['invoice_number'] = $invoice->number;
$payable_invoice['due_date'] = $this->formatDate($invoice->due_date, $invoice->client->date_format());
$payable_invoice['invoice_number'] = $invoice->number;
if (isset($invoice->po_number)) {
$additional_info = $invoice->po_number;
@ -146,8 +153,13 @@ class PaymentController extends Controller
$additional_info = $invoice->date;
}
$payable_invoices[$key]['additional_info'] = $additional_info;
}
$payable_invoice['additional_info'] = $additional_info;
return $payable_invoice;
});
if ((bool) request()->signature) {
$invoices->each(function ($invoice) {
@ -157,7 +169,7 @@ class PaymentController extends Controller
$payment_method_id = request()->input('payment_method_id');
$invoice_totals = array_sum(array_column($payable_invoices, 'amount'));
$invoice_totals = $payable_invoices->sum('amount');
$first_invoice = $invoices->first();
@ -209,24 +221,14 @@ class PaymentController extends Controller
/*Payment Gateway*/
$gateway = CompanyGateway::find($request->input('company_gateway_id'))->firstOrFail();
//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
//
// Success workflow
//
// - Rehydrate the hash and iterate through the invoices and update the balances
// - Update the type_id of the gateway fee to type_id 4
// - Link invoices to payment
//
// Failure workflow
//
// - Rehydrate hash, iterate through invoices and remove type_id 3's
// - Recalcuate invoice totals
return $gateway
->driver(auth()->user()->client)
->setPaymentMethod($request->input('payment_method_id'))
->processPaymentResponse($request);
}
public function credit_response(Request $request)
{
$payment_hash = PaymentHash::find($request->input('payment_hash'));
}
}

View File

@ -517,7 +517,7 @@ class Client extends BaseModel implements HasLocalePreference
$fee_label = $gateway->calcGatewayFeeLabel($amount, $this);
$payment_urls[] = [
'label' => ctrans('texts.'.$gateway->getTypeAlias($gateway_type_id)).$fee_label,
'label' => $gateway->getTypeAlias($gateway_type_id) . $fee_label,
'company_gateway_id' => $gateway_id,
'gateway_type_id' => $gateway_type_id,
];

View File

@ -79,7 +79,7 @@ class CompanyGateway extends BaseModel
public function getTypeAlias($gateway_type_id)
{
return GatewayType::find($gateway_type_id)->alias;
return GatewayType::getAlias($gateway_type_id);
}
/* This is the public entry point into the payment superclass */

View File

@ -37,4 +37,41 @@ class GatewayType extends StaticModel
{
return $this->hasMany(PaymentType::class);
}
public static function getAlias($type)
{
switch ($type) {
case self::CREDIT_CARD:
return ctrans('texts.credit_card');
break;
case self::BANK_TRANSFER:
return ctrans('texts.bank_transfer');
break;
case self::PAYPAL:
return ctrans('texts.paypal');
break;
case self::CRYPTO:
return ctrans('texts.crypto');
break;
case self::CUSTOM:
return ctrans('texts.custom');
break;
case self::ALIPAY:
return ctrans('texts.alipay');
break;
case self::SOFORT:
return ctrans('texts.sofort');
break;
case self::APPLE_PAY:
return ctrans('texts.apple_pay');
break;
case self::SEPA:
return ctrans('texts.sepa');
break;
default:
return 'Undefined.';
break;
}
}
}

View File

@ -104,10 +104,8 @@ class AutoBillInvoice extends AbstractService
*/
private function finalizePaymentUsingCredits()
{
info("finalizing");
info(print_r($this->used_credit,1));
$amount = array_sum(array_column($this->used_credit, 'amount'));
info("amount {$amount}");
$payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
$payment->amount = $amount;

View File

@ -77,7 +77,8 @@ class ExpenseTransformer extends EntityTransformer
'public_notes' => (string) $expense->public_notes ?: '',
'transaction_reference' => (string) $expense->transaction_reference ?: '',
'transaction_id' => (string) $expense->transaction_id ?: '',
'date' => $expense->date ?: '',
//'date' => $expense->date ?: '',
'expense_date' => $expense->date ?: '',
'payment_date' => $expense->payment_date ?: '',
'custom_value1' => $expense->custom_value1 ?: '',
'custom_value2' => $expense->custom_value2 ?: '',

View File

@ -16,6 +16,10 @@
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
</form>
<form action="{{route('client.payments.credit_response')}}" method="post" id="credit-payment">
@csrf
<input type="hidden" name="payment_hash" value="{{$payment_hash}}">
</form>
<div class="container mx-auto">
<div class="grid grid-cols-6 gap-4">
<div class="col-span-6 md:col-start-2 md:col-span-4">
@ -64,7 +68,9 @@
</div>
@if((int)$total['amount_with_fee'] == 0)
<!-- finalize with credits only -->
<button class="button button-primary bg-primary inline-flex items-center">Pay with credit</button>
<div class="bg-white px-4 py-5 flex justify-end">
<button form="credit-payment" class="button button-primary bg-primary inline-flex items-center">Pay with credit</button>
</div>
@elseif($token)
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">

View File

@ -35,6 +35,8 @@ Route::group(['middleware' => ['auth:contact', 'locale'], 'prefix' => 'client',
Route::get('recurring_invoices/{recurring_invoice}/request_cancellation', 'ClientPortal\RecurringInvoiceController@requestCancellation')->name('recurring_invoices.request_cancellation');
Route::post('payments/process', 'ClientPortal\PaymentController@process')->name('payments.process');
Route::post('payments/credit_response', 'ClientPortal\PaymentController@credit_response')->name('payments.credit_response');
Route::get('payments', 'ClientPortal\PaymentController@index')->name('payments.index')->middleware('portal_enabled');
Route::get('payments/{payment}', 'ClientPortal\PaymentController@show')->name('payments.show');
Route::post('payments/process/response', 'ClientPortal\PaymentController@response')->name('payments.response');

View File

@ -154,7 +154,7 @@ trait MockAccountData
$cu->is_admin = true;
$cu->save();
$this->token = \Illuminate\Support\Str::random(64);
$this->token = 'TOKEN';
$company_token = new CompanyToken;
$company_token->user_id = $this->user->id;