Merge pull request #4685 from turbo124/v5-develop

Catch exception in Authorize - failedResponse method
This commit is contained in:
David Bomba 2021-01-14 21:29:58 +11:00 committed by GitHub
commit 4967ffb668
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 268 additions and 151 deletions

View File

@ -47,7 +47,7 @@ jobs:
- name: Cleanup Builds - name: Cleanup Builds
run: | run: |
sudo rm -rf bootstrap/cache/* sudo rm -rf bootstrap/cache/*
sudo rm -rf node_modules
- name: Build project # This would actually build your project, using zip for an example artifact - name: Build project # This would actually build your project, using zip for an example artifact
run: | run: |
zip -r ./invoiceninja.zip ./ zip -r ./invoiceninja.zip ./

View File

@ -31,6 +31,8 @@ class UserWasArchived
*/ */
public $user; public $user;
public $creating_user;
public $company; public $company;
public $event_vars; public $event_vars;
@ -42,9 +44,10 @@ class UserWasArchived
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(User $user, Company $company, array $event_vars) public function __construct(User $user, User $creating_user, Company $company, array $event_vars)
{ {
$this->user = $user; $this->user = $user;
$this->creating_user = $creating_user;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -31,6 +31,8 @@ class UserWasCreated
*/ */
public $user; public $user;
public $creating_user;
public $company; public $company;
public $event_vars; public $event_vars;
@ -42,9 +44,10 @@ class UserWasCreated
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(User $user, Company $company, array $event_vars) public function __construct(User $user, User $creating_user, Company $company, array $event_vars)
{ {
$this->user = $user; $this->user = $user;
$this->creating_user = $creating_user;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -31,6 +31,8 @@ class UserWasDeleted
*/ */
public $user; public $user;
public $creating_user;
public $company; public $company;
public $event_vars; public $event_vars;
@ -42,9 +44,10 @@ class UserWasDeleted
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(User $user, Company $company, array $event_vars) public function __construct(User $user, User $creating_user, Company $company, array $event_vars)
{ {
$this->user = $user; $this->user = $user;
$this->creating_user = $creating_user;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -35,7 +35,7 @@ class UserWasRestored
public $event_vars; public $event_vars;
public $fromDeleted; public $creating_user;
/** /**
* Create a new event instance. * Create a new event instance.
@ -44,12 +44,12 @@ class UserWasRestored
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(User $user, bool $fromDeleted, Company $company, array $event_vars) public function __construct(User $user, User $creating_user, Company $company, array $event_vars)
{ {
$this->user = $user; $this->user = $user;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
$this->fromDeleted = $fromDeleted; $this->creating_user = $creating_user;
} }
/** /**

View File

@ -31,6 +31,8 @@ class UserWasUpdated
*/ */
public $user; public $user;
public $creating_user;
public $company; public $company;
public $event_vars; public $event_vars;
@ -42,9 +44,10 @@ class UserWasUpdated
* @param Company $company * @param Company $company
* @param array $event_vars * @param array $event_vars
*/ */
public function __construct(User $user, Company $company, array $event_vars) public function __construct(User $user, User $creating_user, Company $company, array $event_vars)
{ {
$this->user = $user; $this->user = $user;
$this->creating_user = $creating_user;
$this->company = $company; $this->company = $company;
$this->event_vars = $event_vars; $this->event_vars = $event_vars;
} }

View File

@ -21,6 +21,10 @@
*/ */
function nlog($output, $context = []): void function nlog($output, $context = []): void
{ {
$trace = debug_backtrace();
\Illuminate\Support\Facades\Log::channel('invoiceninja')->info(print_r($trace[1]['class'],1), []);
if (config('ninja.expanded_logging')) { if (config('ninja.expanded_logging')) {
if (gettype($output) == 'object') { if (gettype($output) == 'object') {
$output = print_r($output, 1); $output = print_r($output, 1);

View File

@ -175,7 +175,7 @@ class PaymentController extends Controller
foreach($payable_invoices as $payable_invoice) foreach($payable_invoices as $payable_invoice)
{ {
nlog($payable_invoice); // nlog($payable_invoice);
$payable_invoice['amount'] = Number::parseFloat($payable_invoice['amount']); $payable_invoice['amount'] = Number::parseFloat($payable_invoice['amount']);

View File

@ -174,7 +174,7 @@ class TaskStatusController extends BaseController
*/ */
public function store(StoreTaskStatusRequest $request) public function store(StoreTaskStatusRequest $request)
{ {
nlog($request->all()); // nlog($request->all());
$task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id); $task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id);
$task_status->fill($request->all()); $task_status->fill($request->all());

View File

@ -13,6 +13,8 @@ namespace App\Http\Controllers;
use App\DataMapper\CompanySettings; use App\DataMapper\CompanySettings;
use App\Events\User\UserWasCreated; use App\Events\User\UserWasCreated;
use App\Events\User\UserWasDeleted;
use App\Events\User\UserWasUpdated;
use App\Factory\UserFactory; use App\Factory\UserFactory;
use App\Filters\UserFilters; use App\Filters\UserFilters;
use App\Http\Controllers\Traits\VerifiesUserEmail; use App\Http\Controllers\Traits\VerifiesUserEmail;
@ -202,7 +204,7 @@ class UserController extends BaseController
$ct = CreateCompanyToken::dispatchNow($company, $user, $user_agent); $ct = CreateCompanyToken::dispatchNow($company, $user, $user_agent);
event(new UserWasCreated($user, $company, Ninja::eventVars())); event(new UserWasCreated($user, auth()->user(), $company, Ninja::eventVars()));
return $this->itemResponse($user->fresh()); return $this->itemResponse($user->fresh());
} }
@ -376,6 +378,8 @@ class UserController extends BaseController
UserEmailChanged::dispatch($new_email, $old_email, auth()->user()->company()); UserEmailChanged::dispatch($new_email, $old_email, auth()->user()->company());
} }
event(new UserWasUpdated($user, auth()->user(), auth()->user()->company, Ninja::eventVars()));
return $this->itemResponse($user); return $this->itemResponse($user);
} }
@ -444,6 +448,8 @@ class UserController extends BaseController
/* If the user passes the company user we archive the company user */ /* If the user passes the company user we archive the company user */
$user = $this->user_repo->destroy($request->all(), $user); $user = $this->user_repo->destroy($request->all(), $user);
event(new UserWasDeleted($user, auth()->user(), auth()->user()->company, Ninja::eventVars()));
return $this->itemResponse($user->fresh()); return $this->itemResponse($user->fresh());
} }

View File

@ -78,7 +78,7 @@ class CreateUser
'settings' => null, 'settings' => null,
]); ]);
event(new UserWasCreated($user, $this->company, Ninja::eventVars())); event(new UserWasCreated($user, $user, $this->company, Ninja::eventVars()));
return $user; return $user;
} }

