Merge pull request #8991 from turbo124/v5-develop

v5.7.53
This commit is contained in:
David Bomba 2023-11-24 10:24:32 +11:00 committed by GitHub
commit cab854287f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 680 additions and 129 deletions

View File

@ -1 +1 @@
5.7.52 5.7.53

View File

@ -85,7 +85,7 @@ class BackupUpdate extends Command
->each(function ($company) { ->each(function ($company) {
$company_logo_path = $company->settings->company_logo; $company_logo_path = $company->settings->company_logo;
if ($company_logo_path == 'https://invoicing.co/images/new_logo.png' || $company_logo_path == '') { if ($company_logo_path == config('ninja.app_logo') || $company_logo_path == '') {
return; return;
} }

View File

@ -977,7 +977,7 @@ class CheckData extends Command
$cc = ClientContact::on('db-ninja-01')->where('company_id', config('ninja.ninja_default_company_id'))->where('email', $cu->user->email)->first(); $cc = ClientContact::on('db-ninja-01')->where('company_id', config('ninja.ninja_default_company_id'))->where('email', $cu->user->email)->first();
if ($cc) { if ($cc) {
$ninja_portal_url = "https://invoiceninja.invoicing.co/client/ninja/{$cc->contact_key}/{$cu->account->key}"; $ninja_portal_url = config('ninja.ninja_client_portal')."/client/ninja/{$cc->contact_key}/{$cu->account->key}";
$cu->ninja_portal_url = $ninja_portal_url; $cu->ninja_portal_url = $ninja_portal_url;
$cu->save(); $cu->save();
@ -990,7 +990,7 @@ class CheckData extends Command
$cc = $c->contacts()->first(); $cc = $c->contacts()->first();
if ($cc) { if ($cc) {
$ninja_portal_url = "https://invoiceninja.invoicing.co/client/ninja/{$cc->contact_key}/{$cu->account->key}"; $ninja_portal_url = config('ninja.ninja_client_portal')."/client/ninja/{$cc->contact_key}/{$cu->account->key}";
$cu->ninja_portal_url = $ninja_portal_url; $cu->ninja_portal_url = $ninja_portal_url;
$cu->save(); $cu->save();

View File

@ -55,7 +55,7 @@ class ContactLoginController extends Controller
/** @var \App\Models\Company $company **/ /** @var \App\Models\Company $company **/
if ($company) { if ($company) {
$account = $company->account; $account = $company->account;
} elseif (! $company && strpos($request->getHost(), 'invoicing.co') !== false) { } elseif (! $company && strpos($request->getHost(), config('ninja.app_domain')) !== false) {
$subdomain = explode('.', $request->getHost())[0]; $subdomain = explode('.', $request->getHost())[0];
MultiDB::findAndSetDbByDomain(['subdomain' => $subdomain]); MultiDB::findAndSetDbByDomain(['subdomain' => $subdomain]);
$company = Company::where('subdomain', $subdomain)->first(); $company = Company::where('subdomain', $subdomain)->first();

View File

@ -51,7 +51,7 @@ class YodleeController extends BaseController
$this->getAccounts($company, $token); $this->getAccounts($company, $token);
} }
$redirect_url = isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react'] ? 'https://app.invoicing.co/#/' : 'https://invoicing.co/'; $redirect_url = isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react'] ? config('ninja.react_url') : config('ninja.app_url');
$data = [ $data = [
'access_token' => $yodlee->getAccessToken(), 'access_token' => $yodlee->getAccessToken(),

View File

@ -530,8 +530,8 @@ class BaseController extends Controller
$paginator = $query->paginate($limit); $paginator = $query->paginate($limit);
/** @phpstan-ignore-next-line **/ /** @phpstan-ignore-next-line */
$query = $paginator->getCollection(); $query = $paginator->getCollection(); // @phpstan-ignore-line
$resource = new Collection($query, $transformer, $this->entity_type); $resource = new Collection($query, $transformer, $this->entity_type);
@ -636,7 +636,8 @@ class BaseController extends Controller
$paginator = $query->paginate($limit); $paginator = $query->paginate($limit);
/** @phpstan-ignore-next-line **/ /** @phpstan-ignore-next-line **/
$query = $paginator->getCollection(); $query = $paginator->getCollection();// @phpstan-ignore-line
$resource = new Collection($query, $transformer, $this->entity_type); $resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
} }
@ -885,7 +886,8 @@ class BaseController extends Controller
$paginator = $query->paginate($limit); $paginator = $query->paginate($limit);
/** @phpstan-ignore-next-line **/ /** @phpstan-ignore-next-line **/
$query = $paginator->getCollection(); $query = $paginator->getCollection();// @phpstan-ignore-line
$resource = new Collection($query, $transformer, $this->entity_type); $resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
@ -951,7 +953,8 @@ class BaseController extends Controller
if ($query instanceof Builder) { if ($query instanceof Builder) {
$limit = $this->resolveQueryLimit(); $limit = $this->resolveQueryLimit();
$paginator = $query->paginate($limit); $paginator = $query->paginate($limit);
$query = $paginator->getCollection(); $query = $paginator->getCollection();// @phpstan-ignore-line
$resource = new Collection($query, $transformer, $this->entity_type); $resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
} }
@ -1092,8 +1095,8 @@ class BaseController extends Controller
/** @var \App\Models\Account $account */ /** @var \App\Models\Account $account */
//always redirect invoicing.co to invoicing.co //always redirect invoicing.co to invoicing.co
if (Ninja::isHosted() && !in_array(request()->getSchemeAndHttpHost(), ['https://staging.invoicing.co', 'https://invoicing.co', 'https://demo.invoicing.co', 'https://invoiceninja.net'])) { if (Ninja::isHosted() && !in_array(request()->getSchemeAndHttpHost(), ['https://staging.invoicing.co', 'https://invoicing.co', 'https://demo.invoicing.co', 'https://invoiceninja.net', config('ninja.app_url')])) {
return redirect()->secure('https://invoicing.co'); return redirect()->secure(config('ninja.app_url'));
} }
if (config('ninja.require_https') && ! request()->isSecure()) { if (config('ninja.require_https') && ! request()->isSecure()) {

View File

@ -44,7 +44,7 @@ class ApplePayDomainController extends Controller
$domain_name = $request->getHost(); $domain_name = $request->getHost();
if (strpos($domain_name, 'invoicing.co') !== false) { if (strpos($domain_name, config('ninja.app_domain')) !== false) {
$subdomain = explode('.', $domain_name)[0]; $subdomain = explode('.', $domain_name)[0];
$query = [ $query = [

View File

@ -53,10 +53,6 @@ class PreviewController extends BaseController
public function live(PreviewInvoiceRequest $request): mixed public function live(PreviewInvoiceRequest $request): mixed
{ {
if (Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])) {
return response()->json(['message' => 'This server cannot handle this request.'], 400);
}
$start = microtime(true); $start = microtime(true);
/** Build models */ /** Build models */

View File

@ -51,7 +51,7 @@ class StripeConnectController extends BaseController
} }
$stripe_client_id = config('ninja.ninja_stripe_client_id'); $stripe_client_id = config('ninja.ninja_stripe_client_id');
$redirect_uri = 'https://invoicing.co/stripe/completed'; $redirect_uri = config('ninja.app_url').'/stripe/completed';
$endpoint = "https://connect.stripe.com/oauth/authorize?response_type=code&client_id={$stripe_client_id}&redirect_uri={$redirect_uri}&scope=read_write&state={$token}"; $endpoint = "https://connect.stripe.com/oauth/authorize?response_type=code&client_id={$stripe_client_id}&redirect_uri={$redirect_uri}&scope=read_write&state={$token}";
return redirect($endpoint); return redirect($endpoint);
@ -139,9 +139,9 @@ class StripeConnectController extends BaseController
// StripeWebhook::dispatch($company->company_key, $company_gateway->id); // StripeWebhook::dispatch($company->company_key, $company_gateway->id);
if(isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react']) { if(isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react']) {
$redirect_uri = 'https://app.invoicing.co/#/settings/online_payments'; $redirect_uri = config('ninja.react_url').'/#/settings/online_payments';
} else { } else {
$redirect_uri = 'https://invoicing.co/stripe/completed'; $redirect_uri = config('ninja.app_url').'/stripe/completed';
} }
//response here //response here

View File

@ -22,7 +22,7 @@ class ContactRegister
$domain_name = $request->getHost(); $domain_name = $request->getHost();
/* Hosted */ /* Hosted */
if (strpos($domain_name, 'invoicing.co') !== false) { if (strpos($domain_name, config('ninja.app_domain')) !== false) {
$subdomain = explode('.', $domain_name)[0]; $subdomain = explode('.', $domain_name)[0];
$query = [ $query = [

View File

@ -32,8 +32,7 @@ class SessionDomains
$domain_name = $request->getHost(); $domain_name = $request->getHost();
if (strpos($domain_name, 'invoicing.co') !== false) { if (strpos($domain_name, config('ninja.app_domain')) !== false) {
// config(['session.domain' => '.invoicing.co']);
} else { } else {
config(['session.domain' => $domain_name]); config(['session.domain' => $domain_name]);
} }

View File

@ -41,7 +41,7 @@ class SetDomainNameDb
$domain_name = $request->getHost(); $domain_name = $request->getHost();
if (strpos($domain_name, 'invoicing.co') !== false) { if (strpos($domain_name, config('ninja.app_domain')) !== false) {
$subdomain = explode('.', $domain_name)[0]; $subdomain = explode('.', $domain_name)[0];
$query = [ $query = [

View File

@ -28,34 +28,45 @@ class StoreExpenseRequest extends Request
*/ */
public function authorize() : bool public function authorize() : bool
{ {
return auth()->user()->can('create', Expense::class); /** @var \App\Models\User $user */
$user = auth()->user();
return $user->can('create', Expense::class);
} }
public function rules() public function rules()
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$rules = []; $rules = [];
if ($this->number) { if ($this->number) {
$rules['number'] = Rule::unique('expenses')->where('company_id', auth()->user()->company()->id); $rules['number'] = Rule::unique('expenses')->where('company_id', $user->company()->id);
} }
if ($this->client_id) { if ($this->client_id) {
$rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id; $rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.$user->company()->id;
} }
$rules['category_id'] = 'bail|nullable|sometimes|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0'; $rules['category_id'] = 'bail|nullable|sometimes|exists:expense_categories,id,company_id,'.$user->company()->id.',is_deleted,0';
$rules['payment_date'] = 'bail|nullable|sometimes|date:Y-m-d';
$rules['date'] = 'bail|sometimes|date:Y-m-d';
return $this->globalRules($rules); return $this->globalRules($rules);
} }
public function prepareForValidation() public function prepareForValidation()
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$input = $this->all(); $input = $this->all();
$input = $this->decodePrimaryKeys($input); $input = $this->decodePrimaryKeys($input);
if (! array_key_exists('currency_id', $input) || strlen($input['currency_id']) == 0) { if (! array_key_exists('currency_id', $input) || strlen($input['currency_id']) == 0) {
$input['currency_id'] = (string) auth()->user()->company()->settings->currency_id; $input['currency_id'] = (string) $user->company()->settings->currency_id;
} }
if (array_key_exists('color', $input) && is_null($input['color'])) { if (array_key_exists('color', $input) && is_null($input['color'])) {
@ -80,7 +91,6 @@ class StoreExpenseRequest extends Request
public function messages() public function messages()
{ {
return [ return [
// 'unique' => ctrans('validation.unique', ['attribute' => 'number']),
]; ];
} }
} }

View File

@ -39,7 +39,7 @@ class StripeConnectFailed extends Mailable
{ {
return new Envelope( return new Envelope(
subject: "Stripe Connect not configured, please login and connect.", subject: "Stripe Connect not configured, please login and connect.",
from: "maildelivery@invoicing.co", from: config('ninja.contact.email'),
to: $this->user->email, to: $this->user->email,
); );
} }

View File

@ -41,6 +41,12 @@ class ExpenseRepository extends BaseRepository
*/ */
public function save(array $data, Expense $expense): Expense public function save(array $data, Expense $expense): Expense
{ {
if(isset($data['payment_date']) && $data['payment_date'] == $expense->payment_date) {
//do nothing
} elseif(isset($data['payment_date']) && strlen($data['payment_date']) > 1 && $expense->company->notify_vendor_when_paid) {
nlog("NOT SAME");
}
$expense->fill($data); $expense->fill($data);
if (!$expense->id) { if (!$expense->id) {
@ -50,8 +56,8 @@ class ExpenseRepository extends BaseRepository
if (empty($expense->number)) { if (empty($expense->number)) {
$expense = $this->findAndSaveNumber($expense); $expense = $this->findAndSaveNumber($expense);
} }
else
$expense->saveQuietly(); $expense->saveQuietly();
if (array_key_exists('documents', $data)) { if (array_key_exists('documents', $data)) {
$this->saveDocuments($data['documents'], $expense); $this->saveDocuments($data['documents'], $expense);

View File

@ -158,7 +158,12 @@ class Statement
->where('company_id', $this->client->company_id) ->where('company_id', $this->client->company_id)
->first(); ->first();
$ts = $template->service()->build([ $ts = $template->service();
$ts->addGlobal(['show_credits' => $this->options['show_credits_table']]);
$ts->addGlobal(['show_aging' => $this->options['show_aging_table']]);
$ts->addGlobal(['show_payments' => $this->options['show_payments_table']]);
$ts->build([
'variables' => collect([$variables]), 'variables' => collect([$variables]),
'invoices' => $this->getInvoices()->get(), 'invoices' => $this->getInvoices()->get(),
'payments' => $this->options['show_payments_table'] ? $this->getPayments()->get() : collect([]), 'payments' => $this->options['show_payments_table'] ? $this->getPayments()->get() : collect([]),
@ -400,6 +405,7 @@ class Statement
protected function getAging(): array protected function getAging(): array
{ {
return [ return [
ctrans('texts.current') => $this->getAgingAmount('0'),
'0-30' => $this->getAgingAmount('30'), '0-30' => $this->getAgingAmount('30'),
'30-60' => $this->getAgingAmount('60'), '30-60' => $this->getAgingAmount('60'),
'60-90' => $this->getAgingAmount('90'), '60-90' => $this->getAgingAmount('90'),
@ -421,14 +427,23 @@ class Statement
$from = $ranges[0]; $from = $ranges[0];
$to = $ranges[1]; $to = $ranges[1];
$amount = Invoice::withTrashed() $query = Invoice::withTrashed()
->where('client_id', $this->client->id) ->where('client_id', $this->client->id)
->where('company_id', $this->client->company_id) ->where('company_id', $this->client->company_id)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('balance', '>', 0) ->where('balance', '>', 0)
->where('is_deleted', 0) ->where('is_deleted', 0);
->whereBetween('due_date', [$to, $from])
->sum('balance'); if($range == '0'){
$query->where(function ($q) use($to, $from){
$q->whereBetween('due_date', [$to, $from])->orWhereNull('due_date');
});
}
else {
$query->whereBetween('due_date', [$to, $from]);
}
$amount = $query->sum('balance');
return Number::formatMoney($amount, $this->client); return Number::formatMoney($amount, $this->client);
} }
@ -444,6 +459,10 @@ class Statement
$ranges = []; $ranges = [];
switch ($range) { switch ($range) {
case '0':
$ranges[0] = now()->subYears(50);
$ranges[1] = now()->startOfDay()->subMinute();
return $ranges;
case '30': case '30':
$ranges[0] = now()->startOfDay(); $ranges[0] = now()->startOfDay();
$ranges[1] = now()->startOfDay()->subDays(30); $ranges[1] = now()->startOfDay()->subDays(30);

View File

@ -213,7 +213,7 @@ class PdfMock
'$client.billing_address2' => '63993 Aiyana View', '$client.billing_address2' => '63993 Aiyana View',
'$client.billing_address1' => '8447', '$client.billing_address1' => '8447',
'$client.shipping_country' => 'USA', '$client.shipping_country' => 'USA',
'$invoiceninja.whitelabel' => 'https://invoicing.co/images/new_logo.png', '$invoiceninja.whitelabel' => config('ninja.app_logo'),
'$client.billing_address' => '8447<br/>63993 Aiyana View<br/>Aufderharchester, North Carolina 11243<br/>United States<br/>', '$client.billing_address' => '8447<br/>63993 Aiyana View<br/>Aufderharchester, North Carolina 11243<br/>United States<br/>',
'$client.billing_country' => 'USA', '$client.billing_country' => 'USA',
'$task.gross_line_total' => '100', '$task.gross_line_total' => '100',
@ -483,12 +483,15 @@ class PdfMock
'_rate3' => '', '_rate3' => '',
'$taxes' => '$40.00', '$taxes' => '$40.00',
'$total' => '$10.00', '$total' => '$10.00',
'$refund' => '',
'$refunded' => '',
'$phone' => '&nbsp;', '$phone' => '&nbsp;',
'$terms' => 'Default company invoice terms', '$terms' => 'Default company invoice terms',
'$from' => 'Bob Jones', '$from' => 'Bob Jones',
'$item' => '', '$item' => '',
'$date' => '25/Feb/2023', '$date' => '25/Feb/2023',
'$tax' => '', '$tax' => '',
'$net' => 'Net',
'$dir' => 'ltr', '$dir' => 'ltr',
'$to' => 'Jimmy Giggles', '$to' => 'Jimmy Giggles',
'$show_paid_stamp' => $this->settings->show_paid_stamp ? 'flex' : 'none', '$show_paid_stamp' => $this->settings->show_paid_stamp ? 'flex' : 'none',
@ -803,6 +806,8 @@ class PdfMock
'$tax_rate1_label' => ctrans('texts.tax_rate1'), '$tax_rate1_label' => ctrans('texts.tax_rate1'),
'$tax_rate2_label' => ctrans('texts.tax_rate2'), '$tax_rate2_label' => ctrans('texts.tax_rate2'),
'$tax_rate3_label' => ctrans('texts.tax_rate3'), '$tax_rate3_label' => ctrans('texts.tax_rate3'),
'$refund_label' => ctrans('texts.refund'),
'$refunded_label' => ctrans('texts.refunded'),
'$phone_label' => ctrans('texts.phone'), '$phone_label' => ctrans('texts.phone'),
'$email_label' => ctrans('texts.email'), '$email_label' => ctrans('texts.email'),
'$taxes_label' => ctrans('texts.taxes'), '$taxes_label' => ctrans('texts.taxes'),
@ -811,6 +816,7 @@ class PdfMock
'$item_label' => ctrans('texts.item'), '$item_label' => ctrans('texts.item'),
'$date_label' => ctrans('texts.date'), '$date_label' => ctrans('texts.date'),
'$tax_label' => ctrans('texts.tax'), '$tax_label' => ctrans('texts.tax'),
'$net_label' => ctrans('texts.net'),
'$dir_label' => '', '$dir_label' => '',
'$to_label' => ctrans('texts.to'), '$to_label' => ctrans('texts.to'),
'$start_date_label' => ctrans('texts.start_date'), '$start_date_label' => ctrans('texts.start_date'),
@ -831,7 +837,7 @@ class PdfMock
'$purchase_order.due_date' => '02-12-2021', '$purchase_order.due_date' => '02-12-2021',
'$vendor.billing_address1' => '589', '$vendor.billing_address1' => '589',
'$vendor.billing_address2' => '761 Odessa Centers Suite 673', '$vendor.billing_address2' => '761 Odessa Centers Suite 673',
'$invoiceninja.whitelabel' => 'https://invoicing.co/images/new_logo.png', '$invoiceninja.whitelabel' => config('ninja.app_logo'),
'$purchase_order.custom1' => 'Custom 1', '$purchase_order.custom1' => 'Custom 1',
'$purchase_order.custom2' => 'Custom 2', '$purchase_order.custom2' => 'Custom 2',
'$purchase_order.custom3' => 'Custom 3', '$purchase_order.custom3' => 'Custom 3',
@ -907,7 +913,7 @@ class PdfMock
'$created_by_user' => 'Mr. Louvenia Armstrong Prof. Reyes Anderson', '$created_by_user' => 'Mr. Louvenia Armstrong Prof. Reyes Anderson',
'$vendor.currency' => 'USD', '$vendor.currency' => 'USD',
'$company.country' => 'United States', '$company.country' => 'United States',
'$tech_hero_image' => 'https://invoicing.co/images/pdf-designs/tech-hero-image.jpg', '$tech_hero_image' => config('ninja.app_url').'/images/pdf-designs/tech-hero-image.jpg',
'$company.website' => 'http://www.dare.com/vero-consequatur-eveniet-dolorum-exercitationem-alias-repellat.html', '$company.website' => 'http://www.dare.com/vero-consequatur-eveniet-dolorum-exercitationem-alias-repellat.html',
'$gross_subtotal' => '$10,256.40', '$gross_subtotal' => '$10,256.40',
'$emailSignature' => '&nbsp;', '$emailSignature' => '&nbsp;',
@ -1115,6 +1121,8 @@ class PdfMock
'$tax_rate1' => '', '$tax_rate1' => '',
'$tax_rate2' => '', '$tax_rate2' => '',
'$tax_rate3' => '', '$tax_rate3' => '',
'$refund' => 'Refund',
'$refunded' => 'Refunded',
'$total' => '$10,256.40', '$total' => '$10,256.40',
'$taxes' => '$488.40', '$taxes' => '$488.40',
'$phone' => '&nbsp;', '$phone' => '&nbsp;',
@ -1123,6 +1131,7 @@ class PdfMock
'$date' => '14/Mar/2023', '$date' => '14/Mar/2023',
'$tax' => '', '$tax' => '',
'$dir' => 'ltr', '$dir' => 'ltr',
'$net' => 'Net',
'$to' => '', '$to' => '',
], ],
'labels' => $this->vendorLabels(), 'labels' => $this->vendorLabels(),
@ -1334,6 +1343,8 @@ class PdfMock
'$tax_rate1_label' => ctrans('texts.tax_rate1'), '$tax_rate1_label' => ctrans('texts.tax_rate1'),
'$tax_rate2_label' => ctrans('texts.tax_rate2'), '$tax_rate2_label' => ctrans('texts.tax_rate2'),
'$tax_rate3_label' => ctrans('texts.tax_rate3'), '$tax_rate3_label' => ctrans('texts.tax_rate3'),
'$refund_label' => ctrans('texts.refund'),
'$refunded_label' => ctrans('texts.refunded'),
'$total_label' => ctrans('texts.total'), '$total_label' => ctrans('texts.total'),
'$taxes_label' => ctrans('texts.taxes'), '$taxes_label' => ctrans('texts.taxes'),
'$phone_label' => ctrans('texts.phone'), '$phone_label' => ctrans('texts.phone'),
@ -1341,6 +1352,7 @@ class PdfMock
'$item_label' => ctrans('texts.item'), '$item_label' => ctrans('texts.item'),
'$date_label' => ctrans('texts.date'), '$date_label' => ctrans('texts.date'),
'$tax_label' => ctrans('texts.tax'), '$tax_label' => ctrans('texts.tax'),
'$net_label' => ctrans('texts.net'),
'$dir_label' => '', '$dir_label' => '',
'$to_label' => ctrans('texts.to'), '$to_label' => ctrans('texts.to'),
]; ];

File diff suppressed because one or more lines are too long

View File

@ -53,6 +53,8 @@ class TemplateService
private array $variables = []; private array $variables = [];
private array $global_vars = [];
public ?Company $company; public ?Company $company;
private ?Client $client; private ?Client $client;
@ -124,6 +126,7 @@ class TemplateService
{ {
$this->compose() $this->compose()
->processData($data) ->processData($data)
->setGlobals()
->parseNinjaBlocks() ->parseNinjaBlocks()
->processVariables($data) ->processVariables($data)
->parseGlobalStacks() ->parseGlobalStacks()
@ -145,6 +148,25 @@ class TemplateService
return $this; return $this;
} }
private function setGlobals(): self
{
foreach($this->global_vars as $key => $value) {
$this->twig->addGlobal($key, $value);
}
$this->global_vars = [];
return $this;
}
public function addGlobal(array $var): self
{
$this->global_vars = array_merge($this->global_vars, $var);
return $this;
}
/** /**
* Returns a Mock Template * Returns a Mock Template
* *
@ -159,6 +181,10 @@ class TemplateService
$this->data = $tm->engines; $this->data = $tm->engines;
$this->variables = $tm->variables[0]; $this->variables = $tm->variables[0];
$this->twig->addGlobal('currency_code', $this->company->currency()->code);
$this->twig->addGlobal('show_credits', true);
$this->twig->addGlobal('show_aging', true);
$this->twig->addGlobal('show_payments', true);
$this->parseNinjaBlocks() $this->parseNinjaBlocks()
->parseGlobalStacks() ->parseGlobalStacks()
@ -442,6 +468,7 @@ class TemplateService
'balance' => Number::formatMoney($invoice->balance, $invoice->client), 'balance' => Number::formatMoney($invoice->balance, $invoice->client),
'status_id' => $invoice->status_id, 'status_id' => $invoice->status_id,
'status' => Invoice::stringStatus($invoice->status_id), 'status' => Invoice::stringStatus($invoice->status_id),
'amount_raw' => $invoice->amount ,
'balance_raw' => $invoice->balance, 'balance_raw' => $invoice->balance,
'number' => $invoice->number ?: '', 'number' => $invoice->number ?: '',
'discount' => $invoice->discount, 'discount' => $invoice->discount,
@ -550,6 +577,8 @@ class TemplateService
$this->payment = $payment; $this->payment = $payment;
$this->addGlobal(['currency_code' => $payment->currency->code ?? $this->company->currency()->code]);
$credits = $payment->credits->map(function ($credit) use ($payment) { $credits = $payment->credits->map(function ($credit) use ($payment) {
return [ return [
'credit' => $credit->number, 'credit' => $credit->number,
@ -827,11 +856,11 @@ class TemplateService
*/ */
public function processPayments($payments): array public function processPayments($payments): array
{ {
nlog("processing payments");
$payments = collect($payments)->map(function ($payment) { $payments = collect($payments)->map(function ($payment) {
return $this->transformPayment($payment); return $this->transformPayment($payment);
})->toArray(); })->toArray();
nlog($payments);
return $payments; return $payments;
} }

View File

@ -166,6 +166,7 @@ class HtmlEngine
$data['$exchange_rate'] = ['value' => $this->entity->exchange_rate ?: ' ', 'label' => ctrans('texts.exchange_rate')]; $data['$exchange_rate'] = ['value' => $this->entity->exchange_rate ?: ' ', 'label' => ctrans('texts.exchange_rate')];
$data['$triangular_tax'] = ['value' => ctrans('texts.triangular_tax'), 'label' => '']; $data['$triangular_tax'] = ['value' => ctrans('texts.triangular_tax'), 'label' => ''];
$data['$tax_info'] = ['value' => $this->taxLabel(), 'label' => '']; $data['$tax_info'] = ['value' => $this->taxLabel(), 'label' => ''];
$data['$net'] = ['value' => '', 'label' => ctrans('texts.net')];
if ($this->entity_string == 'invoice' || $this->entity_string == 'recurring_invoice') { if ($this->entity_string == 'invoice' || $this->entity_string == 'recurring_invoice') {
$data['$entity'] = ['value' => ctrans('texts.invoice'), 'label' => ctrans('texts.invoice')]; $data['$entity'] = ['value' => ctrans('texts.invoice'), 'label' => ctrans('texts.invoice')];
@ -664,6 +665,8 @@ class HtmlEngine
$data['$payment.custom2'] = ['value' => '', 'label' => ctrans('texts.payment')]; $data['$payment.custom2'] = ['value' => '', 'label' => ctrans('texts.payment')];
$data['$payment.custom3'] = ['value' => '', 'label' => ctrans('texts.payment')]; $data['$payment.custom3'] = ['value' => '', 'label' => ctrans('texts.payment')];
$data['$payment.custom4'] = ['value' => '', 'label' => ctrans('texts.payment')]; $data['$payment.custom4'] = ['value' => '', 'label' => ctrans('texts.payment')];
$data['$refund'] = ['value' => '', 'label' => ctrans('texts.refund')];
$data['$refunded'] = ['value' => '', 'label' => ctrans('texts.refunded')];
$data['$payment.amount'] = ['value' => '', 'label' => ctrans('texts.payment')]; $data['$payment.amount'] = ['value' => '', 'label' => ctrans('texts.payment')];
$data['$payment.date'] = ['value' => '', 'label' => ctrans('texts.payment_date')]; $data['$payment.date'] = ['value' => '', 'label' => ctrans('texts.payment_date')];

View File

@ -11,12 +11,14 @@ return [
'version_url' => 'https://pdf.invoicing.co/api/version', 'version_url' => 'https://pdf.invoicing.co/api/version',
'app_name' => env('APP_NAME', 'Invoice Ninja'), 'app_name' => env('APP_NAME', 'Invoice Ninja'),
'app_env' => env('APP_ENV', 'selfhosted'), 'app_env' => env('APP_ENV', 'selfhosted'),
'app_logo' => env('APP_LOGO', 'https://invoicing.co/images/new_logo.png'),
'ninja_client_portal' => env('NINJA_CLIENT_PORTAL', 'https://invoiceninja.invoicing.co'),
'debug_enabled' => env('APP_DEBUG', false), 'debug_enabled' => env('APP_DEBUG', false),
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => env('APP_VERSION','5.7.52'), 'app_version' => env('APP_VERSION','5.7.53'),
'app_tag' => env('APP_TAG','5.7.52'), 'app_tag' => env('APP_TAG','5.7.53'),
'minimum_client_version' => '5.0.16', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false), 'api_secret' => env('API_SECRET', false),

View File

@ -4260,7 +4260,7 @@ $LANG = array(
'direct_debit' => 'Direct Debit', 'direct_debit' => 'Direct Debit',
'clone_to_expense' => 'Clone to Expense', 'clone_to_expense' => 'Clone to Expense',
'checkout' => 'Checkout', 'checkout' => 'Checkout',
'acss' => 'Pre-authorized debit payments', 'acss' => 'ACSS Debit',
'invalid_amount' => 'Invalid amount. Number/Decimal values only.', 'invalid_amount' => 'Invalid amount. Number/Decimal values only.',
'client_payment_failure_body' => 'Payment for Invoice :invoice for amount :amount failed.', 'client_payment_failure_body' => 'Payment for Invoice :invoice for amount :amount failed.',
'browser_pay' => 'Google Pay, Apple Pay, Microsoft Pay', 'browser_pay' => 'Google Pay, Apple Pay, Microsoft Pay',

View File

@ -958,7 +958,7 @@ $LANG = array(
'header_font_id' => 'Police de l\'en-tête', 'header_font_id' => 'Police de l\'en-tête',
'body_font_id' => 'Police du corps', 'body_font_id' => 'Police du corps',
'color_font_help' => 'Note: la couleur principale et les polices sont aussi utilisées dans le portail client et dans les modèles de courriels personnalisés.', 'color_font_help' => 'Note: la couleur principale et les polices sont aussi utilisées dans le portail client et dans les modèles de courriels personnalisés.',
'live_preview' => 'PRÉVISUALISATION', 'live_preview' => 'Prévisualitsation',
'invalid_mail_config' => 'impossible d\'envoyer le courriel, veuillez vérifier vos paramètres courriel.', 'invalid_mail_config' => 'impossible d\'envoyer le courriel, veuillez vérifier vos paramètres courriel.',
'invoice_message_button' => 'Pour voir la facture de :amount, cliquez sur le bouton ci-dessous.', 'invoice_message_button' => 'Pour voir la facture de :amount, cliquez sur le bouton ci-dessous.',
'quote_message_button' => 'Pour voir la soumission de :amount, cliquez sur le bouton ci-dessous.', 'quote_message_button' => 'Pour voir la soumission de :amount, cliquez sur le bouton ci-dessous.',
@ -1183,7 +1183,7 @@ $LANG = array(
'page_size' => 'Taille de page', 'page_size' => 'Taille de page',
'live_preview_disabled' => 'La prévisualisation en direct a été désactivée pour cette police', 'live_preview_disabled' => 'La prévisualisation en direct a été désactivée pour cette police',
'invoice_number_padding' => 'Remplissage (padding)', 'invoice_number_padding' => 'Remplissage (padding)',
'preview' => 'PRÉVISUALISATION', 'preview' => 'Prévisualitsation',
'list_vendors' => 'Liste des fournisseurs', 'list_vendors' => 'Liste des fournisseurs',
'add_users_not_supported' => 'Mettre à niveau vers le plan Enterprise plan pour ajouter des utilisateurs à votre compte.', 'add_users_not_supported' => 'Mettre à niveau vers le plan Enterprise plan pour ajouter des utilisateurs à votre compte.',
'enterprise_plan_features' => 'Le Plan entreprise offre le support pour de multiple utilisateurs ainsi que l\'ajout de pièces jointes, :link pour voir la liste complète des fonctionnalités.', 'enterprise_plan_features' => 'Le Plan entreprise offre le support pour de multiple utilisateurs ainsi que l\'ajout de pièces jointes, :link pour voir la liste complète des fonctionnalités.',
@ -5181,6 +5181,30 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'payment_receipt' => 'Reçu de paiement #', 'payment_receipt' => 'Reçu de paiement #',
'load_template_description' => 'Le modèle s\'appliquera à:', 'load_template_description' => 'Le modèle s\'appliquera à:',
'run_template' => 'Exécuter le modèle', 'run_template' => 'Exécuter le modèle',
'statement_design' => 'Modèle de relevé',
'delivery_note_design' => 'Modèle de note de livraison',
'payment_receipt_design' => 'Modèle de reçu de paiement',
'payment_refund_design' => 'Modèle de paiement de remboursement',
'task_extension_banner' => 'Ajouter l\'extension Chrome pour gérer vos tâches',
'watch_video' => 'Regardez',
'view_extension' => 'Voir l\'extension',
'reactivate_email' => 'Réactiver le courriel',
'email_reactivated' => 'Le courriel a été réactivé',
'template_help' => 'Enable using the design as a template',
'quarter' => 'Quarter',
'item_description' => 'Description d\'article',
'task_item' => 'Article de tâche',
'record_state' => 'État de l\'enregistrement',
'save_files_to_this_folder' => 'Sauvegarder les fichiers dans ce dossier',
'downloads_folder' => 'Dossier de téléchargements',
'total_invoiced_quotes' => 'Soumissions facturées',
'total_invoice_paid_quotes' => 'Soumissions de factures payées',
'downloads_folder_does_not_exist' => 'Le dossier de téléchargements n\'existe pas :value',
'user_logged_in_notification' => 'User Logged in Notification',
'user_logged_in_notification_help' => 'Send an email when logging in from a new location',
'payment_email_all_contacts' => 'Courriel de paiement à tous les contacts',
'payment_email_all_contacts_help' => 'Envoi un courriel de paiement à tous les contacts lorsqu\'activé',
'add_line' => 'Ajouter une ligne',
); );
return $LANG; return $LANG;

View File

@ -64,7 +64,7 @@ $LANG = array(
'archive_invoice' => 'Archiver la facture', 'archive_invoice' => 'Archiver la facture',
'delete_invoice' => 'Supprimer la facture', 'delete_invoice' => 'Supprimer la facture',
'email_invoice' => 'Envoyer la facture par courriel', 'email_invoice' => 'Envoyer la facture par courriel',
'enter_payment' => 'Inscrire un paiement', 'enter_payment' => 'Saisir un paiement',
'tax_rates' => 'Taux de TVA', 'tax_rates' => 'Taux de TVA',
'rate' => 'Taux', 'rate' => 'Taux',
'settings' => 'Paramètres', 'settings' => 'Paramètres',
@ -125,8 +125,8 @@ $LANG = array(
'filter' => 'Filtrer', 'filter' => 'Filtrer',
'new_client' => 'Nouveau client', 'new_client' => 'Nouveau client',
'new_invoice' => 'Nouvelle facture', 'new_invoice' => 'Nouvelle facture',
'new_payment' => 'Inscrire un paiement', 'new_payment' => 'Saisir un paiement',
'new_credit' => 'Inscrire un crédit', 'new_credit' => 'Saisir un crédit',
'contact' => 'Contact', 'contact' => 'Contact',
'date_created' => 'Date de création', 'date_created' => 'Date de création',
'last_login' => 'Dernière connexion', 'last_login' => 'Dernière connexion',
@ -150,7 +150,7 @@ $LANG = array(
'edit_client' => 'Modifier le client', 'edit_client' => 'Modifier le client',
'edit_invoice' => 'Modifier la facture', 'edit_invoice' => 'Modifier la facture',
'create_invoice' => 'Créer une facture', 'create_invoice' => 'Créer une facture',
'enter_credit' => 'Inscrire un crédit', 'enter_credit' => 'Saisir un crédit',
'last_logged_in' => 'Dernière connexion', 'last_logged_in' => 'Dernière connexion',
'details' => 'Détails', 'details' => 'Détails',
'standing' => 'En attente', 'standing' => 'En attente',
@ -387,7 +387,7 @@ $LANG = array(
'more_designs_self_host_text' => '', 'more_designs_self_host_text' => '',
'buy' => 'Acheter', 'buy' => 'Acheter',
'bought_designs' => 'Les nouveaux modèles ont été ajoutés avec succès', 'bought_designs' => 'Les nouveaux modèles ont été ajoutés avec succès',
'sent' => 'Envoyé', 'sent' => 'Envoyée',
'vat_number' => 'N° de taxe', 'vat_number' => 'N° de taxe',
'timesheets' => 'Feuilles de temps', 'timesheets' => 'Feuilles de temps',
'payment_title' => 'Veuillez entrer votre adresse de facturation et vos information de carte de crédit', 'payment_title' => 'Veuillez entrer votre adresse de facturation et vos information de carte de crédit',
@ -5181,6 +5181,30 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'payment_receipt' => 'Reçu de paiement # :number', 'payment_receipt' => 'Reçu de paiement # :number',
'load_template_description' => 'Le modèle sera appliqué aux éléments suivants :', 'load_template_description' => 'Le modèle sera appliqué aux éléments suivants :',
'run_template' => 'Exécuter le modèle', 'run_template' => 'Exécuter le modèle',
'statement_design' => 'Modèle de relevé',
'delivery_note_design' => 'Delivery Note Design',
'payment_receipt_design' => 'Modèle de reçu de paiement',
'payment_refund_design' => 'Payment Refund Design',
'task_extension_banner' => 'Add the Chrome extension to manage your tasks',
'watch_video' => 'Regardez la vidéo',
'view_extension' => 'Voir l\'extension',
'reactivate_email' => 'Réactiver l\'adresse email',
'email_reactivated' => 'L\'adresse email a été réactivée',
'template_help' => 'Enable using the design as a template',
'quarter' => 'Quarter',
'item_description' => 'Description d\'article',
'task_item' => 'Task Item',
'record_state' => 'Record State',
'save_files_to_this_folder' => 'Sauvegarder les fichiers dans ce dossier',
'downloads_folder' => 'Dossier de téléchargements',
'total_invoiced_quotes' => 'Offres facturées',
'total_invoice_paid_quotes' => 'Offres de factures payées',
'downloads_folder_does_not_exist' => 'Le dossier de téléchargements n\'existe pas :value',
'user_logged_in_notification' => 'Notification de connexion d\'utilisateur',
'user_logged_in_notification_help' => 'Send an email when logging in from a new location',
'payment_email_all_contacts' => 'Email de paiement à tous les contacts',
'payment_email_all_contacts_help' => 'Sends the payment email to all contacts when enabled',
'add_line' => 'Ajouter une ligne',
); );
return $LANG; return $LANG;

View File

@ -1889,7 +1889,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/companies/{id}/upload": "/api/v1/companies/{id}/upload":
put: post:
tags: tags:
- companies - companies
summary: "Uploads a document to a company" summary: "Uploads a document to a company"
@ -1907,6 +1907,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the client object" description: "Returns the client object"
@ -3429,7 +3446,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/expenses/{id}/upload": "/api/v1/expenses/{id}/upload":
put: post:
tags: tags:
- expense - expense
summary: "Uploads a document to a expense" summary: "Uploads a document to a expense"
@ -3447,6 +3464,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Expense object" description: "Returns the Expense object"
@ -3801,7 +3835,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/group_settings/{id}/upload": "/api/v1/group_settings/{id}/upload":
put: post:
tags: tags:
- group_settings - group_settings
summary: "Uploads a document to a group setting" summary: "Uploads a document to a group setting"
@ -3819,6 +3853,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Group Setting object" description: "Returns the Group Setting object"
@ -4926,7 +4977,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/recurring_expenses/{id}/upload": "/api/v1/recurring_expenses/{id}/upload":
put: post:
tags: tags:
- recurring_expense - recurring_expense
summary: "Uploads a document to a recurring_expense" summary: "Uploads a document to a recurring_expense"
@ -4944,6 +4995,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the RecurringExpense object" description: "Returns the RecurringExpense object"
@ -8620,7 +8688,7 @@ paths:
$ref: '#/components/responses/default' $ref: '#/components/responses/default'
"/api/v1/products/{id}/upload": "/api/v1/products/{id}/upload":
put: post:
tags: tags:
- products - products
summary: "Add product document" summary: "Add product document"
@ -9021,7 +9089,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/tasks/{id}/upload": "/api/v1/tasks/{id}/upload":
put: post:
tags: tags:
- tasks - tasks
summary: "Uploads a task document" summary: "Uploads a task document"
@ -9039,6 +9107,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Task object" description: "Returns the Task object"
@ -9440,7 +9525,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/projects/{id}/upload": "/api/v1/projects/{id}/upload":
put: post:
tags: tags:
- projects - projects
summary: "Uploads a project document" summary: "Uploads a project document"
@ -9458,6 +9543,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Project object" description: "Returns the Project object"
@ -9924,7 +10026,7 @@ paths:
default: default:
$ref: '#/components/responses/default' $ref: '#/components/responses/default'
'/api/v1/clients/{id}/upload': '/api/v1/clients/{id}/upload':
put: post:
tags: tags:
- clients - clients
summary: 'Add client document' summary: 'Add client document'
@ -10614,7 +10716,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/credits/{id}/upload": "/api/v1/credits/{id}/upload":
put: post:
tags: tags:
- credits - credits
summary: "Upload a credit document" summary: "Upload a credit document"
@ -10632,6 +10734,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Credit object" description: "Returns the Credit object"
@ -11142,7 +11261,7 @@ paths:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/payments/{id}/upload": "/api/v1/payments/{id}/upload":
put: post:
tags: tags:
- payments - payments
summary: "Upload a payment document" summary: "Upload a payment document"
@ -11160,6 +11279,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Payment object" description: "Returns the Payment object"
@ -12400,7 +12536,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/recurring_invoices/{id}/upload": "/api/v1/recurring_invoices/{id}/upload":
put: post:
tags: tags:
- Recurring Invoices - Recurring Invoices
summary: "Add recurring invoice document" summary: "Add recurring invoice document"
@ -12418,6 +12554,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the RecurringInvoice object" description: "Returns the RecurringInvoice object"
@ -12929,7 +13082,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/quotes/{id}/upload": "/api/v1/quotes/{id}/upload":
put: post:
tags: tags:
- quotes - quotes
summary: "Upload a quote document" summary: "Upload a quote document"
@ -12947,6 +13100,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Quote object" description: "Returns the Quote object"
@ -13367,7 +13537,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/purchase_orders/{id}/upload": "/api/v1/purchase_orders/{id}/upload":
put: post:
tags: tags:
- Purchase Orders - Purchase Orders
summary: "Uploads a purchase order document" summary: "Uploads a purchase order document"
@ -13385,6 +13555,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Purchase Order object" description: "Returns the Purchase Order object"
@ -13794,7 +13981,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/vendors/{id}/upload": "/api/v1/vendors/{id}/upload":
put: post:
tags: tags:
- vendors - vendors
summary: "Uploads a vendor document" summary: "Uploads a vendor document"
@ -13812,6 +13999,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Vendor object" description: "Returns the Vendor object"
@ -20666,27 +20870,31 @@ components:
id: id:
description: 'The expense hashed id' description: 'The expense hashed id'
type: string type: string
example: Opnel5aKBz example: 'Opnel5aKBz'
user_id: user_id:
description: 'The user hashed id' description: 'The user hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
assigned_user_id: assigned_user_id:
description: 'The assigned user hashed id' description: 'The assigned user hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
project_id:
description: 'The associated project_id'
type: string
example: 'Opnel5aKBz'
company_id: company_id:
description: 'The company hashed id' description: 'The company hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
client_id: client_id:
description: 'The client hashed id' description: 'The client hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
invoice_id: invoice_id:
description: 'The related invoice hashed id' description: 'The related invoice hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
bank_id: bank_id:
description: 'The bank id related to this expense' description: 'The bank id related to this expense'
type: string type: string
@ -20694,15 +20902,15 @@ components:
invoice_currency_id: invoice_currency_id:
description: 'The currency id of the related invoice' description: 'The currency id of the related invoice'
type: string type: string
example: '' example: '1'
expense_currency_id: expense_currency_id:
description: 'The currency id of the expense' description: 'The currency id of the expense'
type: string type: string
example: '' example: '2'
invoice_category_id: invoice_category_id:
description: 'The invoice category id' description: 'The invoice category id'
type: string type: string
example: '' example: 'Opnel5aKBz'
payment_type_id: payment_type_id:
description: 'The payment type id' description: 'The payment type id'
type: string type: string
@ -20710,7 +20918,7 @@ components:
recurring_expense_id: recurring_expense_id:
description: 'The related recurring expense this expense was created from' description: 'The related recurring expense this expense was created from'
type: string type: string
example: '' example: 'Opnel5aKBz'
private_notes: private_notes:
description: 'The private notes of the expense' description: 'The private notes of the expense'
type: string type: string
@ -20743,30 +20951,34 @@ components:
description: 'A custom value' description: 'A custom value'
type: string type: string
example: '' example: ''
tax_amount:
description: 'The tax amount'
type: number
example: 10.00
tax_name1: tax_name1:
description: 'Tax name' description: 'Tax Name 1'
type: string type: string
example: '' example: 'GST'
tax_name2: tax_name2:
description: 'Tax name' description: 'Tax Name 2'
type: string type: string
example: '' example: 'VAT'
tax_name3:
description: 'Tax Name 3'
type: string
example: 'IVA'
tax_rate1: tax_rate1:
description: 'Tax rate' description: 'Tax rate 1'
type: number type: number
format: float format: float
example: '10.00' example: '10.00'
tax_rate2: tax_rate2:
description: 'Tax rate' description: 'Tax rate 2'
type: number type: number
format: float format: float
example: '10.00' example: '10.00'
tax_name3:
description: 'Tax name'
type: string
example: ''
tax_rate3: tax_rate3:
description: 'Tax rate' description: 'Tax rate 3'
type: number type: number
format: float format: float
example: '10.00' example: '10.00'
@ -20786,13 +20998,13 @@ components:
format: float format: float
example: '0.80' example: '0.80'
date: date:
description: 'The expense date formate Y-m-d' description: 'The expense date format Y-m-d'
type: string type: string
example: '2022-12-01' example: '2022-12-01'
payment_date: payment_date:
description: 'The date of payment for the expense, format Y-m-d' description: 'The date of payment for the expense, format Y-m-d'
type: string type: string
example: '' example: '2022-12-01'
should_be_invoiced: should_be_invoiced:
description: 'Flag whether the expense should be invoiced' description: 'Flag whether the expense should be invoiced'
type: boolean type: boolean

View File

@ -3,27 +3,31 @@
id: id:
description: 'The expense hashed id' description: 'The expense hashed id'
type: string type: string
example: Opnel5aKBz example: 'Opnel5aKBz'
user_id: user_id:
description: 'The user hashed id' description: 'The user hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
assigned_user_id: assigned_user_id:
description: 'The assigned user hashed id' description: 'The assigned user hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
project_id:
description: 'The associated project_id'
type: string
example: 'Opnel5aKBz'
company_id: company_id:
description: 'The company hashed id' description: 'The company hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
client_id: client_id:
description: 'The client hashed id' description: 'The client hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
invoice_id: invoice_id:
description: 'The related invoice hashed id' description: 'The related invoice hashed id'
type: string type: string
example: '' example: 'Opnel5aKBz'
bank_id: bank_id:
description: 'The bank id related to this expense' description: 'The bank id related to this expense'
type: string type: string
@ -31,15 +35,15 @@
invoice_currency_id: invoice_currency_id:
description: 'The currency id of the related invoice' description: 'The currency id of the related invoice'
type: string type: string
example: '' example: '1'
expense_currency_id: expense_currency_id:
description: 'The currency id of the expense' description: 'The currency id of the expense'
type: string type: string
example: '' example: '2'
invoice_category_id: invoice_category_id:
description: 'The invoice category id' description: 'The invoice category id'
type: string type: string
example: '' example: 'Opnel5aKBz'
payment_type_id: payment_type_id:
description: 'The payment type id' description: 'The payment type id'
type: string type: string
@ -47,7 +51,7 @@
recurring_expense_id: recurring_expense_id:
description: 'The related recurring expense this expense was created from' description: 'The related recurring expense this expense was created from'
type: string type: string
example: '' example: 'Opnel5aKBz'
private_notes: private_notes:
description: 'The private notes of the expense' description: 'The private notes of the expense'
type: string type: string
@ -80,30 +84,34 @@
description: 'A custom value' description: 'A custom value'
type: string type: string
example: '' example: ''
tax_amount:
description: 'The tax amount'
type: number
example: 10.00
tax_name1: tax_name1:
description: 'Tax name' description: 'Tax Name 1'
type: string type: string
example: '' example: 'GST'
tax_name2: tax_name2:
description: 'Tax name' description: 'Tax Name 2'
type: string type: string
example: '' example: 'VAT'
tax_name3:
description: 'Tax Name 3'
type: string
example: 'IVA'
tax_rate1: tax_rate1:
description: 'Tax rate' description: 'Tax rate 1'
type: number type: number
format: float format: float
example: '10.00' example: '10.00'
tax_rate2: tax_rate2:
description: 'Tax rate' description: 'Tax rate 2'
type: number type: number
format: float format: float
example: '10.00' example: '10.00'
tax_name3:
description: 'Tax name'
type: string
example: ''
tax_rate3: tax_rate3:
description: 'Tax rate' description: 'Tax rate 3'
type: number type: number
format: float format: float
example: '10.00' example: '10.00'
@ -123,13 +131,13 @@
format: float format: float
example: '0.80' example: '0.80'
date: date:
description: 'The expense date formate Y-m-d' description: 'The expense date format Y-m-d'
type: string type: string
example: '2022-12-01' example: '2022-12-01'
payment_date: payment_date:
description: 'The date of payment for the expense, format Y-m-d' description: 'The date of payment for the expense, format Y-m-d'
type: string type: string
example: '' example: '2022-12-01'
should_be_invoiced: should_be_invoiced:
description: 'Flag whether the expense should be invoiced' description: 'Flag whether the expense should be invoiced'
type: boolean type: boolean

View File

@ -1865,7 +1865,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/companies/{id}/upload": "/api/v1/companies/{id}/upload":
put: post:
tags: tags:
- companies - companies
summary: "Uploads a document to a company" summary: "Uploads a document to a company"
@ -1883,6 +1883,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the client object" description: "Returns the client object"
@ -3405,7 +3422,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/expenses/{id}/upload": "/api/v1/expenses/{id}/upload":
put: post:
tags: tags:
- expense - expense
summary: "Uploads a document to a expense" summary: "Uploads a document to a expense"
@ -3423,6 +3440,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Expense object" description: "Returns the Expense object"
@ -3777,7 +3811,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/group_settings/{id}/upload": "/api/v1/group_settings/{id}/upload":
put: post:
tags: tags:
- group_settings - group_settings
summary: "Uploads a document to a group setting" summary: "Uploads a document to a group setting"
@ -3795,6 +3829,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Group Setting object" description: "Returns the Group Setting object"
@ -4902,7 +4953,7 @@ paths:
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/recurring_expenses/{id}/upload": "/api/v1/recurring_expenses/{id}/upload":
put: post:
tags: tags:
- recurring_expense - recurring_expense
summary: "Uploads a document to a recurring_expense" summary: "Uploads a document to a recurring_expense"
@ -4920,6 +4971,23 @@ paths:
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the RecurringExpense object" description: "Returns the RecurringExpense object"

View File

@ -438,7 +438,7 @@
default: default:
$ref: '#/components/responses/default' $ref: '#/components/responses/default'
'/api/v1/clients/{id}/upload': '/api/v1/clients/{id}/upload':
put: post:
tags: tags:
- clients - clients
summary: 'Add client document' summary: 'Add client document'

View File

@ -385,7 +385,7 @@
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/credits/{id}/upload": "/api/v1/credits/{id}/upload":
put: post:
tags: tags:
- credits - credits
summary: "Upload a credit document" summary: "Upload a credit document"
@ -403,6 +403,23 @@
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Credit object" description: "Returns the Credit object"

View File

@ -482,7 +482,7 @@
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/payments/{id}/upload": "/api/v1/payments/{id}/upload":
put: post:
tags: tags:
- payments - payments
summary: "Upload a payment document" summary: "Upload a payment document"
@ -500,6 +500,23 @@
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Payment object" description: "Returns the Payment object"

View File

@ -382,7 +382,7 @@
$ref: '#/components/responses/default' $ref: '#/components/responses/default'
"/api/v1/products/{id}/upload": "/api/v1/products/{id}/upload":
put: post:
tags: tags:
- products - products
summary: "Add product document" summary: "Add product document"

View File

@ -340,7 +340,7 @@
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/projects/{id}/upload": "/api/v1/projects/{id}/upload":
put: post:
tags: tags:
- projects - projects
summary: "Uploads a project document" summary: "Uploads a project document"
@ -358,6 +358,23 @@
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Project object" description: "Returns the Project object"

View File

@ -392,7 +392,7 @@
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/purchase_orders/{id}/upload": "/api/v1/purchase_orders/{id}/upload":
put: post:
tags: tags:
- Purchase Orders - Purchase Orders
summary: "Uploads a purchase order document" summary: "Uploads a purchase order document"
@ -410,6 +410,23 @@
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Purchase Order object" description: "Returns the Purchase Order object"

View File

@ -483,7 +483,7 @@
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/quotes/{id}/upload": "/api/v1/quotes/{id}/upload":
put: post:
tags: tags:
- quotes - quotes
summary: "Upload a quote document" summary: "Upload a quote document"
@ -501,6 +501,23 @@
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Quote object" description: "Returns the Quote object"

View File

@ -499,7 +499,7 @@
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/recurring_invoices/{id}/upload": "/api/v1/recurring_invoices/{id}/upload":
put: post:
tags: tags:
- Recurring Invoices - Recurring Invoices
summary: "Add recurring invoice document" summary: "Add recurring invoice document"
@ -517,6 +517,23 @@
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the RecurringInvoice object" description: "Returns the RecurringInvoice object"

View File

@ -340,7 +340,7 @@
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/tasks/{id}/upload": "/api/v1/tasks/{id}/upload":
put: post:
tags: tags:
- tasks - tasks
summary: "Uploads a task document" summary: "Uploads a task document"
@ -358,6 +358,23 @@
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Task object" description: "Returns the Task object"

View File

@ -340,7 +340,7 @@
default: default:
$ref: "#/components/responses/default" $ref: "#/components/responses/default"
"/api/v1/vendors/{id}/upload": "/api/v1/vendors/{id}/upload":
put: post:
tags: tags:
- vendors - vendors
summary: "Uploads a vendor document" summary: "Uploads a vendor document"
@ -358,6 +358,23 @@
type: string type: string
format: string format: string
example: D2J234DFA example: D2J234DFA
requestBody:
description: "File Upload Body"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
_method:
type: string
example: PUT
documents:
type: array
items:
description: "Array of binary documents for upload"
type: string
format: binary
responses: responses:
200: 200:
description: "Returns the Vendor object" description: "Returns the Vendor object"