Merge pull request #9291 from turbo124/v5-develop

Fixes for openapi spec
This commit is contained in:
David Bomba 2024-02-13 14:38:29 +11:00 committed by GitHub
commit a72058525e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 7568 additions and 7495 deletions

View File

@ -79,6 +79,7 @@ class OpenApiYaml extends Command
Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components.yaml')); Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components.yaml'));
Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components/examples.yaml')); Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components/examples.yaml'));
Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components/responses.yaml')); Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components/responses.yaml'));
$directory = new DirectoryIterator($path . '/components/responses/'); $directory = new DirectoryIterator($path . '/components/responses/');

View File

@ -225,22 +225,6 @@ class ClientExport extends BaseExport
$entity['client.assigned_user'] = $client->assigned_user ? $client->user->present()->name() : ''; $entity['client.assigned_user'] = $client->assigned_user ? $client->user->present()->name() : '';
} }
// if (in_array('client.country_id', $this->input['report_keys'])) {
// $entity['client.country_id'] = $client->country ? ctrans("texts.country_{$client->country->name}") : '';
// }
// if (in_array('client.shipping_country_id', $this->input['report_keys'])) {
// $entity['client.shipping_country_id'] = $client->shipping_country ? ctrans("texts.country_{$client->shipping_country->name}") : '';
// }
// if (in_array('client.currency_id', $this->input['report_keys'])) {
// $entity['client.currency_id'] = $client->currency() ? $client->currency()->code : $client->company->currency()->code;
// }
// if (in_array('client.industry_id', $this->input['report_keys'])) {
// $entity['industry_id'] = $client->industry ? ctrans("texts.industry_{$client->industry->name}") : '';
// }
if (in_array('client.classification', $this->input['report_keys']) && isset($client->classification)) { if (in_array('client.classification', $this->input['report_keys']) && isset($client->classification)) {
$entity['client.classification'] = ctrans("texts.{$client->classification}") ?? ''; $entity['client.classification'] = ctrans("texts.{$client->classification}") ?? '';
} }

View File

@ -165,6 +165,11 @@ class ClientFilters extends QueryFilters
$dir = ($sort_col[1] == 'asc') ? 'asc' : 'desc'; $dir = ($sort_col[1] == 'asc') ? 'asc' : 'desc';
if($sort_col[0] == 'number')
{
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
return $this->builder->orderBy($sort_col[0], $dir); return $this->builder->orderBy($sort_col[0], $dir);
} }

View File

@ -146,6 +146,11 @@ class CreditFilters extends QueryFilters
->whereColumn('clients.id', 'credits.client_id'), $dir); ->whereColumn('clients.id', 'credits.client_id'), $dir);
} }
if($sort_col[0] == 'number') {
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
return $this->builder->orderBy($sort_col[0], $dir); return $this->builder->orderBy($sort_col[0], $dir);
} }

View File

@ -172,6 +172,8 @@ class ExpenseFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
$dir = ($sort_col[1] == 'asc') ? 'asc' : 'desc';
if ($sort_col[0] == 'client_id' && in_array($sort_col[1], ['asc', 'desc'])) { if ($sort_col[0] == 'client_id' && in_array($sort_col[1], ['asc', 'desc'])) {
return $this->builder return $this->builder
->orderByRaw('ISNULL(client_id), client_id '. $sort_col[1]) ->orderByRaw('ISNULL(client_id), client_id '. $sort_col[1])
@ -194,6 +196,10 @@ class ExpenseFilters extends QueryFilters
->whereColumn('expense_categories.id', 'expenses.category_id'), $sort_col[1]); ->whereColumn('expense_categories.id', 'expenses.category_id'), $sort_col[1]);
} }
if($sort_col[0] == 'number') {
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) { if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) {
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -318,11 +318,16 @@ class InvoiceFilters extends QueryFilters
if ($sort_col[0] == 'client_id') { if ($sort_col[0] == 'client_id') {
return $this->builder->orderBy(\App\Models\Client::select('name') return $this->builder->orderBy(\App\Models\Client::select ('name')
->whereColumn('clients.id', 'invoices.client_id'), $dir); ->whereColumn('clients.id', 'invoices.client_id'), $dir);
} }
if($sort_col[0] == 'number')
{
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
return $this->builder->orderBy($sort_col[0], $dir); return $this->builder->orderBy($sort_col[0], $dir);
} }

