mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-16 16:13:20 +01:00
commit
0a2f9069cc
@ -1 +1 @@
|
|||||||
5.1.70
|
5.1.72
|
@ -12,6 +12,7 @@
|
|||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App;
|
use App;
|
||||||
|
use App\Factory\ClientContactFactory;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
@ -27,6 +28,7 @@ use Exception;
|
|||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Mail;
|
use Mail;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -78,7 +80,10 @@ class CheckData extends Command
|
|||||||
|
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->logMessage(date('Y-m-d h:i:s').' Running CheckData...');
|
$database_connection = $this->option('database') ? $this->option('database') : 'Connected to Default DB';
|
||||||
|
$fix_status = $this->option('fix') ? "Fixing Issues" : "Just checking issues ";
|
||||||
|
|
||||||
|
$this->logMessage(date('Y-m-d h:i:s').' Running CheckData... on ' . $database_connection . " Fix Status = {$fix_status}");
|
||||||
|
|
||||||
if ($database = $this->option('database')) {
|
if ($database = $this->option('database')) {
|
||||||
config(['database.default' => $database]);
|
config(['database.default' => $database]);
|
||||||
@ -208,14 +213,13 @@ class CheckData extends Command
|
|||||||
|
|
||||||
if ($this->option('fix') == 'true') {
|
if ($this->option('fix') == 'true') {
|
||||||
foreach ($clients as $client) {
|
foreach ($clients as $client) {
|
||||||
$contact = new ClientContact();
|
$this->logMessage("Fixing missing contacts #{$client->id}");
|
||||||
$contact->company_id = $client->company_id;
|
|
||||||
$contact->user_id = $client->user_id;
|
$new_contact = ClientContactFactory::create($client->company_id, $client->user_id);
|
||||||
$contact->client_id = $client->id;
|
$new_contact->client_id = $client->id;
|
||||||
$contact->is_primary = true;
|
$new_contact->contact_key = Str::random(40);
|
||||||
$contact->send_invoice = true;
|
$new_contact->is_primary = true;
|
||||||
$contact->contact_key = str_random(config('ninja.key_length'));
|
$new_contact->save();
|
||||||
$contact->save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,9 +237,21 @@ class CheckData extends Command
|
|||||||
$clients->where('clients.id', '=', $this->option('client_id'));
|
$clients->where('clients.id', '=', $this->option('client_id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$clients = $clients->get(['clients.id', DB::raw('count(client_contacts.id)')]);
|
$clients = $clients->get(['clients.id', 'clients.user_id', 'clients.company_id']);
|
||||||
$this->logMessage($clients->count().' clients without a single primary contact');
|
$this->logMessage($clients->count().' clients without a single primary contact');
|
||||||
|
|
||||||
|
if ($this->option('fix') == 'true') {
|
||||||
|
foreach ($clients as $client) {
|
||||||
|
$this->logMessage("Fixing missing primary contacts #{$client->id}");
|
||||||
|
|
||||||
|
$new_contact = ClientContactFactory::create($client->company_id, $client->user_id);
|
||||||
|
$new_contact->client_id = $client->id;
|
||||||
|
$new_contact->contact_key = Str::random(40);
|
||||||
|
$new_contact->is_primary = true;
|
||||||
|
$new_contact->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($clients->count() > 0) {
|
if ($clients->count() > 0) {
|
||||||
$this->isValid = false;
|
$this->isValid = false;
|
||||||
}
|
}
|
||||||
@ -316,7 +332,7 @@ class CheckData extends Command
|
|||||||
if (round($total_invoice_payments, 2) != round($client->paid_to_date, 2)) {
|
if (round($total_invoice_payments, 2) != round($client->paid_to_date, 2)) {
|
||||||
$wrong_paid_to_dates++;
|
$wrong_paid_to_dates++;
|
||||||
|
|
||||||
$this->logMessage($client->present()->name.'id = # '.$client->id." - Paid to date does not match Client Paid To Date = {$client->paid_to_date} - Invoice Payments = {$total_invoice_payments}");
|
$this->logMessage($client->present()->name.' id = # '.$client->id." - Paid to date does not match Client Paid To Date = {$client->paid_to_date} - Invoice Payments = {$total_invoice_payments}");
|
||||||
|
|
||||||
$this->isValid = false;
|
$this->isValid = false;
|
||||||
}
|
}
|
||||||
@ -332,8 +348,8 @@ class CheckData extends Command
|
|||||||
|
|
||||||
Client::cursor()->where('is_deleted', 0)->each(function ($client) use ($wrong_balances) {
|
Client::cursor()->where('is_deleted', 0)->each(function ($client) use ($wrong_balances) {
|
||||||
$client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($wrong_balances, $client) {
|
$client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($wrong_balances, $client) {
|
||||||
$total_amount = $invoice->payments->whereIn('status_id', [Payment::STATUS_PAID, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.amount');
|
$total_amount = $invoice->payments->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.amount');
|
||||||
$total_refund = $invoice->payments->whereIn('status_id', [Payment::STATUS_PAID, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.refunded');
|
$total_refund = $invoice->payments->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.refunded');
|
||||||
$total_credit = $invoice->credits->sum('amount');
|
$total_credit = $invoice->credits->sum('amount');
|
||||||
|
|
||||||
$total_paid = $total_amount - $total_refund;
|
$total_paid = $total_amount - $total_refund;
|
||||||
@ -370,7 +386,7 @@ class CheckData extends Command
|
|||||||
|
|
||||||
if ($ledger && (string) $invoice_balance != (string) $client->balance) {
|
if ($ledger && (string) $invoice_balance != (string) $client->balance) {
|
||||||
$wrong_paid_to_dates++;
|
$wrong_paid_to_dates++;
|
||||||
$this->logMessage($client->present()->name.' - '.$client->id." - calculated client balances do not match {$invoice_balance} - ".rtrim($client->balance, '0'));
|
$this->logMessage($client->present()->name.' - '.$client->id." - calculated client balances do not match Invoice Balances = {$invoice_balance} - Client Balance = ".rtrim($client->balance, '0'). " Ledger balance = {$ledger->balance}");
|
||||||
|
|
||||||
$this->isValid = false;
|
$this->isValid = false;
|
||||||
}
|
}
|
||||||
@ -379,6 +395,12 @@ class CheckData extends Command
|
|||||||
$this->logMessage("{$wrong_paid_to_dates} clients with incorrect client balances");
|
$this->logMessage("{$wrong_paid_to_dates} clients with incorrect client balances");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//fix for client balances =
|
||||||
|
//$adjustment = ($invoice_balance-$client->balance)
|
||||||
|
//$client->balance += $adjustment;
|
||||||
|
|
||||||
|
//$ledger_adjustment = $ledger->balance - $client->balance;
|
||||||
|
//$ledger->balance += $ledger_adjustment
|
||||||
|
|
||||||
private function checkInvoiceBalances()
|
private function checkInvoiceBalances()
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,9 @@ use App\Factory\ClientFactory;
|
|||||||
use App\Factory\InvoiceFactory;
|
use App\Factory\InvoiceFactory;
|
||||||
use App\Factory\InvoiceInvitationFactory;
|
use App\Factory\InvoiceInvitationFactory;
|
||||||
use App\Jobs\Invoice\CreateEntityPdf;
|
use App\Jobs\Invoice\CreateEntityPdf;
|
||||||
|
use App\Jobs\Mail\NinjaMailerJob;
|
||||||
|
use App\Jobs\Mail\NinjaMailerObject;
|
||||||
|
use App\Mail\Migration\MaxCompanies;
|
||||||
use App\Mail\TemplateEmail;
|
use App\Mail\TemplateEmail;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
@ -59,26 +62,9 @@ class SendTestEmails extends Command
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
|
||||||
$this->sendTemplateEmails('plain');
|
|
||||||
$this->sendTemplateEmails('light');
|
|
||||||
$this->sendTemplateEmails('dark');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function sendTemplateEmails($template)
|
|
||||||
{
|
{
|
||||||
$faker = Factory::create();
|
$faker = Factory::create();
|
||||||
|
|
||||||
$message = [
|
|
||||||
'title' => 'Invoice XJ-3838',
|
|
||||||
'body' => '<div>"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</div>',
|
|
||||||
'subject' => 'The Test Subject',
|
|
||||||
'footer' => 'Lovely Footer Texts',
|
|
||||||
];
|
|
||||||
|
|
||||||
$user = User::whereEmail('user@example.com')->first();
|
|
||||||
|
|
||||||
if (! $user) {
|
|
||||||
$account = Account::factory()->create();
|
$account = Account::factory()->create();
|
||||||
|
|
||||||
$user = User::factory()->create([
|
$user = User::factory()->create([
|
||||||
@ -103,57 +89,13 @@ class SendTestEmails extends Command
|
|||||||
//'settings' => DefaultSettings::userSettings(),
|
//'settings' => DefaultSettings::userSettings(),
|
||||||
'settings' => null,
|
'settings' => null,
|
||||||
]);
|
]);
|
||||||
} else {
|
|
||||||
$company = $user->company_users->first()->company;
|
|
||||||
$account = $company->account;
|
|
||||||
}
|
|
||||||
|
|
||||||
$client = Client::all()->first();
|
$nmo = new NinjaMailerObject;
|
||||||
|
$nmo->mailable = new MaxCompanies($user->account->companies()->first());
|
||||||
if (! $client) {
|
$nmo->company = $user->account->companies()->first();
|
||||||
$client = ClientFactory::create($company->id, $user->id);
|
$nmo->settings = $user->account->companies()->first()->settings;
|
||||||
$client->save();
|
$nmo->to_user = $user;
|
||||||
|
|
||||||
ClientContact::factory()->create([
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'client_id' => $client->id,
|
|
||||||
'company_id' => $company->id,
|
|
||||||
'is_primary' => 1,
|
|
||||||
'send_email' => true,
|
|
||||||
'email' => $faker->safeEmail,
|
|
||||||
]);
|
|
||||||
|
|
||||||
ClientContact::factory()->create([
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'client_id' => $client->id,
|
|
||||||
'company_id' => $company->id,
|
|
||||||
'send_email' => true,
|
|
||||||
'email' => $faker->safeEmail,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$invoice = InvoiceFactory::create($company->id, $user->id);
|
|
||||||
$invoice->client_id = $client->id;
|
|
||||||
$invoice->setRelation('client', $client);
|
|
||||||
$invoice->save();
|
|
||||||
|
|
||||||
$ii = InvoiceInvitationFactory::create($invoice->company_id, $invoice->user_id);
|
|
||||||
$ii->invoice_id = $invoice->id;
|
|
||||||
$ii->client_contact_id = $client->primary_contact()->first()->id;
|
|
||||||
$ii->save();
|
|
||||||
|
|
||||||
$invoice->setRelation('invitations', $ii);
|
|
||||||
$invoice->service()->markSent()->save();
|
|
||||||
|
|
||||||
CreateEntityPdf::dispatch($invoice->invitations()->first());
|
|
||||||
|
|
||||||
$cc_emails = [config('ninja.testvars.test_email')];
|
|
||||||
$bcc_emails = [config('ninja.testvars.test_email')];
|
|
||||||
|
|
||||||
|
|
||||||
$email_builder->setFooter($message['footer'])
|
|
||||||
->setSubject($message['subject'])
|
|
||||||
->setBody($message['body']);
|
|
||||||
|
|
||||||
|
NinjaMailerJob::dispatchNow($nmo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ use App\Jobs\Cron\RecurringInvoicesCron;
|
|||||||
use App\Jobs\Cron\SubscriptionCron;
|
use App\Jobs\Cron\SubscriptionCron;
|
||||||
use App\Jobs\Ninja\AdjustEmailQuota;
|
use App\Jobs\Ninja\AdjustEmailQuota;
|
||||||
use App\Jobs\Ninja\CompanySizeCheck;
|
use App\Jobs\Ninja\CompanySizeCheck;
|
||||||
|
use App\Jobs\Util\DiskCleanup;
|
||||||
use App\Jobs\Util\ReminderJob;
|
use App\Jobs\Util\ReminderJob;
|
||||||
use App\Jobs\Util\SchedulerCheck;
|
use App\Jobs\Util\SchedulerCheck;
|
||||||
use App\Jobs\Util\SendFailedEmails;
|
use App\Jobs\Util\SendFailedEmails;
|
||||||
@ -47,6 +48,8 @@ class Kernel extends ConsoleKernel
|
|||||||
|
|
||||||
$schedule->job(new VersionCheck)->daily();
|
$schedule->job(new VersionCheck)->daily();
|
||||||
|
|
||||||
|
$schedule->job(new DiskCleanup)->daily()->withoutOverlapping();
|
||||||
|
|
||||||
$schedule->command('ninja:check-data --database=db-ninja-01')->daily()->withoutOverlapping();
|
$schedule->command('ninja:check-data --database=db-ninja-01')->daily()->withoutOverlapping();
|
||||||
|
|
||||||
$schedule->job(new ReminderJob)->daily()->withoutOverlapping();
|
$schedule->job(new ReminderJob)->daily()->withoutOverlapping();
|
||||||
|
@ -254,7 +254,7 @@ class CompanySettings extends BaseSettings
|
|||||||
public $portal_custom_footer = ''; //@TODO @BEN
|
public $portal_custom_footer = ''; //@TODO @BEN
|
||||||
public $portal_custom_js = ''; //@TODO @BEN
|
public $portal_custom_js = ''; //@TODO @BEN
|
||||||
|
|
||||||
public $client_can_register = false; //@implemented
|
public $client_can_register = false; //@deorecated 04/06/2021
|
||||||
public $client_portal_terms = ''; //@TODO @BEN
|
public $client_portal_terms = ''; //@TODO @BEN
|
||||||
public $client_portal_privacy_policy = ''; //@TODO @BEN
|
public $client_portal_privacy_policy = ''; //@TODO @BEN
|
||||||
public $client_portal_enable_uploads = false; //@implemented
|
public $client_portal_enable_uploads = false; //@implemented
|
||||||
|
@ -50,6 +50,7 @@ class Handler extends ExceptionHandler
|
|||||||
//Swift_TransportException::class,
|
//Swift_TransportException::class,
|
||||||
MaxAttemptsExceededException::class,
|
MaxAttemptsExceededException::class,
|
||||||
CommandNotFoundException::class,
|
CommandNotFoundException::class,
|
||||||
|
ValidationException::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +15,7 @@ use App\Events\Contact\ContactLoggedIn;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
|
use App\Models\Company;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||||
@ -34,10 +35,18 @@ class ContactLoginController extends Controller
|
|||||||
|
|
||||||
public function showLoginForm(Request $request)
|
public function showLoginForm(Request $request)
|
||||||
{
|
{
|
||||||
|
if ($request->subdomain) {
|
||||||
|
$company = Company::where('subdomain', $request->subdomain)->first();
|
||||||
|
} elseif (Ninja::isSelfHost()) {
|
||||||
|
$company = Account::first()->default_company;
|
||||||
|
} else {
|
||||||
|
$company = null;
|
||||||
|
}
|
||||||
|
|
||||||
$account_id = $request->get('account_id');
|
$account_id = $request->get('account_id');
|
||||||
$account = Account::find($account_id);
|
$account = Account::find($account_id);
|
||||||
|
|
||||||
return $this->render('auth.login', ['account' => $account]);
|
return $this->render('auth.login', ['account' => $account, 'company' => $company]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ class ContactRegisterController extends Controller
|
|||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware(['guest', 'contact.register']);
|
$this->middleware(['guest']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showRegisterForm(string $company_key = '')
|
public function showRegisterForm(string $company_key = '')
|
||||||
|
@ -38,6 +38,7 @@ use Illuminate\Http\Request;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Laravel\Socialite\Facades\Socialite;
|
||||||
use PragmaRX\Google2FA\Google2FA;
|
use PragmaRX\Google2FA\Google2FA;
|
||||||
use Turbo124\Beacon\Facades\LightLogs;
|
use Turbo124\Beacon\Facades\LightLogs;
|
||||||
|
|
||||||
@ -212,15 +213,24 @@ class LoginController extends BaseController
|
|||||||
if(!$cu->exists())
|
if(!$cu->exists())
|
||||||
return response()->json(['message' => 'User not linked to any companies'], 403);
|
return response()->json(['message' => 'User not linked to any companies'], 403);
|
||||||
|
|
||||||
$cu->first()->account->companies->each(function ($company) use($cu, $request){
|
/* Ensure the user has a valid token */
|
||||||
|
$user->company_users->each(function ($company_user) use($request){
|
||||||
|
|
||||||
if($company->tokens()->where('is_system', true)->count() == 0)
|
if($company_user->tokens->count() == 0){
|
||||||
{
|
CreateCompanyToken::dispatchNow($company_user->company, $company_user->user, $request->server('HTTP_USER_AGENT'));
|
||||||
CreateCompanyToken::dispatchNow($company, $cu->first()->user, $request->server('HTTP_USER_AGENT'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// $cu->first()->account->companies->each(function ($company) use($cu, $request){
|
||||||
|
|
||||||
|
// if($company->tokens()->where('is_system', true)->count() == 0)
|
||||||
|
// {
|
||||||
|
// CreateCompanyToken::dispatchNow($company, $cu->first()->user, $request->server('HTTP_USER_AGENT'));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// });
|
||||||
|
|
||||||
return $this->timeConstrainedResponse($cu);
|
return $this->timeConstrainedResponse($cu);
|
||||||
|
|
||||||
|
|
||||||
@ -489,49 +499,37 @@ class LoginController extends BaseController
|
|||||||
if (request()->has('code')) {
|
if (request()->has('code')) {
|
||||||
return $this->handleProviderCallback($provider);
|
return $this->handleProviderCallback($provider);
|
||||||
} else {
|
} else {
|
||||||
return Socialite::driver($provider)->scopes($scopes)->redirect();
|
return Socialite::driver($provider)->with(['redirect_uri' => config('ninja.app_url')."/auth/google"])->scopes($scopes)->redirect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleProviderCallback(string $provider)
|
public function handleProviderCallback(string $provider)
|
||||||
{
|
{
|
||||||
$socialite_user = Socialite::driver($provider)
|
$socialite_user = Socialite::driver($provider)
|
||||||
->stateless()
|
|
||||||
->user();
|
->user();
|
||||||
|
|
||||||
// if($user = OAuth::handleAuth($socialite_user, $provider))
|
if($user = OAuth::handleAuth($socialite_user, $provider))
|
||||||
// {
|
{
|
||||||
// Auth::login($user, true);
|
|
||||||
|
|
||||||
// return redirect($this->redirectTo);
|
nlog('found user and updating their user record');
|
||||||
// }
|
|
||||||
// else if(MultiDB::checkUserEmailExists($socialite_user->getEmail()))
|
|
||||||
// {
|
|
||||||
// Session::flash('error', 'User exists in system, but not with this authentication method'); //todo add translations
|
|
||||||
|
|
||||||
// return view('auth.login');
|
$update_user = [
|
||||||
// }
|
'first_name' => $name[0],
|
||||||
// else {
|
'last_name' => $name[1],
|
||||||
// //todo
|
'password' => '',
|
||||||
// $name = OAuth::splitName($socialite_user->getName());
|
'email' => $socialite_user->getEmail(),
|
||||||
|
'oauth_user_id' => $socialite_user->getId(),
|
||||||
|
'oauth_provider_id' => $provider,
|
||||||
|
'oauth_user_token' => $socialite_user->refreshToken,
|
||||||
|
];
|
||||||
|
|
||||||
// $new_account = [
|
$user->update($update_user);
|
||||||
// 'first_name' => $name[0],
|
|
||||||
// 'last_name' => $name[1],
|
|
||||||
// 'password' => '',
|
|
||||||
// 'email' => $socialite_user->getEmail(),
|
|
||||||
// 'oauth_user_id' => $socialite_user->getId(),
|
|
||||||
// 'oauth_provider_id' => $provider
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// $account = CreateAccount::dispatchNow($new_account);
|
|
||||||
|
|
||||||
// Auth::login($account->default_company->owner(), true);
|
|
||||||
|
|
||||||
// $cookie = cookie('db', $account->default_company->db);
|
|
||||||
|
|
||||||
// return redirect($this->redirectTo)->withCookie($cookie);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
nlog("user not found for oauth");
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect('/#/');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,18 +55,21 @@ class InvitationController extends Controller
|
|||||||
->firstOrFail();
|
->firstOrFail();
|
||||||
|
|
||||||
/* Return early if we have the correct client_hash embedded */
|
/* Return early if we have the correct client_hash embedded */
|
||||||
|
$client_contact = $invitation->contact;
|
||||||
|
|
||||||
|
if(empty($client_contact->email))
|
||||||
|
$client_contact->email = Str::random(15) . "@example.com"; $client_contact->save();
|
||||||
|
|
||||||
if (request()->has('client_hash') && request()->input('client_hash') == $invitation->contact->client->client_hash) {
|
if (request()->has('client_hash') && request()->input('client_hash') == $invitation->contact->client->client_hash) {
|
||||||
auth()->guard('contact')->loginUsingId($invitation->contact->id, true);
|
auth()->guard('contact')->login($client_contact, true);
|
||||||
|
|
||||||
} elseif ((bool) $invitation->contact->client->getSetting('enable_client_portal_password') !== false) {
|
} elseif ((bool) $invitation->contact->client->getSetting('enable_client_portal_password') !== false) {
|
||||||
|
|
||||||
//If no contact password is set - this will cause a 401 error - instead redirect to the client.login route
|
|
||||||
$this->middleware('auth:contact');
|
$this->middleware('auth:contact');
|
||||||
return redirect()->route('client.login');
|
return redirect()->route('client.login');
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
auth()->guard('contact')->loginUsingId($invitation->contact->id, true);
|
nlog("else - default - login contact");
|
||||||
|
auth()->guard('contact')->login($client_contact, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ use App\Transformers\DesignTransformer;
|
|||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class DesignController.
|
* Class DesignController.
|
||||||
@ -412,6 +413,7 @@ class DesignController extends BaseController
|
|||||||
{
|
{
|
||||||
//may not need these destroy routes as we are using actions to 'archive/delete'
|
//may not need these destroy routes as we are using actions to 'archive/delete'
|
||||||
$design->is_deleted = true;
|
$design->is_deleted = true;
|
||||||
|
$design->name = $design->name . "_deleted_" . Str::random(5);
|
||||||
$design->delete();
|
$design->delete();
|
||||||
$design->save();
|
$design->save();
|
||||||
|
|
||||||
|
42
app/Http/Controllers/Gateways/Checkout3dsController.php
Normal file
42
app/Http/Controllers/Gateways/Checkout3dsController.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Gateways;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Gateways\Checkout3ds\Checkout3dsRequest;
|
||||||
|
|
||||||
|
class Checkout3dsController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Checkout3dsRequest $request, string $company_key, string $company_gateway_id, string $hash)
|
||||||
|
{
|
||||||
|
if (!$request->getCompany()) {
|
||||||
|
return response()->json(['message' => 'Company record not found.', 'company_key' => $company_key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$request->getCompanyGateway()) {
|
||||||
|
return response()->json(['message' => 'Company gateway record not found.', 'company_gateway_id' => $company_gateway_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$request->getPaymentHash()) {
|
||||||
|
return response()->json(['message' => 'Hash record not found.', 'hash' => $hash]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$request->getClient()) {
|
||||||
|
return response()->json(['message' => 'Client record not found.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $request->getCompanyGateway()
|
||||||
|
->driver($request->getClient())
|
||||||
|
->process3dsConfirmation($request);
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ use App\Utils\Traits\MakesHash;
|
|||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use ZipArchive;
|
||||||
|
|
||||||
class ImportJsonController extends BaseController
|
class ImportJsonController extends BaseController
|
||||||
{
|
{
|
||||||
@ -56,7 +57,7 @@ class ImportJsonController extends BaseController
|
|||||||
* ),
|
* ),
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
public function index(ImportJsonRequest $request)
|
public function import(ImportJsonRequest $request)
|
||||||
{
|
{
|
||||||
|
|
||||||
$import_file = $request->file('files');
|
$import_file = $request->file('files');
|
||||||
@ -65,9 +66,11 @@ class ImportJsonController extends BaseController
|
|||||||
|
|
||||||
$hash = Str::random(32);
|
$hash = Str::random(32);
|
||||||
|
|
||||||
|
nlog($hash);
|
||||||
|
|
||||||
Cache::put( $hash, base64_encode( $contents ), 3600 );
|
Cache::put( $hash, base64_encode( $contents ), 3600 );
|
||||||
|
|
||||||
CompanyImport::dispatch(auth()->user()->getCompany(), auth()->user(), $hash, $request->all());
|
CompanyImport::dispatch(auth()->user()->getCompany(), auth()->user(), $hash, $request->except('files'))->delay(now()->addMinutes(1));
|
||||||
|
|
||||||
return response()->json(['message' => 'Processing'], 200);
|
return response()->json(['message' => 'Processing'], 200);
|
||||||
|
|
||||||
@ -86,11 +89,11 @@ class ImportJsonController extends BaseController
|
|||||||
if (! file_exists($file_location))
|
if (! file_exists($file_location))
|
||||||
throw new NonExistingMigrationFile('Backup file does not exist, or is corrupted.');
|
throw new NonExistingMigrationFile('Backup file does not exist, or is corrupted.');
|
||||||
|
|
||||||
$data = json_decode(file_get_contents($file_location));
|
$data = file_get_contents($file_location);
|
||||||
|
|
||||||
unlink($file_contents);
|
unlink($file_contents);
|
||||||
unlink($file_location);
|
unlink($file_location);
|
||||||
|
|
||||||
return $data
|
return $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,4 +71,12 @@ class TwoFactorController extends BaseController
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function disableTwoFactor()
|
||||||
|
{
|
||||||
|
$user = auth()->user();
|
||||||
|
$user->google_2fa_secret = null;
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
return $this->itemResponse($user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ class Kernel extends HttpKernel
|
|||||||
TrimStrings::class,
|
TrimStrings::class,
|
||||||
ConvertEmptyStringsToNull::class,
|
ConvertEmptyStringsToNull::class,
|
||||||
TrustProxies::class,
|
TrustProxies::class,
|
||||||
//\Fruitcake\Cors\HandleCors::class,
|
// \Fruitcake\Cors\HandleCors::class,
|
||||||
Cors::class,
|
Cors::class,
|
||||||
|
|
||||||
];
|
];
|
||||||
@ -85,7 +85,6 @@ class Kernel extends HttpKernel
|
|||||||
EncryptCookies::class,
|
EncryptCookies::class,
|
||||||
AddQueuedCookiesToResponse::class,
|
AddQueuedCookiesToResponse::class,
|
||||||
StartSession::class,
|
StartSession::class,
|
||||||
// \Illuminate\Session\Middleware\AuthenticateSession::class,
|
|
||||||
ShareErrorsFromSession::class,
|
ShareErrorsFromSession::class,
|
||||||
VerifyCsrfToken::class,
|
VerifyCsrfToken::class,
|
||||||
SubstituteBindings::class,
|
SubstituteBindings::class,
|
||||||
@ -96,7 +95,6 @@ class Kernel extends HttpKernel
|
|||||||
'throttle:300,1',
|
'throttle:300,1',
|
||||||
'bindings',
|
'bindings',
|
||||||
'query_logging',
|
'query_logging',
|
||||||
Cors::class,
|
|
||||||
],
|
],
|
||||||
'contact' => [
|
'contact' => [
|
||||||
'throttle:60,1',
|
'throttle:60,1',
|
||||||
@ -154,7 +152,7 @@ class Kernel extends HttpKernel
|
|||||||
'api_db' => SetDb::class,
|
'api_db' => SetDb::class,
|
||||||
'company_key_db' => SetDbByCompanyKey::class,
|
'company_key_db' => SetDbByCompanyKey::class,
|
||||||
'locale' => Locale::class,
|
'locale' => Locale::class,
|
||||||
'contact.register' => ContactRegister::class,
|
'contact_register' => ContactRegister::class,
|
||||||
'shop_token_auth' => ShopTokenAuth::class,
|
'shop_token_auth' => ShopTokenAuth::class,
|
||||||
'phantom_secret' => PhantomSecret::class,
|
'phantom_secret' => PhantomSecret::class,
|
||||||
'contact_key_login' => ContactKeyLogin::class,
|
'contact_key_login' => ContactKeyLogin::class,
|
||||||
@ -164,6 +162,7 @@ class Kernel extends HttpKernel
|
|||||||
|
|
||||||
|
|
||||||
protected $middlewarePriority = [
|
protected $middlewarePriority = [
|
||||||
|
Cors::class,
|
||||||
SetDomainNameDb::class,
|
SetDomainNameDb::class,
|
||||||
SetDb::class,
|
SetDb::class,
|
||||||
SetWebDb::class,
|
SetWebDb::class,
|
||||||
|
@ -14,11 +14,12 @@ namespace App\Http\Livewire;
|
|||||||
use App\Factory\ClientFactory;
|
use App\Factory\ClientFactory;
|
||||||
use App\Jobs\Mail\NinjaMailerJob;
|
use App\Jobs\Mail\NinjaMailerJob;
|
||||||
use App\Jobs\Mail\NinjaMailerObject;
|
use App\Jobs\Mail\NinjaMailerObject;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Mail\ContactPasswordlessLogin;
|
use App\Mail\ContactPasswordlessLogin;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Subscription;
|
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Subscription;
|
||||||
use App\Repositories\ClientContactRepository;
|
use App\Repositories\ClientContactRepository;
|
||||||
use App\Repositories\ClientRepository;
|
use App\Repositories\ClientRepository;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
@ -162,8 +163,24 @@ class BillingPortalPurchase extends Component
|
|||||||
*/
|
*/
|
||||||
public $passwordless_login_btn = false;
|
public $passwordless_login_btn = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of company.
|
||||||
|
*
|
||||||
|
* @var Company
|
||||||
|
*/
|
||||||
|
public $company;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Campaign reference.
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
public $campaign;
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
$this->price = $this->subscription->price;
|
$this->price = $this->subscription->price;
|
||||||
|
|
||||||
if (request()->query('coupon')) {
|
if (request()->query('coupon')) {
|
||||||
@ -262,7 +279,7 @@ class BillingPortalPurchase extends Component
|
|||||||
*/
|
*/
|
||||||
protected function getPaymentMethods(ClientContact $contact): self
|
protected function getPaymentMethods(ClientContact $contact): self
|
||||||
{
|
{
|
||||||
Auth::guard('contact')->login($contact);
|
Auth::guard('contact')->login($contact, true);
|
||||||
|
|
||||||
$this->contact = $contact;
|
$this->contact = $contact;
|
||||||
|
|
||||||
@ -273,7 +290,7 @@ class BillingPortalPurchase extends Component
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((int)$this->subscription->price == 0)
|
if ((int)$this->subscription->price == 0)
|
||||||
$this->steps['payment_required'] = false;
|
$this->steps['payment_required'] = false;
|
||||||
else
|
else
|
||||||
$this->steps['fetched_payment_methods'] = true;
|
$this->steps['fetched_payment_methods'] = true;
|
||||||
@ -332,9 +349,9 @@ class BillingPortalPurchase extends Component
|
|||||||
|
|
||||||
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
||||||
|
|
||||||
if ($is_eligible['exception']['message'] != 'Success') {
|
if (is_array($is_eligible) && $is_eligible['message'] != 'Success') {
|
||||||
$this->steps['not_eligible'] = true;
|
$this->steps['not_eligible'] = true;
|
||||||
$this->steps['not_eligible_message'] = $is_eligible['exception']['message'];
|
$this->steps['not_eligible_message'] = $is_eligible['message'];
|
||||||
$this->steps['show_loading_bar'] = false;
|
$this->steps['show_loading_bar'] = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -346,8 +363,8 @@ class BillingPortalPurchase extends Component
|
|||||||
'client_id' => $this->contact->client->id,
|
'client_id' => $this->contact->client->id,
|
||||||
'invoice_id' => $this->invoice->id,
|
'invoice_id' => $this->invoice->id,
|
||||||
'context' => 'purchase',
|
'context' => 'purchase',
|
||||||
now()->addMinutes(60)]
|
'campaign' => $this->campaign,
|
||||||
);
|
], now()->addMinutes(60));
|
||||||
|
|
||||||
$this->emit('beforePaymentEventsCompleted');
|
$this->emit('beforePaymentEventsCompleted');
|
||||||
}
|
}
|
||||||
@ -374,7 +391,7 @@ class BillingPortalPurchase extends Component
|
|||||||
|
|
||||||
if ($is_eligible['status_code'] != 200) {
|
if ($is_eligible['status_code'] != 200) {
|
||||||
$this->steps['not_eligible'] = true;
|
$this->steps['not_eligible'] = true;
|
||||||
$this->steps['not_eligible_message'] = $is_eligible['exception']['message'];
|
$this->steps['not_eligible_message'] = $is_eligible['message'];
|
||||||
$this->steps['show_loading_bar'] = false;
|
$this->steps['show_loading_bar'] = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -434,7 +451,7 @@ class BillingPortalPurchase extends Component
|
|||||||
->first();
|
->first();
|
||||||
|
|
||||||
$mailer = new NinjaMailerObject();
|
$mailer = new NinjaMailerObject();
|
||||||
$mailer->mailable = new ContactPasswordlessLogin($this->email, (string)route('client.subscription.purchase', $this->subscription->hashed_id) . '?coupon=' . $this->coupon);
|
$mailer->mailable = new ContactPasswordlessLogin($this->email, $this->subscription->company->id, (string)route('client.subscription.purchase', $this->subscription->hashed_id) . '?coupon=' . $this->coupon);
|
||||||
$mailer->company = $this->subscription->company;
|
$mailer->company = $this->subscription->company;
|
||||||
$mailer->settings = $this->subscription->company->settings;
|
$mailer->settings = $this->subscription->company->settings;
|
||||||
$mailer->to_user = $contact;
|
$mailer->to_user = $contact;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
use App\Utils\Traits\WithSorting;
|
use App\Utils\Traits\WithSorting;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -24,6 +25,13 @@ class CreditsTable extends Component
|
|||||||
|
|
||||||
public $per_page = 10;
|
public $per_page = 10;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
$query = Credit::query()
|
$query = Credit::query()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Utils\Traits\WithSorting;
|
use App\Utils\Traits\WithSorting;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -25,8 +26,13 @@ class DocumentsTable extends Component
|
|||||||
|
|
||||||
public $per_page = 10;
|
public $per_page = 10;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
public function mount($client)
|
public function mount($client)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Utils\Traits\WithSorting;
|
use App\Utils\Traits\WithSorting;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@ -26,8 +27,12 @@ class InvoicesTable extends Component
|
|||||||
|
|
||||||
public $status = [];
|
public $status = [];
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
$this->sort_asc = false;
|
$this->sort_asc = false;
|
||||||
|
|
||||||
$this->sort_field = 'date';
|
$this->sort_field = 'date';
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class PayNowDropdown extends Component
|
class PayNowDropdown extends Component
|
||||||
@ -20,8 +21,12 @@ class PayNowDropdown extends Component
|
|||||||
|
|
||||||
public $methods;
|
public $methods;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
public function mount(int $total)
|
public function mount(int $total)
|
||||||
{
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
$this->total = $total;
|
$this->total = $total;
|
||||||
|
|
||||||
$this->methods = auth()->user()->client->service()->getPaymentMethods($total);
|
$this->methods = auth()->user()->client->service()->getPaymentMethods($total);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\ClientGatewayToken;
|
use App\Models\ClientGatewayToken;
|
||||||
use App\Utils\Traits\WithSorting;
|
use App\Utils\Traits\WithSorting;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -16,10 +17,16 @@ class PaymentMethodsTable extends Component
|
|||||||
use WithSorting;
|
use WithSorting;
|
||||||
|
|
||||||
public $per_page = 10;
|
public $per_page = 10;
|
||||||
|
|
||||||
public $client;
|
public $client;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
public function mount($client)
|
public function mount($client)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Utils\Traits\WithSorting;
|
use App\Utils\Traits\WithSorting;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -23,11 +24,17 @@ class PaymentsTable extends Component
|
|||||||
use WithPagination;
|
use WithPagination;
|
||||||
|
|
||||||
public $per_page = 10;
|
public $per_page = 10;
|
||||||
|
|
||||||
public $user;
|
public $user;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
$this->user = auth()->user();
|
$this->user = auth()->user();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
use App\Utils\Traits\WithSorting;
|
use App\Utils\Traits\WithSorting;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -23,8 +24,17 @@ class QuotesTable extends Component
|
|||||||
use WithPagination;
|
use WithPagination;
|
||||||
|
|
||||||
public $per_page = 10;
|
public $per_page = 10;
|
||||||
|
|
||||||
public $status = [];
|
public $status = [];
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
$query = Quote::query()
|
$query = Quote::query()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\RecurringInvoice;
|
use App\Models\RecurringInvoice;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
@ -22,6 +23,18 @@ class RecurringInvoiceCancellation extends Component
|
|||||||
*/
|
*/
|
||||||
public $invoice;
|
public $invoice;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return render('components.livewire.recurring-invoice-cancellation');
|
||||||
|
}
|
||||||
|
|
||||||
public function processCancellation()
|
public function processCancellation()
|
||||||
{
|
{
|
||||||
if ($this->invoice->subscription) {
|
if ($this->invoice->subscription) {
|
||||||
@ -31,8 +44,5 @@ class RecurringInvoiceCancellation extends Component
|
|||||||
return redirect()->route('client.recurring_invoices.request_cancellation', ['recurring_invoice' => $this->invoice->hashed_id]);
|
return redirect()->route('client.recurring_invoices.request_cancellation', ['recurring_invoice' => $this->invoice->hashed_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render()
|
|
||||||
{
|
|
||||||
return render('components.livewire.recurring-invoice-cancellation');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
@ -65,7 +66,12 @@ class RequiredClientInfo extends Component
|
|||||||
|
|
||||||
public $show_form = false;
|
public $show_form = false;
|
||||||
|
|
||||||
public function mount() {}
|
public $company;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
}
|
||||||
|
|
||||||
public function handleSubmit(array $data): bool
|
public function handleSubmit(array $data): bool
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\Subscription;
|
use App\Models\Subscription;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
@ -71,8 +72,12 @@ class SubscriptionPlanSwitch extends Component
|
|||||||
*/
|
*/
|
||||||
public $hash;
|
public $hash;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
$this->total = $this->amount;
|
$this->total = $this->amount;
|
||||||
|
|
||||||
$this->methods = $this->contact->client->service()->getPaymentMethods($this->amount);
|
$this->methods = $this->contact->client->service()->getPaymentMethods($this->amount);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\RecurringInvoice;
|
use App\Models\RecurringInvoice;
|
||||||
use App\Utils\Traits\WithSorting;
|
use App\Utils\Traits\WithSorting;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -24,6 +25,13 @@ class SubscriptionRecurringInvoicesTable extends Component
|
|||||||
|
|
||||||
public $per_page = 10;
|
public $per_page = 10;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
$query = RecurringInvoice::query()
|
$query = RecurringInvoice::query()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Utils\Traits\WithSorting;
|
use App\Utils\Traits\WithSorting;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -24,6 +25,13 @@ class TasksTable extends Component
|
|||||||
|
|
||||||
public $per_page = 10;
|
public $per_page = 10;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
MultiDB::setDb($this->company->db);
|
||||||
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
$query = Task::query()
|
$query = Task::query()
|
||||||
|
@ -39,7 +39,25 @@ class ContactKeyLogin
|
|||||||
Auth::guard('contact')->logout();
|
Auth::guard('contact')->logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->segment(3) && config('ninja.db.multi_db_enabled')) {
|
if ($request->segment(2) && $request->segment(2) == 'magic_link' && $request->segment(3)) {
|
||||||
|
$payload = Cache::get($request->segment(3));
|
||||||
|
$contact_email = $payload['email'];
|
||||||
|
|
||||||
|
if($client_contact = ClientContact::where('email', $contact_email)->where('company_id', $payload['company_id'])->first()){
|
||||||
|
|
||||||
|
if(empty($client_contact->email))
|
||||||
|
$client_contact->email = Str::random(15) . "@example.com"; $client_contact->save();
|
||||||
|
|
||||||
|
auth()->guard('contact')->login($client_contact, true);
|
||||||
|
|
||||||
|
if ($request->query('redirect') && !empty($request->query('redirect'))) {
|
||||||
|
return redirect()->to($request->query('redirect'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->to('client/dashboard');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($request->segment(3) && config('ninja.db.multi_db_enabled')) {
|
||||||
if (MultiDB::findAndSetDbByContactKey($request->segment(3))) {
|
if (MultiDB::findAndSetDbByContactKey($request->segment(3))) {
|
||||||
|
|
||||||
if($client_contact = ClientContact::where('contact_key', $request->segment(3))->first()){
|
if($client_contact = ClientContact::where('contact_key', $request->segment(3))->first()){
|
||||||
@ -84,21 +102,6 @@ class ContactKeyLogin
|
|||||||
|
|
||||||
auth()->guard('contact')->login($primary_contact, true);
|
auth()->guard('contact')->login($primary_contact, true);
|
||||||
|
|
||||||
return redirect()->to('client/dashboard');
|
|
||||||
}
|
|
||||||
} elseif ($request->segment(2) && $request->segment(2) == 'magic_link' && $request->segment(3)) {
|
|
||||||
$contact_email = Cache::get($request->segment(3));
|
|
||||||
if($client_contact = ClientContact::where('email', $contact_email)->first()){
|
|
||||||
|
|
||||||
if(empty($client_contact->email))
|
|
||||||
$client_contact->email = Str::random(6) . "@example.com"; $client_contact->save();
|
|
||||||
|
|
||||||
auth()->guard('contact')->login($client_contact, true);
|
|
||||||
|
|
||||||
if ($request->query('redirect') && !empty($request->query('redirect'))) {
|
|
||||||
return redirect()->to($request->query('redirect'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->to('client/dashboard');
|
return redirect()->to('client/dashboard');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,17 +19,44 @@ class ContactRegister
|
|||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
// Resolving based on subdomain. Used in version 5 hosted platform.
|
|
||||||
if ($request->subdomain) {
|
|
||||||
$company = Company::where('subdomain', $request->subdomain)->firstOrFail();
|
|
||||||
|
|
||||||
abort_unless($company->getSetting('enable_client_registration'), 404);
|
if (strpos($request->getHost(), 'invoicing.co') !== false)
|
||||||
|
{
|
||||||
|
$subdomain = explode('.', $request->getHost())[0];
|
||||||
|
|
||||||
|
$query = [
|
||||||
|
'subdomain' => $subdomain,
|
||||||
|
'portal_mode' => 'subdomain',
|
||||||
|
];
|
||||||
|
|
||||||
|
$company = Company::where($query)->first();
|
||||||
|
|
||||||
|
if($company)
|
||||||
|
{
|
||||||
|
abort_unless($company->client_can_register, 404);
|
||||||
|
|
||||||
$request->merge(['key' => $company->company_key]);
|
$request->merge(['key' => $company->company_key]);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = [
|
||||||
|
'portal_domain' => $request->getSchemeAndHttpHost(),
|
||||||
|
'portal_mode' => 'domain',
|
||||||
|
];
|
||||||
|
|
||||||
|
if($company = Company::where($query)->first())
|
||||||
|
{
|
||||||
|
abort_unless($company->client_can_register, 404);
|
||||||
|
|
||||||
|
$request->merge(['key' => $company->company_key]);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// For self-hosted platforms with multiple companies, resolving is done using company key
|
// For self-hosted platforms with multiple companies, resolving is done using company key
|
||||||
// if it doesn't resolve using a domain.
|
// if it doesn't resolve using a domain.
|
||||||
if ($request->route()->parameter('company_key') && Ninja::isSelfHost()) {
|
if ($request->route()->parameter('company_key') && Ninja::isSelfHost()) {
|
||||||
|
@ -16,7 +16,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-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,Range',
|
'Access-Control-Allow-Headers'=> '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,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE',
|
||||||
];
|
];
|
||||||
|
|
||||||
return Response::make('OK', 200, $headers);
|
return Response::make('OK', 200, $headers);
|
||||||
@ -26,7 +26,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-COMPANY-KEY,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range');
|
$response->headers->set('Access-Control-Allow-Headers', '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,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE');
|
||||||
$response->headers->set('Access-Control-Expose-Headers', 'X-APP-VERSION,X-MINIMUM-CLIENT-VERSION');
|
$response->headers->set('Access-Control-Expose-Headers', 'X-APP-VERSION,X-MINIMUM-CLIENT-VERSION');
|
||||||
$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'));
|
||||||
|
@ -86,6 +86,7 @@ class SetDomainNameDb
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// config(['app.url' => $request->getSchemeAndHttpHost()]);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,6 @@ class VerifyCsrfToken extends Middleware
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $except = [
|
protected $except = [
|
||||||
//
|
// 'livewire/message/*'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Gateways\Checkout3ds;
|
||||||
|
|
||||||
|
use App\Models\Client;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\CompanyGateway;
|
||||||
|
use App\Models\PaymentHash;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class Checkout3dsRequest extends FormRequest
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompany()
|
||||||
|
{
|
||||||
|
return Company::where('company_key', $this->company_key)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompanyGateway()
|
||||||
|
{
|
||||||
|
return CompanyGateway::find($this->decodePrimaryKey($this->company_gateway_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPaymentHash()
|
||||||
|
{
|
||||||
|
return PaymentHash::where('hash', $this->hash)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClient()
|
||||||
|
{
|
||||||
|
return Client::find($this->getPaymentHash()->data->client_id);
|
||||||
|
}
|
||||||
|
}
|
@ -100,14 +100,15 @@ class PaymentWebhookRequest extends Request
|
|||||||
/**
|
/**
|
||||||
* Resolve client from payment hash.
|
* Resolve client from payment hash.
|
||||||
*
|
*
|
||||||
* @return null|\App\Models\Client
|
* @return null|\App\Models\Client|bool
|
||||||
*/
|
*/
|
||||||
public function getClient()
|
public function getClient()
|
||||||
{
|
{
|
||||||
$hash = $this->getPaymentHash();
|
$hash = $this->getPaymentHash();
|
||||||
|
|
||||||
if($hash)
|
if($hash) {
|
||||||
return Client::find($hash->data->client_id)->firstOrFail();
|
return Client::find($hash->data->client_id)->firstOrFail();
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,6 @@ class CreateAccount
|
|||||||
|
|
||||||
$sp035a66 = CreateCompany::dispatchNow($this->request, $sp794f3f);
|
$sp035a66 = CreateCompany::dispatchNow($this->request, $sp794f3f);
|
||||||
$sp035a66->load('account');
|
$sp035a66->load('account');
|
||||||
$sp035a66->settings = $this->processSettings($sp035a66->settings);
|
|
||||||
$sp794f3f->default_company_id = $sp035a66->id;
|
$sp794f3f->default_company_id = $sp035a66->id;
|
||||||
$sp794f3f->save();
|
$sp794f3f->save();
|
||||||
|
|
||||||
@ -116,11 +115,12 @@ class CreateAccount
|
|||||||
|
|
||||||
private function processSettings($settings)
|
private function processSettings($settings)
|
||||||
{
|
{
|
||||||
if(Ninja::isHosted() && Cache::get('currencies') && $data = unserialize(@file_get_contents('http://www.geoplugin.net/php.gp?ip=' . $this->client_ip)))
|
if(Ninja::isHosted() && Cache::get('currencies'))
|
||||||
{
|
{
|
||||||
|
|
||||||
$currency_code = strtolower($data['geoplugin_currencyCode']);
|
//&& $data = unserialize(@file_get_contents('http://www.geoplugin.net/php.gp?ip=' . $this->client_ip))
|
||||||
$country_code = strtolower($data['geoplugin_countryCode']);
|
// $currency_code = strtolower($data['geoplugin_currencyCode']);
|
||||||
|
// $country_code = strtolower($data['geoplugin_countryCode']);
|
||||||
|
|
||||||
$currency = Cache::get('currencies')->filter(function ($item) use ($currency_code) {
|
$currency = Cache::get('currencies')->filter(function ($item) use ($currency_code) {
|
||||||
return strtolower($item->code) == $currency_code;
|
return strtolower($item->code) == $currency_code;
|
||||||
@ -146,7 +146,7 @@ class CreateAccount
|
|||||||
$settings->language_id = (string)$language->id;
|
$settings->language_id = (string)$language->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
$timezone = Timezone::where('name', $data['geoplugin_timezone'])->first();
|
//$timezone = Timezone::where('name', $data['geoplugin_timezone'])->first();
|
||||||
|
|
||||||
if($timezone) {
|
if($timezone) {
|
||||||
$settings->timezone_id = (string)$timezone->id;
|
$settings->timezone_id = (string)$timezone->id;
|
||||||
|
@ -168,7 +168,7 @@ class CompanyExport implements ShouldQueue
|
|||||||
|
|
||||||
$this->export_data['company'] = $this->company->toArray();
|
$this->export_data['company'] = $this->company->toArray();
|
||||||
|
|
||||||
$this->export_data['company_gateways'] = $this->company->company_gateways->map(function ($company_gateway){
|
$this->export_data['company_gateways'] = $this->company->company_gateways()->withTrashed()->cursor()->map(function ($company_gateway){
|
||||||
|
|
||||||
$company_gateway = $this->transformArrayOfKeys($company_gateway, ['company_id', 'user_id']);
|
$company_gateway = $this->transformArrayOfKeys($company_gateway, ['company_id', 'user_id']);
|
||||||
$company_gateway->config = decrypt($company_gateway->config);
|
$company_gateway->config = decrypt($company_gateway->config);
|
||||||
@ -480,6 +480,7 @@ class CompanyExport implements ShouldQueue
|
|||||||
|
|
||||||
$file_name = date('Y-m-d').'_'.str_replace(' ', '_', $this->company->present()->name() . '_' . $this->company->company_key .'.zip');
|
$file_name = date('Y-m-d').'_'.str_replace(' ', '_', $this->company->present()->name() . '_' . $this->company->company_key .'.zip');
|
||||||
|
|
||||||
|
Storage::makeDirectory(public_path('storage/backups/'), 0775);
|
||||||
$zip_path = public_path('storage/backups/'.$file_name);
|
$zip_path = public_path('storage/backups/'.$file_name);
|
||||||
$zip = new \ZipArchive();
|
$zip = new \ZipArchive();
|
||||||
|
|
||||||
@ -502,8 +503,6 @@ class CompanyExport implements ShouldQueue
|
|||||||
|
|
||||||
NinjaMailerJob::dispatch($nmo);
|
NinjaMailerJob::dispatch($nmo);
|
||||||
|
|
||||||
UnlinkFile::dispatch(config('filesystems.default'), 'backups/'.$file_name)->delay(now()->addHours(1));
|
|
||||||
UnlinkFile::dispatch('public', 'backups/'.$file_name)->delay(now()->addHours(1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@ use App\Jobs\Util\UnlinkFile;
|
|||||||
use App\Libraries\MultiDB;
|
use App\Libraries\MultiDB;
|
||||||
use App\Mail\DownloadBackup;
|
use App\Mail\DownloadBackup;
|
||||||
use App\Mail\DownloadInvoices;
|
use App\Mail\DownloadInvoices;
|
||||||
|
use App\Mail\Import\CompanyImportFailure;
|
||||||
use App\Models\Activity;
|
use App\Models\Activity;
|
||||||
|
use App\Models\Backup;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\ClientGatewayToken;
|
use App\Models\ClientGatewayToken;
|
||||||
@ -40,6 +42,7 @@ use App\Models\Payment;
|
|||||||
use App\Models\PaymentTerm;
|
use App\Models\PaymentTerm;
|
||||||
use App\Models\Paymentable;
|
use App\Models\Paymentable;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\Models\Project;
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
use App\Models\QuoteInvitation;
|
use App\Models\QuoteInvitation;
|
||||||
use App\Models\RecurringInvoice;
|
use App\Models\RecurringInvoice;
|
||||||
@ -59,6 +62,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
|||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use ZipArchive;
|
use ZipArchive;
|
||||||
@ -85,6 +89,10 @@ class CompanyImport implements ShouldQueue
|
|||||||
|
|
||||||
private $request_array = [];
|
private $request_array = [];
|
||||||
|
|
||||||
|
public $message = '';
|
||||||
|
|
||||||
|
public $pre_flight_checks_pass = true;
|
||||||
|
|
||||||
private $importables = [
|
private $importables = [
|
||||||
// 'company',
|
// 'company',
|
||||||
'users',
|
'users',
|
||||||
@ -145,28 +153,128 @@ class CompanyImport implements ShouldQueue
|
|||||||
$this->company = Company::where('company_key', $this->company->company_key)->firstOrFail();
|
$this->company = Company::where('company_key', $this->company->company_key)->firstOrFail();
|
||||||
$this->account = $this->company->account;
|
$this->account = $this->company->account;
|
||||||
|
|
||||||
|
nlog("Company ID = {$this->company->id}");
|
||||||
|
nlog("Hash ID = {$this->hash}");
|
||||||
|
|
||||||
$this->backup_file = Cache::get($this->hash);
|
$this->backup_file = Cache::get($this->hash);
|
||||||
|
|
||||||
if ( empty( $this->backup_file ) )
|
if ( empty( $this->backup_file ) )
|
||||||
throw new \Exception('No import data found, has the cache expired?');
|
throw new \Exception('No import data found, has the cache expired?');
|
||||||
|
|
||||||
$this->backup_file = base64_decode($this->backup_file);
|
$this->backup_file = json_decode(base64_decode($this->backup_file));
|
||||||
|
|
||||||
|
// nlog($this->backup_file);
|
||||||
|
|
||||||
if(array_key_exists('import_settings', $request) && $request['import_settings'] == 'true') {
|
if(array_key_exists('import_settings', $this->request_array) && $this->request_array['import_settings'] == 'true') {
|
||||||
$this->preFlightChecks()->importSettings();
|
$this->checkUserCount()->preFlightChecks()->importSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(array_key_exists('import_data', $request) && $request['import_data'] == 'true') {
|
if(array_key_exists('import_data', $this->request_array) && $this->request_array['import_data'] == 'true') {
|
||||||
|
|
||||||
$this->preFlightChecks()
|
try{
|
||||||
|
|
||||||
|
$this->checkUserCount()
|
||||||
|
->preFlightChecks()
|
||||||
->purgeCompanyData()
|
->purgeCompanyData()
|
||||||
->importData();
|
->importData();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
|
||||||
|
info($e->getMessage());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On the hosted platform we cannot allow the
|
||||||
|
* import to start if there are users > plan number
|
||||||
|
* due to entity user_id dependencies
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkUserCount()
|
||||||
|
{
|
||||||
|
|
||||||
|
if(Ninja::isSelfHost())
|
||||||
|
$this->pre_flight_checks_pass = true;
|
||||||
|
|
||||||
|
$backup_users = $this->backup_file->users;
|
||||||
|
|
||||||
|
$company_users = $this->company->users;
|
||||||
|
|
||||||
|
$company_owner = $this->company->owner();
|
||||||
|
|
||||||
|
if($this->company->account->isFreeHostedClient()){
|
||||||
|
|
||||||
|
nlog("This is a free account");
|
||||||
|
nlog("Backup user count = ".count($backup_users));
|
||||||
|
|
||||||
|
if(count($backup_users) > 1){
|
||||||
|
$this->message = 'Only one user can be in the import for a Free Account';
|
||||||
|
$this->pre_flight_checks_pass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlog("backup users email = " . $backup_users[0]->email);
|
||||||
|
|
||||||
|
if(count($backup_users) == 1 && $company_owner->email != $backup_users[0]->email) {
|
||||||
|
$this->message = 'Account emails do not match. Account owner email must match backup user email';
|
||||||
|
$this->pre_flight_checks_pass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$backup_users_emails = array_column($backup_users, 'email');
|
||||||
|
|
||||||
|
$company_users_emails = $company_users->pluck('email')->toArray();
|
||||||
|
|
||||||
|
$existing_user_count = count(array_intersect($backup_users_emails, $company_users_emails));
|
||||||
|
|
||||||
|
nlog("existing user count = {$existing_user_count}");
|
||||||
|
|
||||||
|
if($existing_user_count > 1){
|
||||||
|
|
||||||
|
if($this->account->plan == 'pro'){
|
||||||
|
$this->message = 'Pro plan is limited to one user, you have multiple users in the backup file';
|
||||||
|
$this->pre_flight_checks_pass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->account->plan == 'enterprise'){
|
||||||
|
|
||||||
|
$total_import_users = count($backup_users_emails);
|
||||||
|
|
||||||
|
$account_plan_num_user = $this->account->num_users;
|
||||||
|
|
||||||
|
if($total_import_users > $account_plan_num_user){
|
||||||
|
$this->message = "Total user count ({$total_import_users}) greater than your plan allows ({$account_plan_num_user})";
|
||||||
|
$this->pre_flight_checks_pass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->company->account->isFreeHostedClient() && count($this->backup_file->clients) > config('ninja.quotas.free.clients')){
|
||||||
|
|
||||||
|
nlog("client quota busted");
|
||||||
|
|
||||||
|
$client_count = count($this->backup_file->clients);
|
||||||
|
|
||||||
|
$client_limit = config('ninja.quotas.free.clients');
|
||||||
|
|
||||||
|
$this->message = "You are attempting to import ({$client_count}) clients, your current plan allows a total of ({$client_limit})";
|
||||||
|
|
||||||
|
$this->pre_flight_checks_pass = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nlog($this->message);
|
||||||
|
nlog($this->pre_flight_checks_pass);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
//check if this is a complete company import OR if it is selective
|
//check if this is a complete company import OR if it is selective
|
||||||
/*
|
/*
|
||||||
@ -177,12 +285,23 @@ class CompanyImport implements ShouldQueue
|
|||||||
private function preFlightChecks()
|
private function preFlightChecks()
|
||||||
{
|
{
|
||||||
//check the file version and perform any necessary adjustments to the file in order to proceed - needed when we change schema
|
//check the file version and perform any necessary adjustments to the file in order to proceed - needed when we change schema
|
||||||
|
|
||||||
if($this->current_app_version != $this->backup_file->app_version)
|
if($this->current_app_version != $this->backup_file->app_version)
|
||||||
{
|
{
|
||||||
//perform some magic here
|
//perform some magic here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($this->pre_flight_checks_pass === false)
|
||||||
|
{
|
||||||
|
$nmo = new NinjaMailerObject;
|
||||||
|
$nmo->mailable = new CompanyImportFailure($this->company, $this->message);
|
||||||
|
$nmo->company = $this->company;
|
||||||
|
$nmo->settings = $this->company->settings;
|
||||||
|
$nmo->to_user = $this->company->owner();
|
||||||
|
NinjaMailerJob::dispatchNow($nmo);
|
||||||
|
|
||||||
|
nlog($this->message);
|
||||||
|
throw new \Exception($this->message);
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -236,10 +355,14 @@ class CompanyImport implements ShouldQueue
|
|||||||
|
|
||||||
$method = "import_{$import}";
|
$method = "import_{$import}";
|
||||||
|
|
||||||
|
nlog($method);
|
||||||
|
|
||||||
$this->{$method}();
|
$this->{$method}();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nlog("finished importing company data");
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -278,6 +401,8 @@ class CompanyImport implements ShouldQueue
|
|||||||
$obj_array,
|
$obj_array,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$new_obj->company_id = $this->company->id;
|
||||||
|
$new_obj->user_id = $user_id;
|
||||||
$new_obj->save(['timestamps' => false]);
|
$new_obj->save(['timestamps' => false]);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -328,8 +453,8 @@ class CompanyImport implements ShouldQueue
|
|||||||
{
|
{
|
||||||
|
|
||||||
$this->genericImport(ClientContact::class,
|
$this->genericImport(ClientContact::class,
|
||||||
['user_id', 'assigned_user_id', 'company_id', 'id', 'hashed_id'],
|
['user_id', 'company_id', 'id', 'hashed_id'],
|
||||||
[['users' => 'user_id'], ['users' => 'assigned_user_id']],
|
[['users' => 'user_id'], ['clients' => 'client_id']],
|
||||||
'client_contacts',
|
'client_contacts',
|
||||||
'email');
|
'email');
|
||||||
|
|
||||||
@ -644,24 +769,8 @@ class CompanyImport implements ShouldQueue
|
|||||||
|
|
||||||
$this->backup_file->activities = $activities;
|
$this->backup_file->activities = $activities;
|
||||||
|
|
||||||
$this->genericImport(Activity::class,
|
$this->genericNewClassImport(Activity::class,
|
||||||
[
|
[
|
||||||
'user_id',
|
|
||||||
'company_id',
|
|
||||||
'client_id',
|
|
||||||
'client_contact_id',
|
|
||||||
'project_id',
|
|
||||||
'vendor_id',
|
|
||||||
'payment_id',
|
|
||||||
'invoice_id',
|
|
||||||
'credit_id',
|
|
||||||
'invitation_id',
|
|
||||||
'task_id',
|
|
||||||
'expense_id',
|
|
||||||
'token_id',
|
|
||||||
'quote_id',
|
|
||||||
'subscription_id',
|
|
||||||
'recurring_invoice_id',
|
|
||||||
'hashed_id',
|
'hashed_id',
|
||||||
'company_id',
|
'company_id',
|
||||||
],
|
],
|
||||||
@ -681,8 +790,7 @@ class CompanyImport implements ShouldQueue
|
|||||||
['recurring_invoices' => 'recurring_invoice_id'],
|
['recurring_invoices' => 'recurring_invoice_id'],
|
||||||
['invitations' => 'invitation_id'],
|
['invitations' => 'invitation_id'],
|
||||||
],
|
],
|
||||||
'activities',
|
'activities');
|
||||||
'created_at');
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
||||||
@ -692,7 +800,7 @@ class CompanyImport implements ShouldQueue
|
|||||||
{
|
{
|
||||||
|
|
||||||
$this->genericImportWithoutCompany(Backup::class,
|
$this->genericImportWithoutCompany(Backup::class,
|
||||||
['activity_id','hashed_id'],
|
['hashed_id','id'],
|
||||||
[
|
[
|
||||||
['activities' => 'activity_id'],
|
['activities' => 'activity_id'],
|
||||||
],
|
],
|
||||||
@ -711,7 +819,7 @@ class CompanyImport implements ShouldQueue
|
|||||||
[
|
[
|
||||||
['users' => 'user_id'],
|
['users' => 'user_id'],
|
||||||
['clients' => 'client_id'],
|
['clients' => 'client_id'],
|
||||||
['activities' => 'activity_id'],
|
// ['activities' => 'activity_id'],
|
||||||
],
|
],
|
||||||
'company_ledger',
|
'company_ledger',
|
||||||
'created_at');
|
'created_at');
|
||||||
@ -802,9 +910,14 @@ class CompanyImport implements ShouldQueue
|
|||||||
if(User::where('email', $user->email)->where('account_id', '!=', $this->account->id)->exists())
|
if(User::where('email', $user->email)->where('account_id', '!=', $this->account->id)->exists())
|
||||||
throw new ImportCompanyFailed("{$user->email} is already in the system attached to a different account");
|
throw new ImportCompanyFailed("{$user->email} is already in the system attached to a different account");
|
||||||
|
|
||||||
|
$user_array = (array)$user;
|
||||||
|
unset($user_array['laravel_through_key']);
|
||||||
|
unset($user_array['hashed_id']);
|
||||||
|
unset($user_array['id']);
|
||||||
|
|
||||||
$new_user = User::firstOrNew(
|
$new_user = User::firstOrNew(
|
||||||
['email' => $user->email],
|
['email' => $user->email],
|
||||||
(array)$user,
|
$user_array,
|
||||||
);
|
);
|
||||||
|
|
||||||
$new_user->account_id = $this->account->id;
|
$new_user->account_id = $this->account->id;
|
||||||
@ -824,11 +937,14 @@ class CompanyImport implements ShouldQueue
|
|||||||
|
|
||||||
foreach($this->backup_file->company_users as $cu)
|
foreach($this->backup_file->company_users as $cu)
|
||||||
{
|
{
|
||||||
$user_id = $this->transformId($cu->user_id);
|
$user_id = $this->transformId('users', $cu->user_id);
|
||||||
|
|
||||||
|
$cu_array = (array)$cu;
|
||||||
|
unset($cu_array['id']);
|
||||||
|
|
||||||
$new_cu = CompanyUser::firstOrNew(
|
$new_cu = CompanyUser::firstOrNew(
|
||||||
['user_id' => $user_id, 'company_id', $this->company->id],
|
['user_id' => $user_id, 'company_id' => $this->company->id],
|
||||||
(array)$cu,
|
$cu_array,
|
||||||
);
|
);
|
||||||
|
|
||||||
$new_cu->account_id = $this->account->id;
|
$new_cu->account_id = $this->account->id;
|
||||||
@ -945,7 +1061,7 @@ class CompanyImport implements ShouldQueue
|
|||||||
|
|
||||||
$activity_invitation_key = false;
|
$activity_invitation_key = false;
|
||||||
|
|
||||||
if($class instanceof Activity){
|
if($class == 'App\Models\Activity'){
|
||||||
|
|
||||||
if(isset($obj->invitation_id)){
|
if(isset($obj->invitation_id)){
|
||||||
|
|
||||||
@ -955,6 +1071,7 @@ class CompanyImport implements ShouldQueue
|
|||||||
$activity_invitation_key = 'quote_invitations';
|
$activity_invitation_key = 'quote_invitations';
|
||||||
elseif($isset($obj->credit_id))
|
elseif($isset($obj->credit_id))
|
||||||
$activity_invitation_key = 'credit_invitations';
|
$activity_invitation_key = 'credit_invitations';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -964,14 +1081,15 @@ class CompanyImport implements ShouldQueue
|
|||||||
{
|
{
|
||||||
foreach($transform as $key => $value)
|
foreach($transform as $key => $value)
|
||||||
{
|
{
|
||||||
if($class instanceof Activity && $activity_invitation_key)
|
if($class == 'App\Models\Activity' && $activity_invitation_key && $key == 'invitations'){
|
||||||
$key = $activity_invitation_key;
|
$key = $activity_invitation_key;
|
||||||
|
}
|
||||||
|
|
||||||
$obj_array["{$value}"] = $this->transformId($key, $obj->{$value});
|
$obj_array["{$value}"] = $this->transformId($key, $obj->{$value});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($class instanceof CompanyGateway) {
|
if($class == 'App\Models\CompanyGateway') {
|
||||||
$obj_array['config'] = encrypt($obj_array['config']);
|
$obj_array['config'] = encrypt($obj_array['config']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1105,10 +1223,13 @@ class CompanyImport implements ShouldQueue
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (! array_key_exists($resource, $this->ids)) {
|
if (! array_key_exists($resource, $this->ids)) {
|
||||||
|
// nlog($this->ids);
|
||||||
throw new \Exception("Resource {$resource} not available.");
|
throw new \Exception("Resource {$resource} not available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! array_key_exists("{$old}", $this->ids[$resource])) {
|
if (! array_key_exists("{$old}", $this->ids[$resource])) {
|
||||||
|
// nlog($this->ids[$resource]);
|
||||||
|
nlog("searching for {$old} in {$resource}");
|
||||||
throw new \Exception("Missing {$resource} key: {$old}");
|
throw new \Exception("Missing {$resource} key: {$old}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,8 +127,8 @@ class CheckCompanyData implements ShouldQueue
|
|||||||
|
|
||||||
$this->company->clients->where('is_deleted', 0)->each(function ($client) use ($wrong_balances) {
|
$this->company->clients->where('is_deleted', 0)->each(function ($client) use ($wrong_balances) {
|
||||||
$client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($wrong_balances, $client) {
|
$client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($wrong_balances, $client) {
|
||||||
$total_amount = $invoice->payments->whereIn('status_id', [Payment::STATUS_PAID, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.amount');
|
$total_amount = $invoice->payments->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.amount');
|
||||||
$total_refund = $invoice->payments->whereIn('status_id', [Payment::STATUS_PAID, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.refunded');
|
$total_refund = $invoice->payments->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.refunded');
|
||||||
$total_credit = $invoice->credits->sum('amount');
|
$total_credit = $invoice->credits->sum('amount');
|
||||||
|
|
||||||
$total_paid = $total_amount - $total_refund;
|
$total_paid = $total_amount - $total_refund;
|
||||||
|
49
app/Jobs/Util/DiskCleanup.php
Normal file
49
app/Jobs/Util/DiskCleanup.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Jobs\Util;
|
||||||
|
|
||||||
|
use App\Jobs\Util\UnlinkFile;
|
||||||
|
use App\Models\Account;
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class DiskCleanup implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// Get all files in a directory
|
||||||
|
$files = Storage::allFiles(config('filesystems.default'), 'backups/');
|
||||||
|
Storage::delete($files);
|
||||||
|
|
||||||
|
$files = Storage::allFiles('public', 'backups/');
|
||||||
|
Storage::delete($files);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -928,6 +928,10 @@ class Import implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
||||||
|
|
||||||
|
if(array_key_exists('invoice_id', $resource) && $this->tryTransformingId('invoices', $resource['invoice_id']))
|
||||||
|
$modified['invoice_id'] = $this->transformId('invoices', $resource['invoice_id']);
|
||||||
|
|
||||||
$modified['user_id'] = $this->processUserId($resource);
|
$modified['user_id'] = $this->processUserId($resource);
|
||||||
|
|
||||||
$modified['company_id'] = $this->company->id;
|
$modified['company_id'] = $this->company->id;
|
||||||
@ -1566,6 +1570,7 @@ class Import implements ShouldQueue
|
|||||||
*/
|
*/
|
||||||
public function transformId($resource, string $old): int
|
public function transformId($resource, string $old): int
|
||||||
{
|
{
|
||||||
|
|
||||||
if (! array_key_exists($resource, $this->ids)) {
|
if (! array_key_exists($resource, $this->ids)) {
|
||||||
info(print_r($resource, 1));
|
info(print_r($resource, 1));
|
||||||
throw new Exception("Resource {$resource} not available.");
|
throw new Exception("Resource {$resource} not available.");
|
||||||
@ -1650,76 +1655,13 @@ class Import implements ShouldQueue
|
|||||||
return $response->getBody();
|
return $response->getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildNewUserPlan()
|
|
||||||
{
|
|
||||||
$current_db = config('database.default');
|
|
||||||
|
|
||||||
nlog($this->company);
|
|
||||||
|
|
||||||
$local_company = Company::on($current_db)->where('company_key', $this->company->company_key)->first();
|
|
||||||
|
|
||||||
MultiDB::setDb('db-ninja-01');
|
|
||||||
$ninja_company = Company::find(config('ninja.ninja_default_company_id'));
|
|
||||||
|
|
||||||
/* If we already have a record of this user - move along. */
|
|
||||||
if($client_contact = ClientContact::where(['email' => $this->user->email, 'company_id' => $ninja_company->id])->first())
|
|
||||||
return $client_contact->client;
|
|
||||||
|
|
||||||
$ninja_client = ClientFactory::create($ninja_company->id, $ninja_company->owner()->id);
|
|
||||||
$ninja_client->name = $this->user->present()->name();
|
|
||||||
$ninja_client->address1 = $local_company->settings->address1;
|
|
||||||
$ninja_client->address2 = $local_company->settings->address2;
|
|
||||||
$ninja_client->city = $local_company->settings->city;
|
|
||||||
$ninja_client->postal_code = $local_company->settings->postal_code;
|
|
||||||
$ninja_client->state = $local_company->settings->state;
|
|
||||||
$ninja_client->country_id = $local_company->settings->country_id;
|
|
||||||
$ninja_client->custom_value1 = $local_company->company_key;
|
|
||||||
|
|
||||||
$ninja_client->save();
|
|
||||||
|
|
||||||
$ninja_client_contact = ClientContactFactory::create($ninja_company->id, $ninja_company->owner()->id);
|
|
||||||
$ninja_client_contact->first_name = $this->user->first_name;
|
|
||||||
$ninja_client_contact->last_name = $this->user->last_name;
|
|
||||||
$ninja_client_contact->client_id = $ninja_client->id;
|
|
||||||
$ninja_client_contact->email = $this->user->email;
|
|
||||||
$ninja_client_contact->phone = $this->user->phone;
|
|
||||||
$ninja_client_contact->save();
|
|
||||||
|
|
||||||
|
|
||||||
MultiDB::setDb($current_db);
|
|
||||||
|
|
||||||
return $ninja_client;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function processNinjaTokens(array $data)
|
private function processNinjaTokens(array $data)
|
||||||
{
|
{
|
||||||
$current_db = config('database.default');
|
if(Ninja::isHosted())
|
||||||
$local_company = Company::on($current_db)->where('company_key', $this->company->company_key)->first();
|
\Modules\Admin\Jobs\Account\NinjaUser::dispatch($data, $this->company);
|
||||||
|
|
||||||
MultiDB::setDb('db-ninja-01');
|
|
||||||
|
|
||||||
if($existing_client = Client::where('custom_value1', $local_company->company_key)->first())
|
|
||||||
$ninja_client = $existing_client;
|
|
||||||
else
|
|
||||||
$ninja_client = $this->buildNewUserPlan();
|
|
||||||
|
|
||||||
foreach($data as $token)
|
|
||||||
{
|
|
||||||
//get invoiceninja company_id
|
|
||||||
$ninja_company = Company::where('id', config('ninja.ninja_default_company_id'))->first();
|
|
||||||
|
|
||||||
$token['company_id'] = $ninja_company->id;
|
|
||||||
$token['client_id'] = $ninja_client->id;/////
|
|
||||||
$token['user_id'] = $ninja_company->owner()->id;
|
|
||||||
$token['company_gateway_id'] = config('ninja.ninja_default_company_gateway_id');
|
|
||||||
//todo
|
|
||||||
|
|
||||||
ClientGatewayToken::unguard();
|
|
||||||
$cgt = ClientGatewayToken::Create($token);
|
|
||||||
ClientGatewayToken::reguard();
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiDB::setDb($current_db);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,9 +57,9 @@ class UpdateUserLastLogin implements ShouldQueue
|
|||||||
if($user->ip != $ip)
|
if($user->ip != $ip)
|
||||||
{
|
{
|
||||||
$nmo = new NinjaMailerObject;
|
$nmo = new NinjaMailerObject;
|
||||||
$nmo->mailable = new UserLoggedIn($user, $user->account->companies()->first(), $ip);
|
$nmo->mailable = new UserLoggedIn($user, $user->account->companies->first(), $ip);
|
||||||
$nmo->company = $user->account->companies()->first();
|
$nmo->company = $user->account->companies->first();
|
||||||
$nmo->settings = $user->account->companies()->first()->settings;
|
$nmo->settings = $user->account->companies->first()->settings;
|
||||||
$nmo->to_user = $user;
|
$nmo->to_user = $user;
|
||||||
NinjaMailerJob::dispatch($nmo);
|
NinjaMailerJob::dispatch($nmo);
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace App\Mail;
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use App\Models\Company;
|
||||||
use App\Utils\ClientPortal\MagicLink;
|
use App\Utils\ClientPortal\MagicLink;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
@ -20,24 +21,25 @@ use Illuminate\Queue\SerializesModels;
|
|||||||
|
|
||||||
class ContactPasswordlessLogin extends Mailable
|
class ContactPasswordlessLogin extends Mailable
|
||||||
{
|
{
|
||||||
use Queueable, SerializesModels;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $email;
|
public $email;
|
||||||
|
|
||||||
|
public $url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new message instance.
|
* Create a new message instance.
|
||||||
*
|
*
|
||||||
* @param string $email
|
* @param string $email
|
||||||
* @param string $redirect
|
* @param string $redirect
|
||||||
*/
|
*/
|
||||||
public function __construct(string $email, string $redirect = '')
|
public function __construct(string $email, $company_id, string $redirect = '')
|
||||||
{
|
{
|
||||||
$this->email = $email;
|
$this->email = $email;
|
||||||
|
|
||||||
$this->url = MagicLink::create($email, $redirect);
|
$this->url = MagicLink::create($email, $company_id, $redirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
65
app/Mail/Import/CompanyImportFailure.php
Normal file
65
app/Mail/Import/CompanyImportFailure.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Mail\Import;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class CompanyImportFailure extends Mailable
|
||||||
|
{
|
||||||
|
// use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $company;
|
||||||
|
|
||||||
|
public $settings;
|
||||||
|
|
||||||
|
public $logo;
|
||||||
|
|
||||||
|
public $title;
|
||||||
|
|
||||||
|
public $message;
|
||||||
|
|
||||||
|
public $whitelabel;
|
||||||
|
|
||||||
|
public $user_message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($company, $user_message)
|
||||||
|
{
|
||||||
|
$this->company = $company;
|
||||||
|
$this->user_message = $user_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
$this->settings = $this->company->settings;
|
||||||
|
$this->logo = $this->company->present()->logo();
|
||||||
|
$this->title = ctrans('texts.company_import_failure_subject', ['company' => $this->company->present()->name()]);
|
||||||
|
$this->whitelabel = $this->company->account->isPaid();
|
||||||
|
|
||||||
|
nlog($this->user_message);
|
||||||
|
|
||||||
|
return $this->from(config('mail.from.address'), config('mail.from.name'))
|
||||||
|
->subject(ctrans('texts.company_import_failure_subject', ['company' => $this->company->present()->name()]))
|
||||||
|
->view('email.import.import_failure', ['user_message' => $this->user_message, 'title' => $this->title]);
|
||||||
|
}
|
||||||
|
}
|
@ -41,8 +41,8 @@ class MigrationCompleted extends Mailable
|
|||||||
$result = $this->from(config('mail.from.address'), config('mail.from.name'))
|
$result = $this->from(config('mail.from.address'), config('mail.from.name'))
|
||||||
->view('email.import.completed', $data);
|
->view('email.import.completed', $data);
|
||||||
|
|
||||||
if($this->company->invoices->count() >=1)
|
// if($this->company->invoices->count() >=1)
|
||||||
$result->attach($this->company->invoices->first()->pdf_file_path());
|
// $result->attach($this->company->invoices->first()->pdf_file_path());
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ class Account extends BaseModel
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->plan == 'free';
|
return $this->plan == 'free' || is_null($this->plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isEnterpriseClient()
|
public function isEnterpriseClient()
|
||||||
|
@ -133,7 +133,7 @@ class Company extends BaseModel
|
|||||||
|
|
||||||
public function all_documents()
|
public function all_documents()
|
||||||
{
|
{
|
||||||
return $this->HasMany(Document::class);
|
return $this->hasMany(Document::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEntityType()
|
public function getEntityType()
|
||||||
|
@ -81,7 +81,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||||||
'custom_value3',
|
'custom_value3',
|
||||||
'custom_value4',
|
'custom_value4',
|
||||||
'is_deleted',
|
'is_deleted',
|
||||||
'google_2fa_secret',
|
// 'google_2fa_secret',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -244,6 +244,10 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
if (property_exists($this->payment_hash->data, 'billing_context')) {
|
if (property_exists($this->payment_hash->data, 'billing_context')) {
|
||||||
$billing_subscription = \App\Models\Subscription::find($this->payment_hash->data->billing_context->subscription_id);
|
$billing_subscription = \App\Models\Subscription::find($this->payment_hash->data->billing_context->subscription_id);
|
||||||
|
|
||||||
|
// To access campaign hash => $this->payment_hash->data->billing_context->campaign;
|
||||||
|
// To access campaign data => Cache::get(CAMPAIGN_HASH)
|
||||||
|
// To access utm data => session()->get('utm-' . CAMPAIGN_HASH);
|
||||||
|
|
||||||
(new SubscriptionService($billing_subscription))->completePurchase($this->payment_hash);
|
(new SubscriptionService($billing_subscription))->completePurchase($this->payment_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ class CreditCard
|
|||||||
if ($this->checkout->client->currency()->code == 'EUR' || $this->checkout->company_gateway->getConfigField('threeds')) {
|
if ($this->checkout->client->currency()->code == 'EUR' || $this->checkout->company_gateway->getConfigField('threeds')) {
|
||||||
$payment->{'3ds'} = ['enabled' => true];
|
$payment->{'3ds'} = ['enabled' => true];
|
||||||
|
|
||||||
$payment->{'success_url'} = route('payment_webhook', [
|
$payment->{'success_url'} = route('checkout.3ds_redirect', [
|
||||||
'company_key' => $this->checkout->client->company->company_key,
|
'company_key' => $this->checkout->client->company->company_key,
|
||||||
'company_gateway_id' => $this->checkout->company_gateway->hashed_id,
|
'company_gateway_id' => $this->checkout->company_gateway->hashed_id,
|
||||||
'hash' => $this->checkout->payment_hash->hash,
|
'hash' => $this->checkout->payment_hash->hash,
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
namespace App\PaymentDrivers;
|
namespace App\PaymentDrivers;
|
||||||
|
|
||||||
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||||
|
use App\Http\Requests\Gateways\Checkout3ds\Checkout3dsRequest;
|
||||||
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
||||||
use App\Jobs\Mail\PaymentFailureMailer;
|
use App\Jobs\Mail\PaymentFailureMailer;
|
||||||
use App\Jobs\Util\SystemLogger;
|
use App\Jobs\Util\SystemLogger;
|
||||||
@ -287,6 +288,11 @@ class CheckoutComPaymentDriver extends BaseDriver
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null)
|
public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process3dsConfirmation(Checkout3dsRequest $request)
|
||||||
{
|
{
|
||||||
$this->init();
|
$this->init();
|
||||||
$this->setPaymentHash($request->getPaymentHash());
|
$this->setPaymentHash($request->getPaymentHash());
|
||||||
|
@ -187,7 +187,7 @@ class PayPalExpressPaymentDriver extends BaseDriver
|
|||||||
'cancelUrl' => $this->client->company->domain() . '/client/invoices',
|
'cancelUrl' => $this->client->company->domain() . '/client/invoices',
|
||||||
'description' => implode(',', collect($this->payment_hash->data->invoices)
|
'description' => implode(',', collect($this->payment_hash->data->invoices)
|
||||||
->map(function ($invoice) {
|
->map(function ($invoice) {
|
||||||
return sprintf('%s: %s', ctrans('texts.invoice_number'), $invoice->number);
|
return sprintf('%s: %s', ctrans('texts.invoice_number'), $invoice->invoice_number);
|
||||||
})->toArray()),
|
})->toArray()),
|
||||||
'transactionId' => $this->payment_hash->hash . '-' . time(),
|
'transactionId' => $this->payment_hash->hash . '-' . time(),
|
||||||
'ButtonSource' => 'InvoiceNinja_SP',
|
'ButtonSource' => 'InvoiceNinja_SP',
|
||||||
|
@ -11,9 +11,22 @@
|
|||||||
|
|
||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Models\Design;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for DesignRepository .
|
* Class for DesignRepository .
|
||||||
*/
|
*/
|
||||||
class DesignRepository extends BaseRepository
|
class DesignRepository extends BaseRepository
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public function delete($design) :Design
|
||||||
|
{
|
||||||
|
|
||||||
|
$design->name = $design->name . "_deleted_" . Str::random(5);
|
||||||
|
|
||||||
|
parent::delete($design);
|
||||||
|
|
||||||
|
return $design;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,6 +346,8 @@ class Design extends BaseDesign
|
|||||||
|
|
||||||
$items = $this->transformLineItems($this->entity->line_items, $type);
|
$items = $this->transformLineItems($this->entity->line_items, $type);
|
||||||
|
|
||||||
|
// $this->processMarkdownOnLineItems($items);
|
||||||
|
|
||||||
if (count($items) == 0) {
|
if (count($items) == 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -321,10 +321,27 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
public static function parseMarkdownToHtml(string $markdown): ?string
|
public static function parseMarkdownToHtml(string $markdown): ?string
|
||||||
{
|
{
|
||||||
|
// Use setting to determinate if parsing should be done.
|
||||||
|
// 'parse_markdown_on_pdfs'
|
||||||
|
|
||||||
$converter = new CommonMarkConverter([
|
$converter = new CommonMarkConverter([
|
||||||
'allow_unsafe_links' => false,
|
'allow_unsafe_links' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $converter->convertToHtml($markdown);
|
return $converter->convertToHtml($markdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function processMarkdownOnLineItems(array &$items)
|
||||||
|
{
|
||||||
|
// Use setting to determinate if parsing should be done.
|
||||||
|
// 'parse_markdown_on_pdfs'
|
||||||
|
|
||||||
|
foreach ($items as $key => $item) {
|
||||||
|
foreach ($item as $variable => $value) {
|
||||||
|
$item[$variable] = DesignHelpers::parseMarkdownToHtml($value ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
$items[$key] = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,9 @@ trait PdfMakerUtilities
|
|||||||
$contains_html = false;
|
$contains_html = false;
|
||||||
|
|
||||||
if (isset($child['content'])) {
|
if (isset($child['content'])) {
|
||||||
|
// Commented cause it keeps adding <br> at the end, if markdown parsing is turned on.
|
||||||
|
// Should update with 'parse_markdown_on_pdfs' setting.
|
||||||
|
|
||||||
$child['content'] = nl2br($child['content']);
|
$child['content'] = nl2br($child['content']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ class SubscriptionService
|
|||||||
*/
|
*/
|
||||||
private function calculateProRataRefund($invoice) :float
|
private function calculateProRataRefund($invoice) :float
|
||||||
{
|
{
|
||||||
if(!$this->invoice->date)
|
if(!$invoice->date)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
$start_date = Carbon::parse($invoice->date);
|
$start_date = Carbon::parse($invoice->date);
|
||||||
@ -317,7 +317,7 @@ class SubscriptionService
|
|||||||
|
|
||||||
$days_in_frequency = $this->getDaysInFrequency();
|
$days_in_frequency = $this->getDaysInFrequency();
|
||||||
|
|
||||||
nlog("days to charge = {$days_to_charge} fays in frequency = {$days_in_frequency}");
|
nlog("days to charge = {$days_to_charge} days in frequency = {$days_in_frequency}");
|
||||||
|
|
||||||
$pro_rata_charge = round(($days_to_charge/$days_in_frequency) * $invoice->amount ,2);
|
$pro_rata_charge = round(($days_to_charge/$days_in_frequency) * $invoice->amount ,2);
|
||||||
|
|
||||||
@ -630,9 +630,8 @@ class SubscriptionService
|
|||||||
*/
|
*/
|
||||||
public function triggerWebhook($context)
|
public function triggerWebhook($context)
|
||||||
{
|
{
|
||||||
/* If no webhooks have been set, then just return gracefully */
|
if (empty($this->subscription->webhook_configuration['post_purchase_url']) || empty($this->subscription->webhook_configuration['post_purchase_rest_method'])) {
|
||||||
if(!array_key_exists('post_purchase_url', $this->subscription->webhook_configuration) || !array_key_exists('post_purchase_rest_method', $this->subscription->webhook_configuration)) {
|
return ["message" => "Success", "status_code" => 200];
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = false;
|
$response = false;
|
||||||
@ -653,10 +652,7 @@ class SubscriptionService
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
$status = $response->getStatusCode();
|
$body = $response->getStatusCode();
|
||||||
|
|
||||||
//$response_body = $response->getReasonPhrase();
|
|
||||||
//$body = array_merge($body, ['status' => $status, 'response_body' => $response_body]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,7 +667,10 @@ class SubscriptionService
|
|||||||
$client->company,
|
$client->company,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if(is_array($body))
|
||||||
return $response;
|
return $response;
|
||||||
|
else
|
||||||
|
return ['message' => 'There was a problem encountered with the webhook', 'status_code' => 500];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ use App\Models\Account;
|
|||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\CompanyUser;
|
use App\Models\CompanyUser;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Utils\Ninja;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,12 +18,17 @@ class MagicLink
|
|||||||
{
|
{
|
||||||
|
|
||||||
//return a magic login link URL
|
//return a magic login link URL
|
||||||
public static function create($email, $url = null) :string
|
public static function create($email, $company_id, $url = null) :string
|
||||||
{
|
{
|
||||||
$magic_key = Str::random(64);
|
$magic_key = Str::random(64);
|
||||||
$timeout = 600; //seconds
|
$timeout = 600; //seconds
|
||||||
|
|
||||||
Cache::add($magic_key, $email, $timeout);
|
$payload = [
|
||||||
|
'email' => $email,
|
||||||
|
'company_id' => $company_id,
|
||||||
|
];
|
||||||
|
|
||||||
|
Cache::add($magic_key, $payload, $timeout);
|
||||||
|
|
||||||
return route('client.contact_magic_link', ['magic_link' => $magic_key, 'redirect' => $url]);
|
return route('client.contact_magic_link', ['magic_link' => $magic_key, 'redirect' => $url]);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ use App\Models\CreditInvitation;
|
|||||||
use App\Models\InvoiceInvitation;
|
use App\Models\InvoiceInvitation;
|
||||||
use App\Models\QuoteInvitation;
|
use App\Models\QuoteInvitation;
|
||||||
use App\Models\RecurringInvoiceInvitation;
|
use App\Models\RecurringInvoiceInvitation;
|
||||||
|
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
|
||||||
use App\Utils\Traits\MakesDates;
|
use App\Utils\Traits\MakesDates;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
@ -214,6 +215,7 @@ class HtmlEngine
|
|||||||
$data['$quote_no'] = &$data['$quote.number'];
|
$data['$quote_no'] = &$data['$quote.number'];
|
||||||
$data['$quote.quote_no'] = &$data['$quote.number'];
|
$data['$quote.quote_no'] = &$data['$quote.number'];
|
||||||
$data['$quote.valid_until'] = ['value' => $this->translateDate($this->entity->due_date, $this->client->date_format(), $this->entity->client->locale()), 'label' => ctrans('texts.valid_until')];
|
$data['$quote.valid_until'] = ['value' => $this->translateDate($this->entity->due_date, $this->client->date_format(), $this->entity->client->locale()), 'label' => ctrans('texts.valid_until')];
|
||||||
|
$data['$valid_until'] = &$data['$quote.valid_until'];
|
||||||
$data['$credit_amount'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.credit_amount')];
|
$data['$credit_amount'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.credit_amount')];
|
||||||
$data['$credit_balance'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: ' ', 'label' => ctrans('texts.credit_balance')];
|
$data['$credit_balance'] = ['value' => Number::formatMoney($this->entity->balance, $this->client) ?: ' ', 'label' => ctrans('texts.credit_balance')];
|
||||||
$data['$quote.custom1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice1', $this->entity->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice1')];
|
$data['$quote.custom1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice1', $this->entity->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice1')];
|
||||||
@ -231,6 +233,10 @@ class HtmlEngine
|
|||||||
$data['$client2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client2', $this->client->custom_value2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client2')];
|
$data['$client2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client2', $this->client->custom_value2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client2')];
|
||||||
$data['$client3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client3', $this->client->custom_value3, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client3')];
|
$data['$client3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client3', $this->client->custom_value3, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client3')];
|
||||||
$data['$client4'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client4', $this->client->custom_value4, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client4')];
|
$data['$client4'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client4', $this->client->custom_value4, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client4')];
|
||||||
|
$data['$client.custom1'] = &$data['$client1'];
|
||||||
|
$data['$client.custom2'] = &$data['$client2'];
|
||||||
|
$data['$client.custom3'] = &$data['$client3'];
|
||||||
|
$data['$client.custom4'] = &$data['$client4'];
|
||||||
$data['$address1'] = ['value' => $this->client->address1 ?: ' ', 'label' => ctrans('texts.address1')];
|
$data['$address1'] = ['value' => $this->client->address1 ?: ' ', 'label' => ctrans('texts.address1')];
|
||||||
$data['$address2'] = ['value' => $this->client->address2 ?: ' ', 'label' => ctrans('texts.address2')];
|
$data['$address2'] = ['value' => $this->client->address2 ?: ' ', 'label' => ctrans('texts.address2')];
|
||||||
$data['$id_number'] = ['value' => $this->client->id_number ?: ' ', 'label' => ctrans('texts.id_number')];
|
$data['$id_number'] = ['value' => $this->client->id_number ?: ' ', 'label' => ctrans('texts.id_number')];
|
||||||
@ -246,6 +252,7 @@ class HtmlEngine
|
|||||||
$data['$client.address2'] = &$data['$address2'];
|
$data['$client.address2'] = &$data['$address2'];
|
||||||
$data['$client_address'] = ['value' => $this->client->present()->address() ?: ' ', 'label' => ctrans('texts.address')];
|
$data['$client_address'] = ['value' => $this->client->present()->address() ?: ' ', 'label' => ctrans('texts.address')];
|
||||||
$data['$client.address'] = &$data['$client_address'];
|
$data['$client.address'] = &$data['$client_address'];
|
||||||
|
$data['$client.postal_code'] = ['value' => $this->client->postal_code ?: ' ', 'label' => ctrans('texts.postal_code')];
|
||||||
$data['$client.id_number'] = &$data['$id_number'];
|
$data['$client.id_number'] = &$data['$id_number'];
|
||||||
$data['$client.vat_number'] = &$data['$vat_number'];
|
$data['$client.vat_number'] = &$data['$vat_number'];
|
||||||
$data['$client.website'] = &$data['$website'];
|
$data['$client.website'] = &$data['$website'];
|
||||||
@ -306,6 +313,11 @@ class HtmlEngine
|
|||||||
$data['$company3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company3', $this->settings->custom_value3, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company3')];
|
$data['$company3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company3', $this->settings->custom_value3, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company3')];
|
||||||
$data['$company4'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company4', $this->settings->custom_value4, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company4')];
|
$data['$company4'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company4', $this->settings->custom_value4, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company4')];
|
||||||
|
|
||||||
|
$data['$company.custom1'] = &$data['$company1'];
|
||||||
|
$data['$company.custom2'] = &$data['$company2'];
|
||||||
|
$data['$company.custom3'] = &$data['$company3'];
|
||||||
|
$data['$company.custom4'] = &$data['$company4'];
|
||||||
|
|
||||||
$data['$custom_surcharge1'] = ['value' => Number::formatMoney($this->entity->custom_surcharge1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge1')];
|
$data['$custom_surcharge1'] = ['value' => Number::formatMoney($this->entity->custom_surcharge1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge1')];
|
||||||
$data['$custom_surcharge2'] = ['value' => Number::formatMoney($this->entity->custom_surcharge2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge2')];
|
$data['$custom_surcharge2'] = ['value' => Number::formatMoney($this->entity->custom_surcharge2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge2')];
|
||||||
$data['$custom_surcharge3'] = ['value' => Number::formatMoney($this->entity->custom_surcharge3, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge3')];
|
$data['$custom_surcharge3'] = ['value' => Number::formatMoney($this->entity->custom_surcharge3, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge3')];
|
||||||
@ -379,6 +391,8 @@ class HtmlEngine
|
|||||||
$data['$page_size'] = ['value' => $this->settings->page_size, 'label' => ''];
|
$data['$page_size'] = ['value' => $this->settings->page_size, 'label' => ''];
|
||||||
$data['$page_layout'] = ['value' => property_exists($this->settings, 'page_layout') ? $this->settings->page_layout : 'Portrait', 'label' => ''];
|
$data['$page_layout'] = ['value' => property_exists($this->settings, 'page_layout') ? $this->settings->page_layout : 'Portrait', 'label' => ''];
|
||||||
|
|
||||||
|
$data['$tech_hero_image'] = ['value' => asset('images/pdf-designs/tech-hero-image.jpg'), 'label' => ''];
|
||||||
|
|
||||||
$arrKeysLength = array_map('strlen', array_keys($data));
|
$arrKeysLength = array_map('strlen', array_keys($data));
|
||||||
array_multisort($arrKeysLength, SORT_DESC, $data);
|
array_multisort($arrKeysLength, SORT_DESC, $data);
|
||||||
|
|
||||||
|
@ -40,14 +40,13 @@ trait SubscriptionHooker
|
|||||||
RequestOptions::JSON => ['body' => $body], RequestOptions::ALLOW_REDIRECTS => false
|
RequestOptions::JSON => ['body' => $body], RequestOptions::ALLOW_REDIRECTS => false
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return array_merge($body, ['exception' => json_decode($response->getBody(),true), 'status_code' => $response->getStatusCode()]);
|
return array_merge($body, json_decode($response->getBody(),true));
|
||||||
}
|
}
|
||||||
catch(\Exception $e)
|
catch(\Exception $e)
|
||||||
{
|
{
|
||||||
//;
|
|
||||||
// dd($e);
|
return array_merge($body, ['message' => $e->getMessage(), 'status_code' => 500]);
|
||||||
$body = array_merge($body, ['exception' => ['message' => $e->getMessage(), 'status_code' => 500]]);
|
|
||||||
return $body;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
"ext-dom": "*",
|
"ext-dom": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-libxml": "*",
|
"ext-libxml": "*",
|
||||||
"asm/php-ansible": "dev-master",
|
"asm/php-ansible": "dev-main",
|
||||||
"authorizenet/authorizenet": "^2.0",
|
"authorizenet/authorizenet": "^2.0",
|
||||||
"bacon/bacon-qr-code": "^2.0",
|
"bacon/bacon-qr-code": "^2.0",
|
||||||
"beganovich/snappdf": "^1.0",
|
"beganovich/snappdf": "^1.0",
|
||||||
@ -43,6 +43,7 @@
|
|||||||
"doctrine/dbal": "^2.10",
|
"doctrine/dbal": "^2.10",
|
||||||
"fakerphp/faker": "^1.14",
|
"fakerphp/faker": "^1.14",
|
||||||
"fideloper/proxy": "^4.2",
|
"fideloper/proxy": "^4.2",
|
||||||
|
"fruitcake/laravel-cors": "^2.0",
|
||||||
"google/apiclient": "^2.7",
|
"google/apiclient": "^2.7",
|
||||||
"guzzlehttp/guzzle": "^7.0.1",
|
"guzzlehttp/guzzle": "^7.0.1",
|
||||||
"hashids/hashids": "^4.0",
|
"hashids/hashids": "^4.0",
|
||||||
@ -58,7 +59,7 @@
|
|||||||
"league/flysystem-cached-adapter": "^1.1",
|
"league/flysystem-cached-adapter": "^1.1",
|
||||||
"league/fractal": "^0.17.0",
|
"league/fractal": "^0.17.0",
|
||||||
"league/omnipay": "^3.1",
|
"league/omnipay": "^3.1",
|
||||||
"livewire/livewire": "^2.0",
|
"livewire/livewire": "^2.4",
|
||||||
"maennchen/zipstream-php": "^1.2",
|
"maennchen/zipstream-php": "^1.2",
|
||||||
"nwidart/laravel-modules": "^8.0",
|
"nwidart/laravel-modules": "^8.0",
|
||||||
"omnipay/paypal": "^3.0",
|
"omnipay/paypal": "^3.0",
|
||||||
|
948
composer.lock
generated
948
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -15,7 +15,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'paths' => ['api/*'],
|
'paths' => ['*'],
|
||||||
|
|
||||||
'allowed_methods' => ['*'],
|
'allowed_methods' => ['*'],
|
||||||
|
|
||||||
@ -23,9 +23,9 @@ return [
|
|||||||
|
|
||||||
'allowed_origins_patterns' => [],
|
'allowed_origins_patterns' => [],
|
||||||
|
|
||||||
'allowed_headers' => ['*'],
|
'allowed_headers' => ['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,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE'],
|
||||||
|
|
||||||
'exposed_headers' => [],
|
'exposed_headers' => ['X-APP-VERSION,X-MINIMUM-CLIENT-VERSION,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE'],
|
||||||
|
|
||||||
'max_age' => 0,
|
'max_age' => 0,
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ return [
|
|||||||
'require_https' => env('REQUIRE_HTTPS', true),
|
'require_https' => env('REQUIRE_HTTPS', true),
|
||||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||||
'app_version' => '5.1.70',
|
'app_version' => '5.1.72',
|
||||||
'app_tag' => '5.1.70-release',
|
'app_tag' => '5.1.72-release',
|
||||||
'minimum_client_version' => '5.0.16',
|
'minimum_client_version' => '5.0.16',
|
||||||
'terms_version' => '1.0.1',
|
'terms_version' => '1.0.1',
|
||||||
'api_secret' => env('API_SECRET', ''),
|
'api_secret' => env('API_SECRET', ''),
|
||||||
@ -152,6 +152,7 @@ return [
|
|||||||
'ninja_stripe_client_id' => env('NINJA_STRIPE_CLIENT_ID', null),
|
'ninja_stripe_client_id' => env('NINJA_STRIPE_CLIENT_ID', null),
|
||||||
'ninja_default_company_id' => env('NINJA_COMPANY_ID', null),
|
'ninja_default_company_id' => env('NINJA_COMPANY_ID', null),
|
||||||
'ninja_default_company_gateway_id' => env('NINJA_COMPANY_GATEWAY_ID', null),
|
'ninja_default_company_gateway_id' => env('NINJA_COMPANY_GATEWAY_ID', null),
|
||||||
|
'ninja_hosted_secret' => env('NINJA_HOSTED_SECRET', null),
|
||||||
'pdf_generator' => env('PDF_GENERATOR', false),
|
'pdf_generator' => env('PDF_GENERATOR', false),
|
||||||
'internal_queue_enabled' => env('INTERNAL_QUEUE_ENABLED', true),
|
'internal_queue_enabled' => env('INTERNAL_QUEUE_ENABLED', true),
|
||||||
];
|
];
|
||||||
|
49
database/migrations/2021_05_27_105157_add_tech_design.php
Normal file
49
database/migrations/2021_05_27_105157_add_tech_design.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Design;
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AddTechDesign extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if (Ninja::isHosted()) {
|
||||||
|
$design = new Design();
|
||||||
|
|
||||||
|
$design->id = 10;
|
||||||
|
$design->name = 'Tech';
|
||||||
|
$design->is_custom = false;
|
||||||
|
$design->design = '';
|
||||||
|
$design->is_active = true;
|
||||||
|
|
||||||
|
$design->save();
|
||||||
|
} elseif (Design::count() !== 0) {
|
||||||
|
$design = new Design();
|
||||||
|
|
||||||
|
$design->name = 'Tech';
|
||||||
|
$design->is_custom = false;
|
||||||
|
$design->design = '';
|
||||||
|
$design->is_active = true;
|
||||||
|
|
||||||
|
$design->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
\Illuminate\Support\Facades\Artisan::call('ninja:design-update');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
@ -36,6 +36,7 @@ class DesignSeeder extends Seeder
|
|||||||
['id' => 7, 'name' => 'Elegant', 'user_id' => null, 'company_id' => null, 'is_custom' => false, 'design' => '', 'is_active' => true],
|
['id' => 7, 'name' => 'Elegant', 'user_id' => null, 'company_id' => null, 'is_custom' => false, 'design' => '', 'is_active' => true],
|
||||||
['id' => 8, 'name' => 'Hipster', 'user_id' => null, 'company_id' => null, 'is_custom' => false, 'design' => '', 'is_active' => true],
|
['id' => 8, 'name' => 'Hipster', 'user_id' => null, 'company_id' => null, 'is_custom' => false, 'design' => '', 'is_active' => true],
|
||||||
['id' => 9, 'name' => 'Playful', 'user_id' => null, 'company_id' => null, 'is_custom' => false, 'design' => '', 'is_active' => true],
|
['id' => 9, 'name' => 'Playful', 'user_id' => null, 'company_id' => null, 'is_custom' => false, 'design' => '', 'is_active' => true],
|
||||||
|
['id' => 10, 'name' => 'Tech', 'user_id' => null, 'company_id' => null, 'is_custom' => false, 'design' => '', 'is_active' => true],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($designs as $design) {
|
foreach ($designs as $design) {
|
||||||
|
2
public/flutter_service_worker.js
vendored
2
public/flutter_service_worker.js
vendored
@ -5,7 +5,7 @@ const CACHE_NAME = 'flutter-app-cache';
|
|||||||
const RESOURCES = {
|
const RESOURCES = {
|
||||||
"version.json": "9fe5b22a16f39b766c8fdc35a24b3efa",
|
"version.json": "9fe5b22a16f39b766c8fdc35a24b3efa",
|
||||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||||
"main.dart.js": "4ed39edfd85c4ac1e202b7c83715f20d",
|
"main.dart.js": "9f05b24849e19debf0c8286556e368e6",
|
||||||
"/": "23224b5e03519aaa87594403d54412cf",
|
"/": "23224b5e03519aaa87594403d54412cf",
|
||||||
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
|
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
|
||||||
"assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f",
|
"assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f",
|
||||||
|
BIN
public/images/pdf-designs/tech-hero-image.jpg
Normal file
BIN
public/images/pdf-designs/tech-hero-image.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 594 KiB |
152488
public/main.dart.js
vendored
152488
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
151170
public/main.foss.dart.js
vendored
151170
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
@ -4254,6 +4254,8 @@ $LANG = array(
|
|||||||
'account_passwordless_login' => 'Account passwordless login',
|
'account_passwordless_login' => 'Account passwordless login',
|
||||||
'user_duplicate_error' => 'Cannot add the same user to the same company',
|
'user_duplicate_error' => 'Cannot add the same user to the same company',
|
||||||
'user_cross_linked_error' => 'User exists but cannot be crossed linked to multiple accounts',
|
'user_cross_linked_error' => 'User exists but cannot be crossed linked to multiple accounts',
|
||||||
|
'company_import_failure_subject' => 'Error importing :company',
|
||||||
|
'company_import_failure_body' => 'There was an error importing the company data, the error message was:',
|
||||||
);
|
);
|
||||||
|
|
||||||
return $LANG;
|
return $LANG;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
@section('meta_title', ctrans('texts.purchase'))
|
@section('meta_title', ctrans('texts.purchase'))
|
||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
@livewire('billing-portal-purchase', ['subscription' => $subscription, 'contact' => auth('contact')->user(), 'hash' => $hash, 'request_data' => $request_data])
|
@livewire('billing-portal-purchase', ['subscription' => $subscription, 'company' => $subscription->company, 'contact' => auth('contact')->user(), 'hash' => $hash, 'request_data' => $request_data, 'campaign' => request()->query('campaign') ?? null])
|
||||||
@stop
|
@stop
|
||||||
|
|
||||||
@push('footer')
|
@push('footer')
|
||||||
|
@ -70,8 +70,10 @@
|
|||||||
<p><b>{{ ctrans('texts.documents') }}:</b> {{ count($company->documents) }} </p>
|
<p><b>{{ ctrans('texts.documents') }}:</b> {{ count($company->documents) }} </p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if($check_data)
|
||||||
<p><b>Data Quality:</b></p>
|
<p><b>Data Quality:</b></p>
|
||||||
<p> {!! $check_data !!} </p>
|
<p> {!! $check_data !!} </p>
|
||||||
|
@endif
|
||||||
|
|
||||||
@if(!empty($errors) )
|
@if(!empty($errors) )
|
||||||
<p>{{ ctrans('texts.errors') }}:</p>
|
<p>{{ ctrans('texts.errors') }}:</p>
|
||||||
|
22
resources/views/email/import/import_failure.blade.php
Normal file
22
resources/views/email/import/import_failure.blade.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@component('email.template.master', ['design' => 'light', 'settings' => $settings])
|
||||||
|
|
||||||
|
@slot('header')
|
||||||
|
@include('email.components.header', ['logo' => $logo])
|
||||||
|
@endslot
|
||||||
|
|
||||||
|
<h2>{{ $title }}</h2>
|
||||||
|
|
||||||
|
<p>{{ctrans('texts.company_import_failure_body')}}</p>
|
||||||
|
|
||||||
|
@if($user_message)
|
||||||
|
<p>{{ $user_message }}</p>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if(isset($whitelabel) && !$whitelabel)
|
||||||
|
@slot('footer')
|
||||||
|
@component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja'])
|
||||||
|
For any info, please visit InvoiceNinja.
|
||||||
|
@endcomponent
|
||||||
|
@endslot
|
||||||
|
@endif
|
||||||
|
@endcomponent
|
296
resources/views/pdf-designs/tech.html
Normal file
296
resources/views/pdf-designs/tech.html
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
<style id="style">
|
||||||
|
:root {
|
||||||
|
--primary-color: $primary_color;
|
||||||
|
--secondary-color: $secondary_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
font-size: "$font_size";
|
||||||
|
zoom: 80%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@page {
|
||||||
|
margin: 0;
|
||||||
|
size: $page_size $page_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.header-wrapper,
|
||||||
|
.body-wrapper {
|
||||||
|
margin: $global_margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** End of global, standard CSS */
|
||||||
|
.header-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-right-side-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-right-side-section > * {
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-and-partial-entity-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company-logo {
|
||||||
|
zoom: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-invoice-number {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-payment-due-label,
|
||||||
|
.header-amount-due-label {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-amount-due-value {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-section {
|
||||||
|
margin-top: 50px;
|
||||||
|
min-width: 100% !important;
|
||||||
|
background: url('$tech_hero_image'); /** If you want to replace the image, this is the place to do it. */
|
||||||
|
-webkit-background-size: cover;
|
||||||
|
-moz-background-size: cover;
|
||||||
|
-o-background-size: cover;
|
||||||
|
background-size: cover;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1.5fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-contact-section {
|
||||||
|
background-color: rgba(255, 255, 255, 0.98);
|
||||||
|
margin: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client-details,
|
||||||
|
.company-details {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client-details-to-label {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--primary-color);
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#client-details,
|
||||||
|
#company-details,
|
||||||
|
#company-address {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company-details-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company-details {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-wrapper {}
|
||||||
|
|
||||||
|
#product-table,
|
||||||
|
#delivery-note-table,
|
||||||
|
#task-table {
|
||||||
|
min-width: 100%;
|
||||||
|
table-layout: fixed;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#product-table > thead > tr > th,
|
||||||
|
#delivery-note-table > thead > tr > th,
|
||||||
|
#task-table > thead > tr > th {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 1rem;
|
||||||
|
border-bottom: 5px solid black;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#product-table > thead > tr > th:last-child,
|
||||||
|
#delivery-note-table > thead > tr > th:last-child,
|
||||||
|
#task-table > thead > tr > th:last-child {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#product-table > tbody > tr > td,
|
||||||
|
#delivery-note-table > tbody > tr > td,
|
||||||
|
#task-table > tbody > tr > td {
|
||||||
|
border-bottom: 1px solid #e6e6e6;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#product-table > tbody > tr > td:first-child,
|
||||||
|
#delivery-note-table > tbody > tr > td:first-child,
|
||||||
|
#task-table > tbody > tr > td:first-child {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#product-table > tbody > tr > td:last-child,
|
||||||
|
#delivery-note-table > tbody > tr > td:last-child,
|
||||||
|
#task-table > tbody > tr > td:last-child {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-time-details {
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-totals {
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-totals {
|
||||||
|
margin-top: 2rem;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 2fr 1fr;
|
||||||
|
gap: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-totals .totals-table-right-side > * {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-totals > .totals-table-right-side > * > :nth-child(1) {
|
||||||
|
text-align: left;
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-totals > .totals-table-right-side > * > :nth-child(2) {
|
||||||
|
text-align: right;
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-totals
|
||||||
|
> *
|
||||||
|
[data-element='total-table-balance-due-label'],
|
||||||
|
#table-totals
|
||||||
|
> *
|
||||||
|
[data-element='total-table-balance-due'] {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-totals > * > :last-child {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-ref="total_table-footer"] {
|
||||||
|
padding-left: 1rem
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-ref="totals_table-outstanding-label"],
|
||||||
|
[data-ref="totals_table-outstanding"] {
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="header"></div>
|
||||||
|
|
||||||
|
<div id="body">
|
||||||
|
<div class="header-wrapper">
|
||||||
|
<div class="top-right-side-section">
|
||||||
|
<span class="header-invoice-number">$entity_number_label: $entity_number</span>
|
||||||
|
<span>$date_label: $date</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="logo-and-partial-entity-info">
|
||||||
|
<img class="company-logo" src="$company.logo"
|
||||||
|
alt="$company.name logo">
|
||||||
|
<div class="top-right-side-section">
|
||||||
|
<section>
|
||||||
|
<span class="header-payment-due-label">$payment_due_label:</span>
|
||||||
|
<span>$payment_due</span>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<span class="header-amount-due-label">$amount_due_label:</span>
|
||||||
|
<span class="header-amount-due-value">$amount_due</span>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hero-section">
|
||||||
|
<div class="hero-contact-section">
|
||||||
|
<div class="client-details">
|
||||||
|
<span class="client-details-to-label">$from_label:</span>
|
||||||
|
<div id="client-details"></div>
|
||||||
|
</div>
|
||||||
|
<div class="company-details">
|
||||||
|
<span class="client-details-to-label">$to_label:</span>
|
||||||
|
<div class="company-details-wrapper">
|
||||||
|
<div id="company-details"></div>
|
||||||
|
<div id="company-address"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="body-wrapper">
|
||||||
|
<table id="product-table" cellspacing="0"></table>
|
||||||
|
|
||||||
|
<table id="task-table" cellspacing="0"></table>
|
||||||
|
|
||||||
|
<table id="delivery-note-table" cellspacing="0"></table>
|
||||||
|
|
||||||
|
<div id="table-totals" cellspacing="0"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
['product-table', 'task-table', 'delivery-note-table'].forEach((tableIdentifier) => {
|
||||||
|
document.getElementById(tableIdentifier).childElementCount === 0
|
||||||
|
? document.getElementById(tableIdentifier).style.display = 'none'
|
||||||
|
: '';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
@ -20,7 +20,8 @@
|
|||||||
|
|
||||||
@if($account && !$account->isPaid())
|
@if($account && !$account->isPaid())
|
||||||
<div>
|
<div>
|
||||||
<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">
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@ -61,7 +62,12 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
@if(!is_null($company) && $company->client_can_register)
|
||||||
|
<div class="mt-5 text-center">
|
||||||
|
<a class="button-link text-sm" href="{{ route('client.register') }}">{{ ctrans('texts.register_label') }}</a>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="grid lg:grid-cols-3">
|
<div class="grid lg:grid-cols-3">
|
||||||
@if($account && !$account->isPaid())
|
@if($account && !$account->isPaid())
|
||||||
<div class="hidden lg:block col-span-1 bg-red-100 h-screen">
|
<div class="hidden lg:block col-span-1 bg-red-100 h-screen">
|
||||||
<img src="https://www.invoiceninja.com/wp-content/uploads/2018/04/bg-home2018b.jpg"
|
<img src="{{ asset('images/client-portal-new-image.jpg') }}"
|
||||||
class="w-full h-screen object-cover"
|
class="w-full h-screen object-cover"
|
||||||
alt="Background image">
|
alt="Background image">
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="grid lg:grid-cols-3">
|
<div class="grid lg:grid-cols-3">
|
||||||
@if($account && !$account->isPaid())
|
@if($account && !$account->isPaid())
|
||||||
<div class="hidden lg:block col-span-1 bg-red-100 h-screen">
|
<div class="hidden lg:block col-span-1 bg-red-100 h-screen">
|
||||||
<img src="https://www.invoiceninja.com/wp-content/uploads/2018/04/bg-home2018b.jpg"
|
<img src="{{ asset('images/client-portal-new-image.jpg') }}"
|
||||||
class="w-full h-screen object-cover"
|
class="w-full h-screen object-cover"
|
||||||
alt="Background image">
|
alt="Background image">
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,6 +13,6 @@
|
|||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
@livewire('credits-table')
|
@livewire('credits-table', ['company' => $company])
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
@ -14,5 +14,5 @@
|
|||||||
@csrf
|
@csrf
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@livewire('documents-table', ['client' => $client])
|
@livewire('documents-table', ['client' => $client, 'company' => $company])
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -20,6 +20,6 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col mt-4">
|
<div class="flex flex-col mt-4">
|
||||||
@livewire('invoices-table')
|
@livewire('invoices-table', ['company' => $company])
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<div class="col-span-6 md:col-start-2 md:col-span-4">
|
<div class="col-span-6 md:col-start-2 md:col-span-4">
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
<div class="flex justify-end mb-2">
|
<div class="flex justify-end mb-2">
|
||||||
@livewire('pay-now-dropdown', ['total' => $total])
|
@livewire('pay-now-dropdown', ['total' => $total, 'company' => $company])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
@if($settings->client_portal_allow_under_payment || $settings->client_portal_allow_over_payment)
|
@if($settings->client_portal_allow_under_payment || $settings->client_portal_allow_over_payment)
|
||||||
<button class="button button-primary bg-primary">{{ ctrans('texts.pay_now') }}</button>
|
<button class="button button-primary bg-primary">{{ ctrans('texts.pay_now') }}</button>
|
||||||
@else
|
@else
|
||||||
@livewire('pay-now-dropdown', ['total' => $invoice->partial > 0 ? $invoice->partial : $invoice->balance])
|
@livewire('pay-now-dropdown', ['total' => $invoice->partial > 0 ? $invoice->partial : $invoice->balance, 'company' => $company])
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
@endpush
|
@endpush
|
||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
@livewire('required-client-info', ['fields' => method_exists($gateway, 'getClientRequiredFields') ? $gateway->getClientRequiredFields() : [], 'contact' => auth('contact')->user(), 'countries' => $countries])
|
@livewire('required-client-info', ['fields' => method_exists($gateway, 'getClientRequiredFields') ? $gateway->getClientRequiredFields() : [], 'contact' => auth('contact')->user(), 'countries' => $countries, 'company' => $company])
|
||||||
|
|
||||||
<div class="container mx-auto grid grid-cols-12 opacity-25 pointer-events-none" data-ref="gateway-container">
|
<div class="container mx-auto grid grid-cols-12 opacity-25 pointer-events-none" data-ref="gateway-container">
|
||||||
<div class="col-span-12 lg:col-span-6 lg:col-start-4 overflow-hidden bg-white shadow rounded-lg">
|
<div class="col-span-12 lg:col-span-6 lg:col-start-4 overflow-hidden bg-white shadow rounded-lg">
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
@livewire('payment-methods-table', ['client' => $client])
|
@livewire('payment-methods-table', ['client' => $client, 'company' => $company])
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
@livewire('payments-table')
|
@livewire('payments-table', ['company' => $company])
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
@ -22,6 +22,6 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col mt-4">
|
<div class="flex flex-col mt-4">
|
||||||
@livewire('quotes-table')
|
@livewire('quotes-table', ['company' => $company])
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
@ -34,7 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
|
<div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
|
||||||
<div class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
|
<div class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
|
||||||
@livewire('recurring-invoice-cancellation', ['invoice' => $invoice])
|
@livewire('recurring-invoice-cancellation', ['invoice' => $invoice, 'company' => $company])
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto">
|
<div class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto">
|
||||||
<button @click="open = false" type="button" class="button button-secondary button-block">
|
<button @click="open = false" type="button" class="button button-secondary button-block">
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
@livewire('recurring-invoices-table')
|
@livewire('recurring-invoices-table', ['company' => $company])
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
@livewire('subscription-recurring-invoices-table')
|
@livewire('subscription-recurring-invoices-table', ['company' => $company])
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Payment box -->
|
<!-- Payment box -->
|
||||||
@livewire('subscription-plan-switch', compact('recurring_invoice', 'subscription', 'target', 'contact', 'amount'))
|
@livewire('subscription-plan-switch', compact('recurring_invoice', 'subscription', 'target', 'contact', 'amount', 'company'))
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
@livewire('tasks-table')
|
@livewire('tasks-table', ['company' => $company])
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -163,6 +163,7 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a
|
|||||||
|
|
||||||
Route::get('settings/enable_two_factor', 'TwoFactorController@setupTwoFactor');
|
Route::get('settings/enable_two_factor', 'TwoFactorController@setupTwoFactor');
|
||||||
Route::post('settings/enable_two_factor', 'TwoFactorController@enableTwoFactor');
|
Route::post('settings/enable_two_factor', 'TwoFactorController@enableTwoFactor');
|
||||||
|
Route::post('settings/disable_two_factor', 'TwoFactorController@disableTwoFactor');
|
||||||
|
|
||||||
Route::resource('vendors', 'VendorController'); // name = (vendors. index / create / show / update / destroy / edit
|
Route::resource('vendors', 'VendorController'); // name = (vendors. index / create / show / update / destroy / edit
|
||||||
Route::post('vendors/bulk', 'VendorController@bulk')->name('vendors.bulk');
|
Route::post('vendors/bulk', 'VendorController@bulk')->name('vendors.bulk');
|
||||||
|
@ -7,13 +7,13 @@ Route::get('client', 'Auth\ContactLoginController@showLoginForm')->name('client.
|
|||||||
Route::get('client/login', 'Auth\ContactLoginController@showLoginForm')->name('client.login')->middleware(['domain_db', 'contact_account','locale']);
|
Route::get('client/login', 'Auth\ContactLoginController@showLoginForm')->name('client.login')->middleware(['domain_db', 'contact_account','locale']);
|
||||||
Route::post('client/login', 'Auth\ContactLoginController@login')->name('client.login.submit');
|
Route::post('client/login', 'Auth\ContactLoginController@login')->name('client.login.submit');
|
||||||
|
|
||||||
Route::get('client/register/{company_key?}', 'Auth\ContactRegisterController@showRegisterForm')->name('client.register')->middleware(['domain_db', 'contact_account','locale']);
|
Route::get('client/register/{company_key?}', 'Auth\ContactRegisterController@showRegisterForm')->name('client.register')->middleware(['domain_db', 'contact_account', 'contact_register','locale']);
|
||||||
Route::post('client/register/{company_key?}', 'Auth\ContactRegisterController@register');
|
Route::post('client/register/{company_key?}', 'Auth\ContactRegisterController@register')->middleware(['domain_db', 'contact_account', 'contact_register', 'locale']);
|
||||||
|
|
||||||
Route::get('client/password/reset', 'Auth\ContactForgotPasswordController@showLinkRequestForm')->name('client.password.request')->middleware(['domain_db', 'contact_account','locale']);
|
Route::get('client/password/reset', 'Auth\ContactForgotPasswordController@showLinkRequestForm')->name('client.password.request')->middleware(['domain_db', 'contact_account','locale']);
|
||||||
Route::post('client/password/email', 'Auth\ContactForgotPasswordController@sendResetLinkEmail')->name('client.password.email')->middleware('locale');
|
Route::post('client/password/email', 'Auth\ContactForgotPasswordController@sendResetLinkEmail')->name('client.password.email')->middleware('locale');
|
||||||
Route::get('client/password/reset/{token}', 'Auth\ContactResetPasswordController@showResetForm')->name('client.password.reset')->middleware(['domain_db', 'contact_account','locale']);
|
Route::get('client/password/reset/{token}', 'Auth\ContactResetPasswordController@showResetForm')->name('client.password.reset')->middleware(['domain_db', 'contact_account','locale']);
|
||||||
Route::post('client/password/reset', 'Auth\ContactResetPasswordController@reset')->name('client.password.update')->middleware('locale');
|
Route::post('client/password/reset', 'Auth\ContactResetPasswordController@reset')->name('client.password.update')->middleware(['domain_db', 'contact_account','locale']);
|
||||||
|
|
||||||
Route::get('view/{entity_type}/{invitation_key}', 'ClientPortal\EntityViewController@index')->name('client.entity_view');
|
Route::get('view/{entity_type}/{invitation_key}', 'ClientPortal\EntityViewController@index')->name('client.entity_view');
|
||||||
Route::get('view/{entity_type}/{invitation_key}/password', 'ClientPortal\EntityViewController@password')->name('client.entity_view.password');
|
Route::get('view/{entity_type}/{invitation_key}/password', 'ClientPortal\EntityViewController@password')->name('client.entity_view.password');
|
||||||
@ -21,8 +21,8 @@ Route::post('view/{entity_type}/{invitation_key}/password', 'ClientPortal\Entity
|
|||||||
|
|
||||||
Route::get('tmp_pdf/{hash}', 'ClientPortal\TempRouteController@index')->name('tmp_pdf');
|
Route::get('tmp_pdf/{hash}', 'ClientPortal\TempRouteController@index')->name('tmp_pdf');
|
||||||
|
|
||||||
Route::get('client/key_login/{contact_key}', 'ClientPortal\ContactHashLoginController@login')->name('client.contact_login')->middleware(['contact_key_login']);
|
Route::get('client/key_login/{contact_key}', 'ClientPortal\ContactHashLoginController@login')->name('client.contact_login')->middleware(['domain_db','contact_key_login']);
|
||||||
Route::get('client/magic_link/{magic_link}', 'ClientPortal\ContactHashLoginController@magicLink')->name('client.contact_magic_link')->middleware(['contact_key_login']);
|
Route::get('client/magic_link/{magic_link}', 'ClientPortal\ContactHashLoginController@magicLink')->name('client.contact_magic_link')->middleware(['domain_db','contact_key_login']);
|
||||||
Route::get('documents/{document_hash}', 'ClientPortal\DocumentController@publicDownload')->name('documents.public_download');
|
Route::get('documents/{document_hash}', 'ClientPortal\DocumentController@publicDownload')->name('documents.public_download');
|
||||||
Route::get('error', 'ClientPortal\ContactHashLoginController@errorPage')->name('client.error');
|
Route::get('error', 'ClientPortal\ContactHashLoginController@errorPage')->name('client.error');
|
||||||
|
|
||||||
|
@ -37,3 +37,5 @@ Route::group(['middleware' => ['url_db']], function () {
|
|||||||
|
|
||||||
Route::get('stripe/signup/{token}', 'StripeConnectController@initialize')->name('stripe_connect.initialization');
|
Route::get('stripe/signup/{token}', 'StripeConnectController@initialize')->name('stripe_connect.initialization');
|
||||||
Route::get('stripe/completed', 'StripeConnectController@completed')->name('stripe_connect.return');
|
Route::get('stripe/completed', 'StripeConnectController@completed')->name('stripe_connect.return');
|
||||||
|
|
||||||
|
Route::get('checkout/3ds_redirect/{company_key}/{company_gateway_id}/{hash}', 'Gateways\Checkout3dsController@index')->name('checkout.3ds_redirect');
|
||||||
|
@ -769,7 +769,7 @@ class ImportCompanyTest extends TestCase
|
|||||||
|
|
||||||
$this->backup_json_object->activities = $activities;
|
$this->backup_json_object->activities = $activities;
|
||||||
|
|
||||||
$this->genericImport(Activity::class,
|
$this->genericNewClassImport(Activity::class,
|
||||||
[
|
[
|
||||||
'user_id',
|
'user_id',
|
||||||
'company_id',
|
'company_id',
|
||||||
@ -806,8 +806,7 @@ class ImportCompanyTest extends TestCase
|
|||||||
['recurring_invoices' => 'recurring_invoice_id'],
|
['recurring_invoices' => 'recurring_invoice_id'],
|
||||||
['invitations' => 'invitation_id'],
|
['invitations' => 'invitation_id'],
|
||||||
],
|
],
|
||||||
'activities',
|
'activities');
|
||||||
'created_at');
|
|
||||||
|
|
||||||
$this->assertEquals(25, Activity::count());
|
$this->assertEquals(25, Activity::count());
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user