mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge branch 'v5-develop' into v5-stable
This commit is contained in:
commit
d857457867
@ -1 +1 @@
|
||||
5.3.6
|
||||
5.3.7
|
@ -22,6 +22,7 @@ use App\Factory\RecurringInvoiceFactory;
|
||||
use App\Factory\SubscriptionFactory;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Jobs\Company\CreateCompanyTaskStatuses;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Account;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
@ -62,7 +63,7 @@ class CreateSingleAccount extends Command
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ninja:create-single-account {gateway=all}';
|
||||
protected $signature = 'ninja:create-single-account {gateway=all} {--database=db-ninja-01}';
|
||||
|
||||
protected $invoice_repo;
|
||||
|
||||
@ -89,6 +90,8 @@ class CreateSingleAccount extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::setDb($this->option('database'));
|
||||
|
||||
$this->info(date('r').' Create Single Sample Account...');
|
||||
$this->count = 1;
|
||||
$this->gateway = $this->argument('gateway');
|
||||
|
@ -24,6 +24,7 @@ use App\Models\Company;
|
||||
use App\Models\CompanyToken;
|
||||
use App\Models\Country;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Document;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Product;
|
||||
use App\Models\Project;
|
||||
@ -230,6 +231,7 @@ class CreateTestData extends Command
|
||||
'company_id' => $company->id,
|
||||
]);
|
||||
|
||||
|
||||
$this->count = $this->count * 10;
|
||||
|
||||
$this->info('Creating '.$this->count.' clients');
|
||||
@ -387,6 +389,14 @@ class CreateTestData extends Command
|
||||
'company_id' => $company->id,
|
||||
]);
|
||||
|
||||
|
||||
Document::factory()->count(50)->create([
|
||||
'user_id' => $user->id,
|
||||
'company_id' => $company->id,
|
||||
'documentable_type' => Client::class,
|
||||
'documentable_id' => $client->id
|
||||
]);
|
||||
|
||||
ClientContact::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
@ -428,6 +438,13 @@ class CreateTestData extends Command
|
||||
'company_id' => $client->company->id,
|
||||
]);
|
||||
|
||||
Document::factory()->count(50)->create([
|
||||
'user_id' => $client->user->id,
|
||||
'company_id' => $client->company_id,
|
||||
'documentable_type' => Vendor::class,
|
||||
'documentable_id' => $vendor->id
|
||||
]);
|
||||
|
||||
VendorContact::factory()->create([
|
||||
'user_id' => $client->user->id,
|
||||
'vendor_id' => $vendor->id,
|
||||
@ -449,6 +466,14 @@ class CreateTestData extends Command
|
||||
'user_id' => $client->user->id,
|
||||
'company_id' => $client->company->id,
|
||||
]);
|
||||
|
||||
|
||||
Document::factory()->count(5)->create([
|
||||
'user_id' => $client->user->id,
|
||||
'company_id' => $client->company_id,
|
||||
'documentable_type' => Task::class,
|
||||
'documentable_id' => $vendor->id
|
||||
]);
|
||||
}
|
||||
|
||||
private function createProject($client)
|
||||
@ -457,6 +482,13 @@ class CreateTestData extends Command
|
||||
'user_id' => $client->user->id,
|
||||
'company_id' => $client->company->id,
|
||||
]);
|
||||
|
||||
Document::factory()->count(5)->create([
|
||||
'user_id' => $client->user->id,
|
||||
'company_id' => $client->company_id,
|
||||
'documentable_type' => Project::class,
|
||||
'documentable_id' => $vendor->id
|
||||
]);
|
||||
}
|
||||
|
||||
private function createInvoice($client)
|
||||
@ -506,6 +538,13 @@ class CreateTestData extends Command
|
||||
$invoice = $invoice->service()->markPaid()->save();
|
||||
}
|
||||
|
||||
Document::factory()->count(5)->create([
|
||||
'user_id' => $invoice->user->id,
|
||||
'company_id' => $invoice->company_id,
|
||||
'documentable_type' => Invoice::class,
|
||||
'documentable_id' => $invoice->id
|
||||
]);
|
||||
|
||||
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars()));
|
||||
}
|
||||
|
||||
|
128
app/Console/Commands/HostedMigrations.php
Normal file
128
app/Console/Commands/HostedMigrations.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Exceptions\MigrationValidatorFailed;
|
||||
use App\Exceptions\NonExistingMigrationFile;
|
||||
use App\Exceptions\ProcessingMigrationArchiveFailed;
|
||||
use App\Exceptions\ResourceDependencyMissing;
|
||||
use App\Exceptions\ResourceNotAvailableForMigration;
|
||||
use App\Jobs\Util\Import;
|
||||
use App\Jobs\Util\StartMigration;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\MigrationFailed;
|
||||
use App\Models\Account;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyToken;
|
||||
use App\Models\User;
|
||||
use App\Utils\Traits\AppSetup;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use DirectoryIterator;
|
||||
use Faker\Factory;
|
||||
use Faker\Generator;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Str;
|
||||
use ZipArchive;
|
||||
|
||||
class HostedMigrations extends Command
|
||||
{
|
||||
use MakesHash;
|
||||
use AppSetup;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ninja:import {--email=}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Import a v4 migration file';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->buildCache();
|
||||
|
||||
if(!MultiDB::userFindAndSetDb($this->option('email'))){
|
||||
$this->info("Could not find a user with that email address");
|
||||
return;
|
||||
}
|
||||
|
||||
$user = User::where('email', $this->option('email'))->first();
|
||||
|
||||
if(!$user){
|
||||
$this->info("There was a problem getting the user, did you set the right DB?");
|
||||
return;
|
||||
}
|
||||
|
||||
$path = public_path('storage/migrations/import');
|
||||
|
||||
nlog(public_path('storage/migrations/import'));
|
||||
|
||||
$directory = new DirectoryIterator($path);
|
||||
|
||||
foreach ($directory as $file) {
|
||||
if ($file->getExtension() === 'zip') {
|
||||
|
||||
$company = $user->companies()->first();
|
||||
|
||||
$this->info('Started processing: '.$file->getBasename().' at '.now());
|
||||
|
||||
$zip = new ZipArchive();
|
||||
$archive = $zip->open($file->getRealPath());
|
||||
|
||||
try {
|
||||
if (! $archive) {
|
||||
throw new ProcessingMigrationArchiveFailed('Processing migration archive failed. Migration file is possibly corrupted.');
|
||||
}
|
||||
|
||||
$filename = pathinfo($file->getRealPath(), PATHINFO_FILENAME);
|
||||
|
||||
$zip->extractTo(public_path("storage/migrations/{$filename}"));
|
||||
$zip->close();
|
||||
|
||||
$import_file = public_path("storage/migrations/$filename/migration.json");
|
||||
|
||||
Import::dispatch($import_file, $user->companies()->first(), $user);
|
||||
|
||||
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing $e) {
|
||||
\Mail::to($this->user)->send(new MigrationFailed($e, $e->getMessage()));
|
||||
|
||||
if (app()->environment() !== 'production') {
|
||||
info($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -43,7 +43,7 @@ class ImportMigrations extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'migrations:import {--path=}';
|
||||
protected $signature = 'ninja:old-import {--path=}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
|
@ -267,8 +267,10 @@ class CompanySettings extends BaseSettings
|
||||
|
||||
public $use_credits_payment = 'off'; //always, option, off //@implemented
|
||||
public $hide_empty_columns_on_pdf = false;
|
||||
public $email_from_name = '';
|
||||
|
||||
public static $casts = [
|
||||
'email_from_name' => 'string',
|
||||
'show_all_tasks_client_portal' => 'string',
|
||||
'entity_send_time' => 'int',
|
||||
'shared_invoice_credit_counter' => 'bool',
|
||||
|
@ -67,18 +67,6 @@ class InvoiceFilters extends QueryFilters
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
public function client_id(string $client_id = '') :Builder
|
||||
{
|
||||
if (strlen($client_id) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$this->builder->where('client_id', $this->decodePrimaryKey($client_id));
|
||||
|
||||
return $this->builder;
|
||||
|
||||
}
|
||||
|
||||
public function number(string $number) :Builder
|
||||
{
|
||||
return $this->builder->where('number', $number);
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Filters;
|
||||
|
||||
//use Illuminate\Database\Query\Builder;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@ -20,6 +21,8 @@ use Illuminate\Http\Request;
|
||||
*/
|
||||
abstract class QueryFilters
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
/**
|
||||
* active status.
|
||||
*/
|
||||
@ -177,6 +180,18 @@ abstract class QueryFilters
|
||||
|
||||
}
|
||||
|
||||
public function client_id(string $client_id = '') :Builder
|
||||
{
|
||||
if (strlen($client_id) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$this->builder->where('client_id', $this->decodePrimaryKey($client_id));
|
||||
|
||||
return $this->builder;
|
||||
|
||||
}
|
||||
|
||||
public function filter_deleted_clients($value)
|
||||
{
|
||||
|
||||
|
@ -34,11 +34,6 @@ class SystemLogFilters extends QueryFilters
|
||||
return $this->builder->where('event_id', $event_id);
|
||||
}
|
||||
|
||||
public function client_id(int $client_id) :Builder
|
||||
{
|
||||
return $this->builder->where('client_id', $client_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
|
@ -30,7 +30,7 @@ class InvoiceSum
|
||||
|
||||
public $invoice_item;
|
||||
|
||||
public $total_taxes;
|
||||
public $total_taxes = 0;
|
||||
|
||||
private $total;
|
||||
|
||||
|
@ -15,6 +15,7 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ClientPortal\Contact\ContactPasswordResetRequest;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Account;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Http\Request;
|
||||
@ -56,11 +57,13 @@ class ContactForgotPasswordController extends Controller
|
||||
{
|
||||
$account_id = $request->get('account_id');
|
||||
$account = Account::find($account_id);
|
||||
$company = $account->companies->first();
|
||||
|
||||
return $this->render('auth.passwords.request', [
|
||||
'title' => 'Client Password Reset',
|
||||
'passwordEmailRoute' => 'client.password.email',
|
||||
'account' => $account
|
||||
'account' => $account,
|
||||
'company' => $company
|
||||
]);
|
||||
}
|
||||
|
||||
@ -76,7 +79,11 @@ class ContactForgotPasswordController extends Controller
|
||||
|
||||
public function sendResetLinkEmail(ContactPasswordResetRequest $request)
|
||||
{
|
||||
$user = MultiDB::hasContact($request->input('email'));
|
||||
|
||||
if(Ninja::isHosted() && $request->has('db'))
|
||||
MultiDB::setDb($request->input('db'));
|
||||
|
||||
// $user = MultiDB::hasContact($request->input('email'));
|
||||
|
||||
$this->validateEmail($request);
|
||||
|
||||
|
@ -37,9 +37,11 @@ class ContactLoginController extends Controller
|
||||
public function showLoginForm(Request $request)
|
||||
{
|
||||
//if we are on the root domain invoicing.co do not show any company logos
|
||||
if(Ninja::isHosted() && count(explode('.', request()->getHost())) == 2){
|
||||
$company = null;
|
||||
}elseif (strpos($request->getHost(), 'invoicing.co') !== false) {
|
||||
// if(Ninja::isHosted() && count(explode('.', request()->getHost())) == 2){
|
||||
// $company = null;
|
||||
// }else
|
||||
|
||||
if (strpos($request->getHost(), 'invoicing.co') !== false) {
|
||||
$subdomain = explode('.', $request->getHost())[0];
|
||||
|
||||
MultiDB::findAndSetDbByDomain(['subdomain' => $subdomain]);
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Account;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
@ -65,14 +66,18 @@ class ContactResetPasswordController extends Controller
|
||||
{
|
||||
$account_id = $request->get('account_id');
|
||||
$account = Account::find($account_id);
|
||||
$db = $account->companies->first()->db;
|
||||
|
||||
return $this->render('auth.passwords.reset')->with(
|
||||
['token' => $token, 'email' => $request->email, 'account' => $account]
|
||||
['token' => $token, 'email' => $request->email, 'account' => $account, 'db' => $db]
|
||||
);
|
||||
}
|
||||
|
||||
public function reset(Request $request)
|
||||
{
|
||||
if($request->has('db'))
|
||||
MultiDB::setDb($request->input('db'));
|
||||
|
||||
$request->validate($this->rules(), $this->validationErrorMessages());
|
||||
|
||||
// Here we will attempt to reset the user's password. If it is successful we
|
||||
|
@ -221,14 +221,30 @@ class LoginController extends BaseController
|
||||
return response()->json(['message' => 'User not linked to any companies'], 403);
|
||||
|
||||
/* Ensure the user has a valid token */
|
||||
$user->company_users->each(function ($company_user) use($request){
|
||||
if($user->company_users()->count() != $user->tokens()->count())
|
||||
{
|
||||
|
||||
$user->companies->each(function($company) use($user, $request){
|
||||
|
||||
if(!CompanyToken::where('user_id', $user->id)->where('company_id', $company->id)->exists()){
|
||||
|
||||
CreateCompanyToken::dispatchNow($company, $user, $request->server('HTTP_USER_AGENT'));
|
||||
|
||||
if($company_user->tokens->count() == 0){
|
||||
CreateCompanyToken::dispatchNow($company_user->company, $company_user->user, $request->server('HTTP_USER_AGENT'));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//method above override this
|
||||
// $user->company_users->each(function ($company_user) use($request){
|
||||
|
||||
// if($company_user->tokens->count() == 0){
|
||||
// CreateCompanyToken::dispatchNow($company_user->company, $company_user->user, $request->server('HTTP_USER_AGENT'));
|
||||
// }
|
||||
|
||||
// });
|
||||
|
||||
/*On the hosted platform, only owners can login for free/pro accounts*/
|
||||
if(Ninja::isHosted() && !$cu->first()->is_owner && !$user->account->isEnterpriseClient())
|
||||
return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403);
|
||||
|
@ -107,12 +107,14 @@ class BaseController extends Controller
|
||||
'token',
|
||||
'company.activities',
|
||||
'company.documents',
|
||||
'company.company_gateways.gateway',
|
||||
'company.users.company_user',
|
||||
'company.tax_rates',
|
||||
'company.groups',
|
||||
'company.payment_terms',
|
||||
'company.designs.company',
|
||||
'company.expense_categories',
|
||||
'company.subscriptions',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
@ -212,7 +214,7 @@ class BaseController extends Controller
|
||||
$query->with(
|
||||
[
|
||||
'company' => function ($query) use ($updated_at, $user) {
|
||||
$query->whereNotNull('updated_at')->with('documents');
|
||||
$query->whereNotNull('updated_at')->with('documents')->with('users');
|
||||
},
|
||||
'company.clients' => function ($query) use ($updated_at, $user) {
|
||||
$query->where('clients.updated_at', '>=', $updated_at)->with('contacts.company', 'gateway_tokens', 'documents');
|
||||
@ -251,7 +253,7 @@ class BaseController extends Controller
|
||||
$query->where('expenses.user_id', $user->id)->orWhere('expenses.assigned_user_id', $user->id);
|
||||
},
|
||||
'company.groups' => function ($query) use ($updated_at, $user) {
|
||||
$query->where('updated_at', '>=', $updated_at);
|
||||
$query->where('updated_at', '>=', $updated_at)->with('documents');
|
||||
|
||||
if(!$user->isAdmin())
|
||||
$query->where('group_settings.user_id', $user->id);
|
||||
@ -299,7 +301,7 @@ class BaseController extends Controller
|
||||
|
||||
},
|
||||
'company.recurring_invoices'=> function ($query) use ($updated_at, $user) {
|
||||
$query->where('updated_at', '>=', $updated_at)->with('invitations', 'documents');
|
||||
$query->where('updated_at', '>=', $updated_at)->with('invitations', 'documents', 'client.gateway_tokens', 'client.group_settings');
|
||||
|
||||
if(!$user->hasPermission('view_recurring_invoice'))
|
||||
$query->where('recurring_invoices.user_id', $user->id)->orWhere('recurring_invoices.assigned_user_id', $user->id);
|
||||
@ -389,7 +391,7 @@ class BaseController extends Controller
|
||||
$query->where('created_at', '>=', $created_at);
|
||||
},
|
||||
'company.groups' => function ($query) use ($created_at, $user) {
|
||||
$query->where('created_at', '>=', $created_at);
|
||||
$query->where('created_at', '>=', $created_at)->with('documents');
|
||||
|
||||
},
|
||||
'company.payment_terms'=> function ($query) use ($created_at, $user) {
|
||||
@ -476,12 +478,6 @@ class BaseController extends Controller
|
||||
$query->where('credits.user_id', $user->id)->orWhere('credits.assigned_user_id', $user->id);
|
||||
|
||||
},
|
||||
// 'company.designs'=> function ($query) use ($created_at, $user) {
|
||||
// $query->where('created_at', '>=', $created_at)->with('company');
|
||||
|
||||
// if(!$user->isAdmin())
|
||||
// $query->where('designs.user_id', $user->id);
|
||||
// },
|
||||
'company.documents'=> function ($query) use ($created_at, $user) {
|
||||
$query->where('created_at', '>=', $created_at);
|
||||
},
|
||||
@ -492,7 +488,7 @@ class BaseController extends Controller
|
||||
$query->where('expenses.user_id', $user->id)->orWhere('expenses.assigned_user_id', $user->id);
|
||||
},
|
||||
'company.groups' => function ($query) use ($created_at, $user) {
|
||||
$query->where('created_at', '>=', $created_at);
|
||||
$query->where('created_at', '>=', $created_at)->with('documents');
|
||||
|
||||
if(!$user->isAdmin())
|
||||
$query->where('group_settings.user_id', $user->id);
|
||||
|
@ -46,6 +46,21 @@ class InvitationController extends Controller
|
||||
return $this->genericRouter('recurring_invoice', $invitation_key);
|
||||
}
|
||||
|
||||
public function invoiceRouter(string $invitation_key)
|
||||
{
|
||||
return $this->genericRouter('invoice', $invitation_key);
|
||||
}
|
||||
|
||||
public function quoteRouter(string $invitation_key)
|
||||
{
|
||||
return $this->genericRouter('quote', $invitation_key);
|
||||
}
|
||||
|
||||
public function creditRouter(string $invitation_key)
|
||||
{
|
||||
return $this->genericRouter('credit', $invitation_key);
|
||||
}
|
||||
|
||||
private function genericRouter(string $entity, string $invitation_key)
|
||||
{
|
||||
|
||||
|
@ -20,7 +20,9 @@ use App\Utils\Number;
|
||||
use App\Utils\TempFile;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
@ -86,6 +88,10 @@ class InvoiceController extends Controller
|
||||
->with('message', ctrans('texts.no_action_provided'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $ids
|
||||
* @return Factory|View|RedirectResponse
|
||||
*/
|
||||
private function makePayment(array $ids)
|
||||
{
|
||||
$invoices = Invoice::whereIn('id', $ids)
|
||||
@ -119,8 +125,8 @@ class InvoiceController extends Controller
|
||||
//format data
|
||||
$invoices->map(function ($invoice) {
|
||||
$invoice->service()->removeUnpaidGatewayFees()->save();
|
||||
$invoice->balance = Number::formatValue($invoice->balance, $invoice->client->currency());
|
||||
$invoice->partial = Number::formatValue($invoice->partial, $invoice->client->currency());
|
||||
$invoice->balance = $invoice->balance > 0 ? Number::formatValue($invoice->balance, $invoice->client->currency()) : 0;
|
||||
$invoice->partial = $invoice->partial > 0 ? Number::formatValue($invoice->partial, $invoice->client->currency()) : 0;
|
||||
|
||||
return $invoice;
|
||||
});
|
||||
|
@ -30,10 +30,16 @@ class NinjaPlanController extends Controller
|
||||
{
|
||||
MultiDB::findAndSetDbByCompanyKey($company_key);
|
||||
$company = Company::where('company_key', $company_key)->first();
|
||||
|
||||
nlog("Ninja Plan Controller Company key found {$company->company_key}");
|
||||
|
||||
$account = $company->account;
|
||||
|
||||
if (Ninja::isHosted() && MultiDB::findAndSetDbByContactKey(request()->segment(3)) && $client_contact = ClientContact::where('contact_key', request()->segment(3))->first())
|
||||
if (Ninja::isHosted() && MultiDB::findAndSetDbByContactKey($contact_key) && $client_contact = ClientContact::where('contact_key', $contact_key)->first())
|
||||
{
|
||||
|
||||
nlog("Ninja Plan Controller - Found and set Client Contact");
|
||||
|
||||
Auth::guard('contact')->login($client_contact,true);
|
||||
|
||||
/* Current paid users get pushed straight to subscription overview page*/
|
||||
|
@ -14,6 +14,15 @@ namespace App\Http\Livewire;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Client;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Document;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Project;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\Task;
|
||||
use App\Utils\Traits\WithSorting;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
@ -28,23 +37,139 @@ class DocumentsTable extends Component
|
||||
|
||||
public $company;
|
||||
|
||||
public string $tab = 'documents';
|
||||
|
||||
protected $query;
|
||||
|
||||
public function mount($client)
|
||||
{
|
||||
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
$this->client = $client;
|
||||
|
||||
$this->query = $this->documents();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$query = $this->client
|
||||
->documents()
|
||||
->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc')
|
||||
->paginate($this->per_page);
|
||||
|
||||
return render('components.livewire.documents-table', [
|
||||
'documents' => $query,
|
||||
'documents' => $this->query->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc')->paginate($this->per_page),
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateResources(string $resource)
|
||||
{
|
||||
$this->tab = $resource;
|
||||
|
||||
switch ($resource) {
|
||||
case 'documents':
|
||||
$this->query = $this->documents();
|
||||
break;
|
||||
|
||||
case 'credits':
|
||||
$this->query = $this->credits();
|
||||
break;
|
||||
|
||||
case 'expenses':
|
||||
$this->query = $this->expenses();
|
||||
break;
|
||||
|
||||
case 'invoices':
|
||||
$this->query = $this->invoices();
|
||||
break;
|
||||
|
||||
case 'payments':
|
||||
$this->query = $this->payments();
|
||||
break;
|
||||
|
||||
case 'projects':
|
||||
$this->query = $this->projects();
|
||||
break;
|
||||
|
||||
case 'quotes':
|
||||
$this->query = $this->quotes();
|
||||
break;
|
||||
|
||||
case 'recurringInvoices':
|
||||
$this->query = $this->recurringInvoices();
|
||||
break;
|
||||
|
||||
case 'tasks':
|
||||
$this->query = $this->tasks();
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->query = $this->documents();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function documents()
|
||||
{
|
||||
return $this->client->documents();
|
||||
}
|
||||
|
||||
protected function credits()
|
||||
{
|
||||
return Document::query()
|
||||
->whereHasMorph('documentable', [Credit::class], function ($query) {
|
||||
$query->where('client_id', $this->client->id);
|
||||
});
|
||||
}
|
||||
|
||||
protected function expenses()
|
||||
{
|
||||
return Document::query()
|
||||
->whereHasMorph('documentable', [Expense::class], function ($query) {
|
||||
$query->where('client_id', $this->client->id);
|
||||
});
|
||||
}
|
||||
|
||||
protected function invoices()
|
||||
{
|
||||
return Document::query()
|
||||
->whereHasMorph('documentable', [Invoice::class], function ($query) {
|
||||
$query->where('client_id', $this->client->id);
|
||||
});
|
||||
}
|
||||
|
||||
protected function payments()
|
||||
{
|
||||
return Document::query()
|
||||
->whereHasMorph('documentable', [Payment::class], function ($query) {
|
||||
$query->where('client_id', $this->client->id);
|
||||
});
|
||||
}
|
||||
|
||||
protected function projects()
|
||||
{
|
||||
return Document::query()
|
||||
->whereHasMorph('documentable', [Project::class], function ($query) {
|
||||
$query->where('client_id', $this->client->id);
|
||||
});
|
||||
}
|
||||
|
||||
protected function quotes()
|
||||
{
|
||||
return Document::query()
|
||||
->whereHasMorph('documentable', [Quote::class], function ($query) {
|
||||
$query->where('client_id', $this->client->id);
|
||||
});
|
||||
}
|
||||
|
||||
protected function recurringInvoices()
|
||||
{
|
||||
return Document::query()
|
||||
->whereHasMorph('documentable', [RecurringInvoice::class], function ($query) {
|
||||
$query->where('client_id', $this->client->id);
|
||||
});
|
||||
}
|
||||
|
||||
protected function tasks()
|
||||
{
|
||||
return Document::query()
|
||||
->whereHasMorph('documentable', [Task::class], function ($query) {
|
||||
$query->where('client_id', $this->client->id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ class PaymentsTable extends Component
|
||||
->where('company_id', $this->company->id)
|
||||
->where('client_id', auth('contact')->user()->client->id)
|
||||
->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc')
|
||||
->withTrashed()
|
||||
->paginate($this->per_page);
|
||||
|
||||
return render('components.livewire.payments-table', [
|
||||
|
@ -52,8 +52,12 @@ class QueryLogging
|
||||
$timeEnd = microtime(true);
|
||||
$time = $timeEnd - $timeStart;
|
||||
|
||||
// if($count > 150)
|
||||
// nlog($queries);
|
||||
// nlog("Query count = {$count}");
|
||||
|
||||
if($count > 175){
|
||||
nlog("Quer count = {$count}");
|
||||
nlog($queries);
|
||||
}
|
||||
|
||||
$ip = '';
|
||||
|
||||
|
@ -60,6 +60,8 @@ class StoreUserRequest extends Request
|
||||
|
||||
//unique user rule - check company_user table for user_id / company_id / account_id if none exist we can add the user. ELSE return false
|
||||
|
||||
if(array_key_exists('email', $input))
|
||||
$input['email'] = trim($input['email']);
|
||||
|
||||
if (isset($input['company_user'])) {
|
||||
if (! isset($input['company_user']['is_admin'])) {
|
||||
|
@ -45,6 +45,8 @@ class UpdateUserRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if(array_key_exists('email', $input))
|
||||
$input['email'] = trim($input['email']);
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class BaseTransformer
|
||||
public function getClient($client_name, $client_email) {
|
||||
$clients = $this->maps['company']->clients;
|
||||
|
||||
$clients = $clients->where( 'name', $client_name );
|
||||
$clients = $clients->where( 'id_number', $client_name );
|
||||
|
||||
if ( $clients->count() >= 1 ) {
|
||||
return $clients->first()->id;
|
||||
|
@ -42,7 +42,7 @@ class ClientTransformer extends BaseTransformer {
|
||||
'work_phone' => $this->getString( $data, 'Phone' ),
|
||||
'private_notes' => $this->getString( $data, 'Notes' ),
|
||||
'website' => $this->getString( $data, 'Website' ),
|
||||
|
||||
'id_number' => $this->getString( $data, 'Customer ID'),
|
||||
'address1' => $this->getString( $data, 'Billing Address' ),
|
||||
'address2' => $this->getString( $data, 'Billing Street2' ),
|
||||
'city' => $this->getString( $data, 'Billing City' ),
|
||||
|
@ -38,7 +38,7 @@ class InvoiceTransformer extends BaseTransformer {
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'client_id' => $this->getClient( $this->getString( $invoice_data, 'Company Name' ), null ),
|
||||
'client_id' => $this->getClient( $this->getString( $invoice_data, 'Customer ID' ), null ),
|
||||
'number' => $this->getString( $invoice_data, 'Invoice Number' ),
|
||||
'date' => isset( $invoice_data['Invoice Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Invoice Date'] ) ) : null,
|
||||
'due_date' => isset( $invoice_data['Due Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Due Date'] ) ) : null,
|
||||
@ -59,7 +59,7 @@ class InvoiceTransformer extends BaseTransformer {
|
||||
'notes' => $this->getString( $record, 'Item Description' ),
|
||||
'cost' => $this->getFloat( $record, 'Item Price' ),
|
||||
'quantity' => $this->getFloat( $record, 'Quantity' ),
|
||||
'discount' => $this->getFloat( $record, 'Discount Amount' ),
|
||||
'discount' => $this->getString( $record, 'Discount Amount' ),
|
||||
'is_amount_discount' => true,
|
||||
];
|
||||
}
|
||||
|
@ -1241,8 +1241,11 @@ class CompanyImport implements ShouldQueue
|
||||
|
||||
/* New to convert product ids from old hashes to new hashes*/
|
||||
if($class == 'App\Models\Subscription'){
|
||||
$obj_array['product_ids'] = $this->recordProductIds($obj_array['product_ids']);
|
||||
$obj_array['recurring_product_ids'] = $this->recordProductIds($obj_array['recurring_product_ids']);
|
||||
//$obj_array['product_ids'] = $this->recordProductIds($obj_array['product_ids']);
|
||||
//$obj_array['recurring_product_ids'] = $this->recordProductIds($obj_array['recurring_product_ids']);
|
||||
//
|
||||
$obj_array['recurring_product_ids'] = '';
|
||||
$obj_array['product_ids'] = '';
|
||||
}
|
||||
|
||||
$new_obj = $class::firstOrNew(
|
||||
@ -1272,6 +1275,12 @@ class CompanyImport implements ShouldQueue
|
||||
|
||||
foreach($id_array as $id) {
|
||||
|
||||
if(!$id)
|
||||
continue;
|
||||
|
||||
$id = $this->decodePrimaryKey($id);
|
||||
|
||||
nlog($id);
|
||||
$tmp_arr[] = $this->encodePrimaryKey($this->transformId('products', $id));
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class AutoBillCron
|
||||
nlog($auto_bill_partial_invoices->count(). " partial invoices to auto bill");
|
||||
|
||||
$auto_bill_partial_invoices->cursor()->each(function ($invoice){
|
||||
$this->runAutoBiller($invoice);
|
||||
$this->runAutoBiller($invoice, false);
|
||||
});
|
||||
|
||||
$auto_bill_invoices = Invoice::whereDate('due_date', '<=', now())
|
||||
@ -70,7 +70,7 @@ class AutoBillCron
|
||||
nlog($auto_bill_invoices->count(). " full invoices to auto bill");
|
||||
|
||||
$auto_bill_invoices->cursor()->each(function ($invoice){
|
||||
$this->runAutoBiller($invoice);
|
||||
$this->runAutoBiller($invoice, false);
|
||||
});
|
||||
|
||||
|
||||
@ -89,8 +89,8 @@ class AutoBillCron
|
||||
|
||||
nlog($auto_bill_partial_invoices->count(). " partial invoices to auto bill db = {$db}");
|
||||
|
||||
$auto_bill_partial_invoices->cursor()->each(function ($invoice){
|
||||
$this->runAutoBiller($invoice);
|
||||
$auto_bill_partial_invoices->cursor()->each(function ($invoice) use($db){
|
||||
$this->runAutoBiller($invoice, $db);
|
||||
});
|
||||
|
||||
$auto_bill_invoices = Invoice::whereDate('due_date', '<=', now())
|
||||
@ -102,20 +102,25 @@ class AutoBillCron
|
||||
|
||||
nlog($auto_bill_invoices->count(). " full invoices to auto bill db = {$db}");
|
||||
|
||||
$auto_bill_invoices->cursor()->each(function ($invoice){
|
||||
$this->runAutoBiller($invoice);
|
||||
$auto_bill_invoices->cursor()->each(function ($invoice) use($db){
|
||||
$this->runAutoBiller($invoice, $db);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function runAutoBiller(Invoice $invoice)
|
||||
private function runAutoBiller(Invoice $invoice, $db)
|
||||
{
|
||||
info("Firing autobill for {$invoice->company_id} - {$invoice->number}");
|
||||
|
||||
try{
|
||||
|
||||
if($db)
|
||||
MultiDB::setDB($db);
|
||||
|
||||
$invoice->service()->autoBill()->save();
|
||||
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
nlog("Failed to capture payment for {$invoice->company_id} - {$invoice->number} ->" . $e->getMessage());
|
||||
|
@ -89,7 +89,7 @@ class RecurringInvoicesCron
|
||||
->with('company')
|
||||
->cursor();
|
||||
|
||||
nlog(now()->format('Y-m-d') . ' Sending Recurring Invoices. Count = '.$recurring_invoices->count().' On Database # '.$db);
|
||||
nlog(now()->format('Y-m-d') . ' Sending Recurring Invoices. Count = '.$recurring_invoices->count());
|
||||
|
||||
$recurring_invoices->each(function ($recurring_invoice, $key) {
|
||||
nlog("Current date = " . now()->format("Y-m-d") . " Recurring date = " .$recurring_invoice->next_send_date ." Recurring #id = ". $recurring_invoice->id);
|
||||
@ -100,7 +100,7 @@ class RecurringInvoicesCron
|
||||
SendRecurring::dispatchNow($recurring_invoice, $recurring_invoice->company->db);
|
||||
}
|
||||
catch(\Exception $e){
|
||||
nlog("Unable to sending recurring invoice {$recurring_invoice->id} on db {$db}");
|
||||
nlog("Unable to sending recurring invoice {$recurring_invoice->id}");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -30,6 +30,7 @@ use App\Providers\MailServiceProvider;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Dacastro4\LaravelGmail\Facade\LaravelGmail;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
@ -118,10 +119,20 @@ class NinjaMailerJob implements ShouldQueue
|
||||
|
||||
nlog("error failed with {$e->getMessage()}");
|
||||
|
||||
if($this->nmo->entity)
|
||||
$this->entityEmailFailed($e->getMessage());
|
||||
$message = $e->getMessage();
|
||||
|
||||
if(Ninja::isHosted())
|
||||
if($e instanceof ClientException) { //postmark specific failure
|
||||
|
||||
$response = $e->getResponse();
|
||||
|
||||
nlog($response);
|
||||
// $message = $response->Message;
|
||||
}
|
||||
|
||||
if($this->nmo->entity)
|
||||
$this->entityEmailFailed($message);
|
||||
|
||||
if(Ninja::isHosted() && (!$e instanceof ClientException)) // Don't send postmark failures to Sentry
|
||||
app('sentry')->captureException($e);
|
||||
}
|
||||
}
|
||||
@ -241,6 +252,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
|
||||
private function logMailError($errors, $recipient_object)
|
||||
{
|
||||
|
||||
SystemLogger::dispatch(
|
||||
$errors,
|
||||
SystemLog::CATEGORY_MAIL,
|
||||
@ -249,19 +261,18 @@ class NinjaMailerJob implements ShouldQueue
|
||||
$recipient_object,
|
||||
$this->nmo->company
|
||||
);
|
||||
}
|
||||
|
||||
public function failed($exception = null)
|
||||
{
|
||||
nlog('mailer job failed');
|
||||
nlog($exception->getMessage());
|
||||
|
||||
$job_failure = new EmailFailure($this->nmo->company->company_key);
|
||||
$job_failure->string_metric5 = 'failed_email';
|
||||
$job_failure->string_metric6 = substr($exception->getMessage(), 0, 150);
|
||||
$job_failure->string_metric6 = substr($errors, 0, 150);
|
||||
|
||||
LightLogs::create($job_failure)
|
||||
->batch();
|
||||
}
|
||||
|
||||
public function failed($exception = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -25,6 +25,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Turbo124\Beacon\Facades\LightLogs;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class SendRecurring implements ShouldQueue
|
||||
{
|
||||
@ -137,7 +138,7 @@ class SendRecurring implements ShouldQueue
|
||||
}
|
||||
elseif($invoice->client->getSetting('auto_bill_date') == 'on_due_date' && $invoice->auto_bill_enabled) {
|
||||
|
||||
if($invoice->due_date && Carbon\Carbon::parse($invoice->due_date)->startOfDay()->lte(now()->startOfDay())) {
|
||||
if($invoice->due_date && Carbon::parse($invoice->due_date)->startOfDay()->lte(now()->startOfDay())) {
|
||||
|
||||
nlog("attempting to autobill {$invoice->number}");
|
||||
$invoice->service()->autoBill()->save();
|
||||
@ -146,6 +147,8 @@ class SendRecurring implements ShouldQueue
|
||||
|
||||
}
|
||||
|
||||
//important catch all here - we should never leave contacts send_email to false incase they are permanently set to false in the future.
|
||||
$this->recurring_invoice->client->contacts()->update(['send_email' => true]);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1396,7 +1396,7 @@ class Import implements ShouldQueue
|
||||
$modified['fees_and_limits'] = $this->cleanFeesAndLimits($modified['fees_and_limits']);
|
||||
}
|
||||
|
||||
/* On Hosted platform we need to advise Stripe users to connect with Stripe Connect */
|
||||
// /* On Hosted platform we need to advise Stripe users to connect with Stripe Connect */
|
||||
if(Ninja::isHosted() && $modified['gateway_key'] == 'd14dd26a37cecc30fdd65700bfb55b23'){
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
@ -1413,6 +1413,13 @@ class Import implements ShouldQueue
|
||||
|
||||
}
|
||||
|
||||
if(Ninja::isSelfHost() && $modified['gateway_key'] == 'd14dd26a47cecc30fdd65700bfb67b34'){
|
||||
|
||||
$modified['gateway_key'] = 'd14dd26a37cecc30fdd65700bfb55b23';
|
||||
|
||||
}
|
||||
|
||||
|
||||
$company_gateway = CompanyGateway::create($modified);
|
||||
|
||||
$key = "company_gateways_{$resource['id']}";
|
||||
|
@ -73,12 +73,12 @@ class MultiDB
|
||||
public static function checkUserEmailExists($email) : bool
|
||||
{
|
||||
if (! config('ninja.db.multi_db_enabled'))
|
||||
return User::where(['email' => $email])->exists(); // true >= 1 emails found / false -> == emails found
|
||||
return User::where(['email' => $email])->withTrashed()->exists(); // true >= 1 emails found / false -> == emails found
|
||||
|
||||
$current_db = config('database.default');
|
||||
|
||||
foreach (self::$dbs as $db) {
|
||||
if (User::on($db)->where(['email' => $email])->exists()) { // if user already exists, validation will fail
|
||||
if (User::on($db)->where(['email' => $email])->withTrashed()->exists()) { // if user already exists, validation will fail
|
||||
self::setDb($current_db);
|
||||
return true;
|
||||
}
|
||||
@ -107,7 +107,7 @@ class MultiDB
|
||||
$current_db = config('database.default');
|
||||
|
||||
foreach (self::$dbs as $db) {
|
||||
if (User::on($db)->where(['email' => $email])->exists()) {
|
||||
if (User::on($db)->where(['email' => $email])->withTrashed()->exists()) {
|
||||
if (Company::on($db)->where(['company_key' => $company_key])->exists()) {
|
||||
self::setDb($current_db);
|
||||
return true;
|
||||
@ -196,7 +196,7 @@ class MultiDB
|
||||
//multi-db active
|
||||
foreach (self::$dbs as $db) {
|
||||
|
||||
if (User::on($db)->where('email', $email)->exists()){
|
||||
if (User::on($db)->where('email', $email)->withTrashed()->exists()){
|
||||
self::setDb($db);
|
||||
return true;
|
||||
}
|
||||
|
@ -79,7 +79,12 @@ class TemplateEmail extends Mailable
|
||||
else
|
||||
$signature = $settings->email_signature;
|
||||
|
||||
$this->from(config('mail.from.address'), $this->company->present()->name());
|
||||
if(property_exists($settings, 'email_from_name') && strlen($settings->email_from_name) > 1)
|
||||
$email_from_name = $settings->email_from_name;
|
||||
else
|
||||
$email_from_name = $this->company->present()->name();
|
||||
|
||||
$this->from(config('mail.from.address'), $email_from_name);
|
||||
|
||||
if (strlen($settings->bcc_email) > 1)
|
||||
$this->bcc(explode(",",$settings->bcc_email));
|
||||
|
@ -358,11 +358,11 @@ class Account extends BaseModel
|
||||
|
||||
if($this->isPaid()){
|
||||
$limit = $this->paid_plan_email_quota;
|
||||
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 50;
|
||||
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 100;
|
||||
}
|
||||
else{
|
||||
$limit = $this->free_plan_email_quota;
|
||||
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 100;
|
||||
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 50;
|
||||
}
|
||||
|
||||
return min($limit, 5000);
|
||||
|
@ -122,6 +122,13 @@ class Activity extends StaticModel
|
||||
return $this->hasOne(Backup::class);
|
||||
}
|
||||
|
||||
|
||||
public function history()
|
||||
{
|
||||
return $this->hasOne(Backup::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
@ -213,7 +213,7 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
return $this->belongsTo(User::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function assigned_user()
|
||||
|
@ -54,7 +54,7 @@ class CompanyPresenter extends EntityPresenter
|
||||
$settings = $this->entity->settings;
|
||||
}
|
||||
|
||||
if(config('ninja.is_docker'))
|
||||
if(config('ninja.is_docker') || config('ninja.local_download'))
|
||||
return $this->logo($settings);
|
||||
|
||||
$context_options =array(
|
||||
|
@ -46,7 +46,7 @@ class InvoiceObserver
|
||||
* @return void
|
||||
*/
|
||||
public function updated(Invoice $invoice)
|
||||
{
|
||||
{nlog("updated");
|
||||
$subscriptions = Webhook::where('company_id', $invoice->company->id)
|
||||
->where('event_id', Webhook::EVENT_UPDATE_INVOICE)
|
||||
->exists();
|
||||
|
@ -103,6 +103,8 @@ class AuthorizePaymentDriver extends BaseDriver
|
||||
|
||||
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
|
||||
{
|
||||
$this->init();
|
||||
|
||||
$this->setPaymentMethod($cgt->gateway_type_id);
|
||||
|
||||
return $this->payment_method->tokenBilling($cgt, $payment_hash);
|
||||
|
@ -205,6 +205,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
|
||||
$invoices->each(function ($invoice) use ($payment) {
|
||||
event(new InvoiceWasPaid($invoice, $payment, $payment->company, Ninja::eventVars()));
|
||||
$invoice->service()->workFlow();
|
||||
});
|
||||
|
||||
return $payment->service()->applyNumber()->save();
|
||||
@ -389,7 +390,6 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
|
||||
$invoices->each(function ($invoice) {
|
||||
|
||||
if (!$invitation->contact->trashed() && $invitation->contact->send_email && $invitation->contact->email)
|
||||
$invoice->service()->deletePdf();
|
||||
|
||||
});
|
||||
@ -478,7 +478,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
$message,
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
$this::SYSTEM_LOG_TYPE,
|
||||
SystemLog::TYPE_PAYTRACE,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
@ -88,14 +88,30 @@ class CreditCard
|
||||
|
||||
$token = $this->getPaymentToken($request->all(), $customer->id);
|
||||
|
||||
$result = $this->braintree->gateway->transaction()->sale([
|
||||
$data = [
|
||||
'amount' => $this->braintree->payment_hash->data->amount_with_fee,
|
||||
'paymentMethodToken' => $token,
|
||||
'deviceData' => $state['client-data'],
|
||||
'options' => [
|
||||
'submitForSettlement' => true
|
||||
],
|
||||
]);
|
||||
];
|
||||
|
||||
if ($this->braintree->company_gateway->getConfigField('merchantAccountId')) {
|
||||
/** https://developer.paypal.com/braintree/docs/reference/request/transaction/sale/php#full-example */
|
||||
$data['merchantAccountId'] = $this->braintree->company_gateway->getConfigField('merchantAccountId');
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $this->braintree->gateway->transaction()->sale($data);
|
||||
} catch(\Exception $e) {
|
||||
if ($e instanceof \Braintree\Exception\Authorization) {
|
||||
throw new PaymentFailed(ctrans('texts.generic_gateway_error'), $e->getCode());
|
||||
}
|
||||
|
||||
throw new PaymentFailed($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
|
||||
if ($result->success) {
|
||||
$this->braintree->logSuccessfulGatewayResponse(['response' => $request->server_response, 'data' => $this->braintree->payment_hash], SystemLog::TYPE_BRAINTREE);
|
||||
@ -118,8 +134,9 @@ class CreditCard
|
||||
return $data['token'];
|
||||
}
|
||||
|
||||
$gateway_response = json_decode($data['gateway_response']);
|
||||
$gateway_response = \json_decode($data['gateway_response']);
|
||||
|
||||
try {
|
||||
$payment_method = $this->braintree->gateway->paymentMethod()->create([
|
||||
'customerId' => $customerId,
|
||||
'paymentMethodNonce' => $gateway_response->nonce,
|
||||
@ -129,6 +146,20 @@ class CreditCard
|
||||
]);
|
||||
|
||||
return $payment_method->paymentMethod->token;
|
||||
} catch(\Exception $e) {
|
||||
SystemLogger::dispatch(
|
||||
$e->getMessage(),
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_BRAINTREE,
|
||||
$this->braintree->client,
|
||||
$this->braintree->client->company,
|
||||
);
|
||||
|
||||
nlog(['e' => $e->getMessage(), 'class' => \get_class($e)]);
|
||||
|
||||
throw new PaymentFailed($e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
private function processSuccessfulPayment($response)
|
||||
|
@ -51,6 +51,7 @@ class Charge
|
||||
*/
|
||||
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
|
||||
{
|
||||
nlog(" DB = ".$this->stripe->client->company->db);
|
||||
$amount = array_sum(array_column($payment_hash->invoices(), 'amount')) + $payment_hash->fee_total;
|
||||
$invoice = Invoice::whereIn('id', $this->transformKeys(array_column($payment_hash->invoices(), 'invoice_id')))->withTrashed()->first();
|
||||
|
||||
@ -75,6 +76,10 @@ class Charge
|
||||
'description' => $description,
|
||||
];
|
||||
|
||||
nlog("Stripe tokenBilling payload");
|
||||
|
||||
nlog($data);
|
||||
|
||||
$response = $this->stripe->createPaymentIntent($data, $this->stripe->stripe_connect_auth);
|
||||
// $response = $local_stripe->paymentIntents->create($data);
|
||||
|
||||
|
@ -83,12 +83,17 @@ class ImportCustomers
|
||||
if($existing_customer_token){
|
||||
nlog("Skipping - Customer exists: {$customer->email} just updating payment methods");
|
||||
$this->update_payment_methods->updateMethods($customer, $existing_customer_token->client);
|
||||
return;
|
||||
}
|
||||
|
||||
if($customer->email && $contact = $this->stripe->company_gateway->company->client_contacts()->where('email', $customer->email)->first()){
|
||||
if($customer->email && $this->stripe->company_gateway->company->client_contacts()->where('email', $customer->email)->exists()){
|
||||
nlog("Customer exists: {$customer->email} just updating payment methods");
|
||||
|
||||
$this->stripe->company_gateway->company->client_contacts()->where('email', $customer->email)->each(function ($contact) use ($customer){
|
||||
|
||||
$this->update_payment_methods->updateMethods($customer, $contact->client);
|
||||
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,7 @@ class UpdatePaymentMethods
|
||||
$token_exists = ClientGatewayToken::where([
|
||||
'gateway_customer_reference' => $customer_reference,
|
||||
'token' => $method->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $client->company_id,
|
||||
])->exists();
|
||||
|
||||
|
@ -28,6 +28,7 @@ class BaseRepository
|
||||
{
|
||||
use MakesHash;
|
||||
use SavesDocuments;
|
||||
|
||||
public $import_mode = false;
|
||||
|
||||
/**
|
||||
@ -209,7 +210,7 @@ class BaseRepository
|
||||
$model->custom_surcharge_tax3 = $client->company->custom_surcharge_taxes3;
|
||||
$model->custom_surcharge_tax4 = $client->company->custom_surcharge_taxes4;
|
||||
|
||||
$model->save();
|
||||
$model->saveQuietly();
|
||||
|
||||
/* Model now persisted, now lets do some child tasks */
|
||||
|
||||
|
@ -67,8 +67,11 @@ class ClientContactRepository extends BaseRepository
|
||||
|
||||
if (array_key_exists('password', $contact) && strlen($contact['password']) > 1) {
|
||||
$update_contact->password = Hash::make($contact['password']);
|
||||
|
||||
$client->company->client_contacts()->where('email', $update_contact->email)->update(['password' => $update_contact->password]);
|
||||
}
|
||||
|
||||
$update_contact->email = trim($contact['email']);
|
||||
$update_contact->save();
|
||||
});
|
||||
|
||||
|
@ -170,10 +170,10 @@ class PaymentRepository extends BaseRepository {
|
||||
event( new PaymentWasCreated( $payment, $payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null) ) );
|
||||
}
|
||||
|
||||
nlog("payment amount = {$payment->amount}");
|
||||
nlog("payment applied = {$payment->applied}");
|
||||
nlog("invoice totals = {$invoice_totals}");
|
||||
nlog("credit totals = {$credit_totals}");
|
||||
// nlog("payment amount = {$payment->amount}");
|
||||
// nlog("payment applied = {$payment->applied}");
|
||||
// nlog("invoice totals = {$invoice_totals}");
|
||||
// nlog("credit totals = {$credit_totals}");
|
||||
|
||||
$payment->applied += ($invoice_totals - $credit_totals); //wont work because - check tests
|
||||
// $payment->applied += $invoice_totals; //wont work because - check tests
|
||||
|
@ -14,6 +14,7 @@ namespace App\Services\Invoice;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
@ -31,15 +32,22 @@ class AutoBillInvoice extends AbstractService
|
||||
|
||||
private $used_credit = [];
|
||||
|
||||
public function __construct(Invoice $invoice)
|
||||
protected $db;
|
||||
|
||||
public function __construct(Invoice $invoice, $db)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
|
||||
$this->client = $invoice->client;
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
|
||||
MultiDB::setDb($this->db);
|
||||
|
||||
$this->client = $this->invoice->client;
|
||||
|
||||
$is_partial = false;
|
||||
|
||||
/* Is the invoice payable? */
|
||||
@ -51,12 +59,14 @@ class AutoBillInvoice extends AbstractService
|
||||
|
||||
/* Mark the invoice as paid if there is no balance */
|
||||
if ((int)$this->invoice->balance == 0)
|
||||
return $this->invoice->service()->markPaid()->save();
|
||||
return $this->invoice->service()->markPaid()->workFlow()->save();
|
||||
|
||||
//if the credits cover the payments, we stop here, build the payment with credits and exit early
|
||||
if ($this->client->getSetting('use_credits_payment') != 'off')
|
||||
$this->applyCreditPayment();
|
||||
|
||||
$amount = 0;
|
||||
|
||||
/* Determine $amount */
|
||||
if ($this->invoice->partial > 0) {
|
||||
$is_partial = true;
|
||||
@ -68,17 +78,20 @@ class AutoBillInvoice extends AbstractService
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
info("balance remains to be paid!!");
|
||||
info("Auto Bill - balance remains to be paid!! - {$amount}");
|
||||
|
||||
/* Retrieve the Client Gateway Token */
|
||||
$gateway_token = $this->getGateway($amount);
|
||||
|
||||
/* Bail out if no payment methods available */
|
||||
if (! $gateway_token || ! $gateway_token->gateway->driver($this->client)->token_billing)
|
||||
if (! $gateway_token || ! $gateway_token->gateway->driver($this->client)->token_billing){
|
||||
nlog("Bailing out - no suitable gateway token found.");
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
nlog("Gateway present - adding gateway fee");
|
||||
|
||||
/* $gateway fee */
|
||||
//$fee = $gateway_token->gateway->calcGatewayFee($amount, $gateway_token->gateway_type_id, $this->invoice->uses_inclusive_taxes);
|
||||
$this->invoice = $this->invoice->service()->addGatewayFee($gateway_token->gateway, $gateway_token->gateway_type_id, $amount)->save();
|
||||
|
||||
if($is_partial)
|
||||
@ -94,6 +107,8 @@ class AutoBillInvoice extends AbstractService
|
||||
'fee_invoice_id' => $this->invoice->id,
|
||||
]);
|
||||
|
||||
nlog("Payment hash created => {$payment_hash->id}");
|
||||
|
||||
$payment = $gateway_token->gateway
|
||||
->driver($this->client)
|
||||
->setPaymentHash($payment_hash)
|
||||
|
@ -233,7 +233,7 @@ class InvoiceService
|
||||
|
||||
public function autoBill()
|
||||
{
|
||||
$this->invoice = (new AutoBillInvoice($this->invoice))->run();
|
||||
$this->invoice = (new AutoBillInvoice($this->invoice, $this->invoice->company->db))->run();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -82,6 +82,10 @@ class DeletePayment
|
||||
|
||||
$net_deletable = $paymentable_invoice->pivot->amount - $paymentable_invoice->pivot->refunded;
|
||||
|
||||
nlog("net deletable amount - refunded = {$net_deletable}");
|
||||
|
||||
if(!$paymentable_invoice->is_deleted)
|
||||
{
|
||||
$paymentable_invoice->service()
|
||||
->updateBalance($net_deletable)
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
@ -102,9 +106,21 @@ class DeletePayment
|
||||
} else {
|
||||
$paymentable_invoice->service()->setStatus(Invoice::STATUS_PARTIAL)->save();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
//If the invoice is deleted we only update the meta data on the invoice
|
||||
//and reduce the clients paid to date
|
||||
$paymentable_invoice->service()
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
->save();
|
||||
|
||||
// $paymentable_invoice->client
|
||||
// ->service()
|
||||
// ->updatePaidToDate($net_deletable * -1)
|
||||
// ->save();
|
||||
}
|
||||
|
||||
//fire event for this credit
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Transformers;
|
||||
|
||||
use App\Models\Activity;
|
||||
use App\Models\Backup;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
class ActivityTransformer extends EntityTransformer
|
||||
@ -23,7 +24,9 @@ class ActivityTransformer extends EntityTransformer
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [];
|
||||
protected $availableIncludes = [
|
||||
'history'
|
||||
];
|
||||
|
||||
/**
|
||||
* @param Activity $activity
|
||||
@ -55,4 +58,11 @@ class ActivityTransformer extends EntityTransformer
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
public function includeHistory(Activity $activity)
|
||||
{
|
||||
$transformer = new InvoiceHistoryTransformer($this->serializer);
|
||||
|
||||
return $this->includeItem($activity->backup, $transformer, Backup::class);
|
||||
}
|
||||
}
|
||||
|
@ -39,8 +39,6 @@ class ClientTransformer extends EntityTransformer
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
'documents',
|
||||
'gateway_tokens',
|
||||
'activities',
|
||||
'ledger',
|
||||
'system_logs',
|
||||
|
@ -29,10 +29,6 @@ class CreditTransformer extends EntityTransformer
|
||||
];
|
||||
|
||||
protected $availableIncludes = [
|
||||
'invitations',
|
||||
// 'history',
|
||||
// 'client',
|
||||
'documents',
|
||||
'activities',
|
||||
];
|
||||
|
||||
|
@ -31,9 +31,7 @@ class ExpenseTransformer extends EntityTransformer
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
'documents',
|
||||
];
|
||||
protected $availableIncludes = [];
|
||||
|
||||
public function includeDocuments(Expense $expense)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ class InvoiceHistoryTransformer extends EntityTransformer
|
||||
use MakesHash;
|
||||
|
||||
protected $defaultIncludes = [
|
||||
'activity',
|
||||
// 'activity',
|
||||
];
|
||||
|
||||
protected $availableIncludes = [
|
||||
|
@ -31,12 +31,9 @@ class InvoiceTransformer extends EntityTransformer
|
||||
];
|
||||
|
||||
protected $availableIncludes = [
|
||||
// 'invitations',
|
||||
// 'history',
|
||||
'payments',
|
||||
'client',
|
||||
'activities',
|
||||
// 'documents',
|
||||
];
|
||||
|
||||
public function includeInvitations(Invoice $invoice)
|
||||
|
@ -32,8 +32,6 @@ class PaymentTransformer extends EntityTransformer
|
||||
protected $availableIncludes = [
|
||||
'client',
|
||||
'invoices',
|
||||
'paymentables',
|
||||
'documents',
|
||||
];
|
||||
|
||||
public function __construct($serializer = null)
|
||||
|
@ -32,7 +32,6 @@ class ProductTransformer extends EntityTransformer
|
||||
protected $availableIncludes = [
|
||||
'company',
|
||||
'user',
|
||||
'documents',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -30,7 +30,6 @@ class ProjectTransformer extends EntityTransformer
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
'documents'
|
||||
];
|
||||
|
||||
public function includeDocuments(Project $project)
|
||||
|
@ -29,12 +29,7 @@ class QuoteTransformer extends EntityTransformer
|
||||
];
|
||||
|
||||
protected $availableIncludes = [
|
||||
'invitations',
|
||||
'documents',
|
||||
// 'history',
|
||||
'activities',
|
||||
// 'payments',
|
||||
// 'client',
|
||||
];
|
||||
|
||||
public function includeActivities(Quote $quote)
|
||||
|
@ -31,11 +31,7 @@ class RecurringInvoiceTransformer extends EntityTransformer
|
||||
];
|
||||
|
||||
protected $availableIncludes = [
|
||||
'invitations',
|
||||
'documents',
|
||||
'activities',
|
||||
// 'history',
|
||||
// 'client',
|
||||
];
|
||||
|
||||
/*
|
||||
|
@ -30,7 +30,6 @@ class TaskTransformer extends EntityTransformer
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
'documents'
|
||||
];
|
||||
|
||||
public function includeDocuments(Task $task)
|
||||
|
@ -35,7 +35,6 @@ class VendorTransformer extends EntityTransformer
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
'activities',
|
||||
'documents',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -34,7 +34,7 @@ class Helpers
|
||||
|
||||
$elements['signature'] = $_settings->email_signature;
|
||||
$elements['settings'] = $_settings;
|
||||
$elements['whitelabel'] = $client->user->account->isPaid() ? true : false;
|
||||
$elements['whitelabel'] = $client->company->account->isPaid() ? true : false;
|
||||
$elements['company'] = $client->company;
|
||||
|
||||
return $elements;
|
||||
|
@ -132,6 +132,7 @@ class HtmlEngine
|
||||
$data['$view_link'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_invoice').'</a>', 'label' => ctrans('texts.view_invoice')];
|
||||
$data['$viewLink'] = &$data['$view_link'];
|
||||
$data['$viewButton'] = &$data['$view_link'];
|
||||
$data['$paymentButton'] = &$data['$view_link'];
|
||||
$data['$view_url'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_invoice')];
|
||||
$data['$date'] = ['value' => $this->translateDate($this->entity->date, $this->entity->client->date_format(), $this->entity->client->locale()) ?: ' ', 'label' => ctrans('texts.invoice_date')];
|
||||
|
||||
@ -148,6 +149,8 @@ class HtmlEngine
|
||||
$data['$terms'] = &$data['$entity.terms'];
|
||||
$data['$view_link'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_quote').'</a>', 'label' => ctrans('texts.view_quote')];
|
||||
$data['$viewLink'] = &$data['$view_link'];
|
||||
$data['$viewButton'] = &$data['$view_link'];
|
||||
$data['$approveButton'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_quote').'</a>', 'label' => ctrans('texts.approve')];
|
||||
$data['$view_url'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_quote')];
|
||||
$data['$date'] = ['value' => $this->translateDate($this->entity->date, $this->entity->client->date_format(), $this->entity->client->locale()) ?: ' ', 'label' => ctrans('texts.quote_date')];
|
||||
}
|
||||
@ -159,6 +162,7 @@ class HtmlEngine
|
||||
$data['$entity.terms'] = ['value' => $this->entity->terms ?: '', 'label' => ctrans('texts.credit_terms')];
|
||||
$data['$terms'] = &$data['$entity.terms'];
|
||||
$data['$view_link'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_credit').'</a>', 'label' => ctrans('texts.view_credit')];
|
||||
$data['$viewButton'] = &$data['$view_link'];
|
||||
$data['$viewLink'] = &$data['$view_link'];
|
||||
$data['$view_url'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_credit')];
|
||||
// $data['$view_link'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_credit')];
|
||||
|
@ -136,10 +136,8 @@ trait AppSetup
|
||||
|
||||
if (is_null($position)) {
|
||||
$words_count > 1 ? $env[] = "{$property}=" . '"' . $value . '"' . "\n" : $env[] = "{$property}=" . $value . "\n";
|
||||
} elseif ($words_count > 1) {
|
||||
$env[$position] = "{$property}=" . '"' . $value . '"' . "\n"; // If value of variable is more than one word, surround with quotes.
|
||||
} else {
|
||||
$env[$position] = "{$property}=" . $value . "\n"; // Just a normal variable update, with pre-existing keys.
|
||||
$env[$position] = "{$property}=" . '"' . $value . '"' . "\n"; // If value of variable is more than one word, surround with quotes.
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -271,6 +271,8 @@ trait MakesInvoiceValues
|
||||
$data;
|
||||
}
|
||||
|
||||
$locale_info = localeconv();
|
||||
|
||||
foreach ($items as $key => $item) {
|
||||
if ($table_type == '$product' && $item->type_id != 1) {
|
||||
if ($item->type_id != 4 && $item->type_id != 6 && $item->type_id != 5) {
|
||||
@ -301,8 +303,10 @@ trait MakesInvoiceValues
|
||||
$data[$key][$table_type . ".{$_table_type}3"] = $helpers->formatCustomFieldValue($this->client->company->custom_fields, "{$_table_type}3", $item->custom_value3, $this->client);
|
||||
$data[$key][$table_type . ".{$_table_type}4"] = $helpers->formatCustomFieldValue($this->client->company->custom_fields, "{$_table_type}4", $item->custom_value4, $this->client);
|
||||
|
||||
$data[$key][$table_type.'.quantity'] = Number::formatValue($item->quantity, $this->client->currency());
|
||||
//$data[$key][$table_type.'.quantity'] = Number::formatValue($item->quantity, $this->client->currency());
|
||||
|
||||
//change quantity from localized number, to decimal format with no trailing zeroes 06/09/21
|
||||
$data[$key][$table_type.'.quantity'] = rtrim($item->quantity, $locale_info['decimal_point']);
|
||||
$data[$key][$table_type.'.unit_cost'] = Number::formatMoney($item->cost, $this->client);
|
||||
$data[$key][$table_type.'.cost'] = Number::formatMoney($item->cost, $this->client);
|
||||
|
||||
@ -483,7 +487,7 @@ trait MakesInvoiceValues
|
||||
$output = (int)$raw - (int)$_value[1]; // 1 (:MONTH) - 4
|
||||
}
|
||||
|
||||
if ($_operation == '/') {
|
||||
if ($_operation == '/' && (int)$_value[1] != 0) {
|
||||
$output = (int)$raw / (int)$_value[1]; // 1 (:MONTH) / 4
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@
|
||||
"php": "^7.3|^7.4|^8.0",
|
||||
"anahkiasen/former": "^4.2",
|
||||
"barryvdh/laravel-debugbar": "^3.4",
|
||||
"beyondcode/laravel-query-detector": "^1.5",
|
||||
"brianium/paratest": "^6.1",
|
||||
"darkaonline/l5-swagger": "^8.0",
|
||||
"facade/ignition": "^2.3.6",
|
||||
|
62
composer.lock
generated
62
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c78080d7228931d63406b506f04a792f",
|
||||
"content-hash": "5bd3a1c05429cbdf59e68e211c0360c7",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asm/php-ansible",
|
||||
@ -11624,6 +11624,66 @@
|
||||
],
|
||||
"time": "2021-06-14T14:29:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "beyondcode/laravel-query-detector",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/beyondcode/laravel-query-detector.git",
|
||||
"reference": "4a3a0cfb5d5ddc5da59d530ef5c13e260adc6d07"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/beyondcode/laravel-query-detector/zipball/4a3a0cfb5d5ddc5da59d530ef5c13e260adc6d07",
|
||||
"reference": "4a3a0cfb5d5ddc5da59d530ef5c13e260adc6d07",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0",
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/legacy-factories": "^1.0",
|
||||
"orchestra/testbench": "^3.0 || ^4.0 || ^5.0 || ^6.0",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"BeyondCode\\QueryDetector\\QueryDetectorServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"BeyondCode\\QueryDetector\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Marcel Pociot",
|
||||
"email": "marcel@beyondco.de",
|
||||
"homepage": "https://beyondcode.de",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Laravel N+1 Query Detector",
|
||||
"homepage": "https://github.com/beyondcode/laravel-query-detector",
|
||||
"keywords": [
|
||||
"beyondcode",
|
||||
"laravel-query-detector"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/beyondcode/laravel-query-detector/issues",
|
||||
"source": "https://github.com/beyondcode/laravel-query-detector/tree/1.5.0"
|
||||
},
|
||||
"time": "2021-02-16T22:51:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "brianium/paratest",
|
||||
"version": "v6.3.1",
|
||||
|
@ -14,8 +14,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => '5.3.6',
|
||||
'app_tag' => '5.3.6',
|
||||
'app_version' => '5.3.7',
|
||||
'app_tag' => '5.3.7',
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', ''),
|
||||
@ -36,6 +36,7 @@ return [
|
||||
'phantomjs_pdf_generation' => env('PHANTOMJS_PDF_GENERATION', true),
|
||||
'trusted_proxies' => env('TRUSTED_PROXIES', false),
|
||||
'is_docker' => env('IS_DOCKER', false),
|
||||
'local_download' => env('LOCAL_DOWNLOAD', false),
|
||||
'sentry_dsn' => env('SENTRY_LARAVEL_DSN', 'https://9b4e15e575214354a7d666489783904a@sentry.invoicing.co/6'),
|
||||
'environment' => env('NINJA_ENVIRONMENT', 'selfhost'), // 'hosted', 'development', 'selfhost', 'reseller'
|
||||
'preconfigured_install' => env('PRECONFIGURED_INSTALL',false),
|
||||
|
70
config/querydetector.php
Normal file
70
config/querydetector.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
* Enable or disable the query detection.
|
||||
* If this is set to "null", the app.debug config value will be used.
|
||||
*/
|
||||
'enabled' => env('QUERY_DETECTOR_ENABLED', false),
|
||||
|
||||
/*
|
||||
* Threshold level for the N+1 query detection. If a relation query will be
|
||||
* executed more then this amount, the detector will notify you about it.
|
||||
*/
|
||||
'threshold' => (int) env('QUERY_DETECTOR_THRESHOLD', 1),
|
||||
|
||||
/*
|
||||
* Here you can whitelist model relations.
|
||||
*
|
||||
* Right now, you need to define the model relation both as the class name and the attribute name on the model.
|
||||
* So if an "Author" model would have a "posts" relation that points to a "Post" class, you need to add both
|
||||
* the "posts" attribute and the "Post::class", since the relation can get resolved in multiple ways.
|
||||
*/
|
||||
'except' => [
|
||||
//Author::class => [
|
||||
// Post::class,
|
||||
// 'posts',
|
||||
//]
|
||||
],
|
||||
|
||||
/*
|
||||
* Here you can set a specific log channel to write to
|
||||
* in case you are trying to isolate queries or have a lot
|
||||
* going on in the laravel.log. Defaults to laravel.log though.
|
||||
*/
|
||||
'log_channel' => env('QUERY_DETECTOR_LOG_CHANNEL', 'daily'),
|
||||
|
||||
/*
|
||||
* Define the output format that you want to use. Multiple classes are supported.
|
||||
* Available options are:
|
||||
*
|
||||
* Alert:
|
||||
* Displays an alert on the website
|
||||
* \BeyondCode\QueryDetector\Outputs\Alert::class
|
||||
*
|
||||
* Console:
|
||||
* Writes the N+1 queries into your browsers console log
|
||||
* \BeyondCode\QueryDetector\Outputs\Console::class
|
||||
*
|
||||
* Clockwork: (make sure you have the itsgoingd/clockwork package installed)
|
||||
* Writes the N+1 queries warnings to Clockwork log
|
||||
* \BeyondCode\QueryDetector\Outputs\Clockwork::class
|
||||
*
|
||||
* Debugbar: (make sure you have the barryvdh/laravel-debugbar package installed)
|
||||
* Writes the N+1 queries into a custom messages collector of Debugbar
|
||||
* \BeyondCode\QueryDetector\Outputs\Debugbar::class
|
||||
*
|
||||
* JSON:
|
||||
* Writes the N+1 queries into the response body of your JSON responses
|
||||
* \BeyondCode\QueryDetector\Outputs\Json::class
|
||||
*
|
||||
* Log:
|
||||
* Writes the N+1 queries into the Laravel.log file
|
||||
* \BeyondCode\QueryDetector\Outputs\Log::class
|
||||
*/
|
||||
'output' => [
|
||||
//\BeyondCode\QueryDetector\Outputs\Alert::class,
|
||||
\BeyondCode\QueryDetector\Outputs\Log::class,
|
||||
//\BeyondCode\QueryDetector\Outputs\Json::class,
|
||||
]
|
||||
];
|
39
database/factories/DocumentFactory.php
Normal file
39
database/factories/DocumentFactory.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?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 Database\Factories;
|
||||
|
||||
use App\Models\Document;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class DocumentFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $model = Document::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'is_default' => true,
|
||||
'is_public' => true,
|
||||
'name' => true,
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Gateway;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class UpdateBraintreeGateway extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if ($gateway = Gateway::find(50)) {
|
||||
$fields = json_decode($gateway->fields);
|
||||
$fields->merchantAccountId = '';
|
||||
$gateway->fields = json_encode($fields);
|
||||
|
||||
$gateway->save();
|
||||
}
|
||||
}
|
||||
}
|
@ -74,7 +74,7 @@ class PaymentLibrariesSeeder extends Seeder
|
||||
['id' => 47, 'name' => 'Secure Trading', 'provider' => 'SecureTrading', 'key' => '231cb401487b9f15babe04b1ac4f7a27', 'fields' => '{"siteReference":"","username":"","password":"","applyThreeDSecure":false,"accountType":"ECOM"}'],
|
||||
['id' => 48, 'name' => 'SecPay', 'provider' => 'SecPay', 'key' => 'bad8699d581d9fa040e59c0bb721a76c', 'fields' => '{"mid":"","vpnPswd":"","remotePswd":"","usageType":"","confirmEmail":"","testStatus":"true","mailCustomer":"true","additionalOptions":""}'],
|
||||
['id' => 49, 'name' => 'WePay', 'provider' => 'WePay', 'is_offsite' => false, 'sort_order' => 3, 'key' => '8fdeed552015b3c7b44ed6c8ebd9e992', 'fields' => '{"accountId":"","accessToken":"","type":"goods","testMode":false,"feePayer":"payee"}'],
|
||||
['id' => 50, 'name' => 'Braintree', 'provider' => 'Braintree', 'sort_order' => 3, 'key' => 'f7ec488676d310683fb51802d076d713', 'fields' => '{"merchantId":"","publicKey":"","privateKey":"","testMode":false}'],
|
||||
['id' => 50, 'name' => 'Braintree', 'provider' => 'Braintree', 'sort_order' => 3, 'key' => 'f7ec488676d310683fb51802d076d713', 'fields' => '{"merchantId":"","merchantAccountId":"","publicKey":"","privateKey":"","testMode":false}'],
|
||||
['id' => 51, 'name' => 'FirstData Payeezy', 'provider' => 'FirstData_Payeezy', 'key' => '30334a52fb698046572c627ca10412e8', 'fields' => '{"gatewayId":"","password":"","keyId":"","hmac":"","testMode":false}'],
|
||||
['id' => 52, 'name' => 'GoCardless', 'provider' => 'GoCardlessV2\Redirect', 'sort_order' => 9, 'is_offsite' => true, 'key' => 'b9886f9257f0c6ee7c302f1c74475f6c', 'fields' => '{"accessToken":"","webhookSecret":"","testMode":true}'],
|
||||
['id' => 53, 'name' => 'PagSeguro', 'provider' => 'PagSeguro', 'key' => 'ef498756b54db63c143af0ec433da803', 'fields' => '{"email":"","token":"","sandbox":false}'],
|
||||
|
@ -6713,6 +6713,35 @@ 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.
|
||||
--------------------------------------------------------------------------------
|
||||
filepicker_windows
|
||||
|
||||
Copyright 2020, the Dart project authors. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
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
|
||||
OWNER 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.
|
||||
--------------------------------------------------------------------------------
|
||||
files
|
||||
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
|
2
public/css/app.css
vendored
2
public/css/app.css
vendored
File diff suppressed because one or more lines are too long
56
public/flutter_service_worker.js
vendored
56
public/flutter_service_worker.js
vendored
@ -3,38 +3,38 @@ const MANIFEST = 'flutter-app-manifest';
|
||||
const TEMP = 'flutter-temp-cache';
|
||||
const CACHE_NAME = 'flutter-app-cache';
|
||||
const RESOURCES = {
|
||||
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
|
||||
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
|
||||
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
|
||||
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
|
||||
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
|
||||
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
|
||||
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
|
||||
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
|
||||
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
|
||||
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
|
||||
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
|
||||
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
|
||||
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
|
||||
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
|
||||
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
|
||||
"assets/assets/images/icon.png": "090f69e23311a4b6d851b3880ae52541",
|
||||
"assets/assets/images/google_logo.png": "0f118259ce403274f407f5e982e681c3",
|
||||
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
|
||||
"assets/assets/images/logo_dark.png": "a233ed1d4d0f7414bf97a9a10f11fb0a",
|
||||
"main.dart.js": "a4ce90340b3e610ee073d2f40c0377c1",
|
||||
"version.json": "46d4015fc9abcefe5371cafcf2084173",
|
||||
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
||||
"/": "7fb4e233bcd97d5af44e8e4ed2d9784b",
|
||||
"assets/NOTICES": "9eb7e2eb2888ea5bae5f536720db37cd",
|
||||
"assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
|
||||
"assets/AssetManifest.json": "38d9aea341601f3a5c6fa7b5a1216ea5",
|
||||
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
|
||||
"assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
|
||||
"assets/assets/images/logo_dark.png": "a233ed1d4d0f7414bf97a9a10f11fb0a",
|
||||
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
|
||||
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
|
||||
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
|
||||
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
|
||||
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
|
||||
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
|
||||
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
|
||||
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
|
||||
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
|
||||
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
|
||||
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
|
||||
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
|
||||
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
|
||||
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
|
||||
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
|
||||
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
|
||||
"assets/assets/images/google_logo.png": "0f118259ce403274f407f5e982e681c3",
|
||||
"assets/assets/images/icon.png": "090f69e23311a4b6d851b3880ae52541",
|
||||
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
|
||||
"assets/NOTICES": "cd6dfc37608a8f2f6be693260e1c1435",
|
||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
||||
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
||||
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
||||
"version.json": "46d4015fc9abcefe5371cafcf2084173",
|
||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||
"main.dart.js": "ad09f3d4a2f418fe67aa5e04dfde7fc7",
|
||||
"/": "557b6af2ed285b00c0499fe5e06805cd"
|
||||
"favicon.ico": "51636d3a390451561744c42188ccd628"
|
||||
};
|
||||
|
||||
// The application shell files that are downloaded before a service worker can
|
||||
|
279482
public/main.dart.js
vendored
279482
public/main.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
273763
public/main.foss.dart.js
vendored
273763
public/main.foss.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
271221
public/main.last.dart.js
vendored
271221
public/main.last.dart.js
vendored
File diff suppressed because one or more lines are too long
279592
public/main.next.dart.js
vendored
279592
public/main.next.dart.js
vendored
File diff suppressed because one or more lines are too long
437830
public/main.profile.dart.js
vendored
Normal file
437830
public/main.profile.dart.js
vendored
Normal file
File diff suppressed because one or more lines are too long
276880
public/main.wasm.dart.js
vendored
276880
public/main.wasm.dart.js
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5",
|
||||
"/css/app.css": "/css/app.css?id=f0b3774b6c3be0a294a7",
|
||||
"/css/app.css": "/css/app.css?id=4ef1527acb43442be8d2",
|
||||
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
|
||||
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
|
||||
"/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=0dc8c34010d09195d2f7",
|
||||
|
@ -4302,6 +4302,8 @@ $LANG = array(
|
||||
'checking' => 'Checking',
|
||||
'savings' => 'Savings',
|
||||
'unable_to_verify_payment_method' => 'Unable to verify payment method.',
|
||||
'generic_gateway_error' => 'Gateway configuration error. Please check your credentials.',
|
||||
'my_documents' => 'My documents',
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -248,6 +248,10 @@
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -243,6 +243,10 @@
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -207,6 +207,10 @@
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -196,6 +196,10 @@
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -204,6 +204,10 @@
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -221,6 +221,10 @@
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -273,6 +273,10 @@
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -187,6 +187,10 @@
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -253,6 +253,10 @@
|
||||
padding-right: 3rem;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -222,6 +222,10 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
[data-ref*=".line_total-td"] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/** Useful snippets, uncomment to enable. **/
|
||||
|
||||
/** Hide company logo **/
|
||||
|
@ -52,7 +52,7 @@
|
||||
<a class="text-xs text-gray-600 hover:text-gray-800 ease-in duration-100"
|
||||
href="{{ route('client.password.request') }}">{{ trans('texts.forgot_password') }}</a>
|
||||
</div>
|
||||
@if($company)
|
||||
@if(isset($company) && !is_null($company))
|
||||
<input type="hidden" name="db" value="{{$company->db}}">
|
||||
@endif
|
||||
<input type="password" name="password" id="password"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user