View File

@ -167,14 +167,18 @@ class PaymentFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
$dir = ($sort_col[1] == 'asc') ? 'asc' : 'desc';
if ($sort_col[0] == 'client_id') { if ($sort_col[0] == 'client_id') {
return $this->builder->orderBy(\App\Models\Client::select('name') return $this->builder->orderBy(\App\Models\Client::select('name')
->whereColumn('clients.id', 'payments.client_id'), $sort_col[1]); ->whereColumn('clients.id', 'payments.client_id'), $dir);
} }
if($sort_col[0] == 'number') {
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $dir);
} }
public function date_range(string $date_range = ''): Builder public function date_range(string $date_range = ''): Builder

View File

@ -59,21 +59,24 @@ class ProjectFilters extends QueryFilters
public function sort(string $sort = ''): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if ($sort_col[0] == 'client_id') {
return $this->builder->orderBy(\App\Models\Client::select('name')
->whereColumn('clients.id', 'projects.client_id'), $sort_col[1]);
}
if (!is_array($sort_col) || count($sort_col) != 2) { if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder; return $this->builder;
} }
if (is_array($sort_col) && in_array($sort_col[1], ['asc','desc'])) { $dir = ($sort_col[1] == 'asc') ? 'asc' : 'desc';
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
if ($sort_col[0] == 'client_id') {
return $this->builder->orderBy(\App\Models\Client::select('name')
->whereColumn('clients.id', 'projects.client_id'), $dir);
} }
return $this->builder; if($sort_col[0] == 'number') {
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
return $this->builder->orderBy($sort_col[0], $dir);
} }
/** /**

View File

@ -130,6 +130,10 @@ class PurchaseOrderFilters extends QueryFilters
->whereColumn('vendors.id', 'purchase_orders.vendor_id'), $dir); ->whereColumn('vendors.id', 'purchase_orders.vendor_id'), $dir);
} }
if($sort_col[0] == 'number') {
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
return $this->builder->orderBy($sort_col[0], $dir); return $this->builder->orderBy($sort_col[0], $dir);
} }

View File

@ -155,6 +155,10 @@ class QuoteFilters extends QueryFilters
} }
if($sort_col[0] == 'number') {
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
if ($sort_col[0] == 'valid_until') { if ($sort_col[0] == 'valid_until') {
$sort_col[0] = 'due_date'; $sort_col[0] = 'due_date';
} }

View File

@ -140,6 +140,8 @@ class RecurringExpenseFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
$dir = ($sort_col[1] == 'asc') ? 'asc' : 'desc';
if ($sort_col[0] == 'client_id' && in_array($sort_col[1], ['asc', 'desc'])) { if ($sort_col[0] == 'client_id' && in_array($sort_col[1], ['asc', 'desc'])) {
return $this->builder return $this->builder
->orderByRaw('ISNULL(client_id), client_id '. $sort_col[1]) ->orderByRaw('ISNULL(client_id), client_id '. $sort_col[1])
@ -162,6 +164,10 @@ class RecurringExpenseFilters extends QueryFilters
->whereColumn('expense_categories.id', 'expenses.category_id'), $sort_col[1]); ->whereColumn('expense_categories.id', 'expenses.category_id'), $sort_col[1]);
} }
if($sort_col[0] == 'number') {
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) { if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) {
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -143,6 +143,10 @@ class TaskFilters extends QueryFilters
->whereColumn('users.id', 'tasks.user_id'), $dir); ->whereColumn('users.id', 'tasks.user_id'), $dir);
} }
if($sort_col[0] == 'number') {
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
return $this->builder->orderBy($sort_col[0], $dir); return $this->builder->orderBy($sort_col[0], $dir);
} }

View File

@ -71,6 +71,10 @@ class VendorFilters extends QueryFilters
$dir = ($sort_col[1] == 'asc') ? 'asc' : 'desc'; $dir = ($sort_col[1] == 'asc') ? 'asc' : 'desc';
if($sort_col[0] == 'number') {
return $this->builder->orderByRaw('ABS(number) ' . $dir);
}
return $this->builder->orderBy($sort_col[0], $dir); return $this->builder->orderBy($sort_col[0], $dir);
} }

View File

@ -93,7 +93,7 @@ class StoreClientRequest extends Request
$rules['number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)]; $rules['number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)];
$rules['id_number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)]; $rules['id_number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)];
$rules['classification'] = 'bail|sometimes|nullable|in:individual,business,partnership,trust,charity,government,other'; $rules['classification'] = 'bail|sometimes|nullable|in:individual,business,company,partnership,trust,charity,government,other';
return $rules; return $rules;
} }

View File

@ -60,7 +60,7 @@ class UpdateClientRequest extends Request
$rules['size_id'] = 'integer|nullable'; $rules['size_id'] = 'integer|nullable';
$rules['country_id'] = 'integer|nullable'; $rules['country_id'] = 'integer|nullable';
$rules['shipping_country_id'] = 'integer|nullable'; $rules['shipping_country_id'] = 'integer|nullable';
$rules['classification'] = 'bail|sometimes|nullable|in:individual,business,partnership,trust,charity,government,other'; $rules['classification'] = 'bail|sometimes|nullable|in:individual,business,company,partnership,trust,charity,government,other';
if ($this->id_number) { if ($this->id_number) {
$rules['id_number'] = Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id); $rules['id_number'] = Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id);

View File

@ -11,6 +11,7 @@
namespace App\Http\Requests\ExpenseCategory; namespace App\Http\Requests\ExpenseCategory;
use App\Models\Expense;
use App\Http\Requests\Request; use App\Http\Requests\Request;
use App\Models\ExpenseCategory; use App\Models\ExpenseCategory;
@ -23,14 +24,21 @@ class StoreExpenseCategoryRequest extends Request
*/ */
public function authorize(): bool public function authorize(): bool
{ {
return auth()->user()->can('create', ExpenseCategory::class); /** @var \App\Models\User $user */
$user = auth()->user();
return $user->can('create', ExpenseCategory::class) || $user->can('create', Expense::class);
} }
public function rules() public function rules()
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$rules = []; $rules = [];
$rules['name'] = 'required|unique:expense_categories,name,null,null,company_id,'.auth()->user()->companyId(); $rules['name'] = 'required|unique:expense_categories,name,null,null,company_id,'.$user->companyId();
return $this->globalRules($rules); return $this->globalRules($rules);
} }

