mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge branch 'v5-develop' into v5-develop
This commit is contained in:
commit
a386a33a7e
10
CHANGELOG.md
10
CHANGELOG.md
@ -3,12 +3,22 @@
|
|||||||
## [Unreleased (daily channel)](https://github.com/invoiceninja/invoiceninja/tree/v5-develop)
|
## [Unreleased (daily channel)](https://github.com/invoiceninja/invoiceninja/tree/v5-develop)
|
||||||
|
|
||||||
### Added:
|
### Added:
|
||||||
|
- Subscriptions are now going to show the frequency in the table (#5412)
|
||||||
|
- Subscriptions: During upgrade webhook request message will be shown for easier debugging (#5411)
|
||||||
|
- PDF: Custom fields now will be shared across invoices, quotes & credits (#5410)
|
||||||
|
- Client portal: Invoices are now sorted in the descending order (#5408)
|
||||||
|
- Payments: ACH notification after the initial bank account connecting process (#5405)
|
||||||
|
|
||||||
### Fixed:
|
### Fixed:
|
||||||
- Fixes for counters where patterns without {$counter} could causes endless recursion.
|
- Fixes for counters where patterns without {$counter} could causes endless recursion.
|
||||||
- Fixes for surcharge tax displayed amount on PDF.
|
- Fixes for surcharge tax displayed amount on PDF.
|
||||||
- Fixes for custom designs not rendering the custom template
|
- Fixes for custom designs not rendering the custom template
|
||||||
- Fixes for missing bulk actions on Subscriptions
|
- Fixes for missing bulk actions on Subscriptions
|
||||||
|
- Fixes CSS padding on the show page for recurring invoices (#5412)
|
||||||
|
- Fixes for rendering invalid HTML & parsing invalid XML (#5395)
|
||||||
|
|
||||||
|
### Removed:
|
||||||
|
- Removed one-time payments table (#5412)
|
||||||
|
|
||||||
## v5.1.43
|
## v5.1.43
|
||||||
|
|
||||||
|
@ -89,29 +89,6 @@ class PaymentMethodController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function edit($id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @param int $id
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function update(Request $request, $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
public function verify(ClientGatewayToken $payment_method)
|
public function verify(ClientGatewayToken $payment_method)
|
||||||
{
|
{
|
||||||
$gateway = $this->getClientGateway();
|
$gateway = $this->getClientGateway();
|
||||||
|
@ -111,6 +111,7 @@ class BillingPortalPurchase extends Component
|
|||||||
'discount_applied' => false,
|
'discount_applied' => false,
|
||||||
'show_loading_bar' => false,
|
'show_loading_bar' => false,
|
||||||
'not_eligible' => null,
|
'not_eligible' => null,
|
||||||
|
'not_eligible_message' => null,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -327,6 +328,7 @@ class BillingPortalPurchase extends Component
|
|||||||
|
|
||||||
if (is_array($is_eligible)) {
|
if (is_array($is_eligible)) {
|
||||||
$this->steps['not_eligible'] = true;
|
$this->steps['not_eligible'] = true;
|
||||||
|
$this->steps['not_eligible_message'] = $is_eligible['exception'];
|
||||||
$this->steps['show_loading_bar'] = false;
|
$this->steps['show_loading_bar'] = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -26,6 +26,11 @@ class InvoicesTable extends Component
|
|||||||
|
|
||||||
public $status = [];
|
public $status = [];
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
$this->sort_asc = false;
|
||||||
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
$local_status = [];
|
$local_status = [];
|
||||||
@ -62,6 +67,7 @@ class InvoicesTable extends Component
|
|||||||
$query = $query
|
$query = $query
|
||||||
->where('client_id', auth('contact')->user()->client->id)
|
->where('client_id', auth('contact')->user()->client->id)
|
||||||
->where('status_id', '<>', Invoice::STATUS_DRAFT)
|
->where('status_id', '<>', Invoice::STATUS_DRAFT)
|
||||||
|
->withTrashed()
|
||||||
->paginate($this->per_page);
|
->paginate($this->per_page);
|
||||||
|
|
||||||
return render('components.livewire.invoices-table', [
|
return render('components.livewire.invoices-table', [
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoice Ninja (https://invoiceninja.com).
|
|
||||||
*
|
|
||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @license https://opensource.org/licenses/AAL
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Http\Livewire;
|
|
||||||
|
|
||||||
use App\Models\Invoice;
|
|
||||||
use App\Utils\Traits\WithSorting;
|
|
||||||
use Livewire\Component;
|
|
||||||
use Livewire\WithPagination;
|
|
||||||
|
|
||||||
class SubscriptionInvoicesTable extends Component
|
|
||||||
{
|
|
||||||
use WithPagination;
|
|
||||||
use WithSorting;
|
|
||||||
|
|
||||||
public $per_page = 10;
|
|
||||||
|
|
||||||
public function render()
|
|
||||||
{
|
|
||||||
$query = Invoice::query()
|
|
||||||
->where('client_id', auth('contact')->user()->client->id)
|
|
||||||
->whereNotNull('subscription_id')
|
|
||||||
->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc')
|
|
||||||
->where('balance', '=', 0)
|
|
||||||
->paginate($this->per_page);
|
|
||||||
|
|
||||||
return render('components.livewire.subscriptions-invoices-table', [
|
|
||||||
'invoices' => $query,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
43
app/Mail/Gateways/ACHVerificationNotification.php
Normal file
43
app/Mail/Gateways/ACHVerificationNotification.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Mail\Gateways;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ACHVerificationNotification extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
return $this->view('email.gateways.ach-verification-notification');
|
||||||
|
}
|
||||||
|
}
|
@ -14,8 +14,11 @@ namespace App\PaymentDrivers\Stripe;
|
|||||||
|
|
||||||
use App\Exceptions\PaymentFailed;
|
use App\Exceptions\PaymentFailed;
|
||||||
use App\Http\Requests\Request;
|
use App\Http\Requests\Request;
|
||||||
|
use App\Jobs\Mail\NinjaMailerJob;
|
||||||
|
use App\Jobs\Mail\NinjaMailerObject;
|
||||||
use App\Jobs\Mail\PaymentFailureMailer;
|
use App\Jobs\Mail\PaymentFailureMailer;
|
||||||
use App\Jobs\Util\SystemLogger;
|
use App\Jobs\Util\SystemLogger;
|
||||||
|
use App\Mail\Gateways\ACHVerificationNotification;
|
||||||
use App\Models\ClientGatewayToken;
|
use App\Models\ClientGatewayToken;
|
||||||
use App\Models\GatewayType;
|
use App\Models\GatewayType;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
@ -47,7 +50,7 @@ class ACH
|
|||||||
return render('gateways.stripe.ach.authorize', array_merge($data));
|
return render('gateways.stripe.ach.authorize', array_merge($data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function authorizeResponse($request)
|
public function authorizeResponse(Request $request)
|
||||||
{
|
{
|
||||||
$this->stripe->init();
|
$this->stripe->init();
|
||||||
|
|
||||||
@ -63,6 +66,14 @@ class ACH
|
|||||||
|
|
||||||
$client_gateway_token = $this->storePaymentMethod($source, $request->input('method'), $customer);
|
$client_gateway_token = $this->storePaymentMethod($source, $request->input('method'), $customer);
|
||||||
|
|
||||||
|
$mailer = new NinjaMailerObject();
|
||||||
|
$mailer->mailable = new ACHVerificationNotification();
|
||||||
|
$mailer->company = auth('contact')->user()->client->company;
|
||||||
|
$mailer->settings = auth('contact')->user()->client->company->settings;
|
||||||
|
$mailer->to_user = auth('contact')->user();
|
||||||
|
|
||||||
|
NinjaMailerJob::dispatchNow($mailer);
|
||||||
|
|
||||||
return redirect()->route('client.payment_methods.verification', ['payment_method' => $client_gateway_token->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
|
return redirect()->route('client.payment_methods.verification', ['payment_method' => $client_gateway_token->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,8 +209,14 @@ trait DesignHelpers
|
|||||||
|
|
||||||
$javascript = 'document.querySelectorAll("tbody > tr > td").forEach(t=>{if(""!==t.innerText){let e=t.getAttribute("data-ref").slice(0,-3);document.querySelector(`th[data-ref="${e}-th"]`).removeAttribute("hidden")}}),document.querySelectorAll("tbody > tr > td").forEach(t=>{let e=t.getAttribute("data-ref").slice(0,-3);(e=document.querySelector(`th[data-ref="${e}-th"]`)).hasAttribute("hidden")&&""==t.innerText&&t.setAttribute("hidden","true")});';
|
$javascript = 'document.querySelectorAll("tbody > tr > td").forEach(t=>{if(""!==t.innerText){let e=t.getAttribute("data-ref").slice(0,-3);document.querySelector(`th[data-ref="${e}-th"]`).removeAttribute("hidden")}}),document.querySelectorAll("tbody > tr > td").forEach(t=>{let e=t.getAttribute("data-ref").slice(0,-3);(e=document.querySelector(`th[data-ref="${e}-th"]`)).hasAttribute("hidden")&&""==t.innerText&&t.setAttribute("hidden","true")});';
|
||||||
|
|
||||||
|
// Previously we've been decoding the HTML on the backend and XML parsing isn't good options because it requires,
|
||||||
|
// strict & valid HTML to even output/decode. Decoding is now done on the frontend with this piece of Javascript.
|
||||||
|
|
||||||
|
$html_decode = 'document.querySelectorAll(`[data-state="encoded-html"]`).forEach((element) => element.innerHTML = element.innerText)';
|
||||||
|
|
||||||
return ['element' => 'div', 'elements' => [
|
return ['element' => 'div', 'elements' => [
|
||||||
['element' => 'script', 'content' => $javascript],
|
['element' => 'script', 'content' => $javascript],
|
||||||
|
['element' => 'script', 'content' => $html_decode],
|
||||||
]];
|
]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,19 +130,14 @@ trait PdfMakerUtilities
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($contains_html) {
|
if ($contains_html) {
|
||||||
// Support for injecting direct HTML into elements.
|
// If the element contains the HTML, we gonna display it as is. DOMDocument, is going to
|
||||||
// Example: Without documentFragment(): <b>Hello!</b> will result: <b>Hello!</b>
|
// encode it for us, preventing any errors on the backend due processing stage.
|
||||||
// With document fragment we can evaluate HTML directly.
|
// Later, we decode this using Javascript so it looks like it's normal HTML being injected.
|
||||||
|
// To get all elements that need frontend decoding, we use 'data-ref' property.
|
||||||
|
|
||||||
$_child = $this->document->createElement($child['element'], '');
|
$_child = $this->document->createElement($child['element'], '');
|
||||||
|
$_child->setAttribute('data-state', 'encoded-html');
|
||||||
$fragment = $this->document->createDocumentFragment();
|
$_child->nodeValue = htmlspecialchars($child['content']);
|
||||||
|
|
||||||
$fragment->appendXML(
|
|
||||||
strtr($child['content'], ['&' => '&'])
|
|
||||||
);
|
|
||||||
|
|
||||||
$_child->appendChild($fragment);
|
|
||||||
} else {
|
} else {
|
||||||
// .. in case string doesn't contain any HTML, we'll just return
|
// .. in case string doesn't contain any HTML, we'll just return
|
||||||
// raw $content.
|
// raw $content.
|
||||||
|
@ -214,6 +214,10 @@ class HtmlEngine
|
|||||||
$data['$quote.valid_until'] = ['value' => $this->translateDate($this->entity->due_date, $this->client->date_format(), $this->entity->client->locale()), 'label' => ctrans('texts.valid_until')];
|
$data['$quote.valid_until'] = ['value' => $this->translateDate($this->entity->due_date, $this->client->date_format(), $this->entity->client->locale()), 'label' => ctrans('texts.valid_until')];
|
||||||
$data['$credit_amount'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.credit_amount')];
|
$data['$credit_amount'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.credit_amount')];
|
||||||
$data['$credit_balance'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: ' ', 'label' => ctrans('texts.credit_balance')];
|
$data['$credit_balance'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: ' ', 'label' => ctrans('texts.credit_balance')];
|
||||||
|
$data['$quote.custom1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice1', $this->entity->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice1')];
|
||||||
|
$data['$quote.custom2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice2', $this->entity->custom_value2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice2')];
|
||||||
|
$data['$quote.custom3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice3', $this->entity->custom_value3, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice3')];
|
||||||
|
$data['$quote.custom4'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice4', $this->entity->custom_value4, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice4')];
|
||||||
|
|
||||||
$data['$credit_number'] = &$data['$number'];
|
$data['$credit_number'] = &$data['$number'];
|
||||||
$data['$credit_no'] = &$data['$number'];
|
$data['$credit_no'] = &$data['$number'];
|
||||||
|
@ -2138,6 +2138,35 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
boardview
|
||||||
|
|
||||||
|
BSD 2-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2020, Jacob Bonk
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
boolean_selector
|
boolean_selector
|
||||||
build
|
build
|
||||||
@ -6282,6 +6311,31 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
draggable_scrollbar
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2018 Draggable Scrollbar Authors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
extended_image
|
extended_image
|
||||||
|
|
||||||
|
4
public/flutter_service_worker.js
vendored
4
public/flutter_service_worker.js
vendored
@ -10,7 +10,7 @@ const RESOURCES = {
|
|||||||
"/": "23224b5e03519aaa87594403d54412cf",
|
"/": "23224b5e03519aaa87594403d54412cf",
|
||||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||||
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
|
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
|
||||||
"assets/NOTICES": "e80e999afd09f0f14597c78d582d9c7c",
|
"assets/NOTICES": "3bf0be7e0e4deca198e5f5c4800f9232",
|
||||||
"assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac",
|
"assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac",
|
||||||
"assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f",
|
"assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f",
|
||||||
"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
|
"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
|
||||||
@ -31,7 +31,7 @@ const RESOURCES = {
|
|||||||
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
|
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
|
||||||
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
|
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
|
||||||
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
|
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
|
||||||
"main.dart.js": "7c03ff039c186c66a6f79f7e6d5e817c",
|
"main.dart.js": "589fe812bacbb3ceb0a5e0714f69a8cd",
|
||||||
"version.json": "e021a7a1750aa3e7d1d89b51ac9837e9"
|
"version.json": "e021a7a1750aa3e7d1d89b51ac9837e9"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
252175
public/main.dart.js
vendored
252175
public/main.dart.js
vendored
File diff suppressed because one or more lines are too long
251448
public/main.foss.dart.js
vendored
251448
public/main.foss.dart.js
vendored
File diff suppressed because one or more lines are too long
248079
public/main.wasm.dart.js
vendored
248079
public/main.wasm.dart.js
vendored
File diff suppressed because one or more lines are too long
@ -0,0 +1,14 @@
|
|||||||
|
@component('email.template.master', ['design' => 'light'])
|
||||||
|
@slot('header')
|
||||||
|
@include('email.components.header', ['logo' => 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
|
||||||
|
@endslot
|
||||||
|
|
||||||
|
<p>Hello,</p>
|
||||||
|
|
||||||
|
<p>Connecting bank accounts require verification. Stripe will automatically sends two
|
||||||
|
small deposits for this purpose. These deposits take 1-2 business days to appear on the customer's online
|
||||||
|
statement.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Thank you!</p>
|
||||||
|
@endcomponent
|
@ -59,10 +59,12 @@
|
|||||||
|
|
||||||
<div class="relative flex justify-center text-sm leading-5">
|
<div class="relative flex justify-center text-sm leading-5">
|
||||||
<h1 class="text-2xl font-bold tracking-wide bg-gray-50 px-6 py-0">
|
<h1 class="text-2xl font-bold tracking-wide bg-gray-50 px-6 py-0">
|
||||||
{{ ctrans('texts.total') }}: {{ \App\Utils\Number::formatMoney($price, $subscription->company) }}
|
{{ ctrans('texts.total') }}
|
||||||
|
: {{ \App\Utils\Number::formatMoney($price, $subscription->company) }}
|
||||||
|
|
||||||
@if($steps['discount_applied'])
|
@if($steps['discount_applied'])
|
||||||
<small class="ml-1 line-through text-gray-500">{{ \App\Utils\Number::formatMoney($subscription->price, $subscription->company) }}</small>
|
<small
|
||||||
|
class="ml-1 line-through text-gray-500">{{ \App\Utils\Number::formatMoney($subscription->price, $subscription->company) }}</small>
|
||||||
@endif
|
@endif
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
@ -208,6 +210,10 @@
|
|||||||
|
|
||||||
@if($steps['not_eligible'] && !is_null($steps['not_eligible']))
|
@if($steps['not_eligible'] && !is_null($steps['not_eligible']))
|
||||||
<h1>{{ ctrans('texts.payment_error') }}</h1>
|
<h1>{{ ctrans('texts.payment_error') }}</h1>
|
||||||
|
|
||||||
|
@if($steps['not_eligible_message'])
|
||||||
|
<small class="mt-4 block">{{ $steps['not_eligible_message'] }}</small>
|
||||||
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
<div>
|
|
||||||
<p class="mb-4 uppercase leading-4 tracking-wide inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-primary text-white">
|
|
||||||
One-time payments
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="flex items-center justify-between mt-4">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<span class="mr-2 text-sm hidden md:block">{{ ctrans('texts.per_page') }}</span>
|
|
||||||
<select wire:model="per_page" class="form-select py-1 text-sm">
|
|
||||||
<option>5</option>
|
|
||||||
<option selected>10</option>
|
|
||||||
<option>15</option>
|
|
||||||
<option>20</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
|
|
||||||
<div class="align-middle inline-block min-w-full overflow-hidden rounded">
|
|
||||||
<table class="min-w-full shadow rounded border border-gray-200 mt-4 credits-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
|
|
||||||
<p role="button" wire:click="sortBy('number')" class="cursor-pointer">
|
|
||||||
{{ ctrans('texts.subscription') }}
|
|
||||||
</p>
|
|
||||||
</th>
|
|
||||||
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
|
|
||||||
<p role="button" wire:click="sortBy('number')" class="cursor-pointer">
|
|
||||||
{{ ctrans('texts.invoice') }}
|
|
||||||
</p>
|
|
||||||
</th>
|
|
||||||
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
|
|
||||||
<p role="button" wire:click="sortBy('amount')" class="cursor-pointer">
|
|
||||||
{{ ctrans('texts.amount') }}
|
|
||||||
</p>
|
|
||||||
</th>
|
|
||||||
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
|
|
||||||
<p role="button" wire:click="sortBy('date')" class="cursor-pointer">
|
|
||||||
{{ ctrans('texts.date') }}
|
|
||||||
</p>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@forelse($invoices as $invoice)
|
|
||||||
<tr class="bg-white group hover:bg-gray-100">
|
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
|
||||||
{{ $invoice->subscription->name }}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
|
||||||
<a href="{{ route('client.invoice.show', $invoice->hashed_id) }}"
|
|
||||||
class="button-link text-primary">
|
|
||||||
{{ $invoice->number }}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
|
||||||
{{ App\Utils\Number::formatMoney($invoice->amount, $invoice->client) }}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
|
||||||
{{ $invoice->formatDate($invoice->date, $invoice->client->date_format()) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@empty
|
|
||||||
<tr class="bg-white group hover:bg-gray-100">
|
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500" colspan="100%">
|
|
||||||
{{ ctrans('texts.no_results') }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@endforelse
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-center md:justify-between mt-6 mb-6">
|
|
||||||
@if($invoices->total() > 0)
|
|
||||||
<span class="text-gray-700 text-sm hidden md:block">
|
|
||||||
{{ ctrans('texts.showing_x_of', ['first' => $invoices->firstItem(), 'last' => $invoices->lastItem(), 'total' => $invoices->total()]) }}
|
|
||||||
</span>
|
|
||||||
@endif
|
|
||||||
{{ $invoices->links('portal/ninja2020/vendor/pagination') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,9 +1,5 @@
|
|||||||
<div>
|
<div>
|
||||||
<p class="mb-4 uppercase leading-4 tracking-wide inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-primary text-white">
|
<div class="flex items-center justify-between">
|
||||||
Subscriptions
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="flex items-center justify-between mt-4">
|
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span class="mr-2 text-sm hidden md:block">{{ ctrans('texts.per_page') }}</span>
|
<span class="mr-2 text-sm hidden md:block">{{ ctrans('texts.per_page') }}</span>
|
||||||
<select wire:model="per_page" class="form-select py-1 text-sm">
|
<select wire:model="per_page" class="form-select py-1 text-sm">
|
||||||
@ -24,6 +20,11 @@
|
|||||||
{{ ctrans('texts.subscription') }}
|
{{ ctrans('texts.subscription') }}
|
||||||
</p>
|
</p>
|
||||||
</th>
|
</th>
|
||||||
|
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
|
||||||
|
<p role="button" wire:click="sortBy('number')" class="cursor-pointer">
|
||||||
|
{{ ctrans('texts.frequency') }}
|
||||||
|
</p>
|
||||||
|
</th>
|
||||||
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
|
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
|
||||||
<p role="button" wire:click="sortBy('number')" class="cursor-pointer">
|
<p role="button" wire:click="sortBy('number')" class="cursor-pointer">
|
||||||
{{ ctrans('texts.invoice') }}
|
{{ ctrans('texts.invoice') }}
|
||||||
@ -47,6 +48,9 @@
|
|||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
||||||
{{ $recurring_invoice->subscription->name }}
|
{{ $recurring_invoice->subscription->name }}
|
||||||
</td>
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
||||||
|
{{ \App\Models\RecurringInvoice::frequencyForKey($recurring_invoice->frequency_id) }}
|
||||||
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
||||||
<a href="{{ route('client.recurring_invoice.show', $recurring_invoice->hashed_id) }}"
|
<a href="{{ route('client.recurring_invoice.show', $recurring_invoice->hashed_id) }}"
|
||||||
class="button-link text-primary">
|
class="button-link text-primary">
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
@push('head')
|
@push('head')
|
||||||
<meta name="show-invoice-terms" content="{{ $settings->show_accept_invoice_terms ? true : false }}">
|
<meta name="show-invoice-terms" content="{{ $settings->show_accept_invoice_terms ? true : false }}">
|
||||||
<meta name="require-invoice-signature" content="{{ $client->company->account->hasFeature(\App\Models\Account::FEATURE_INVOICE_SETTINGS) && $settings->require_invoice_signature }}">
|
<meta name="require-invoice-signature" content="{{ $client->user->account->hasFeature(\App\Models\Account::FEATURE_INVOICE_SETTINGS) && $settings->require_invoice_signature }}">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script>
|
||||||
@endpush
|
@endpush
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
@push('head')
|
@push('head')
|
||||||
<meta name="pdf-url" content="{{ $invoice->pdf_file_path() }}">
|
<meta name="pdf-url" content="{{ $invoice->pdf_file_path() }}">
|
||||||
<meta name="show-invoice-terms" content="{{ $settings->show_accept_invoice_terms ? true : false }}">
|
<meta name="show-invoice-terms" content="{{ $settings->show_accept_invoice_terms ? true : false }}">
|
||||||
<meta name="require-invoice-signature" content="{{ $client->company->account->hasFeature(\App\Models\Account::FEATURE_INVOICE_SETTINGS) && $settings->require_invoice_signature }}">
|
<meta name="require-invoice-signature" content="{{ $client->user->account->hasFeature(\App\Models\Account::FEATURE_INVOICE_SETTINGS) && $settings->require_invoice_signature }}">
|
||||||
<script src="{{ asset('js/vendor/pdf.js/pdf.min.js') }}"></script>
|
<script src="{{ asset('js/vendor/pdf.js/pdf.min.js') }}"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script>
|
||||||
@endpush
|
@endpush
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if(is_null($invoice->subscription_id) || optional($invoice->subscription)->allow_cancellation)
|
@if(is_null($invoice->subscription_id) || optional($invoice->subscription)->allow_cancellation)
|
||||||
<div class="bg-white shadow sm:rounded-lg mb-4 mt-4">
|
<div class="bg-white shadow sm:rounded-lg mt-4">
|
||||||
<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>
|
||||||
@ -86,11 +86,11 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if($invoice->subscription && $invoice->subscription->allow_plan_changes)
|
@if($invoice->subscription && $invoice->subscription->allow_plan_changes)
|
||||||
<div class="bg-white shadow overflow-hidden px-4 py-5 lg:rounded-lg">
|
<div class="bg-white shadow overflow-hidden px-4 py-5 lg:rounded-lg mt-4">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">Switch Plans:</h3>
|
<h3 class="text-lg leading-6 font-medium text-gray-900">Switch Plans:</h3>
|
||||||
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">Upgrade or downgrade your current plan.</p>
|
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">Upgrade or downgrade your current plan.</p>
|
||||||
|
|
||||||
<div class="flex mt-4">
|
<div class="flex mt-4 space-x-2">
|
||||||
@foreach($invoice->subscription->service()->getPlans() as $subscription)
|
@foreach($invoice->subscription->service()->getPlans() as $subscription)
|
||||||
<a href="{{ route('client.subscription.plan_switch', ['recurring_invoice' => $invoice->hashed_id, 'target' => $subscription->hashed_id]) }}" class="border rounded px-5 py-2 hover:border-gray-800 text-sm cursor-pointer">{{ $subscription->name }}</a>
|
<a href="{{ route('client.subscription.plan_switch', ['recurring_invoice' => $invoice->hashed_id, 'target' => $subscription->hashed_id]) }}" class="border rounded px-5 py-2 hover:border-gray-800 text-sm cursor-pointer">{{ $subscription->name }}</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
@livewire('subscription-invoices-table')
|
|
||||||
@livewire('subscription-recurring-invoices-table')
|
@livewire('subscription-recurring-invoices-table')
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -54,7 +54,7 @@ Route::group(['middleware' => ['auth:contact', 'locale', 'check_client_existence
|
|||||||
Route::get('payment_methods/{payment_method}/verification', 'ClientPortal\PaymentMethodController@verify')->name('payment_methods.verification');
|
Route::get('payment_methods/{payment_method}/verification', 'ClientPortal\PaymentMethodController@verify')->name('payment_methods.verification');
|
||||||
Route::post('payment_methods/{payment_method}/verification', 'ClientPortal\PaymentMethodController@processVerification');
|
Route::post('payment_methods/{payment_method}/verification', 'ClientPortal\PaymentMethodController@processVerification');
|
||||||
|
|
||||||
Route::resource('payment_methods', 'ClientPortal\PaymentMethodController'); // name = (payment_methods. index / create / show / update / destroy / edit
|
Route::resource('payment_methods', 'ClientPortal\PaymentMethodController')->except(['edit', 'update']); // name = (payment_methods. index / create / show / update / destroy / edit
|
||||||
|
|
||||||
Route::match(['GET', 'POST'], 'quotes/approve', 'ClientPortal\QuoteController@bulk')->name('quotes.bulk');
|
Route::match(['GET', 'POST'], 'quotes/approve', 'ClientPortal\QuoteController@bulk')->name('quotes.bulk');
|
||||||
Route::get('quotes', 'ClientPortal\QuoteController@index')->name('quotes.index')->middleware('portal_enabled');
|
Route::get('quotes', 'ClientPortal\QuoteController@index')->name('quotes.index')->middleware('portal_enabled');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user