From 4829b762ddb73bba2efd0383c1ad135eb613edbe Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Dec 2021 20:30:53 +1100 Subject: [PATCH 1/8] Fixes for plain design --- .../Auth/ContactLoginController.php | 3 +++ resources/views/pdf-designs/plain.html | 20 +++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/Auth/ContactLoginController.php b/app/Http/Controllers/Auth/ContactLoginController.php index fad924f812..bd39ca0da8 100644 --- a/app/Http/Controllers/Auth/ContactLoginController.php +++ b/app/Http/Controllers/Auth/ContactLoginController.php @@ -100,6 +100,9 @@ class ContactLoginController extends Controller $contact = ClientContact::where(['email' => $request->input('email'), 'company_id' => $company->id])->first(); + if(!$contact) + return $this->sendFailedLoginResponse($request); + if(Hash::check($request->input('password'), $contact->password)) return $this->authenticated($request, $contact); diff --git a/resources/views/pdf-designs/plain.html b/resources/views/pdf-designs/plain.html index 205f401583..43f51401c9 100644 --- a/resources/views/pdf-designs/plain.html +++ b/resources/views/pdf-designs/plain.html @@ -16,7 +16,7 @@ } @page { - margin: $global_margin; + margin: 5px $global_margin $global_margin $global_margin; size: $page_size $page_layout; } @@ -42,7 +42,7 @@ } .header-wrapper #entity-details { - margin-top: 1.5rem; + margin-top: 0.5rem; text-align: left; width: 100%; } @@ -74,7 +74,7 @@ min-width: 100%; table-layout: fixed; overflow-wrap: break-word; - margin-top: 3rem; + margin-top: 1rem; /* margin-bottom: 200px; */ } @@ -89,7 +89,7 @@ } [data-ref="table"] > thead > tr > th { - padding: 1rem; + padding: 0.5rem; background-color: #e6e6e6; } @@ -99,7 +99,7 @@ [data-ref="table"] > tbody > tr > td { border-bottom: 1px solid #e6e6e6; - padding: 1rem; + padding: 0.75rem; } [data-ref="table"] > tbody > tr > td:last-child { @@ -111,7 +111,7 @@ } #table-totals { - margin-top: 1rem; + margin-top: 0rem; display: grid; grid-template-columns: 2fr 1fr; padding-top: .5rem; @@ -127,14 +127,14 @@ #table-totals>.totals-table-right-side>*> :nth-child(1) { text-align: "$dir_text_align"; - margin-top: .75rem; + margin-top: .25rem; padding-left: 7px; } #table-totals>.totals-table-right-side> * > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; - margin-top: calc(.75rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(.75rem * var(--tw-space-y-reverse)); + margin-top: calc(.25rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(.25rem * var(--tw-space-y-reverse)); } #table-totals>.totals-table-right-side>*> :nth-child(2) { @@ -197,7 +197,7 @@ .repeating-header-space, **/ .repeating-footer, .repeating-footer-space { - height: 160px; + height: 100px; } .repeating-header { position: fixed; From 0e01b376e451694d61555795dfc9823a4b721762 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Dec 2021 08:43:25 +1100 Subject: [PATCH 2/8] Fixes for localizing emails to company localization --- app/Mail/ExistingMigration.php | 3 +++ app/Mail/MigrationCompleted.php | 1 + app/Mail/MigrationFailed.php | 3 +++ app/Services/Invoice/MarkSent.php | 1 + 4 files changed, 8 insertions(+) diff --git a/app/Mail/ExistingMigration.php b/app/Mail/ExistingMigration.php index f6c80d14e0..449b8dbfdc 100644 --- a/app/Mail/ExistingMigration.php +++ b/app/Mail/ExistingMigration.php @@ -5,6 +5,7 @@ namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\App; class ExistingMigration extends Mailable { @@ -35,6 +36,8 @@ class ExistingMigration extends Mailable */ public function build() { + App::setLocale($this->company->getLocale()); + $this->settings = $this->company->settings; $this->logo = $this->company->present()->logo(); $this->company_name = $this->company->present()->name(); diff --git a/app/Mail/MigrationCompleted.php b/app/Mail/MigrationCompleted.php index 09fa1c8319..19374f757e 100644 --- a/app/Mail/MigrationCompleted.php +++ b/app/Mail/MigrationCompleted.php @@ -39,6 +39,7 @@ class MigrationCompleted extends Mailable App::forgetInstance('translator'); $t = app('translator'); $t->replace(Ninja::transformTranslations($this->company->settings)); + App::setLocale($this->company->getLocale()); $data['settings'] = $this->company->settings; $data['company'] = $this->company->fresh(); diff --git a/app/Mail/MigrationFailed.php b/app/Mail/MigrationFailed.php index 55d6f08389..409e843b20 100644 --- a/app/Mail/MigrationFailed.php +++ b/app/Mail/MigrationFailed.php @@ -4,6 +4,7 @@ namespace App\Mail; use App\Models\Company; use Illuminate\Mail\Mailable; +use Illuminate\Support\Facades\App; class MigrationFailed extends Mailable { @@ -35,6 +36,8 @@ class MigrationFailed extends Mailable */ public function build() { + App::setLocale($this->company->getLocale()); + return $this ->from(config('mail.from.address'), config('mail.from.name')) ->view('email.migration.failed', [ diff --git a/app/Services/Invoice/MarkSent.php b/app/Services/Invoice/MarkSent.php index a7d0488ce8..7527ab633b 100644 --- a/app/Services/Invoice/MarkSent.php +++ b/app/Services/Invoice/MarkSent.php @@ -26,6 +26,7 @@ class MarkSent extends AbstractService public function __construct(Client $client, Invoice $invoice) { $this->client = $client; + $this->invoice = $invoice; } From 8bc58a7e2ce5df682ce2ee1b9e20d4f8fb29df72 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Dec 2021 08:54:38 +1100 Subject: [PATCH 3/8] Force DB Connection for transactions --- app/Services/Client/Statement.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Services/Client/Statement.php b/app/Services/Client/Statement.php index 7c25252047..9a27def416 100644 --- a/app/Services/Client/Statement.php +++ b/app/Services/Client/Statement.php @@ -110,7 +110,7 @@ class Statement } if ($this->rollback) { - DB::rollBack(); + \DB::connection(config('database.default'))->rollBack(); } @@ -129,7 +129,8 @@ class Statement } if (\is_null($this->entity)) { - DB::beginTransaction(); + \DB::connection(config('database.default'))->beginTransaction(); + $this->rollback = true; $invoice = InvoiceFactory::create($this->client->company->id, $this->client->user->id); From 2cee0bc232a89c6a541737d8bae76b91c2605795 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Dec 2021 12:34:01 +1100 Subject: [PATCH 4/8] Fixes for ledger transactions --- app/Services/Ledger/LedgerService.php | 55 +++++++++++++++------------ 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/app/Services/Ledger/LedgerService.php b/app/Services/Ledger/LedgerService.php index f905eed815..63698f4a5e 100644 --- a/app/Services/Ledger/LedgerService.php +++ b/app/Services/Ledger/LedgerService.php @@ -28,25 +28,29 @@ class LedgerService { $balance = 0; - \DB::connection(config('database.default'))->beginTransaction(); + // \DB::connection(config('database.default'))->beginTransaction(); - $company_ledger = $this->ledger(); + \DB::connection(config('database.default'))->transaction(function () use($notes, $adjustment){ - if ($company_ledger) { - $balance = $company_ledger->balance; - } + $company_ledger = $this->ledger(); - $company_ledger = CompanyLedgerFactory::create($this->entity->company_id, $this->entity->user_id); - $company_ledger->client_id = $this->entity->client_id; - $company_ledger->adjustment = $adjustment; - $company_ledger->notes = $notes; - $company_ledger->balance = $balance + $adjustment; - $company_ledger->activity_id = Activity::UPDATE_INVOICE; - $company_ledger->save(); + if ($company_ledger) { + $balance = $company_ledger->balance; + } - $this->entity->company_ledger()->save($company_ledger); + $company_ledger = CompanyLedgerFactory::create($this->entity->company_id, $this->entity->user_id); + $company_ledger->client_id = $this->entity->client_id; + $company_ledger->adjustment = $adjustment; + $company_ledger->notes = $notes; + $company_ledger->balance = $balance + $adjustment; + $company_ledger->activity_id = Activity::UPDATE_INVOICE; + $company_ledger->save(); - \DB::connection(config('database.default'))->commit(); + $this->entity->company_ledger()->save($company_ledger); + + }, 5); + + // \DB::connection(config('database.default'))->commit(); return $this; } @@ -55,7 +59,9 @@ class LedgerService { $balance = 0; - \DB::connection(config('database.default'))->beginTransaction(); + // \DB::connection(config('database.default'))->beginTransaction(); + + \DB::connection(config('database.default'))->transaction(function () use($notes, $adjustment){ /* Get the last record for the client and set the current balance*/ $company_ledger = $this->ledger(); @@ -74,7 +80,9 @@ class LedgerService $this->entity->company_ledger()->save($company_ledger); - \DB::connection(config('database.default'))->commit(); + }, 5); + + // \DB::connection(config('database.default'))->commit(); return $this; } @@ -83,7 +91,9 @@ class LedgerService { $balance = 0; - \DB::connection(config('database.default'))->beginTransaction(); + // \DB::connection(config('database.default'))->beginTransaction(); + + \DB::connection(config('database.default'))->transaction(function () use($notes, $adjustment){ $company_ledger = $this->ledger(); @@ -101,7 +111,9 @@ class LedgerService $this->entity->company_ledger()->save($company_ledger); - \DB::connection(config('database.default'))->commit(); + }, 5); + + // \DB::connection(config('database.default'))->commit(); return $this; } @@ -123,10 +135,3 @@ class LedgerService } } -/* - DB::connection(config('database.default'))->beginTransaction(); - - \DB::connection(config('database.default'))->commit(); - - -*/ From 761d19c85767de8683d43b4df4aad29bdbc570f7 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Dec 2021 13:26:57 +1100 Subject: [PATCH 5/8] Fixes for ledger service --- app/Http/Requests/Invoice/StoreInvoiceRequest.php | 1 + app/Services/Ledger/LedgerService.php | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/Http/Requests/Invoice/StoreInvoiceRequest.php b/app/Http/Requests/Invoice/StoreInvoiceRequest.php index 06b0bf1b1c..b0fe7266fd 100644 --- a/app/Http/Requests/Invoice/StoreInvoiceRequest.php +++ b/app/Http/Requests/Invoice/StoreInvoiceRequest.php @@ -48,6 +48,7 @@ class StoreInvoiceRequest extends Request } $rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.auth()->user()->company()->id; + // $rules['client_id'] = ['required', Rule::exists('clients')->where('company_id', auth()->user()->company()->id)]; $rules['invitations.*.client_contact_id'] = 'distinct'; diff --git a/app/Services/Ledger/LedgerService.php b/app/Services/Ledger/LedgerService.php index 63698f4a5e..2724b43f86 100644 --- a/app/Services/Ledger/LedgerService.php +++ b/app/Services/Ledger/LedgerService.php @@ -30,7 +30,7 @@ class LedgerService // \DB::connection(config('database.default'))->beginTransaction(); - \DB::connection(config('database.default'))->transaction(function () use($notes, $adjustment){ + \DB::connection(config('database.default'))->transaction(function () use($notes, $adjustment, $balance){ $company_ledger = $this->ledger(); @@ -61,7 +61,7 @@ class LedgerService // \DB::connection(config('database.default'))->beginTransaction(); - \DB::connection(config('database.default'))->transaction(function () use($notes, $adjustment){ + \DB::connection(config('database.default'))->transaction(function () use($notes, $adjustment, $balance){ /* Get the last record for the client and set the current balance*/ $company_ledger = $this->ledger(); @@ -93,7 +93,7 @@ class LedgerService // \DB::connection(config('database.default'))->beginTransaction(); - \DB::connection(config('database.default'))->transaction(function () use($notes, $adjustment){ + \DB::connection(config('database.default'))->transaction(function () use($notes, $adjustment, $balance){ $company_ledger = $this->ledger(); From 375e6f1faf394cbbdabdaf0264e68f0c42122594 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Dec 2021 15:58:59 +1100 Subject: [PATCH 6/8] Fixes for statements --- app/Console/Commands/CheckData.php | 16 ++++++++++++++++ app/Services/Client/Statement.php | 15 +++++++++------ app/Services/PdfMaker/Design.php | 4 ++-- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/Console/Commands/CheckData.php b/app/Console/Commands/CheckData.php index 4189e0d8ca..68ca30c41d 100644 --- a/app/Console/Commands/CheckData.php +++ b/app/Console/Commands/CheckData.php @@ -949,3 +949,19 @@ ORDER BY clients.id; return $type.'s'; } } + + +/* query if we want to company company ledger to client balance + $results = \DB::select( \DB::raw(" + SELECT + clients.id as client_id, + clients.balance as client_balance + from clients, + (select max(company_ledgers.id) as cid, company_ledgers.client_id as client_id, company_ledgers.balance as balance + FROM company_ledgers) ledger + where clients.id=ledger.client_id + AND clients.balance != ledger.balance + GROUP BY clients.id + ORDER BY clients.id; + ") ); + */ \ No newline at end of file diff --git a/app/Services/Client/Statement.php b/app/Services/Client/Statement.php index 9a27def416..0ff972eeca 100644 --- a/app/Services/Client/Statement.php +++ b/app/Services/Client/Statement.php @@ -30,6 +30,7 @@ use App\Utils\PhantomJS\Phantom; use App\Utils\Traits\Pdf\PdfMaker as PdfMakerTrait; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; use Illuminate\Support\LazyCollection; @@ -220,15 +221,16 @@ class Statement * * @return Invoice[]|\Illuminate\Database\Eloquent\Collection */ - protected function getInvoices(): Builder + protected function getInvoices(): \Illuminate\Support\LazyCollection { return Invoice::withTrashed() ->where('is_deleted', false) ->where('company_id', $this->client->company_id) ->where('client_id', $this->client->id) ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL, Invoice::STATUS_PAID]) - ->whereBetween('date', [$this->options['start_date'], $this->options['end_date']]) - ->orderBy('number', 'ASC'); + ->whereBetween('date', [Carbon::parse($this->options['start_date']), Carbon::parse($this->options['end_date'])]) + ->orderBy('number', 'ASC') + ->cursor(); } /** @@ -236,7 +238,7 @@ class Statement * * @return Payment[]|\Illuminate\Database\Eloquent\Collection */ - protected function getPayments(): Builder + protected function getPayments(): \Illuminate\Support\LazyCollection { return Payment::withTrashed() ->with('client.country','invoices') @@ -244,8 +246,9 @@ class Statement ->where('company_id', $this->client->company_id) ->where('client_id', $this->client->id) ->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED]) - ->whereBetween('date', [$this->options['start_date'], $this->options['end_date']]) - ->orderBy('number', 'ASC'); + ->whereBetween('date', [Carbon::parse($this->options['start_date']), Carbon::parse($this->options['end_date'])]) + ->orderBy('number', 'ASC') + ->cursor(); } /** diff --git a/app/Services/PdfMaker/Design.php b/app/Services/PdfMaker/Design.php index fee18cd16c..14053737b8 100644 --- a/app/Services/PdfMaker/Design.php +++ b/app/Services/PdfMaker/Design.php @@ -359,7 +359,7 @@ class Design extends BaseDesign $tbody = []; - foreach ($this->invoices->cursor() as $invoice) { + foreach ($this->invoices as $invoice) { $element = ['element' => 'tr', 'elements' => []]; $element['elements'][] = ['element' => 'td', 'content' => $invoice->number]; @@ -407,7 +407,7 @@ class Design extends BaseDesign $tbody = []; - foreach ($this->payments->cursor() as $payment) { + foreach ($this->payments as $payment) { foreach ($payment->invoices as $invoice) { $element = ['element' => 'tr', 'elements' => []]; From d1dfbd95da23f5243fd461e51d0483a576053af0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Dec 2021 16:01:42 +1100 Subject: [PATCH 7/8] Code cleanup --- app/Jobs/Company/CompanyImport.php | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/app/Jobs/Company/CompanyImport.php b/app/Jobs/Company/CompanyImport.php index 5b476f6268..ddfe5c0950 100644 --- a/app/Jobs/Company/CompanyImport.php +++ b/app/Jobs/Company/CompanyImport.php @@ -307,17 +307,13 @@ class CompanyImport implements ShouldQueue nlog("Backup user count = ".count($backup_users)); if(count($backup_users) > 1){ - // $this->message = 'Only one user can be in the import for a Free Account'; - // $this->pre_flight_checks_pass = false; - //$this->force_user_coalesce = true; + } nlog("backup users email = " . $backup_users[0]->email); if(count($backup_users) == 1 && $this->company_owner->email != $backup_users[0]->email) { - // $this->message = 'Account emails do not match. Account owner email must match backup user email'; - // $this->pre_flight_checks_pass = false; - // $this->force_user_coalesce = true; + } $backup_users_emails = array_column($backup_users, 'email'); @@ -331,22 +327,11 @@ class CompanyImport implements ShouldQueue if($existing_user_count > 1){ if($this->account->plan == 'pro'){ - // $this->message = 'Pro plan is limited to one user, you have multiple users in the backup file'; - // $this->pre_flight_checks_pass = false; - // $this->force_user_coalesce = true; + } if($this->account->plan == 'enterprise'){ - // $total_import_users = count($backup_users_emails); - - // $account_plan_num_user = $this->account->num_users; - - // if($total_import_users > $account_plan_num_user){ - // $this->message = "Total user count ({$total_import_users}) greater than your plan allows ({$account_plan_num_user})"; - // $this->pre_flight_checks_pass = false; - // } - } } From 727420dd0e3add5d917be709e1522fc9aefc8356 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 20 Dec 2021 07:16:44 +1100 Subject: [PATCH 8/8] v5.3.39 --- VERSION.txt | 2 +- app/Http/Controllers/PreviewController.php | 64 ++++++++++++++++++++-- config/ninja.php | 4 +- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 7422b58bc0..5a3f9061cb 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.3.38 \ No newline at end of file +5.3.39 \ No newline at end of file diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index 9978033a44..008827dfe9 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -305,13 +305,69 @@ class PreviewController extends BaseController } - private function blankEntity() { App::forgetInstance('translator'); $t = app('translator'); $t->replace(Ninja::transformTranslations(auth()->user()->company()->settings)); + $invitation = InvoiceInvitation::where('company_id', auth()->user()->company()->id)->first(); + + /* If we don't have a valid invitation in the system - create a mock using transactions */ + if(!$invitation) + return $this->mockEntity(); + + $design_object = json_decode(json_encode(request()->input('design'))); + + if (! is_object($design_object)) { + return response()->json(['message' => 'Invalid custom design object'], 400); + } + + $html = new HtmlEngine($invitation); + + $design = new Design(Design::CUSTOM, ['custom_partials' => request()->design['design']]); + + $state = [ + 'template' => $design->elements([ + 'client' => $invitation->invoice->client, + 'entity' => $invitation->invoice, + 'pdf_variables' => (array) $invitation->invoice->company->settings->pdf_variables, + 'products' => request()->design['design']['product'], + ]), + 'variables' => $html->generateLabelsAndValues(), + 'process_markdown' => $invitation->invoice->client->company->markdown_enabled, + ]; + + $maker = new PdfMaker($state); + + $maker + ->design($design) + ->build(); + + if (request()->query('html') == 'true') { + return $maker->getCompiledHTML(); + } + + if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { + return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true)); + } + + if(config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja'){ + return (new NinjaPdf())->build($maker->getCompiledHTML(true)); + } + + $file_path = PreviewPdf::dispatchNow($maker->getCompiledHTML(true), auth()->user()->company()); + + $response = Response::make($file_path, 200); + $response->header('Content-Type', 'application/pdf'); + + return $response; + + } + + private function mockEntity() + { + DB::connection(auth()->user()->company()->db)->beginTransaction(); $client = Client::factory()->create([ @@ -345,8 +401,6 @@ class PreviewController extends BaseController $invoice->setRelation('company', auth()->user()->company()); $invoice->load('client.company'); - // nlog(print_r($invoice->toArray(),1)); - $design_object = json_decode(json_encode(request()->input('design'))); if (! is_object($design_object)) { @@ -374,6 +428,8 @@ class PreviewController extends BaseController ->design($design) ->build(); + DB::connection(auth()->user()->company()->db)->rollBack(); + if (request()->query('html') == 'true') { return $maker->getCompiledHTML(); } @@ -388,8 +444,6 @@ class PreviewController extends BaseController $file_path = PreviewPdf::dispatchNow($maker->getCompiledHTML(true), auth()->user()->company()); - DB::connection(auth()->user()->company()->db)->rollBack(); - $response = Response::make($file_path, 200); $response->header('Content-Type', 'application/pdf'); diff --git a/config/ninja.php b/config/ninja.php index 4557bc9b84..84287f0422 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.3.38', - 'app_tag' => '5.3.38', + 'app_version' => '5.3.39', + 'app_tag' => '5.3.39', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''),