View File

@ -26,16 +26,24 @@ class UpdateExpenseCategoryRequest extends Request
*/ */
public function authorize(): bool public function authorize(): bool
{ {
return auth()->user()->can('edit', $this->expense_category);
/** @var \App\Models\User $user */
$user = auth()->user();
return $user->can('edit', $this->expense_category);
} }
public function rules() public function rules()
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$rules = []; $rules = [];
if ($this->input('name')) { if ($this->input('name')) {
// $rules['name'] = 'unique:expense_categories,name,'.$this->id.',id,company_id,'.$this->expense_category->company_id; // $rules['name'] = 'unique:expense_categories,name,'.$this->id.',id,company_id,'.$this->expense_category->company_id;
$rules['name'] = Rule::unique('expense_categories')->where('company_id', auth()->user()->company()->id)->ignore($this->expense_category->id); $rules['name'] = Rule::unique('expense_categories')->where('company_id', $user->company()->id)->ignore($this->expense_category->id);
} }
return $rules; return $rules;

View File

@ -198,6 +198,18 @@ class Request extends FormRequest
} }
} }
if(isset($input['public_notes']))
$input['public_notes'] = str_replace("</sc","<-", $input['public_notes']);
if(isset($input['footer']))
$input['footer'] = str_replace("</sc", "<-", $input['footer']);
if(isset($input['terms']))
$input['terms'] = str_replace("</sc", "<-", $input['terms']);
if(isset($input['private_notes']))
$input['private_notes'] = str_replace("</sc", "<-", $input['private_notes']);
return $input; return $input;
} }

