Transaction events

This commit is contained in:
David Bomba 2022-03-10 11:32:04 +11:00
parent bdcf902c6c
commit b7dced76cd
31 changed files with 674 additions and 110 deletions

View File

@ -0,0 +1,100 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* BaseTransaction.
*/
class BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::INVOICE_MARK_PAID;
public array $model = [
'client_id',
'invoice_id',
'payment_id',
'credit_id',
'client_balance',
'client_paid_to_date',
'client_credit_balance',
'invoice_balance',
'invoice_amount',
'invoice_partial',
'invoice_paid_to_date',
'invoice_status',
'payment_amount',
'payment_applied',
'payment_refunded',
'payment_status',
'paymentables',
'event_id',
'timestamp',
'payment_request',
'metadata',
'credit_balance',
'credit_amount',
'credit_status',
];
public function transform(array $data) :array
{
// $invoice = $data['invoice'];
// $payment = $data['payment'];
// $client = $data['client'];
// $credit = $data['credit'];
// $payment_request = $data['payment']['payment_request'];
// $metadata = $data['metadata'];
return array_merge(
$data['invoice'],
$data['payment'],
$data['client'],
$data['credit'],
$data['metadata'],
['event_id' => $this->event_id, 'timestamp' =>time()],
);
// return [
// 'event_id' => $this->event_id,
// 'client_id' => $client?->id,
// 'invoice_id' => $invoice?->id,
// 'payment_id' => $payment?->id,
// 'credit_id' => $credit?->creditid,
// 'client_balance' => $client?->balance,
// 'client_paid_to_date' => $client?->paid_to_date,
// 'client_credit_balance' => $client?->credit_balance,
// 'invoice_balance' => $invoice?->balance,
// 'invoice_amount' => $invoice?->amount,
// 'invoice_partial' => $invoice?->partial,
// 'invoice_paid_to_date' => $invoice?->paid_to_date,
// 'invoice_status' => $invoice?->status_id,
// 'payment_amount' => $payment?->amount,
// 'payment_applied' => $payment?->applied,
// 'payment_refunded' => $payment?->refunded,
// 'payment_status' => $payment?->status_id,
// 'paymentables' => $payment?->paymentables,
// 'payment_request' => $payment_request,
// 'metadata' => $metadata,
// 'credit_balance' => $credit?->balance,
// 'credit_amount' => $credit?->amount,
// 'credit_status' => $credit?->status_id,
// 'timestamp' => time(),
// ];
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* ClientStatusTransaction.
*/
class ClientStatusTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::CLIENT_STATUS;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* GatewayPaymentMadeTransaction.
*/
class GatewayPaymentMadeTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::GATEWAY_PAYMENT_MADE;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* InvoiceCancelledTransaction.
*/
class InvoiceCancelledTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::INVOICE_CANCELLED;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* InvoiceDeletedTransaction.
*/
class InvoiceDeletedTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::INVOICE_DELETED;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* InvoiceFeeAppliedTransaction.
*/
class InvoiceFeeAppliedTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::INVOICE_FEE_APPLIED;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* InvoicePaymentTransaction.
*/
class InvoicePaymentTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::INVOICE_PAYMENT_APPLIED;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* InvoiceUpdatedTransaction.
*/
class InvoiceUpdatedTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::INVOICE_UPDATED;
}

View File

