mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-11 05:32:39 +01:00
commit
18f1e3c1b8
@ -1 +1 @@
|
||||
5.8.15
|
||||
5.8.16
|
@ -918,7 +918,18 @@ class CheckData extends Command
|
||||
$p->saveQuietly();
|
||||
|
||||
|
||||
$this->logMessage("Fixing currency for # {$p->id}");
|
||||
$this->logMessage("Fixing currency for # {$p->id}");
|
||||
|
||||
});
|
||||
|
||||
Company::whereNull("subdomain")
|
||||
->cursor()
|
||||
->when(Ninja::isHosted())
|
||||
->each(function ($c) {
|
||||
$c->subdomain = MultiDB::randomSubdomainGenerator();
|
||||
$c->save();
|
||||
|
||||
$this->logMessage("Fixing subdomain for # {$c->id}");
|
||||
|
||||
});
|
||||
|
||||
|
@ -832,6 +832,42 @@ class BaseExport
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function addClientFilter($query, $clients): Builder
|
||||
{
|
||||
$transformed_clients = $this->transformKeys(explode(',', $clients));
|
||||
|
||||
$query->whereIn('client_id', $transformed_clients);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function addVendorFilter($query, $vendors): Builder
|
||||
{
|
||||
$transformed_vendors = $this->transformKeys(explode(',', $vendors));
|
||||
|
||||
$query->whereIn('vendor_id', $transformed_vendors);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function addProjectFilter($query, $projects): Builder
|
||||
{
|
||||
$transformed_projects = $this->transformKeys(explode(',', $projects));
|
||||
|
||||
$query->whereIn('project_id', $transformed_projects);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function addCategoryFilter($query, $expense_categories): Builder
|
||||
{
|
||||
$transformed_expense_categories = $this->transformKeys(explode(',', $expense_categories));
|
||||
|
||||
$query->whereIn('category_id', $transformed_expense_categories);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function addInvoiceStatusFilter($query, $status): Builder
|
||||
{
|
||||
|
||||
|
@ -88,6 +88,22 @@ class ExpenseExport extends BaseExport
|
||||
|
||||
$query = $this->addDateRange($query);
|
||||
|
||||
if(isset($this->input['clients'])) {
|
||||
$query = $this->addClientFilter($query, $this->input['clients']);
|
||||
}
|
||||
|
||||
if(isset($this->input['vendors'])) {
|
||||
$query = $this->addVendorFilter($query, $this->input['vendors']);
|
||||
}
|
||||
|
||||
if(isset($this->input['projects'])) {
|
||||
$query = $this->addProjectFilter($query, $this->input['projects']);
|
||||
}
|
||||
|
||||
if(isset($this->input['categories'])) {
|
||||
$query = $this->addCategoryFilter($query, $this->input['categories']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
|
||||
}
|
||||
|
@ -11,13 +11,14 @@
|
||||
|
||||
namespace App\Http\Requests\Company;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Http\ValidationRules\Company\ValidCompanyQuantity;
|
||||
use App\Http\ValidationRules\Company\ValidSubdomain;
|
||||
use App\Http\ValidationRules\ValidSettingsRule;
|
||||
use App\Models\Company;
|
||||
use App\Utils\Ninja;
|
||||
use App\Models\Company;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Http\ValidationRules\ValidSettingsRule;
|
||||
use App\Http\ValidationRules\Company\ValidSubdomain;
|
||||
use App\Http\ValidationRules\Company\ValidCompanyQuantity;
|
||||
|
||||
class StoreCompanyRequest extends Request
|
||||
{
|
||||
@ -74,6 +75,10 @@ class StoreCompanyRequest extends Request
|
||||
$input['portal_domain'] = rtrim(strtolower($input['portal_domain']), "/");
|
||||
}
|
||||
|
||||
if(Ninja::isHosted() && !isset($input['subdomain'])) {
|
||||
$input['subdomain'] = MultiDB::randomSubdomainGenerator();
|
||||
}
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -557,9 +557,9 @@ class MultiDB
|
||||
$current_db = config('database.default');
|
||||
|
||||
do {
|
||||
$length = 8;
|
||||
$length = 10;
|
||||
$string = '';
|
||||
$vowels = ['a', 'e', 'i', 'o', 'u'];
|
||||
$vowels = ['a', 'e', 'i', 'o', 'u', 'y'];
|
||||
$consonants = [
|
||||
'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
|
||||
'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z',
|
||||
@ -568,7 +568,7 @@ class MultiDB
|
||||
$max = $length / 2;
|
||||
for ($i = 1; $i <= $max; $i++) {
|
||||
$string .= $consonants[rand(0, 19)];
|
||||
$string .= $vowels[rand(0, 4)];
|
||||
$string .= $vowels[rand(0, 5)];
|
||||
}
|
||||
} while (! self::checkDomainAvailable($string));
|
||||
|
||||
|
@ -54,6 +54,7 @@ class TasksTable extends Component
|
||||
|
||||
return render('components.livewire.tasks-table', [
|
||||
'tasks' => $query,
|
||||
'show_item_description' => auth()->guard('contact')->user()->company->invoice_task_item_description ?? false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ class TemplateEmail extends Mailable
|
||||
'whitelabel' => $this->client->user->account->isPaid() ? true : false,
|
||||
'logo' => $this->company->present()->logo($settings),
|
||||
'links' => $this->build_email->getAttachmentLinks(),
|
||||
'email_preferences' => URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key]),
|
||||
'email_preferences' => (Ninja::isHosted() && in_array($settings->email_sending_method, ['default', 'mailgun'])) ? URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key]) : false,
|
||||
]);
|
||||
|
||||
foreach ($this->build_email->getAttachments() as $file) {
|
||||
|
@ -316,8 +316,8 @@ class Task extends BaseModel
|
||||
$logged['end_date'] = ctrans('texts.running');
|
||||
}
|
||||
|
||||
$logged['description'] = $log[2];
|
||||
$logged['billable'] = $log[3];
|
||||
$logged['description'] = $log[2] ?? '';
|
||||
$logged['billable'] = $log[3] ?? false;
|
||||
$logged['duration_raw'] = $duration;
|
||||
$logged['duration'] = gmdate("H:i:s", $duration);
|
||||
|
||||
|
@ -70,7 +70,7 @@ class ClientRepository extends BaseRepository
|
||||
$client->settings = $client->saveSettings($data['settings'], $client);
|
||||
}
|
||||
|
||||
if (! $client->country_id) {
|
||||
if (! $client->country_id || $client->country_id == 0) {
|
||||
/** @var \App\Models\Company $company **/
|
||||
$company = Company::find($client->company_id);
|
||||
$client->country_id = $company->settings->country_id;
|
||||
|
@ -11,13 +11,14 @@
|
||||
|
||||
namespace App\Services\Email;
|
||||
|
||||
use App\Utils\Ninja;
|
||||
use App\Models\Document;
|
||||
use Illuminate\Mail\Attachment;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Mail\Mailables\Headers;
|
||||
use Illuminate\Mail\Attachment;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Headers;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
||||
class EmailMailable extends Mailable
|
||||
{
|
||||
@ -77,7 +78,7 @@ class EmailMailable extends Mailable
|
||||
'company' => $this->email_object->company,
|
||||
'greeting' => '',
|
||||
'links' => array_merge($this->email_object->links, $links->toArray()),
|
||||
'email_preferences' => $this->email_object->invitation
|
||||
'email_preferences' => (Ninja::isHosted() && in_array($this->email_object->settings->email_sending_method, ['default', 'mailgun']) && $this->email_object->invitation)
|
||||
? URL::signedRoute('client.email_preferences', ['entity' => $this->email_object->invitation->getEntityString(), 'invitation_key' => $this->email_object->invitation->key])
|
||||
: false,
|
||||
]
|
||||
|
@ -17,8 +17,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => env('APP_VERSION', '5.8.15'),
|
||||
'app_tag' => env('APP_TAG', '5.8.15'),
|
||||
'app_version' => env('APP_VERSION', '5.8.16'),
|
||||
'app_tag' => env('APP_TAG', '5.8.16'),
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', false),
|
||||
|
@ -1359,7 +1359,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "List of client tokens"
|
||||
summary: "List of client payment tokens"
|
||||
description: "Lists client_gateway_tokens, search and filters allow fine grained lists to be generated.\n\n Query parameters can be added to performed more fine grained filtering of the client_gateway_tokens, these are handled by the ClientGatewayTokenFilters class which defines the methods available"
|
||||
operationId: getClientGatewayTokens
|
||||
parameters:
|
||||
@ -1400,8 +1400,8 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Adds a client"
|
||||
description: "Adds an client to a company"
|
||||
summary: "Adds a client payment token"
|
||||
description: "Adds a client payment token to a company"
|
||||
operationId: storeClientGatewayToken
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/X-API-TOKEN"
|
||||
@ -1409,7 +1409,7 @@ paths:
|
||||
- $ref: "#/components/parameters/include"
|
||||
responses:
|
||||
200:
|
||||
description: "Returns the saved client object"
|
||||
description: "Returns the saved client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
@ -1433,8 +1433,8 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Shows a client"
|
||||
description: "Displays a client by id"
|
||||
summary: "Shows a client payment token"
|
||||
description: "Displays a client payment token by id"
|
||||
operationId: showClientGatewayToken
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/X-API-TOKEN"
|
||||
@ -1450,7 +1450,7 @@ paths:
|
||||
example: D2J234DFA
|
||||
responses:
|
||||
200:
|
||||
description: "Returns the cl.ient object"
|
||||
description: "Returns the client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
@ -1473,8 +1473,8 @@ paths:
|
||||
put:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Updates a client"
|
||||
description: "Handles the updating of a client by id"
|
||||
summary: "Updates a client payment token"
|
||||
description: "Handles the updating of a client payment token by id"
|
||||
operationId: updateClientGatewayToken
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/X-API-TOKEN"
|
||||
@ -1490,7 +1490,7 @@ paths:
|
||||
example: D2J234DFA
|
||||
responses:
|
||||
200:
|
||||
description: "Returns the client object"
|
||||
description: "Returns the client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
@ -1514,7 +1514,7 @@ paths:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Deletes a client"
|
||||
description: "Handles the deletion of a client by id"
|
||||
description: "Handles the deletion of a client payment token by id"
|
||||
operationId: deleteClientGatewayToken
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/X-API-TOKEN"
|
||||
@ -1550,7 +1550,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Shows a client for editting"
|
||||
summary: "Shows a client payment token for editting"
|
||||
description: "Displays a client by id"
|
||||
operationId: editClientGatewayToken
|
||||
parameters:
|
||||
@ -1567,7 +1567,7 @@ paths:
|
||||
example: D2J234DFA
|
||||
responses:
|
||||
200:
|
||||
description: "Returns the client object"
|
||||
description: "Returns the client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
@ -1591,7 +1591,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Gets a new blank client object"
|
||||
summary: "Gets a new blank client payment token object"
|
||||
description: "Returns a blank object with default values"
|
||||
operationId: getClientGatewayTokensCreate
|
||||
parameters:
|
||||
@ -1600,7 +1600,7 @@ paths:
|
||||
- $ref: "#/components/parameters/include"
|
||||
responses:
|
||||
200:
|
||||
description: "A blank client object"
|
||||
description: "A blank client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
|
@ -1335,7 +1335,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "List of client tokens"
|
||||
summary: "List of client payment tokens"
|
||||
description: "Lists client_gateway_tokens, search and filters allow fine grained lists to be generated.\n\n Query parameters can be added to performed more fine grained filtering of the client_gateway_tokens, these are handled by the ClientGatewayTokenFilters class which defines the methods available"
|
||||
operationId: getClientGatewayTokens
|
||||
parameters:
|
||||
@ -1376,8 +1376,8 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Adds a client"
|
||||
description: "Adds an client to a company"
|
||||
summary: "Adds a client payment token"
|
||||
description: "Adds a client payment token to a company"
|
||||
operationId: storeClientGatewayToken
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/X-API-TOKEN"
|
||||
@ -1385,7 +1385,7 @@ paths:
|
||||
- $ref: "#/components/parameters/include"
|
||||
responses:
|
||||
200:
|
||||
description: "Returns the saved client object"
|
||||
description: "Returns the saved client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
@ -1409,8 +1409,8 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Shows a client"
|
||||
description: "Displays a client by id"
|
||||
summary: "Shows a client payment token"
|
||||
description: "Displays a client payment token by id"
|
||||
operationId: showClientGatewayToken
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/X-API-TOKEN"
|
||||
@ -1426,7 +1426,7 @@ paths:
|
||||
example: D2J234DFA
|
||||
responses:
|
||||
200:
|
||||
description: "Returns the cl.ient object"
|
||||
description: "Returns the client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
@ -1449,8 +1449,8 @@ paths:
|
||||
put:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Updates a client"
|
||||
description: "Handles the updating of a client by id"
|
||||
summary: "Updates a client payment token"
|
||||
description: "Handles the updating of a client payment token by id"
|
||||
operationId: updateClientGatewayToken
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/X-API-TOKEN"
|
||||
@ -1466,7 +1466,7 @@ paths:
|
||||
example: D2J234DFA
|
||||
responses:
|
||||
200:
|
||||
description: "Returns the client object"
|
||||
description: "Returns the client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
@ -1490,7 +1490,7 @@ paths:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Deletes a client"
|
||||
description: "Handles the deletion of a client by id"
|
||||
description: "Handles the deletion of a client payment token by id"
|
||||
operationId: deleteClientGatewayToken
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/X-API-TOKEN"
|
||||
@ -1526,7 +1526,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Shows a client for editting"
|
||||
summary: "Shows a client payment token for editting"
|
||||
description: "Displays a client by id"
|
||||
operationId: editClientGatewayToken
|
||||
parameters:
|
||||
@ -1543,7 +1543,7 @@ paths:
|
||||
example: D2J234DFA
|
||||
responses:
|
||||
200:
|
||||
description: "Returns the client object"
|
||||
description: "Returns the client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
@ -1567,7 +1567,7 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- client_gateway_tokens
|
||||
summary: "Gets a new blank client object"
|
||||
summary: "Gets a new blank client payment token object"
|
||||
description: "Returns a blank object with default values"
|
||||
operationId: getClientGatewayTokensCreate
|
||||
parameters:
|
||||
@ -1576,7 +1576,7 @@ paths:
|
||||
- $ref: "#/components/parameters/include"
|
||||
responses:
|
||||
200:
|
||||
description: "A blank client object"
|
||||
description: "A blank client payment token object"
|
||||
headers:
|
||||
X-MINIMUM-CLIENT-VERSION:
|
||||
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
|
||||
|
@ -12,7 +12,7 @@
|
||||
</div>
|
||||
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
|
||||
<div class="align-middle inline-block min-w-full overflow-hidden rounded">
|
||||
<table class="min-w-full shadow rounded border border-gray-200 mt-4 credits-table">
|
||||
<table class="min-w-full shadow rounded border border-gray-200 mt-4 credits-table bg-white">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
|
||||
@ -38,7 +38,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($tasks as $task)
|
||||
@foreach($tasks as $task)
|
||||
<tr class="bg-white group hover:bg-gray-100">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
|
||||
{{ \Illuminate\Support\Str::limit($task->description, 80) }}
|
||||
@ -63,13 +63,56 @@
|
||||
{{ \Carbon\CarbonInterval::seconds($task->calcDuration())->cascade()->forHumans() }}
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
@if($show_item_description)
|
||||
<tr><td width="100%" colspan="4">
|
||||
<table class="min-w-full ml-5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500">
|
||||
<span>
|
||||
{{ ctrans('texts.date') }}
|
||||
</span>
|
||||
</th>
|
||||
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500">
|
||||
<span>
|
||||
{{ ctrans('texts.duration') }}
|
||||
</span>
|
||||
</th>
|
||||
<th colspan="4" class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500">
|
||||
<span>
|
||||
{{ ctrans('texts.description') }}
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($task->processLogsExpandedNotation() as $log)
|
||||
@if(strlen($log['description']) > 1)
|
||||
<tr class="bg-white group border-b border-gray-100">
|
||||
<td class="px-6 py-4 text-sm leading-5 text-gray-500 w-1/6">
|
||||
{{ $log['start_date']}}
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm leading-5 text-gray-500 w-1/6">
|
||||
{{ $log['duration']}}
|
||||
</td>
|
||||
<td colspan="4" class="px-6 py-4 text-sm leading-5 text-gray-500 w-4/6">
|
||||
{!! nl2br(e($log['description'])) !!}
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</td></tr>
|
||||
@endif
|
||||
@endforeach
|
||||
@if($tasks->count() == 0)
|
||||
<tr class="bg-white group hover:bg-gray-100">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500" colspan="100%">
|
||||
{{ ctrans('texts.no_results') }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user