View File

@ -73,7 +73,7 @@ class StoreVendorRequest extends Request
} }
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id'; $rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
$rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other'; $rules['classification'] = 'bail|sometimes|nullable|in:individual,business,company,partnership,trust,charity,government,other';
return $rules; return $rules;
} }
@ -89,6 +89,10 @@ class StoreVendorRequest extends Request
$input['currency_id'] = $user->company()->settings->currency_id; $input['currency_id'] = $user->company()->settings->currency_id;
} }
if (isset($input['name'])) {
$input['name'] = strip_tags($input['name']);
}
$input = $this->decodePrimaryKeys($input); $input = $this->decodePrimaryKeys($input);
$this->replace($input); $this->replace($input);

View File

@ -74,7 +74,7 @@ class UpdateVendorRequest extends Request
} }
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id'; $rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
$rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other'; $rules['classification'] = 'bail|sometimes|nullable|in:individual,business,company,partnership,trust,charity,government,other';
return $rules; return $rules;
} }
@ -92,8 +92,8 @@ class UpdateVendorRequest extends Request
{ {
$input = $this->all(); $input = $this->all();
if (array_key_exists('assigned_user_id', $input) && is_string($input['assigned_user_id'])) { if (isset($input['name'])) {
$input['assigned_user_id'] = $this->decodePrimaryKey($input['assigned_user_id']); $input['name'] = strip_tags($input['name']);
} }
if (array_key_exists('country_id', $input) && is_null($input['country_id'])) { if (array_key_exists('country_id', $input) && is_null($input['country_id'])) {

View File

@ -1239,7 +1239,7 @@ class PdfBuilder
public function productTable(): array public function productTable(): array
{ {
$product_items = collect($this->service->config->entity->line_items)->filter(function ($item) { $product_items = collect($this->service->config->entity->line_items)->filter(function ($item) {
return $item->type_id == 1 || $item->type_id == 6 || $item->type_id == 5; return $item->type_id == 1 || $item->type_id == 6 || $item->type_id == 5 || $item->type_id == 4;
}); });
if (count($product_items) == 0) { if (count($product_items) == 0) {

View File

@ -441,7 +441,7 @@ class Design extends BaseDesign
public function productTable(): array public function productTable(): array
{ {
$product_items = collect($this->entity->line_items)->filter(function ($item) { $product_items = collect($this->entity->line_items)->filter(function ($item) {
return $item->type_id == 1 || $item->type_id == 6 || $item->type_id == 5; return $item->type_id == 1 || $item->type_id == 6 || $item->type_id == 5 || $item->type_id == 4;
}); });
if (count($product_items) == 0) { if (count($product_items) == 0) {

View File

@ -277,7 +277,6 @@ class PaymentLinkService
/** /**
* @param Invoice $invoice * @param Invoice $invoice
* @return true * @return true
* @throws BindingResolutionException
*/ */
public function planPaid(Invoice $invoice) public function planPaid(Invoice $invoice)
{ {

View File

@ -74,6 +74,12 @@ trait CleanLineItems
} }
if(isset($item['notes']))
$item['notes'] = str_replace("</", "<-", $item['notes']);
if(isset($item['product_key']))
$item['product_key'] = str_replace("</", "<-", $item['product_key']);
} }
if (array_key_exists('id', $item) || array_key_exists('_id', $item)) { if (array_key_exists('id', $item) || array_key_exists('_id', $item)) {

View File

@ -5120,7 +5120,7 @@ $lang = array(
'set_private' => 'Set private', 'set_private' => 'Set private',
'individual' => 'Individual', 'individual' => 'Individual',
'business' => 'Business', 'business' => 'Business',
'partnership' => 'partnership', 'partnership' => 'Partnership',
'trust' => 'Trust', 'trust' => 'Trust',
'charity' => 'Charity', 'charity' => 'Charity',
'government' => 'Government', 'government' => 'Government',

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,6 @@ components:
description: 'The total number of requests in a given time window.' description: 'The total number of requests in a given time window.'
schema: schema:
type: integer type: integer
components:
securitySchemes: securitySchemes:
ApiKeyAuth: ApiKeyAuth:
type: apiKey type: apiKey

View File

@ -1,72 +1,75 @@
examples: #examples:
Client: # Client:
- id: Opnel5aKBz # $ref: '#/components/schemas/Client'
user_id: Ua6Rw4pVbS
assigned_user_id: Ua6Rw4pVbS # Client:
company_id: Co7Vn3yLmW # id: Opnel5aKBz
name: "Jim's Housekeeping" # user_id: Ua6Rw4pVbS
website: https://www.jims-housekeeping.com # assigned_user_id: Ua6Rw4pVbS
private_notes: Client prefers email communication over phone calls # company_id: Co7Vn3yLmW
client_hash: asdfkjhk342hjhbfdvmnfb1 # name: "Jim's Housekeeping"
industry_id: 5 # website: https://www.jims-housekeeping.com
size_id: 2 # private_notes: Client prefers email communication over phone calls
address1: 123 Main St # client_hash: asdfkjhk342hjhbfdvmnfb1
address2: Apt 4B # industry_id: 5
city: Beverly Hills # size_id: 2
state: California # address1: 123 Main St
postal_code: 90210 # address2: Apt 4B
phone: 555-3434-3434 # city: Beverly Hills
country_id: 1 # state: California
custom_value1: Email # postal_code: 90210
custom_value2: John Doe # phone: 555-3434-3434
custom_value3: Yes # country_id: 1
custom_value4: $50,000 # custom_value1: Email
vat_number: VAT123456 # custom_value2: John Doe
id_number: ID123456 # custom_value3: Yes
number: CL-0001 # custom_value4: $50,000
shipping_address1: 5 Wallaby Way # vat_number: VAT123456
shipping_address2: Suite 5 # id_number: ID123456
shipping_city: Perth # number: CL-0001
shipping_state: Western Australia # shipping_address1: 5 Wallaby Way
shipping_postal_code: 6110 # shipping_address2: Suite 5
shipping_country_id: 4 # shipping_city: Perth
is_deleted: false # shipping_state: Western Australia
balance: 500.00 # shipping_postal_code: 6110
paid_to_date: 2000.00 # shipping_country_id: 4
credit_balance: 100.00 # is_deleted: false
last_login: 1628686031 # balance: 500.00
created_at: 1617629031 # paid_to_date: 2000.00
updated_at: 1628445631 # credit_balance: 100.00
group_settings_id: Opnel5aKBz # last_login: 1628686031
routing_id: Opnel5aKBz3489-dfkiu-2239-sdsd # created_at: 1617629031
is_tax_exempt: false # updated_at: 1628445631
has_valid_vat_number: false # group_settings_id: Opnel5aKBz
payment_balance: 100 # routing_id: Opnel5aKBz3489-dfkiu-2239-sdsd
contacts: # is_tax_exempt: false
- id: Opnel5aKBz # has_valid_vat_number: false
first_name: John # payment_balance: 100
last_name: Doe # contacts:
email: jim@gmail.com # id: Opnel5aKBz
phone: 555-3434-3434 # first_name: John
send_invoice: true # last_name: Doe
custom_value1: Email # email: jim@gmail.com
custom_value2: John Doe # phone: 555-3434-3434
custom_value3: Yes # send_invoice: true
custom_value4: $50,000 # custom_value1: Email
is_primary: true # custom_value2: John Doe
created_at: 1617629031 # custom_value3: Yes
updated_at: 1628445631 # custom_value4: $50,000
deleted_at: 1628445631 # is_primary: true
Meta: # created_at: 1617629031
value: # updated_at: 1628445631
pagination: # deleted_at: 1628445631
total: 1 # Meta:
count: 1 # value:
per_page: 20 # pagination:
current_page: 1 # total: 1
total_pages: 1 # count: 1
links: # per_page: 20
- first: https://invoicing.co/api/v1/invoices?page=1 # current_page: 1
- last: https://invoicing.co/api/v1/invoices?page=1 # total_pages: 1
- prev: null # links:
- next: null # - first: https://invoicing.co/api/v1/invoices?page=1
# - last: https://invoicing.co/api/v1/invoices?page=1
# - prev: null
# - next: null

View File

@ -139,7 +139,7 @@
description: The number of records to return for each request, default is 20 description: The number of records to return for each request, default is 20
required: false required: false
schema: schema:
type: int type: integer
example: 20 example: 20
page_meta: page_meta:
name: page name: page
@ -147,7 +147,7 @@
description: The page number to return for this request (when performing pagination), default is 1 description: The page number to return for this request (when performing pagination), default is 1
required: false required: false
schema: schema:
type: int type: integer
example: 1 example: 1
include: include:
name: include name: include

View File

@ -45,7 +45,7 @@
Filters the entity list by entities that have been deleted. Filters the entity list by entities that have been deleted.
required: false required: false
schema: schema:
type: booleans type: boolean
example: ?is_deleted=true example: ?is_deleted=true
vendor_id: vendor_id:
name: vendor_id name: vendor_id

View File

@ -143,7 +143,7 @@
type: boolean type: boolean
example: true example: true
default_auto_bill: default_auto_bill:
type: enum type: string
example: 'always' example: 'always'
description: | description: |
A flag determining whether to auto-bill clients by default A flag determining whether to auto-bill clients by default

View File

@ -7,11 +7,9 @@
settings: settings:
description: 'Settings that are used for the frontend applications to store user preferences / metadata' description: 'Settings that are used for the frontend applications to store user preferences / metadata'
type: object type: object
example: 'json object'
react_settings: react_settings:
description: 'Dedicated settings object for the react web application' description: 'Dedicated settings object for the react web application'
type: object' type: object
example: 'json object'
is_owner: is_owner:
description: 'Determines whether the user owns this company' description: 'Determines whether the user owns this company'
type: boolean type: boolean

View File

@ -101,7 +101,7 @@
type: number type: number
format: float format: float
example: '10.00' example: '10.00'
readOnly: readOnly: true
line_items: line_items:
type: array type: array
description: 'An array of objects which define the line items of the invoice' description: 'An array of objects which define the line items of the invoice'

View File

@ -31,6 +31,6 @@
example: 1 example: 1
readOnly: true readOnly: true
links: links:
type: array type: object
description: 'The pagination links' description: 'The pagination links'
readOnly: true readOnly: true

View File

@ -10,99 +10,99 @@
type: string type: string
description: 'The hashed ID of the user assigned to this product.' description: 'The hashed ID of the user assigned to this product.'
example: pR0j3 example: pR0j3
required: false
project_id: project_id:
type: string type: string
description: 'The hashed ID of the project that this product is associated with.' description: 'The hashed ID of the project that this product is associated with.'
example: pR0j3 example: pR0j3
required: false
vendor_id: vendor_id:
type: string type: string
description: 'The hashed ID of the vendor that this product is associated with.' description: 'The hashed ID of the vendor that this product is associated with.'
example: pR0j3 example: pR0j3
required: false
custom_value1: custom_value1:
type: string type: string
description: 'Custom value field 1.' description: 'Custom value field 1.'
example: 'Custom value 1' example: 'Custom value 1'
required: false
custom_value2: custom_value2:
type: string type: string
description: 'Custom value field 2.' description: 'Custom value field 2.'
example: 'Custom value 2' example: 'Custom value 2'
required: false
custom_value3: custom_value3:
type: string type: string
description: 'Custom value field 3.' description: 'Custom value field 3.'
example: 'Custom value 3' example: 'Custom value 3'
required: false
custom_value4: custom_value4:
type: string type: string
description: 'Custom value field 4.' description: 'Custom value field 4.'
example: 'Custom value 4' example: 'Custom value 4'
required: false
product_key: product_key:
type: string type: string
description: 'The product key.' description: 'The product key.'
example: '1234' example: '1234'
required: false
notes: notes:
type: string type: string
description: 'Notes about the product.' description: 'Notes about the product.'
example: 'These are some notes about the product.' example: 'These are some notes about the product.'
required: false
cost: cost:
type: number type: number
format: double format: double
description: 'The cost of the product.' description: 'The cost of the product.'
example: 10.0 example: 10.0
required: false
price: price:
type: number type: number
format: double format: double
description: 'The price of the product.' description: 'The price of the product.'
example: 20.0 example: 20.0
required: false
quantity: quantity:
type: number type: number
format: double format: double
description: 'The quantity of the product.' description: 'The quantity of the product.'
example: 5.0 example: 5.0
required: false
default: 1 default: 1
tax_name1: tax_name1:
type: string type: string
description: 'The name of tax 1.' description: 'The name of tax 1.'
example: 'Tax 1' example: 'Tax 1'
required: false
tax_rate1: tax_rate1:
type: number type: number
format: double format: double
description: 'The rate of tax 1.' description: 'The rate of tax 1.'
example: 10.0 example: 10.0
required: false
tax_name2: tax_name2:
type: string type: string
description: 'The name of tax 2.' description: 'The name of tax 2.'
example: 'Tax 2' example: 'Tax 2'
required: false
tax_rate2: tax_rate2:
type: number type: number
format: double format: double
description: 'The rate of tax 2.' description: 'The rate of tax 2.'
example: 5.0 example: 5.0
required: false
tax_name3: tax_name3:
type: string type: string
description: 'The name of tax 3.' description: 'The name of tax 3.'
example: 'Tax 3' example: 'Tax 3'
required: false
tax_rate3: tax_rate3:
type: number type: number
format: double format: double
description: 'The rate of tax 3.' description: 'The rate of tax 3.'
example: 0.0 example: 0.0
required: false
in_stock_quantity: in_stock_quantity:
type: integer type: integer
format: int32 format: int32
@ -114,32 +114,32 @@
The query parameter ?update_in_stock_quantity=true **MUST** be passed if you wish to update this value manually. The query parameter ?update_in_stock_quantity=true **MUST** be passed if you wish to update this value manually.
default: 0 default: 0
required: false
stock_notification: stock_notification:
type: boolean type: boolean
description: Indicates whether stock notifications are enabled for this product description: Indicates whether stock notifications are enabled for this product
default: true default: true
required: false
stock_notification_threshold: stock_notification_threshold:
type: integer type: integer
format: int32 format: int32
description: The minimum quantity threshold for which stock notifications will be triggered description: The minimum quantity threshold for which stock notifications will be triggered
default: 0 default: 0
required: false
max_quantity: max_quantity:
type: integer type: integer
format: int32 format: int32
description: The maximum quantity that can be ordered for this product description: The maximum quantity that can be ordered for this product
required: false
product_image: product_image:
type: string type: string
description: The URL of the product image description: The URL of the product image
format: uri-reference format: uri-reference
required: false
tax_id: tax_id:
type: string type: string
default: '1' default: '1'
required: false
description: | description: |
The tax category id for this product.' The tax category id for this product.'

View File

@ -36,7 +36,6 @@ tags:
description: | description: |
Endpoint definitions for interacting with vendors. Endpoint definitions for interacting with vendors.
- name: Purchase Orders - name: Purchase Orders
summary: Purchase Orders
description: | description: |
Endpoint definitions for interacting with purchase orders. Endpoint definitions for interacting with purchase orders.
- name: expenses - name: expenses

View File

@ -91,8 +91,6 @@ paths:
summary: "Attempts authentication" summary: "Attempts authentication"
description: "Returns a CompanyUser object on success" description: "Returns a CompanyUser object on success"
operationId: postLogin operationId: postLogin
security:
- []
parameters: parameters:
- $ref: "#/components/parameters/X-API-SECRET" - $ref: "#/components/parameters/X-API-SECRET"
- $ref: "#/components/parameters/X-API-TOKEN" - $ref: "#/components/parameters/X-API-TOKEN"

View File

@ -125,12 +125,12 @@
items: items:
$ref: '#/components/schemas/Client' $ref: '#/components/schemas/Client'
example: example:
$ref: '#/components/examples/Client' $ref: '#/components/schemas/Client'
meta: meta:
type: object type: object
$ref: '#/components/schemas/Meta' $ref: '#/components/schemas/Meta'
example: example:
$ref: '#/components/examples/Meta' $ref: '#/components/schemas/Meta'
401: 401:
$ref: '#/components/responses/401' $ref: '#/components/responses/401'
403: 403:

View File

@ -437,7 +437,6 @@
type: object type: object
properties: properties:
action: action:
required: true
type: string type: string
description: | description: |
The action to be performed, options include: The action to be performed, options include:
@ -470,7 +469,6 @@
- `send_email` - `send_email`
Emails an array of invoices. Requires additional properties to be sent. `email_type` Emails an array of invoices. Requires additional properties to be sent. `email_type`
ids: ids:
required: true
type: array type: array
items: items:
description: "Array of hashed IDs to be bulk 'actioned - ['D2J234DFA','D2J234DFA','D2J234DFA']" description: "Array of hashed IDs to be bulk 'actioned - ['D2J234DFA','D2J234DFA','D2J234DFA']"

View File

@ -21,7 +21,7 @@
@if($account && !$account->isPaid()) @if($account && !$account->isPaid())
<div> <div>
<img src="{{ asset('images/invoiceninja-black-logo-2.png') }}" <img src="{{ asset('images/invoiceninja-black-logo-2.png') }}"
class="border-b border-gray-100 h-18 pb-4" alt="Invoice Ninja logo"> class="border-b border-gray-100 h-18 pb-4" alt="Invoice Ninja logo" id="company_logo">
</div> </div>
@elseif(isset($company) && !is_null($company)) @elseif(isset($company) && !is_null($company))
<div> <div>

View File

@ -77,7 +77,7 @@ span {
<td> <td>
<div class="product-information"> <div class="product-information">
<div class="item-details"> <div class="item-details">
<p class="overflow-ellipsis overflow-hidden px-1 mb-2">{!! $product['notes'] !!}</p> <p class="overflow-ellipsis overflow-hidden px-1 mb-2">{!! $product['notes'] !!}</p>
<p class="mt-2"> <p class="mt-2">
@if($show_quantity) @if($show_quantity)
@ -170,7 +170,7 @@ span {
</button> </button>
<div id="notes" class="py-10 border-b-2 border-fuschia-600" x-show="show_notes"> <div id="notes" class="py-10 border-b-2 border-fuschia-600" x-show="show_notes">
{!! html_entity_decode($entity->public_notes) !!} {!! html_entity_decode(e($entity->public_notes)) !!}
</div> </div>
</div> </div>

View File

@ -98,6 +98,11 @@
@livewireStyles @livewireStyles
@if((bool) \App\Utils\Ninja::isSelfHost() && isset($company))
<style>
{!! $company->settings->portal_custom_css !!}
</style>
@endif
<link rel="stylesheet" type="text/css" href="{{ asset('vendor/cookieconsent@3/cookieconsent.min.css') }}" defer> <link rel="stylesheet" type="text/css" href="{{ asset('vendor/cookieconsent@3/cookieconsent.min.css') }}" defer>
</head> </head>