@ -18,75 +18,11 @@ use App\Models\Payment;
use App\Models\TransactionEvent; use App\Models\TransactionEvent;
/** /**
* MarkPaidTransaction. * BaseTransaction.
*/ */
class MarkPaidTransaction implements TransactionInterface class MarkPaidTransaction extends BaseTransaction implements TransactionInterface
{ {
public $event_id = TransactionEvent::INVOICE_MARK_PAID; public $event_id = TransactionEvent::INVOICE_MARK_PAID;
public array $model = [
'client_id',
'invoice_id',
'payment_id',
'credit_id',
'client_balance',
'client_paid_to_date',
'client_credit_balance',
'invoice_balance',
'invoice_amount',
'invoice_partial',
'invoice_paid_to_date',
'invoice_status',
'payment_amount',
'payment_applied',
'payment_refunded',
'payment_status',
'paymentables',
'event_id',
'timestamp',
'payment_request',
'metadata',
'credit_balance',
'credit_amount',
'credit_status',
];
public function transform(array $data) :array
{
$invoice = $data['invoice'];
$payment = $data['payment'];
$client = $data['client'];
$credit = $data['credit'];
$payment_request = $data['payment_request'];
$metadata = $data['metadata'];
return [
'event_id' => $this->event_id,
'client_id' => $client?->id,
'invoice_id' => $invoice?->id,
'payment_id' => $payment?->id,
'credit_id' => $credit?->id,
'client_balance' => $client?->balance,
'client_paid_to_date' => $client?->paid_to_date,
'client_credit_balance' => $client?->credit_balance,
'invoice_balance' => $invoice?->balance,
'invoice_amount' => $invoice?->amount,
'invoice_partial' => $invoice?->partial,
'invoice_paid_to_date' => $invoice?->paid_to_date,
'invoice_status' => $invoice?->status_id,
'payment_amount' => $payment?->amount,
'payment_applied' => $payment?->applied,
'payment_refunded' => $payment?->refunded,
'payment_status' => $payment?->status_id,
'paymentables' => $payment?->paymentables,
'payment_request' => $payment_request,
'metadata' => $metadata,
'credit_balance' => $credit?->balance,
'credit_amount' => $credit?->amount,
'credit_status' => $credit?->status_id,
'timestamp' => time(),
];
}
} }

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* PaymentAppliedTransaction.
*/
class PaymentAppliedTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::PAYMENT_APPLIED;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* PaymentDeletedTransaction.
*/
class PaymentDeletedTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::PAYMENT_DELETED;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* PaymentFailedTransaction.
*/
class PaymentFailedTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::PAYMENT_FAILED;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* PaymentMadeTransaction.
*/
class PaymentMadeTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::PAYMENT_MADE;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Transactions;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\TransactionEvent;
/**
* PaymentRefundedTransaction.
*/
class PaymentRefundedTransaction extends BaseTransaction implements TransactionInterface
{
public $event_id = TransactionEvent::PAYMENT_REFUND;
}

View File

@ -29,11 +29,13 @@ use App\Http\Requests\Invoice\UploadInvoiceRequest;
use App\Jobs\Entity\EmailEntity; use App\Jobs\Entity\EmailEntity;
use App\Jobs\Invoice\StoreInvoice; use App\Jobs\Invoice\StoreInvoice;
use App\Jobs\Invoice\ZipInvoices; use App\Jobs\Invoice\ZipInvoices;
use App\Jobs\Ninja\TransactionLog;
use App\Jobs\Util\UnlinkFile; use App\Jobs\Util\UnlinkFile;
use App\Models\Account; use App\Models\Account;
use App\Models\Client; use App\Models\Client;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Quote; use App\Models\Quote;
use App\Models\TransactionEvent;
use App\Repositories\InvoiceRepository; use App\Repositories\InvoiceRepository;
use App\Transformers\InvoiceTransformer; use App\Transformers\InvoiceTransformer;
use App\Transformers\QuoteTransformer; use App\Transformers\QuoteTransformer;
@ -224,6 +226,16 @@ class InvoiceController extends BaseController
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
$transaction = [
'invoice' => $invoice->transaction_event(),
'payment' => [],
'client' => $invoice->client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
return $this->itemResponse($invoice); return $this->itemResponse($invoice);
} }
@ -405,6 +417,16 @@ class InvoiceController extends BaseController
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
$transaction = [
'invoice' => $invoice->transaction_event(),
'payment' => [],
'client' => $invoice->client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
return $this->itemResponse($invoice); return $this->itemResponse($invoice);
} }

View File

