Working on applying credits to payments prior to billing via gateway

This commit is contained in:
David Bomba 2020-10-07 22:03:53 +11:00
parent c41fb6e00f
commit 50b24c55d9
4 changed files with 118 additions and 19 deletions

View File

@ -156,6 +156,11 @@ class Client extends BaseModel implements HasLocalePreference
->first();
}
public function credits()
{
return $this->hasMany(Credit::class)->withTrashed();
}
public function activities()
{
return $this->hasMany(Activity::class)->orderBy('id', 'desc');

View File

@ -30,6 +30,8 @@ class AutoBillInvoice extends AbstractService
private $client;
private $payment;
public function __construct(Invoice $invoice)
{
$this->invoice = $invoice;
@ -39,32 +41,37 @@ class AutoBillInvoice extends AbstractService
public function run()
{
if (! $this->invoice->isPayable()) {
/* Is the invoice payable? */
if (! $this->invoice->isPayable())
return $this->invoice;
}
/* Mark the invoice as sent */
$this->invoice = $this->invoice->service()->markSent()->save();
if ($this->invoice->balance > 0) {
$gateway_token = $this->getGateway($this->invoice->balance); //todo what if it is only a partial amount?
} else {
/* Mark the invoice as paid if there is no balance */
if ((int)$this->invoice->balance == 0)
return $this->invoice->service()->markPaid()->save();
}
if (! $gateway_token || ! $gateway_token->gateway->driver($this->client)->token_billing) {
return $this->invoice;
}
$this->applyCreditPayment();
if ($this->invoice->partial > 0) {
$fee = $gateway_token->gateway->calcGatewayFee($this->invoice->partial);
// $amount = $this->invoice->partial + $fee;
/* Determine $amount */
if ($this->invoice->partial > 0)
$amount = $this->invoice->partial;
} else {
$fee = $gateway_token->gateway->calcGatewayFee($this->invoice->balance);
// $amount = $this->invoice->balance + $fee;
elseif($this->invoice->balance >0)
$amount = $this->invoice->balance;
}
else
return $this->invoice;
$gateway_token = $this->getGateway($amount);
/* Bail out if no payment methods available */
if (! $gateway_token || ! $gateway_token->gateway->driver($this->client)->token_billing)
return $this->invoice;
/* $gateway fee */
$fee = $gateway_token->gateway->calcGatewayFee($this->invoice->partial);
/* Build payment hash */
$payment_hash = PaymentHash::create([
'hash' => Str::random(128),
'data' => ['invoice_id' => $this->invoice->hashed_id, 'amount' => $amount],
@ -72,11 +79,95 @@ class AutoBillInvoice extends AbstractService
'fee_invoice_id' => $this->invoice->id,
]);
$payment = $gateway_token->gateway->driver($this->client)->tokenBilling($gateway_token, $payment_hash);
$payment = $gateway_token->gateway
->driver($this->client)
->tokenBilling($gateway_token, $payment_hash);
return $this->invoice;
}
/**
* Applies credits to a payment prior to push
* to the payment gateway
*
* @return $this
*/
private function applyCreditPayment()
{
$available_credits = $this->client
->credits
->where('is_deleted', false)
->where('balance', '>', 0)
->sortBy('created_at');
$available_credit_balance = $available_credits->sum('balance');
if((int)$available_credit_balance == 0)
return;
$is_partial_amount = false;
if ($this->invoice->partial > 0) {
$is_partial_amount = true;
}
$this->payment = PaymentFactory::create($this->client->company_id, $this->client->user_id);
$this->payment->save();
$available_credits->each(function($credit) use($is_partial_amount){
// if($credit->balance >= $amount){
// //current credit covers the total amount
// }
//return false to exit each loop
});
return $this;
}
private function buildPayment($credit, $is_partial_amount)
{
if($is_partial_amount) {
if($this->invoice->partial >= $credit->balance) {
$amount = $this->invoice->partial - $credit->balance;
$this->invoice->partial -= $amount;
$this->payment->credits()->attach([
$credit->id => ['amount' => $amount]
]);
$this->applyPaymentToCredit($credit, $amount);
}
}
}
private function applyPaymentToCredit($credit, $amount)
{
$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 = $amount * -1;
$credit_items = $credit->line_items;
$credit_items[] = $credit_item;
$credit->line_items = $credit_items;
$credit = $credit->calc()->getCredit();
}
/**
* Harvests a client gateway token which passes the
* necessary filters for an $amount.

View File

@ -214,7 +214,7 @@ class RandomDataSeeder extends Seeder
$invoice->ledger()->updateInvoiceBalance($invoice->balance);
if (rand(0, 1)) {
$payment = App\Models\Payment::create([
$payment = Payment::create([
'date' => now(),
'user_id' => $user->id,
'company_id' => $company->id,

View File

@ -3281,4 +3281,7 @@ return [
'paused' => 'Paused',
'saved_at' => 'Saved at :time',
'credit_payment' => 'Credit applied to Invoice :invoice_number',
];