2020-07-07 14:33:11 +02:00
< ? php
/**
2020-09-06 11:38:10 +02:00
* Invoice Ninja ( https :// invoiceninja . com ) .
2020-07-07 14:33:11 +02:00
*
* @ 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\Invoice ;
2020-07-08 04:20:44 +02:00
use App\DataMapper\InvoiceItem ;
2020-07-07 14:33:11 +02:00
use App\Events\Payment\PaymentWasCreated ;
use App\Factory\PaymentFactory ;
use App\Models\Client ;
use App\Models\Invoice ;
use App\Models\Payment ;
2020-09-04 00:01:17 +02:00
use App\Models\PaymentHash ;
2020-07-07 14:33:11 +02:00
use App\Services\AbstractService ;
use App\Services\Client\ClientService ;
use App\Services\Payment\PaymentService ;
use App\Utils\Traits\GeneratesCounter ;
2020-09-04 00:01:17 +02:00
use Illuminate\Support\Str ;
2020-07-07 14:33:11 +02:00
class AutoBillInvoice extends AbstractService
{
private $invoice ;
2020-09-06 11:38:10 +02:00
private $client ;
2020-07-07 14:33:11 +02:00
public function __construct ( Invoice $invoice )
{
$this -> invoice = $invoice ;
2020-09-06 11:38:10 +02:00
2020-07-07 14:33:11 +02:00
$this -> client = $invoice -> client ;
}
public function run ()
{
2020-09-06 11:38:10 +02:00
if ( ! $this -> invoice -> isPayable ()) {
2020-07-08 04:20:44 +02:00
return $this -> invoice ;
2020-09-06 11:38:10 +02:00
}
2020-07-07 14:33:11 +02:00
2020-07-15 08:08:57 +02:00
$this -> invoice = $this -> invoice -> service () -> markSent () -> save ();
2020-09-06 11:38:10 +02:00
if ( $this -> invoice -> balance > 0 ) {
2020-09-17 01:26:23 +02:00
$gateway_token = $this -> getGateway ( $this -> invoice -> balance ); //todo what if it is only a partial amount?
2020-09-06 11:38:10 +02:00
} else {
2020-07-13 01:29:44 +02:00
return $this -> invoice -> service () -> markPaid () -> save ();
2020-09-06 11:38:10 +02:00
}
2020-07-13 00:28:19 +02:00
2020-09-06 11:38:10 +02:00
if ( ! $gateway_token || ! $gateway_token -> gateway -> driver ( $this -> client ) -> token_billing ) {
2020-07-13 00:28:19 +02:00
return $this -> invoice ;
2020-07-14 14:50:16 +02:00
}
2020-07-07 14:33:11 +02:00
2020-09-06 11:38:10 +02:00
if ( $this -> invoice -> partial > 0 ) {
2020-07-13 05:35:28 +02:00
$fee = $gateway_token -> gateway -> calcGatewayFee ( $this -> invoice -> partial );
2020-09-04 00:01:17 +02:00
// $amount = $this->invoice->partial + $fee;
$amount = $this -> invoice -> partial ;
2020-09-06 11:38:10 +02:00
} else {
2020-07-13 05:35:28 +02:00
$fee = $gateway_token -> gateway -> calcGatewayFee ( $this -> invoice -> balance );
2020-09-04 00:01:17 +02:00
// $amount = $this->invoice->balance + $fee;
$amount = $this -> invoice -> balance ;
2020-07-13 05:35:28 +02:00
}
2020-07-08 04:20:44 +02:00
2020-09-04 00:01:17 +02:00
$payment_hash = PaymentHash :: create ([
'hash' => Str :: random ( 128 ),
'data' => [ 'invoice_id' => $this -> invoice -> hashed_id , 'amount' => $amount ],
'fee_total' => $fee ,
'fee_invoice_id' => $this -> invoice -> id ,
]);
2020-07-08 04:20:44 +02:00
2020-09-04 00:01:17 +02:00
$payment = $gateway_token -> gateway -> driver ( $this -> client ) -> tokenBilling ( $gateway_token , $payment_hash );
2020-08-30 12:47:32 +02:00
2020-07-15 07:05:02 +02:00
return $this -> invoice ;
2020-07-07 14:33:11 +02:00
}
2020-07-15 07:05:02 +02:00
/**
* Harvests a client gateway token which passes the
2020-09-06 11:38:10 +02:00
* necessary filters for an $amount .
*
2020-07-15 07:05:02 +02:00
* @ param float $amount The amount to charge
* @ return ClientGatewayToken The client gateway token
*/
2020-07-07 14:33:11 +02:00
private function getGateway ( $amount )
{
2020-07-13 00:28:19 +02:00
$gateway_tokens = $this -> client -> gateway_tokens () -> orderBy ( 'is_default' , 'DESC' ) -> get ();
2020-09-06 11:38:10 +02:00
foreach ( $gateway_tokens as $gateway_token ) {
if ( $this -> validGatewayLimits ( $gateway_token , $amount )) {
2020-07-13 00:28:19 +02:00
return $gateway_token ;
2020-07-15 07:05:02 +02:00
}
2020-07-13 00:28:19 +02:00
}
2020-07-08 02:18:13 +02:00
}
2020-07-07 16:50:51 +02:00
2020-07-08 05:07:07 +02:00
/**
2020-09-06 11:38:10 +02:00
* Adds a gateway fee to the invoice .
*
2020-07-08 05:07:07 +02:00
* @ param float $fee The fee amount .
*/
2020-07-08 04:20:44 +02:00
private function addFeeToInvoice ( float $fee )
{
2020-07-08 05:07:07 +02:00
//todo if we increase the invoice balance here, we will also need to adjust UP the client balance and ledger?
$starting_amount = $this -> invoice -> amount ;
2020-07-08 04:20:44 +02:00
$item = new InvoiceItem ;
$item -> quantity = 1 ;
$item -> cost = $fee ;
$item -> notes = ctrans ( 'texts.online_payment_surcharge' );
$item -> type_id = 3 ;
2020-09-06 11:38:10 +02:00
$items = ( array ) $this -> invoice -> line_items ;
2020-07-08 04:20:44 +02:00
$items [] = $item ;
$this -> invoice -> line_items = $items ;
$this -> invoice -> save ();
$this -> invoice = $this -> invoice -> calc () -> getInvoice () -> save ();
2020-09-06 11:38:10 +02:00
if ( $starting_amount != $this -> invoice -> amount && $this -> invoice -> status_id != Invoice :: STATUS_DRAFT ) {
2020-07-08 05:07:07 +02:00
$this -> invoice -> client -> service () -> updateBalance ( $this -> invoice -> amount - $starting_amount ) -> save ();
$this -> invoice -> ledger () -> updateInvoiceBalance ( $this -> invoice -> amount - $starting_amount , 'Invoice balance updated after stale gateway fee removed' ) -> save ();
}
2020-07-08 08:54:16 +02:00
2020-07-08 05:07:07 +02:00
return $this ;
}
/**
2020-09-06 11:38:10 +02:00
* Removes any existing unpaid gateway fees
2020-07-08 05:07:07 +02:00
* due to previous payment failure .
2020-09-06 11:38:10 +02:00
*
2020-07-08 05:07:07 +02:00
* @ return $this
*/
2020-08-30 12:47:32 +02:00
// private function purgeStaleGatewayFees()
// {
// $starting_amount = $this->invoice->amount;
2020-07-08 05:07:07 +02:00
2020-08-30 12:47:32 +02:00
// $line_items = $this->invoice->line_items;
2020-07-08 05:07:07 +02:00
2020-08-30 12:47:32 +02:00
// $new_items = [];
2020-07-08 05:07:07 +02:00
2020-08-30 12:47:32 +02:00
// foreach($line_items as $item)
// {
2020-07-08 05:07:07 +02:00
2020-08-30 12:47:32 +02:00
// if($item->type_id != 3)
// $new_items[] = $item;
2020-09-06 11:38:10 +02:00
2020-08-30 12:47:32 +02:00
// }
2020-07-08 05:07:07 +02:00
2020-08-30 12:47:32 +02:00
// $this->invoice->line_items = $new_items;
// $this->invoice->save();
2020-07-08 05:07:07 +02:00
2020-08-30 12:47:32 +02:00
// $this->invoice = $this->invoice->calc()->getInvoice();
2020-07-08 05:07:07 +02:00
2020-08-30 12:47:32 +02:00
// if($starting_amount != $this->invoice->amount && $this->invoice->status_id != Invoice::STATUS_DRAFT){
// $this->invoice->client->service()->updateBalance($this->invoice->amount - $starting_amount)->save();
// $this->invoice->ledger()->updateInvoiceBalance($this->invoice->amount - $starting_amount, 'Invoice balance updated after stale gateway fee removed')->save();
// }
2020-07-08 05:07:07 +02:00
2020-08-30 12:47:32 +02:00
// return $this;
// }
2020-07-08 04:20:44 +02:00
2020-07-08 02:18:13 +02:00
/**
* Checks whether a given gateway token is able
* to process the payment after passing through the
2020-09-06 11:38:10 +02:00
* fees and limits check .
*
2020-07-08 02:18:13 +02:00
* @ param CompanyGateway $cg The CompanyGateway instance
* @ param float $amount The amount to be paid
* @ return bool
*/
public function validGatewayLimits ( $cg , $amount ) : bool
{
2020-09-06 11:38:10 +02:00
if ( isset ( $cg -> fees_and_limits )) {
$fees_and_limits = $cg -> fees_and_limits -> { '1' };
} else {
2020-07-15 07:05:02 +02:00
return true ;
2020-07-08 02:18:13 +02:00
}
2020-09-06 11:38:10 +02:00
if (( property_exists ( $fees_and_limits , 'min_limit' )) && $fees_and_limits -> min_limit !== null && $amount < $fees_and_limits -> min_limit ) {
info ( " amount { $amount } less than " . $fees_and_limits -> min_limit );
2020-07-08 02:18:13 +02:00
$passes = false ;
2020-09-06 11:38:10 +02:00
} elseif (( property_exists ( $fees_and_limits , 'max_limit' )) && $fees_and_limits -> max_limit !== null && $amount > $fees_and_limits -> max_limit ) {
info ( " amount { $amount } greater than " . $fees_and_limits -> max_limit );
$passes = false ;
} else {
2020-07-08 02:18:13 +02:00
$passes = true ;
2020-09-06 11:38:10 +02:00
}
2020-07-08 02:18:13 +02:00
return $passes ;
2020-07-07 14:33:11 +02:00
}
}