@ -11,7 +11,19 @@
namespace App\Jobs\Ninja; namespace App\Jobs\Ninja;
use App\DataMapper\Transactions\ClientStatusTransaction;
use App\DataMapper\Transactions\GatewayPaymentMadeTransaction;
use App\DataMapper\Transactions\InvoiceCancelledTransaction;
use App\DataMapper\Transactions\InvoiceDeletedTransaction;
use App\DataMapper\Transactions\InvoiceFeeAppliedTransaction;
use App\DataMapper\Transactions\InvoicePaymentTransaction;
use App\DataMapper\Transactions\InvoiceUpdatedTransaction;
use App\DataMapper\Transactions\MarkPaidTransaction; use App\DataMapper\Transactions\MarkPaidTransaction;
use App\DataMapper\Transactions\PaymentAppliedTransaction;
use App\DataMapper\Transactions\PaymentDeletedTransaction;
use App\DataMapper\Transactions\PaymentFailedTransaction;
use App\DataMapper\Transactions\PaymentMadeTransaction;
use App\DataMapper\Transactions\PaymentRefundedTransaction;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\TransactionEvent; use App\Models\TransactionEvent;
use App\Utils\Ninja; use App\Utils\Ninja;
@ -38,15 +50,18 @@ class TransactionLog implements ShouldQueue
private array $transformer_array = [ private array $transformer_array = [
TransactionEvent::INVOICE_MARK_PAID => MarkPaidTransaction::class, TransactionEvent::INVOICE_MARK_PAID => MarkPaidTransaction::class,
TransactionEvent::INVOICE_UPDATED => MarkPaidTransaction::class, TransactionEvent::INVOICE_UPDATED => InvoiceUpdatedTransaction::class,
TransactionEvent::INVOICE_DELETED => MarkPaidTransaction::class, TransactionEvent::INVOICE_DELETED => InvoiceDeletedTransaction::class,
TransactionEvent::INVOICE_PAYMENT_APPLIED => MarkPaidTransaction::class, TransactionEvent::INVOICE_PAYMENT_APPLIED => InvoicePaymentTransaction::class,
TransactionEvent::INVOICE_CANCELLED => MarkPaidTransaction::class, TransactionEvent::INVOICE_CANCELLED => InvoiceCancelledTransaction::class,
TransactionEvent::INVOICE_FEE_APPLIED => MarkPaidTransaction::class, TransactionEvent::INVOICE_FEE_APPLIED => InvoiceFeeAppliedTransaction::class,
TransactionEvent::PAYMENT_MADE => MarkPaidTransaction::class, TransactionEvent::PAYMENT_MADE => PaymentMadeTransaction::class,
TransactionEvent::PAYMENT_APPLIED => MarkPaidTransaction::class, TransactionEvent::GATEWAY_PAYMENT_MADE => GatewayPaymentMadeTransaction::class,
TransactionEvent::PAYMENT_REFUND => MarkPaidTransaction::class, TransactionEvent::PAYMENT_APPLIED => PaymentAppliedTransaction::class,
TransactionEvent::PAYMENT_FAILED => MarkPaidTransaction::class, TransactionEvent::PAYMENT_REFUND => PaymentRefundedTransaction::class,
TransactionEvent::PAYMENT_FAILED => PaymentFailedTransaction::class,
TransactionEvent::PAYMENT_DELETED => PaymentDeletedTransaction::class,
TransactionEvent::CLIENT_STATUS => ClientStatusTransaction::class,
]; ];
/** /**
@ -69,8 +84,8 @@ class TransactionLog implements ShouldQueue
*/ */
public function handle() public function handle()
{ {
if(!Ninja::isHosted()) // if(!Ninja::isHosted())
return; // return;
$this->setTransformer(); $this->setTransformer();

View File

@ -840,4 +840,17 @@ class Client extends BaseModel implements HasLocalePreference
return $offset; return $offset;
} }
public function transaction_event()
{
$this->fresh();
return [
'client_id' => $this->id,
'client_balance' => $this->balance ?: 0,
'client_paid_to_date' => $this->paid_to_date ?: 0,
'client_credit_balance' => $this->credit_balance ?: 0
];
}
} }

