mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge branch 'v5-develop' of https://github.com/turbo124/invoiceninja into v5-develop
This commit is contained in:
commit
2497e4296d
@ -471,7 +471,7 @@ class CheckData extends Command
|
|||||||
$ii->saveQuietly();
|
$ii->saveQuietly();
|
||||||
});
|
});
|
||||||
|
|
||||||
collect([Invoice::class, Quote::class, Credit::class, PurchaseOrder::class])->each(function ($entity) {
|
collect([Invoice::class, Quote::class, Credit::class, PurchaseOrder::class, RecurringInvoice::class])->each(function ($entity) {
|
||||||
if ($entity::doesntHave('invitations')->count() > 0) {
|
if ($entity::doesntHave('invitations')->count() > 0) {
|
||||||
$entity::doesntHave('invitations')->cursor()->each(function ($entity) {
|
$entity::doesntHave('invitations')->cursor()->each(function ($entity) {
|
||||||
$client_vendor_key = 'client_id';
|
$client_vendor_key = 'client_id';
|
||||||
@ -694,7 +694,7 @@ class CheckData extends Command
|
|||||||
{
|
{
|
||||||
$this->wrong_balances = 0;
|
$this->wrong_balances = 0;
|
||||||
|
|
||||||
Client::cursor()->where('is_deleted', 0)->where('clients.updated_at', '>', now()->subDays(2))->each(function ($client) {
|
Client::query()->cursor()->where('is_deleted', 0)->where('clients.updated_at', '>', now()->subDays(2))->each(function ($client) {
|
||||||
$client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($client) {
|
$client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($client) {
|
||||||
$total_paid = $invoice->payments()
|
$total_paid = $invoice->payments()
|
||||||
->where('is_deleted', false)->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
|
->where('is_deleted', false)->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
|
||||||
@ -876,7 +876,7 @@ class CheckData extends Command
|
|||||||
$this->wrong_balances = 0;
|
$this->wrong_balances = 0;
|
||||||
$this->wrong_paid_to_dates = 0;
|
$this->wrong_paid_to_dates = 0;
|
||||||
|
|
||||||
foreach (Client::where('is_deleted', 0)->where('clients.updated_at', '>', now()->subDays(2))->cursor() as $client) {
|
foreach (Client::query()->where('is_deleted', 0)->where('clients.updated_at', '>', now()->subDays(2))->cursor() as $client) {
|
||||||
$invoice_balance = $client->invoices()->where('is_deleted', false)->whereIn('status_id', [2,3])->sum('balance');
|
$invoice_balance = $client->invoices()->where('is_deleted', false)->whereIn('status_id', [2,3])->sum('balance');
|
||||||
$ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first();
|
$ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first();
|
||||||
|
|
||||||
|
101
app/DataMapper/Analytics/RevenueTrack.php
Normal file
101
app/DataMapper/Analytics/RevenueTrack.php
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\DataMapper\Analytics;
|
||||||
|
|
||||||
|
use Turbo124\Beacon\ExampleMetric\GenericMixedMetric;
|
||||||
|
|
||||||
|
class RevenueTrack extends GenericMixedMetric
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The type of Sample.
|
||||||
|
*
|
||||||
|
* Monotonically incrementing counter
|
||||||
|
*
|
||||||
|
* - counter
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $type = 'mixed_metric';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the counter.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $name = 'app.revenue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The datetime of the counter measurement.
|
||||||
|
*
|
||||||
|
* date("Y-m-d H:i:s")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public $datetime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Client email
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $string_metric5 = 'email';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The AccountKey email
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $string_metric6 = 'key';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Product Type
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $string_metric7 = 'product';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gateway Reference
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $string_metric8 = 'gateway_reference';
|
||||||
|
|
||||||
|
public $string_metric9 = 'entity_reference';
|
||||||
|
|
||||||
|
public $string_metric10 = 'gateway_type';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The counter
|
||||||
|
* set to 1.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $int_metric1 = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount Received
|
||||||
|
*
|
||||||
|
* @var double
|
||||||
|
*/
|
||||||
|
public $double_metric2 = 0;
|
||||||
|
|
||||||
|
public function __construct($string_metric5, $string_metric6, $int_metric1, $double_metric2, $string_metric7, $string_metric8, $string_metric9, $string_metric10)
|
||||||
|
{
|
||||||
|
$this->int_metric1 = $int_metric1;
|
||||||
|
$this->double_metric2 = $double_metric2;
|
||||||
|
$this->string_metric5 = $string_metric5;
|
||||||
|
$this->string_metric6 = $string_metric6;
|
||||||
|
$this->string_metric7 = $string_metric7;
|
||||||
|
$this->string_metric8 = $string_metric8;
|
||||||
|
$this->string_metric9 = $string_metric9;
|
||||||
|
$this->string_metric10 = $string_metric10;
|
||||||
|
}
|
||||||
|
}
|
36
app/Events/Account/StripeConnectFailure.php
Normal file
36
app/Events/Account/StripeConnectFailure.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Events\Account;
|
||||||
|
|
||||||
|
use App\Models\Company;
|
||||||
|
use Illuminate\Broadcasting\Channel;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Broadcasting\PrivateChannel;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class StripeConnectFailure.
|
||||||
|
*/
|
||||||
|
class StripeConnectFailure
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
public function __construct(public Company $company, public string $db)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function broadcastOn()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
@ -88,6 +88,11 @@ class CreditFilters extends QueryFilters
|
|||||||
->orWhere('credits.custom_value4', 'like', '%'.$filter.'%')
|
->orWhere('credits.custom_value4', 'like', '%'.$filter.'%')
|
||||||
->orWhereHas('client', function ($q) use ($filter) {
|
->orWhereHas('client', function ($q) use ($filter) {
|
||||||
$q->where('name', 'like', '%'.$filter.'%');
|
$q->where('name', 'like', '%'.$filter.'%');
|
||||||
|
})
|
||||||
|
->orWhereHas('client.contacts', function ($q) use ($filter) {
|
||||||
|
$q->where('first_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,11 @@ class InvoiceFilters extends QueryFilters
|
|||||||
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
||||||
->orWhereHas('client', function ($q) use ($filter) {
|
->orWhereHas('client', function ($q) use ($filter) {
|
||||||
$q->where('name', 'like', '%'.$filter.'%');
|
$q->where('name', 'like', '%'.$filter.'%');
|
||||||
|
})
|
||||||
|
->orWhereHas('client.contacts', function ($q) use ($filter) {
|
||||||
|
$q->where('first_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,12 @@ class PaymentFilters extends QueryFilters
|
|||||||
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
||||||
->orWhereHas('client', function ($q) use ($filter) {
|
->orWhereHas('client', function ($q) use ($filter) {
|
||||||
$q->where('name', 'like', '%'.$filter.'%');
|
$q->where('name', 'like', '%'.$filter.'%');
|
||||||
});
|
})
|
||||||
|
->orWhereHas('client.contacts', function ($q) use ($filter) {
|
||||||
|
$q->where('first_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,12 @@ class QuoteFilters extends QueryFilters
|
|||||||
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
||||||
->orWhereHas('client', function ($q) use ($filter) {
|
->orWhereHas('client', function ($q) use ($filter) {
|
||||||
$q->where('name', 'like', '%'.$filter.'%');
|
$q->where('name', 'like', '%'.$filter.'%');
|
||||||
});
|
})
|
||||||
|
->orWhereHas('client.contacts', function ($q) use ($filter) {
|
||||||
|
$q->where('first_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,12 @@ class RecurringInvoiceFilters extends QueryFilters
|
|||||||
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
||||||
->orWhereHas('client', function ($q) use ($filter) {
|
->orWhereHas('client', function ($q) use ($filter) {
|
||||||
$q->where('name', 'like', '%'.$filter.'%');
|
$q->where('name', 'like', '%'.$filter.'%');
|
||||||
});
|
})
|
||||||
|
->orWhereHas('client.contacts', function ($q) use ($filter) {
|
||||||
|
$q->where('first_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,12 @@ class TaskFilters extends QueryFilters
|
|||||||
})
|
})
|
||||||
->orWhereHas('client', function ($q) use ($filter) {
|
->orWhereHas('client', function ($q) use ($filter) {
|
||||||
$q->where('name', 'like', '%'.$filter.'%');
|
$q->where('name', 'like', '%'.$filter.'%');
|
||||||
});
|
})
|
||||||
|
->orWhereHas('client.contacts', function ($q) use ($filter) {
|
||||||
|
$q->where('first_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +162,9 @@ class InvoiceController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function create(CreateInvoiceRequest $request)
|
public function create(CreateInvoiceRequest $request)
|
||||||
{
|
{
|
||||||
$invoice = InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
$invoice = InvoiceFactory::create($user->company()->id, $user->id);
|
||||||
|
|
||||||
return $this->itemResponse($invoice);
|
return $this->itemResponse($invoice);
|
||||||
}
|
}
|
||||||
@ -211,7 +213,11 @@ class InvoiceController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function store(StoreInvoiceRequest $request)
|
public function store(StoreInvoiceRequest $request)
|
||||||
{
|
{
|
||||||
$invoice = $this->invoice_repo->save($request->all(), InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
$invoice = $this->invoice_repo->save($request->all(), InvoiceFactory::create($user->company()->id, $user->id));
|
||||||
|
|
||||||
$invoice = $invoice->service()
|
$invoice = $invoice->service()
|
||||||
->fillDefaults()
|
->fillDefaults()
|
||||||
@ -219,7 +225,7 @@ class InvoiceController extends BaseController
|
|||||||
->adjustInventory()
|
->adjustInventory()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars($user ? $user->id : null)));
|
||||||
|
|
||||||
$transaction = [
|
$transaction = [
|
||||||
'invoice' => $invoice->transaction_event(),
|
'invoice' => $invoice->transaction_event(),
|
||||||
@ -473,62 +479,17 @@ class InvoiceController extends BaseController
|
|||||||
return $this->itemResponse($invoice->fresh());
|
return $this->itemResponse($invoice->fresh());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform bulk actions on the list view.
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Support\Collection
|
|
||||||
*
|
|
||||||
* @OA\Post(
|
|
||||||
* path="/api/v1/invoices/bulk",
|
|
||||||
* operationId="bulkInvoices",
|
|
||||||
* tags={"invoices"},
|
|
||||||
* summary="Performs bulk actions on an array of invoices",
|
|
||||||
* description="",
|
|
||||||
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
|
|
||||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
|
||||||
* @OA\Parameter(ref="#/components/parameters/index"),
|
|
||||||
* @OA\RequestBody(
|
|
||||||
* description="User credentials",
|
|
||||||
* required=true,
|
|
||||||
* @OA\MediaType(
|
|
||||||
* mediaType="application/json",
|
|
||||||
* @OA\Schema(
|
|
||||||
* type="array",
|
|
||||||
* @OA\Items(
|
|
||||||
* type="integer",
|
|
||||||
* description="Array of hashed IDs to be bulk 'actioned",
|
|
||||||
* example="[0,1,2,3]",
|
|
||||||
* ),
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* ),
|
|
||||||
* @OA\Response(
|
|
||||||
* response=200,
|
|
||||||
* description="The Bulk Action response",
|
|
||||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
|
||||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
|
||||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
|
||||||
* ),
|
|
||||||
* @OA\Response(
|
|
||||||
* response=422,
|
|
||||||
* description="Validation error",
|
|
||||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
|
||||||
|
|
||||||
* ),
|
|
||||||
* @OA\Response(
|
|
||||||
* response="default",
|
|
||||||
* description="Unexpected Error",
|
|
||||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
|
||||||
* ),
|
|
||||||
* )
|
|
||||||
*/
|
|
||||||
public function bulk(BulkInvoiceRequest $request)
|
public function bulk(BulkInvoiceRequest $request)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
$action = $request->input('action');
|
$action = $request->input('action');
|
||||||
|
|
||||||
$ids = $request->input('ids');
|
$ids = $request->input('ids');
|
||||||
|
|
||||||
if (Ninja::isHosted() && (stripos($action, 'email') !== false) && !auth()->user()->company()->account->account_sms_verified) {
|
if (Ninja::isHosted() && (stripos($action, 'email') !== false) && !$user->company()->account->account_sms_verified) {
|
||||||
return response(['message' => 'Please verify your account to send emails.'], 400);
|
return response(['message' => 'Please verify your account to send emails.'], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,8 +504,8 @@ class InvoiceController extends BaseController
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if ($action == 'bulk_download' && $invoices->count() > 1) {
|
if ($action == 'bulk_download' && $invoices->count() > 1) {
|
||||||
$invoices->each(function ($invoice) {
|
$invoices->each(function ($invoice) use($user) {
|
||||||
if (auth()->user()->cannot('view', $invoice)) {
|
if ($user->cannot('view', $invoice)) {
|
||||||
nlog('access denied');
|
nlog('access denied');
|
||||||
|
|
||||||
return response()->json(['message' => ctrans('text.access_denied')]);
|
return response()->json(['message' => ctrans('text.access_denied')]);
|
||||||
@ -556,7 +517,7 @@ class InvoiceController extends BaseController
|
|||||||
return response()->json(['message' => ctrans('texts.sent_message')], 200);
|
return response()->json(['message' => ctrans('texts.sent_message')], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($action == 'download' && $invoices->count() >=1 && auth()->user()->can('view', $invoices->first())) {
|
if ($action == 'download' && $invoices->count() >=1 && $user->can('view', $invoices->first())) {
|
||||||
$file = $invoices->first()->service()->getInvoicePdf();
|
$file = $invoices->first()->service()->getInvoicePdf();
|
||||||
|
|
||||||
return response()->streamDownload(function () use ($file) {
|
return response()->streamDownload(function () use ($file) {
|
||||||
@ -564,7 +525,7 @@ class InvoiceController extends BaseController
|
|||||||
}, basename($file), ['Content-Type' => 'application/pdf']);
|
}, basename($file), ['Content-Type' => 'application/pdf']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($action == 'bulk_print' && auth()->user()->can('view', $invoices->first())) {
|
if ($action == 'bulk_print' && $user->can('view', $invoices->first())) {
|
||||||
$paths = $invoices->map(function ($invoice) {
|
$paths = $invoices->map(function ($invoice) {
|
||||||
return $invoice->service()->getInvoicePdf();
|
return $invoice->service()->getInvoicePdf();
|
||||||
});
|
});
|
||||||
@ -579,15 +540,15 @@ class InvoiceController extends BaseController
|
|||||||
/*
|
/*
|
||||||
* Send the other actions to the switch
|
* Send the other actions to the switch
|
||||||
*/
|
*/
|
||||||
$invoices->each(function ($invoice, $key) use ($action) {
|
$invoices->each(function ($invoice, $key) use ($action, $user) {
|
||||||
if (auth()->user()->can('edit', $invoice)) {
|
if ($user->can('edit', $invoice)) {
|
||||||
$this->performAction($invoice, $action, true);
|
$this->performAction($invoice, $action, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
||||||
|
|
||||||
return $this->listResponse(Invoice::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
return $this->listResponse(Invoice::query()->withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1005,16 +966,17 @@ class InvoiceController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function upload(UploadInvoiceRequest $request, Invoice $invoice)
|
public function upload(UploadInvoiceRequest $request, Invoice $invoice)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (! $this->checkFeature(Account::FEATURE_DOCUMENTS)) {
|
if (! $this->checkFeature(Account::FEATURE_DOCUMENTS)) {
|
||||||
return $this->featureFailure();
|
return $this->featureFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->has('documents')) {
|
if ($request->has('documents')) {
|
||||||
$this->saveDocuments($request->file('documents'), $invoice);
|
$this->saveDocuments($request->file('documents'), $invoice, $request->input('is_public', true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->has('file')) {
|
if ($request->has('file')) {
|
||||||
$this->saveDocuments($request->file('documents'), $invoice);
|
$this->saveDocuments($request->file('documents'), $invoice, $request->input('is_public', true));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->itemResponse($invoice->fresh());
|
return $this->itemResponse($invoice->fresh());
|
||||||
@ -1022,7 +984,10 @@ class InvoiceController extends BaseController
|
|||||||
|
|
||||||
public function update_reminders(UpdateReminderRequest $request)
|
public function update_reminders(UpdateReminderRequest $request)
|
||||||
{
|
{
|
||||||
UpdateReminders::dispatch(auth()->user()->company());
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
UpdateReminders::dispatch($user->company());
|
||||||
|
|
||||||
return response()->json(['message' => 'Updating reminders'], 200);
|
return response()->json(['message' => 'Updating reminders'], 200);
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,11 @@ class BillingPortalPurchase extends Component
|
|||||||
public $password;
|
public $password;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of subscription.
|
* This arrives as an int and we resolve in the mount method
|
||||||
*
|
*
|
||||||
* @var \App\Models\Subscription $subscription
|
* @var int|Subscription
|
||||||
*/
|
*/
|
||||||
public Subscription $subscription;
|
public $subscription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of client contact.
|
* Instance of client contact.
|
||||||
|
@ -121,6 +121,7 @@ class PdfSlot extends Component
|
|||||||
|
|
||||||
$this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_columns);
|
$this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_columns);
|
||||||
$this->show_line_total = in_array('$product.line_total', $this->settings->pdf_variables->product_columns);
|
$this->show_line_total = in_array('$product.line_total', $this->settings->pdf_variables->product_columns);
|
||||||
|
$this->show_quantity = in_array('$product.quantity', $this->settings->pdf_variables->product_columns);
|
||||||
|
|
||||||
if($this->entity_type == 'quote' && !$this->settings->sync_invoice_quote_columns ){
|
if($this->entity_type == 'quote' && !$this->settings->sync_invoice_quote_columns ){
|
||||||
$this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_quote_columns);
|
$this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_quote_columns);
|
||||||
|
@ -23,7 +23,9 @@ class UploadInvoiceRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function authorize() : bool
|
public function authorize() : bool
|
||||||
{
|
{
|
||||||
return auth()->user()->can('edit', $this->invoice);
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
return $user->can('edit', $this->invoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rules()
|
public function rules()
|
||||||
@ -42,6 +44,8 @@ class UploadInvoiceRequest extends Request
|
|||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->file_validation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ class Request extends FormRequest
|
|||||||
use MakesHash;
|
use MakesHash;
|
||||||
use RuntimeFormRequest;
|
use RuntimeFormRequest;
|
||||||
|
|
||||||
protected $file_validation = 'sometimes|file|mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx,webp|max:20000';
|
protected $file_validation = 'sometimes|file|mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx,webp,xml|max:20000';
|
||||||
/**
|
/**
|
||||||
* Get the validation rules that apply to the request.
|
* Get the validation rules that apply to the request.
|
||||||
*
|
*
|
||||||
|
@ -36,10 +36,10 @@ class UserEmailChanged implements ShouldQueue
|
|||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
*
|
*
|
||||||
* @param \App\Models\User $new_user
|
* @param \App\Models\User $new_user
|
||||||
* @param \App\Models\User $old_user
|
* @param \stdClass $old_user
|
||||||
* @param \App\Models\Company $company
|
* @param \App\Models\Company $company
|
||||||
*/
|
*/
|
||||||
public function __construct(protected User $new_user, protected User $old_user, protected Company $company)
|
public function __construct(protected User $new_user, protected \stdClass $old_user, protected Company $company)
|
||||||
{
|
{
|
||||||
$this->settings = $this->company->settings;
|
$this->settings = $this->company->settings;
|
||||||
}
|
}
|
||||||
|
@ -1821,7 +1821,7 @@ class Import implements ShouldQueue
|
|||||||
|
|
||||||
private function processActivities(array $data): void
|
private function processActivities(array $data): void
|
||||||
{
|
{
|
||||||
Activity::where('company_id', $this->company->id)->cursor()->each(function ($a){
|
Activity::query()->where('company_id', $this->company->id)->cursor()->each(function ($a){
|
||||||
$a->forceDelete();
|
$a->forceDelete();
|
||||||
nlog("deleting {$a->id}");
|
nlog("deleting {$a->id}");
|
||||||
});
|
});
|
||||||
|
@ -53,7 +53,7 @@ class UploadFile implements ShouldQueue
|
|||||||
|
|
||||||
public $disk;
|
public $disk;
|
||||||
|
|
||||||
public function __construct($file, $type, $user, $company, $entity, $disk = null, $is_public = false)
|
public function __construct($file, $type, $user, $company, $entity, $disk = null, $is_public = true)
|
||||||
{
|
{
|
||||||
$this->file = $file;
|
$this->file = $file;
|
||||||
$this->type = $type;
|
$this->type = $type;
|
||||||
|
57
app/Listeners/Account/StripeConnectFailureListener.php
Normal file
57
app/Listeners/Account/StripeConnectFailureListener.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Listeners\Account;
|
||||||
|
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use App\Jobs\Mail\NinjaMailerJob;
|
||||||
|
use App\Jobs\Mail\NinjaMailerObject;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use App\Mail\Ninja\StripeConnectFailed;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
|
||||||
|
class StripeConnectFailureListener implements ShouldQueue
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param object $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle($event)
|
||||||
|
{
|
||||||
|
MultiDB::setDb($event->db);
|
||||||
|
|
||||||
|
if (Ninja::isHosted() && is_null(Cache::get("stripe_connect_notification:{$event->company->company_key}")))
|
||||||
|
{
|
||||||
|
|
||||||
|
$nmo = new NinjaMailerObject();
|
||||||
|
$nmo->mailable = new StripeConnectFailed($event->company->owner(), $event->company);
|
||||||
|
$nmo->company = $event->company;
|
||||||
|
$nmo->settings = $event->company->settings;
|
||||||
|
$nmo->to_user = $event->company->owner();
|
||||||
|
|
||||||
|
NinjaMailerJob::dispatch($nmo, true);
|
||||||
|
|
||||||
|
Cache::put("stripe_connect_notification:{$event->company->company_key}", true, 60 * 60 * 24);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,7 @@ class PaymentCreatedActivity implements ShouldQueue
|
|||||||
{
|
{
|
||||||
protected $activity_repo;
|
protected $activity_repo;
|
||||||
|
|
||||||
|
public $delay = 5;
|
||||||
/**
|
/**
|
||||||
* Create the event listener.
|
* Create the event listener.
|
||||||
*
|
*
|
||||||
|
@ -21,6 +21,8 @@ class InvoicePaidActivity implements ShouldQueue
|
|||||||
{
|
{
|
||||||
protected $activity_repo;
|
protected $activity_repo;
|
||||||
|
|
||||||
|
public $delay = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the event listener.
|
* Create the event listener.
|
||||||
*
|
*
|
||||||
|
@ -11,14 +11,16 @@
|
|||||||
|
|
||||||
namespace App\Listeners\Payment;
|
namespace App\Listeners\Payment;
|
||||||
|
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Jobs\Mail\NinjaMailer;
|
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\Libraries\MultiDB;
|
|
||||||
use App\Mail\Admin\EntityPaidObject;
|
use App\Mail\Admin\EntityPaidObject;
|
||||||
use App\Utils\Ninja;
|
use Turbo124\Beacon\Facades\LightLogs;
|
||||||
use App\Utils\Traits\Notifications\UserNotifies;
|
use App\DataMapper\Analytics\RevenueTrack;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use App\Utils\Traits\Notifications\UserNotifies;
|
||||||
|
|
||||||
class PaymentNotification implements ShouldQueue
|
class PaymentNotification implements ShouldQueue
|
||||||
{
|
{
|
||||||
@ -158,6 +160,15 @@ class PaymentNotification implements ShouldQueue
|
|||||||
|
|
||||||
$url = $base."&t=item&in={$item}&ip={$amount}&iq=1";
|
$url = $base."&t=item&in={$item}&ip={$amount}&iq=1";
|
||||||
$this->sendAnalytics($url);
|
$this->sendAnalytics($url);
|
||||||
|
|
||||||
|
$email = $client->present()->email();
|
||||||
|
$account_key = $client->custom_value2 ?? 'unknown';
|
||||||
|
$product = $item;
|
||||||
|
$gateway_reference = $client->gateway_tokens()->count() >= 1 ? ($client->gateway_tokens()->first()->gateway_customer_reference ?? '') : '';
|
||||||
|
|
||||||
|
// LightLogs::create(new RevenueTrack($email, $account_key, 1, $amount, $product, $gateway_reference, $entity_number))
|
||||||
|
// ->batch();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
114
app/Mail/Ninja/StripeConnectFailed.php
Normal file
114
app/Mail/Ninja/StripeConnectFailed.php
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Mail\Ninja;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\Company;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Headers;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
|
||||||
|
class StripeConnectFailed extends Mailable
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(public User $user, public Company $company)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Envelope
|
||||||
|
*/
|
||||||
|
public function envelope()
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: "Stripe Connect not configured, please login and connect.",
|
||||||
|
from: "maildelivery@invoicing.co",
|
||||||
|
to: $this->user->email,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Content
|
||||||
|
*/
|
||||||
|
public function content()
|
||||||
|
{
|
||||||
|
|
||||||
|
return new Content(
|
||||||
|
view: 'email.admin.stripe_connect_failed',
|
||||||
|
text: 'email.admin.stripe_connect_failed_text',
|
||||||
|
with: [
|
||||||
|
'text_body' => $this->textBody(), //@todo this is a bit hacky here.
|
||||||
|
'body' => $this->htmlBody(),
|
||||||
|
'title' => 'Connect your Stripe account',
|
||||||
|
'settings' => $this->company->settings,
|
||||||
|
'logo' => $this->company->present()->logo(),
|
||||||
|
'signature' => '',
|
||||||
|
'company' => $this->company,
|
||||||
|
'greeting' => '',
|
||||||
|
'links' => [],
|
||||||
|
'url' => 'https://www.loom.com/share/a3dc3131cc924e14a34634d5d48065c8?sid=b1971aa2-9deb-4339-8ebd-53f9947ef633',
|
||||||
|
'button' => "texts.view"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function textBody()
|
||||||
|
{
|
||||||
|
return "
|
||||||
|
We note you are yet to connect your Stripe account to Invoice Ninja. Please log in to Invoice Ninja and connect your Stripe account.\n\n
|
||||||
|
Once logged in you can use the following resource to connect your Stripe account: \n\n
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
private function htmlBody()
|
||||||
|
{
|
||||||
|
return "
|
||||||
|
We note you are yet to connect your Stripe account to Invoice Ninja. Please log in to Invoice Ninja and connect your Stripe account.<br><br>
|
||||||
|
|
||||||
|
Once logged in you can use the following resource to connect your Stripe account: <br><br>
|
||||||
|
|
||||||
|
";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get the attachments for the message.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function attachments()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message headers.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Headers
|
||||||
|
*/
|
||||||
|
public function headers()
|
||||||
|
{
|
||||||
|
return new Headers(
|
||||||
|
messageId: null,
|
||||||
|
references: [],
|
||||||
|
text:['' => ''],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -707,6 +707,7 @@ class Company extends BaseModel
|
|||||||
|
|
||||||
public function getSetting($setting)
|
public function getSetting($setting)
|
||||||
{
|
{
|
||||||
|
//todo $this->setting ?? false
|
||||||
if (property_exists($this->settings, $setting) != false) {
|
if (property_exists($this->settings, $setting) != false) {
|
||||||
return $this->settings->{$setting};
|
return $this->settings->{$setting};
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
* @property string $hash
|
* @property string $hash
|
||||||
* @property float $fee_total
|
* @property float $fee_total
|
||||||
* @property int|null $fee_invoice_id
|
* @property int|null $fee_invoice_id
|
||||||
* @property mixed $data
|
* @property \stdClass $data
|
||||||
* @property int|null $payment_id
|
* @property int|null $payment_id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
@ -38,9 +38,16 @@ class PaymentHash extends Model
|
|||||||
'data' => 'object',
|
'data' => 'object',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class \App\Models\PaymentHash $this
|
||||||
|
* @property \App\Models\PaymentHash $data
|
||||||
|
* @class \stdClass $data
|
||||||
|
* @property string $raw_value
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function invoices()
|
public function invoices()
|
||||||
{
|
{
|
||||||
@ -75,9 +82,8 @@ class PaymentHash extends Model
|
|||||||
|
|
||||||
public function withData(string $property, $value): self
|
public function withData(string $property, $value): self
|
||||||
{
|
{
|
||||||
$this->data = array_merge((array) $this->data, [$property => $value]);
|
$this->data = array_merge((array) $this->data, [$property => $value]); // @phpstan-ignore-line
|
||||||
$this->save();
|
$this->save();// @phpstan-ignore-line
|
||||||
|
return $this; // @phpstan-ignore-line
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,9 +230,9 @@ class Vendor extends BaseModel
|
|||||||
* Returns a vendor settings proxying company setting
|
* Returns a vendor settings proxying company setting
|
||||||
*
|
*
|
||||||
* @param string $setting
|
* @param string $setting
|
||||||
* @return string
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getSetting($setting): string
|
public function getSetting($setting): mixed
|
||||||
{
|
{
|
||||||
if ((property_exists($this->company->settings, $setting) != false) && (isset($this->company->settings->{$setting}) !== false)) {
|
if ((property_exists($this->company->settings, $setting) != false) && (isset($this->company->settings->{$setting}) !== false)) {
|
||||||
return $this->company->settings->{$setting};
|
return $this->company->settings->{$setting};
|
||||||
|
@ -69,7 +69,7 @@ class CheckoutWebhook implements ShouldQueue
|
|||||||
{
|
{
|
||||||
$payment_object = $this->webhook_array['data'];
|
$payment_object = $this->webhook_array['data'];
|
||||||
|
|
||||||
$payment = Payment::withTrashed()->where('transaction_reference', $payment_object['id'])->first();
|
$payment = Payment::query()->withTrashed()->where('transaction_reference', $payment_object['id'])->first();
|
||||||
|
|
||||||
if($payment && $payment->status_id == Payment::STATUS_COMPLETED)
|
if($payment && $payment->status_id == Payment::STATUS_COMPLETED)
|
||||||
return;
|
return;
|
||||||
@ -84,18 +84,19 @@ class CheckoutWebhook implements ShouldQueue
|
|||||||
|
|
||||||
$metadata = $this->webhook_array['metadata'];
|
$metadata = $this->webhook_array['metadata'];
|
||||||
|
|
||||||
$payment_hash = PaymentHash::where('hash', $metadata['udf2'])->first();
|
$payment_hash = PaymentHash::query()->where('hash', $metadata['udf2'])->first();
|
||||||
|
|
||||||
$driver = $this->company_gateway->driver($payment_hash->fee_invoice->client)->init()->setPaymentMethod();
|
$driver = $this->company_gateway->driver($payment_hash->fee_invoice->client)->init()->setPaymentMethod();
|
||||||
|
|
||||||
$payment_hash->data = array_merge((array) $payment_hash->data, $this->webhook_array);
|
$payment_hash->data = array_merge((array) $payment_hash->data, $this->webhook_array); // @phpstan-ignore-line
|
||||||
$payment_hash->save();
|
$payment_hash->save();
|
||||||
$driver->setPaymentHash($payment_hash);
|
$driver->setPaymentHash($payment_hash);
|
||||||
|
|
||||||
|
// @phpstan-ignore-line
|
||||||
$data = [
|
$data = [
|
||||||
'payment_method' => isset($this->webhook_array['source']['id']) ? $this->webhook_array['source']['id'] : '',
|
'payment_method' => isset($this->webhook_array['source']['id']) ? $this->webhook_array['source']['id'] : '',
|
||||||
'payment_type' => PaymentType::CREDIT_CARD_OTHER,
|
'payment_type' => PaymentType::CREDIT_CARD_OTHER,
|
||||||
'amount' => $payment_hash->data->raw_value,
|
'amount' => $payment_hash->data->raw_value, // @phpstan-ignore-line
|
||||||
'transaction_reference' => $payment_object['id'],
|
'transaction_reference' => $payment_object['id'],
|
||||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||||
];
|
];
|
||||||
|
@ -66,8 +66,6 @@ class Webhook
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists the workflows in Checkout
|
* Lists the workflows in Checkout
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function getWorkFlows()
|
public function getWorkFlows()
|
||||||
{
|
{
|
||||||
|
@ -94,6 +94,7 @@ use App\Events\Misc\InvitationWasViewed;
|
|||||||
use App\Events\Payment\PaymentWasVoided;
|
use App\Events\Payment\PaymentWasVoided;
|
||||||
use App\Events\Vendor\VendorWasArchived;
|
use App\Events\Vendor\VendorWasArchived;
|
||||||
use App\Events\Vendor\VendorWasRestored;
|
use App\Events\Vendor\VendorWasRestored;
|
||||||
|
use App\Events\Account\StripeConnectFailure;
|
||||||
use App\Listeners\Mail\MailSentListener;
|
use App\Listeners\Mail\MailSentListener;
|
||||||
use App\Observers\ClientContactObserver;
|
use App\Observers\ClientContactObserver;
|
||||||
use App\Observers\PurchaseOrderObserver;
|
use App\Observers\PurchaseOrderObserver;
|
||||||
@ -198,6 +199,8 @@ use App\Listeners\Invoice\InvoiceRestoredActivity;
|
|||||||
use App\Listeners\Invoice\InvoiceReversedActivity;
|
use App\Listeners\Invoice\InvoiceReversedActivity;
|
||||||
use App\Listeners\Payment\PaymentRestoredActivity;
|
use App\Listeners\Payment\PaymentRestoredActivity;
|
||||||
use App\Listeners\Quote\QuoteApprovedNotification;
|
use App\Listeners\Quote\QuoteApprovedNotification;
|
||||||
|
use SocialiteProviders\Apple\AppleExtendSocialite;
|
||||||
|
use SocialiteProviders\Manager\SocialiteWasCalled;
|
||||||
use App\Events\Subscription\SubscriptionWasCreated;
|
use App\Events\Subscription\SubscriptionWasCreated;
|
||||||
use App\Events\Subscription\SubscriptionWasDeleted;
|
use App\Events\Subscription\SubscriptionWasDeleted;
|
||||||
use App\Events\Subscription\SubscriptionWasUpdated;
|
use App\Events\Subscription\SubscriptionWasUpdated;
|
||||||
@ -221,10 +224,12 @@ use App\Listeners\Invoice\InvoiceEmailFailedActivity;
|
|||||||
use App\Events\PurchaseOrder\PurchaseOrderWasAccepted;
|
use App\Events\PurchaseOrder\PurchaseOrderWasAccepted;
|
||||||
use App\Events\PurchaseOrder\PurchaseOrderWasArchived;
|
use App\Events\PurchaseOrder\PurchaseOrderWasArchived;
|
||||||
use App\Events\PurchaseOrder\PurchaseOrderWasRestored;
|
use App\Events\PurchaseOrder\PurchaseOrderWasRestored;
|
||||||
|
use App\Listeners\Payment\PaymentEmailFailureActivity;
|
||||||
use App\Listeners\Vendor\UpdateVendorContactLastLogin;
|
use App\Listeners\Vendor\UpdateVendorContactLastLogin;
|
||||||
use App\Events\RecurringQuote\RecurringQuoteWasCreated;
|
use App\Events\RecurringQuote\RecurringQuoteWasCreated;
|
||||||
use App\Events\RecurringQuote\RecurringQuoteWasDeleted;
|
use App\Events\RecurringQuote\RecurringQuoteWasDeleted;
|
||||||
use App\Events\RecurringQuote\RecurringQuoteWasUpdated;
|
use App\Events\RecurringQuote\RecurringQuoteWasUpdated;
|
||||||
|
use App\Listeners\Account\StripeConnectFailureListener;
|
||||||
use App\Listeners\Activity\CreatedSubscriptionActivity;
|
use App\Listeners\Activity\CreatedSubscriptionActivity;
|
||||||
use App\Listeners\Activity\SubscriptionDeletedActivity;
|
use App\Listeners\Activity\SubscriptionDeletedActivity;
|
||||||
use App\Listeners\Activity\SubscriptionUpdatedActivity;
|
use App\Listeners\Activity\SubscriptionUpdatedActivity;
|
||||||
@ -234,6 +239,7 @@ use App\Events\RecurringQuote\RecurringQuoteWasRestored;
|
|||||||
use App\Listeners\Activity\SubscriptionArchivedActivity;
|
use App\Listeners\Activity\SubscriptionArchivedActivity;
|
||||||
use App\Listeners\Activity\SubscriptionRestoredActivity;
|
use App\Listeners\Activity\SubscriptionRestoredActivity;
|
||||||
use App\Listeners\Invoice\InvoiceFailedEmailNotification;
|
use App\Listeners\Invoice\InvoiceFailedEmailNotification;
|
||||||
|
use SocialiteProviders\Microsoft\MicrosoftExtendSocialite;
|
||||||
use App\Events\RecurringExpense\RecurringExpenseWasCreated;
|
use App\Events\RecurringExpense\RecurringExpenseWasCreated;
|
||||||
use App\Events\RecurringExpense\RecurringExpenseWasDeleted;
|
use App\Events\RecurringExpense\RecurringExpenseWasDeleted;
|
||||||
use App\Events\RecurringExpense\RecurringExpenseWasUpdated;
|
use App\Events\RecurringExpense\RecurringExpenseWasUpdated;
|
||||||
@ -587,6 +593,9 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
TaskWasRestored::class => [
|
TaskWasRestored::class => [
|
||||||
TaskRestoredActivity::class,
|
TaskRestoredActivity::class,
|
||||||
],
|
],
|
||||||
|
StripeConnectFailure::class => [
|
||||||
|
StripeConnectFailureListener::class,
|
||||||
|
],
|
||||||
SubscriptionWasCreated::class => [
|
SubscriptionWasCreated::class => [
|
||||||
CreatedSubscriptionActivity::class,
|
CreatedSubscriptionActivity::class,
|
||||||
],
|
],
|
||||||
|
@ -136,7 +136,11 @@ class InvoiceMigrationRepository extends BaseRepository
|
|||||||
|
|
||||||
$state['finished_amount'] = $model->amount;
|
$state['finished_amount'] = $model->amount;
|
||||||
|
|
||||||
$model = $model->service()->applyNumber()->setReminder()->save();
|
$model = $model->service()->applyNumber()->save();
|
||||||
|
|
||||||
|
if ($class->name == Invoice::class) {
|
||||||
|
$model->service()->setReminder()->save();
|
||||||
|
}
|
||||||
|
|
||||||
if ($class->name == Invoice::class || $class->name == RecurringInvoice::class) {
|
if ($class->name == Invoice::class || $class->name == RecurringInvoice::class) {
|
||||||
if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) {
|
if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) {
|
||||||
|
@ -57,7 +57,7 @@ class PurchaseOrderExpense
|
|||||||
|
|
||||||
$expense->number = empty($expense->number) ? $this->getNextExpenseNumber($expense) : $expense->number;
|
$expense->number = empty($expense->number) ? $this->getNextExpenseNumber($expense) : $expense->number;
|
||||||
|
|
||||||
$expense->save();
|
$expense->saveQuietly();
|
||||||
event('eloquent.created: App\Models\Expense', $expense);
|
event('eloquent.created: App\Models\Expense', $expense);
|
||||||
|
|
||||||
$this->purchase_order->expense_id = $expense->id;
|
$this->purchase_order->expense_id = $expense->id;
|
||||||
|
@ -20,11 +20,8 @@ class PurchaseOrderService
|
|||||||
{
|
{
|
||||||
use MakesHash;
|
use MakesHash;
|
||||||
|
|
||||||
public PurchaseOrder $purchase_order;
|
public function __construct(public PurchaseOrder $purchase_order)
|
||||||
|
|
||||||
public function __construct(PurchaseOrder $purchase_order)
|
|
||||||
{
|
{
|
||||||
$this->purchase_order = $purchase_order;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createInvitations()
|
public function createInvitations()
|
||||||
@ -156,7 +153,7 @@ class PurchaseOrderService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the purchase order.
|
* Saves the purchase order.
|
||||||
* @return \App\Models\PurchaseOrder object
|
* @return \App\Models\PurchaseOrder
|
||||||
*/
|
*/
|
||||||
public function save(): ?PurchaseOrder
|
public function save(): ?PurchaseOrder
|
||||||
{
|
{
|
||||||
|
@ -52,8 +52,8 @@ class TemplateEngine
|
|||||||
|
|
||||||
public $template;
|
public $template;
|
||||||
|
|
||||||
/** @var \App\Models\Invoice | \App\Models\Quote | \App\Models\Credit | \App\Models\PurchaseOrder | \App\Models\RecurringInvoice $entity_obj **/
|
/** @var \App\Models\Invoice | \App\Models\Quote | \App\Models\Credit | \App\Models\PurchaseOrder | \App\Models\RecurringInvoice | \App\Models\Payment $entity_obj **/
|
||||||
private \App\Models\Invoice | \App\Models\Quote | \App\Models\Credit | \App\Models\PurchaseOrder | \App\Models\RecurringInvoice $entity_obj;
|
private \App\Models\Invoice | \App\Models\Quote | \App\Models\Credit | \App\Models\PurchaseOrder | \App\Models\RecurringInvoice | \App\Models\Payment $entity_obj;
|
||||||
|
|
||||||
/** @var \App\Models\Company | \App\Models\Client | null $settings_entity **/
|
/** @var \App\Models\Company | \App\Models\Client | null $settings_entity **/
|
||||||
private $settings_entity;
|
private $settings_entity;
|
||||||
|
743
composer.lock
generated
743
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -22,8 +22,8 @@ return [
|
|||||||
*/
|
*/
|
||||||
'batch' => true,
|
'batch' => true,
|
||||||
|
|
||||||
'cache_connection' => 'sentinel-cache',
|
'cache_connection' => 'sentinel-cache',
|
||||||
|
// 'cache_connection' => 'cache',
|
||||||
/*
|
/*
|
||||||
* The default key used to store
|
* The default key used to store
|
||||||
* metrics for batching
|
* metrics for batching
|
||||||
|
@ -8,6 +8,7 @@ parameters:
|
|||||||
excludePaths:
|
excludePaths:
|
||||||
- 'vendor/'
|
- 'vendor/'
|
||||||
- 'app/Jobs/Ninja/*'
|
- 'app/Jobs/Ninja/*'
|
||||||
|
- 'app/Models/Presenters/*'
|
||||||
- 'app/Console/Commands/*'
|
- 'app/Console/Commands/*'
|
||||||
- 'app/DataMapper/Analytics/*'
|
- 'app/DataMapper/Analytics/*'
|
||||||
- 'app/PaymentDrivers/Authorize/*'
|
- 'app/PaymentDrivers/Authorize/*'
|
||||||
@ -17,10 +18,7 @@ parameters:
|
|||||||
- App\DataMapper\FeesAndLimits
|
- App\DataMapper\FeesAndLimits
|
||||||
reportUnmatchedIgnoredErrors: false
|
reportUnmatchedIgnoredErrors: false
|
||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
- '#Call to an undefined method [a-zA-Z0-9\\_]+::company\(\)#'
|
|
||||||
- '#Call to an undefined method [a-zA-Z0-9\\_]+::entityFilter\(\)#'
|
|
||||||
- '#Call to an undefined method [a-zA-Z0-9\\_]+::exclude\(\)#'
|
|
||||||
- '#Array has 2 duplicate keys with value#'
|
- '#Array has 2 duplicate keys with value#'
|
||||||
- '#Undefined method#'
|
- '#Call to an undefined method#'
|
||||||
- '#makeHidden#'
|
- '#makeHidden#'
|
||||||
- '#Socialite#'
|
- '#Socialite#'
|
59
resources/views/email/admin/stripe_connect_failed.blade.php
Normal file
59
resources/views/email/admin/stripe_connect_failed.blade.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
@component('email.template.admin', ['design' => 'light', 'settings' => $settings, 'logo' => $logo])
|
||||||
|
<div class="center">
|
||||||
|
@isset($greeting)
|
||||||
|
<p>{{ $greeting }}</p>
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
@isset($title)
|
||||||
|
<h1>{{ $title }}</h1>
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
@isset($h2)
|
||||||
|
<h2>{{ $title }}</h2>
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
<div style="margin-top: 10px; margin-bottom: 30px;">
|
||||||
|
@isset($body)
|
||||||
|
{!! $body !!}
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
@isset($slot)
|
||||||
|
{{ $slot }}
|
||||||
|
@endisset
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@isset($additional_info)
|
||||||
|
<p>{{ $additional_info }}</p>
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
@isset($url)
|
||||||
|
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table align="center" cellspacing="0" cellpadding="0" style="width: 600px;">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top">
|
||||||
|
<![endif]-->
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" >
|
||||||
|
<tbody><tr>
|
||||||
|
<td align="center" class="new_button" style="border-radius: 2px; background-color: {{ $settings->primary_color }} ;">
|
||||||
|
<a href="{{ $url }}" target="_blank" class="new_button" style="text-decoration: none; border: 1px solid {{ $settings->primary_color }}; display: inline-block; border-radius: 2px; padding-top: 15px; padding-bottom: 15px; padding-left: 25px; padding-right: 25px; font-size: 20px; color: #fff">
|
||||||
|
<singleline label="cta button">{{ ctrans($button) }}</singleline>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
@isset($signature)
|
||||||
|
<p>{!! nl2br($signature) !!}</p>
|
||||||
|
@endisset
|
||||||
|
</div>
|
||||||
|
@endcomponent
|
@ -0,0 +1,5 @@
|
|||||||
|
{!! $title !!}
|
||||||
|
|
||||||
|
{!! $text_body !!}
|
||||||
|
|
||||||
|
{!! $url !!}
|
Loading…
x
Reference in New Issue
Block a user