diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000000..8aab1edc58db --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,4 @@ +# Invoice Ninja Code of Conduct + +The development team has invested a tremendous amount of time and energy into this project. While we appreciate that bugs can be frustrating we ask that our community refrain from insults and snide remarks. We're happy to provide support to both our hosted and selfhosted communities but ask that feedback is always polite. + diff --git a/VERSION.txt b/VERSION.txt index 30aaaeaa47a6..8f7bfe6fb860 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.1.59 \ No newline at end of file +5.1.60 \ No newline at end of file diff --git a/app/Console/Commands/MobileLocalization.php b/app/Console/Commands/MobileLocalization.php new file mode 100644 index 000000000000..7ae72f6cd1bc --- /dev/null +++ b/app/Console/Commands/MobileLocalization.php @@ -0,0 +1,120 @@ +option('type')); + + switch ($type) { + case 'laravel': + $this->laravelResources(); + break; + default: + $this->flutterResources(); + break; + } + } + + private function laravelResources() + { + $resources = $this->getResources(); + + foreach ($resources as $key => $val) { + $transKey = "texts.{$key}"; + if (trans($transKey) == $transKey) { + echo "'$key' => '$val',\n"; + } + } + } + + private function flutterResources() + { + $languages = cache('languages'); + $resources = $this->getResources(); + + foreach ($languages as $language) { + if ($language->locale == 'en') { + continue; + } + + echo "'{$language->locale}': {\n"; + + foreach ($resources as $key => $val) { + $text = trim(addslashes(trans("texts.{$key}", [], $language->locale))); + if (substr($text, 0, 6) == 'texts.') { + $text = $resources->$key; + } + + $text = str_replace(array('', ''), '', $text); + $text = str_replace(array('', ''), '', $text); + $text = str_replace(array('', ''), '', $text); + + echo "'$key': '$text',\n"; + } + + echo "},\n"; + } + } + + private function getResources() + { + $url = 'https://raw.githubusercontent.com/invoiceninja/flutter-client/develop/lib/utils/i18n.dart'; + $data = CurlUtils::get($url); + + $start = strpos($data, 'do not remove comment') + 25; + $end = strpos($data, '},', $start); + $data = substr($data, $start, $end - $start - 5); + + $data = str_replace("\n", "", $data); + $data = str_replace("\"", "\'", $data); + $data = str_replace("'", "\"", $data); + + return json_decode('{' . rtrim($data, ',') . '}'); + } + + protected function getOptions() + { + return [ + ['type', null, InputOption::VALUE_OPTIONAL, 'Type', null], + ]; + } + +} diff --git a/app/DataMapper/Analytics/Mail/EmailBounce.php b/app/DataMapper/Analytics/Mail/EmailBounce.php new file mode 100644 index 000000000000..5a8aaf10af3d --- /dev/null +++ b/app/DataMapper/Analytics/Mail/EmailBounce.php @@ -0,0 +1,77 @@ +string_metric5 = $string_metric5; + $this->string_metric6 = $string_metric6; + $this->string_metric7 = $string_metric7; + } +} diff --git a/app/DataMapper/Analytics/Mail/EmailSpam.php b/app/DataMapper/Analytics/Mail/EmailSpam.php new file mode 100644 index 000000000000..c420327ddc78 --- /dev/null +++ b/app/DataMapper/Analytics/Mail/EmailSpam.php @@ -0,0 +1,77 @@ +string_metric5 = $string_metric5; + $this->string_metric6 = $string_metric6; + $this->string_metric7 = $string_metric7; + } +} diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php index f6e97b7e01f6..4f854498784e 100644 --- a/app/Http/Controllers/ActivityController.php +++ b/app/Http/Controllers/ActivityController.php @@ -14,12 +14,14 @@ namespace App\Http\Controllers; use App\Http\Requests\Activity\DownloadHistoricalEntityRequest; use App\Models\Activity; use App\Transformers\ActivityTransformer; +use App\Utils\HostedPDF\NinjaPdf; +use App\Utils\PhantomJS\Phantom; use App\Utils\Traits\Pdf\PdfMaker; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Http\Response; -use stdClass; use Symfony\Component\HttpFoundation\StreamedResponse; +use stdClass; class ActivityController extends BaseController { @@ -139,7 +141,15 @@ class ActivityController extends BaseController return response()->json(['message'=> ctrans('texts.no_backup_exists'), 'errors' => new stdClass], 404); } - $pdf = $this->makePdf(null, null, $backup->html_backup); + if (config('ninja.phantomjs_pdf_generation')) { + $pdf = (new Phantom)->convertHtmlToPdf($backup->html_backup); + } + elseif(config('ninja.invoiceninja_hosted_pdf_generation')){ + $pdf = (new NinjaPdf())->build($backup->html_backup); + } + else { + $pdf = $this->makePdf(null, null, $backup->html_backup); + } if (isset($activity->invoice_id)) { $filename = $activity->invoice->numberFormatter().'.pdf'; diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index aec442c9c184..9b03936b5722 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -395,7 +395,8 @@ class BaseController extends Controller 'company' => function ($query) use ($created_at, $user) { $query->whereNotNull('created_at')->with('documents'); }, - 'company.clients' => function ($query) use ($user) { + 'company.clients' => function ($query) use ($created_at, $user) { + $query->where('clients.created_at', '>=', $created_at)->with('contacts.company', 'gateway_tokens', 'documents'); if(!$user->hasPermission('view_client')) $query->where('clients.user_id', $user->id)->orWhere('clients.assigned_user_id', $user->id); diff --git a/app/Http/Controllers/ClientPortal/InvoiceController.php b/app/Http/Controllers/ClientPortal/InvoiceController.php index 2300600714c0..9746863da046 100644 --- a/app/Http/Controllers/ClientPortal/InvoiceController.php +++ b/app/Http/Controllers/ClientPortal/InvoiceController.php @@ -50,6 +50,8 @@ class InvoiceController extends Controller { set_time_limit(0); + $invoice->service()->removeUnpaidGatewayFees()->save(); + $data = [ 'invoice' => $invoice, ]; diff --git a/app/Http/Controllers/ClientPortal/PaymentController.php b/app/Http/Controllers/ClientPortal/PaymentController.php index 6d17c3daff54..8531c36fefb1 100644 --- a/app/Http/Controllers/ClientPortal/PaymentController.php +++ b/app/Http/Controllers/ClientPortal/PaymentController.php @@ -97,6 +97,10 @@ class PaymentController extends Controller $payable_invoices = collect($request->payable_invoices); $invoices = Invoice::whereIn('id', $this->transformKeys($payable_invoices->pluck('invoice_id')->toArray()))->get(); + $invoices->each(function($invoice){ + $invoice->service()->removeUnpaidGatewayFees()->save(); + }); + /* pop non payable invoice from the $payable_invoices array */ $payable_invoices = $payable_invoices->filter(function ($payable_invoice) use ($invoices) { diff --git a/app/Http/Controllers/MigrationController.php b/app/Http/Controllers/MigrationController.php index afe76b9c1c80..c554a657e821 100644 --- a/app/Http/Controllers/MigrationController.php +++ b/app/Http/Controllers/MigrationController.php @@ -18,6 +18,7 @@ use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerObject; use App\Jobs\Util\StartMigration; use App\Mail\ExistingMigration; +use App\Mail\Migration\MaxCompanies; use App\Models\Company; use App\Models\CompanyToken; use Illuminate\Foundation\Bus\DispatchesJobs; @@ -231,19 +232,51 @@ class MigrationController extends BaseController nlog($request->all()); } + try { + return response()->json([ + '_id' => Str::uuid(), + 'method' => config('queue.default'), + 'started_at' => now(), + ], 200); + + } finally { + // Controller logic here + foreach ($companies as $company) { $is_valid = $request->file($company->company_index)->isValid(); if (!$is_valid) { - // We might want to send user something's wrong with migration or nope? continue; } $user = auth()->user(); + $company_count = $user->account->companies()->count(); + // Look for possible existing company (based on company keys). $existing_company = Company::whereRaw('BINARY `company_key` = ?', [$company->company_key])->first(); + if(!$existing_company && $company_count >=10) { + + $nmo = new NinjaMailerObject; + $nmo->mailable = new MaxCompanies($user->account->companies()->first()); + $nmo->company = $user->account->companies()->first(); + $nmo->settings = $user->account->companies()->first()->settings; + $nmo->to_user = $user; + NinjaMailerJob::dispatch($nmo); + return; + } + elseif($existing_company && $company_count > 10 ){ + + $nmo = new NinjaMailerObject; + $nmo->mailable = new MaxCompanies($user->account->companies()->first()); + $nmo->company = $user->account->companies()->first(); + $nmo->settings = $user->account->companies()->first()->settings; + $nmo->to_user = $user; + NinjaMailerJob::dispatch($nmo); + return; + } + $checks = [ 'existing_company' => $existing_company ? (bool)1 : false, 'force' => property_exists($company, 'force') ? (bool) $company->force : false, @@ -254,11 +287,11 @@ class MigrationController extends BaseController nlog('Migrating: Existing company without force. (CASE_01)'); $nmo = new NinjaMailerObject; - $nmo->mailable = new ExistingMigration(); - $nmo->company = $existing_company; - $nmo->settings = $existing_company->settings; + $nmo->mailable = new ExistingMigration($existing_company); + $nmo->company = $user->account->companies()->first(); + $nmo->settings = $user->account->companies()->first(); $nmo->to_user = $user; - + NinjaMailerJob::dispatch($nmo); return response()->json([ @@ -355,10 +388,7 @@ class MigrationController extends BaseController // } } - return response()->json([ - '_id' => Str::uuid(), - 'method' => config('queue.default'), - 'started_at' => now(), - ], 200); + } + } } diff --git a/app/Http/Controllers/PostMarkController.php b/app/Http/Controllers/PostMarkController.php index e4f6a855d0af..7a98a59f1adc 100644 --- a/app/Http/Controllers/PostMarkController.php +++ b/app/Http/Controllers/PostMarkController.php @@ -11,6 +11,8 @@ namespace App\Http\Controllers; +use App\DataMapper\Analytics\EmailBounce; +use App\DataMapper\Analytics\EmailSpam; use App\Jobs\Util\SystemLogger; use App\Libraries\MultiDB; use App\Models\CreditInvitation; @@ -19,6 +21,7 @@ use App\Models\QuoteInvitation; use App\Models\RecurringInvoiceInvitation; use App\Models\SystemLog; use Illuminate\Http\Request; +use Turbo124\Beacon\Facades\LightLogs; /** * Class PostMarkController. @@ -71,8 +74,7 @@ class PostMarkController extends BaseController if($request->header('X-API-SECURITY') && $request->header('X-API-SECURITY') == config('postmark.secret')) { - - nlog($request->all()); + // nlog($request->all()); MultiDB::findAndSetDbByCompanyKey($request->input('Tag')); @@ -157,6 +159,14 @@ class PostMarkController extends BaseController $this->invitation->email_status = 'bounced'; $this->invitation->save(); + $bounce = new EmailBounce( + $request->input('Tag'), + $request->input('From'), + $request->input('MessageID') + ); + + LightLogs::create($bounce)->batch(); + SystemLogger::dispatch($request->all(), SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client); } @@ -191,6 +201,14 @@ class PostMarkController extends BaseController $this->invitation->email_status = 'spam'; $this->invitation->save(); + $spam = new EmailSpam( + $request->input('Tag'), + $request->input('From'), + $request->input('MessageID') + ); + + LightLogs::create($bounce)->batch(); + SystemLogger::dispatch($request->all(), SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client); } diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index d39e2a554680..9fc0a4ec0511 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -31,6 +31,7 @@ use App\Factory\VendorFactory; use App\Http\Requests\Company\UpdateCompanyRequest; use App\Http\ValidationRules\ValidCompanyGatewayFeesAndLimitsRule; use App\Http\ValidationRules\ValidUserForCompany; +use App\Jobs\Company\CreateCompanyTaskStatuses; use App\Jobs\Company\CreateCompanyToken; use App\Jobs\Ninja\CheckCompanyData; use App\Jobs\Ninja\CompanySizeCheck; @@ -82,10 +83,10 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Http\UploadedFile; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; use Turbo124\Beacon\Facades\LightLogs; -use Illuminate\Support\Facades\Mail; class Import implements ShouldQueue { @@ -230,6 +231,9 @@ class Import implements ShouldQueue $this->company->save(); } + // CreateCompanyPaymentTerms::dispatchNow($sp035a66, $spaa9f78); + CreateCompanyTaskStatuses::dispatchNow($this->company, $this->user); + info('Completedπππππ at '.now()); unlink($this->file_path); diff --git a/app/Jobs/Util/StartMigration.php b/app/Jobs/Util/StartMigration.php index 8b5f09fcfbc6..e26c7462ed74 100644 --- a/app/Jobs/Util/StartMigration.php +++ b/app/Jobs/Util/StartMigration.php @@ -109,7 +109,7 @@ class StartMigration implements ShouldQueue throw new NonExistingMigrationFile('Migration file does not exist, or it is corrupted.'); } - Import::dispatchNow($file, $this->company, $this->user)->onQueue('migration'); + Import::dispatchNow($file, $this->company, $this->user); Storage::deleteDirectory(public_path("storage/migrations/{$filename}")); diff --git a/app/Mail/Admin/EntityCreatedObject.php b/app/Mail/Admin/EntityCreatedObject.php index f33c7cd540ce..ba773ac3c5f9 100644 --- a/app/Mail/Admin/EntityCreatedObject.php +++ b/app/Mail/Admin/EntityCreatedObject.php @@ -62,20 +62,20 @@ class EntityCreatedObject switch ($this->entity_type) { case 'invoice': $this->template_subject = "texts.notification_invoice_created_subject"; - $this->template_body = "texts.notification_invoice_sent"; + $this->template_body = "texts.notification_invoice_created_body"; break; case 'quote': $this->template_subject = "texts.notification_quote_created_subject"; - $this->template_body = "texts.notification_quote_sent"; + $this->template_body = "texts.notification_quote_created_body"; break; case 'credit': $this->template_subject = "texts.notification_credit_created_subject"; - $this->template_body = "texts.notification_credit_sent"; + $this->template_body = "texts.notification_credit_created_body"; break; default: $this->template_subject = "texts.notification_invoice_created_subject"; - $this->template_body = "texts.notification_invoice_sent"; + $this->template_body = "texts.notification_invoice_created_body"; break; } } diff --git a/app/Mail/ExistingMigration.php b/app/Mail/ExistingMigration.php index 60f7abdf95d4..366a4c146af5 100644 --- a/app/Mail/ExistingMigration.php +++ b/app/Mail/ExistingMigration.php @@ -10,14 +10,22 @@ class ExistingMigration extends Mailable { // use Queueable, SerializesModels; + public $company; + + public $settings; + + public $logo; + + public $company_name; + /** * Create a new message instance. * * @return void */ - public function __construct() + public function __construct($company) { - // + $this->company = $company; } /** @@ -27,8 +35,11 @@ class ExistingMigration extends Mailable */ public function build() { - return $this->from(config('mail.from.address'), config('mail.from.name')) + $this->settings = $this->company->settings; + $this->logo = $this->company->present()->logo(); + $this->company_name = $this->company->present()->name(); + return $this->from(config('mail.from.address'), config('mail.from.name')) ->view('email.migration.existing'); } } diff --git a/app/Mail/Migration/MaxCompanies.php b/app/Mail/Migration/MaxCompanies.php new file mode 100644 index 000000000000..af65f766b95e --- /dev/null +++ b/app/Mail/Migration/MaxCompanies.php @@ -0,0 +1,51 @@ +company = $company; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + $this->settings = $this->company->settings; + $this->logo = $this->company->present()->logo(); + $this->title = ctrans('texts.max_companies'); + $this->message = ctrans('texts.max_companies_desc'); + $this->whitelabel = $this->company->account->isPaid(); + + return $this->from(config('mail.from.address'), config('mail.from.name')) + ->view('email.migration.max_companies'); + } +} diff --git a/app/Models/Client.php b/app/Models/Client.php index dbb2b12ba8af..1e1ef2232d42 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -79,8 +79,9 @@ class Client extends BaseModel implements HasLocalePreference protected $with = [ 'gateway_tokens', - 'documents' - //'currency', + 'documents', + 'contacts.company', + // 'currency', // 'primary_contact', // 'country', // 'contacts', diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index 6495fae14aaf..9ca4e81b42ea 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -65,6 +65,7 @@ class CompanyGateway extends BaseModel '3758e7f7c6f4cecf0f4f348b9a00f456' => 304, '3b6621f970ab18887c4f6dca78d3f8bb' => 305, '54faab2ab6e3223dbe848b1686490baa' => 306, + 'd14dd26a47cecc30fdd65700bfb67b34' => 301, ]; protected $touches = []; @@ -225,7 +226,7 @@ class CompanyGateway extends BaseModel { $config = $this->getConfig(); - if ($this->gateway->provider == 'Stripe' && strpos($config->publishableKey, 'test')) { + if ($this->gateway->provider == 'Stripe' && property_exists($config, 'publishableKey') && strpos($config->publishableKey, 'test')) { return true; } diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index 5d470680aab5..c182f4e1d7ad 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -85,6 +85,7 @@ class Gateway extends StaticModel return [GatewayType::PAYPAL => ['refund' => true, 'token_billing' => false]]; //Paypal break; case 20: + case 56: return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true], GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable']], GatewayType::ALIPAY => ['refund' => false, 'token_billing' => false], diff --git a/app/Models/Presenters/ClientPresenter.php b/app/Models/Presenters/ClientPresenter.php index 4e4aacf67626..dfdc11c26423 100644 --- a/app/Models/Presenters/ClientPresenter.php +++ b/app/Models/Presenters/ClientPresenter.php @@ -27,7 +27,8 @@ class ClientPresenter extends EntityPresenter return $this->entity->name; } - $contact = $this->entity->primary_contact->first(); + //$contact = $this->entity->primary_contact->first(); + $contact = $this->entity->contacts->first(); $contact_name = 'No Contact Set'; diff --git a/app/Repositories/Migration/InvoiceMigrationRepository.php b/app/Repositories/Migration/InvoiceMigrationRepository.php index 14d56965d29f..ee142650f2ba 100644 --- a/app/Repositories/Migration/InvoiceMigrationRepository.php +++ b/app/Repositories/Migration/InvoiceMigrationRepository.php @@ -107,35 +107,7 @@ class InvoiceMigrationRepository extends BaseRepository InvoiceInvitation::reguard(); RecurringInvoiceInvitation::reguard(); - /* - if (isset($data['invitations'])) { - $invitations = collect($data['invitations']); - $model->invitations->pluck('key')->diff($invitations->pluck('key'))->each(function ($invitation) use ($resource) { - $this->getInvitation($invitation, $resource)->delete(); - }); - - foreach ($data['invitations'] as $invitation) { - - //if no invitations are present - create one. - if (! $this->getInvitation($invitation, $resource)) { - if (isset($invitation['id'])) { - unset($invitation['id']); - } - - //make sure we are creating an invite for a contact who belongs to the client only! - $contact = ClientContact::find($invitation['client_contact_id']); - - if ($contact && $model->client_id == $contact->client_id) { - $new_invitation = $invitation_factory_class::create($model->company_id, $model->user_id); - $new_invitation->{$lcfirst_resource_id} = $model->id; - $new_invitation->client_contact_id = $contact->id; - $new_invitation->save(); - } - } - } - } - */ $model->load('invitations'); /* If no invitations have been created, this is our fail safe to maintain state*/ @@ -152,8 +124,6 @@ class InvoiceMigrationRepository extends BaseRepository if ($class->name == Invoice::class || $class->name == RecurringInvoice::class) { if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) { - // $model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount'])); - // $model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save(); } if (! $model->design_id) { @@ -162,7 +132,7 @@ class InvoiceMigrationRepository extends BaseRepository if ($model->company->update_products) { - UpdateOrCreateProduct::dispatchNow($model->line_items, $model, $model->company); + //UpdateOrCreateProduct::dispatchNow($model->line_items, $model, $model->company); } } diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index 4ae0787809df..3531e0d266f5 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -110,6 +110,7 @@ class InvoiceService public function addGatewayFee(CompanyGateway $company_gateway, $gateway_type_id, float $amount) { + $this->invoice = (new AddGatewayFee($company_gateway, $gateway_type_id, $this->invoice, $amount))->run(); return $this; diff --git a/config/ninja.php b/config/ninja.php index 34e346da0a9d..4481e81ae629 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -14,8 +14,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => '5.1.59', - 'app_tag' => '5.1.59-release', + 'app_version' => '5.1.60', + 'app_tag' => '5.1.60-release', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false), diff --git a/database/migrations/2021_04_12_095424_stripe_connect_gateway.php b/database/migrations/2021_04_12_095424_stripe_connect_gateway.php index 0f2a72242151..2d9fe819f7d3 100644 --- a/database/migrations/2021_04_12_095424_stripe_connect_gateway.php +++ b/database/migrations/2021_04_12_095424_stripe_connect_gateway.php @@ -30,8 +30,8 @@ class StripeConnectGateway extends Migration Gateway::create($gateway); if (Ninja::isNinja()) { - Gateway::where('id', 20)->update(['visible' => 0]); - Gateway::where('id', 56)->update(['visible' => 1]); + Gateway::whereIn('id', [20])->update(['visible' => 0]); + Gateway::whereIn('id', [56])->update(['visible' => 1]); } } diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 2619e20330fc..4adf5fa1d78d 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -4229,12 +4229,17 @@ $LANG = array( 'amount_greater_than_balance_v5' => 'The amount is greater than the invoice balance. You cannot overpay an invoice.', 'click_to_continue' => 'Click to continue', - 'notification_invoice_created_subject' => 'Invoice :invoice was created to :client', + 'notification_invoice_created_body' => 'The following invoice :invoice was created for client :client for :amount.', 'notification_invoice_created_subject' => 'Invoice :invoice was created for :client', - 'notification_quote_created_subject' => 'Quote :invoice was created to :client', + 'notification_quote_created_body' => 'The following quote :invoice was created for client :client for :amount.', 'notification_quote_created_subject' => 'Quote :invoice was created for :client', - 'notification_credit_created_subject' => 'Credit :invoice was created to :client', + 'notification_credit_created_body' => 'The following credit :invoice was created for client :client for :amount.', 'notification_credit_created_subject' => 'Credit :invoice was created for :client', + 'max_companies' => 'Maximum companies migrated', + 'max_companies_desc' => 'You have reached your maximum number of companies. Delete existing companies to migrate new ones.', + 'migration_already_completed' => 'Company already migrated', + 'migration_already_completed_desc' => 'Looks like you already migrated :company_name to the V5 version of the Invoice Ninja. In case you want to start over, you can force migrate to wipe existing data.', + ); return $LANG; diff --git a/resources/views/email/migration/existing.blade.php b/resources/views/email/migration/existing.blade.php index 1491488b17d6..3a4c1dbd6ca1 100644 --- a/resources/views/email/migration/existing.blade.php +++ b/resources/views/email/migration/existing.blade.php @@ -1,31 +1,18 @@ @component('email.template.master', ['design' => 'light', 'settings' => $settings]) -@slot('header') - @component('email.components.header') - Migration already completed - @endcomponent -@endslot + @slot('header') + @include('email.components.header', ['logo' => $logo]) + @endslot -@slot('greeting') - Hello, -@endslot +
{{ctrans('texts.migration_already_completed_desc', ['company_name' => $company_name])}}
+ @if(isset($whitelabel) && !$whitelabel) + @slot('footer') + @component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja']) + For any info, please visit InvoiceNinja. + @endcomponent + @endslot + @endif @endcomponent diff --git a/resources/views/email/migration/max_companies.blade.php b/resources/views/email/migration/max_companies.blade.php new file mode 100644 index 000000000000..4d76f055b962 --- /dev/null +++ b/resources/views/email/migration/max_companies.blade.php @@ -0,0 +1,18 @@ +@component('email.template.master', ['design' => 'light', 'settings' => $settings]) + + @slot('header') + @include('email.components.header', ['logo' => $logo]) + @endslot + +{{ctrans('texts.max_companies_desc')}}
+ + @if(isset($whitelabel) && !$whitelabel) + @slot('footer') + @component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja']) + For any info, please visit InvoiceNinja. + @endcomponent + @endslot + @endif +@endcomponent