View File

@ -302,4 +302,16 @@ class Credit extends BaseModel
}); });
} }
public function transaction_event()
{
$this->fresh();
return [
'credit_id' => $this->id,
'credit_amount' => $this->amount ?: 0,
'credit_balance' => $this->balance ?: 0,
'credit_status' => $this->status_id ?: 1,
];
}
} }

View File

@ -538,13 +538,16 @@ class Invoice extends BaseModel
public function transaction_event() public function transaction_event()
{ {
$this->fresh();
return [ return [
'id' => $this->id, 'invoice_id' => $this->id,
'amount' => $this->amount, 'invoice_amount' => $this->amount ?: 0,
'partial' => $this->partial, 'invoice_partial' => $this->partial ?: 0,
'balance' => $this->balance, 'invoice_balance' => $this->balance ?: 0,
'paid_to_date' => $this->paid_to_date, 'invoice_paid_to_date' => $this->paid_to_date ?: 0,
'status_id' => $this->status_id, 'invoice_status' => $this->status_id ?: 1,
]; ];
} }
} }

View File

@ -326,13 +326,16 @@ class Payment extends BaseModel
public function transaction_event() public function transaction_event()
{ {
$this->fresh();
return [ return [
'payment_id' => $this->id, 'payment_id' => $this->id,
'payment_amount' => $this->amount, 'payment_amount' => $this->amount ?: 0,
'payment_applied' => $this->applied, 'payment_applied' => $this->applied ?: 0,
'payment_refunded' => $this->refunded, 'payment_refunded' => $this->refunded ?: 0,
'payment_status' => $this->status_id, 'payment_status' => $this->status_id ?: 1,
'paymentables' => $this->paymentables->toArray(), 'paymentables' => $this->paymentables->toArray(),
'payment_request' => request() ? request()->all() : [],
]; ];
} }

View File

@ -22,7 +22,7 @@ class TransactionEvent extends StaticModel
public $guarded = ['id']; public $guarded = ['id'];
public $casts = [ public $casts = [
'metadata' => 'object', 'metadata' => 'array',
'payment_request' => 'array', 'payment_request' => 'array',
'paymentables' => 'array', 'paymentables' => 'array',
]; ];
@ -38,6 +38,8 @@ class TransactionEvent extends StaticModel
public const PAYMENT_APPLIED = 101; public const PAYMENT_APPLIED = 101;
public const PAYMENT_REFUND = 102; public const PAYMENT_REFUND = 102;
public const PAYMENT_FAILED = 103; public const PAYMENT_FAILED = 103;
public const GATEWAY_PAYMENT_MADE = 104;
public const PAYMENT_DELETED = 105;
public const CLIENT_STATUS = 200;
} }

View File

@ -20,6 +20,7 @@ use App\Jobs\Mail\NinjaMailer;
use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject; use App\Jobs\Mail\NinjaMailerObject;
use App\Jobs\Mail\PaymentFailedMailer; use App\Jobs\Mail\PaymentFailedMailer;
use App\Jobs\Ninja\TransactionLog;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Mail\Admin\ClientPaymentFailureObject; use App\Mail\Admin\ClientPaymentFailureObject;
use App\Models\Client; use App\Models\Client;
@ -32,6 +33,7 @@ use App\Models\Payment;
use App\Models\PaymentHash; use App\Models\PaymentHash;
use App\Models\PaymentType; use App\Models\PaymentType;
use App\Models\SystemLog; use App\Models\SystemLog;
use App\Models\TransactionEvent;
use App\Services\Subscription\SubscriptionService; use App\Services\Subscription\SubscriptionService;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
@ -317,11 +319,23 @@ class BaseDriver extends AbstractPaymentDriver
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($payment_invoices, 'invoice_id')))->withTrashed()->get(); $invoices = Invoice::whereIn('id', $this->transformKeys(array_column($payment_invoices, 'invoice_id')))->withTrashed()->get();
$invoices->each(function ($invoice) use ($fee_total) { $invoices->each(function ($invoice) use ($fee_total) {
if (collect($invoice->line_items)->contains('type_id', '3')) { if (collect($invoice->line_items)->contains('type_id', '3')) {
$invoice->service()->toggleFeesPaid()->save(); $invoice->service()->toggleFeesPaid()->save();
$invoice->client->service()->updateBalance($fee_total)->save(); $invoice->client->service()->updateBalance($fee_total)->save();
$invoice->ledger()->updateInvoiceBalance($fee_total, "Gateway fee adjustment for invoice {$invoice->number}"); $invoice->ledger()->updateInvoiceBalance($fee_total, "Gateway fee adjustment for invoice {$invoice->number}");
} }
$transaction = [
'invoice' => $invoice->transaction_event(),
'payment' => [],
'client' => $invoice->client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::INVOICE_FEE_APPLIED, $transaction, $invoice->company->db);
}); });
} }