View File

@ -43,13 +43,10 @@ class ArchivedUserActivity implements ShouldQueue
$fields = new stdClass; $fields = new stdClass;
if (auth()->user()->id) { $fields->user_id = $event->user->id;
$fields->user_id = auth()->user()->id; $fields->notes = $event->creating_user->present()->name . " Archived User";
} else {
$fields->user_id = $event->user->id;
}
$fields->company_id = $event->user->company_id; $fields->company_id = $event->company->id;
$fields->activity_type_id = Activity::ARCHIVE_USER; $fields->activity_type_id = Activity::ARCHIVE_USER;
$this->activityRepo->save($fields, $event->user, $event->event_vars); $this->activityRepo->save($fields, $event->user, $event->event_vars);

View File

@ -43,13 +43,9 @@ class CreatedUserActivity implements ShouldQueue
$fields = new stdClass; $fields = new stdClass;
if (auth()->user()) { $fields->user_id = $event->user->id;
$fields->user_id = auth()->user()->id; $fields->notes = $event->creating_user->present()->name() . " Created the user";
} else { $fields->company_id = $event->company->id;
$fields->user_id = $event->user->id;
}
$fields->company_id = $event->user->company_id;
$fields->activity_type_id = Activity::CREATE_USER; $fields->activity_type_id = Activity::CREATE_USER;
$this->activityRepo->save($fields, $event->user, $event->event_vars); $this->activityRepo->save($fields, $event->user, $event->event_vars);

View File

@ -48,12 +48,8 @@ class DeletedUserActivity implements ShouldQueue
$fields = new stdClass; $fields = new stdClass;
if (auth()->check()) { $fields->user_id = $event->user->id;
$fields->user_id = auth()->user()->id; $fields->notes = $event->creating_user->present()->name . " Deleted User";
} else {
$fields->user_id = $event->user->id;
}
$fields->company_id = $event->company->id; $fields->company_id = $event->company->id;
$fields->activity_type_id = Activity::DELETE_USER; $fields->activity_type_id = Activity::DELETE_USER;

View File

@ -43,13 +43,10 @@ class RestoredUserActivity implements ShouldQueue
$fields = new stdClass; $fields = new stdClass;
if (auth()->user()->id) { $fields->user_id = $event->user->id;
$fields->user_id = auth()->user()->id; $fields->notes = $event->creating_user->present()->name() . " Restored user";
} else {
$fields->user_id = $event->user->id;
}
$fields->company_id = $event->user->company_id; $fields->company_id = $event->company->id;
$fields->activity_type_id = Activity::RESTORE_USER; $fields->activity_type_id = Activity::RESTORE_USER;
$this->activityRepo->save($fields, $event->user, $event->event_vars); $this->activityRepo->save($fields, $event->user, $event->event_vars);

View File

@ -42,14 +42,9 @@ class UpdatedUserActivity implements ShouldQueue
MultiDB::setDb($event->company->db); MultiDB::setDb($event->company->db);
$fields = new stdClass; $fields = new stdClass;
$fields->user_id = $event->user->id;
if (auth()->user()->id) { $fields->notes = $event->creating_user->present()->name . " Updated user";
$fields->user_id = auth()->user()->id; $fields->company_id = $event->company->id;
} else {
$fields->user_id = $event->user->id;
}
$fields->company_id = $event->user->company_id;
$fields->activity_type_id = Activity::UPDATE_USER; $fields->activity_type_id = Activity::UPDATE_USER;
$this->activityRepo->save($fields, $event->user, $event->event_vars); $this->activityRepo->save($fields, $event->user, $event->event_vars);

View File

