1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-24 10:21:35 +02:00

Merge pull request #7052 from turbo124/v5-stable

v5.3.39
This commit is contained in:
David Bomba 2021-12-20 07:18:14 +11:00 committed by GitHub
commit b4374f0b99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 147 additions and 71 deletions

View File

@ -1 +1 @@
5.3.38
5.3.39

View File

@ -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;
") );
*/

View File

@ -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);

View File

@ -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');

View File

@ -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';

View File

@ -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;
// }
}
}

View File

@ -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();

View File

@ -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();

View File

@ -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', [

View File

@ -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;
@ -110,7 +111,7 @@ class Statement
}
if ($this->rollback) {
DB::rollBack();
\DB::connection(config('database.default'))->rollBack();
}
@ -129,7 +130,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);
@ -219,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();
}
/**
@ -235,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')
@ -243,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();
}
/**

View File

@ -26,6 +26,7 @@ class MarkSent extends AbstractService
public function __construct(Client $client, Invoice $invoice)
{
$this->client = $client;
$this->invoice = $invoice;
}

View File

@ -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, $balance){
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, $balance){
/* 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, $balance){
$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();
*/

View File

@ -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' => []];

View File

@ -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', ''),

View File

@ -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;