View File

@ -14,11 +14,13 @@ namespace App\Repositories;
use App\Events\Payment\PaymentWasCreated; use App\Events\Payment\PaymentWasCreated;
use App\Events\Payment\PaymentWasDeleted; use App\Events\Payment\PaymentWasDeleted;
use App\Jobs\Credit\ApplyCreditPayment; use App\Jobs\Credit\ApplyCreditPayment;
use App\Jobs\Ninja\TransactionLog;
use App\Libraries\Currency\Conversion\CurrencyApi; use App\Libraries\Currency\Conversion\CurrencyApi;
use App\Models\Client; use App\Models\Client;
use App\Models\Credit; use App\Models\Credit;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\TransactionEvent;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Utils\Traits\SavesDocuments; use App\Utils\Traits\SavesDocuments;
@ -66,8 +68,6 @@ class PaymentRepository extends BaseRepository {
*/ */
private function applyPayment(array $data, Payment $payment): ?Payment private function applyPayment(array $data, Payment $payment): ?Payment
{ {
nlog("applying payment");
nlog($data);
$is_existing_payment = true; $is_existing_payment = true;
$client = false; $client = false;
@ -96,11 +96,8 @@ class PaymentRepository extends BaseRepository {
if (array_key_exists('credits', $data) && is_array($data['credits']) && count($data['credits']) > 0) { if (array_key_exists('credits', $data) && is_array($data['credits']) && count($data['credits']) > 0) {
$_credit_totals = array_sum(array_column($data['credits'], 'amount')); $_credit_totals = array_sum(array_column($data['credits'], 'amount'));
// if ($data['amount'] == $_credit_totals) { $client->service()->updatePaidToDate($_credit_totals)->save();
// $data['amount'] = 0;
// } else {
$client->service()->updatePaidToDate($_credit_totals)->save();
// }
} }
} }
@ -183,10 +180,19 @@ class PaymentRepository extends BaseRepository {
} }
$payment->applied += ($invoice_totals - $credit_totals); //wont work because - check tests $payment->applied += ($invoice_totals - $credit_totals); //wont work because - check tests
// $payment->applied += $invoice_totals; //wont work because - check tests
$payment->save(); $payment->save();
$transaction = [
'invoice' => [],
'payment' => $payment->transaction_event(),
'client' => $payment->client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::PAYMENT_MADE, $transaction, $payment->company->db);
return $payment->fresh(); return $payment->fresh();
} }

View File

@ -11,8 +11,10 @@
namespace App\Services\Invoice; namespace App\Services\Invoice;
use App\Jobs\Ninja\TransactionLog;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\TransactionEvent;
use App\Services\AbstractService; use App\Services\AbstractService;
class ApplyPayment extends AbstractService class ApplyPayment extends AbstractService
@ -128,6 +130,16 @@ class ApplyPayment extends AbstractService
$this->invoice->service()->applyNumber()->workFlow()->save(); $this->invoice->service()->applyNumber()->workFlow()->save();
$transaction = [
'invoice' => $this->invoice->transaction_event(),
'payment' => $this->payment->transaction_event(),
'client' => $this->invoice->client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::INVOICE_PAYMENT_APPLIED, $transaction, $this->invoice->company->db);
return $this->invoice; return $this->invoice;
} }
} }