@ -60,7 +60,7 @@ class EntitySentObject
private function setTemplate() private function setTemplate()
{ {
nlog($this->template); // nlog($this->template);
switch ($this->template) { switch ($this->template) {
case 'invoice': case 'invoice':

View File

@ -65,11 +65,11 @@ class Activity extends StaticModel
const RESTORE_TASK = 46; // const RESTORE_TASK = 46; //
const UPDATE_EXPENSE = 47;// const UPDATE_EXPENSE = 47;//
const CREATE_USER = 48; // only used in CreateUser::job const CREATE_USER = 48;
const UPDATE_USER = 49; // not needed? const UPDATE_USER = 49;
const ARCHIVE_USER = 50; // not needed? const ARCHIVE_USER = 50;
const DELETE_USER = 51; // not needed? const DELETE_USER = 51;
const RESTORE_USER = 52; // not needed? const RESTORE_USER = 52;
const MARK_SENT_INVOICE = 53; // not needed? const MARK_SENT_INVOICE = 53; // not needed?
const PAID_INVOICE = 54; // const PAID_INVOICE = 54; //
const EMAIL_INVOICE_FAILED = 57; const EMAIL_INVOICE_FAILED = 57;

View File

@ -34,7 +34,8 @@ class SystemLog extends Model
const CATEGORY_GATEWAY_RESPONSE = 1; const CATEGORY_GATEWAY_RESPONSE = 1;
const CATEGORY_MAIL = 2; const CATEGORY_MAIL = 2;
const CATEGORY_WEBHOOK = 3; const CATEGORY_WEBHOOK = 3;
const CATEGORY_PDF = 3; const CATEGORY_PDF = 4;
const CATEGORY_SECURITY = 5;
/* Event IDs*/ /* Event IDs*/
const EVENT_PAYMENT_RECONCILIATION_FAILURE = 10; const EVENT_PAYMENT_RECONCILIATION_FAILURE = 10;
@ -50,6 +51,9 @@ class SystemLog extends Model
const EVENT_WEBHOOK_RESPONSE = 40; const EVENT_WEBHOOK_RESPONSE = 40;
const EVENT_PDF_RESPONSE = 50; const EVENT_PDF_RESPONSE = 50;
const EVENT_AUTHENTICATION_FAILURE = 60;
const EVENT_USER = 61;
/*Type IDs*/ /*Type IDs*/
const TYPE_PAYPAL = 300; const TYPE_PAYPAL = 300;
const TYPE_STRIPE = 301; const TYPE_STRIPE = 301;
@ -62,9 +66,13 @@ class SystemLog extends Model
const TYPE_UPSTREAM_FAILURE = 401; const TYPE_UPSTREAM_FAILURE = 401;
const TYPE_WEBHOOK_RESPONSE = 500; const TYPE_WEBHOOK_RESPONSE = 500;
const TYPE_PDF_FAILURE = 600; const TYPE_PDF_FAILURE = 600;
const TYPE_PDF_SUCCESS = 601; const TYPE_PDF_SUCCESS = 601;
const TYPE_MODIFIED = 701;
const TYPE_DELETED = 702;
protected $fillable = [ protected $fillable = [
'client_id', 'client_id',
'company_id', 'company_id',

View File

@ -98,29 +98,8 @@ class AuthorizeCreditCard
/*Refactor and push to BaseDriver*/ /*Refactor and push to BaseDriver*/
if ($data['response'] != null && $data['response']->getMessages()->getResultCode() == 'Ok') { if ($data['response'] != null && $data['response']->getMessages()->getResultCode() == 'Ok') {
// $response = $data['response'];
// $payment_record = [];
// $payment_record['amount'] = $amount;
// $payment_record['payment_type'] = PaymentType::CREDIT_CARD_OTHER;;
// $payment_record['transaction_reference'] = $response->getTransactionResponse()->getTransId();
// $this->authorize->createPayment($payment_record);
$this->storePayment($payment_hash, $data); $this->storePayment($payment_hash, $data);
// $payment = $this->createPaymentRecord($data, $amount);
// $payment->meta = $cgt->meta;
// $payment->save();
// $payment_hash->payment_id = $payment->id;
// $payment_hash->save();
// $this->authorize->attachInvoices($payment, $payment_hash);
// $payment->service()->updateInvoicePayment($payment_hash);
// event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));
$vars = [ $vars = [
'hashed_ids' => $invoice->hashed_id, 'hashed_ids' => $invoice->hashed_id,
'amount' => $amount, 'amount' => $amount,
@ -212,8 +191,7 @@ class AuthorizeCreditCard
private function processFailedResponse($data, $request) private function processFailedResponse($data, $request)
{ {
//dd($data); throw new \Exception(ctrans('texts.error_title'));
// nlog(print_r($data, 1));
} }
private function formatGatewayResponse($data, $vars) private function formatGatewayResponse($data, $vars)

View File

@ -72,8 +72,11 @@ use App\Events\Task\TaskWasDeleted;
use App\Events\Task\TaskWasRestored; use App\Events\Task\TaskWasRestored;
use App\Events\Task\TaskWasUpdated; use App\Events\Task\TaskWasUpdated;
use App\Events\User\UserLoggedIn; use App\Events\User\UserLoggedIn;
use App\Events\User\UserWasArchived;
use App\Events\User\UserWasCreated; use App\Events\User\UserWasCreated;
use App\Events\User\UserWasDeleted; use App\Events\User\UserWasDeleted;
use App\Events\User\UserWasRestored;
use App\Events\User\UserWasUpdated;
use App\Events\Vendor\VendorWasArchived; use App\Events\Vendor\VendorWasArchived;
use App\Events\Vendor\VendorWasCreated; use App\Events\Vendor\VendorWasCreated;
use App\Events\Vendor\VendorWasDeleted; use App\Events\Vendor\VendorWasDeleted;
@ -123,8 +126,8 @@ use App\Listeners\Invoice\InvoiceArchivedActivity;
use App\Listeners\Invoice\InvoiceCancelledActivity; use App\Listeners\Invoice\InvoiceCancelledActivity;
use App\Listeners\Invoice\InvoiceDeletedActivity; use App\Listeners\Invoice\InvoiceDeletedActivity;
use App\Listeners\Invoice\InvoiceEmailActivity; use App\Listeners\Invoice\InvoiceEmailActivity;
use App\Listeners\Invoice\InvoiceEmailedNotification;
use App\Listeners\Invoice\InvoiceEmailFailedActivity; use App\Listeners\Invoice\InvoiceEmailFailedActivity;
use App\Listeners\Invoice\InvoiceEmailedNotification;
use App\Listeners\Invoice\InvoicePaidActivity; use App\Listeners\Invoice\InvoicePaidActivity;
use App\Listeners\Invoice\InvoiceReminderEmailActivity; use App\Listeners\Invoice\InvoiceReminderEmailActivity;
use App\Listeners\Invoice\InvoiceRestoredActivity; use App\Listeners\Invoice\InvoiceRestoredActivity;
@ -132,8 +135,8 @@ use App\Listeners\Invoice\InvoiceReversedActivity;
use App\Listeners\Invoice\InvoiceViewedActivity; use App\Listeners\Invoice\InvoiceViewedActivity;
use App\Listeners\Invoice\UpdateInvoiceActivity; use App\Listeners\Invoice\UpdateInvoiceActivity;
use App\Listeners\Misc\InvitationViewedListener; use App\Listeners\Misc\InvitationViewedListener;
use App\Listeners\Payment\PaymentEmailedActivity;
use App\Listeners\Payment\PaymentEmailFailureActivity; use App\Listeners\Payment\PaymentEmailFailureActivity;
use App\Listeners\Payment\PaymentEmailedActivity;
use App\Listeners\Payment\PaymentNotification; use App\Listeners\Payment\PaymentNotification;
use App\Listeners\Payment\PaymentRestoredActivity; use App\Listeners\Payment\PaymentRestoredActivity;
use App\Listeners\Quote\QuoteApprovedActivity; use App\Listeners\Quote\QuoteApprovedActivity;
@ -145,8 +148,12 @@ use App\Listeners\Quote\QuoteRestoredActivity;
use App\Listeners\Quote\QuoteViewedActivity; use App\Listeners\Quote\QuoteViewedActivity;
use App\Listeners\Quote\ReachWorkflowSettings; use App\Listeners\Quote\ReachWorkflowSettings;
use App\Listeners\SendVerificationNotification; use App\Listeners\SendVerificationNotification;
use App\Listeners\User\ArchivedUserActivity;
use App\Listeners\User\CreatedUserActivity;
use App\Listeners\User\DeletedUserActivity; use App\Listeners\User\DeletedUserActivity;
use App\Listeners\User\RestoredUserActivity;
use App\Listeners\User\UpdateUserLastLogin; use App\Listeners\User\UpdateUserLastLogin;
use App\Listeners\User\UpdatedUserActivity;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider class EventServiceProvider extends ServiceProvider
@ -158,14 +165,24 @@ class EventServiceProvider extends ServiceProvider
*/ */
protected $listen = [ protected $listen = [
UserWasCreated::class => [ UserWasCreated::class => [
CreatedUserActivity::class,
SendVerificationNotification::class, SendVerificationNotification::class,
], ],
UserWasDeleted::class => [ UserWasDeleted::class => [
DeletedUserActivity::class, DeletedUserActivity::class,
], ],
UserWasArchived::class => [
ArchivedUserActivity::class,
],
UserLoggedIn::class => [ UserLoggedIn::class => [
UpdateUserLastLogin::class, UpdateUserLastLogin::class,
], ],
UserWasUpdated::class => [
UpdatedUserActivity::class,
],
UserWasRestored::class => [
RestoredUserActivity::class,
],
ContactLoggedIn::class => [ ContactLoggedIn::class => [
UpdateContactLastLogin::class, UpdateContactLastLogin::class,
], ],

View File

@ -19,6 +19,7 @@ use App\Models\Design;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Quote; use App\Models\Quote;
use App\Models\RecurringInvoice; use App\Models\RecurringInvoice;
use App\Models\User;
use App\Services\PdfMaker\Design as PdfDesignModel; use App\Services\PdfMaker\Design as PdfDesignModel;
use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\Design as PdfMakerDesign;
use App\Services\PdfMaker\PdfMaker as PdfMakerService; use App\Services\PdfMaker\PdfMaker as PdfMakerService;
@ -69,7 +70,11 @@ class ActivityRepository extends BaseRepository
*/ */
public function createBackup($entity, $activity) public function createBackup($entity, $activity)
{ {
if ($entity->company->is_disabled) {
if($entity instanceof User){
}
else if ($entity->company->is_disabled) {
return; return;
} }

View File

@ -12,7 +12,9 @@
namespace App\Repositories; namespace App\Repositories;
use App\DataMapper\CompanySettings; use App\DataMapper\CompanySettings;
use App\Events\User\UserWasArchived;
use App\Events\User\UserWasDeleted; use App\Events\User\UserWasDeleted;
use App\Events\User\UserWasRestored;
use App\Models\CompanyUser; use App\Models\CompanyUser;
use App\Models\User; use App\Models\User;
use App\Utils\Ninja; use App\Utils\Ninja;
@ -137,7 +139,7 @@ class UserRepository extends BaseRepository
$cu->delete(); $cu->delete();
} }
event(new UserWasDeleted($user, $company, Ninja::eventVars())); event(new UserWasDeleted($user, auth()->user(), $company, Ninja::eventVars()));
$user->is_deleted = true; $user->is_deleted = true;
$user->save(); $user->save();
@ -146,4 +148,31 @@ class UserRepository extends BaseRepository
return $user->fresh(); return $user->fresh();
} }
public function archive($user)
{
if ($user->trashed()) {
return;
}
$user->delete();
event(new UserWasArchived($user, auth()->user(), auth()->user()->company, Ninja::eventVars()));
}
/**
* @param $entity
*/
public function restore($user)
{
if (! $user->trashed()) {
return;
}
$user->restore();
event(new UserWasRestored($user, auth()->user(), auth()->user()->company, Ninja::eventVars()));
}
} }

View File

@ -106,7 +106,7 @@ class HtmlEngine
$data['$line_tax_labels'] = ['value' => $this->lineTaxLabels(), 'label' => ctrans('texts.taxes')]; $data['$line_tax_labels'] = ['value' => $this->lineTaxLabels(), 'label' => ctrans('texts.taxes')];
$data['$line_tax_values'] = ['value' => $this->lineTaxValues(), 'label' => ctrans('texts.taxes')]; $data['$line_tax_values'] = ['value' => $this->lineTaxValues(), 'label' => ctrans('texts.taxes')];
$data['$date'] = ['value' => $this->formatDate($this->entity->date, $this->entity->client->date_format()) ?: ' ', 'label' => ctrans('texts.date')]; $data['$date'] = ['value' => $this->formatDate($this->entity->date, $this->entity->client->date_format()) ?: ' ', 'label' => ctrans('texts.date')];
//$data['$invoice_date'] = ['value' => $this->date ?: ' ', 'label' => ctrans('texts.invoice_date')];
$data['$invoice.date'] = &$data['$date']; $data['$invoice.date'] = &$data['$date'];
$data['$due_date'] = ['value' => $this->formatDate($this->entity->due_date, $this->entity->client->date_format()) ?: ' ', 'label' => ctrans('texts.'.$this->entity_string.'_due_date')]; $data['$due_date'] = ['value' => $this->formatDate($this->entity->due_date, $this->entity->client->date_format()) ?: ' ', 'label' => ctrans('texts.'.$this->entity_string.'_due_date')];
$data['$payment_due'] = ['value' => $this->formatDate($this->entity->due_date, $this->entity->client->date_format()) ?: ' ', 'label' => ctrans('texts.payment_due')]; $data['$payment_due'] = ['value' => $this->formatDate($this->entity->due_date, $this->entity->client->date_format()) ?: ' ', 'label' => ctrans('texts.payment_due')];
@ -118,12 +118,6 @@ class HtmlEngine
$data['$quote.datetime'] = &$data['$entity.datetime']; $data['$quote.datetime'] = &$data['$entity.datetime'];
$data['$credit.datetime'] = &$data['$entity.datetime']; $data['$credit.datetime'] = &$data['$entity.datetime'];
// $data['$line_taxes'] = ['value' => $this->makeLineTaxes() ?: ' ', 'label' => ctrans('texts.taxes')];
// $data['$invoice.line_taxes'] = &$data['$line_taxes'];
// $data['$total_taxes'] = ['value' => $this->makeTotalTaxes() ?: ' ', 'label' => ctrans('texts.taxes')];
// $data['$invoice.total_taxes'] = &$data['$total_taxes'];
if ($this->entity_string == 'invoice') { if ($this->entity_string == 'invoice') {
$data['$entity'] = ['value' => '', 'label' => ctrans('texts.invoice')]; $data['$entity'] = ['value' => '', 'label' => ctrans('texts.invoice')];
$data['$number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.invoice_number')]; $data['$number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.invoice_number')];
@ -159,14 +153,14 @@ class HtmlEngine
$data['$invoice.subtotal'] = &$data['$subtotal']; $data['$invoice.subtotal'] = &$data['$subtotal'];
if ($this->entity->partial > 0) { if ($this->entity->partial > 0) {
$data['$balance_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->client) ?: ' ', 'label' => ctrans('texts.balance_due')]; $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->client) ?: ' ', 'label' => ctrans('texts.partial_due')];
} else { } else {
$data['$balance_due'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: ' ', 'label' => ctrans('texts.balance_due')]; $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: ' ', 'label' => ctrans('texts.balance_due')];
} }
$data['$quote.balance_due'] = $data['$balance_due']; $data['$quote.balance_due'] = $data['$balance_due'];
$data['$invoice.balance_due'] = $data['$balance_due']; $data['$invoice.balance_due'] = $data['$balance_due'];
$data['$balance_due'] = $data['$balance_due']; // $data['$balance_due'] = $data['$balance_due'];
$data['$outstanding'] = $data['$balance_due']; $data['$outstanding'] = $data['$balance_due'];
$data['$partial_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->client) ?: ' ', 'label' => ctrans('texts.partial_due')]; $data['$partial_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->client) ?: ' ', 'label' => ctrans('texts.partial_due')];
$data['$total'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.total')]; $data['$total'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.total')];
@ -212,15 +206,6 @@ class HtmlEngine
$data['$credit_no'] = &$data['$number']; $data['$credit_no'] = &$data['$number'];
$data['$credit.credit_no'] = &$data['$number']; $data['$credit.credit_no'] = &$data['$number'];
// $data['$invoice_issued_to'] = ;
// $data['$quote_issued_to'] = ;
// $data['$rate'] = ;
// $data['$hours'] = ;
// $data['$from'] = ;
// $data['$to'] = ;
// $data['$invoice_to'] = ;
// $data['$quote_to'] = ;
// $data['$details'] = ;
$data['$invoice_no'] = &$data['$number']; $data['$invoice_no'] = &$data['$number'];
$data['$invoice.invoice_no'] = &$data['$number']; $data['$invoice.invoice_no'] = &$data['$number'];
$data['$client1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client1', $this->client->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client1')]; $data['$client1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client1', $this->client->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client1')];
@ -362,44 +347,6 @@ class HtmlEngine
$data['$entity_footer'] = ['value' => $this->client->getSetting("{$this->entity_string}_footer"), 'label' => '']; $data['$entity_footer'] = ['value' => $this->client->getSetting("{$this->entity_string}_footer"), 'label' => ''];
// $data['custom_label1'] = ['value' => '', 'label' => ctrans('texts.')];
// $data['custom_label2'] = ['value' => '', 'label' => ctrans('texts.')];
// $data['custom_label3'] = ['value' => '', 'label' => ctrans('texts.')];
// $data['custom_label4'] = ['value' => '', 'label' => ctrans('texts.')];
//$data['$blank'] = ;
//$data['$surcharge'] = ;
/*
$data['$tax_invoice'] =
$data['$tax_quote'] =
$data['$statement'] = ;
$data['$statement_date'] = ;
$data['$your_statement'] = ;
$data['$statement_issued_to'] = ;
$data['$statement_to'] = ;
$data['$credit_note'] = ;
$data['$credit_date'] = ;
$data['$credit_issued_to'] = ;
$data['$credit_to'] = ;
$data['$your_credit'] = ;
$data['$phone'] = ;
$data['$outstanding'] = ;
$data['$invoice_due_date'] = ;
$data['$quote_due_date'] = ;
$data['$service'] = ;
$data['$product_key'] = ;
$data['$unit_cost'] = ;
$data['$custom_value1'] = ;
$data['$custom_value2'] = ;
$data['$delivery_note'] = ;
$data['$date'] = ;
$data['$method'] = ;
$data['$payment_date'] = ;
$data['$reference'] = ;
$data['$amount'] = ;
$data['$amount_paid'] =;
*/
$arrKeysLength = array_map('strlen', array_keys($data)); $arrKeysLength = array_map('strlen', array_keys($data));
array_multisort($arrKeysLength, SORT_DESC, $data); array_multisort($arrKeysLength, SORT_DESC, $data);

0
public/css/card-js.min.css vendored Normal file → Executable file
View File

View File

@ -38,6 +38,11 @@
<polyline points="22,6 12,13 2,6"></polyline> <polyline points="22,6 12,13 2,6"></polyline>
</svg> </svg>
</a> </a>
<a href="https://www.youtube.com/channel/UCXAHcBvhW05PDtWYIq7WDFA">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"></path>
</svg>
</a>
</div> </div>
</div> </div>
@endif @endif

View File

@ -44,6 +44,11 @@
<polyline points="22,6 12,13 2,6"></polyline> <polyline points="22,6 12,13 2,6"></polyline>
</svg> </svg>
</a> </a>
<a href="https://www.youtube.com/channel/UCXAHcBvhW05PDtWYIq7WDFA">
<svg class="text-white hover:text-gray-300 mr-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"></path>
</svg>
</a>
</div> </div>
</div> </div>
@endif @endif

View File

@ -1,5 +1,5 @@
@extends('portal.ninja2020.layout.app') @extends('portal.ninja2020.layout.app')
@section('meta_title', ctrans('texts.credit')) @section('meta_title', ctrans('texts.entity_number_placeholder', ['entity' => ctrans('texts.credit'), 'entity_number' => $credit->number]))
@push('head') @push('head')
<meta name="pdf-url" content="{{ $credit->pdf_file_path() }}"> <meta name="pdf-url" content="{{ $credit->pdf_file_path() }}">

View File

@ -22,7 +22,7 @@
<div class="sm:flex sm:items-start sm:justify-between"> <div class="sm:flex sm:items-start sm:justify-between">
<div> <div>
<h3 class="text-lg leading-6 font-medium text-gray-900"> <h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.unpaid') }} {{ ctrans('texts.invoice_number_placeholder', ['invoice' => $invoice->number])}} - {{ ctrans('texts.unpaid') }}
</h3> </h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500"> <div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p translate> <p translate>
@ -42,6 +42,18 @@
</div> </div>
</div> </div>
</form> </form>
@else
<div class="bg-white shadow sm:rounded-lg mb-4" translate>
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.invoice_number_placeholder', ['invoice' => $invoice->number])}} - {{ ctrans('texts.unpaid') }}
</h3>
</div>
</div>
</div>
</div>
@endif @endif
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">

View File

@ -5,25 +5,22 @@
@if($invoice->isPayable()) @if($invoice->isPayable())
<form action="{{ route('client.invoices.bulk') }}" method="post"> <form action="{{ route('client.invoices.bulk') }}" method="post">
@csrf @csrf
<div class="bg-white"> <div class="bg-white shadow sm:rounded-lg mb-4" translate>
<div class="px-4 py-5 sm:p-6"> <div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between"> <div class="sm:flex sm:items-start sm:justify-between">
<div> <div>
<h3 class="text-lg leading-6 font-medium text-gray-900"> <h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.unpaid') }} {{ ctrans('texts.invoice_number_placeholder', ['invoice' => $invoice->number])}} - {{ ctrans('texts.unpaid') }}
</h3> </h3>
<div class="mt-2 max-w-xl text-sm leading-5 text-gray-500"> <div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p translate> <p translate>
{{ ctrans('texts.invoice_still_unpaid') }} {{ ctrans('texts.invoice_still_unpaid') }}
<!-- This invoice is still not paid. Click the button to complete the payment. -->
</p> </p>
</div> </div>
</div> </div>
<div class="mt-5 sm:mt-0 sm:ml-6 sm:flex-shrink-0 sm:flex sm:items-center"> <div class="mt-5 sm:mt-0 sm:ml-6 sm:flex-shrink-0 sm:flex sm:items-center">
<a href="{{ route('client.invoice.show', $invoice->hashed_id) }}" class="mr-4 text-primary"> <div class="inline-flex rounded-md shadow-sm">
&#8592; {{ ctrans('texts.client_portal') }}
</a>
<div class="inline-flex items-center rounded-md shadow-sm">
<input type="hidden" name="invoices[]" value="{{ $invoice->hashed_id }}"> <input type="hidden" name="invoices[]" value="{{ $invoice->hashed_id }}">
<input type="hidden" name="action" value="payment"> <input type="hidden" name="action" value="payment">
<button class="button button-primary bg-primary">{{ ctrans('texts.pay_now') }}</button> <button class="button button-primary bg-primary">{{ ctrans('texts.pay_now') }}</button>
@ -33,6 +30,18 @@
</div> </div>
</div> </div>
</form> </form>
@else
<div class="bg-white shadow sm:rounded-lg mb-4" translate>
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.invoice_number_placeholder', ['invoice' => $invoice->number])}} - {{ ctrans('texts.unpaid') }}
</h3>
</div>
</div>
</div>
</div>
@endif @endif
<iframe src="{{ $invoice->pdf_file_path() }}" class="h-screen w-full border-0"></iframe> <iframe src="{{ $invoice->pdf_file_path() }}" class="h-screen w-full border-0"></iframe>

View File

@ -1,5 +1,5 @@
@extends('portal.ninja2020.layout.app') @extends('portal.ninja2020.layout.app')
@section('meta_title', ctrans('texts.view_quote')) @section('meta_title', ctrans('texts.entity_number_placeholder', ['entity' => ctrans('texts.quote'), 'entity_number' => $quote->number]))
@push('head') @push('head')
<meta name="pdf-url" content="{{ asset($quote->pdf_file_path()) }}"> <meta name="pdf-url" content="{{ asset($quote->pdf_file_path()) }}">

View File

@ -58,8 +58,8 @@ class ExportCsvTest extends TestCase
$merged_values = array_merge($header_invoice_values, (array)$header_item_values); $merged_values = array_merge($header_invoice_values, (array)$header_item_values);
$merged_keys = array_merge($header_invoice_keys, (array)$header_item_keys); $merged_keys = array_merge($header_invoice_keys, (array)$header_item_keys);
nlog(print_r($merged_keys, 1)); // nlog(print_r($merged_keys, 1));
nlog(print_r($merged_values, 1)); // nlog(print_r($merged_values, 1));
foreach ($merged_keys as &$key) { foreach ($merged_keys as &$key) {

View File

@ -184,8 +184,8 @@ class InvoiceTest extends TestCase
->assertStatus(302); ->assertStatus(302);
} catch (ValidationException $e) { } catch (ValidationException $e) {
$message = json_decode($e->validator->getMessageBag(), 1); $message = json_decode($e->validator->getMessageBag(), 1);
nlog('inside update invoice validator'); // nlog('inside update invoice validator');
nlog($message); // nlog($message);
$this->assertNotNull($message); $this->assertNotNull($message);
} }

View File

@ -195,7 +195,7 @@ class LoginTest extends TestCase
$arr = $response->json(); $arr = $response->json();
nlog(print_r($arr, 1)); // nlog(print_r($arr, 1));
$response->assertStatus(200); $response->assertStatus(200);
} }

View File

@ -46,14 +46,23 @@ use App\Events\Task\TaskWasCreated;
use App\Events\Task\TaskWasDeleted; use App\Events\Task\TaskWasDeleted;
use App\Events\Task\TaskWasRestored; use App\Events\Task\TaskWasRestored;
use App\Events\Task\TaskWasUpdated; use App\Events\Task\TaskWasUpdated;
use App\Events\User\UserWasArchived;
use App\Events\User\UserWasCreated;
use App\Events\User\UserWasDeleted;
use App\Events\User\UserWasRestored;
use App\Events\User\UserWasUpdated;
use App\Events\Vendor\VendorWasArchived; use App\Events\Vendor\VendorWasArchived;
use App\Events\Vendor\VendorWasCreated; use App\Events\Vendor\VendorWasCreated;
use App\Events\Vendor\VendorWasDeleted; use App\Events\Vendor\VendorWasDeleted;
use App\Events\Vendor\VendorWasRestored; use App\Events\Vendor\VendorWasRestored;
use App\Events\Vendor\VendorWasUpdated; use App\Events\Vendor\VendorWasUpdated;
use App\Http\Middleware\PasswordProtection;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Quote; use App\Models\Quote;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Tests\MockAccountData; use Tests\MockAccountData;
use Tests\TestCase; use Tests\TestCase;
@ -64,6 +73,7 @@ class EventTest extends TestCase
{ {
use MockAccountData; use MockAccountData;
use MakesHash; use MakesHash;
use DatabaseTransactions;
public function setUp() :void public function setUp() :void
{ {
@ -72,6 +82,13 @@ class EventTest extends TestCase
$this->faker = \Faker\Factory::create(); $this->faker = \Faker\Factory::create();
$this->makeTestData(); $this->makeTestData();
Model::reguard();
$this->withoutMiddleware(
ThrottleRequests::class,
PasswordProtection::class
);
} }
public function testExpenseEvents() public function testExpenseEvents()
@ -134,6 +151,7 @@ class EventTest extends TestCase
public function testVendorEvents() public function testVendorEvents()
{ {
$this->expectsEvents([ $this->expectsEvents([
VendorWasCreated::class, VendorWasCreated::class,
VendorWasUpdated::class, VendorWasUpdated::class,
@ -456,7 +474,6 @@ class EventTest extends TestCase
public function testInvoiceEvents() public function testInvoiceEvents()
{ {
/* Test fire new invoice */ /* Test fire new invoice */
$data = [ $data = [
'client_id' => $this->client->hashed_id, 'client_id' => $this->client->hashed_id,
@ -573,4 +590,85 @@ class EventTest extends TestCase
])->post('/api/v1/clients/bulk?action=delete', $data) ])->post('/api/v1/clients/bulk?action=delete', $data)
->assertStatus(200); ->assertStatus(200);
} }
public function testUserEvents()
{
$this->withoutMiddleware(PasswordProtection::class);
$this->expectsEvents([
UserWasCreated::class,
UserWasUpdated::class,
UserWasArchived::class,
UserWasRestored::class,
UserWasDeleted::class,
]);
$data = [
'first_name' => 'hey',
'last_name' => 'you',
'email' => 'bob1@good.ole.boys.com',
'company_user' => [
'is_admin' => false,
'is_owner' => false,
'permissions' => 'create_client,create_invoice',
],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
'X-API-PASSWORD' => 'ALongAndBriliantPassword',
])->post('/api/v1/users?include=company_user', $data)
->assertStatus(200);
$arr = $response->json();
$data = [
'first_name' => 'hasdasdy',
'last_name' => 'you',
'email' => 'bob1@good.ole.boys.com',
'company_user' => [
'is_admin' => false,
'is_owner' => false,
'permissions' => 'create_client,create_invoice',
],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
'X-API-PASSWORD' => 'ALongAndBriliantPassword',
])->put('/api/v1/users/' . $arr['data']['id'], $data)
->assertStatus(200);
$data = [
'ids' => [$arr['data']['id']],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
'X-API-PASSWORD' => 'ALongAndBriliantPassword',
])->post('/api/v1/users/bulk?action=archive', $data)
->assertStatus(200);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
'X-API-PASSWORD' => 'ALongAndBriliantPassword',
])->post('/api/v1/users/bulk?action=restore', $data)
->assertStatus(200);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
'X-API-PASSWORD' => 'ALongAndBriliantPassword',
])->post('/api/v1/users/bulk?action=delete', $data)
->assertStatus(200);
}
} }

View File

@ -189,6 +189,7 @@ trait MockAccountData
$this->user = User::factory()->create([ $this->user = User::factory()->create([
'account_id' => $this->account->id, 'account_id' => $this->account->id,
'confirmation_code' => $this->createDbHash(config('database.default')), 'confirmation_code' => $this->createDbHash(config('database.default')),
'email' => 'user@example.com',
]); ]);
} }