mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-05 18:52:44 +01:00
Set Invitations as a default include for invoices (#3362)
* Working on importing company gateways * Fix for companyuser settings object * Migrate client_gateway_tokens * Working on Notificaitons * Working on notifications * Failsafe for user-company * unlink files * Set DB for jobs * Always have a fallback for company_id * Fixes for user model * Formatting for MultiDB * Working on Company Ledger Tests * Fixes for contact request * Set Invitations as a default include for invoices
This commit is contained in:
parent
c97d664d31
commit
3d31f810c0
@ -83,6 +83,14 @@ class CreateTestData extends Command
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
|
||||
$settings = $company->settings;
|
||||
|
||||
$settings->system_notifications_slack = config('ninja.notification.slack');
|
||||
$settings->system_notifications_email = config('ninja.contact.email');
|
||||
|
||||
$company->settings = $settings;
|
||||
$company->save();
|
||||
|
||||
$account->default_company_id = $company->id;
|
||||
$account->save();
|
||||
|
||||
@ -167,6 +175,15 @@ class CreateTestData extends Command
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
|
||||
|
||||
$settings = $company->settings;
|
||||
|
||||
$settings->system_notifications_slack = config('ninja.notification.slack');
|
||||
$settings->system_notifications_email = config('ninja.contact.email');
|
||||
|
||||
$company->settings = $settings;
|
||||
$company->save();
|
||||
|
||||
$account->default_company_id = $company->id;
|
||||
$account->save();
|
||||
|
||||
@ -265,6 +282,14 @@ class CreateTestData extends Command
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
|
||||
$settings = $company->settings;
|
||||
|
||||
$settings->system_notifications_slack = config('ninja.notification.slack');
|
||||
$settings->system_notifications_email = config('ninja.contact.email');
|
||||
|
||||
$company->settings = $settings;
|
||||
$company->save();
|
||||
|
||||
$account->default_company_id = $company->id;
|
||||
$account->save();
|
||||
|
||||
|
@ -193,6 +193,9 @@ class CompanySettings extends BaseSettings {
|
||||
public $client_online_payment_notification = true;
|
||||
public $client_manual_payment_notification = true;
|
||||
|
||||
public $system_notifications_slack = '';
|
||||
public $system_notifications_email = '';
|
||||
|
||||
/* Company Meta data that we can use to build sub companies*/
|
||||
|
||||
public $name = '';
|
||||
@ -220,6 +223,8 @@ class CompanySettings extends BaseSettings {
|
||||
public $pdf_variables = [];
|
||||
|
||||
public static $casts = [
|
||||
'system_notifications_slack' => 'string',
|
||||
'system_notifications_email' => 'string',
|
||||
'portal_design_id' => 'string',
|
||||
'late_fee_endless_percent' => 'float',
|
||||
'late_fee_endless_amount' => 'float',
|
||||
@ -401,9 +406,11 @@ class CompanySettings extends BaseSettings {
|
||||
* @return object
|
||||
*/
|
||||
public static function defaults():\stdClass {
|
||||
|
||||
$config = json_decode(config('ninja.settings'));
|
||||
|
||||
$data = (object) get_class_vars(CompanySettings::class );
|
||||
|
||||
unset($data->casts);
|
||||
unset($data->protected_fields);
|
||||
|
||||
@ -415,7 +422,7 @@ class CompanySettings extends BaseSettings {
|
||||
$data->date_format_id = (string) config('ninja.i18n.date_format_id');
|
||||
$data->country_id = (string) config('ninja.i18n.country_id');
|
||||
$data->translations = (object) [];
|
||||
$data->pdf_variables = (array) self::getEntityVariableDefaults();
|
||||
$data->pdf_variables = (array) self::getEntityVariableDefaults();
|
||||
|
||||
// $data->email_subject_invoice = EmailTemplateDefaults::emailInvoiceSubject();
|
||||
// $data->email_template_invoice = EmailTemplateDefaults:: emailInvoiceTemplate();
|
||||
|
@ -213,8 +213,8 @@ class CompanyController extends BaseController
|
||||
'is_owner' => 1,
|
||||
'is_admin' => 1,
|
||||
'is_locked' => 0,
|
||||
'permissions' => json_encode([]),
|
||||
'settings' => json_encode(DefaultSettings::userSettings()),
|
||||
'permissions' => '',
|
||||
'settings' => DefaultSettings::userSettings(),
|
||||
]);
|
||||
|
||||
/*
|
||||
|
@ -520,7 +520,7 @@ class InvoiceController extends BaseController {
|
||||
|
||||
});
|
||||
|
||||
ZipInvoices::dispatch($invoices, $invoices->first()->company);
|
||||
ZipInvoices::dispatch($invoices, $invoices->first()->company, auth()->user()->email);
|
||||
|
||||
return response()->json(['message' => 'Email Sent!'],200);
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ class TokenAuth
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if ($request->header('X-API-TOKEN') && ($company_token = CompanyToken::with(['user','company'])->whereRaw("BINARY `token`= ?", [$request->header('X-API-TOKEN')])->first())) {
|
||||
|
||||
$user = $company_token->user;
|
||||
|
||||
|
||||
$error = [
|
||||
'message' => 'User inactive',
|
||||
@ -48,6 +48,12 @@ class TokenAuth
|
||||
|
|
||||
*/
|
||||
$user->setCompany($company_token->company);
|
||||
|
||||
config(['ninja.company_id' => $company_token->company->id]);
|
||||
|
||||
app('queue')->createPayloadUsing(function () use($company_token) {
|
||||
return ['db' => $company_token->company->db];
|
||||
});
|
||||
|
||||
//user who once existed, but has been soft deleted
|
||||
if ($user->company_user->is_locked) {
|
||||
|
@ -70,12 +70,12 @@ class StoreClientRequest extends Request
|
||||
|
||||
if(isset($input['contacts']))
|
||||
{
|
||||
foreach($input['contacts'] as $contact)
|
||||
foreach($input['contacts'] as $key => $contact)
|
||||
{
|
||||
if(is_numeric($contact['id']))
|
||||
unset($contact['id']);
|
||||
unset($input['contacts'][$key]['id']);
|
||||
elseif(is_string($contact['id']))
|
||||
$contact['id'] = $this->decodePrimaryKey($contact['id']);
|
||||
$input['contacts'][$key]['id'] = $this->decodePrimaryKey($contact['id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,12 +81,12 @@ class UpdateClientRequest extends Request
|
||||
|
||||
if(isset($input['contacts']))
|
||||
{
|
||||
foreach($input['contacts'] as $contact)
|
||||
foreach($input['contacts'] as $key => $contact)
|
||||
{
|
||||
if(is_numeric($contact['id']))
|
||||
unset($contact['id']);
|
||||
unset($input['contacts'][$key]['id']);
|
||||
elseif(is_string($contact['id']))
|
||||
$contact['id'] = $this->decodePrimaryKey($contact['id']);
|
||||
$input['contacts'][$key]['id'] = $this->decodePrimaryKey($contact['id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,14 @@ class CreateAccount
|
||||
|
||||
$user->fresh();
|
||||
|
||||
Notification::route('slack', config('ninja.notification.slack'))
|
||||
->notify(new NewAccountCreated($user, $company));
|
||||
$company->notification(new NewAccountCreated($user, $company))->run();
|
||||
|
||||
// $user->route('slack', $company->settings->system_notifications_slack)
|
||||
// ->route('mail', $company->settings->system_notifications_email)
|
||||
// ->notify(new NewAccountCreated($user, $company));
|
||||
|
||||
// Notification::route('slack', config('ninja.notification.slack'))
|
||||
// ->notify(new NewAccountCreated($user, $company));
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
@ -35,19 +35,17 @@ class ApplyCreditPayment implements ShouldQueue
|
||||
|
||||
public $amount;
|
||||
|
||||
private $company;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Credit $credit, Payment $payment, float $amount, Company $company)
|
||||
public function __construct(Credit $credit, Payment $payment, float $amount)
|
||||
{
|
||||
$this->credit = $credit;
|
||||
$this->payment = $payment;
|
||||
$this->amount = $amount;
|
||||
$this->company = $company;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,7 +56,6 @@ class ApplyCreditPayment implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::setDB($this->company->db);
|
||||
|
||||
/* Update Pivot Record amount */
|
||||
$this->payment->credits->each(function ($cred) {
|
||||
|
@ -16,7 +16,6 @@ use App\Events\Credit\CreditWasEmailedAndFailed;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\TemplateEmail;
|
||||
use App\Models\Company;
|
||||
use App\Models\Credit;
|
||||
use App\Models\SystemLog;
|
||||
use Illuminate\Bus\Queueable;
|
||||
@ -34,18 +33,15 @@ class EmailCredit implements ShouldQueue
|
||||
|
||||
public $message_array = [];
|
||||
|
||||
private $company;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Credit $credit, Company $company)
|
||||
public function __construct(Credit $credit)
|
||||
{
|
||||
$this->credit = $credit;
|
||||
|
||||
$this->company = $company;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,9 +52,6 @@ class EmailCredit implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
/*Jobs are not multi-db aware, need to set! */
|
||||
MultiDB::setDB($this->company->db);
|
||||
|
||||
//todo - change runtime config of mail driver if necessary
|
||||
|
||||
$template_style = $this->credit->client->getSetting('email_style');
|
||||
|
@ -21,20 +21,16 @@ class StoreCredit implements ShouldQueue
|
||||
|
||||
protected $data;
|
||||
|
||||
private $company;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Credit $credit, array $data, Company $company)
|
||||
public function __construct(Credit $credit, array $data)
|
||||
{
|
||||
$this->credit = $credit;
|
||||
|
||||
$this->data = $data;
|
||||
|
||||
$this->company = $company;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Jobs\Cron;
|
||||
|
||||
use App\Jobs\RecurringInvoice\SendRecurring;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\RecurringInvoice;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
@ -63,8 +63,6 @@ class CreateInvoicePdf implements ShouldQueue {
|
||||
|
||||
public function handle() {
|
||||
|
||||
MultiDB::setDB($this->company->db);
|
||||
|
||||
$this->invoice->load('client');
|
||||
|
||||
if(!$this->contact)
|
||||
|
@ -54,7 +54,6 @@ class EmailInvoice implements ShouldQueue
|
||||
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
Mail::to($this->invoice_invitation->contact->email, $this->invoice_invitation->contact->present()->name())
|
||||
->send(new TemplateEmail($this->email_builder,
|
||||
|
@ -64,8 +64,6 @@ class StoreInvoice implements ShouldQueue
|
||||
*/
|
||||
public function handle(InvoiceRepository $invoice_repo) : ?Invoice
|
||||
{
|
||||
MultiDB::setDB($this->company->db);
|
||||
|
||||
$payment = false;
|
||||
|
||||
// /* Test if we should auto-bill the invoice */
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace App\Jobs\Invoice;
|
||||
|
||||
use App\Jobs\Util\UnlinkFile;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\DownloadInvoices;
|
||||
use App\Models\Company;
|
||||
@ -20,10 +21,10 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class ZipInvoices implements ShouldQueue
|
||||
{
|
||||
@ -33,17 +34,21 @@ class ZipInvoices implements ShouldQueue
|
||||
|
||||
private $company;
|
||||
|
||||
private $email;
|
||||
|
||||
/**
|
||||
* @deprecated confirm to be deleted
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($invoices, Company $company)
|
||||
public function __construct($invoices, Company $company, $email)
|
||||
{
|
||||
$this->invoices = $invoices;
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->email = $email;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,7 +59,6 @@ class ZipInvoices implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::setDB($this->company->db);
|
||||
|
||||
$tempStream = fopen('php://memory', 'w+');
|
||||
|
||||
@ -78,9 +82,9 @@ class ZipInvoices implements ShouldQueue
|
||||
|
||||
fclose($tempStream);
|
||||
|
||||
//fire email here
|
||||
Mail::to(config('ninja.contact.ninja_official_contact'))
|
||||
->send(new DownloadInvoices(Storage::disk(config('filesystems.default'))->url($path . $file_name)));
|
||||
Mail::to($this->email)
|
||||
->send(new DownloadInvoices(Storage::disk(config('filesystems.default'))->url($path . $file_name), $this->company));
|
||||
|
||||
UnlinkFile::dispatch(config('filesystems.default'), $path . $file_name)->delay(now()->addHours(1));
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ class PaymentNotification implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::setDB($this->company->db);
|
||||
|
||||
//notification for the payment.
|
||||
//
|
||||
|
@ -15,12 +15,17 @@ use App\Factory\RecurringInvoiceToInvoiceFactory;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
|
||||
class SendRecurring
|
||||
class SendRecurring implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
use GeneratesCounter;
|
||||
|
||||
public $recurring_invoice;
|
||||
@ -46,7 +51,6 @@ class SendRecurring
|
||||
*/
|
||||
public function handle() : void
|
||||
{
|
||||
MultiDb::setDb($this->db);
|
||||
|
||||
// Generate Standard Invoice
|
||||
$invoice = RecurringInvoiceToInvoiceFactory::create($this->recurring_invoice);
|
||||
|
@ -14,12 +14,15 @@ use App\Factory\QuoteFactory;
|
||||
use App\Factory\TaxRateFactory;
|
||||
use App\Factory\UserFactory;
|
||||
use App\Http\Requests\Company\UpdateCompanyRequest;
|
||||
use App\Http\ValidationRules\ValidCompanyGatewayFeesAndLimitsRule;
|
||||
use App\Http\ValidationRules\ValidUserForCompany;
|
||||
use App\Jobs\Company\CreateCompanyToken;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\MigrationFailed;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Document;
|
||||
use App\Models\Invoice;
|
||||
@ -37,6 +40,7 @@ use App\Repositories\PaymentRepository;
|
||||
use App\Repositories\ProductRepository;
|
||||
use App\Repositories\QuoteRepository;
|
||||
use App\Repositories\UserRepository;
|
||||
use App\Utils\Traits\CompanyGatewayFeesAndLimitsSaver;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
@ -49,6 +53,7 @@ use Illuminate\Support\Str;
|
||||
class Import implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
use CompanyGatewayFeesAndLimitsSaver;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
@ -64,7 +69,18 @@ class Import implements ShouldQueue
|
||||
* @var array
|
||||
*/
|
||||
private $available_imports = [
|
||||
'company', 'users', 'tax_rates', 'clients', 'products', 'invoices', 'quotes', 'payments', 'credits', 'documents',
|
||||
'company',
|
||||
'users',
|
||||
'tax_rates',
|
||||
'clients',
|
||||
'products',
|
||||
'invoices',
|
||||
'quotes',
|
||||
'payments',
|
||||
'credits',
|
||||
'company_gateways',
|
||||
'documents',
|
||||
'client_gateway_tokens',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -110,6 +126,7 @@ class Import implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
try {
|
||||
foreach ($this->data as $key => $resource) {
|
||||
|
||||
@ -143,7 +160,7 @@ class Import implements ShouldQueue
|
||||
$validator = Validator::make($data, $rules);
|
||||
|
||||
if ($validator->fails()) {
|
||||
\Log::error($validator->errors());
|
||||
// \Log::error($validator->errors());
|
||||
throw new MigrationValidatorFailed($validator->errors());
|
||||
}
|
||||
|
||||
@ -548,11 +565,84 @@ class Import implements ShouldQueue
|
||||
|
||||
$this->ids['documents'] = [
|
||||
"documents_{$old_user_key}" => [
|
||||
'old' => $old_user_key,
|
||||
'old' => $resource['id'],
|
||||
'new' => $document->id,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function processCompanyGateways(array $data) :void
|
||||
{
|
||||
CompanyGateway::unguard();
|
||||
|
||||
$rules = [
|
||||
'*.gateway_key' => 'required',
|
||||
'*.fees_and_limits' => new ValidCompanyGatewayFeesAndLimitsRule(),
|
||||
];
|
||||
|
||||
$validator = Validator::make($data, $rules);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new MigrationValidatorFailed($validator->errors());
|
||||
}
|
||||
|
||||
foreach ($data as $resource) {
|
||||
|
||||
$modified = $resource;
|
||||
|
||||
$modified['user_id'] = $this->processUserId($resource);
|
||||
$modified['company_id'] = $this->company->id;
|
||||
|
||||
unset($modified['id']);
|
||||
|
||||
if (isset($modified['config'])) {
|
||||
$modified['config'] = encrypt($modified['config']);
|
||||
}
|
||||
|
||||
if (isset($modified['fees_and_limits'])) {
|
||||
$modified['fees_and_limits'] = $this->cleanFeesAndLimits($modified['fees_and_limits']);
|
||||
}
|
||||
|
||||
$company_gateway = CompanyGateway::create($modified);
|
||||
|
||||
$old_user_key = array_key_exists('user_id', $resource) ?? $this->user->id;
|
||||
|
||||
$this->ids['company_gateways'] = [
|
||||
"company_gateways_{$old_user_key}" => [
|
||||
'old' => $resource['id'],
|
||||
'new' => $company_gateway->id,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function processClientGatewayTokens(array $data) :void
|
||||
{
|
||||
ClientGatewayToken::unguard();
|
||||
|
||||
foreach ($data as $resource) {
|
||||
|
||||
$modified = $resource;
|
||||
|
||||
unset($modified['id']);
|
||||
|
||||
$modified['company_id'] = $this->company->id;
|
||||
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
||||
|
||||
$cgt = ClientGatewayToken::Create($modified);
|
||||
|
||||
$old_user_key = array_key_exists('user_id', $resource) ?? $this->user->id;
|
||||
|
||||
$this->ids['client_gateway_tokens'] = [
|
||||
"client_gateway_tokens_{$old_user_key}" => [
|
||||
'old' => $resource['id'],
|
||||
'new' => $cgt->id,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
38
app/Jobs/Util/UnlinkFile.php
Normal file
38
app/Jobs/Util/UnlinkFile.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs\Util;
|
||||
|
||||
use App\Utils\Traits\BulkOptions;
|
||||
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 UnlinkFile implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $file_path;
|
||||
|
||||
protected $disk;
|
||||
|
||||
public function __construct(string $disk, string $file_path)
|
||||
{
|
||||
$this->file_path = $file_path;
|
||||
$this->disk = $disk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
Storage::disk($this->disk)->delete($this->file_path);
|
||||
|
||||
}
|
||||
}
|
@ -215,7 +215,7 @@ class MultiDB
|
||||
* @param $database
|
||||
*/
|
||||
public static function setDB(string $database) : void
|
||||
{
|
||||
{
|
||||
/* This will set the database connection for the request */
|
||||
config(['database.default' => $database]);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
@ -14,9 +15,13 @@ class DownloadInvoices extends Mailable
|
||||
|
||||
public $file_path;
|
||||
|
||||
public function __construct($file_path)
|
||||
public $company;
|
||||
|
||||
public function __construct($file_path, Company $company)
|
||||
{
|
||||
$this->file_path = $file_path;
|
||||
|
||||
$this->company = $company;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -27,10 +32,17 @@ class DownloadInvoices extends Mailable
|
||||
public function build()
|
||||
{
|
||||
|
||||
return $this->from(config('mail.from.address')) //todo this needs to be fixed to handle the hosted version
|
||||
->subject(ctrans('texts.download_documents',['size'=>'']))
|
||||
->markdown('email.admin.download_files', [
|
||||
'file_path' => $this->file_path
|
||||
]);
|
||||
return $this->subject(ctrans('texts.download_files'))
|
||||
->markdown('email.admin.download_files',
|
||||
[
|
||||
'url' => $this->file_path,
|
||||
'logo' => $this->company->present()->logo,
|
||||
]);
|
||||
|
||||
// return $this->from(config('mail.from.address')) //todo this needs to be fixed to handle the hosted version
|
||||
// ->subject(ctrans('texts.download_documents',['size'=>'']))
|
||||
// ->markdown('email.admin.download_files', [
|
||||
// 'file_path' => $this->file_path
|
||||
// ]);
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,13 @@ use App\Models\TaxRate;
|
||||
use App\Models\Timezone;
|
||||
use App\Models\Traits\AccountTrait;
|
||||
use App\Models\User;
|
||||
use App\Services\Notification\NotificationService;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\CompanySettingsSaver;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\ThrottlesEmail;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
|
||||
@ -300,7 +302,8 @@ class Company extends BaseModel
|
||||
|
||||
public function company_users()
|
||||
{
|
||||
return $this->hasMany(CompanyUser::class)->withTimestamps();
|
||||
//return $this->hasMany(CompanyUser::class)->withTimestamps();
|
||||
return $this->hasMany(CompanyUser::class);
|
||||
}
|
||||
|
||||
public function owner()
|
||||
@ -320,4 +323,19 @@ class Company extends BaseModel
|
||||
{
|
||||
return 'https://' . $this->subdomain . config('ninja.app_domain');
|
||||
}
|
||||
|
||||
public function notification(Notification $notification)
|
||||
{
|
||||
return new NotificationService($this, $notification);
|
||||
}
|
||||
|
||||
public function routeNotificationForSlack($notification)
|
||||
{
|
||||
//todo need to return the company channel here for hosted users
|
||||
//else the env variable for selfhosted
|
||||
if(config('ninja.environment') == 'selfhosted')
|
||||
return config('ninja.notification.slack');
|
||||
else
|
||||
return $this->settings->system_notifications_slack;
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +152,10 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||
*/
|
||||
public function getCompany()
|
||||
{
|
||||
return $this->company;
|
||||
if($this->company)
|
||||
return $this->company;
|
||||
|
||||
return Company::find( config('ninja.company_id') );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -298,7 +301,13 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||
{
|
||||
//todo need to return the company channel here for hosted users
|
||||
//else the env variable for selfhosted
|
||||
return config('ninja.notification.slack');
|
||||
if(config('ninja.environment') == 'selfhosted')
|
||||
return config('ninja.notification.slack');
|
||||
|
||||
if($this->company())
|
||||
return $this->company()->settings->system_notifications_slack;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Mail\Signup\NewSignup;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
@ -36,7 +37,8 @@ class NewAccountCreated extends Notification implements ShouldQueue
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['slack'];
|
||||
//return ['mail'];
|
||||
return ['slack','mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,10 +49,25 @@ class NewAccountCreated extends Notification implements ShouldQueue
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
|
||||
$user_name = $this->user->first_name . " " . $this->user->last_name;
|
||||
$email = $this->user->email;
|
||||
$ip = $this->user->ip;
|
||||
|
||||
$data = [
|
||||
'title' => ctrans('texts.new_signup'),
|
||||
'message' => ctrans('texts.new_signup_text', ['user' => $user_name, 'email' => $email, 'ip' => $ip]),
|
||||
'url' => config('ninja.web_url'),
|
||||
'button' => ctrans('texts.account_login'),
|
||||
'signature' => '',
|
||||
];
|
||||
|
||||
|
||||
return (new MailMessage)
|
||||
->line('The introduction to the notification.')
|
||||
->action('Notification Action', url('/'))
|
||||
->line('Thank you for using our application!');
|
||||
->subject(ctrans('texts.new_signup'))
|
||||
->markdown('email.admin.generic', $data);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,6 +85,9 @@ class NewAccountCreated extends Notification implements ShouldQueue
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
|
||||
$this->user->setCompany($this->company);
|
||||
|
||||
$user_name = $this->user->first_name . " " . $this->user->last_name;
|
||||
$email = $this->user->email;
|
||||
$ip = $this->user->ip;
|
||||
|
@ -39,6 +39,7 @@ use App\Listeners\Invoice\InvoiceEmailFailedActivity;
|
||||
use App\Listeners\Invoice\UpdateInvoiceActivity;
|
||||
use App\Listeners\Invoice\UpdateInvoiceInvitations;
|
||||
use App\Listeners\SendVerificationNotification;
|
||||
use App\Listeners\SetDBListener;
|
||||
use App\Listeners\User\UpdateUserLastLogin;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
|
||||
|
58
app/Providers/MultiDBProvider.php
Normal file
58
app/Providers/MultiDBProvider.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class MultiDBProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
if($this->app->runningInConsole()){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$this->app['events']->listen(\Illuminate\Queue\Events\JobProcessing::class, function($event) {
|
||||
|
||||
if (isset($event->job->payload()['db'])) {
|
||||
|
||||
//\Log::error("Provider Setting DB = ".$event->job->payload()['db']);
|
||||
|
||||
MultiDB::setDb($event->job->payload()['db']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Providers\UserSignedUp;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class SendConfirmationNotification
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserSignedUp $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UserSignedUp $event)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
|
||||
class UserSignedUp
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return \Illuminate\Broadcasting\Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
}
|
@ -23,13 +23,12 @@ class ClientContactRepository extends BaseRepository
|
||||
{
|
||||
public function save(array $data, Client $client) : void
|
||||
{
|
||||
|
||||
if(isset($data['contacts']))
|
||||
$contacts = collect($data['contacts']);
|
||||
else
|
||||
$contacts = collect();
|
||||
|
||||
collect($client->contacts->pluck('id'))->diff($contacts->pluck('id'))->each(function ($contact) {
|
||||
$client->contacts->pluck('id')->diff($contacts->pluck('id'))->each(function ($contact) {
|
||||
ClientContact::destroy($contact);
|
||||
});
|
||||
|
||||
@ -43,7 +42,7 @@ class ClientContactRepository extends BaseRepository
|
||||
|
||||
//loop and update/create contacts
|
||||
$contacts->each(function ($contact) use ($client) {
|
||||
//$update_contact = null;
|
||||
$update_contact = null;
|
||||
|
||||
if (isset($contact['id'])) {
|
||||
$update_contact = ClientContact::find($contact['id']);
|
||||
|
@ -51,7 +51,8 @@ class CreditRepository extends BaseRepository
|
||||
$credit->fill($data);
|
||||
$credit->save();
|
||||
|
||||
$credit->number = $credit->client->getNextCreditNumber($credit->client);
|
||||
if(!$credit->number)
|
||||
$credit->number = $credit->client->getNextCreditNumber($credit->client);
|
||||
|
||||
if (isset($data['invitations'])) {
|
||||
$invitations = collect($data['invitations']);
|
||||
|
@ -66,16 +66,20 @@ class InvoiceRepository extends BaseRepository {
|
||||
$invitations = collect($data['invitations']);
|
||||
|
||||
/* Get array of Keys which have been removed from the invitations array and soft delete each invitation */
|
||||
collect($invoice->invitations->pluck('key'))->diff($invitations->pluck('key'))->each(function ($invitation) {
|
||||
InvoiceInvitation::whereRaw("BINARY `key`= ?", [$invitation])->delete();
|
||||
$invoice->invitations->pluck('key')->diff($invitations->pluck('key'))->each(function ($invitation) {
|
||||
|
||||
$invite = $this->getInvitationByKey($invitation);
|
||||
|
||||
if($invite)
|
||||
$invite->forceDelete();
|
||||
|
||||
});
|
||||
|
||||
foreach ($data['invitations'] as $invitation) {
|
||||
$inv = false;
|
||||
|
||||
if (array_key_exists('key', $invitation)) {
|
||||
// $inv = InvoiceInvitation::whereKey($invitation['key'])->first();
|
||||
$inv = InvoiceInvitation::whereRaw("BINARY `key`= ?", [$invitation['key']])->first();
|
||||
$inv = $this->getInvitationByKey($invitation['key']);
|
||||
}
|
||||
|
||||
if (!$inv) {
|
||||
|
@ -102,7 +102,7 @@ class QuoteRepository extends BaseRepository
|
||||
return $quote->fresh();
|
||||
}
|
||||
|
||||
public function getInvitationByKey($key) :QuoteInvitation
|
||||
public function getInvitationByKey($key) :?QuoteInvitation
|
||||
{
|
||||
return QuoteInvitation::whereRaw("BINARY `key`= ?", [$key])->first();
|
||||
}
|
||||
|
42
app/Services/Notification/NotificationService.php
Normal file
42
app/Services/Notification/NotificationService.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Services\Notification;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Services\AbstractService;
|
||||
use Illuminate\Notifications\Notification as Notifiable;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
class NotificationService extends AbstractService
|
||||
{
|
||||
|
||||
public $company;
|
||||
|
||||
public $notification;
|
||||
|
||||
public function __construct(Company $company, Notifiable $notification)
|
||||
{
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->notification = $notification;
|
||||
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
|
||||
$this->company->owner()->notify($this->notification);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,7 @@ class InvoiceTransformer extends EntityTransformer
|
||||
use MakesHash;
|
||||
|
||||
protected $defaultIncludes = [
|
||||
// 'invoice_items',
|
||||
'invitations'
|
||||
];
|
||||
|
||||
protected $availableIncludes = [
|
||||
@ -88,6 +88,7 @@ class InvoiceTransformer extends EntityTransformer
|
||||
'amount' => (float) $invoice->amount,
|
||||
'balance' => (float) $invoice->balance,
|
||||
'client_id' => (string) $this->encodePrimaryKey($invoice->client_id),
|
||||
'vendor_id' => (string) $this->encodePrimaryKey($invoice->vendor_id),
|
||||
'status_id' => (string) ($invoice->status_id ?: 1),
|
||||
'design_id' => (string) ($invoice->design_id ?: 1),
|
||||
'updated_at' => (int)$invoice->updated_at,
|
||||
|
@ -179,6 +179,7 @@ return [
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
App\Providers\ComposerServiceProvider::class,
|
||||
Codedge\Updater\UpdaterServiceProvider::class,
|
||||
App\Providers\MultiDBProvider::class,
|
||||
|
||||
],
|
||||
|
||||
|
@ -17,6 +17,7 @@ return [
|
||||
'date_time_format' => 'Y-m-d H:i',
|
||||
'daily_email_limit' => 300,
|
||||
'error_email' => env('ERROR_EMAIL', ''),
|
||||
'company_id' => 0,
|
||||
|
||||
'environment' => env('NINJA_ENVIRONMENT', 'selfhost'), // 'hosted', 'development', 'selfhost', 'reseller'
|
||||
|
||||
|
@ -9,8 +9,8 @@ $factory->define(App\Models\Client::class, function (Faker $faker) {
|
||||
'name' => $faker->name(),
|
||||
'website' => $faker->url,
|
||||
'private_notes' => $faker->text(200),
|
||||
'balance' => $faker->numberBetween(0,1000),
|
||||
'paid_to_date' => $faker->numberBetween(0,10000),
|
||||
'balance' => 0,
|
||||
'paid_to_date' => 0,
|
||||
'vat_number' => $faker->text(25),
|
||||
'id_number' => $faker->text(20),
|
||||
'custom_value1' => $faker->text(20),
|
||||
|
@ -67,6 +67,7 @@ class CreateUsersTable extends Migration
|
||||
$table->string('decimal_separator');
|
||||
$table->string('code');
|
||||
$table->boolean('swap_currency_symbol')->default(false);
|
||||
$table->decimal('exchange_rate', 6, 6);
|
||||
|
||||
});
|
||||
|
||||
@ -261,6 +262,7 @@ class CreateUsersTable extends Migration
|
||||
$table->unsignedInteger('avatar_width')->nullable();
|
||||
$table->unsignedInteger('avatar_height')->nullable();
|
||||
$table->unsignedInteger('avatar_size')->nullable();
|
||||
|
||||
$table->datetime('last_login')->nullable();
|
||||
$table->mediumText('signature')->nullable();
|
||||
$table->string('password');
|
||||
|
@ -3113,6 +3113,19 @@ $LANG = array(
|
||||
'next_send_date' => 'Next send date',
|
||||
'cycles_remaining' => 'Cycles remaining',
|
||||
'i_understand_delete' => 'I understand, delete',
|
||||
|
||||
|
||||
|
||||
'download_files' => 'Download Files',
|
||||
'download_timeframe' => 'Use this link to download your files, the link will expire in 1 hour.',
|
||||
'new_signup' => 'New Signup',
|
||||
'new_signup_text' => 'A new account has been created by :user - :email - from IP address: :ip'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -1,20 +1,25 @@
|
||||
@component('mail::layout')
|
||||
@component('email.components.layout')
|
||||
|
||||
{{-- Header --}}
|
||||
@slot('header')
|
||||
@component('mail::header', ['url' => config('app.url')])
|
||||
Download
|
||||
@endcomponent
|
||||
@component('email.components.header', ['p' => ''])
|
||||
<img src="{{ $logo }}" alt="Company Logo" style="display: block">
|
||||
@endcomponent
|
||||
@endslot
|
||||
|
||||
{{-- Body --}}
|
||||
{{ $file_path }}
|
||||
@lang('texts.download_timeframe')
|
||||
|
||||
@component('email.components.button', ['url' => $url])
|
||||
@lang('texts.download')
|
||||
@endcomponent
|
||||
|
||||
@slot('signature')
|
||||
InvoiceNinja
|
||||
@endslot
|
||||
|
||||
{{-- Footer --}}
|
||||
@slot('footer')
|
||||
@component('mail::footer')
|
||||
© {{ date('Y') }} {{ config('ninja.app_name') }}.
|
||||
@endcomponent
|
||||
@component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja'])
|
||||
For any info, please visit InvoiceNinja.
|
||||
@endcomponent
|
||||
@endslot
|
||||
|
||||
@endcomponent
|
||||
@endcomponent
|
25
resources/views/email/admin/generic.blade.php
Normal file
25
resources/views/email/admin/generic.blade.php
Normal file
@ -0,0 +1,25 @@
|
||||
@component('email.components.layout')
|
||||
|
||||
@slot('header')
|
||||
@component('email.components.header', ['p' => ''])
|
||||
@lang($title)
|
||||
@endcomponent
|
||||
@endslot
|
||||
|
||||
@lang($message)
|
||||
|
||||
@component('email.components.button', ['url' => $url])
|
||||
@lang($button)
|
||||
@endcomponent
|
||||
|
||||
@slot('signature')
|
||||
{{ $signature }}
|
||||
@endslot
|
||||
|
||||
@slot('footer')
|
||||
@component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja'])
|
||||
For any info, please visit InvoiceNinja.
|
||||
@endcomponent
|
||||
@endslot
|
||||
|
||||
@endcomponent
|
@ -1,4 +1,8 @@
|
||||
@if()
|
||||
@component('email.components.layout-dark')
|
||||
@else
|
||||
@component('email.components.layout')
|
||||
@endif
|
||||
|
||||
@slot('header')
|
||||
@component('email.components.header', ['p' => 'Your upgrade has completed!'])
|
||||
|
150
tests/Integration/CompanyLedgerTest.php
Normal file
150
tests/Integration/CompanyLedgerTest.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Integration;
|
||||
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Events\Invoice\InvoiceWasCreated;
|
||||
use App\Events\Invoice\InvoiceWasUpdated;
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
use App\Factory\CompanyUserFactory;
|
||||
use App\Jobs\Invoice\MarkInvoicePaid;
|
||||
use App\Models\Account;
|
||||
use App\Models\Activity;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyLedger;
|
||||
use App\Models\CompanyToken;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\User;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Foundation\Testing\Concerns\InteractsWithDatabase;
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
/** @test*/
|
||||
|
||||
class CompanyLedgerTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
use MakesHash;
|
||||
|
||||
public $company;
|
||||
|
||||
public $client;
|
||||
|
||||
public $user;
|
||||
|
||||
public $token;
|
||||
|
||||
public $account;
|
||||
|
||||
public function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
/* Warm up the cache !*/
|
||||
$cached_tables = config('ninja.cached_tables');
|
||||
|
||||
foreach ($cached_tables as $name => $class) {
|
||||
|
||||
// check that the table exists in case the migration is pending
|
||||
if (! Schema::hasTable((new $class())->getTable())) {
|
||||
continue;
|
||||
}
|
||||
if ($name == 'payment_terms') {
|
||||
$orderBy = 'num_days';
|
||||
} elseif ($name == 'fonts') {
|
||||
$orderBy = 'sort_order';
|
||||
} elseif (in_array($name, ['currencies', 'industries', 'languages', 'countries', 'banks'])) {
|
||||
$orderBy = 'name';
|
||||
} else {
|
||||
$orderBy = 'id';
|
||||
}
|
||||
$tableData = $class::orderBy($orderBy)->get();
|
||||
if ($tableData->count()) {
|
||||
Cache::forever($name, $tableData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->account = factory(\App\Models\Account::class)->create();
|
||||
$this->company = factory(\App\Models\Company::class)->create([
|
||||
'account_id' => $this->account->id,
|
||||
]);
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
|
||||
$settings->company_logo = 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png';
|
||||
$settings->website = 'www.invoiceninja.com';
|
||||
$settings->address1 = 'Address 1';
|
||||
$settings->address2 = 'Address 2';
|
||||
$settings->city = 'City';
|
||||
$settings->state = 'State';
|
||||
$settings->postal_code = 'Postal Code';
|
||||
$settings->phone = '555-343-2323';
|
||||
$settings->email = 'user@example.com';
|
||||
$settings->country_id = '840';
|
||||
$settings->vat_number = 'vat number';
|
||||
$settings->id_number = 'id number';
|
||||
|
||||
$this->company->settings = $settings;
|
||||
$this->company->save();
|
||||
|
||||
$this->account->default_company_id = $this->company->id;
|
||||
$this->account->save();
|
||||
|
||||
$this->user = User::whereEmail('user@example.com')->first();
|
||||
|
||||
if(!$this->user){
|
||||
$this->user = factory(\App\Models\User::class)->create([
|
||||
'password' => Hash::make('ALongAndBriliantPassword'),
|
||||
'confirmation_code' => $this->createDbHash(config('database.default'))
|
||||
]);
|
||||
}
|
||||
|
||||
$cu = CompanyUserFactory::create($this->user->id, $this->company->id, $this->account->id);
|
||||
$cu->is_owner = true;
|
||||
$cu->is_admin = true;
|
||||
$cu->save();
|
||||
|
||||
$this->token = \Illuminate\Support\Str::random(64);
|
||||
|
||||
$company_token = CompanyToken::create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'account_id' => $this->account->id,
|
||||
'name' => 'test token',
|
||||
'token' => $this->token,
|
||||
]);
|
||||
|
||||
$this->client = factory(\App\Models\Client::class)->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
]);
|
||||
|
||||
|
||||
factory(\App\Models\ClientContact::class,1)->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $this->client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
'send_email' => true,
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testBaseLine()
|
||||
{
|
||||
|
||||
$this->assertEquals($this->company->invoices->count(), 0);
|
||||
$this->assertEquals($this->company->clients->count(), 1);
|
||||
$this->assertEquals($this->client->balance, 0);
|
||||
}
|
||||
|
||||
}
|
@ -10,7 +10,9 @@ use App\Jobs\Util\StartMigration;
|
||||
use App\Mail\MigrationFailed;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Document;
|
||||
use App\Models\Invoice;
|
||||
@ -329,10 +331,9 @@ class ImportTest extends TestCase
|
||||
$this->invoice->forceDelete();
|
||||
$this->quote->forceDelete();
|
||||
|
||||
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
|
||||
|
||||
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
|
||||
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
|
||||
|
||||
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
|
||||
|
||||
Import::dispatchNow($this->migration_array, $this->company, $this->user);
|
||||
|
||||
@ -407,7 +408,7 @@ class ImportTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/*foreach ($this->migration_array['credits'] as $key => $credit) {
|
||||
foreach ($this->migration_array['credits'] as $key => $credit) {
|
||||
|
||||
// The Import::processCredits() does insert the credit record with number: 0053,
|
||||
// .. however this part of the code doesn't see it at all.
|
||||
@ -418,7 +419,36 @@ class ImportTest extends TestCase
|
||||
if (!$record) {
|
||||
$differences['credits']['missing'][] = $credit['id'];
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
foreach ($this->migration_array['company_gateways'] as $key => $company_gateway) {
|
||||
|
||||
// The Import::processCredits() does insert the credit record with number: 0053,
|
||||
// .. however this part of the code doesn't see it at all.
|
||||
|
||||
$record = CompanyGateway::where('gateway_key' ,$company_gateway['gateway_key'])
|
||||
->first();
|
||||
|
||||
if (!$record) {
|
||||
$differences['company_gateways']['missing'][] = $company_gateway['id'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->migration_array['client_gateway_tokens'] as $key => $cgt) {
|
||||
|
||||
// The Import::processCredits() does insert the credit record with number: 0053,
|
||||
// .. however this part of the code doesn't see it at all.
|
||||
|
||||
$record = ClientGatewayToken::where('token' ,$cgt['token'])
|
||||
->first();
|
||||
|
||||
if (!$record) {
|
||||
$differences['client_gateway_tokens']['missing'][] = $cgt['id'];
|
||||
}
|
||||
}
|
||||
|
||||
//@TODO we can uncomment tests for documents when we have imported expenses.
|
||||
|
||||
// foreach ($this->migration_array['documents'] as $key => $document) {
|
||||
|
||||
@ -433,7 +463,8 @@ class ImportTest extends TestCase
|
||||
// }
|
||||
// }
|
||||
|
||||
\Log::error($differences);
|
||||
//\Log::error($differences);
|
||||
|
||||
$this->assertCount(0, $differences);
|
||||
}
|
||||
|
||||
@ -453,6 +484,18 @@ class ImportTest extends TestCase
|
||||
$this->assertGreaterThan($original, ClientContact::count());
|
||||
}
|
||||
|
||||
public function testClientGatewayTokensImport()
|
||||
{
|
||||
$this->invoice->forceDelete();
|
||||
$this->quote->forceDelete();
|
||||
|
||||
$original = ClientGatewayToken::count();
|
||||
|
||||
Import::dispatchNow($this->migration_array, $this->company, $this->user);
|
||||
|
||||
$this->assertGreaterThan($original, ClientGatewayToken::count());
|
||||
}
|
||||
|
||||
public function testDocumentsImport()
|
||||
{
|
||||
$this->invoice->forceDelete();
|
||||
@ -462,11 +505,11 @@ class ImportTest extends TestCase
|
||||
|
||||
Import::dispatchNow($this->migration_array, $this->company, $this->user);
|
||||
|
||||
$this->assertGreaterThan($original, Document::count());
|
||||
// $this->assertGreaterThan($original, Document::count());
|
||||
|
||||
$document = Document::first();
|
||||
|
||||
$this->assertNotNull(Invoice::find($document->documentable_id)->documents);
|
||||
$this->assertNotNull($document->documentable);
|
||||
// $this->assertNotNull(Invoice::find($document->documentable_id)->documents);
|
||||
// $this->assertNotNull($document->documentable);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
"invoice_text1": "Service Date"
|
||||
},
|
||||
"created_at": "2020-02-11",
|
||||
"updated_at": "2020-02-21",
|
||||
"updated_at": "2020-02-22",
|
||||
"settings": {
|
||||
"timezone_id": "15",
|
||||
"date_format_id": "1",
|
||||
@ -114,7 +114,7 @@
|
||||
"google_2fa_secret": null,
|
||||
"accepted_terms_version": "1.0.1",
|
||||
"password": "$2y$10$pDVj9LrItbYsvEenqOQe7.fSgdiIYzoLF86YnVtVVMLJzaBDI4iHC",
|
||||
"remember_token": "dhZnqoBgFsxcBn2tesbAfgQ9US4TkxCsHaF8HjqN0IQuoAZ7Ptfiw3jNZY4U",
|
||||
"remember_token": "nMizwyeTun32YxDB1NPpdiWzb0kMeAgDBlvJCFAgUwOA8yo8qwiEGpG1xwUS",
|
||||
"created_at": "2020-02-11",
|
||||
"updated_at": "2020-02-11",
|
||||
"deleted_at": null
|
||||
@ -17126,134 +17126,6 @@
|
||||
"deleted_at": null
|
||||
}
|
||||
],
|
||||
"documents": [
|
||||
{
|
||||
"id": 1,
|
||||
"user_id": 1,
|
||||
"company_id": 1,
|
||||
"invoice_id": 28,
|
||||
"expense_id": null,
|
||||
"path": "zuom5k2exmedyhztpgnkmwhwkzzxpbtk\/f8e8b45317131b60cd3177c13a5761ab278da43d.pdf",
|
||||
"preview": "",
|
||||
"name": "0019.pdf",
|
||||
"type": "pdf",
|
||||
"disk": "documents",
|
||||
"hash": "f8e8b45317131b60cd3177c13a5761ab278da43d",
|
||||
"size": 51397,
|
||||
"width": null,
|
||||
"height": null,
|
||||
"created_at": "2020-02-18",
|
||||
"updated_at": "2020-02-18"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"user_id": 1,
|
||||
"company_id": 1,
|
||||
"invoice_id": null,
|
||||
"expense_id": null,
|
||||
"path": "zuom5k2exmedyhztpgnkmwhwkzzxpbtk\/ddbba2265fe3e3d5ed1ce72bcc3e67e6dc6d9a2e.pdf",
|
||||
"preview": "",
|
||||
"name": "0001.pdf",
|
||||
"type": "pdf",
|
||||
"disk": "documents",
|
||||
"hash": "ddbba2265fe3e3d5ed1ce72bcc3e67e6dc6d9a2e",
|
||||
"size": 49393,
|
||||
"width": null,
|
||||
"height": null,
|
||||
"created_at": "2020-02-18",
|
||||
"updated_at": "2020-02-18"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"user_id": 1,
|
||||
"company_id": 1,
|
||||
"invoice_id": null,
|
||||
"expense_id": 60,
|
||||
"path": "zuom5k2exmedyhztpgnkmwhwkzzxpbtk\/858c794d4988ebcce27e01adb1cd8b2ba98d5668.pdf",
|
||||
"preview": "",
|
||||
"name": "0001.pdf",
|
||||
"type": "pdf",
|
||||
"disk": "documents",
|
||||
"hash": "858c794d4988ebcce27e01adb1cd8b2ba98d5668",
|
||||
"size": 51250,
|
||||
"width": null,
|
||||
"height": null,
|
||||
"created_at": "2020-02-18",
|
||||
"updated_at": "2020-02-18"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"user_id": 1,
|
||||
"company_id": 1,
|
||||
"invoice_id": 28,
|
||||
"expense_id": null,
|
||||
"path": "zuom5k2exmedyhztpgnkmwhwkzzxpbtk\/ed80d3d94084cefa54d41d3989fb99a757747276.pdf",
|
||||
"preview": "",
|
||||
"name": "Invoice_0028 (11).pdf",
|
||||
"type": "pdf",
|
||||
"disk": "documents",
|
||||
"hash": "ed80d3d94084cefa54d41d3989fb99a757747276",
|
||||
"size": 74468,
|
||||
"width": null,
|
||||
"height": null,
|
||||
"created_at": "2020-02-21",
|
||||
"updated_at": "2020-02-21"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"user_id": 1,
|
||||
"company_id": 1,
|
||||
"invoice_id": null,
|
||||
"expense_id": 51,
|
||||
"path": "zuom5k2exmedyhztpgnkmwhwkzzxpbtk\/c81cf7f4bae0c1e32b87835a39d056110a0d63ec.pdf",
|
||||
"preview": "",
|
||||
"name": "Invoice_0028 (8).pdf",
|
||||
"type": "pdf",
|
||||
"disk": "documents",
|
||||
"hash": "c81cf7f4bae0c1e32b87835a39d056110a0d63ec",
|
||||
"size": 28390,
|
||||
"width": null,
|
||||
"height": null,
|
||||
"created_at": "2020-02-21",
|
||||
"updated_at": "2020-02-21"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"user_id": 1,
|
||||
"company_id": 1,
|
||||
"invoice_id": null,
|
||||
"expense_id": 51,
|
||||
"path": "zuom5k2exmedyhztpgnkmwhwkzzxpbtk\/7ce4feb538a975856e29c47709698b5b792ec3b4.pdf",
|
||||
"preview": "",
|
||||
"name": "Invoice_0028 (6).pdf",
|
||||
"type": "pdf",
|
||||
"disk": "documents",
|
||||
"hash": "7ce4feb538a975856e29c47709698b5b792ec3b4",
|
||||
"size": 29613,
|
||||
"width": null,
|
||||
"height": null,
|
||||
"created_at": "2020-02-21",
|
||||
"updated_at": "2020-02-21"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"user_id": 1,
|
||||
"company_id": 1,
|
||||
"invoice_id": null,
|
||||
"expense_id": 51,
|
||||
"path": "zuom5k2exmedyhztpgnkmwhwkzzxpbtk\/1bbf0c9bd9024ceb83064daeeab9386d68097410.pdf",
|
||||
"preview": "",
|
||||
"name": "Invoice_0028 (5).pdf",
|
||||
"type": "pdf",
|
||||
"disk": "documents",
|
||||
"hash": "1bbf0c9bd9024ceb83064daeeab9386d68097410",
|
||||
"size": 28268,
|
||||
"width": null,
|
||||
"height": null,
|
||||
"created_at": "2020-02-21",
|
||||
"updated_at": "2020-02-21"
|
||||
}
|
||||
],
|
||||
"company_gateways": [
|
||||
{
|
||||
"id": 3,
|
||||
@ -17264,19 +17136,33 @@
|
||||
"show_billing_address": null,
|
||||
"show_shipping_address": 1,
|
||||
"update_details": null,
|
||||
"config": "{\"apiKey\":\"sk_test_faU9gVB7Hx19fCTo0e5ggZ0x\",\"publishableKey\":\"pk_test_iRPDj3jLiQs0Guae0lvSHaOD\",\"plaidClientId\":\"\",\"plaidSecret\":\"\",\"plaidPublicKey\":\"\",\"enableAlipay\":true,\"enableSofort\":true,\"enableSepa\":false,\"enableBitcoin\":false,\"enableApplePay\":true,\"enableAch\":true}",
|
||||
"fees_and_limits": {
|
||||
"min_limit": 234,
|
||||
"max_limit": 65317,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
"config": {
|
||||
"apiKey": "sk_test_faU9gVB7Hx19fCTo0e5ggZ0x",
|
||||
"publishableKey": "pk_test_iRPDj3jLiQs0Guae0lvSHaOD",
|
||||
"plaidClientId": "",
|
||||
"plaidSecret": "",
|
||||
"plaidPublicKey": "",
|
||||
"enableAlipay": true,
|
||||
"enableSofort": true,
|
||||
"enableSepa": false,
|
||||
"enableBitcoin": false,
|
||||
"enableApplePay": true,
|
||||
"enableAch": true
|
||||
},
|
||||
"fees_and_limits": [
|
||||
{
|
||||
"min_limit": 234,
|
||||
"max_limit": 65317,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
}
|
||||
],
|
||||
"custom_value1": "",
|
||||
"custom_value2": "",
|
||||
"custom_value3": "",
|
||||
@ -17291,7 +17177,19 @@
|
||||
"show_billing_address": null,
|
||||
"show_shipping_address": 1,
|
||||
"update_details": null,
|
||||
"config": "{\"apiKey\":\"sk_test_faU9gVB7Hx19fCTo0e5ggZ0x\",\"publishableKey\":\"pk_test_iRPDj3jLiQs0Guae0lvSHaOD\",\"plaidClientId\":\"\",\"plaidSecret\":\"\",\"plaidPublicKey\":\"\",\"enableAlipay\":true,\"enableSofort\":true,\"enableSepa\":false,\"enableBitcoin\":false,\"enableApplePay\":true,\"enableAch\":true}",
|
||||
"config": {
|
||||
"apiKey": "sk_test_faU9gVB7Hx19fCTo0e5ggZ0x",
|
||||
"publishableKey": "pk_test_iRPDj3jLiQs0Guae0lvSHaOD",
|
||||
"plaidClientId": "",
|
||||
"plaidSecret": "",
|
||||
"plaidPublicKey": "",
|
||||
"enableAlipay": true,
|
||||
"enableSofort": true,
|
||||
"enableSepa": false,
|
||||
"enableBitcoin": false,
|
||||
"enableApplePay": true,
|
||||
"enableAch": true
|
||||
},
|
||||
"fees_and_limits": {},
|
||||
"custom_value1": "",
|
||||
"custom_value2": "",
|
||||
@ -17307,19 +17205,33 @@
|
||||
"show_billing_address": null,
|
||||
"show_shipping_address": 1,
|
||||
"update_details": null,
|
||||
"config": "{\"apiKey\":\"sk_test_faU9gVB7Hx19fCTo0e5ggZ0x\",\"publishableKey\":\"pk_test_iRPDj3jLiQs0Guae0lvSHaOD\",\"plaidClientId\":\"\",\"plaidSecret\":\"\",\"plaidPublicKey\":\"\",\"enableAlipay\":true,\"enableSofort\":true,\"enableSepa\":false,\"enableBitcoin\":false,\"enableApplePay\":true,\"enableAch\":true}",
|
||||
"fees_and_limits": {
|
||||
"min_limit": 147,
|
||||
"max_limit": 53254,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
"config": {
|
||||
"apiKey": "sk_test_faU9gVB7Hx19fCTo0e5ggZ0x",
|
||||
"publishableKey": "pk_test_iRPDj3jLiQs0Guae0lvSHaOD",
|
||||
"plaidClientId": "",
|
||||
"plaidSecret": "",
|
||||
"plaidPublicKey": "",
|
||||
"enableAlipay": true,
|
||||
"enableSofort": true,
|
||||
"enableSepa": false,
|
||||
"enableBitcoin": false,
|
||||
"enableApplePay": true,
|
||||
"enableAch": true
|
||||
},
|
||||
"fees_and_limits": [
|
||||
{
|
||||
"min_limit": 147,
|
||||
"max_limit": 53254,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
}
|
||||
],
|
||||
"custom_value1": "",
|
||||
"custom_value2": "",
|
||||
"custom_value3": "",
|
||||
@ -17334,19 +17246,33 @@
|
||||
"show_billing_address": null,
|
||||
"show_shipping_address": 1,
|
||||
"update_details": null,
|
||||
"config": "{\"apiKey\":\"sk_test_faU9gVB7Hx19fCTo0e5ggZ0x\",\"publishableKey\":\"pk_test_iRPDj3jLiQs0Guae0lvSHaOD\",\"plaidClientId\":\"\",\"plaidSecret\":\"\",\"plaidPublicKey\":\"\",\"enableAlipay\":true,\"enableSofort\":true,\"enableSepa\":false,\"enableBitcoin\":false,\"enableApplePay\":true,\"enableAch\":true}",
|
||||
"fees_and_limits": {
|
||||
"min_limit": 155,
|
||||
"max_limit": 72857,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
"config": {
|
||||
"apiKey": "sk_test_faU9gVB7Hx19fCTo0e5ggZ0x",
|
||||
"publishableKey": "pk_test_iRPDj3jLiQs0Guae0lvSHaOD",
|
||||
"plaidClientId": "",
|
||||
"plaidSecret": "",
|
||||
"plaidPublicKey": "",
|
||||
"enableAlipay": true,
|
||||
"enableSofort": true,
|
||||
"enableSepa": false,
|
||||
"enableBitcoin": false,
|
||||
"enableApplePay": true,
|
||||
"enableAch": true
|
||||
},
|
||||
"fees_and_limits": [
|
||||
{
|
||||
"min_limit": 155,
|
||||
"max_limit": 72857,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
}
|
||||
],
|
||||
"custom_value1": "",
|
||||
"custom_value2": "",
|
||||
"custom_value3": "",
|
||||
@ -17361,19 +17287,33 @@
|
||||
"show_billing_address": null,
|
||||
"show_shipping_address": 1,
|
||||
"update_details": null,
|
||||
"config": "{\"apiKey\":\"sk_test_faU9gVB7Hx19fCTo0e5ggZ0x\",\"publishableKey\":\"pk_test_iRPDj3jLiQs0Guae0lvSHaOD\",\"plaidClientId\":\"\",\"plaidSecret\":\"\",\"plaidPublicKey\":\"\",\"enableAlipay\":true,\"enableSofort\":true,\"enableSepa\":false,\"enableBitcoin\":false,\"enableApplePay\":true,\"enableAch\":true}",
|
||||
"fees_and_limits": {
|
||||
"min_limit": 139,
|
||||
"max_limit": 71349,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
"config": {
|
||||
"apiKey": "sk_test_faU9gVB7Hx19fCTo0e5ggZ0x",
|
||||
"publishableKey": "pk_test_iRPDj3jLiQs0Guae0lvSHaOD",
|
||||
"plaidClientId": "",
|
||||
"plaidSecret": "",
|
||||
"plaidPublicKey": "",
|
||||
"enableAlipay": true,
|
||||
"enableSofort": true,
|
||||
"enableSepa": false,
|
||||
"enableBitcoin": false,
|
||||
"enableApplePay": true,
|
||||
"enableAch": true
|
||||
},
|
||||
"fees_and_limits": [
|
||||
{
|
||||
"min_limit": 139,
|
||||
"max_limit": 71349,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
}
|
||||
],
|
||||
"custom_value1": "",
|
||||
"custom_value2": "",
|
||||
"custom_value3": "",
|
||||
@ -17388,19 +17328,33 @@
|
||||
"show_billing_address": null,
|
||||
"show_shipping_address": 1,
|
||||
"update_details": null,
|
||||
"config": "{\"apiKey\":\"sk_test_faU9gVB7Hx19fCTo0e5ggZ0x\",\"publishableKey\":\"pk_test_iRPDj3jLiQs0Guae0lvSHaOD\",\"plaidClientId\":\"\",\"plaidSecret\":\"\",\"plaidPublicKey\":\"\",\"enableAlipay\":true,\"enableSofort\":true,\"enableSepa\":false,\"enableBitcoin\":false,\"enableApplePay\":true,\"enableAch\":true}",
|
||||
"fees_and_limits": {
|
||||
"min_limit": 151,
|
||||
"max_limit": 74365,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
"config": {
|
||||
"apiKey": "sk_test_faU9gVB7Hx19fCTo0e5ggZ0x",
|
||||
"publishableKey": "pk_test_iRPDj3jLiQs0Guae0lvSHaOD",
|
||||
"plaidClientId": "",
|
||||
"plaidSecret": "",
|
||||
"plaidPublicKey": "",
|
||||
"enableAlipay": true,
|
||||
"enableSofort": true,
|
||||
"enableSepa": false,
|
||||
"enableBitcoin": false,
|
||||
"enableApplePay": true,
|
||||
"enableAch": true
|
||||
},
|
||||
"fees_and_limits": [
|
||||
{
|
||||
"min_limit": 151,
|
||||
"max_limit": 74365,
|
||||
"fee_amount": "0.00",
|
||||
"fee_percent": "0.000",
|
||||
"tax_name1": null,
|
||||
"tax_rate1": null,
|
||||
"tax_name2": null,
|
||||
"tax_rate2": null,
|
||||
"tax_name3": "",
|
||||
"tax_rate3": 0
|
||||
}
|
||||
],
|
||||
"custom_value1": "",
|
||||
"custom_value2": "",
|
||||
"custom_value3": "",
|
||||
|
Loading…
Reference in New Issue
Block a user