View File

@ -12,8 +12,10 @@
namespace App\Services\Invoice; namespace App\Services\Invoice;
use App\Events\Invoice\InvoiceWasCancelled; use App\Events\Invoice\InvoiceWasCancelled;
use App\Jobs\Ninja\TransactionLog;
use App\Models\Client; use App\Models\Client;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\TransactionEvent;
use App\Services\AbstractService; use App\Services\AbstractService;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\GeneratesCounter;
@ -52,6 +54,16 @@ class HandleCancellation extends AbstractService
event(new InvoiceWasCancelled($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new InvoiceWasCancelled($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
$transaction = [
'invoice' => $this->invoice->transaction_event(),
'payment' => [],
'client' => $this->invoice->client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::INVOICE_CANCELLED, $transaction, $this->invoice->company->db);
return $this->invoice; return $this->invoice;
} }

View File

@ -11,7 +11,9 @@
namespace App\Services\Invoice; namespace App\Services\Invoice;
use App\Jobs\Ninja\TransactionLog;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\TransactionEvent;
use App\Services\AbstractService; use App\Services\AbstractService;
use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\GeneratesCounter;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@ -47,6 +49,16 @@ class MarkInvoiceDeleted extends AbstractService
->adjustBalance() ->adjustBalance()
->adjustLedger(); ->adjustLedger();
$transaction = [
'invoice' => $this->invoice->transaction_event(),
'payment' => $this->invoice->payments()->exists() ? $this->invoice->payments()->first()->transaction_event() : [],
'client' => $this->invoice->client->transaction_event(),
'credit' => [],
'metadata' => ['total_payments' => $this->total_payments, 'balance_adjustment' => $this->balance_adjustment, 'adjustment_amount' => $this->adjustment_amount],
];
TransactionLog::dispatch(TransactionEvent::INVOICE_DELETED, $transaction, $this->invoice->company->db);
return $this->invoice; return $this->invoice;
} }
@ -127,11 +139,6 @@ class MarkInvoiceDeleted extends AbstractService
$this->total_payments = $this->invoice->payments->sum('amount') - $this->invoice->payments->sum('refunded'); $this->total_payments = $this->invoice->payments->sum('amount') - $this->invoice->payments->sum('refunded');
$this->balance_adjustment = $this->invoice->balance; $this->balance_adjustment = $this->invoice->balance;
//$this->total_payments = $this->invoice->payments->sum('amount - refunded');
// nlog("adjustment amount = {$this->adjustment_amount}");
// nlog("total payments = {$this->total_payments}");
return $this; return $this;
} }

View File

