Merge branch 'v5-develop' of https://github.com/turbo124/invoiceninja into v5-develop

This commit is contained in:
David Bomba 2023-06-05 07:09:36 +10:00
commit c3c5b54fe0
25 changed files with 98 additions and 99 deletions

View File

@ -112,7 +112,8 @@ class ClientFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
return $this->builder->where('group_settings_id', $group_id); return $this->builder->where('group_settings_id', $this->decodePrimaryKey($group_id));
} }
/** /**

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Libraries\MultiDB;
use App\Models\Account; use App\Models\Account;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails; use App\Models\Company;
use App\Libraries\MultiDB;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Password; use Illuminate\Support\Facades\Password;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class ForgotPasswordController extends Controller class ForgotPasswordController extends Controller
{ {

View File

@ -69,7 +69,7 @@ class ResetPasswordController extends Controller
$account = Account::first(); $account = Account::first();
} }
return $this->render('auth.passwords.reset', ['root' => 'themes', 'token' => $token, 'account' => $account]); return $this->render('auth.passwords.reset', ['root' => 'themes', 'token' => $token, 'account' => $account, 'email' => $request->email]);
} }
/** /**
@ -111,4 +111,28 @@ class ResetPasswordController extends Controller
return redirect('/'); return redirect('/');
} }
/**
* Get the response for a successful password reset.
*
* @param \Illuminate\Http\Request $request
* @param string $response
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
protected function sendResetResponse(Request $request, $response)
{
if ($request->wantsJson()) {
return new JsonResponse(['message' => trans($response)], 200);
}
if(Ninja::isHosted() && $request->hasHeader('X-React')){
return redirect('https://app.invoicing.co/#/login');
}
elseif($request->hasHeader('X-React'))
return redirect('/#/login');
return redirect($this->redirectPath())
->with('status', trans($response));
}
} }

View File

@ -84,6 +84,7 @@ trait VerifiesUserEmail
return $this->render('auth.confirmed', [ return $this->render('auth.confirmed', [
'root' => 'themes', 'root' => 'themes',
'message' => ctrans('texts.security_confirmation'), 'message' => ctrans('texts.security_confirmation'),
'redirect_url' => request()->hasHeader('X-React') ? 'https://app.invoicing.co/#/' : url('/'),
]); ]);
} }
} }

View File

@ -231,8 +231,11 @@ class UserController extends BaseController
$return_user_collection = collect(); $return_user_collection = collect();
$users->each(function ($user, $key) use ($action, $return_user_collection) { /** @var \App\Models\User $logged_in_user */
if (auth()->user()->can('edit', $user)) { $logged_in_user = auth()->user();
$users->each(function ($user, $key) use ($logged_in_user, $action, $return_user_collection) {
if ($logged_in_user->can('edit', $user)) {
$this->user_repo->{$action}($user); $this->user_repo->{$action}($user);
$return_user_collection->push($user->id); $return_user_collection->push($user->id);
@ -251,12 +254,11 @@ class UserController extends BaseController
*/ */
public function detach(DetachCompanyUserRequest $request, User $user) public function detach(DetachCompanyUserRequest $request, User $user)
{ {
// if ($request->entityIsDeleted($user)) { /** @var \App\Models\User $logged_in_user */
// return $request->disallowUpdate(); $logged_in_user = auth()->user();
// }
$company_user = CompanyUser::whereUserId($user->id) $company_user = CompanyUser::whereUserId($user->id)
->whereCompanyId(auth()->user()->companyId()) ->whereCompanyId($logged_in_user->companyId())
->withTrashed() ->withTrashed()
->first(); ->first();

View File

@ -15,7 +15,7 @@ class Cors
// ALLOW OPTIONS METHOD // ALLOW OPTIONS METHOD
$headers = [ $headers = [
'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE', 'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers'=> 'X-API-PASSWORD-BASE64,X-API-COMPANY-KEY,X-CLIENT-VERSION,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Disposition,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE', 'Access-Control-Allow-Headers'=> 'X-React,X-API-PASSWORD-BASE64,X-API-COMPANY-KEY,X-CLIENT-VERSION,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Disposition,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE',
]; ];
return Response::make('OK', 200, $headers); return Response::make('OK', 200, $headers);
@ -25,7 +25,7 @@ class Cors
$response->headers->set('Access-Control-Allow-Origin', '*'); $response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); $response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
$response->headers->set('Access-Control-Allow-Headers', 'X-API-PASSWORD-BASE64,X-API-COMPANY-KEY,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Disposition,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE'); $response->headers->set('Access-Control-Allow-Headers', 'X-React,X-API-PASSWORD-BASE64,X-API-COMPANY-KEY,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Disposition,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE');
$response->headers->set('Access-Control-Expose-Headers', 'X-APP-VERSION,X-MINIMUM-CLIENT-VERSION,Content-Disposition'); $response->headers->set('Access-Control-Expose-Headers', 'X-APP-VERSION,X-MINIMUM-CLIENT-VERSION,Content-Disposition');
$response->headers->set('X-APP-VERSION', config('ninja.app_version')); $response->headers->set('X-APP-VERSION', config('ninja.app_version'));
$response->headers->set('X-MINIMUM-CLIENT-VERSION', config('ninja.minimum_client_version')); $response->headers->set('X-MINIMUM-CLIENT-VERSION', config('ninja.minimum_client_version'));

View File

@ -241,12 +241,12 @@ class Company extends BaseModel
protected array $tax_coverage_countries = [ protected array $tax_coverage_countries = [
'US', 'US',
// //EU countries // //EU countries
// 'AT', // Austria 'AT', // Austria
// 'BE', // Belgium // 'BE', // Belgium
// 'BG', // Bulgaria // 'BG', // Bulgaria
// 'CY', // Cyprus // 'CY', // Cyprus
// 'CZ', // Czech Republic // 'CZ', // Czech Republic
// 'DE', // Germany 'DE', // Germany
// 'DK', // Denmark // 'DK', // Denmark
// 'EE', // Estonia // 'EE', // Estonia
// 'ES', // Spain // 'ES', // Spain
@ -269,9 +269,12 @@ class Company extends BaseModel
// 'SI', // Slovenia // 'SI', // Slovenia
// 'SK', // Slovakia // 'SK', // Slovakia
// //EU Countries // //EU Countries
'AU', // Australia
]; ];
protected $fillable = [ protected $fillable = [
'invoice_task_item_description',
'invoice_task_project_header',
'invoice_task_hours', 'invoice_task_hours',
'markdown_enabled', 'markdown_enabled',
'calculate_expense_tax_by_amount', 'calculate_expense_tax_by_amount',

View File

@ -11,25 +11,15 @@
namespace App\Services\Invoice; namespace App\Services\Invoice;
use App\Jobs\Ninja\TransactionLog;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\TransactionEvent;
use App\Services\AbstractService; use App\Services\AbstractService;
class ApplyPayment extends AbstractService class ApplyPayment extends AbstractService
{ {
private $invoice;
private $payment; public function __construct(private Invoice $invoice, private Payment $payment, private float $payment_amount)
private $payment_amount;
public function __construct($invoice, $payment, $payment_amount)
{ {
$this->invoice = $invoice;
$this->payment = $payment;
$this->payment_amount = $payment_amount;
} }
/* Apply payment to a single invoice */ /* Apply payment to a single invoice */

View File

@ -23,11 +23,8 @@ class CreateInvitations extends AbstractService
{ {
use MakesHash; use MakesHash;
private $invoice; public function __construct(private Invoice $invoice)
public function __construct(Invoice $invoice)
{ {
$this->invoice = $invoice;
} }
public function run() public function run()

View File

@ -28,27 +28,13 @@ class GenerateDeliveryNote
{ {
use MakesHash, PdfMaker; use MakesHash, PdfMaker;
/**
* @var \App\Models\Invoice
*/
private $invoice;
/**
* @var \App\Models\ClientContact
*/
private $contact;
/** /**
* @var mixed * @var mixed
*/ */
private $disk; private $disk;
public function __construct(Invoice $invoice, ClientContact $contact = null, $disk = null) public function __construct(private Invoice $invoice, private ?ClientContact $contact = null, $disk = null)
{ {
$this->invoice = $invoice;
$this->contact = $contact;
$this->disk = $disk ?? config('filesystems.default'); $this->disk = $disk ?? config('filesystems.default');
} }

View File

@ -19,11 +19,8 @@ use Illuminate\Support\Facades\Storage;
class GetInvoicePdf extends AbstractService class GetInvoicePdf extends AbstractService
{ {
public function __construct(Invoice $invoice, ClientContact $contact = null) public function __construct(public Invoice $invoice, public ?ClientContact $contact = null)
{ {
$this->invoice = $invoice;
$this->contact = $contact;
} }
public function run() public function run()

View File

@ -12,10 +12,7 @@
namespace App\Services\Invoice; namespace App\Services\Invoice;
use App\Events\Invoice\InvoiceWasCancelled; use App\Events\Invoice\InvoiceWasCancelled;
use App\Jobs\Ninja\TransactionLog;
use App\Models\Client;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\TransactionEvent;
use App\Services\AbstractService; use App\Services\AbstractService;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\GeneratesCounter;
@ -25,9 +22,7 @@ class HandleCancellation extends AbstractService
{ {
use GeneratesCounter; use GeneratesCounter;
private $invoice; public function __construct(private Invoice $invoice)
public function __construct(Invoice $invoice)
{ {
$this->invoice = $invoice; $this->invoice = $invoice;
} }

View File

@ -23,17 +23,14 @@ class HandleRestore extends AbstractService
{ {
use GeneratesCounter; use GeneratesCounter;
private $invoice;
private $payment_total = 0; private $payment_total = 0;
private $total_payments = 0; private $total_payments = 0;
private $adjustment_amount = 0; private $adjustment_amount = 0;
public function __construct(Invoice $invoice) public function __construct(private Invoice $invoice)
{ {
$this->invoice = $invoice;
} }
public function run() public function run()

View File

@ -23,11 +23,8 @@ class HandleReversal extends AbstractService
{ {
use GeneratesCounter; use GeneratesCounter;
private $invoice; public function __construct(private Invoice $invoice)
public function __construct(Invoice $invoice)
{ {
$this->invoice = $invoice;
} }
public function run() public function run()

View File

@ -21,17 +21,14 @@ class MarkInvoiceDeleted extends AbstractService
{ {
use GeneratesCounter; use GeneratesCounter;
public $invoice;
private $adjustment_amount = 0; private $adjustment_amount = 0;
private $total_payments = 0; private $total_payments = 0;
private $balance_adjustment = 0; private $balance_adjustment = 0;
public function __construct(Invoice $invoice) public function __construct(public Invoice $invoice)
{ {
$this->invoice = $invoice;
} }
public function run() public function run()

View File

@ -18,19 +18,8 @@ use App\Services\AbstractService;
class SendEmail extends AbstractService class SendEmail extends AbstractService
{ {
protected $invoice; public function __construct(protected Invoice $invoice, protected $reminder_template = null, protected ?ClientContact $contact = null)
protected $reminder_template;
protected $contact;
public function __construct(Invoice $invoice, $reminder_template = null, ClientContact $contact = null)
{ {
$this->invoice = $invoice;
$this->reminder_template = $reminder_template;
$this->contact = $contact;
} }
/** /**

View File

@ -23,17 +23,10 @@ class TriggeredActions extends AbstractService
{ {
use GeneratesCounter; use GeneratesCounter;
private $request;
private $invoice;
private bool $updated = false; private bool $updated = false;
public function __construct(Invoice $invoice, Request $request) public function __construct(private Invoice $invoice, private Request $request)
{ {
$this->request = $request;
$this->invoice = $invoice;
} }
public function run() public function run()

View File

@ -18,14 +18,9 @@ use Carbon\Carbon;
class UpdateReminder extends AbstractService class UpdateReminder extends AbstractService
{ {
public $invoice;
public $settings; public function __construct(public Invoice $invoice, public mixed $settings = null)
public function __construct(Invoice $invoice, $settings = null)
{ {
$this->invoice = $invoice;
$this->settings = $settings;
} }
/* We only support setting reminders based on the due date, not the partial due date */ /* We only support setting reminders based on the due date, not the partial due date */

View File

@ -811,7 +811,7 @@ class PdfMock
'$purchase_order.due_date' => '02-12-2021', '$purchase_order.due_date' => '02-12-2021',
'$vendor.billing_address1' => '589', '$vendor.billing_address1' => '589',
'$vendor.billing_address2' => '761 Odessa Centers Suite 673', '$vendor.billing_address2' => '761 Odessa Centers Suite 673',
'$invoiceninja.whitelabel' => 'https://raw.githubusercontent.com/invoiceninja/invoiceninja/v5-develop/public/images/new_logo.png', '$invoiceninja.whitelabel' => 'https://invoicing.co/images/new_logo.png',
'$purchase_order.custom1' => 'Custom 1', '$purchase_order.custom1' => 'Custom 1',
'$purchase_order.custom2' => 'Custom 2', '$purchase_order.custom2' => 'Custom 2',
'$purchase_order.custom3' => 'Custom 3', '$purchase_order.custom3' => 'Custom 3',

View File

@ -201,6 +201,8 @@ class CompanyTransformer extends EntityTransformer
'tax_data' => $company->tax_data ?: new \stdClass, 'tax_data' => $company->tax_data ?: new \stdClass,
'has_e_invoice_certificate' => $company->e_invoice_certificate ? true : false, 'has_e_invoice_certificate' => $company->e_invoice_certificate ? true : false,
'has_e_invoice_certificate_passphrase' => $company->e_invoice_certificate_passphrase ? true : false, 'has_e_invoice_certificate_passphrase' => $company->e_invoice_certificate_passphrase ? true : false,
'invoice_task_project_header' => (bool) $company->invoice_task_project_header,
'invoice_task_item_description' => (bool) $company->invoice_task_item_description,
]; ];
} }

View File

@ -606,7 +606,7 @@ class HtmlEngine
$data['$secondary_font_name'] = ['value' => Helpers::resolveFont($this->settings->secondary_font)['name'], 'label' => '']; $data['$secondary_font_name'] = ['value' => Helpers::resolveFont($this->settings->secondary_font)['name'], 'label' => ''];
$data['$secondary_font_url'] = ['value' => Helpers::resolveFont($this->settings->secondary_font)['url'], 'label' => '']; $data['$secondary_font_url'] = ['value' => Helpers::resolveFont($this->settings->secondary_font)['url'], 'label' => ''];
$data['$invoiceninja.whitelabel'] = ['value' => 'https://raw.githubusercontent.com/invoiceninja/invoiceninja/v5-develop/public/images/new_logo.png', 'label' => '']; $data['$invoiceninja.whitelabel'] = ['value' => 'https://invoicing.co/images/new_logo.png', 'label' => ''];
$data['$primary_color'] = ['value' => $this->settings->primary_color, 'label' => '']; $data['$primary_color'] = ['value' => $this->settings->primary_color, 'label' => ''];
$data['$secondary_color'] = ['value' => $this->settings->secondary_color, 'label' => '']; $data['$secondary_color'] = ['value' => $this->settings->secondary_color, 'label' => ''];

View File

@ -384,7 +384,7 @@ class VendorHtmlEngine
$data['$font_name'] = ['value' => Helpers::resolveFont($this->settings->primary_font)['name'], 'label' => '']; $data['$font_name'] = ['value' => Helpers::resolveFont($this->settings->primary_font)['name'], 'label' => ''];
$data['$font_url'] = ['value' => Helpers::resolveFont($this->settings->primary_font)['url'], 'label' => '']; $data['$font_url'] = ['value' => Helpers::resolveFont($this->settings->primary_font)['url'], 'label' => ''];
$data['$invoiceninja.whitelabel'] = ['value' => 'https://raw.githubusercontent.com/invoiceninja/invoiceninja/v5-develop/public/images/new_logo.png', 'label' => '']; $data['$invoiceninja.whitelabel'] = ['value' => 'https://invoicing.co/images/new_logo.png', 'label' => ''];
$data['$primary_color'] = ['value' => $this->settings->primary_color, 'label' => '']; $data['$primary_color'] = ['value' => $this->settings->primary_color, 'label' => ''];
$data['$secondary_color'] = ['value' => $this->settings->secondary_color, 'label' => '']; $data['$secondary_color'] = ['value' => $this->settings->secondary_color, 'label' => ''];

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('companies', function (Illuminate\Database\Schema\Blueprint $table) {
$table->boolean('invoice_task_project_header')->default(true);
$table->boolean('invoice_task_item_description')->default(true);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
};

View File

@ -41,7 +41,7 @@
<input type="email" name="email" id="email" <input type="email" name="email" id="email"
class="input" class="input"
value="{{ $email ?? old('email') }}" value="{{ $email ?? old('email') }}"
autofocus> >
@error('email') @error('email')
<div class="validation validation-fail"> <div class="validation validation-fail">
{{ $message }} {{ $message }}
@ -63,7 +63,7 @@
<label for="password" class="input-label">{{ ctrans('texts.password') }}</label> <label for="password" class="input-label">{{ ctrans('texts.password') }}</label>
<input type="password" name="password_confirmation" id="password_confirmation" <input type="password" name="password_confirmation" id="password_confirmation"
class="input" class="input"
autofocus> >
@error('password_confirmation') @error('password_confirmation')
<div class="validation validation-fail"> <div class="validation validation-fail">
{{ $message }} {{ $message }}

View File

@ -8,7 +8,7 @@
<img src="{{ asset('images/invoiceninja-black-logo-2.png') }}" class="border-b border-gray-100 h-18 pb-4" alt="Invoice Ninja logo"> <img src="{{ asset('images/invoiceninja-black-logo-2.png') }}" class="border-b border-gray-100 h-18 pb-4" alt="Invoice Ninja logo">
<h1 class="text-center text-3xl mt-10">{{ ctrans('texts.confirmation') }}</h1> <h1 class="text-center text-3xl mt-10">{{ ctrans('texts.confirmation') }}</h1>
<p class="text-center opacity-75">{{ $message }}</p> <p class="text-center opacity-75">{{ $message }}</p>
<a class="button button-primary text-blue-600 text-center mt-8" href="{{ url('/') }}">{{ ctrans('texts.return_to_login') }}</a> <a class="button button-primary text-blue-600 text-center mt-8" href="{{ $redirect_url }}">{{ ctrans('texts.return_to_login') }}</a>
</div> </div>
</div> </div>
</div> </div>