mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-05 18:52:44 +01:00
Working on credit payments
This commit is contained in:
parent
96750d5fdb
commit
080c82770e
@ -12,6 +12,7 @@
|
||||
|
||||
namespace App\Http\Controllers\ClientPortal;
|
||||
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||
use App\Jobs\Invoice\InjectSignature;
|
||||
@ -100,7 +101,6 @@ class PaymentController extends Controller
|
||||
/*iterate through invoices and add gateway fees and other payment metadata*/
|
||||
$payable_invoices = $payable_invoices->map(function($payable_invoice) use($invoices, $settings){
|
||||
|
||||
|
||||
$payable_invoice['amount'] = Number::parseFloat($payable_invoice['amount']);
|
||||
|
||||
$invoice = $invoices->first(function ($inv) use ($payable_invoice) {
|
||||
@ -159,8 +159,6 @@ class PaymentController extends Controller
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
if ((bool) request()->signature) {
|
||||
$invoices->each(function ($invoice) {
|
||||
InjectSignature::dispatch($invoice, request()->signature);
|
||||
@ -189,7 +187,7 @@ class PaymentController extends Controller
|
||||
|
||||
$payment_hash = new PaymentHash;
|
||||
$payment_hash->hash = Str::random(128);
|
||||
$payment_hash->data = $payable_invoices;
|
||||
$payment_hash->data = $payable_invoices->toArray();
|
||||
$payment_hash->fee_total = $fee_totals;
|
||||
$payment_hash->fee_invoice_id = $first_invoice->id;
|
||||
$payment_hash->save();
|
||||
@ -230,5 +228,46 @@ class PaymentController extends Controller
|
||||
public function credit_response(Request $request)
|
||||
{
|
||||
$payment_hash = PaymentHash::find($request->input('payment_hash'));
|
||||
|
||||
if($payment_hash->payment->exists())
|
||||
$payment = $payment_hash->payment;
|
||||
else {
|
||||
$payment = PaymentFactory::create($payment_hash->fee_invoice->company_id, $payment_hash->fee_invoice->user_id)->save();
|
||||
$payment_hash->payment_id = $payment->id;
|
||||
$payment_hash->save();
|
||||
}
|
||||
|
||||
collect($payment_hash->invoices())->each(function ($payable_invoice) use ($payment, $payment_hash){
|
||||
|
||||
$invoice = Invoice::find($this->decodePrimaryKey($payable_invoice['invoice_id']));
|
||||
$amount = $payable_invoice['amount'];
|
||||
|
||||
$credits = $payment_hash->fee_invoice
|
||||
->client
|
||||
->service()
|
||||
->getCredits();
|
||||
|
||||
foreach($credits as $credit)
|
||||
{
|
||||
//starting invoice balance
|
||||
$invoice_balance = $invoice->balance;
|
||||
|
||||
//credit payment applied
|
||||
$invoice = $credit->service()->applyPayment($invoice, $amount, $payment);
|
||||
|
||||
//amount paid from invoice calculated
|
||||
$remaining_balance = ($invoice_balance - $invoice->balance);
|
||||
|
||||
//reduce the amount to be paid on the invoice from the NEXT credit
|
||||
$amount -= $remaining_balance;
|
||||
|
||||
//break if the invoice is no longer PAYABLE OR there is no more amount to be applied
|
||||
if(!$invoice->isPayable() || (int)$amount == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,4 +25,14 @@ class PaymentHash extends Model
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function payment()
|
||||
{
|
||||
return $this->belongsTo(Payment::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function fee_invoice()
|
||||
{
|
||||
return $this->belongsTo(Invoice::class, 'fee_invoice_id', 'id');
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,17 @@ class ClientService
|
||||
return Number::roundValue($credits->sum('balance'), $this->client->currency()->precision);
|
||||
}
|
||||
|
||||
public function getCredits() :float
|
||||
{
|
||||
|
||||
return $this->client->credits
|
||||
->where('is_deleted', false)
|
||||
->where('balance', '>', 0)
|
||||
->sortBy('created_at');
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function save() :Client
|
||||
{
|
||||
$this->client->save();
|
||||
|
97
app/Services/Credit/ApplyPayment.php
Normal file
97
app/Services/Credit/ApplyPayment.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Services\Credit;
|
||||
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
|
||||
class ApplyPayment
|
||||
{
|
||||
|
||||
private $credit;
|
||||
|
||||
private $invoice;
|
||||
|
||||
private $amount;
|
||||
|
||||
private $amount_applied;
|
||||
|
||||
private $payment;
|
||||
|
||||
public function __construct(Credit $credit, Invoice $invoice, float $amount, Payment $payment)
|
||||
{
|
||||
$this->credit = $credit;
|
||||
$this->invoice = $invoice;
|
||||
$this->amount = $amount;
|
||||
$this->amount_applied = 0;
|
||||
$this->payment = $payment->fresh();
|
||||
}
|
||||
|
||||
public function run() :Invoice
|
||||
{
|
||||
|
||||
//$available_credit_balance = $this->credit->balance;
|
||||
$applicable_amount = min($this->amount, $this->credit->balance);
|
||||
//check invoice partial for amount to be cleared first
|
||||
|
||||
if($this->invoice->partial > 0){
|
||||
|
||||
$partial_payment = min($this->invoice->partial, $applicable_amount);
|
||||
|
||||
$this->invoice->partial -= $partial_payment;
|
||||
$this->invoice->balance -= $partial_payment;
|
||||
$this->amount -= $partial_payment;
|
||||
// $this->credit->balance -= $partial_payment;
|
||||
$applicable_amount -= $partial_payment;
|
||||
$this->amount_applied += $partial_payment;
|
||||
|
||||
}
|
||||
|
||||
if($this->amount > 0 && $applicable_amount > 0 && $this->invoice->balance > 0){
|
||||
|
||||
$balance_payment = min($this->invoice->balance, $this->amount);
|
||||
|
||||
$this->invoice->balance -= $balance_payment;
|
||||
$this->amount -= $balance_payment;
|
||||
// $this->credit->balance -= $balance_payment;
|
||||
$this->amount_applied += $balance_payment;
|
||||
|
||||
}
|
||||
|
||||
return $this->invoice;
|
||||
|
||||
}
|
||||
|
||||
private function applyPaymentToCredit()
|
||||
{
|
||||
|
||||
$credit_item = new InvoiceItem;
|
||||
$credit_item->type_id = '1';
|
||||
$credit_item->product_key = ctrans('texts.credit');
|
||||
$credit_item->notes = ctrans('texts.credit_payment', ['invoice_number' => $this->invoice->number]);
|
||||
$credit_item->quantity = 1;
|
||||
$credit_item->cost = $this->amount_applied * -1;
|
||||
|
||||
$credit_items = $credit->line_items;
|
||||
$credit_items[] = $credit_item;
|
||||
|
||||
$this->credit->line_items = $credit_items;
|
||||
|
||||
$this->credit = $this->credit->calc()->getCredit();
|
||||
$this->credit->save();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
namespace App\Services\Credit;
|
||||
|
||||
use App\Models\Credit;
|
||||
use App\Services\Credit\ApplyPayment;
|
||||
use App\Services\Credit\CreateInvitations;
|
||||
use App\Services\Credit\MarkSent;
|
||||
|
||||
@ -61,6 +62,13 @@ class CreditService
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function applyPayment($invoice, $amount, $payment)
|
||||
{
|
||||
$this->credit = (new ApplyPayment($this->client, $invoice, $amount, $payment))->run();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the credit.
|
||||
* @return Credit object
|
||||
|
Loading…
Reference in New Issue
Block a user