@ -15,10 +15,12 @@ use App\Events\Invoice\InvoiceWasPaid;
use App\Events\Payment\PaymentWasCreated; use App\Events\Payment\PaymentWasCreated;
use App\Factory\PaymentFactory; use App\Factory\PaymentFactory;
use App\Jobs\Invoice\InvoiceWorkflowSettings; use App\Jobs\Invoice\InvoiceWorkflowSettings;
use App\Jobs\Ninja\TransactionLog;
use App\Jobs\Payment\EmailPayment; use App\Jobs\Payment\EmailPayment;
use App\Libraries\Currency\Conversion\CurrencyApi; use App\Libraries\Currency\Conversion\CurrencyApi;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\TransactionEvent;
use App\Services\AbstractService; use App\Services\AbstractService;
use App\Services\Client\ClientService; use App\Services\Client\ClientService;
use App\Utils\Ninja; use App\Utils\Ninja;
@ -110,6 +112,16 @@ class MarkPaid extends AbstractService
event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
event(new InvoiceWasPaid($this->invoice, $payment, $payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new InvoiceWasPaid($this->invoice, $payment, $payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
$transaction = [
'invoice' => $this->invoice->transaction_event(),
'payment' => $payment->transaction_event(),
'client' => $this->invoice->client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::INVOICE_MARK_PAID, $transaction, $this->invoice->company->db);
return $this->invoice; return $this->invoice;
} }

View File

@ -11,9 +11,11 @@
namespace App\Services\Payment; namespace App\Services\Payment;
use App\Jobs\Ninja\TransactionLog;
use App\Models\Credit; use App\Models\Credit;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\TransactionEvent;
use App\Repositories\ActivityRepository; use App\Repositories\ActivityRepository;
class DeletePayment class DeletePayment
@ -106,6 +108,7 @@ class DeletePayment
} else { } else {
$paymentable_invoice->service()->setStatus(Invoice::STATUS_PARTIAL)->save(); $paymentable_invoice->service()->setStatus(Invoice::STATUS_PARTIAL)->save();
} }
} }
else { else {
@ -118,19 +121,36 @@ class DeletePayment
} }
$transaction = [
'invoice' => $paymentable_invoice->transaction_event(),
'payment' => $this->payment->transaction_event(),
'client' => $client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::PAYMENT_DELETED, $transaction, $paymentable_invoice->company->db);
}); });
} }
// else {
/* If there are no invoices - then we need to still adjust the total client->paid_to_date amount*/ $this->payment
->client
->service()
->updatePaidToDate(($this->payment->amount - $this->payment->refunded)*-1)
->save();
$this->payment $transaction = [
->client 'invoice' => [],
->service() 'payment' => [],
->updatePaidToDate(($this->payment->amount - $this->payment->refunded)*-1) 'client' => $this->payment->client->transaction_event(),
->save(); 'credit' => [],
'metadata' => [],
];
// } TransactionLog::dispatch(TransactionEvent::CLIENT_STATUS, $transaction, $this->payment->company->db);
return $this; return $this;
} }

View File

@ -14,10 +14,12 @@ namespace App\Services\Payment;
use App\Exceptions\PaymentRefundFailed; use App\Exceptions\PaymentRefundFailed;
use App\Factory\CreditFactory; use App\Factory\CreditFactory;
use App\Factory\InvoiceItemFactory; use App\Factory\InvoiceItemFactory;
use App\Jobs\Ninja\TransactionLog;
use App\Models\Activity; use App\Models\Activity;
use App\Models\Credit; use App\Models\Credit;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\TransactionEvent;
use App\Repositories\ActivityRepository; use App\Repositories\ActivityRepository;
use App\Utils\Ninja; use App\Utils\Ninja;
use stdClass; use stdClass;
@ -61,6 +63,17 @@ class RefundPayment
->adjustInvoices() ->adjustInvoices()
->processGatewayRefund() //process the gateway refund if needed ->processGatewayRefund() //process the gateway refund if needed
->save(); ->save();
$transaction = [
'invoice' => [],
'payment' => $this->payment->transaction_event(),
'client' => $this->payment->client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::PAYMENT_REFUND, $transaction, $this->payment->company->db);
} }
/** /**

View File

@ -13,9 +13,11 @@ namespace App\Services\Payment;
use App\Events\Invoice\InvoiceWasUpdated; use App\Events\Invoice\InvoiceWasUpdated;
use App\Jobs\Invoice\InvoiceWorkflowSettings; use App\Jobs\Invoice\InvoiceWorkflowSettings;
use App\Jobs\Ninja\TransactionLog;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\PaymentHash; use App\Models\PaymentHash;
use App\Models\TransactionEvent;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
@ -88,6 +90,17 @@ class UpdateInvoicePayment
$this->payment->applied += $paid_amount; $this->payment->applied += $paid_amount;
$transaction = [
'invoice' => $this->invoice->transaction_event(),
'payment' => $this->payment->transaction_event(),
'client' => $client->transaction_event(),
'credit' => [],
'metadata' => [],
];
TransactionLog::dispatch(TransactionEvent::GATEWAY_PAYMENT_MADE, $transaction, $this->invoice->company->db);
}); });
/* Remove the event updater from within the loop to prevent race conditions */ /* Remove the event updater from within the loop to prevent race conditions */

