mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-15 15:42:51 +01:00
commit
7c0787e7e1
@ -1 +1 @@
|
|||||||
5.3.3
|
5.3.4
|
@ -13,6 +13,7 @@ namespace App\Http\Controllers\Auth;
|
|||||||
|
|
||||||
use App\Events\Contact\ContactLoggedIn;
|
use App\Events\Contact\ContactLoggedIn;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
@ -40,8 +41,16 @@ class ContactLoginController extends Controller
|
|||||||
$company = null;
|
$company = null;
|
||||||
}elseif (strpos($request->getHost(), 'invoicing.co') !== false) {
|
}elseif (strpos($request->getHost(), 'invoicing.co') !== false) {
|
||||||
$subdomain = explode('.', $request->getHost())[0];
|
$subdomain = explode('.', $request->getHost())[0];
|
||||||
|
|
||||||
|
MultiDB::findAndSetDbByDomain(['subdomain' => $subdomain]);
|
||||||
|
|
||||||
$company = Company::where('subdomain', $subdomain)->first();
|
$company = Company::where('subdomain', $subdomain)->first();
|
||||||
} elseif(Ninja::isHosted() && $company = Company::where('portal_domain', $request->getSchemeAndHttpHost())->first()){
|
|
||||||
|
} elseif(Ninja::isHosted()){
|
||||||
|
|
||||||
|
MultiDB::findAndSetDbByDomain(['portal_domain' => $request->getSchemeAndHttpHost()]);
|
||||||
|
|
||||||
|
$company = Company::where('portal_domain', $request->getSchemeAndHttpHost())->first();
|
||||||
|
|
||||||
}
|
}
|
||||||
elseif (Ninja::isSelfHost()) {
|
elseif (Ninja::isSelfHost()) {
|
||||||
@ -61,6 +70,9 @@ class ContactLoginController extends Controller
|
|||||||
{
|
{
|
||||||
Auth::shouldUse('contact');
|
Auth::shouldUse('contact');
|
||||||
|
|
||||||
|
if(Ninja::isHosted() && $request->has('db'))
|
||||||
|
MultiDB::setDb($request->input('db'));
|
||||||
|
|
||||||
$this->validateLogin($request);
|
$this->validateLogin($request);
|
||||||
// If the class is using the ThrottlesLogins trait, we can automatically throttle
|
// If the class is using the ThrottlesLogins trait, we can automatically throttle
|
||||||
// the login attempts for this application. We'll key this by the username and
|
// the login attempts for this application. We'll key this by the username and
|
||||||
|
@ -16,28 +16,28 @@ use App\Http\Controllers\Controller;
|
|||||||
use App\Http\Requests\ClientPortal\Uploads\StoreUploadRequest;
|
use App\Http\Requests\ClientPortal\Uploads\StoreUploadRequest;
|
||||||
use App\Libraries\MultiDB;
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
|
use App\Models\Company;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
|
use Auth;
|
||||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Auth;
|
|
||||||
|
|
||||||
class NinjaPlanController extends Controller
|
class NinjaPlanController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
public function index(string $contact_key)
|
public function index(string $contact_key, string $company_key)
|
||||||
{
|
{
|
||||||
|
MultiDB::findAndSetDbByCompanyKey($company_key);
|
||||||
|
$company = Company::where('company_key', $company_key)->first();
|
||||||
|
$account = $company->account;
|
||||||
|
|
||||||
if (Ninja::isHosted() && MultiDB::findAndSetDbByContactKey(request()->segment(3)) && $client_contact = ClientContact::where('contact_key', request()->segment(3))->first())
|
if (Ninja::isHosted() && MultiDB::findAndSetDbByContactKey(request()->segment(3)) && $client_contact = ClientContact::where('contact_key', request()->segment(3))->first())
|
||||||
{
|
{
|
||||||
// auth()->guard('contact')->login($client_contact, true);
|
Auth::guard('contact')->login($client_contact,true);
|
||||||
Auth::guard('contact')->login($client_contact);
|
|
||||||
|
|
||||||
/* Harvest user account*/
|
|
||||||
$account = $client_contact->company->account;
|
|
||||||
|
|
||||||
/* Current paid users get pushed straight to subscription overview page*/
|
/* Current paid users get pushed straight to subscription overview page*/
|
||||||
if($account->isPaid())
|
if($account->isPaidHostedClient())
|
||||||
return redirect('/client/subscriptions');
|
return redirect('/client/subscriptions');
|
||||||
|
|
||||||
/* Users that are not paid get pushed to a custom purchase page */
|
/* Users that are not paid get pushed to a custom purchase page */
|
||||||
|
@ -14,6 +14,7 @@ namespace App\Http\Controllers;
|
|||||||
|
|
||||||
use App\Jobs\Util\ImportStripeCustomers;
|
use App\Jobs\Util\ImportStripeCustomers;
|
||||||
use App\Jobs\Util\StripeUpdatePaymentMethods;
|
use App\Jobs\Util\StripeUpdatePaymentMethods;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\CompanyGateway;
|
use App\Models\CompanyGateway;
|
||||||
|
|
||||||
@ -60,6 +61,8 @@ class StripeController extends BaseController
|
|||||||
if(auth()->user()->isAdmin())
|
if(auth()->user()->isAdmin())
|
||||||
{
|
{
|
||||||
|
|
||||||
|
MultiDB::findAndSetDbByCompanyKey(auth()->user()->company()->company_key);
|
||||||
|
|
||||||
$company_gateway = CompanyGateway::where('company_id', auth()->user()->company()->id)
|
$company_gateway = CompanyGateway::where('company_id', auth()->user()->company()->id)
|
||||||
->where('is_deleted',0)
|
->where('is_deleted',0)
|
||||||
->whereIn('gateway_key', $this->stripe_keys)
|
->whereIn('gateway_key', $this->stripe_keys)
|
||||||
|
@ -79,7 +79,7 @@ class PortalComposer
|
|||||||
$data['currencies'] = TranslationHelper::getCurrencies();
|
$data['currencies'] = TranslationHelper::getCurrencies();
|
||||||
$data['contact'] = auth('contact')->user();
|
$data['contact'] = auth('contact')->user();
|
||||||
|
|
||||||
$data['multiple_contacts'] = session()->get('multiple_contacts');
|
$data['multiple_contacts'] = session()->get('multiple_contacts') ?: collect();
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@ -875,7 +875,7 @@ class CompanyImport implements ShouldQueue
|
|||||||
{
|
{
|
||||||
|
|
||||||
$this->genericImport(Design::class,
|
$this->genericImport(Design::class,
|
||||||
['company_id', 'user_id'],
|
['company_id', 'user_id', 'hashed_id'],
|
||||||
[
|
[
|
||||||
['users' => 'user_id'],
|
['users' => 'user_id'],
|
||||||
],
|
],
|
||||||
|
@ -51,8 +51,12 @@ class AutoBillCron
|
|||||||
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
->where('auto_bill_enabled', true)
|
->where('auto_bill_enabled', true)
|
||||||
->where('balance', '>', 0)
|
->where('balance', '>', 0)
|
||||||
->with('company')
|
->where('is_deleted', false)
|
||||||
->cursor()->each(function ($invoice){
|
->with('company');
|
||||||
|
|
||||||
|
nlog($auto_bill_partial_invoices->count(). " partial invoices to auto bill");
|
||||||
|
|
||||||
|
$auto_bill_partial_invoices->cursor()->each(function ($invoice){
|
||||||
$this->runAutoBiller($invoice);
|
$this->runAutoBiller($invoice);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -60,8 +64,12 @@ class AutoBillCron
|
|||||||
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
->where('auto_bill_enabled', true)
|
->where('auto_bill_enabled', true)
|
||||||
->where('balance', '>', 0)
|
->where('balance', '>', 0)
|
||||||
->with('company')
|
->where('is_deleted', false)
|
||||||
->cursor()->each(function ($invoice){
|
->with('company');
|
||||||
|
|
||||||
|
nlog($auto_bill_invoices->count(). " full invoices to auto bill");
|
||||||
|
|
||||||
|
$auto_bill_invoices->cursor()->each(function ($invoice){
|
||||||
$this->runAutoBiller($invoice);
|
$this->runAutoBiller($invoice);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -69,14 +77,19 @@ class AutoBillCron
|
|||||||
} else {
|
} else {
|
||||||
//multiDB environment, need to
|
//multiDB environment, need to
|
||||||
foreach (MultiDB::$dbs as $db) {
|
foreach (MultiDB::$dbs as $db) {
|
||||||
|
|
||||||
MultiDB::setDB($db);
|
MultiDB::setDB($db);
|
||||||
|
|
||||||
$auto_bill_partial_invoices = Invoice::whereDate('partial_due_date', '<=', now())
|
$auto_bill_partial_invoices = Invoice::whereDate('partial_due_date', '<=', now())
|
||||||
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
->where('auto_bill_enabled', true)
|
->where('auto_bill_enabled', true)
|
||||||
->where('balance', '>', 0)
|
->where('balance', '>', 0)
|
||||||
->with('company')
|
->where('is_deleted', false)
|
||||||
->cursor()->each(function ($invoice){
|
->with('company');
|
||||||
|
|
||||||
|
nlog($auto_bill_partial_invoices->count(). " partial invoices to auto bill db = {$db}");
|
||||||
|
|
||||||
|
$auto_bill_partial_invoices->cursor()->each(function ($invoice){
|
||||||
$this->runAutoBiller($invoice);
|
$this->runAutoBiller($invoice);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -84,8 +97,12 @@ class AutoBillCron
|
|||||||
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
->where('auto_bill_enabled', true)
|
->where('auto_bill_enabled', true)
|
||||||
->where('balance', '>', 0)
|
->where('balance', '>', 0)
|
||||||
->with('company')
|
->where('is_deleted', false)
|
||||||
->cursor()->each(function ($invoice){
|
->with('company');
|
||||||
|
|
||||||
|
nlog($auto_bill_invoices->count(). " full invoices to auto bill db = {$db}");
|
||||||
|
|
||||||
|
$auto_bill_invoices->cursor()->each(function ($invoice){
|
||||||
$this->runAutoBiller($invoice);
|
$this->runAutoBiller($invoice);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -96,6 +113,12 @@ class AutoBillCron
|
|||||||
private function runAutoBiller(Invoice $invoice)
|
private function runAutoBiller(Invoice $invoice)
|
||||||
{
|
{
|
||||||
info("Firing autobill for {$invoice->company_id} - {$invoice->number}");
|
info("Firing autobill for {$invoice->company_id} - {$invoice->number}");
|
||||||
|
|
||||||
|
try{
|
||||||
$invoice->service()->autoBill()->save();
|
$invoice->service()->autoBill()->save();
|
||||||
}
|
}
|
||||||
|
catch(\Exception $e) {
|
||||||
|
nlog("Failed to capture payment for {$invoice->company_id} - {$invoice->number} ->" . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ class RecurringInvoicesCron
|
|||||||
$recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
|
$recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
|
||||||
->whereNotNull('next_send_date')
|
->whereNotNull('next_send_date')
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
|
->where('is_deleted', false)
|
||||||
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
|
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
|
||||||
->where('remaining_cycles', '!=', '0')
|
->where('remaining_cycles', '!=', '0')
|
||||||
->whereHas('client', function ($query) {
|
->whereHas('client', function ($query) {
|
||||||
@ -61,8 +62,14 @@ class RecurringInvoicesCron
|
|||||||
nlog("Current date = " . now()->format("Y-m-d") . " Recurring date = " .$recurring_invoice->next_send_date);
|
nlog("Current date = " . now()->format("Y-m-d") . " Recurring date = " .$recurring_invoice->next_send_date);
|
||||||
|
|
||||||
if (!$recurring_invoice->company->is_disabled) {
|
if (!$recurring_invoice->company->is_disabled) {
|
||||||
|
|
||||||
|
try{
|
||||||
SendRecurring::dispatchNow($recurring_invoice, $recurring_invoice->company->db);
|
SendRecurring::dispatchNow($recurring_invoice, $recurring_invoice->company->db);
|
||||||
}
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
nlog("Unable to sending recurring invoice {$recurring_invoice->id}");
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//multiDB environment, need to
|
//multiDB environment, need to
|
||||||
@ -72,6 +79,7 @@ class RecurringInvoicesCron
|
|||||||
$recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
|
$recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
|
||||||
->whereNotNull('next_send_date')
|
->whereNotNull('next_send_date')
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
|
->where('is_deleted', false)
|
||||||
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
|
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
|
||||||
->where('remaining_cycles', '!=', '0')
|
->where('remaining_cycles', '!=', '0')
|
||||||
->whereHas('client', function ($query) {
|
->whereHas('client', function ($query) {
|
||||||
@ -87,8 +95,14 @@ class RecurringInvoicesCron
|
|||||||
nlog("Current date = " . now()->format("Y-m-d") . " Recurring date = " .$recurring_invoice->next_send_date ." Recurring #id = ". $recurring_invoice->id);
|
nlog("Current date = " . now()->format("Y-m-d") . " Recurring date = " .$recurring_invoice->next_send_date ." Recurring #id = ". $recurring_invoice->id);
|
||||||
|
|
||||||
if (!$recurring_invoice->company->is_disabled) {
|
if (!$recurring_invoice->company->is_disabled) {
|
||||||
|
|
||||||
|
try{
|
||||||
SendRecurring::dispatchNow($recurring_invoice, $recurring_invoice->company->db);
|
SendRecurring::dispatchNow($recurring_invoice, $recurring_invoice->company->db);
|
||||||
}
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
nlog("Unable to sending recurring invoice {$recurring_invoice->id} on db {$db}");
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,9 +129,21 @@ class SendRecurring implements ShouldQueue
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($invoice->client->getSetting('auto_bill_date') == 'on_send_date' && $this->recurring_invoice->auto_bill_enabled) {
|
if ($invoice->client->getSetting('auto_bill_date') == 'on_send_date' && $invoice->auto_bill_enabled) {
|
||||||
|
|
||||||
nlog("attempting to autobill {$invoice->number}");
|
nlog("attempting to autobill {$invoice->number}");
|
||||||
$invoice->service()->autoBill()->save();
|
$invoice->service()->autoBill()->save();
|
||||||
|
|
||||||
|
}
|
||||||
|
elseif($invoice->client->getSetting('auto_bill_date') == 'on_due_date' && $invoice->auto_bill_enabled) {
|
||||||
|
|
||||||
|
if($invoice->due_date && Carbon\Carbon::parse($invoice->due_date)->startOfDay()->lte(now()->startOfDay())) {
|
||||||
|
|
||||||
|
nlog("attempting to autobill {$invoice->number}");
|
||||||
|
$invoice->service()->autoBill()->save();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class SupportMessageSent extends Mailable
|
|||||||
$db = str_replace("db-ninja-", "", $company->db);
|
$db = str_replace("db-ninja-", "", $company->db);
|
||||||
|
|
||||||
if(Ninja::isHosted())
|
if(Ninja::isHosted())
|
||||||
$subject = "{$priority}Hosted-{$db} :: {$plan} :: ".date('M jS, g:ia');
|
$subject = "{$priority}Hosted-{$db}-[{$company->is_large}] :: {$plan} :: ".date('M jS, g:ia');
|
||||||
else
|
else
|
||||||
$subject = "{$priority}Self Hosted :: {$plan} :: ".date('M jS, g:ia');
|
$subject = "{$priority}Self Hosted :: {$plan} :: ".date('M jS, g:ia');
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ class TestMailServer extends Mailable
|
|||||||
$this->from_email = $from_email;
|
$this->from_email = $from_email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test Server mail.
|
* Test Server mail.
|
||||||
*
|
*
|
||||||
@ -36,12 +37,18 @@ class TestMailServer extends Mailable
|
|||||||
*/
|
*/
|
||||||
public function build()
|
public function build()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->primary_color = "#4caf50";
|
||||||
|
$settings->email_style = 'dark';
|
||||||
|
|
||||||
return $this->from(config('mail.from.address'), config('mail.from.name'))
|
return $this->from(config('mail.from.address'), config('mail.from.name'))
|
||||||
->subject(ctrans('texts.email'))
|
->subject(ctrans('texts.email'))
|
||||||
->markdown('email.support.message', [
|
->markdown('email.support.message', [
|
||||||
'support_message' => $this->support_messages,
|
'support_message' => $this->support_messages,
|
||||||
'system_info' => '',
|
'system_info' => '',
|
||||||
'laravel_log' => [],
|
'laravel_log' => [],
|
||||||
|
'settings' => $settings,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ class ClientGatewayToken extends BaseModel
|
|||||||
|
|
||||||
public function client()
|
public function client()
|
||||||
{
|
{
|
||||||
return $this->hasOne(Client::class)->withTrashed();
|
return $this->belongsTo(Client::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function gateway()
|
public function gateway()
|
||||||
@ -60,12 +60,12 @@ class ClientGatewayToken extends BaseModel
|
|||||||
|
|
||||||
public function company()
|
public function company()
|
||||||
{
|
{
|
||||||
return $this->hasOne(Company::class);
|
return $this->belongsTo(Company::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->hasOne(User::class)->withTrashed();
|
return $this->belongsTo(User::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +63,7 @@ class CreditCard
|
|||||||
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
|
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
|
||||||
'currency' => $this->stripe->client->getCurrencyCode(),
|
'currency' => $this->stripe->client->getCurrencyCode(),
|
||||||
'customer' => $this->stripe->findOrCreateCustomer(),
|
'customer' => $this->stripe->findOrCreateCustomer(),
|
||||||
'description' => ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number'), // TODO: More meaningful description.
|
'description' => $this->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')),
|
||||||
];
|
];
|
||||||
|
|
||||||
$payment_intent_data['setup_future_usage'] = 'off_session';
|
$payment_intent_data['setup_future_usage'] = 'off_session';
|
||||||
@ -74,6 +74,15 @@ class CreditCard
|
|||||||
return render('gateways.stripe.credit_card.pay', $data);
|
return render('gateways.stripe.credit_card.pay', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function decodeUnicodeString($string)
|
||||||
|
{
|
||||||
|
return iconv("UTF-8", "ISO-8859-1//TRANSLIT", $this->decode_encoded_utf8($string));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function decode_encoded_utf8($string){
|
||||||
|
return preg_replace_callback('#\\\\u([0-9a-f]{4})#ism', function($matches) { return mb_convert_encoding(pack("H*", $matches[1]), "UTF-8", "UCS-2BE"); }, $string);
|
||||||
|
}
|
||||||
|
|
||||||
public function paymentResponse(PaymentResponseRequest $request)
|
public function paymentResponse(PaymentResponseRequest $request)
|
||||||
{
|
{
|
||||||
$this->stripe->init();
|
$this->stripe->init();
|
||||||
|
@ -23,6 +23,7 @@ use App\Models\Currency;
|
|||||||
use App\Models\GatewayType;
|
use App\Models\GatewayType;
|
||||||
use App\PaymentDrivers\StripePaymentDriver;
|
use App\PaymentDrivers\StripePaymentDriver;
|
||||||
use App\PaymentDrivers\Stripe\UpdatePaymentMethods;
|
use App\PaymentDrivers\Stripe\UpdatePaymentMethods;
|
||||||
|
use App\Utils\Ninja;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use Stripe\Customer;
|
use Stripe\Customer;
|
||||||
@ -51,7 +52,7 @@ class ImportCustomers
|
|||||||
|
|
||||||
$this->update_payment_methods = new UpdatePaymentMethods($this->stripe);
|
$this->update_payment_methods = new UpdatePaymentMethods($this->stripe);
|
||||||
|
|
||||||
if(strlen($this->stripe->company_gateway->getConfigField('account_id')) < 1)
|
if(Ninja::isHosted() && strlen($this->stripe->company_gateway->getConfigField('account_id')) < 1)
|
||||||
throw new StripeConnectFailure('Stripe Connect has not been configured');
|
throw new StripeConnectFailure('Stripe Connect has not been configured');
|
||||||
|
|
||||||
$customers = Customer::all([], $this->stripe->stripe_connect_auth);
|
$customers = Customer::all([], $this->stripe->stripe_connect_auth);
|
||||||
@ -61,9 +62,6 @@ class ImportCustomers
|
|||||||
$this->addCustomer($customer);
|
$this->addCustomer($customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now call the update payment methods handler*/
|
|
||||||
// $this->stripe->updateAllPaymentMethods();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function addCustomer(Customer $customer)
|
private function addCustomer(Customer $customer)
|
||||||
@ -76,14 +74,21 @@ class ImportCustomers
|
|||||||
|
|
||||||
nlog("search Stripe for {$customer->id}");
|
nlog("search Stripe for {$customer->id}");
|
||||||
|
|
||||||
$existing_customer = $this->stripe
|
$existing_customer_token = $this->stripe
|
||||||
->company_gateway
|
->company_gateway
|
||||||
->client_gateway_tokens()
|
->client_gateway_tokens()
|
||||||
->where('gateway_customer_reference', $customer->id)
|
->where('gateway_customer_reference', $customer->id)
|
||||||
->exists();
|
->first();
|
||||||
|
|
||||||
if($existing_customer){
|
if($existing_customer_token){
|
||||||
nlog("Skipping - Customer exists: {$customer->email}");
|
nlog("Skipping - Customer exists: {$customer->email} just updating payment methods");
|
||||||
|
$this->update_payment_methods->updateMethods($customer, $existing_customer_token->client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($customer->email && $contact = $this->stripe->company_gateway->company->client_contacts()->where('email', $customer->email)->first()){
|
||||||
|
nlog("Customer exists: {$customer->email} just updating payment methods");
|
||||||
|
$this->update_payment_methods->updateMethods($customer, $contact->client);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,15 +97,15 @@ class ImportCustomers
|
|||||||
|
|
||||||
$client = ClientFactory::create($this->stripe->company_gateway->company_id, $this->stripe->company_gateway->user_id);
|
$client = ClientFactory::create($this->stripe->company_gateway->company_id, $this->stripe->company_gateway->user_id);
|
||||||
|
|
||||||
if(property_exists($customer, 'address'))
|
if($customer->address)
|
||||||
{
|
{
|
||||||
$client->address1 = property_exists($customer->address, 'line1') ? $customer->address->line1 : '';
|
$client->address1 = $customer->address->line1 ? $customer->address->line1 : '';
|
||||||
$client->address2 = property_exists($customer->address, 'line2') ? $customer->address->line2 : '';
|
$client->address2 = $customer->address->line2 ? $customer->address->line2 : '';
|
||||||
$client->city = property_exists($customer->address, 'city') ? $customer->address->city : '';
|
$client->city = $customer->address->city ? $customer->address->city : '';
|
||||||
$client->state = property_exists($customer->address, 'state') ? $customer->address->state : '';
|
$client->state = $customer->address->state ? $customer->address->state : '';
|
||||||
$client->phone = property_exists($customer->address, 'phone') ? $customer->phone : '';
|
$client->phone = $customer->address->phone ? $customer->phone : '';
|
||||||
|
|
||||||
if(property_exists($customer->address, 'country')){
|
if($customer->address->country){
|
||||||
|
|
||||||
$country = Country::where('iso_3166_2', $customer->address->country)->first();
|
$country = Country::where('iso_3166_2', $customer->address->country)->first();
|
||||||
|
|
||||||
@ -124,7 +129,7 @@ class ImportCustomers
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$client->name = property_exists($customer, 'name') ? $customer->name : $customer->email;
|
$client->name = $customer->name ? $customer->name : $customer->email;
|
||||||
|
|
||||||
if (!isset($client->number) || empty($client->number)) {
|
if (!isset($client->number) || empty($client->number)) {
|
||||||
$client->number = $this->getNextClientNumber($client);
|
$client->number = $this->getNextClientNumber($client);
|
||||||
|
@ -130,6 +130,7 @@ class UpdatePaymentMethods
|
|||||||
$token_exists = ClientGatewayToken::where([
|
$token_exists = ClientGatewayToken::where([
|
||||||
'gateway_customer_reference' => $customer_reference,
|
'gateway_customer_reference' => $customer_reference,
|
||||||
'token' => $method->id,
|
'token' => $method->id,
|
||||||
|
'company_id' => $client->company_id,
|
||||||
])->exists();
|
])->exists();
|
||||||
|
|
||||||
/* Already exists return */
|
/* Already exists return */
|
||||||
|
@ -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.3.3',
|
'app_version' => '5.3.4',
|
||||||
'app_tag' => '5.3.3',
|
'app_tag' => '5.3.4',
|
||||||
'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', ''),
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
<a class="text-xs text-gray-600 hover:text-gray-800 ease-in duration-100"
|
<a class="text-xs text-gray-600 hover:text-gray-800 ease-in duration-100"
|
||||||
href="{{ route('client.password.request') }}">{{ trans('texts.forgot_password') }}</a>
|
href="{{ route('client.password.request') }}">{{ trans('texts.forgot_password') }}</a>
|
||||||
</div>
|
</div>
|
||||||
|
@if($company)
|
||||||
|
<input type="hidden" name="db" value="{{$company->db}}">
|
||||||
|
@endif
|
||||||
<input type="password" name="password" id="password"
|
<input type="password" name="password" id="password"
|
||||||
class="input"
|
class="input"
|
||||||
autofocus>
|
autofocus>
|
||||||
|
@ -0,0 +1,171 @@
|
|||||||
|
@extends('portal.ninja2020.layout.app')
|
||||||
|
@section('meta_title', ctrans('texts.pro_plan_call_to_action'))
|
||||||
|
|
||||||
|
@section('body')
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Toggle A */
|
||||||
|
input:checked ~ .dot {
|
||||||
|
transform: translateX(100%);
|
||||||
|
background-color: #48bb78;
|
||||||
|
}
|
||||||
|
/* Toggle B */
|
||||||
|
input:checked ~ .dot {
|
||||||
|
transform: translateX(100%);
|
||||||
|
background-color: #48bb78;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="container flex flex-wrap pt-4 pb-10 m-auto mt-6 md:mt-15 lg:px-12 xl:px-16" x-data="{show: true}">
|
||||||
|
<div class="w-full px-0 lg:px-4">
|
||||||
|
<h2 class="px-12 text-base font-bold text-center md:text-2xl text-blue-700">
|
||||||
|
Choose your plan
|
||||||
|
</h2>
|
||||||
|
<p class="py-1 text-sm text-center text-blue-700 mb-10">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Toggle B -->
|
||||||
|
<div class="flex items-center justify-center w-full mb-12"">
|
||||||
|
|
||||||
|
<label for="toggleB" class="flex items-center cursor-pointer">
|
||||||
|
<!-- toggle -->
|
||||||
|
<div class="relative">
|
||||||
|
<!-- input -->
|
||||||
|
<input type="checkbox" id="toggleB" class="sr-only" @click="show = !show">
|
||||||
|
<!-- line -->
|
||||||
|
<div class="block bg-gray-600 w-14 h-8 rounded-full"></div>
|
||||||
|
<!-- dot -->
|
||||||
|
<div class="dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition"></div>
|
||||||
|
</div>
|
||||||
|
<!-- label -->
|
||||||
|
<div class="ml-3 text-gray-700 font-medium">
|
||||||
|
Monthly vs Annual
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- monthly Plans -->
|
||||||
|
|
||||||
|
<div class="flex flex-wrap items-center justify-center py-4 pt-0" x-show=" show ">
|
||||||
|
<div class="w-full p-4 md:w-1/2 lg:w-1/2">
|
||||||
|
<label class="flex flex-col rounded-lg shadow-lg relative cursor-pointer hover:shadow-2xl">
|
||||||
|
<div class="w-full px-4 py-8 rounded-t-lg bg-blue-500">
|
||||||
|
<h3 class="mx-auto text-base font-semibold text-center underline text-white group-hover:text-white">
|
||||||
|
Pro Plan
|
||||||
|
</h3>
|
||||||
|
<p class="text-5xl font-bold text-center text-white">
|
||||||
|
$10
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-center uppercase text-white">
|
||||||
|
monthly
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700">
|
||||||
|
<p class="text-xl text-white">
|
||||||
|
Sign up!
|
||||||
|
</p>
|
||||||
|
<a type="button" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500" href="https://invoiceninja.invoicing.co/client/subscriptions/WJxbojagwO/purchase">
|
||||||
|
Purchase
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="w-full p-4 md:w-1/2 lg:w-1/2">
|
||||||
|
<label class="flex flex-col rounded-lg shadow-lg relative cursor-pointer hover:shadow-2xl">
|
||||||
|
<div class="w-full px-4 py-8 rounded-t-lg bg-blue-500">
|
||||||
|
<h3 class="mx-auto text-base font-semibold text-center underline text-white group-hover:text-white">
|
||||||
|
Enterprise (1-2 Users)
|
||||||
|
</h3>
|
||||||
|
<p class="text-5xl font-bold text-center text-white">
|
||||||
|
$14
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-center uppercase text-white">
|
||||||
|
monthly
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700">
|
||||||
|
<p class="text-xl text-white">
|
||||||
|
Sign up!
|
||||||
|
</p>
|
||||||
|
<a type="button" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500" href="https://invoiceninja.invoicing.co/client/subscriptions/7LDdwRb1YK/purchase">
|
||||||
|
Purchase
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Annual Plans -->
|
||||||
|
<div class="flex flex-wrap items-center justify-center py-4 pt-0" x-show=" !show ">
|
||||||
|
<div class="w-full p-4 md:w-1/2 lg:w-1/2">
|
||||||
|
<label class="flex flex-col rounded-lg shadow-lg relative cursor-pointer hover:shadow-2xl">
|
||||||
|
<div class="w-full px-4 py-8 rounded-t-lg bg-blue-500">
|
||||||
|
<h3 class="mx-auto text-base font-semibold text-center underline text-white group-hover:text-white">
|
||||||
|
Pro Plan
|
||||||
|
</h3>
|
||||||
|
<p class="text-5xl font-bold text-center text-white">
|
||||||
|
$100
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-center uppercase text-white">
|
||||||
|
yearly
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700"
|
||||||
|
>
|
||||||
|
<p class="text-xl text-white">
|
||||||
|
Buy 10 months get 2 free!
|
||||||
|
</p>
|
||||||
|
<a type="button" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500" href="https://invoiceninja.invoicing.co/client/subscriptions/q9wdL9wejP/purchase">
|
||||||
|
Purchase
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full p-4 md:w-1/2 lg:w-1/2">
|
||||||
|
<label class="flex flex-col rounded-lg shadow-lg relative cursor-pointer hover:shadow-2xl">
|
||||||
|
<div class="w-full px-4 py-8 rounded-t-lg bg-blue-500">
|
||||||
|
<h3 class="mx-auto text-base font-semibold text-center underline text-white group-hover:text-white">
|
||||||
|
Enterprise (1-2 Users)
|
||||||
|
</h3>
|
||||||
|
<p class="text-5xl font-bold text-center text-white">
|
||||||
|
$140
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-center uppercase text-white">
|
||||||
|
yearly
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex flex-col items-center justify-center w-full h-full py-6 rounded-b-lg bg-blue-700"
|
||||||
|
>
|
||||||
|
<p class="text-xl text-white">
|
||||||
|
Buy 10 months get 2 free!
|
||||||
|
</p>
|
||||||
|
<a type="button" class="w-5/6 py-2 mt-2 font-semibold text-center uppercase bg-white border border-transparent rounded text-blue-500" href="https://invoiceninja.invoicing.co/client/subscriptions/LYqaQWldnj/purchase">
|
||||||
|
Purchase
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('footer')
|
||||||
|
|
||||||
|
|
||||||
|
@endpush
|
@ -26,7 +26,7 @@ Route::get('client/magic_link/{magic_link}', 'ClientPortal\ContactHashLoginContr
|
|||||||
Route::get('documents/{document_hash}', 'ClientPortal\DocumentController@publicDownload')->name('documents.public_download')->middleware(['document_db']);
|
Route::get('documents/{document_hash}', 'ClientPortal\DocumentController@publicDownload')->name('documents.public_download')->middleware(['document_db']);
|
||||||
Route::get('error', 'ClientPortal\ContactHashLoginController@errorPage')->name('client.error');
|
Route::get('error', 'ClientPortal\ContactHashLoginController@errorPage')->name('client.error');
|
||||||
Route::get('client/payment/{contact_key}/{payment_id}', 'ClientPortal\InvitationController@paymentRouter')->middleware(['domain_db','contact_key_login']);
|
Route::get('client/payment/{contact_key}/{payment_id}', 'ClientPortal\InvitationController@paymentRouter')->middleware(['domain_db','contact_key_login']);
|
||||||
Route::get('client/ninja/{contact_key}', 'ClientPortal\NinjaPlanController@index')->name('client.ninja_contact_login')->middleware(['domain_db']);
|
Route::get('client/ninja/{contact_key}/{company_key}', 'ClientPortal\NinjaPlanController@index')->name('client.ninja_contact_login')->middleware(['domain_db']);
|
||||||
|
|
||||||
Route::group(['middleware' => ['auth:contact', 'locale', 'check_client_existence','domain_db'], 'prefix' => 'client', 'as' => 'client.'], function () {
|
Route::group(['middleware' => ['auth:contact', 'locale', 'check_client_existence','domain_db'], 'prefix' => 'client', 'as' => 'client.'], function () {
|
||||||
Route::get('dashboard', 'ClientPortal\DashboardController@index')->name('dashboard'); // name = (dashboard. index / create / show / update / destroy / edit
|
Route::get('dashboard', 'ClientPortal\DashboardController@index')->name('dashboard'); // name = (dashboard. index / create / show / update / destroy / edit
|
||||||
|
Loading…
Reference in New Issue
Block a user