View File

@ -317,6 +317,7 @@ class HtmlEngine
$data['$website'] = ['value' => $this->client->present()->website() ?: '&nbsp;', 'label' => ctrans('texts.website')]; $data['$website'] = ['value' => $this->client->present()->website() ?: '&nbsp;', 'label' => ctrans('texts.website')];
$data['$phone'] = ['value' => $this->client->present()->phone() ?: '&nbsp;', 'label' => ctrans('texts.phone')]; $data['$phone'] = ['value' => $this->client->present()->phone() ?: '&nbsp;', 'label' => ctrans('texts.phone')];
$data['$country'] = ['value' => isset($this->client->country->name) ? ctrans('texts.country_' . $this->client->country->name) : '', 'label' => ctrans('texts.country')]; $data['$country'] = ['value' => isset($this->client->country->name) ? ctrans('texts.country_' . $this->client->country->name) : '', 'label' => ctrans('texts.country')];
$data['$country_2'] = ['value' => isset($this->client->country) ? $this->client->country->iso_3166_2 : '', 'label' => ctrans('texts.country')];
$data['$email'] = ['value' => isset($this->contact) ? $this->contact->email : 'no contact email on record', 'label' => ctrans('texts.email')]; $data['$email'] = ['value' => isset($this->contact) ? $this->contact->email : 'no contact email on record', 'label' => ctrans('texts.email')];
$data['$client_name'] = ['value' => $this->entity->present()->clientName() ?: '&nbsp;', 'label' => ctrans('texts.client_name')]; $data['$client_name'] = ['value' => $this->entity->present()->clientName() ?: '&nbsp;', 'label' => ctrans('texts.client_name')];
$data['$client.name'] = &$data['$client_name']; $data['$client.name'] = &$data['$client_name'];
@ -392,6 +393,7 @@ class HtmlEngine
$data['$company.state'] = ['value' => $this->settings->state ?: '&nbsp;', 'label' => ctrans('texts.state')]; $data['$company.state'] = ['value' => $this->settings->state ?: '&nbsp;', 'label' => ctrans('texts.state')];
$data['$company.postal_code'] = ['value' => $this->settings->postal_code ?: '&nbsp;', 'label' => ctrans('texts.postal_code')]; $data['$company.postal_code'] = ['value' => $this->settings->postal_code ?: '&nbsp;', 'label' => ctrans('texts.postal_code')];
$data['$company.country'] = ['value' => $this->getCountryName(), 'label' => ctrans('texts.country')]; $data['$company.country'] = ['value' => $this->getCountryName(), 'label' => ctrans('texts.country')];
$data['$company.country_2'] = ['value' => $this->getCountryCode(), 'label' => ctrans('texts.country')];
$data['$company.phone'] = ['value' => $this->settings->phone ?: '&nbsp;', 'label' => ctrans('texts.phone')]; $data['$company.phone'] = ['value' => $this->settings->phone ?: '&nbsp;', 'label' => ctrans('texts.phone')];
$data['$company.email'] = ['value' => $this->settings->email ?: '&nbsp;', 'label' => ctrans('texts.email')]; $data['$company.email'] = ['value' => $this->settings->email ?: '&nbsp;', 'label' => ctrans('texts.email')];
$data['$company.vat_number'] = ['value' => $this->settings->vat_number ?: '&nbsp;', 'label' => ctrans('texts.vat_number')]; $data['$company.vat_number'] = ['value' => $this->settings->vat_number ?: '&nbsp;', 'label' => ctrans('texts.vat_number')];
@ -617,6 +619,17 @@ class HtmlEngine
return '&nbsp;'; return '&nbsp;';
} }
private function getCountryCode() :string
{
$country = Country::find($this->settings->country_id);
if ($country) {
return ctrans('texts.country_' . $country->iso_3166_2);
}
return '&nbsp;';
}
/** /**
* Due to the way we are compiling the blade template we * Due to the way we are compiling the blade template we
* have no ability to iterate, so in the case * have no ability to iterate, so in the case