From f5e582f75bb486ad08f227468cb34a5e5d19b2f9 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 08:00:40 +1100 Subject: [PATCH 01/32] Hide pre payments --- app/Http/ViewComposers/PortalComposer.php | 4 ++-- app/PaymentDrivers/GoCardlessPaymentDriver.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Http/ViewComposers/PortalComposer.php b/app/Http/ViewComposers/PortalComposer.php index 3e796d110b5b..747cc9572adb 100644 --- a/app/Http/ViewComposers/PortalComposer.php +++ b/app/Http/ViewComposers/PortalComposer.php @@ -138,9 +138,9 @@ class PortalComposer $data[] = ['title' => ctrans('texts.subscriptions'), 'url' => 'client.subscriptions.index', 'icon' => 'calendar']; } - // if(property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) { + if(property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) { $data[] = ['title' => ctrans('texts.pre_payment'), 'url' => 'client.pre_payments.index', 'icon' => 'dollar-sign']; - // } + } return $data; } diff --git a/app/PaymentDrivers/GoCardlessPaymentDriver.php b/app/PaymentDrivers/GoCardlessPaymentDriver.php index 6aad29ac375c..6b99492148c5 100644 --- a/app/PaymentDrivers/GoCardlessPaymentDriver.php +++ b/app/PaymentDrivers/GoCardlessPaymentDriver.php @@ -83,7 +83,7 @@ class GoCardlessPaymentDriver extends BaseDriver $types[] = GatewayType::DIRECT_DEBIT; } - if ($this->client->currency()->code === 'EUR') { + if (in_array($this->client->currency()->code, ['EUR'])) { $types[] = GatewayType::SEPA; } From 9ca10fadb35d94a67527469806fc2d71bb42a86e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 09:56:03 +1100 Subject: [PATCH 02/32] Minor changes for GoCardless --- app/Models/Client.php | 4 ++-- app/Models/Presenters/ClientPresenter.php | 6 +++--- app/PaymentDrivers/GoCardless/DirectDebit.php | 14 +++++++++++++- app/PaymentDrivers/GoCardless/SEPA.php | 12 ++++++------ app/PaymentDrivers/GoCardlessPaymentDriver.php | 5 +++-- app/Services/Client/PaymentMethod.php | 2 +- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/app/Models/Client.php b/app/Models/Client.php index a58d7fb450c0..644124f4e70e 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -666,7 +666,7 @@ class Client extends BaseModel implements HasLocalePreference } } - if ($this->country && $this->country->iso_3166_3 == 'GBR' && in_array(GatewayType::DIRECT_DEBIT, array_column($pms, 'gateway_type_id'))) { + if (in_array(GatewayType::DIRECT_DEBIT, array_column($pms, 'gateway_type_id'))) { foreach ($pms as $pm) { if ($pm['gateway_type_id'] == GatewayType::DIRECT_DEBIT) { $cg = CompanyGateway::find($pm['company_gateway_id']); @@ -691,7 +691,7 @@ class Client extends BaseModel implements HasLocalePreference return GatewayType::SEPA; } - if ($this->currency()->code == 'GBP') { + if (in_array($this->currency()->code, ['EUR', 'GBP','DKK','SEK','AUD','NZD','USD'])) { return GatewayType::DIRECT_DEBIT; } } diff --git a/app/Models/Presenters/ClientPresenter.php b/app/Models/Presenters/ClientPresenter.php index 4a42cd2c1510..b0c30b107807 100644 --- a/app/Models/Presenters/ClientPresenter.php +++ b/app/Models/Presenters/ClientPresenter.php @@ -42,17 +42,17 @@ class ClientPresenter extends EntityPresenter public function first_name() { - return $this->entity->primary_contact->first() !== null ? $this->entity->primary_contact->first()->first_name : $this->entity->contacts()->first()->first_name; + return $this->entity->primary_contact()->first()?->first_name ?: ($this->entity->contacts()->first()->first_name ?: ''); } public function last_name() { - return $this->entity->primary_contact->first() !== null ? $this->entity->primary_contact->first()->last_name : $this->entity->contacts()->first()->last_name; + return $this->entity->primary_contact()->first()?->last_name ?: ($this->entity->contacts()->first()->last_name ?: ''); } public function primary_contact_name() { - return $this->entity->primary_contact->first() !== null ? $this->entity->primary_contact->first()->first_name.' '.$this->entity->primary_contact->first()->last_name : 'No primary contact set'; + return $this->entity?->primary_contact()?->first() ? $this->entity->primary_contact()->first()->first_name.' '.$this->entity->primary_contact()->first()->last_name : 'No primary contact set'; } public function email() diff --git a/app/PaymentDrivers/GoCardless/DirectDebit.php b/app/PaymentDrivers/GoCardless/DirectDebit.php index edb853ba3d85..2fec81223f84 100644 --- a/app/PaymentDrivers/GoCardless/DirectDebit.php +++ b/app/PaymentDrivers/GoCardless/DirectDebit.php @@ -67,6 +67,7 @@ class DirectDebit implements MethodInterface 'address_line1' => auth()->guard('contact')->user()->client->address1 ?: '', 'city' => auth()->guard('contact')->user()->client->city ?: '', 'postal_code' => auth()->guard('contact')->user()->client->postal_code ?: '', + 'country_code' => auth()->guard('contact')->user()->client->country->iso_3166_2, ], ], ]); @@ -124,7 +125,7 @@ class DirectDebit implements MethodInterface $data = [ 'payment_meta' => $payment_meta, 'token' => $redirect_flow->links->mandate, - 'payment_method_id' => GatewayType::DIRECT_DEBIT, + 'payment_method_id' => $this->resolveScheme($redirect_flow->scheme), ]; $payment_method = $this->go_cardless->storeGatewayToken($data, ['gateway_customer_reference' => $redirect_flow->links->customer]); @@ -135,6 +136,17 @@ class DirectDebit implements MethodInterface } } + private function resolveScheme(string $scheme): int + { + match($scheme){ + 'sepa_core' => $type = GatewayType::SEPA, + default => $type = GatewayType::DIRECT_DEBIT, + }; + + return $type; + } + + /** * Payment view for Direct Debit. * diff --git a/app/PaymentDrivers/GoCardless/SEPA.php b/app/PaymentDrivers/GoCardless/SEPA.php index df92a500b3a6..c4950314d491 100644 --- a/app/PaymentDrivers/GoCardless/SEPA.php +++ b/app/PaymentDrivers/GoCardless/SEPA.php @@ -62,12 +62,12 @@ class SEPA implements MethodInterface 'session_token' => $session_token, ]), 'prefilled_customer' => [ - 'given_name' => auth()->guard('contact')->user()->first_name, - 'family_name' => auth()->guard('contact')->user()->last_name, - 'email' => auth()->guard('contact')->user()->email, - 'address_line1' => auth()->guard('contact')->user()->client->address1, - 'city' => auth()->guard('contact')->user()->client->city, - 'postal_code' => auth()->guard('contact')->user()->client->postal_code, + 'given_name' => auth()->guard('contact')->user()->client->present()->first_name(), + 'family_name' => auth()->guard('contact')->user()->client->present()->last_name(), + 'email' => auth()->guard('contact')->user()->client->present()->email(), + 'address_line1' => auth()->guard('contact')->user()->client->address1 ?: '', + 'city' => auth()->guard('contact')->user()->client->city ?: '', + 'postal_code' => auth()->guard('contact')->user()->client->postal_code ?: '', ], ], ]); diff --git a/app/PaymentDrivers/GoCardlessPaymentDriver.php b/app/PaymentDrivers/GoCardlessPaymentDriver.php index 6b99492148c5..91d845997a3f 100644 --- a/app/PaymentDrivers/GoCardlessPaymentDriver.php +++ b/app/PaymentDrivers/GoCardlessPaymentDriver.php @@ -78,12 +78,13 @@ class GoCardlessPaymentDriver extends BaseDriver if ( $this->client && isset($this->client->country) - && in_array($this->client->country->iso_3166_3, ['GBR']) + // && in_array($this->client->country->iso_3166_3, ['GBR']) + && in_array($this->client->currency()->code, ['EUR', 'GBP','DKK','SEK','AUD','NZD','USD']) ) { $types[] = GatewayType::DIRECT_DEBIT; } - if (in_array($this->client->currency()->code, ['EUR'])) { + if (in_array($this->client->currency()->code, ['EUR', 'GBP'])) { $types[] = GatewayType::SEPA; } diff --git a/app/Services/Client/PaymentMethod.php b/app/Services/Client/PaymentMethod.php index 8f095ea22fa3..7f7d6c4933bc 100644 --- a/app/Services/Client/PaymentMethod.php +++ b/app/Services/Client/PaymentMethod.php @@ -197,7 +197,7 @@ class PaymentMethod 'gateway_type_id' => GatewayType::CREDIT, ]; } - + return $this; } From 97f7f16f7c2fd21f51c6063659e33ac38c4d0f0c Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 10:03:20 +1100 Subject: [PATCH 03/32] Catch all logo --- app/Services/Pdf/PdfMock.php | 2 +- resources/views/portal/ninja2020/generic/error.blade.php | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/Services/Pdf/PdfMock.php b/app/Services/Pdf/PdfMock.php index 510508b4bdb9..dd92e8a8a920 100644 --- a/app/Services/Pdf/PdfMock.php +++ b/app/Services/Pdf/PdfMock.php @@ -421,7 +421,7 @@ class PdfMock '$country_2' => 'AF', '$firstName' => 'Benedict', '$user.name' => 'Derrick Monahan DDS Erna Wunsch', - '$font_name' => $this->settings?->primary_font ?: 'Roboto', + '$font_name' => isset($this->settings?->primary_font) ? $this->settings?->primary_font : 'Roboto', '$auto_bill' => 'This invoice will automatically be billed to your credit card on file on the due date.', '$payments' => '', '$task.tax' => '', diff --git a/resources/views/portal/ninja2020/generic/error.blade.php b/resources/views/portal/ninja2020/generic/error.blade.php index 422bd36e682d..3eda46a72858 100644 --- a/resources/views/portal/ninja2020/generic/error.blade.php +++ b/resources/views/portal/ninja2020/generic/error.blade.php @@ -12,11 +12,16 @@ Invoice Ninja logo - @else + @elseif($company)
{{ $company->present()->name() }} logo
+ @else +
+ Invoice Ninja logo +
@endif

{{ $title }}

From 448a13947533da02075234806f79476cce3eb2e0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 10:07:02 +1100 Subject: [PATCH 04/32] Updates for favicon --- resources/views/layouts/guest.blade.php | 4 ++- resources/views/layouts/master.blade.php | 26 +++---------------- .../portal/ninja2020/layout/clean.blade.php | 2 ++ .../ninja2020/layout/clean_setup.blade.php | 3 +++ .../views/themes/ninja2020/clean.blade.php | 2 ++ 5 files changed, 13 insertions(+), 24 deletions(-) diff --git a/resources/views/layouts/guest.blade.php b/resources/views/layouts/guest.blade.php index 6db093859999..7447cfb82f88 100644 --- a/resources/views/layouts/guest.blade.php +++ b/resources/views/layouts/guest.blade.php @@ -28,8 +28,10 @@ @yield('meta_title', 'Invoice Ninja') | {{ config('app.name') }} - + @if(auth()->guard('contact')->user() && !auth()->guard('contact')->user()->user->account->isPaid()) + + @endif diff --git a/resources/views/layouts/master.blade.php b/resources/views/layouts/master.blade.php index e4aef481b2e3..ac7a393cadb0 100644 --- a/resources/views/layouts/master.blade.php +++ b/resources/views/layouts/master.blade.php @@ -28,29 +28,9 @@ @yield('meta_title', 'Invoice Ninja') | {{ config('app.name') }} - - - - + @if(auth()->guard('contact')->user() && !auth()->guard('contact')->user()->user->account->isPaid()) + + @endif diff --git a/resources/views/portal/ninja2020/layout/clean.blade.php b/resources/views/portal/ninja2020/layout/clean.blade.php index 17ee40e4947f..805429cb1ed0 100644 --- a/resources/views/portal/ninja2020/layout/clean.blade.php +++ b/resources/views/portal/ninja2020/layout/clean.blade.php @@ -91,7 +91,9 @@ + @if(auth()->guard('contact')->user() && !auth()->guard('contact')->user()->user->account->isPaid()) {{-- --}} + @endif diff --git a/resources/views/portal/ninja2020/layout/clean_setup.blade.php b/resources/views/portal/ninja2020/layout/clean_setup.blade.php index a6781bd4fbc9..2083e6ff5b0a 100644 --- a/resources/views/portal/ninja2020/layout/clean_setup.blade.php +++ b/resources/views/portal/ninja2020/layout/clean_setup.blade.php @@ -89,7 +89,10 @@ @else @endif + + @if(auth()->guard('contact')->user() && !auth()->guard('contact')->user()->user->account->isPaid()) {{-- --}} + @endif diff --git a/resources/views/themes/ninja2020/clean.blade.php b/resources/views/themes/ninja2020/clean.blade.php index f58c8f7ffab1..66ac3ebda118 100644 --- a/resources/views/themes/ninja2020/clean.blade.php +++ b/resources/views/themes/ninja2020/clean.blade.php @@ -78,7 +78,9 @@ + @if(auth()->guard('contact')->user() && !auth()->guard('contact')->user()->user->account->isPaid()) {{-- --}} + @endif From f5a5946cb7f3d5c2483625085a84a69f2cc9fe2b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 18:13:49 +1100 Subject: [PATCH 05/32] Fixes for invoice filters - overdue --- app/Filters/InvoiceFilters.php | 1 - app/Http/Livewire/BillingPortalPurchasev2.php | 8 +-- app/PaymentDrivers/CustomPaymentDriver.php | 59 ++++++++++++++++++- .../billing-portal-purchasev2.blade.php | 18 ++++-- .../gateways/custom/payment.blade.php | 25 +++++++- 5 files changed, 99 insertions(+), 12 deletions(-) diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index 81f3e6db68dd..cafeee6ab5e7 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -69,7 +69,6 @@ class InvoiceFilters extends QueryFilters if (in_array('overdue', $status_parameters)) { $query->orWhereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) ->where('due_date', '<', Carbon::now()) - ->orWhere('due_date', null) ->orWhere('partial_due_date', '<', Carbon::now()); } }); diff --git a/app/Http/Livewire/BillingPortalPurchasev2.php b/app/Http/Livewire/BillingPortalPurchasev2.php index 612dfd5b8209..f3f0a3b132a7 100644 --- a/app/Http/Livewire/BillingPortalPurchasev2.php +++ b/app/Http/Livewire/BillingPortalPurchasev2.php @@ -311,7 +311,7 @@ class BillingPortalPurchasev2 extends Component 'description' => $p->notes, 'product_key' => $p->product_key, 'unit_cost' => $p->price, - 'product' => nl2br(substr($p->notes, 0, 50)), + 'product' => substr(strip_tags($p->markdownNotes()), 0, 50), 'price' => Number::formatMoney($total, $this->subscription->company).' / '. RecurringInvoice::frequencyForKey($this->subscription->frequency_id), 'total' => $total, 'qty' => $qty, @@ -329,7 +329,7 @@ class BillingPortalPurchasev2 extends Component 'description' => $p->notes, 'product_key' => $p->product_key, 'unit_cost' => $p->price, - 'product' => nl2br(substr($p->notes, 0, 50)), + 'product' => substr(strip_tags($p->markdownNotes()), 0, 50), 'price' => Number::formatMoney($total, $this->subscription->company), 'total' => $total, 'qty' => $qty, @@ -352,7 +352,7 @@ class BillingPortalPurchasev2 extends Component 'description' => $p->notes, 'product_key' => $p->product_key, 'unit_cost' => $p->price, - 'product' => nl2br(substr($p->notes, 0, 50)), + 'product' => substr(strip_tags($p->markdownNotes()), 0, 50), 'price' => Number::formatMoney($total, $this->subscription->company).' / '. RecurringInvoice::frequencyForKey($this->subscription->frequency_id), 'total' => $total, 'qty' => $qty, @@ -375,7 +375,7 @@ class BillingPortalPurchasev2 extends Component 'description' => $p->notes, 'product_key' => $p->product_key, 'unit_cost' => $p->price, - 'product' => nl2br(substr($p->notes, 0, 50)), + 'product' => substr(strip_tags($p->markdownNotes()), 0, 50), 'price' => Number::formatMoney($total, $this->subscription->company), 'total' => $total, 'qty' => $qty, diff --git a/app/PaymentDrivers/CustomPaymentDriver.php b/app/PaymentDrivers/CustomPaymentDriver.php index 6cc437e53494..a99bdd4123fe 100644 --- a/app/PaymentDrivers/CustomPaymentDriver.php +++ b/app/PaymentDrivers/CustomPaymentDriver.php @@ -12,12 +12,16 @@ namespace App\PaymentDrivers; -use App\Models\ClientGatewayToken; -use App\Models\GatewayType; use App\Models\Invoice; use App\Models\Payment; +use App\Models\SystemLog; use App\Utils\HtmlEngine; +use App\Models\GatewayType; +use App\Models\PaymentHash; +use App\Models\PaymentType; +use App\Jobs\Util\SystemLogger; use App\Utils\Traits\MakesHash; +use App\Models\ClientGatewayToken; /** * Class CustomPaymentDriver. @@ -81,6 +85,7 @@ class CustomPaymentDriver extends BaseDriver $this->payment_hash->save(); $data['gateway'] = $this; + $data['payment_hash'] = $this->payment_hash->hash; return render('gateways.custom.payment', $data); } @@ -92,6 +97,56 @@ class CustomPaymentDriver extends BaseDriver */ public function processPaymentResponse($request) { + + if ($request->has('gateway_response')) { + + $this->client = auth()->guard('contact')->user()->client; + + $state = [ + 'server_response' => json_decode($request->gateway_response), + 'payment_hash' => $request->payment_hash, + ]; + + $payment_hash = PaymentHash::where('hash', $request->payment_hash)->first(); + + if($payment_hash) + { + $this->payment_hash = $payment_hash; + + $payment_hash->data = array_merge((array) $payment_hash->data, $state); + $payment_hash->save(); + } + + $gateway_response = json_decode($request->gateway_response); + + if ($gateway_response->status == 'COMPLETED') { + $this->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $payment_hash], SystemLog::TYPE_CUSTOM); + + $data = [ + 'payment_method' => '', + 'payment_type' => PaymentType::CREDIT_CARD_OTHER, + 'amount' => $payment_hash->amount_with_fee(), + 'transaction_reference' => $gateway_response?->purchase_units[0]?->payments?->captures[0]?->id, + 'gateway_type_id' => GatewayType::PAYPAL, + ]; + + $payment = $this->createPayment($data, Payment::STATUS_COMPLETED); + + SystemLogger::dispatch( + ['response' => $payment_hash->data->server_response, 'data' => $data], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_STRIPE, + $this->client, + $this->client->company, + ); + + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); + + } + } + + return redirect()->route('client.invoices'); } diff --git a/resources/views/portal/ninja2020/components/livewire/billing-portal-purchasev2.blade.php b/resources/views/portal/ninja2020/components/livewire/billing-portal-purchasev2.blade.php index d3417dded2f0..82dc46a03241 100644 --- a/resources/views/portal/ninja2020/components/livewire/billing-portal-purchasev2.blade.php +++ b/resources/views/portal/ninja2020/components/livewire/billing-portal-purchasev2.blade.php @@ -107,7 +107,9 @@

- {!! nl2br($product->markdownNotes()) !!} +
+ {!! $product->markdownNotes() !!} +

{{ \App\Utils\Number::formatMoney($product->price, $subscription->company) }}

@@ -145,7 +147,11 @@
-

{!! nl2br($product->markdownNotes()) !!}

+

+
+ {!! $product->markdownNotes() !!} +
+

{{ \App\Utils\Number::formatMoney($product->price, $subscription->company) }} / {{ App\Models\RecurringInvoice::frequencyForKey($subscription->frequency_id) }}

@@ -186,7 +192,11 @@
-

{!! nl2br($product->markdownNotes()) !!}

+

+
+ {!! $product->markdownNotes() !!} +
+

{{ \App\Utils\Number::formatMoney($product->price, $subscription->company) }}

@@ -234,7 +244,7 @@ @foreach($bundle->toArray() as $item)
- {{ $item['qty'] }} x {{ substr(str_replace(["\r","\n","
","
","
","
"]," ", $item['product']), 0, 30) . "..." }}
+ {{ $item['qty'] }} x {{ $item['product'] }} {{ $item['price'] }}
@endforeach diff --git a/resources/views/portal/ninja2020/gateways/custom/payment.blade.php b/resources/views/portal/ninja2020/gateways/custom/payment.blade.php index d337c71897d9..42373e59628f 100644 --- a/resources/views/portal/ninja2020/gateways/custom/payment.blade.php +++ b/resources/views/portal/ninja2020/gateways/custom/payment.blade.php @@ -1,7 +1,15 @@ @extends('portal.ninja2020.layout.payments', ['gateway_title' => $title, 'card_title' => $title]) @section('gateway_content') - @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')]) +
+ @csrf + + + + + +
+@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')]) {{ $title }} @endcomponent @@ -11,3 +19,18 @@ {!! nl2br($instructions) !!} @endcomponent @endsection + \ No newline at end of file From 5a42b89d551a6df71a502fd6800c980009051cc2 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 18:24:56 +1100 Subject: [PATCH 06/32] cs fixer --- app/Console/Commands/BackupUpdate.php | 2 - app/Console/Commands/CheckData.php | 58 ++- app/DataMapper/ClientSettings.php | 4 +- app/DataMapper/Schedule/ScheduleInvoice.php | 1 - app/Events/Client/ClientWasArchived.php | 1 - app/Events/Invoice/InvoiceWasCreated.php | 4 +- app/Export/CSV/BaseExport.php | 3 +- app/Export/CSV/ProductSalesExport.php | 54 +- app/Filters/CreditFilters.php | 4 +- app/Filters/InvoiceFilters.php | 4 +- app/Filters/PaymentFilters.php | 2 +- app/Filters/PurchaseOrderFilters.php | 6 +- app/Filters/QuoteFilters.php | 6 +- app/Http/Controllers/Auth/LoginController.php | 2 +- .../Controllers/BankTransactionController.php | 1 - .../ClientPortal/PaymentController.php | 27 +- .../ClientPortal/PaymentMethodController.php | 1 - .../ClientPortal/PrePaymentController.php | 18 +- .../SubscriptionPurchaseController.php | 1 - app/Http/Controllers/CompanyController.php | 56 +-- app/Http/Controllers/EmailController.php | 32 +- app/Http/Controllers/ImportController.php | 6 +- app/Http/Controllers/LicenseController.php | 18 +- app/Http/Controllers/PreviewController.php | 2 - .../RecurringInvoiceController.php | 35 +- .../Controllers/TaskSchedulerController.php | 2 +- app/Http/Controllers/WebhookController.php | 26 +- app/Http/Livewire/BillingPortalPurchase.php | 28 +- app/Http/Livewire/BillingPortalPurchasev2.php | 4 +- app/Http/Livewire/RequiredClientInfo.php | 3 +- .../UploadBankIntegrationRequest.php | 5 +- .../UploadBankTransactionRequest.php | 5 +- .../Requests/Client/StoreClientRequest.php | 5 +- .../Requests/Client/UpdateClientRequest.php | 5 +- .../Requests/Client/UploadClientRequest.php | 5 +- .../PrePayments/StorePrePaymentRequest.php | 2 - .../Requests/Company/UploadCompanyRequest.php | 5 +- .../Requests/Credit/StoreCreditRequest.php | 5 +- .../Requests/Credit/UpdateCreditRequest.php | 5 +- .../Requests/Credit/UploadCreditRequest.php | 5 +- .../Requests/Expense/UploadExpenseRequest.php | 5 +- .../UploadGroupSettingRequest.php | 5 +- .../Requests/Invoice/StoreInvoiceRequest.php | 5 +- .../Requests/Invoice/UpdateInvoiceRequest.php | 5 +- .../Requests/Invoice/UploadInvoiceRequest.php | 6 +- .../Requests/Payment/StorePaymentRequest.php | 5 +- .../Requests/Payment/UpdatePaymentRequest.php | 5 +- .../Requests/Payment/UploadPaymentRequest.php | 5 +- .../Preview/PreviewInvoiceRequest.php | 4 - .../Preview/PreviewPurchaseOrderRequest.php | 1 - .../Requests/Product/StoreProductRequest.php | 5 +- .../Requests/Product/UpdateProductRequest.php | 6 +- .../Requests/Product/UploadProductRequest.php | 5 +- .../Requests/Project/CreateProjectRequest.php | 3 +- .../Requests/Project/ShowProjectRequest.php | 1 - .../Requests/Project/StoreProjectRequest.php | 5 +- .../Requests/Project/UpdateProjectRequest.php | 5 +- .../Requests/Project/UploadProjectRequest.php | 5 +- .../StorePurchaseOrderRequest.php | 5 +- .../UpdatePurchaseOrderRequest.php | 5 +- .../UploadPurchaseOrderRequest.php | 5 +- app/Http/Requests/Quote/StoreQuoteRequest.php | 5 +- .../Requests/Quote/UpdateQuoteRequest.php | 5 +- .../Requests/Quote/UploadQuoteRequest.php | 5 +- .../StoreRecurringExpenseRequest.php | 5 +- .../UpdateRecurringExpenseRequest.php | 5 +- .../UploadRecurringExpenseRequest.php | 5 +- .../StoreRecurringInvoiceRequest.php | 5 +- .../UpdateRecurringInvoiceRequest.php | 5 +- .../UploadRecurringInvoiceRequest.php | 5 +- .../StoreRecurringQuoteRequest.php | 5 +- .../UpdateRecurringQuoteRequest.php | 5 +- .../UploadRecurringQuoteRequest.php | 5 +- .../Requests/Report/GenericReportRequest.php | 1 - app/Http/Requests/Task/StoreTaskRequest.php | 5 +- app/Http/Requests/Task/UpdateTaskRequest.php | 5 +- .../User/DetachCompanyUserRequest.php | 2 - .../Requests/Vendor/StoreVendorRequest.php | 6 +- .../Requests/Vendor/UpdateVendorRequest.php | 5 +- .../Requests/Vendor/UploadVendorRequest.php | 5 +- .../PaymentAppliedValidAmount.php | 6 +- app/Http/ViewComposers/PortalComposer.php | 2 +- app/Import/Providers/BaseImport.php | 9 +- app/Jobs/Inventory/AdjustProductInventory.php | 17 +- app/Jobs/Mail/NinjaMailerJob.php | 3 +- app/Jobs/Ninja/AdjustEmailQuota.php | 10 +- app/Jobs/Ninja/SendReminders.php | 1 - app/Jobs/Payment/EmailPayment.php | 3 +- app/Jobs/Util/Import.php | 2 +- app/Jobs/Util/ReminderJob.php | 22 +- .../Payment/PaymentBalanceActivity.php | 4 +- .../Payment/PaymentEmailedActivity.php | 5 +- app/Mail/Engine/PaymentEmailEngine.php | 10 +- app/Models/Gateway.php | 2 +- app/Models/Payment.php | 1 - app/Models/PaymentType.php | 3 +- app/Models/Product.php | 2 +- app/Models/Vendor.php | 2 +- .../Ninja/EmailQualityNotification.php | 1 - app/PaymentDrivers/BaseDriver.php | 53 +- app/PaymentDrivers/Braintree/CreditCard.php | 1 - app/PaymentDrivers/CustomPaymentDriver.php | 50 +- app/PaymentDrivers/GoCardless/DirectDebit.php | 2 +- .../GoCardlessPaymentDriver.php | 13 +- app/PaymentDrivers/Stripe/ACH.php | 5 +- app/PaymentDrivers/Stripe/ACSS.php | 1 - app/PaymentDrivers/Stripe/Alipay.php | 7 +- app/PaymentDrivers/Stripe/BACS.php | 9 +- app/PaymentDrivers/Stripe/Charge.php | 15 +- app/PaymentDrivers/Stripe/CreditCard.php | 1 - .../PaymentIntentPartiallyFundedWebhook.php | 4 +- .../Jobs/PaymentIntentProcessingWebhook.php | 5 +- .../Stripe/Jobs/PaymentIntentWebhook.php | 12 +- app/PaymentDrivers/Stripe/Klarna.php | 1 - .../Stripe/UpdatePaymentMethods.php | 1 - app/PaymentDrivers/StripePaymentDriver.php | 96 ++-- app/Providers/EventServiceProvider.php | 464 +++++++++--------- app/Providers/RouteServiceProvider.php | 19 +- app/Repositories/InvoiceRepository.php | 3 +- app/Services/Client/ClientService.php | 7 +- app/Services/ClientPortal/InstantPayment.php | 6 +- app/Services/Email/Email.php | 78 ++- app/Services/Email/EmailDefaults.php | 29 +- app/Services/Email/EmailMailable.php | 32 +- app/Services/Email/EmailObject.php | 22 +- app/Services/Invoice/ApplyNumber.php | 2 +- app/Services/Invoice/AutoBillInvoice.php | 8 +- app/Services/Invoice/MarkSent.php | 3 +- app/Services/Payment/DeletePayment.php | 2 - app/Services/Payment/SendEmail.php | 20 +- app/Services/Payment/UpdateInvoicePayment.php | 18 +- app/Services/Pdf/PdfService.php | 4 +- app/Services/PdfMaker/Design.php | 4 +- app/Services/PdfMaker/PdfMakerUtilities.php | 2 +- app/Services/Quote/GetQuotePdf.php | 5 +- app/Services/Quote/SendEmail.php | 3 +- app/Services/Recurring/IncreasePrice.php | 10 - app/Services/Recurring/RecurringService.php | 14 +- app/Services/Recurring/UpdatePrice.php | 14 +- app/Services/Scheduler/SchedulerService.php | 3 +- .../Subscription/SubscriptionService.php | 59 ++- app/Utils/HtmlEngine.php | 6 +- app/Utils/Number.php | 5 +- app/Utils/PaymentHtmlEngine.php | 13 +- app/Utils/TemplateEngine.php | 53 +- app/Utils/Traits/Uploadable.php | 1 - app/Utils/VendorHtmlEngine.php | 8 +- 147 files changed, 884 insertions(+), 1057 deletions(-) diff --git a/app/Console/Commands/BackupUpdate.php b/app/Console/Commands/BackupUpdate.php index 536e1499e80d..a2fc126e9264 100644 --- a/app/Console/Commands/BackupUpdate.php +++ b/app/Console/Commands/BackupUpdate.php @@ -190,14 +190,12 @@ class BackupUpdate extends Command ->where('filename', '!=', '') ->cursor() ->each(function ($backup) { - $backup_bin = Storage::disk('s3')->get($backup->filename); if ($backup_bin) { Storage::disk($this->option('disk'))->put($backup->filename, $backup_bin); nlog("Backups - Moving {$backup->filename} to {$this->option('disk')}"); - } }); } diff --git a/app/Console/Commands/CheckData.php b/app/Console/Commands/CheckData.php index 8e04496b3782..202f37280504 100644 --- a/app/Console/Commands/CheckData.php +++ b/app/Console/Commands/CheckData.php @@ -12,36 +12,36 @@ namespace App\Console\Commands; use App; -use Exception; -use App\Models\User; -use App\Utils\Ninja; -use App\Models\Quote; -use App\Models\Client; -use App\Models\Credit; -use App\Models\Vendor; -use App\Models\Account; -use App\Models\Company; -use App\Models\Contact; -use App\Models\Invoice; -use App\Models\Payment; -use App\Models\CompanyUser; -use Illuminate\Support\Str; -use App\Models\CompanyToken; -use App\Models\ClientContact; -use App\Models\CompanyLedger; -use App\Models\PurchaseOrder; -use App\Models\VendorContact; -use App\Models\QuoteInvitation; -use Illuminate\Console\Command; -use App\Models\CreditInvitation; -use App\Models\InvoiceInvitation; use App\DataMapper\ClientSettings; -use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Mail; use App\Factory\ClientContactFactory; use App\Factory\VendorContactFactory; use App\Jobs\Company\CreateCompanyToken; +use App\Models\Account; +use App\Models\Client; +use App\Models\ClientContact; +use App\Models\Company; +use App\Models\CompanyLedger; +use App\Models\CompanyToken; +use App\Models\CompanyUser; +use App\Models\Contact; +use App\Models\Credit; +use App\Models\CreditInvitation; +use App\Models\Invoice; +use App\Models\InvoiceInvitation; +use App\Models\Payment; +use App\Models\PurchaseOrder; +use App\Models\Quote; +use App\Models\QuoteInvitation; use App\Models\RecurringInvoiceInvitation; +use App\Models\User; +use App\Models\Vendor; +use App\Models\VendorContact; +use App\Utils\Ninja; +use Exception; +use Illuminate\Console\Command; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Mail; +use Illuminate\Support\Str; use Symfony\Component\Console\Input\InputOption; /* @@ -176,18 +176,16 @@ class CheckData extends Command if (CompanyToken::where('user_id', $cu->user_id)->where('company_id', $cu->company_id)->where('is_system', 1)->doesntExist()) { $this->logMessage("Creating missing company token for user # {$cu->user_id} for company id # {$cu->company_id}"); - if($cu->company && $cu->user) + if ($cu->company && $cu->user) { (new CreateCompanyToken($cu->company, $cu->user, 'System'))->handle(); + } } }); - - - } /** * checkOauthSanity - * + * * @return void */ private function checkOauthSanity() diff --git a/app/DataMapper/ClientSettings.php b/app/DataMapper/ClientSettings.php index de723d6f1967..4e0f02176fbc 100644 --- a/app/DataMapper/ClientSettings.php +++ b/app/DataMapper/ClientSettings.php @@ -84,13 +84,13 @@ class ClientSettings extends BaseSettings */ public static function buildClientSettings($company_settings, $client_settings) { - if (! $client_settings) { return $company_settings; } - if(is_array($client_settings)) + if (is_array($client_settings)) { $client_settings = (object)$client_settings; + } foreach ($company_settings as $key => $value) { /* pseudo code diff --git a/app/DataMapper/Schedule/ScheduleInvoice.php b/app/DataMapper/Schedule/ScheduleInvoice.php index 71b57e820b50..cf22aaa7e224 100644 --- a/app/DataMapper/Schedule/ScheduleInvoice.php +++ b/app/DataMapper/Schedule/ScheduleInvoice.php @@ -33,5 +33,4 @@ class ScheduleInvoice * @var string */ public string $entity_id = ''; - } diff --git a/app/Events/Client/ClientWasArchived.php b/app/Events/Client/ClientWasArchived.php index 77bf459da449..709d9c7b11ac 100644 --- a/app/Events/Client/ClientWasArchived.php +++ b/app/Events/Client/ClientWasArchived.php @@ -16,7 +16,6 @@ use App\Models\Company; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PrivateChannel; -use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; diff --git a/app/Events/Invoice/InvoiceWasCreated.php b/app/Events/Invoice/InvoiceWasCreated.php index c78ea9aef7d9..741b40b63930 100644 --- a/app/Events/Invoice/InvoiceWasCreated.php +++ b/app/Events/Invoice/InvoiceWasCreated.php @@ -13,11 +13,11 @@ namespace App\Events\Invoice; use App\Models\Company; use App\Models\Invoice; -use Illuminate\Queue\SerializesModels; +use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; -use Illuminate\Broadcasting\InteractsWithSockets; +use Illuminate\Queue\SerializesModels; /** * Class InvoiceWasCreated. diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index 18bb04eb4dd0..b9619700865a 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -12,8 +12,8 @@ namespace App\Export\CSV; use App\Models\Client; -use Illuminate\Support\Carbon; use App\Utils\Traits\MakesHash; +use Illuminate\Support\Carbon; class BaseExport { @@ -34,7 +34,6 @@ class BaseExport protected function filterByClients($query) { if (isset($this->input['client_id']) && $this->input['client_id'] != 'all') { - $client = Client::withTrashed()->find($this->input['client_id']); $this->client_description = $client->present()->name; return $query->where('client_id', $this->input['client_id']); diff --git a/app/Export/CSV/ProductSalesExport.php b/app/Export/CSV/ProductSalesExport.php index 6a2708fbc7e0..b6110dd480f5 100644 --- a/app/Export/CSV/ProductSalesExport.php +++ b/app/Export/CSV/ProductSalesExport.php @@ -11,15 +11,15 @@ namespace App\Export\CSV; -use App\Utils\Ninja; -use League\Csv\Writer; +use App\Libraries\MultiDB; use App\Models\Company; use App\Models\Invoice; use App\Models\Product; -use App\Libraries\MultiDB; +use App\Utils\Ninja; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\App; -use Illuminate\Database\Eloquent\Collection; +use League\Csv\Writer; class ProductSalesExport extends BaseExport { @@ -117,10 +117,9 @@ class ProductSalesExport extends BaseExport }); - $grouped = $this->sales->groupBy('product_key')->map(function ($key, $value){ - + $grouped = $this->sales->groupBy('product_key')->map(function ($key, $value) { $data = [ - 'product' => $value, + 'product' => $value, 'quantity' => $key->sum('quantity'), 'markup' => $key->sum('markup'), 'profit' => $key->sum('profit'), @@ -183,11 +182,10 @@ class ProductSalesExport extends BaseExport $this->sales->push($entity); return $entity; - } private function decorateAdvancedFields(Invoice $invoice, $entity) :array - { + { $product = $this->getProduct($entity['product_key']); $entity['cost'] = $product->cost ?? 0; @@ -199,31 +197,31 @@ class ProductSalesExport extends BaseExport $entity['date'] = Carbon::parse($invoice->date)->format($this->company->date_format()); $entity['discount'] = $this->calculateDiscount($invoice, $entity); - $entity['markup'] = round(((($entity['price'] - $entity['discount'] - $entity['cost']) / $unit_cost) * 100),2); + $entity['markup'] = round(((($entity['price'] - $entity['discount'] - $entity['cost']) / $unit_cost) * 100), 2); $entity['net_total'] = $entity['price'] - $entity['discount']; $entity['profit'] = $entity['price'] - $entity['discount'] - $entity['cost']; - if(strlen($entity['tax_name1']) > 1) { + if (strlen($entity['tax_name1']) > 1) { $entity['tax_name1'] = $entity['tax_name1'] . ' [' . $entity['tax_rate1'] . '%]'; $entity['tax_amount1'] = $this->calculateTax($invoice, $entity['line_total'], $entity['tax_rate1']); - } - else + } else { $entity['tax_amount1'] = 0; + } - if(strlen($entity['tax_name2']) > 1) { + if (strlen($entity['tax_name2']) > 1) { $entity['tax_name2'] = $entity['tax_name2'] . ' [' . $entity['tax_rate2'] . '%]'; $entity['tax_amount2'] = $this->calculateTax($invoice, $entity['line_total'], $entity['tax_rate2']); - } - else + } else { $entity['tax_amount2'] = 0; + } - if(strlen($entity['tax_name3']) > 1) { + if (strlen($entity['tax_name3']) > 1) { $entity['tax_name3'] = $entity['tax_name3'] . ' [' . $entity['tax_rate3'] . '%]'; $entity['tax_amount3'] = $this->calculateTax($invoice, $entity['line_total'], $entity['tax_rate3']); - } - else + } else { $entity['tax_amount3'] = 0; + } return $entity; } @@ -240,13 +238,11 @@ class ProductSalesExport extends BaseExport { $amount = $amount - ($amount * ($invoice->discount / 100)); - if($invoice->uses_inclusive_taxes) { + if ($invoice->uses_inclusive_taxes) { return round($amount - ($amount / (1 + ($tax_rate / 100))), 2); - } - else { + } else { return round(($amount * $tax_rate / 100), 2); } - } @@ -258,15 +254,15 @@ class ProductSalesExport extends BaseExport * @param mixed $entity * @return float */ - private function calculateDiscount(Invoice $invoice , $entity) :float + private function calculateDiscount(Invoice $invoice, $entity) :float { - if($entity['discount'] == 0) + if ($entity['discount'] == 0) { return 0; - - if($invoice->is_amount_discount && $entity['discount'] != 0) { - return $entity['discount']; } - elseif(!$invoice->is_amount_discount && $entity['discount'] != 0) { + + if ($invoice->is_amount_discount && $entity['discount'] != 0) { + return $entity['discount']; + } elseif (!$invoice->is_amount_discount && $entity['discount'] != 0) { return round($entity['line_total'] * ($entity['discount'] / 100), 2); } diff --git a/app/Filters/CreditFilters.php b/app/Filters/CreditFilters.php index 7f00792adc0f..ffbbba3fdb90 100644 --- a/app/Filters/CreditFilters.php +++ b/app/Filters/CreditFilters.php @@ -86,8 +86,8 @@ class CreditFilters extends QueryFilters ->orWhere('credits.custom_value2', 'like', '%'.$filter.'%') ->orWhere('credits.custom_value3', 'like', '%'.$filter.'%') ->orWhere('credits.custom_value4', 'like', '%'.$filter.'%') - ->orWhereHas('client', function ($q) use ($filter){ - $q->where('name', 'like', '%'.$filter.'%'); + ->orWhereHas('client', function ($q) use ($filter) { + $q->where('name', 'like', '%'.$filter.'%'); }); }); } diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index cafeee6ab5e7..c8e2f8216a36 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -108,8 +108,8 @@ class InvoiceFilters extends QueryFilters ->orWhere('custom_value2', 'like', '%'.$filter.'%') ->orWhere('custom_value3', 'like', '%'.$filter.'%') ->orWhere('custom_value4', 'like', '%'.$filter.'%') - ->orWhereHas('client', function ($q) use ($filter){ - $q->where('name', 'like', '%'.$filter.'%'); + ->orWhereHas('client', function ($q) use ($filter) { + $q->where('name', 'like', '%'.$filter.'%'); }); }); } diff --git a/app/Filters/PaymentFilters.php b/app/Filters/PaymentFilters.php index a8e6a1b6d165..5276772e9060 100644 --- a/app/Filters/PaymentFilters.php +++ b/app/Filters/PaymentFilters.php @@ -136,7 +136,7 @@ class PaymentFilters extends QueryFilters * Sorts the list based on $sort. * * formatted as column|asc - * + * * @param string $sort * @return Builder */ diff --git a/app/Filters/PurchaseOrderFilters.php b/app/Filters/PurchaseOrderFilters.php index 61fdbb9956fc..ea3035db32ee 100644 --- a/app/Filters/PurchaseOrderFilters.php +++ b/app/Filters/PurchaseOrderFilters.php @@ -63,8 +63,8 @@ class PurchaseOrderFilters extends QueryFilters $po_status[] = PurchaseOrder::STATUS_CANCELLED; } - if (count($status_parameters) >=1) { - $query->whereIn('status_id', $status_parameters); + if (count($po_status) >=1) { + $query->whereIn('status_id', $po_status); } }); @@ -94,7 +94,7 @@ class PurchaseOrderFilters extends QueryFilters ->orWhere('custom_value2', 'like', '%'.$filter.'%') ->orWhere('custom_value3', 'like', '%'.$filter.'%') ->orWhere('custom_value4', 'like', '%'.$filter.'%') - ->orWhereHas('vendor', function ($q) use ($filter){ + ->orWhereHas('vendor', function ($q) use ($filter) { $q->where('name', 'like', '%'.$filter.'%'); }); }); diff --git a/app/Filters/QuoteFilters.php b/app/Filters/QuoteFilters.php index 7b4151b7983a..4c99c5cc87ea 100644 --- a/app/Filters/QuoteFilters.php +++ b/app/Filters/QuoteFilters.php @@ -38,9 +38,9 @@ class QuoteFilters extends QueryFilters ->orWhere('custom_value2', 'like', '%'.$filter.'%') ->orWhere('custom_value3', 'like', '%'.$filter.'%') ->orWhere('custom_value4', 'like', '%'.$filter.'%') - ->orWhereHas('client', function ($q) use ($filter){ - $q->where('name', 'like', '%'.$filter.'%'); - }); + ->orWhereHas('client', function ($q) use ($filter) { + $q->where('name', 'like', '%'.$filter.'%'); + }); }); } diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 413bf66a3118..8ae2803a2742 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -377,7 +377,7 @@ class LoginController extends BaseController if (auth()->user()->company_users()->count() != auth()->user()->tokens()->distinct('company_id')->count()) { auth()->user()->companies->each(function ($company) { - if (!CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $company->id)->where('is_system',true)->exists()) { + if (!CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $company->id)->where('is_system', true)->exists()) { (new CreateCompanyToken($company, auth()->user(), 'Google_O_Auth'))->handle(); } }); diff --git a/app/Http/Controllers/BankTransactionController.php b/app/Http/Controllers/BankTransactionController.php index 6c7839769eb1..be049d7c174c 100644 --- a/app/Http/Controllers/BankTransactionController.php +++ b/app/Http/Controllers/BankTransactionController.php @@ -531,7 +531,6 @@ class BankTransactionController extends BaseController */ public function match(MatchBankTransactionRequest $request) { - $bts = (new MatchBankTransactions(auth()->user()->company()->id, auth()->user()->company()->db, $request->all()))->handle(); return $this->listResponse($bts); diff --git a/app/Http/Controllers/ClientPortal/PaymentController.php b/app/Http/Controllers/ClientPortal/PaymentController.php index 680d629932e9..8c726b97dec0 100644 --- a/app/Http/Controllers/ClientPortal/PaymentController.php +++ b/app/Http/Controllers/ClientPortal/PaymentController.php @@ -12,24 +12,24 @@ namespace App\Http\Controllers\ClientPortal; +use App\Factory\PaymentFactory; +use App\Http\Controllers\Controller; +use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; +use App\Models\CompanyGateway; +use App\Models\GatewayType; use App\Models\Invoice; use App\Models\Payment; -use Illuminate\View\View; -use App\Models\GatewayType; use App\Models\PaymentHash; use App\Models\PaymentType; -use Illuminate\Http\Request; -use App\Models\CompanyGateway; -use App\Factory\PaymentFactory; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\MakesDates; -use App\Http\Controllers\Controller; -use Illuminate\Http\RedirectResponse; -use Illuminate\Contracts\View\Factory; use App\PaymentDrivers\Stripe\BankTransfer; use App\Services\ClientPortal\InstantPayment; use App\Services\Subscription\SubscriptionService; -use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; +use App\Utils\Traits\MakesDates; +use App\Utils\Traits\MakesHash; +use Illuminate\Contracts\View\Factory; +use Illuminate\Http\RedirectResponse; +use Illuminate\Http\Request; +use Illuminate\View\View; /** * Class PaymentController. @@ -64,15 +64,14 @@ class PaymentController extends Controller $data = false; $gateway = false; - if($payment->gateway_type_id == GatewayType::DIRECT_DEBIT && $payment->type_id == PaymentType::DIRECT_DEBIT){ - + if ($payment->gateway_type_id == GatewayType::DIRECT_DEBIT && $payment->type_id == PaymentType::DIRECT_DEBIT) { if (method_exists($payment->company_gateway->driver($payment->client), 'getPaymentIntent')) { $stripe = $payment->company_gateway->driver($payment->client); $payment_intent = $stripe->getPaymentIntent($payment->transaction_reference); $bt = new BankTransfer($stripe); - match($payment->currency->code){ + match ($payment->currency->code) { 'MXN' => $data = $bt->formatDataforMx($payment_intent), 'EUR' => $data = $bt->formatDataforEur($payment_intent), 'JPY' => $data = $bt->formatDataforJp($payment_intent), diff --git a/app/Http/Controllers/ClientPortal/PaymentMethodController.php b/app/Http/Controllers/ClientPortal/PaymentMethodController.php index 1a640aa0fcda..a590276c8a0d 100644 --- a/app/Http/Controllers/ClientPortal/PaymentMethodController.php +++ b/app/Http/Controllers/ClientPortal/PaymentMethodController.php @@ -15,7 +15,6 @@ namespace App\Http\Controllers\ClientPortal; use App\Events\Payment\Methods\MethodDeleted; use App\Http\Controllers\Controller; use App\Http\Requests\ClientPortal\PaymentMethod\CreatePaymentMethodRequest; -use App\Http\Requests\ClientPortal\PaymentMethod\VerifyPaymentMethodRequest; use App\Http\Requests\Request; use App\Models\ClientGatewayToken; use App\Models\GatewayType; diff --git a/app/Http/Controllers/ClientPortal/PrePaymentController.php b/app/Http/Controllers/ClientPortal/PrePaymentController.php index 874be8a353aa..1fb91c04a5ab 100644 --- a/app/Http/Controllers/ClientPortal/PrePaymentController.php +++ b/app/Http/Controllers/ClientPortal/PrePaymentController.php @@ -12,16 +12,16 @@ namespace App\Http\Controllers\ClientPortal; -use App\Utils\Number; -use Illuminate\View\View; use App\DataMapper\InvoiceItem; use App\Factory\InvoiceFactory; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\MakesDates; use App\Http\Controllers\Controller; -use Illuminate\Contracts\View\Factory; -use App\Repositories\InvoiceRepository; use App\Http\Requests\ClientPortal\PrePayments\StorePrePaymentRequest; +use App\Repositories\InvoiceRepository; +use App\Utils\Number; +use App\Utils\Traits\MakesDates; +use App\Utils\Traits\MakesHash; +use Illuminate\Contracts\View\Factory; +use Illuminate\View\View; /** * Class PrePaymentController. @@ -38,7 +38,6 @@ class PrePaymentController extends Controller */ public function index() { - $data = [ 'title' => ctrans('texts.amount'). " " .auth()->guard('contact')->user()->client->currency()->code." (".auth()->guard('contact')->user()->client->currency()->symbol . ")", 'allows_recurring' => auth()->guard('contact')->user()->client->getSetting('client_initiated_payments_recurring'), @@ -51,7 +50,6 @@ class PrePaymentController extends Controller public function process(StorePrePaymentRequest $request) { - $invoice = InvoiceFactory::create(auth()->guard('contact')->user()->company_id, auth()->guard('contact')->user()->user_id); $invoice->due_date = now()->format('Y-m-d'); $invoice->is_proforma = true; @@ -114,7 +112,5 @@ class PrePaymentController extends Controller ]; return $this->render('invoices.payment', $data); - } - -} \ No newline at end of file +} diff --git a/app/Http/Controllers/ClientPortal/SubscriptionPurchaseController.php b/app/Http/Controllers/ClientPortal/SubscriptionPurchaseController.php index e5007a607d98..62d776869f37 100644 --- a/app/Http/Controllers/ClientPortal/SubscriptionPurchaseController.php +++ b/app/Http/Controllers/ClientPortal/SubscriptionPurchaseController.php @@ -44,7 +44,6 @@ class SubscriptionPurchaseController extends Controller public function upgrade(Subscription $subscription, Request $request) { - App::setLocale($subscription->company->locale()); /* Make sure the contact is logged into the correct company for this subscription */ diff --git a/app/Http/Controllers/CompanyController.php b/app/Http/Controllers/CompanyController.php index b12e5c06dcc4..f65e970d7199 100644 --- a/app/Http/Controllers/CompanyController.php +++ b/app/Http/Controllers/CompanyController.php @@ -11,37 +11,37 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use App\Models\Account; -use App\Models\Company; -use App\Models\CompanyUser; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\Uploadable; -use App\Jobs\Mail\NinjaMailerJob; -use App\DataMapper\CompanySettings; -use App\Jobs\Company\CreateCompany; -use App\Jobs\Mail\NinjaMailerObject; -use App\Mail\Company\CompanyDeleted; -use App\Utils\Traits\SavesDocuments; -use Turbo124\Beacon\Facades\LightLogs; -use App\Repositories\CompanyRepository; -use Illuminate\Support\Facades\Storage; -use App\Jobs\Company\CreateCompanyToken; -use App\Transformers\CompanyTransformer; use App\DataMapper\Analytics\AccountDeleted; -use App\Transformers\CompanyUserTransformer; -use Illuminate\Foundation\Bus\DispatchesJobs; -use App\Jobs\Company\CreateCompanyPaymentTerms; -use App\Jobs\Company\CreateCompanyTaskStatuses; +use App\DataMapper\CompanySettings; +use App\Http\Requests\Company\CreateCompanyRequest; +use App\Http\Requests\Company\DefaultCompanyRequest; +use App\Http\Requests\Company\DestroyCompanyRequest; use App\Http\Requests\Company\EditCompanyRequest; use App\Http\Requests\Company\ShowCompanyRequest; use App\Http\Requests\Company\StoreCompanyRequest; -use App\Http\Requests\Company\CreateCompanyRequest; use App\Http\Requests\Company\UpdateCompanyRequest; use App\Http\Requests\Company\UploadCompanyRequest; -use App\Http\Requests\Company\DefaultCompanyRequest; -use App\Http\Requests\Company\DestroyCompanyRequest; +use App\Jobs\Company\CreateCompany; +use App\Jobs\Company\CreateCompanyPaymentTerms; +use App\Jobs\Company\CreateCompanyTaskStatuses; +use App\Jobs\Company\CreateCompanyToken; +use App\Jobs\Mail\NinjaMailerJob; +use App\Jobs\Mail\NinjaMailerObject; +use App\Mail\Company\CompanyDeleted; +use App\Models\Account; +use App\Models\Company; +use App\Models\CompanyUser; +use App\Repositories\CompanyRepository; +use App\Transformers\CompanyTransformer; +use App\Transformers\CompanyUserTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; +use App\Utils\Traits\Uploadable; +use Illuminate\Foundation\Bus\DispatchesJobs; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\Storage; +use Turbo124\Beacon\Facades\LightLogs; /** * Class CompanyController. @@ -489,8 +489,7 @@ class CompanyController extends BaseController try { Storage::disk(config('filesystems.default'))->deleteDirectory($company->company_key); - } - catch(\Exception $e) { + } catch(\Exception $e) { } $account->delete(); @@ -502,9 +501,6 @@ class CompanyController extends BaseController LightLogs::create(new AccountDeleted()) ->increment() ->batch(); - - - } else { $company_id = $company->id; diff --git a/app/Http/Controllers/EmailController.php b/app/Http/Controllers/EmailController.php index af73ff04ccff..3899dbf76620 100644 --- a/app/Http/Controllers/EmailController.php +++ b/app/Http/Controllers/EmailController.php @@ -11,26 +11,26 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use App\Models\Quote; +use App\Events\Credit\CreditWasEmailed; +use App\Events\Quote\QuoteWasEmailed; +use App\Http\Requests\Email\SendEmailRequest; +use App\Jobs\Entity\EmailEntity; +use App\Jobs\PurchaseOrder\PurchaseOrderEmail; use App\Models\Credit; use App\Models\Invoice; use App\Models\PurchaseOrder; -use App\Services\Email\Email; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Entity\EmailEntity; +use App\Models\Quote; use App\Models\RecurringInvoice; +use App\Services\Email\Email; use App\Services\Email\EmailObject; -use App\Events\Quote\QuoteWasEmailed; -use App\Transformers\QuoteTransformer; -use App\Events\Credit\CreditWasEmailed; use App\Transformers\CreditTransformer; use App\Transformers\InvoiceTransformer; -use App\Http\Requests\Email\SendEmailRequest; -use App\Jobs\PurchaseOrder\PurchaseOrderEmail; use App\Transformers\PurchaseOrderTransformer; +use App\Transformers\QuoteTransformer; use App\Transformers\RecurringInvoiceTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; use Illuminate\Mail\Mailables\Address; class EmailController extends BaseController @@ -136,8 +136,9 @@ class EmailController extends BaseController $mo->email_template_body = $request->input('template'); $mo->email_template_subject = str_replace("template", "subject", $request->input('template')); - if($request->has('cc_email')) + if ($request->has('cc_email')) { $mo->cc[] = new Address($request->cc_email); + } // if ($entity == 'purchaseOrder' || $entity == 'purchase_order' || $template == 'purchase_order' || $entity == 'App\Models\PurchaseOrder') { // return $this->sendPurchaseOrder($entity_obj, $data, $template); @@ -152,7 +153,6 @@ class EmailController extends BaseController $mo->invitation_id = $invitation->id; Email::dispatch($mo, $invitation->company); - } }); @@ -193,7 +193,7 @@ class EmailController extends BaseController $this->entity_transformer = RecurringInvoiceTransformer::class; } - if($entity_obj instanceof PurchaseOrder){ + if ($entity_obj instanceof PurchaseOrder) { $this->entity_type = PurchaseOrder::class; $this->entity_transformer = PurchaseOrderTransformer::class; } @@ -217,8 +217,7 @@ class EmailController extends BaseController private function resolveClass(string $entity): string { - - match($entity){ + match ($entity) { 'invoice' => $class = Invoice::class, 'App\Models\Invoice' => $class = Invoice::class, 'credit' => $class = Credit::class, @@ -232,6 +231,5 @@ class EmailController extends BaseController }; return $class; - } } diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php index 3c0ed45bdb05..39c0177d47a1 100644 --- a/app/Http/Controllers/ImportController.php +++ b/app/Http/Controllers/ImportController.php @@ -163,19 +163,15 @@ class ImportController extends Controller $bestDelimiter = ' '; $count = 0; foreach ($delimiters as $delimiter) { - // if (substr_count($csvfile, $delimiter) > $count) { // $count = substr_count($csvfile, $delimiter); // $bestDelimiter = $delimiter; // } - if (substr_count(strstr($csvfile,"\n",true), $delimiter) > $count) { + if (substr_count(strstr($csvfile, "\n", true), $delimiter) > $count) { $count = substr_count($csvfile, $delimiter); $bestDelimiter = $delimiter; } - - - } return $bestDelimiter; } diff --git a/app/Http/Controllers/LicenseController.php b/app/Http/Controllers/LicenseController.php index 3d27d5bb51f0..1c1e0c1cb99e 100644 --- a/app/Http/Controllers/LicenseController.php +++ b/app/Http/Controllers/LicenseController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers; -use stdClass; -use Carbon\Carbon; use App\Models\Account; use App\Utils\CurlUtils; +use Carbon\Carbon; +use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Http; -use Illuminate\Http\Request; +use stdClass; class LicenseController extends BaseController { @@ -155,15 +155,13 @@ class LicenseController extends BaseController /* Catch claim license requests */ if (config('ninja.environment') == 'selfhost' && request()->has('license_key')) { - // $response = Http::get( "http://ninja.test:8000/claim_license", [ - $response = Http::get( "https://invoicing.co/claim_license", [ + $response = Http::get("https://invoicing.co/claim_license", [ 'license_key' => $request->input('license_key'), 'product_id' => 3, ]); - if($response->successful()) { - + if ($response->successful()) { $payload = $response->json(); $account = auth()->user()->account; @@ -179,8 +177,7 @@ class LicenseController extends BaseController ]; return response()->json($error, 200); - }else { - + } else { $error = [ 'message' => trans('texts.white_label_license_error'), 'errors' => new stdClass, @@ -188,7 +185,6 @@ class LicenseController extends BaseController return response()->json($error, 400); } - } $error = [ @@ -197,7 +193,6 @@ class LicenseController extends BaseController ]; return response()->json($error, 400); - } @@ -210,6 +205,5 @@ class LicenseController extends BaseController $account->plan_expires = null; $account->save(); } - } } diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index 2e7c6da78441..eead3581a0e3 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -23,7 +23,6 @@ use App\Libraries\MultiDB; use App\Models\Client; use App\Models\ClientContact; use App\Models\Credit; -use App\Models\GroupSetting; use App\Models\Invoice; use App\Models\InvoiceInvitation; use App\Models\Quote; @@ -37,7 +36,6 @@ use App\Services\PdfMaker\Design; use App\Services\PdfMaker\Design as PdfDesignModel; use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\PdfMaker; -use App\Services\Preview\StubBuilder; use App\Utils\HostedPDF\NinjaPdf; use App\Utils\HtmlEngine; use App\Utils\Ninja; diff --git a/app/Http/Controllers/RecurringInvoiceController.php b/app/Http/Controllers/RecurringInvoiceController.php index 77078d3a818c..5c0bb277edd0 100644 --- a/app/Http/Controllers/RecurringInvoiceController.php +++ b/app/Http/Controllers/RecurringInvoiceController.php @@ -11,29 +11,29 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use App\Models\Account; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Models\RecurringInvoice; -use App\Utils\Traits\SavesDocuments; -use Illuminate\Support\Facades\Storage; -use App\Factory\RecurringInvoiceFactory; -use App\Filters\RecurringInvoiceFilters; -use App\Jobs\RecurringInvoice\UpdateRecurring; -use App\Repositories\RecurringInvoiceRepository; -use App\Transformers\RecurringInvoiceTransformer; use App\Events\RecurringInvoice\RecurringInvoiceWasCreated; use App\Events\RecurringInvoice\RecurringInvoiceWasUpdated; +use App\Factory\RecurringInvoiceFactory; +use App\Filters\RecurringInvoiceFilters; +use App\Http\Requests\RecurringInvoice\ActionRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\BulkRecurringInvoiceRequest; +use App\Http\Requests\RecurringInvoice\CreateRecurringInvoiceRequest; +use App\Http\Requests\RecurringInvoice\DestroyRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\EditRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\ShowRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\StoreRecurringInvoiceRequest; -use App\Http\Requests\RecurringInvoice\ActionRecurringInvoiceRequest; -use App\Http\Requests\RecurringInvoice\CreateRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\UpdateRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\UploadRecurringInvoiceRequest; -use App\Http\Requests\RecurringInvoice\DestroyRecurringInvoiceRequest; +use App\Jobs\RecurringInvoice\UpdateRecurring; +use App\Models\Account; +use App\Models\RecurringInvoice; +use App\Repositories\RecurringInvoiceRepository; +use App\Transformers\RecurringInvoiceTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\Storage; /** * Class RecurringInvoiceController. @@ -406,10 +406,9 @@ class RecurringInvoiceController extends BaseController */ public function bulk(BulkRecurringInvoiceRequest $request) { - $percentage_increase = request()->has('percentage_increase') ? request()->input('percentage_increase') : 0; - if(in_array($request->action, ['increase_prices', 'update_prices'])) { + if (in_array($request->action, ['increase_prices', 'update_prices'])) { UpdateRecurring::dispatch($request->ids, auth()->user()->company(), auth()->user(), $request->action, $percentage_increase); return response()->json(['message' => 'Update in progress.'], 200); @@ -417,7 +416,7 @@ class RecurringInvoiceController extends BaseController $recurring_invoices = RecurringInvoice::withTrashed()->find($request->ids); - $recurring_invoices->each(function ($recurring_invoice, $key) use($request){ + $recurring_invoices->each(function ($recurring_invoice, $key) use ($request) { if (auth()->user()->can('edit', $recurring_invoice)) { $this->performAction($recurring_invoice, $request->action, true); } diff --git a/app/Http/Controllers/TaskSchedulerController.php b/app/Http/Controllers/TaskSchedulerController.php index 370d45cf1feb..195065f62f21 100644 --- a/app/Http/Controllers/TaskSchedulerController.php +++ b/app/Http/Controllers/TaskSchedulerController.php @@ -13,8 +13,8 @@ namespace App\Http\Controllers; use App\Factory\SchedulerFactory; use App\Filters\SchedulerFilters; -use App\Http\Requests\TaskScheduler\DestroySchedulerRequest; use App\Http\Requests\TaskScheduler\CreateSchedulerRequest; +use App\Http\Requests\TaskScheduler\DestroySchedulerRequest; use App\Http\Requests\TaskScheduler\ShowSchedulerRequest; use App\Http\Requests\TaskScheduler\StoreSchedulerRequest; use App\Http\Requests\TaskScheduler\UpdateSchedulerRequest; diff --git a/app/Http/Controllers/WebhookController.php b/app/Http/Controllers/WebhookController.php index f33c3ea0674b..d7a2a581e43a 100644 --- a/app/Http/Controllers/WebhookController.php +++ b/app/Http/Controllers/WebhookController.php @@ -12,22 +12,22 @@ namespace App\Http\Controllers; -use App\Models\Webhook; -use Illuminate\Support\Str; -use Illuminate\Http\Response; use App\Factory\WebhookFactory; use App\Filters\WebhookFilters; -use App\Utils\Traits\MakesHash; +use App\Http\Requests\Webhook\CreateWebhookRequest; +use App\Http\Requests\Webhook\DestroyWebhookRequest; +use App\Http\Requests\Webhook\EditWebhookRequest; +use App\Http\Requests\Webhook\RetryWebhookRequest; +use App\Http\Requests\Webhook\ShowWebhookRequest; +use App\Http\Requests\Webhook\StoreWebhookRequest; +use App\Http\Requests\Webhook\UpdateWebhookRequest; use App\Jobs\Util\WebhookSingle; +use App\Models\Webhook; use App\Repositories\BaseRepository; use App\Transformers\WebhookTransformer; -use App\Http\Requests\Webhook\EditWebhookRequest; -use App\Http\Requests\Webhook\ShowWebhookRequest; -use App\Http\Requests\Webhook\RetryWebhookRequest; -use App\Http\Requests\Webhook\StoreWebhookRequest; -use App\Http\Requests\Webhook\CreateWebhookRequest; -use App\Http\Requests\Webhook\UpdateWebhookRequest; -use App\Http\Requests\Webhook\DestroyWebhookRequest; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; +use Illuminate\Support\Str; class WebhookController extends BaseController { @@ -493,7 +493,7 @@ class WebhookController extends BaseController public function retry(RetryWebhookRequest $request, Webhook $webhook) { - match($request->entity) { + match ($request->entity) { 'invoice' => $includes ='client', 'payment' => $includes ='invoices,client', 'project' => $includes ='client', @@ -506,7 +506,7 @@ class WebhookController extends BaseController $entity = $class::withTrashed()->where('id', $this->decodePrimaryKey($request->entity_id))->company()->first(); - if(!$entity){ + if (!$entity) { return response()->json(['message' => ctrans('texts.record_not_found')], 400); } diff --git a/app/Http/Livewire/BillingPortalPurchase.php b/app/Http/Livewire/BillingPortalPurchase.php index b0df3019ca18..89931982db93 100644 --- a/app/Http/Livewire/BillingPortalPurchase.php +++ b/app/Http/Livewire/BillingPortalPurchase.php @@ -11,24 +11,24 @@ namespace App\Http\Livewire; -use App\Utils\Ninja; -use App\Models\Client; -use App\Models\Invoice; -use Livewire\Component; -use App\Libraries\MultiDB; -use Illuminate\Support\Str; -use App\Models\Subscription; -use App\Models\ClientContact; +use App\DataMapper\ClientSettings; use App\Factory\ClientFactory; use App\Jobs\Mail\NinjaMailerJob; -use App\DataMapper\ClientSettings; use App\Jobs\Mail\NinjaMailerObject; +use App\Libraries\MultiDB; +use App\Mail\ContactPasswordlessLogin; +use App\Models\Client; +use App\Models\ClientContact; +use App\Models\Invoice; +use App\Models\Subscription; +use App\Repositories\ClientContactRepository; +use App\Repositories\ClientRepository; +use App\Services\Subscription\SubscriptionService; +use App\Utils\Ninja; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; -use App\Mail\ContactPasswordlessLogin; -use App\Repositories\ClientRepository; -use App\Repositories\ClientContactRepository; -use App\Services\Subscription\SubscriptionService; +use Illuminate\Support\Str; +use Livewire\Component; class BillingPortalPurchase extends Component { @@ -401,7 +401,7 @@ class BillingPortalPurchase extends Component $context = 'purchase'; // if(Ninja::isHosted() && $this->subscription->service()->recurring_products()->first()?->id == SubscriptionService::WHITE_LABEL) { - if(Ninja::isHosted() && $this->subscription->service()->recurring_products()->first()?->product_key == 'whitelabel') { + if (Ninja::isHosted() && $this->subscription->service()->recurring_products()->first()?->product_key == 'whitelabel') { $context = 'whitelabel'; } diff --git a/app/Http/Livewire/BillingPortalPurchasev2.php b/app/Http/Livewire/BillingPortalPurchasev2.php index f3f0a3b132a7..aaf9bf65cbfe 100644 --- a/app/Http/Livewire/BillingPortalPurchasev2.php +++ b/app/Http/Livewire/BillingPortalPurchasev2.php @@ -172,8 +172,7 @@ class BillingPortalPurchasev2 extends Component $this->contact = auth()->guard('contact')->user(); $this->authenticated = true; $this->payment_started = true; - } - else { + } else { $this->bundle = collect(); } @@ -276,7 +275,6 @@ class BillingPortalPurchasev2 extends Component */ public function handleCoupon() { - $this->resetErrorBag('coupon'); $this->resetValidation('coupon'); diff --git a/app/Http/Livewire/RequiredClientInfo.php b/app/Http/Livewire/RequiredClientInfo.php index 70af5590a8dc..df184eff52bf 100644 --- a/app/Http/Livewire/RequiredClientInfo.php +++ b/app/Http/Livewire/RequiredClientInfo.php @@ -232,8 +232,9 @@ class RequiredClientInfo extends Component if ($cg && $cg->update_details) { $payment_gateway = $cg->driver($this->client)->init(); - if(method_exists($payment_gateway, "updateCustomer")) + if (method_exists($payment_gateway, "updateCustomer")) { $payment_gateway->updateCustomer(); + } } return true; diff --git a/app/Http/Requests/BankIntegration/UploadBankIntegrationRequest.php b/app/Http/Requests/BankIntegration/UploadBankIntegrationRequest.php index b92c22c55ad5..cd07c0688343 100644 --- a/app/Http/Requests/BankIntegration/UploadBankIntegrationRequest.php +++ b/app/Http/Requests/BankIntegration/UploadBankIntegrationRequest.php @@ -29,10 +29,11 @@ class UploadBankIntegrationRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/BankTransaction/UploadBankTransactionRequest.php b/app/Http/Requests/BankTransaction/UploadBankTransactionRequest.php index e3b62225019e..0bbc319ef3e0 100644 --- a/app/Http/Requests/BankTransaction/UploadBankTransactionRequest.php +++ b/app/Http/Requests/BankTransaction/UploadBankTransactionRequest.php @@ -29,10 +29,11 @@ class UploadBankTransactionRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Client/StoreClientRequest.php b/app/Http/Requests/Client/StoreClientRequest.php index ffe65adb9612..095b89561c2d 100644 --- a/app/Http/Requests/Client/StoreClientRequest.php +++ b/app/Http/Requests/Client/StoreClientRequest.php @@ -38,10 +38,11 @@ class StoreClientRequest extends Request public function rules() { - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Client/UpdateClientRequest.php b/app/Http/Requests/Client/UpdateClientRequest.php index 6a51aec64bf0..8b4059c9aac4 100644 --- a/app/Http/Requests/Client/UpdateClientRequest.php +++ b/app/Http/Requests/Client/UpdateClientRequest.php @@ -38,10 +38,11 @@ class UpdateClientRequest extends Request { /* Ensure we have a client name, and that all emails are unique*/ - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Client/UploadClientRequest.php b/app/Http/Requests/Client/UploadClientRequest.php index 1093b3f1ebcd..e5baef5ef0be 100644 --- a/app/Http/Requests/Client/UploadClientRequest.php +++ b/app/Http/Requests/Client/UploadClientRequest.php @@ -29,10 +29,11 @@ class UploadClientRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/ClientPortal/PrePayments/StorePrePaymentRequest.php b/app/Http/Requests/ClientPortal/PrePayments/StorePrePaymentRequest.php index a591632db413..f596ef2e6295 100644 --- a/app/Http/Requests/ClientPortal/PrePayments/StorePrePaymentRequest.php +++ b/app/Http/Requests/ClientPortal/PrePayments/StorePrePaymentRequest.php @@ -15,7 +15,6 @@ class StorePrePaymentRequest extends FormRequest public function authorize() { return auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES; - } /** @@ -30,5 +29,4 @@ class StorePrePaymentRequest extends FormRequest 'amount' => 'required|bail|', ]; } - } diff --git a/app/Http/Requests/Company/UploadCompanyRequest.php b/app/Http/Requests/Company/UploadCompanyRequest.php index 999101417dd0..4e5cdd6308d2 100644 --- a/app/Http/Requests/Company/UploadCompanyRequest.php +++ b/app/Http/Requests/Company/UploadCompanyRequest.php @@ -29,10 +29,11 @@ class UploadCompanyRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Credit/StoreCreditRequest.php b/app/Http/Requests/Credit/StoreCreditRequest.php index 589cfe24527c..13eee9c59852 100644 --- a/app/Http/Requests/Credit/StoreCreditRequest.php +++ b/app/Http/Requests/Credit/StoreCreditRequest.php @@ -43,10 +43,11 @@ class StoreCreditRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Credit/UpdateCreditRequest.php b/app/Http/Requests/Credit/UpdateCreditRequest.php index d208cf223f51..929ad49e443a 100644 --- a/app/Http/Requests/Credit/UpdateCreditRequest.php +++ b/app/Http/Requests/Credit/UpdateCreditRequest.php @@ -42,10 +42,11 @@ class UpdateCreditRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Credit/UploadCreditRequest.php b/app/Http/Requests/Credit/UploadCreditRequest.php index 06721355bbbd..e25782acaf12 100644 --- a/app/Http/Requests/Credit/UploadCreditRequest.php +++ b/app/Http/Requests/Credit/UploadCreditRequest.php @@ -29,10 +29,11 @@ class UploadCreditRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Expense/UploadExpenseRequest.php b/app/Http/Requests/Expense/UploadExpenseRequest.php index b04cde728549..694f2317f2dd 100644 --- a/app/Http/Requests/Expense/UploadExpenseRequest.php +++ b/app/Http/Requests/Expense/UploadExpenseRequest.php @@ -29,10 +29,11 @@ class UploadExpenseRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/GroupSetting/UploadGroupSettingRequest.php b/app/Http/Requests/GroupSetting/UploadGroupSettingRequest.php index c3c1415a6c90..4b7379068059 100644 --- a/app/Http/Requests/GroupSetting/UploadGroupSettingRequest.php +++ b/app/Http/Requests/GroupSetting/UploadGroupSettingRequest.php @@ -29,10 +29,11 @@ class UploadGroupSettingRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Invoice/StoreInvoiceRequest.php b/app/Http/Requests/Invoice/StoreInvoiceRequest.php index 5f21287c3839..cedbb7fd4f7f 100644 --- a/app/Http/Requests/Invoice/StoreInvoiceRequest.php +++ b/app/Http/Requests/Invoice/StoreInvoiceRequest.php @@ -37,10 +37,11 @@ class StoreInvoiceRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php index 0a4f5d31e149..0668a8e60ff2 100644 --- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php @@ -39,10 +39,11 @@ class UpdateInvoiceRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Invoice/UploadInvoiceRequest.php b/app/Http/Requests/Invoice/UploadInvoiceRequest.php index 70157d05aac1..93396d9ee7aa 100644 --- a/app/Http/Requests/Invoice/UploadInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UploadInvoiceRequest.php @@ -29,10 +29,11 @@ class UploadInvoiceRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; @@ -45,6 +46,5 @@ class UploadInvoiceRequest extends Request public function prepareForValidation() { - } } diff --git a/app/Http/Requests/Payment/StorePaymentRequest.php b/app/Http/Requests/Payment/StorePaymentRequest.php index d796a082454d..196c302e57a7 100644 --- a/app/Http/Requests/Payment/StorePaymentRequest.php +++ b/app/Http/Requests/Payment/StorePaymentRequest.php @@ -112,10 +112,11 @@ class StorePaymentRequest extends Request ]; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Payment/UpdatePaymentRequest.php b/app/Http/Requests/Payment/UpdatePaymentRequest.php index 1d87ef164542..1cd8d8b4c850 100644 --- a/app/Http/Requests/Payment/UpdatePaymentRequest.php +++ b/app/Http/Requests/Payment/UpdatePaymentRequest.php @@ -44,10 +44,11 @@ class UpdatePaymentRequest extends Request $rules['number'] = Rule::unique('payments')->where('company_id', auth()->user()->company()->id)->ignore($this->payment->id); } - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Payment/UploadPaymentRequest.php b/app/Http/Requests/Payment/UploadPaymentRequest.php index ad3874895f2e..52bb9b2b318b 100644 --- a/app/Http/Requests/Payment/UploadPaymentRequest.php +++ b/app/Http/Requests/Payment/UploadPaymentRequest.php @@ -29,10 +29,11 @@ class UploadPaymentRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Preview/PreviewInvoiceRequest.php b/app/Http/Requests/Preview/PreviewInvoiceRequest.php index ab0586f5a5f8..b2da03628210 100644 --- a/app/Http/Requests/Preview/PreviewInvoiceRequest.php +++ b/app/Http/Requests/Preview/PreviewInvoiceRequest.php @@ -12,10 +12,6 @@ namespace App\Http\Requests\Preview; use App\Http\Requests\Request; -use App\Models\Credit; -use App\Models\Invoice; -use App\Models\Quote; -use App\Models\RecurringInvoice; use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\MakesHash; diff --git a/app/Http/Requests/Preview/PreviewPurchaseOrderRequest.php b/app/Http/Requests/Preview/PreviewPurchaseOrderRequest.php index 6b3ce83cd85e..d91de03c19ec 100644 --- a/app/Http/Requests/Preview/PreviewPurchaseOrderRequest.php +++ b/app/Http/Requests/Preview/PreviewPurchaseOrderRequest.php @@ -12,7 +12,6 @@ namespace App\Http\Requests\Preview; use App\Http\Requests\Request; -use App\Models\PurchaseOrder; use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\MakesHash; diff --git a/app/Http/Requests/Product/StoreProductRequest.php b/app/Http/Requests/Product/StoreProductRequest.php index a512dc6e1750..4dacdbdfca16 100644 --- a/app/Http/Requests/Product/StoreProductRequest.php +++ b/app/Http/Requests/Product/StoreProductRequest.php @@ -28,10 +28,11 @@ class StoreProductRequest extends Request public function rules() { - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Product/UpdateProductRequest.php b/app/Http/Requests/Product/UpdateProductRequest.php index b66dfd00601f..36197b90cf4a 100644 --- a/app/Http/Requests/Product/UpdateProductRequest.php +++ b/app/Http/Requests/Product/UpdateProductRequest.php @@ -12,7 +12,6 @@ namespace App\Http\Requests\Product; use App\Http\Requests\Request; -use App\Models\Product; use App\Utils\Traits\ChecksEntityStatus; class UpdateProductRequest extends Request @@ -31,10 +30,11 @@ class UpdateProductRequest extends Request public function rules() { - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Product/UploadProductRequest.php b/app/Http/Requests/Product/UploadProductRequest.php index d08a20c0f571..b7117c035790 100644 --- a/app/Http/Requests/Product/UploadProductRequest.php +++ b/app/Http/Requests/Product/UploadProductRequest.php @@ -28,10 +28,11 @@ class UploadProductRequest extends Request public function rules() { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Project/CreateProjectRequest.php b/app/Http/Requests/Project/CreateProjectRequest.php index e9f9f193f750..44abf721d522 100644 --- a/app/Http/Requests/Project/CreateProjectRequest.php +++ b/app/Http/Requests/Project/CreateProjectRequest.php @@ -11,8 +11,8 @@ namespace App\Http\Requests\Project; -use App\Models\Project; use App\Http\Requests\Request; +use App\Models\Project; class CreateProjectRequest extends Request { @@ -24,6 +24,5 @@ class CreateProjectRequest extends Request public function authorize() : bool { return auth()->user()->can('create', Project::class); - } } diff --git a/app/Http/Requests/Project/ShowProjectRequest.php b/app/Http/Requests/Project/ShowProjectRequest.php index 6e6b4ba98a84..47abf0c57f74 100644 --- a/app/Http/Requests/Project/ShowProjectRequest.php +++ b/app/Http/Requests/Project/ShowProjectRequest.php @@ -24,7 +24,6 @@ class ShowProjectRequest extends Request { // return auth()->user()->isAdmin(); return auth()->user()->can('view', $this->project); - } /** diff --git a/app/Http/Requests/Project/StoreProjectRequest.php b/app/Http/Requests/Project/StoreProjectRequest.php index 3e2b7ee6a132..98664cd84c0e 100644 --- a/app/Http/Requests/Project/StoreProjectRequest.php +++ b/app/Http/Requests/Project/StoreProjectRequest.php @@ -42,10 +42,11 @@ class StoreProjectRequest extends Request $rules['number'] = Rule::unique('projects')->where('company_id', auth()->user()->company()->id); } - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Project/UpdateProjectRequest.php b/app/Http/Requests/Project/UpdateProjectRequest.php index 9d938ce8d046..484f18f036f3 100644 --- a/app/Http/Requests/Project/UpdateProjectRequest.php +++ b/app/Http/Requests/Project/UpdateProjectRequest.php @@ -37,10 +37,11 @@ class UpdateProjectRequest extends Request $rules['number'] = Rule::unique('projects')->where('company_id', auth()->user()->company()->id)->ignore($this->project->id); } - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Project/UploadProjectRequest.php b/app/Http/Requests/Project/UploadProjectRequest.php index bf37beab7d29..c7504f5b41f7 100644 --- a/app/Http/Requests/Project/UploadProjectRequest.php +++ b/app/Http/Requests/Project/UploadProjectRequest.php @@ -29,10 +29,11 @@ class UploadProjectRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/PurchaseOrder/StorePurchaseOrderRequest.php b/app/Http/Requests/PurchaseOrder/StorePurchaseOrderRequest.php index 3071a870a6ec..74697c804ad0 100644 --- a/app/Http/Requests/PurchaseOrder/StorePurchaseOrderRequest.php +++ b/app/Http/Requests/PurchaseOrder/StorePurchaseOrderRequest.php @@ -47,10 +47,11 @@ class StorePurchaseOrderRequest extends Request $rules['is_amount_discount'] = ['boolean']; $rules['line_items'] = 'array'; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/PurchaseOrder/UpdatePurchaseOrderRequest.php b/app/Http/Requests/PurchaseOrder/UpdatePurchaseOrderRequest.php index 3ee030773a09..e504fea5c08b 100644 --- a/app/Http/Requests/PurchaseOrder/UpdatePurchaseOrderRequest.php +++ b/app/Http/Requests/PurchaseOrder/UpdatePurchaseOrderRequest.php @@ -50,10 +50,11 @@ class UpdatePurchaseOrderRequest extends Request $rules['discount'] = 'sometimes|numeric'; $rules['is_amount_discount'] = ['boolean']; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/PurchaseOrder/UploadPurchaseOrderRequest.php b/app/Http/Requests/PurchaseOrder/UploadPurchaseOrderRequest.php index 3fdce5fac4e0..25aadfdb1a19 100644 --- a/app/Http/Requests/PurchaseOrder/UploadPurchaseOrderRequest.php +++ b/app/Http/Requests/PurchaseOrder/UploadPurchaseOrderRequest.php @@ -29,10 +29,11 @@ class UploadPurchaseOrderRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Quote/StoreQuoteRequest.php b/app/Http/Requests/Quote/StoreQuoteRequest.php index 18c132367891..387f165de110 100644 --- a/app/Http/Requests/Quote/StoreQuoteRequest.php +++ b/app/Http/Requests/Quote/StoreQuoteRequest.php @@ -39,10 +39,11 @@ class StoreQuoteRequest extends Request $rules['client_id'] = 'required|exists:clients,id,company_id,'.auth()->user()->company()->id; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Quote/UpdateQuoteRequest.php b/app/Http/Requests/Quote/UpdateQuoteRequest.php index 5d75ef768a7a..07b463936892 100644 --- a/app/Http/Requests/Quote/UpdateQuoteRequest.php +++ b/app/Http/Requests/Quote/UpdateQuoteRequest.php @@ -37,10 +37,11 @@ class UpdateQuoteRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Quote/UploadQuoteRequest.php b/app/Http/Requests/Quote/UploadQuoteRequest.php index 1dce9e19de03..cfc3580ad412 100644 --- a/app/Http/Requests/Quote/UploadQuoteRequest.php +++ b/app/Http/Requests/Quote/UploadQuoteRequest.php @@ -29,10 +29,11 @@ class UploadQuoteRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/RecurringExpense/StoreRecurringExpenseRequest.php b/app/Http/Requests/RecurringExpense/StoreRecurringExpenseRequest.php index d2752a446e57..7b9e582a58d1 100644 --- a/app/Http/Requests/RecurringExpense/StoreRecurringExpenseRequest.php +++ b/app/Http/Requests/RecurringExpense/StoreRecurringExpenseRequest.php @@ -48,10 +48,11 @@ class StoreRecurringExpenseRequest extends Request $rules['tax_amount2'] = 'numeric'; $rules['tax_amount3'] = 'numeric'; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/RecurringExpense/UpdateRecurringExpenseRequest.php b/app/Http/Requests/RecurringExpense/UpdateRecurringExpenseRequest.php index 271a46bfd25b..76c61120971e 100644 --- a/app/Http/Requests/RecurringExpense/UpdateRecurringExpenseRequest.php +++ b/app/Http/Requests/RecurringExpense/UpdateRecurringExpenseRequest.php @@ -48,10 +48,11 @@ class UpdateRecurringExpenseRequest extends Request $rules['tax_amount3'] = 'numeric'; $rules['category_id'] = 'bail|nullable|sometimes|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0'; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/RecurringExpense/UploadRecurringExpenseRequest.php b/app/Http/Requests/RecurringExpense/UploadRecurringExpenseRequest.php index d086142bff41..b202ece92069 100644 --- a/app/Http/Requests/RecurringExpense/UploadRecurringExpenseRequest.php +++ b/app/Http/Requests/RecurringExpense/UploadRecurringExpenseRequest.php @@ -29,10 +29,11 @@ class UploadRecurringExpenseRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/RecurringInvoice/StoreRecurringInvoiceRequest.php b/app/Http/Requests/RecurringInvoice/StoreRecurringInvoiceRequest.php index 9cfab48bbf5f..420afb7c09f7 100644 --- a/app/Http/Requests/RecurringInvoice/StoreRecurringInvoiceRequest.php +++ b/app/Http/Requests/RecurringInvoice/StoreRecurringInvoiceRequest.php @@ -38,10 +38,11 @@ class StoreRecurringInvoiceRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php b/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php index 2ad0c1d52558..f268cbe84288 100644 --- a/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php +++ b/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php @@ -38,10 +38,11 @@ class UpdateRecurringInvoiceRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/RecurringInvoice/UploadRecurringInvoiceRequest.php b/app/Http/Requests/RecurringInvoice/UploadRecurringInvoiceRequest.php index a6125e8c7bcb..7d0ef57f7eba 100644 --- a/app/Http/Requests/RecurringInvoice/UploadRecurringInvoiceRequest.php +++ b/app/Http/Requests/RecurringInvoice/UploadRecurringInvoiceRequest.php @@ -29,10 +29,11 @@ class UploadRecurringInvoiceRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/RecurringQuote/StoreRecurringQuoteRequest.php b/app/Http/Requests/RecurringQuote/StoreRecurringQuoteRequest.php index ec3225dfd0f1..396341b9fcd0 100644 --- a/app/Http/Requests/RecurringQuote/StoreRecurringQuoteRequest.php +++ b/app/Http/Requests/RecurringQuote/StoreRecurringQuoteRequest.php @@ -37,10 +37,11 @@ class StoreRecurringQuoteRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/RecurringQuote/UpdateRecurringQuoteRequest.php b/app/Http/Requests/RecurringQuote/UpdateRecurringQuoteRequest.php index 957173a241fc..d7004836bd9c 100644 --- a/app/Http/Requests/RecurringQuote/UpdateRecurringQuoteRequest.php +++ b/app/Http/Requests/RecurringQuote/UpdateRecurringQuoteRequest.php @@ -37,10 +37,11 @@ class UpdateRecurringQuoteRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/RecurringQuote/UploadRecurringQuoteRequest.php b/app/Http/Requests/RecurringQuote/UploadRecurringQuoteRequest.php index 6ec54bf6ae1b..ee17418bb88f 100644 --- a/app/Http/Requests/RecurringQuote/UploadRecurringQuoteRequest.php +++ b/app/Http/Requests/RecurringQuote/UploadRecurringQuoteRequest.php @@ -29,10 +29,11 @@ class UploadRecurringQuoteRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Report/GenericReportRequest.php b/app/Http/Requests/Report/GenericReportRequest.php index 826ef00a5156..63837aa41341 100644 --- a/app/Http/Requests/Report/GenericReportRequest.php +++ b/app/Http/Requests/Report/GenericReportRequest.php @@ -58,6 +58,5 @@ class GenericReportRequest extends Request } $this->replace($input); - } } diff --git a/app/Http/Requests/Task/StoreTaskRequest.php b/app/Http/Requests/Task/StoreTaskRequest.php index a4fe31f950c5..e97d5d4c1a00 100644 --- a/app/Http/Requests/Task/StoreTaskRequest.php +++ b/app/Http/Requests/Task/StoreTaskRequest.php @@ -59,10 +59,11 @@ class StoreTaskRequest extends Request } }]; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Task/UpdateTaskRequest.php b/app/Http/Requests/Task/UpdateTaskRequest.php index 69194e7beee0..e8b5deb52f3c 100644 --- a/app/Http/Requests/Task/UpdateTaskRequest.php +++ b/app/Http/Requests/Task/UpdateTaskRequest.php @@ -66,10 +66,11 @@ class UpdateTaskRequest extends Request } }]; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/User/DetachCompanyUserRequest.php b/app/Http/Requests/User/DetachCompanyUserRequest.php index 843b84d98371..393295f9bc4c 100644 --- a/app/Http/Requests/User/DetachCompanyUserRequest.php +++ b/app/Http/Requests/User/DetachCompanyUserRequest.php @@ -12,11 +12,9 @@ namespace App\Http\Requests\User; use App\Http\Requests\Request; -use App\Utils\Traits\MakesHash; class DetachCompanyUserRequest extends Request { - /** * Determine if the user is authorized to make this request. * diff --git a/app/Http/Requests/Vendor/StoreVendorRequest.php b/app/Http/Requests/Vendor/StoreVendorRequest.php index 3ede512b7d74..777930dd70b4 100644 --- a/app/Http/Requests/Vendor/StoreVendorRequest.php +++ b/app/Http/Requests/Vendor/StoreVendorRequest.php @@ -41,10 +41,11 @@ class StoreVendorRequest extends Request $rules['currency_id'] = 'bail|required|exists:currencies,id'; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; @@ -57,7 +58,6 @@ class StoreVendorRequest extends Request public function prepareForValidation() { - $input = $this->all(); if (!array_key_exists('currency_id', $input) || empty($input['currency_id'])) { diff --git a/app/Http/Requests/Vendor/UpdateVendorRequest.php b/app/Http/Requests/Vendor/UpdateVendorRequest.php index 46ac272f643d..2010b38d1d1e 100644 --- a/app/Http/Requests/Vendor/UpdateVendorRequest.php +++ b/app/Http/Requests/Vendor/UpdateVendorRequest.php @@ -44,10 +44,11 @@ class UpdateVendorRequest extends Request $rules['contacts.*.email'] = 'nullable|distinct'; $rules['currency_id'] = 'bail|sometimes|exists:currencies,id'; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/Requests/Vendor/UploadVendorRequest.php b/app/Http/Requests/Vendor/UploadVendorRequest.php index fb08ca962608..6df26684fd6c 100644 --- a/app/Http/Requests/Vendor/UploadVendorRequest.php +++ b/app/Http/Requests/Vendor/UploadVendorRequest.php @@ -29,10 +29,11 @@ class UploadVendorRequest extends Request { $rules = []; - if($this->file('documents') && is_array($this->file('documents'))) + if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->file_validation; - elseif($this->file('documents')) + } elseif ($this->file('documents')) { $rules['documents'] = $this->file_validation; + } if ($this->file('file') && is_array($this->file('file'))) { $rules['file.*'] = $this->file_validation; diff --git a/app/Http/ValidationRules/PaymentAppliedValidAmount.php b/app/Http/ValidationRules/PaymentAppliedValidAmount.php index 88432bd8f2a8..1d674e07d8c5 100644 --- a/app/Http/ValidationRules/PaymentAppliedValidAmount.php +++ b/app/Http/ValidationRules/PaymentAppliedValidAmount.php @@ -84,17 +84,15 @@ class PaymentAppliedValidAmount implements Rule $inv = $inv_collection->firstWhere('id', $invoice['invoice_id']); - if($inv->balance < $invoice['amount']) { - + if ($inv->balance < $invoice['amount']) { $this->message = 'Amount cannot be greater than invoice balance'; return false; } - } } - if(round($payment_amounts, 3) >= round($invoice_amounts, 3)) { + if (round($payment_amounts, 3) >= round($invoice_amounts, 3)) { return true; } diff --git a/app/Http/ViewComposers/PortalComposer.php b/app/Http/ViewComposers/PortalComposer.php index 747cc9572adb..1a318e0e3f5b 100644 --- a/app/Http/ViewComposers/PortalComposer.php +++ b/app/Http/ViewComposers/PortalComposer.php @@ -138,7 +138,7 @@ class PortalComposer $data[] = ['title' => ctrans('texts.subscriptions'), 'url' => 'client.subscriptions.index', 'icon' => 'calendar']; } - if(property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) { + if (property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) { $data[] = ['title' => ctrans('texts.pre_payment'), 'url' => 'client.pre_payments.index', 'icon' => 'dollar-sign']; } diff --git a/app/Import/Providers/BaseImport.php b/app/Import/Providers/BaseImport.php index 072bc65c5713..b264a4320dea 100644 --- a/app/Import/Providers/BaseImport.php +++ b/app/Import/Providers/BaseImport.php @@ -130,12 +130,10 @@ class BaseImport // $count = substr_count($csvfile, $delimiter); // $bestDelimiter = $delimiter; // } - if (substr_count(strstr($csvfile,"\n",true), $delimiter) > $count) { + if (substr_count(strstr($csvfile, "\n", true), $delimiter) > $count) { $count = substr_count($csvfile, $delimiter); $bestDelimiter = $delimiter; } - - } return $bestDelimiter; } @@ -641,8 +639,6 @@ class BaseImport public function preTransform(array $data, $entity_type) { - - $keys = array_shift($data); ksort($keys); @@ -666,11 +662,10 @@ class BaseImport ksort($keys); $data = array_map(function ($row) use ($keys) { - $row_count = count($row); $key_count = count($keys); - if($key_count > $row_count) { + if ($key_count > $row_count) { $row = array_pad($row, $key_count, ' '); } diff --git a/app/Jobs/Inventory/AdjustProductInventory.php b/app/Jobs/Inventory/AdjustProductInventory.php index 8e5c01e1dcd4..27d7c4b7926e 100644 --- a/app/Jobs/Inventory/AdjustProductInventory.php +++ b/app/Jobs/Inventory/AdjustProductInventory.php @@ -68,22 +68,17 @@ class AdjustProductInventory implements ShouldQueue // $p->saveQuietly(); // } - collect($this->invoice->line_items)->filter(function ($item){ + collect($this->invoice->line_items)->filter(function ($item) { return $item->type_id == '1'; - })->each(function ($i){ - + })->each(function ($i) { $p = Product::where('product_key', $i->product_key)->where('company_id', $this->company->id)->first(); if ($p) { - $p->in_stock_quantity += $i->quantity; $p->saveQuietly(); - } - }); - } public function handleRestoredInvoice() @@ -112,8 +107,6 @@ class AdjustProductInventory implements ShouldQueue $p->saveQuietly(); } }); - - } public function middleware() @@ -157,12 +150,8 @@ class AdjustProductInventory implements ShouldQueue } elseif ($this->company->stock_notification && $p->stock_notification && $this->company->inventory_notification_threshold && $p->in_stock_quantity <= $this->company->inventory_notification_threshold) { $this->notifyStocklevels($p, 'company'); } - } }); - - - } private function existingInventoryAdjustment() @@ -189,8 +178,6 @@ class AdjustProductInventory implements ShouldQueue $p->saveQuietly(); } }); - - } private function notifyStocklevels(Product $product, string $notification_level) diff --git a/app/Jobs/Mail/NinjaMailerJob.php b/app/Jobs/Mail/NinjaMailerJob.php index 34ebd668c65e..871595f1c0ef 100644 --- a/app/Jobs/Mail/NinjaMailerJob.php +++ b/app/Jobs/Mail/NinjaMailerJob.php @@ -584,8 +584,9 @@ class NinjaMailerJob implements ShouldQueue $guzzle = new \GuzzleHttp\Client(); $url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'; - if(!$user->oauth_user_refresh_token || $user->oauth_user_refresh_token == '') + if (!$user->oauth_user_refresh_token || $user->oauth_user_refresh_token == '') { return false; + } $token = json_decode($guzzle->post($url, [ 'form_params' => [ diff --git a/app/Jobs/Ninja/AdjustEmailQuota.php b/app/Jobs/Ninja/AdjustEmailQuota.php index 1cec63ab0d04..e8a482b56893 100644 --- a/app/Jobs/Ninja/AdjustEmailQuota.php +++ b/app/Jobs/Ninja/AdjustEmailQuota.php @@ -21,8 +21,9 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Cache; -use Turbo124\Beacon\Facades\LightLogs; use Illuminate\Support\Facades\Redis; +use Turbo124\Beacon\Facades\LightLogs; + class AdjustEmailQuota implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; @@ -78,14 +79,11 @@ class AdjustEmailQuota implements ShouldQueue $keys = $redis->keys($prefix); - if(is_array($keys)) - { + if (is_array($keys)) { $redis->pipeline(function ($pipe) use ($keys) { - foreach ($keys as $key) { $pipe->del($key); } - }); } $keys = null; @@ -101,7 +99,5 @@ class AdjustEmailQuota implements ShouldQueue } }); } - - } } diff --git a/app/Jobs/Ninja/SendReminders.php b/app/Jobs/Ninja/SendReminders.php index 47754da05b6d..884a555cf436 100644 --- a/app/Jobs/Ninja/SendReminders.php +++ b/app/Jobs/Ninja/SendReminders.php @@ -215,7 +215,6 @@ class SendReminders implements ShouldQueue EmailEntity::dispatch($invitation, $invitation->company, $template)->delay(10); event(new InvoiceWasEmailed($invoice->invitations->first(), $invoice->company, Ninja::eventVars(), $template)); - } }); diff --git a/app/Jobs/Payment/EmailPayment.php b/app/Jobs/Payment/EmailPayment.php index ff01b4e9e898..54bc5c00d63f 100644 --- a/app/Jobs/Payment/EmailPayment.php +++ b/app/Jobs/Payment/EmailPayment.php @@ -73,8 +73,9 @@ class EmailPayment implements ShouldQueue $this->payment->load('invoices'); - if(!$this->contact) + if (!$this->contact) { $this->contact = $this->payment->client->contacts()->first(); + } $this->contact->load('client'); diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index ecfb43a5f96c..4ace36d167d6 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -811,7 +811,7 @@ class Import implements ShouldQueue $modified['updated_at'] = Carbon::parse($modified['updated_at']); } - if(!array_key_exists('currency_id', $modified) || !$modified['currency_id']) { + if (!array_key_exists('currency_id', $modified) || !$modified['currency_id']) { $modified['currency_id'] = $this->company->settings->currency_id; } diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php index bf56b28546fe..df52f0084b15 100644 --- a/app/Jobs/Util/ReminderJob.php +++ b/app/Jobs/Util/ReminderJob.php @@ -11,24 +11,22 @@ namespace App\Jobs\Util; -use App\Utils\Ninja; -use App\Models\Invoice; -use App\Libraries\MultiDB; -use Illuminate\Bus\Queueable; -use Illuminate\Support\Carbon; use App\DataMapper\InvoiceItem; use App\Jobs\Entity\EmailEntity; -use App\Models\TransactionEvent; -use App\Utils\Traits\MakesDates; use App\Jobs\Ninja\TransactionLog; -use Illuminate\Support\Facades\App; +use App\Libraries\MultiDB; +use App\Models\Invoice; +use App\Models\TransactionEvent; +use App\Utils\Ninja; +use App\Utils\Traits\MakesDates; use App\Utils\Traits\MakesReminders; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; -use App\Events\Invoice\InvoiceWasEmailed; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; -use App\Events\Invoice\InvoiceReminderWasEmailed; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\App; class ReminderJob implements ShouldQueue { diff --git a/app/Listeners/Payment/PaymentBalanceActivity.php b/app/Listeners/Payment/PaymentBalanceActivity.php index 23d021e1c12c..d04dcaf5ffa8 100644 --- a/app/Listeners/Payment/PaymentBalanceActivity.php +++ b/app/Listeners/Payment/PaymentBalanceActivity.php @@ -12,8 +12,8 @@ namespace App\Listeners\Payment; use App\Libraries\MultiDB; -use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\WithoutOverlapping; class PaymentBalanceActivity implements ShouldQueue @@ -35,11 +35,9 @@ class PaymentBalanceActivity implements ShouldQueue */ public function handle($event) { - MultiDB::setDb($event->company->db); $event->payment->client->service()->updatePaymentBalance(); - } public function middleware($event): array diff --git a/app/Listeners/Payment/PaymentEmailedActivity.php b/app/Listeners/Payment/PaymentEmailedActivity.php index 5fcf3e765abd..16149f9cd3d1 100644 --- a/app/Listeners/Payment/PaymentEmailedActivity.php +++ b/app/Listeners/Payment/PaymentEmailedActivity.php @@ -11,15 +11,13 @@ namespace App\Listeners\Payment; -use App\Models\Activity; use App\Libraries\MultiDB; +use App\Models\Activity; use App\Repositories\ActivityRepository; use Illuminate\Contracts\Queue\ShouldQueue; -use App\Utils\Traits\Notifications\UserNotifies; class PaymentEmailedActivity implements ShouldQueue { - protected $activity_repo; /** @@ -52,6 +50,5 @@ class PaymentEmailedActivity implements ShouldQueue $fields->payment_id = $event->payment->id; $this->activity_repo->save($fields, $event->payment, $event->event_vars); - } } diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php index 215949837570..b16cd3f7133a 100644 --- a/app/Mail/Engine/PaymentEmailEngine.php +++ b/app/Mail/Engine/PaymentEmailEngine.php @@ -362,7 +362,7 @@ class PaymentEmailEngine extends BaseEmailEngine /** * generateLabelsAndValues - * + * * @return array */ public function generateLabelsAndValues(): array @@ -388,11 +388,9 @@ class PaymentEmailEngine extends BaseEmailEngine */ private function buildViewButton(string $link, string $text): string { - - - if ($this->settings->email_style == 'plain') { - return ''. $text .''; - } + if ($this->settings->email_style == 'plain') { + return ''. $text .''; + } return ' diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index aa1105b852a9..56603bf3f05b 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -134,7 +134,7 @@ class Gateway extends StaticModel GatewayType::PAYPAL => ['refund' => false, 'token_billing' => false], ]; //Paypal case 20: - case 56: + case 56: return [ GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true, 'webhooks' => ['payment_intent.succeeded', 'payment_intent.payment_failed']], GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'customer.source.updated','payment_intent.processing', 'payment_intent.payment_failed']], diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 70da83de1bdd..b7d9d47e7565 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -311,7 +311,6 @@ class Payment extends BaseModel $pt = new PaymentType(); return $pt->name($this->type_id); - } public function gateway_type() diff --git a/app/Models/PaymentType.php b/app/Models/PaymentType.php index a9529e0963ee..528d0be6a74f 100644 --- a/app/Models/PaymentType.php +++ b/app/Models/PaymentType.php @@ -152,8 +152,9 @@ class PaymentType extends StaticModel public function name($id) { - if(isset($this->type_names[$id])) + if (isset($this->type_names[$id])) { return ctrans("texts.".$this->type_names[$id]); + } return ctrans('texts.manual_entry'); } diff --git a/app/Models/Product.php b/app/Models/Product.php index ac34c8f43cb2..29174daaf466 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -12,8 +12,8 @@ namespace App\Models; use App\Utils\Traits\MakesHash; -use League\CommonMark\CommonMarkConverter; use Illuminate\Database\Eloquent\SoftDeletes; +use League\CommonMark\CommonMarkConverter; /** * App\Models\Product diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index 1508a5944a19..84ca29d6f31d 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -263,7 +263,7 @@ class Vendor extends BaseModel public function getMergedSettings() :object { return $this->company->settings; - } + } public function purchase_order_filepath($invitation) { diff --git a/app/Notifications/Ninja/EmailQualityNotification.php b/app/Notifications/Ninja/EmailQualityNotification.php index dcba5702604b..ee1a32f6d8c1 100644 --- a/app/Notifications/Ninja/EmailQualityNotification.php +++ b/app/Notifications/Ninja/EmailQualityNotification.php @@ -12,7 +12,6 @@ namespace App\Notifications\Ninja; use App\Models\Company; -use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index b746e17299ca..42f0f553ff38 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -11,36 +11,36 @@ namespace App\PaymentDrivers; -use App\Utils\Ninja; -use App\Utils\Number; +use App\Events\Invoice\InvoiceWasPaid; +use App\Events\Payment\PaymentWasCreated; +use App\Exceptions\PaymentFailed; +use App\Factory\PaymentFactory; +use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; +use App\Jobs\Mail\NinjaMailer; +use App\Jobs\Mail\NinjaMailerJob; +use App\Jobs\Mail\NinjaMailerObject; +use App\Jobs\Mail\PaymentFailedMailer; +use App\Jobs\Util\SystemLogger; +use App\Mail\Admin\ClientPaymentFailureObject; use App\Models\Client; -use App\Utils\Helpers; +use App\Models\ClientContact; +use App\Models\ClientGatewayToken; +use App\Models\CompanyGateway; +use App\Models\GatewayType; use App\Models\Invoice; use App\Models\Payment; -use App\Models\SystemLog; -use App\Models\GatewayType; use App\Models\PaymentHash; -use Illuminate\Support\Str; -use Illuminate\Http\Request; -use App\Models\ClientContact; -use App\Jobs\Mail\NinjaMailer; -use App\Models\CompanyGateway; -use Illuminate\Support\Carbon; -use App\Factory\PaymentFactory; -use App\Jobs\Util\SystemLogger; -use App\Utils\Traits\MakesHash; -use App\Exceptions\PaymentFailed; -use App\Jobs\Mail\NinjaMailerJob; -use App\Models\ClientGatewayToken; -use Illuminate\Support\Facades\App; -use App\Jobs\Mail\NinjaMailerObject; -use App\Utils\Traits\SystemLogTrait; -use App\Events\Invoice\InvoiceWasPaid; -use App\Jobs\Mail\PaymentFailedMailer; -use App\Events\Payment\PaymentWasCreated; -use App\Mail\Admin\ClientPaymentFailureObject; +use App\Models\SystemLog; use App\Services\Subscription\SubscriptionService; -use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; +use App\Utils\Helpers; +use App\Utils\Ninja; +use App\Utils\Number; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SystemLogTrait; +use Illuminate\Http\Request; +use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\App; +use Illuminate\Support\Str; /** * Class BaseDriver. @@ -749,11 +749,10 @@ class BaseDriver extends AbstractPaymentDriver return ctrans('texts.gateway_payment_text', [ 'invoices' => $invoices_string, 'amount' => $amount, - 'client' => $this->client->present()->name(), + 'client' => $this->client->present()->name(), ]); return sprintf('%s: %s', ctrans('texts.invoices'), \implode(', ', collect($this->payment_hash->invoices())->pluck('invoice_number')->toArray())); - } /** diff --git a/app/PaymentDrivers/Braintree/CreditCard.php b/app/PaymentDrivers/Braintree/CreditCard.php index c8dbeba2c8a7..76945859519a 100644 --- a/app/PaymentDrivers/Braintree/CreditCard.php +++ b/app/PaymentDrivers/Braintree/CreditCard.php @@ -140,7 +140,6 @@ class CreditCard try { $result = $this->braintree->gateway->transaction()->sale($data); - } catch (\Exception $e) { if ($e instanceof \Braintree\Exception\Authorization) { $this->braintree->sendFailureMail(ctrans('texts.generic_gateway_error')); diff --git a/app/PaymentDrivers/CustomPaymentDriver.php b/app/PaymentDrivers/CustomPaymentDriver.php index a99bdd4123fe..7a28833ed5d0 100644 --- a/app/PaymentDrivers/CustomPaymentDriver.php +++ b/app/PaymentDrivers/CustomPaymentDriver.php @@ -12,16 +12,16 @@ namespace App\PaymentDrivers; +use App\Jobs\Util\SystemLogger; +use App\Models\ClientGatewayToken; +use App\Models\GatewayType; use App\Models\Invoice; use App\Models\Payment; -use App\Models\SystemLog; -use App\Utils\HtmlEngine; -use App\Models\GatewayType; use App\Models\PaymentHash; use App\Models\PaymentType; -use App\Jobs\Util\SystemLogger; +use App\Models\SystemLog; +use App\Utils\HtmlEngine; use App\Utils\Traits\MakesHash; -use App\Models\ClientGatewayToken; /** * Class CustomPaymentDriver. @@ -97,9 +97,7 @@ class CustomPaymentDriver extends BaseDriver */ public function processPaymentResponse($request) { - if ($request->has('gateway_response')) { - $this->client = auth()->guard('contact')->user()->client; $state = [ @@ -109,8 +107,7 @@ class CustomPaymentDriver extends BaseDriver $payment_hash = PaymentHash::where('hash', $request->payment_hash)->first(); - if($payment_hash) - { + if ($payment_hash) { $this->payment_hash = $payment_hash; $payment_hash->data = array_merge((array) $payment_hash->data, $state); @@ -122,27 +119,26 @@ class CustomPaymentDriver extends BaseDriver if ($gateway_response->status == 'COMPLETED') { $this->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $payment_hash], SystemLog::TYPE_CUSTOM); - $data = [ - 'payment_method' => '', - 'payment_type' => PaymentType::CREDIT_CARD_OTHER, - 'amount' => $payment_hash->amount_with_fee(), - 'transaction_reference' => $gateway_response?->purchase_units[0]?->payments?->captures[0]?->id, - 'gateway_type_id' => GatewayType::PAYPAL, - ]; + $data = [ + 'payment_method' => '', + 'payment_type' => PaymentType::CREDIT_CARD_OTHER, + 'amount' => $payment_hash->amount_with_fee(), + 'transaction_reference' => $gateway_response?->purchase_units[0]?->payments?->captures[0]?->id, + 'gateway_type_id' => GatewayType::PAYPAL, + ]; - $payment = $this->createPayment($data, Payment::STATUS_COMPLETED); + $payment = $this->createPayment($data, Payment::STATUS_COMPLETED); - SystemLogger::dispatch( - ['response' => $payment_hash->data->server_response, 'data' => $data], - SystemLog::CATEGORY_GATEWAY_RESPONSE, - SystemLog::EVENT_GATEWAY_SUCCESS, - SystemLog::TYPE_STRIPE, - $this->client, - $this->client->company, - ); - - return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); + SystemLogger::dispatch( + ['response' => $payment_hash->data->server_response, 'data' => $data], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_STRIPE, + $this->client, + $this->client->company, + ); + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); } } diff --git a/app/PaymentDrivers/GoCardless/DirectDebit.php b/app/PaymentDrivers/GoCardless/DirectDebit.php index 2fec81223f84..4de93dc8dfc8 100644 --- a/app/PaymentDrivers/GoCardless/DirectDebit.php +++ b/app/PaymentDrivers/GoCardless/DirectDebit.php @@ -138,7 +138,7 @@ class DirectDebit implements MethodInterface private function resolveScheme(string $scheme): int { - match($scheme){ + match ($scheme) { 'sepa_core' => $type = GatewayType::SEPA, default => $type = GatewayType::DIRECT_DEBIT, }; diff --git a/app/PaymentDrivers/GoCardlessPaymentDriver.php b/app/PaymentDrivers/GoCardlessPaymentDriver.php index 91d845997a3f..869924adebf8 100644 --- a/app/PaymentDrivers/GoCardlessPaymentDriver.php +++ b/app/PaymentDrivers/GoCardlessPaymentDriver.php @@ -416,14 +416,12 @@ class GoCardlessPaymentDriver extends BaseDriver private function updatePaymentMethods($customer, Client $client): void { - $this->client = $client; $mandates = $this->gateway->mandates()->list(); - foreach($mandates->records as $mandate) - { - if($customer->id != $mandate->links->customer || $mandate->status != 'active' || ClientGatewayToken::where('token', $mandate->id)->where('gateway_customer_reference', $customer->id)->exists()) { + foreach ($mandates->records as $mandate) { + if ($customer->id != $mandate->links->customer || $mandate->status != 'active' || ClientGatewayToken::where('token', $mandate->id)->where('gateway_customer_reference', $customer->id)->exists()) { continue; } @@ -432,12 +430,10 @@ class GoCardlessPaymentDriver extends BaseDriver if ($mandate->scheme == 'bacs') { $payment_meta->brand = ctrans('texts.payment_type_direct_debit'); $payment_meta->type = GatewayType::DIRECT_DEBIT; - } - elseif($mandate->scheme == 'sepa_core') { + } elseif ($mandate->scheme == 'sepa_core') { $payment_meta->brand = ctrans('texts.sepa'); $payment_meta->type = GatewayType::SEPA; - } - else { + } else { continue; } @@ -451,7 +447,6 @@ class GoCardlessPaymentDriver extends BaseDriver $payment_method = $this->storeGatewayToken($data, ['gateway_customer_reference' => $mandate->links->customer]); } - } /* diff --git a/app/PaymentDrivers/Stripe/ACH.php b/app/PaymentDrivers/Stripe/ACH.php index 1a3473fc67d9..75789084245c 100644 --- a/app/PaymentDrivers/Stripe/ACH.php +++ b/app/PaymentDrivers/Stripe/ACH.php @@ -356,8 +356,7 @@ class ACH $response = json_decode($request->gateway_response); $bank_account_response = json_decode($request->bank_account_response); - if($response->status == 'requires_source_action' && $response->next_action->type == 'verify_with_microdeposits') - { + if ($response->status == 'requires_source_action' && $response->next_action->type == 'verify_with_microdeposits') { $method = $bank_account_response->payment_method->us_bank_account; $method = $bank_account_response->payment_method->us_bank_account; $method->id = $response->payment_method; @@ -561,7 +560,7 @@ class ACH $payment_meta->type = GatewayType::BANK_TRANSFER; $payment_meta->state = $state; - if(property_exists($method, 'next_action')) { + if (property_exists($method, 'next_action')) { $payment_meta->next_action = $method->next_action; } diff --git a/app/PaymentDrivers/Stripe/ACSS.php b/app/PaymentDrivers/Stripe/ACSS.php index 0cfa8f0812f4..2b60283d1839 100644 --- a/app/PaymentDrivers/Stripe/ACSS.php +++ b/app/PaymentDrivers/Stripe/ACSS.php @@ -185,7 +185,6 @@ class ACSS $this->stripe->payment_hash->save(); if (property_exists($gateway_response, 'status') && $gateway_response->status == 'processing') { - return $this->processSuccessfulPayment($gateway_response->id); } diff --git a/app/PaymentDrivers/Stripe/Alipay.php b/app/PaymentDrivers/Stripe/Alipay.php index 01a5329bc700..b3eb136ba236 100644 --- a/app/PaymentDrivers/Stripe/Alipay.php +++ b/app/PaymentDrivers/Stripe/Alipay.php @@ -33,7 +33,6 @@ class Alipay public function paymentView(array $data) { - $intent = \Stripe\PaymentIntent::create([ 'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()), 'currency' => $this->stripe->client->currency()->code, @@ -76,8 +75,7 @@ class Alipay $this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, $request->all()); $this->stripe->payment_hash->save(); - if($request->payment_intent){ - + if ($request->payment_intent) { $pi = \Stripe\PaymentIntent::retrieve( $request->payment_intent, $this->stripe->stripe_connect_auth @@ -89,10 +87,9 @@ class Alipay return $this->processSuccesfulRedirect($pi); } - if($pi->status == 'requires_source_action') { + if ($pi->status == 'requires_source_action') { return redirect($pi->next_action->alipay_handle_redirect->url); } - } return $this->processUnsuccesfulRedirect(); diff --git a/app/PaymentDrivers/Stripe/BACS.php b/app/PaymentDrivers/Stripe/BACS.php index b7fde1e47b30..3e649eef124b 100644 --- a/app/PaymentDrivers/Stripe/BACS.php +++ b/app/PaymentDrivers/Stripe/BACS.php @@ -20,12 +20,10 @@ use App\Models\GatewayType; use App\Models\Payment; use App\Models\PaymentType; use App\Models\SystemLog; -use App\PaymentDrivers\StripePaymentDriver; use App\PaymentDrivers\Stripe\Jobs\UpdateCustomer; -use Stripe\Checkout\Session; -use Stripe\PaymentIntent; -use Stripe\PaymentMethod; +use App\PaymentDrivers\StripePaymentDriver; use App\Utils\Number; +use Stripe\Checkout\Session; class BACS { @@ -78,7 +76,6 @@ class BACS return render('gateways.stripe.bacs.pay', $data); } public function paymentResponse(PaymentResponseRequest $request) - { $this->stripe->init(); $invoice_numbers = collect($this->stripe->payment_hash->invoices())->pluck('invoice_number')->implode(','); @@ -183,7 +180,7 @@ class BACS $clientgateway = ClientGatewayToken::query() ->where('token', $method->id) ->first(); - if (!$clientgateway){ + if (!$clientgateway) { $this->stripe->storeGatewayToken($data, ['gateway_customer_reference' => $customer->id]); } } catch (\Exception $e) { diff --git a/app/PaymentDrivers/Stripe/Charge.php b/app/PaymentDrivers/Stripe/Charge.php index da7263502309..fbed56e34e41 100644 --- a/app/PaymentDrivers/Stripe/Charge.php +++ b/app/PaymentDrivers/Stripe/Charge.php @@ -136,15 +136,11 @@ class Charge if ($cgt->gateway_type_id == GatewayType::SEPA) { $payment_method_type = PaymentType::SEPA; $status = Payment::STATUS_PENDING; - - } elseif ($cgt->gateway_type_id == GatewayType::BACS){ + } elseif ($cgt->gateway_type_id == GatewayType::BACS) { $payment_method_type = PaymentType::BACS; $status = Payment::STATUS_PENDING; - } - else { - - if(isset($response->latest_charge)) { - + } else { + if (isset($response->latest_charge)) { $charge = \Stripe\Charge::retrieve($response->latest_charge, $this->stripe->stripe_connect_auth); $payment_method_type = $charge->payment_method_details->card->brand; } elseif (isset($response->charges->data[0]->payment_method_details->card->brand)) { @@ -157,9 +153,8 @@ class Charge } - if(!in_array($response?->status, ['succeeded', 'processing'])){ - $this->stripe->processInternallyFailedPayment($this->stripe, new \Exception('Auto billing failed.',400)); - + if (!in_array($response?->status, ['succeeded', 'processing'])) { + $this->stripe->processInternallyFailedPayment($this->stripe, new \Exception('Auto billing failed.', 400)); } $data = [ diff --git a/app/PaymentDrivers/Stripe/CreditCard.php b/app/PaymentDrivers/Stripe/CreditCard.php index e53ffe3da27f..7816e3c9a9f3 100644 --- a/app/PaymentDrivers/Stripe/CreditCard.php +++ b/app/PaymentDrivers/Stripe/CreditCard.php @@ -21,7 +21,6 @@ use App\Models\PaymentType; use App\Models\SystemLog; use App\PaymentDrivers\Stripe\Jobs\UpdateCustomer; use App\PaymentDrivers\StripePaymentDriver; -use App\Utils\Number; use Stripe\PaymentIntent; use Stripe\PaymentMethod; diff --git a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentPartiallyFundedWebhook.php b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentPartiallyFundedWebhook.php index 382ac5569110..d30fa0695581 100644 --- a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentPartiallyFundedWebhook.php +++ b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentPartiallyFundedWebhook.php @@ -50,7 +50,7 @@ class PaymentIntentPartiallyFundedWebhook implements ShouldQueue $payment_intent = $transaction['id']; } - if(!$payment_intent){ + if (!$payment_intent) { nlog("payment intent not found"); nlog($transaction); return; @@ -61,7 +61,7 @@ class PaymentIntentPartiallyFundedWebhook implements ShouldQueue ->where('transaction_reference', $payment_intent) ->first(); - if(!$payment){ + if (!$payment) { nlog("paymentintent found but no payment"); } diff --git a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentProcessingWebhook.php b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentProcessingWebhook.php index 5725e56dc95f..28f3b92c5d4c 100644 --- a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentProcessingWebhook.php +++ b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentProcessingWebhook.php @@ -79,11 +79,10 @@ class PaymentIntentProcessingWebhook implements ShouldQueue $this->payment_completed = true; } - if(isset($transaction['payment_method'])) - { + if (isset($transaction['payment_method'])) { $cgt = ClientGatewayToken::where('token', $transaction['payment_method'])->first(); - if($cgt && $cgt->meta?->state == 'unauthorized'){ + if ($cgt && $cgt->meta?->state == 'unauthorized') { $meta = $cgt->meta; $meta->state = 'authorized'; $cgt->meta = $meta; diff --git a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentWebhook.php b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentWebhook.php index 5f04159130f8..70417665ae49 100644 --- a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentWebhook.php +++ b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentWebhook.php @@ -120,9 +120,8 @@ class PaymentIntentWebhook implements ShouldQueue ->where('transaction_reference', $charge['id']) ->first(); - //return early - if($payment && $payment->status_id == Payment::STATUS_COMPLETED){ - + //return early + if ($payment && $payment->status_id == Payment::STATUS_COMPLETED) { nlog(" payment found and status correct - returning "); return; } elseif ($payment) { @@ -188,11 +187,9 @@ class PaymentIntentWebhook implements ShouldQueue } $this->updateAchPayment($payment_hash, $client, $meta); - } elseif(isset($pi['payment_method_types']) && in_array('bacs_debit', $pi['payment_method_types'])){ + } elseif (isset($pi['payment_method_types']) && in_array('bacs_debit', $pi['payment_method_types'])) { return; } - - } private function updateAchPayment($payment_hash, $client, $meta) @@ -260,9 +257,7 @@ class PaymentIntentWebhook implements ShouldQueue } $driver->storeGatewayToken($data, $additional_data); - } catch(\Exception $e) { - nlog("failed to import payment methods"); nlog($e->getMessage()); } @@ -297,5 +292,4 @@ class PaymentIntentWebhook implements ShouldQueue $client->company, ); } - } diff --git a/app/PaymentDrivers/Stripe/Klarna.php b/app/PaymentDrivers/Stripe/Klarna.php index c794a4e22b53..97067dfb2c9c 100644 --- a/app/PaymentDrivers/Stripe/Klarna.php +++ b/app/PaymentDrivers/Stripe/Klarna.php @@ -19,7 +19,6 @@ use App\Models\Payment; use App\Models\PaymentType; use App\Models\SystemLog; use App\PaymentDrivers\StripePaymentDriver; -use App\Utils\Number; class Klarna { diff --git a/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php b/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php index 6034f62ba448..a06daa855b50 100644 --- a/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php +++ b/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php @@ -99,7 +99,6 @@ class UpdatePaymentMethods /* Already exists return */ if ($token) { - $meta = $token->meta; $meta->state = 'authorized'; $token->meta = $meta; diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index ee187536c11b..8e813802b13c 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -12,55 +12,54 @@ namespace App\PaymentDrivers; -use Exception; -use Stripe\Stripe; -use Stripe\Account; -use Stripe\Customer; -use App\Models\Payment; -use Stripe\SetupIntent; -use Stripe\StripeClient; -use App\Models\SystemLog; -use Stripe\PaymentIntent; -use Stripe\PaymentMethod; -use App\Models\GatewayType; -use App\Models\PaymentHash; +use App\Exceptions\PaymentFailed; +use App\Exceptions\StripeConnectFailure; +use App\Http\Requests\Payments\PaymentWebhookRequest; use App\Http\Requests\Request; use App\Jobs\Util\SystemLogger; use App\Models\Client; -use App\Utils\Traits\MakesHash; -use App\Exceptions\PaymentFailed; use App\Models\ClientGatewayToken; +use App\Models\GatewayType; +use App\Models\Payment; +use App\Models\PaymentHash; +use App\Models\SystemLog; use App\PaymentDrivers\Stripe\ACH; -use App\PaymentDrivers\Stripe\EPS; -use App\PaymentDrivers\Stripe\FPX; use App\PaymentDrivers\Stripe\ACSS; use App\PaymentDrivers\Stripe\Alipay; use App\PaymentDrivers\Stripe\BACS; -use App\PaymentDrivers\Stripe\BECS; -use App\PaymentDrivers\Stripe\SEPA; -use App\PaymentDrivers\Stripe\iDeal; -use App\PaymentDrivers\Stripe\Charge; -use App\PaymentDrivers\Stripe\Klarna; -use App\PaymentDrivers\Stripe\SOFORT; -use Illuminate\Http\RedirectResponse; -use App\PaymentDrivers\Stripe\GIROPAY; -use Stripe\Exception\ApiErrorException; -use App\Exceptions\StripeConnectFailure; -use App\PaymentDrivers\Stripe\Utilities; use App\PaymentDrivers\Stripe\Bancontact; -use App\PaymentDrivers\Stripe\BrowserPay; -use App\PaymentDrivers\Stripe\CreditCard; -use App\PaymentDrivers\Stripe\PRZELEWY24; use App\PaymentDrivers\Stripe\BankTransfer; +use App\PaymentDrivers\Stripe\BECS; +use App\PaymentDrivers\Stripe\BrowserPay; +use App\PaymentDrivers\Stripe\Charge; use App\PaymentDrivers\Stripe\Connect\Verify; +use App\PaymentDrivers\Stripe\CreditCard; +use App\PaymentDrivers\Stripe\EPS; +use App\PaymentDrivers\Stripe\FPX; +use App\PaymentDrivers\Stripe\GIROPAY; +use App\PaymentDrivers\Stripe\iDeal; use App\PaymentDrivers\Stripe\ImportCustomers; -use App\Http\Requests\Payments\PaymentWebhookRequest; -use Laracasts\Presenter\Exceptions\PresenterException; -use App\PaymentDrivers\Stripe\Jobs\PaymentIntentWebhook; use App\PaymentDrivers\Stripe\Jobs\PaymentIntentFailureWebhook; -use App\PaymentDrivers\Stripe\Jobs\PaymentIntentProcessingWebhook; use App\PaymentDrivers\Stripe\Jobs\PaymentIntentPartiallyFundedWebhook; - +use App\PaymentDrivers\Stripe\Jobs\PaymentIntentProcessingWebhook; +use App\PaymentDrivers\Stripe\Jobs\PaymentIntentWebhook; +use App\PaymentDrivers\Stripe\Klarna; +use App\PaymentDrivers\Stripe\PRZELEWY24; +use App\PaymentDrivers\Stripe\SEPA; +use App\PaymentDrivers\Stripe\SOFORT; +use App\PaymentDrivers\Stripe\Utilities; +use App\Utils\Traits\MakesHash; +use Exception; +use Illuminate\Http\RedirectResponse; +use Laracasts\Presenter\Exceptions\PresenterException; +use Stripe\Account; +use Stripe\Customer; +use Stripe\Exception\ApiErrorException; +use Stripe\PaymentIntent; +use Stripe\PaymentMethod; +use Stripe\SetupIntent; +use Stripe\Stripe; +use Stripe\StripeClient; class StripePaymentDriver extends BaseDriver { @@ -446,11 +445,10 @@ class StripePaymentDriver extends BaseDriver { $this->init(); - return PaymentIntent::retrieve( - $payment_intent_id, - $this->stripe_connect_auth - ); - + return PaymentIntent::retrieve( + $payment_intent_id, + $this->stripe_connect_auth + ); } /** @@ -667,7 +665,6 @@ class StripePaymentDriver extends BaseDriver public function processWebhookRequest(PaymentWebhookRequest $request) { - if ($request->type === 'customer.source.updated') { $ach = new ACH($this); $ach->updateBankAccount($request->all()); @@ -754,12 +751,11 @@ class StripePaymentDriver extends BaseDriver } } } - } elseif ($request->type === "payment_method.automatically_updated"){ + } elseif ($request->type === "payment_method.automatically_updated") { // Will notify customer on updated information return response()->json([], 200); - } elseif ($request->type === "mandate.updated"){ - - if ($request->data['object']['status'] == "active"){ + } elseif ($request->type === "mandate.updated") { + if ($request->data['object']['status'] == "active") { // Check if payment method existsn $payment_method = (string) $request->data['object']['payment_method']; @@ -767,18 +763,15 @@ class StripePaymentDriver extends BaseDriver ->where('token', $payment_method) ->first(); - if ($clientgateway){ - + if ($clientgateway) { $meta = $clientgateway->meta; $meta->state = 'authorized'; $clientgateway->meta = $meta; $clientgateway->save(); - } return response()->json([], 200); - } - elseif ($request->data['object']['status'] == "inactive" && $request->data['object']['payment_method']){ + } elseif ($request->data['object']['status'] == "inactive" && $request->data['object']['payment_method']) { // Delete payment method $clientgateway = ClientGatewayToken::query() ->where('token', $request->data['object']['payment_method']) @@ -787,8 +780,7 @@ class StripePaymentDriver extends BaseDriver $clientgateway->delete(); return response()->json([], 200); - } - elseif ($request->data['object']['status'] == "pending"){ + } elseif ($request->data['object']['status'] == "pending") { return response()->json([], 200); } } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index ae34c09620cd..1028a0c943cc 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -11,259 +11,259 @@ namespace App\Providers; -use App\Models\Task; -use App\Models\User; -use App\Models\Quote; -use App\Models\Client; -use App\Models\Credit; -use App\Models\Vendor; +use App\Events\Account\AccountCreated; +use App\Events\Client\ClientWasArchived; +use App\Events\Client\ClientWasCreated; +use App\Events\Client\ClientWasDeleted; +use App\Events\Client\ClientWasRestored; +use App\Events\Client\ClientWasUpdated; +use App\Events\Client\DesignWasDeleted; +use App\Events\Client\DesignWasRestored; +use App\Events\Client\DesignWasUpdated; +use App\Events\Company\CompanyDocumentsDeleted; +use App\Events\Contact\ContactLoggedIn; +use App\Events\Credit\CreditWasArchived; +use App\Events\Credit\CreditWasCreated; +use App\Events\Credit\CreditWasDeleted; +use App\Events\Credit\CreditWasEmailed; +use App\Events\Credit\CreditWasEmailedAndFailed; +use App\Events\Credit\CreditWasMarkedSent; +use App\Events\Credit\CreditWasRestored; +use App\Events\Credit\CreditWasUpdated; +use App\Events\Credit\CreditWasViewed; +use App\Events\Design\DesignWasArchived; +use App\Events\Expense\ExpenseWasArchived; +use App\Events\Expense\ExpenseWasCreated; +use App\Events\Expense\ExpenseWasDeleted; +use App\Events\Expense\ExpenseWasRestored; +use App\Events\Expense\ExpenseWasUpdated; +use App\Events\Invoice\InvoiceReminderWasEmailed; +use App\Events\Invoice\InvoiceWasArchived; +use App\Events\Invoice\InvoiceWasCancelled; +use App\Events\Invoice\InvoiceWasCreated; +use App\Events\Invoice\InvoiceWasDeleted; +use App\Events\Invoice\InvoiceWasEmailed; +use App\Events\Invoice\InvoiceWasEmailedAndFailed; +use App\Events\Invoice\InvoiceWasMarkedSent; +use App\Events\Invoice\InvoiceWasPaid; +use App\Events\Invoice\InvoiceWasRestored; +use App\Events\Invoice\InvoiceWasReversed; +use App\Events\Invoice\InvoiceWasUpdated; +use App\Events\Invoice\InvoiceWasViewed; +use App\Events\Misc\InvitationWasViewed; +use App\Events\Payment\PaymentWasArchived; +use App\Events\Payment\PaymentWasCreated; +use App\Events\Payment\PaymentWasDeleted; +use App\Events\Payment\PaymentWasEmailed; +use App\Events\Payment\PaymentWasEmailedAndFailed; +use App\Events\Payment\PaymentWasRefunded; +use App\Events\Payment\PaymentWasRestored; +use App\Events\Payment\PaymentWasUpdated; +use App\Events\Payment\PaymentWasVoided; +use App\Events\PurchaseOrder\PurchaseOrderWasAccepted; +use App\Events\PurchaseOrder\PurchaseOrderWasArchived; +use App\Events\PurchaseOrder\PurchaseOrderWasCreated; +use App\Events\PurchaseOrder\PurchaseOrderWasDeleted; +use App\Events\PurchaseOrder\PurchaseOrderWasEmailed; +use App\Events\PurchaseOrder\PurchaseOrderWasRestored; +use App\Events\PurchaseOrder\PurchaseOrderWasUpdated; +use App\Events\PurchaseOrder\PurchaseOrderWasViewed; +use App\Events\Quote\QuoteWasApproved; +use App\Events\Quote\QuoteWasArchived; +use App\Events\Quote\QuoteWasCreated; +use App\Events\Quote\QuoteWasDeleted; +use App\Events\Quote\QuoteWasEmailed; +use App\Events\Quote\QuoteWasRestored; +use App\Events\Quote\QuoteWasUpdated; +use App\Events\Quote\QuoteWasViewed; +use App\Events\RecurringExpense\RecurringExpenseWasArchived; +use App\Events\RecurringExpense\RecurringExpenseWasCreated; +use App\Events\RecurringExpense\RecurringExpenseWasDeleted; +use App\Events\RecurringExpense\RecurringExpenseWasRestored; +use App\Events\RecurringExpense\RecurringExpenseWasUpdated; +use App\Events\RecurringInvoice\RecurringInvoiceWasArchived; +use App\Events\RecurringInvoice\RecurringInvoiceWasCreated; +use App\Events\RecurringInvoice\RecurringInvoiceWasDeleted; +use App\Events\RecurringInvoice\RecurringInvoiceWasRestored; +use App\Events\RecurringInvoice\RecurringInvoiceWasUpdated; +use App\Events\RecurringQuote\RecurringQuoteWasArchived; +use App\Events\RecurringQuote\RecurringQuoteWasCreated; +use App\Events\RecurringQuote\RecurringQuoteWasDeleted; +use App\Events\RecurringQuote\RecurringQuoteWasRestored; +use App\Events\RecurringQuote\RecurringQuoteWasUpdated; +use App\Events\Subscription\SubscriptionWasArchived; +use App\Events\Subscription\SubscriptionWasCreated; +use App\Events\Subscription\SubscriptionWasDeleted; +use App\Events\Subscription\SubscriptionWasRestored; +use App\Events\Subscription\SubscriptionWasUpdated; +use App\Events\Task\TaskWasArchived; +use App\Events\Task\TaskWasCreated; +use App\Events\Task\TaskWasDeleted; +use App\Events\Task\TaskWasRestored; +use App\Events\Task\TaskWasUpdated; +use App\Events\User\UserLoggedIn; +use App\Events\User\UserWasArchived; +use App\Events\User\UserWasCreated; +use App\Events\User\UserWasDeleted; +use App\Events\User\UserWasRestored; +use App\Events\User\UserWasUpdated; +use App\Events\Vendor\VendorWasArchived; +use App\Events\Vendor\VendorWasCreated; +use App\Events\Vendor\VendorWasDeleted; +use App\Events\Vendor\VendorWasRestored; +use App\Events\Vendor\VendorWasUpdated; +use App\Listeners\Activity\ArchivedClientActivity; +use App\Listeners\Activity\ClientUpdatedActivity; +use App\Listeners\Activity\CreatedClientActivity; +use App\Listeners\Activity\CreatedCreditActivity; +use App\Listeners\Activity\CreatedExpenseActivity; +use App\Listeners\Activity\CreatedQuoteActivity; +use App\Listeners\Activity\CreatedSubscriptionActivity; +use App\Listeners\Activity\CreatedTaskActivity; +use App\Listeners\Activity\CreatedVendorActivity; +use App\Listeners\Activity\CreditArchivedActivity; +use App\Listeners\Activity\DeleteClientActivity; +use App\Listeners\Activity\DeleteCreditActivity; +use App\Listeners\Activity\ExpenseArchivedActivity; +use App\Listeners\Activity\ExpenseDeletedActivity; +use App\Listeners\Activity\ExpenseRestoredActivity; +use App\Listeners\Activity\ExpenseUpdatedActivity; +use App\Listeners\Activity\PaymentArchivedActivity; +use App\Listeners\Activity\PaymentCreatedActivity; +use App\Listeners\Activity\PaymentDeletedActivity; +use App\Listeners\Activity\PaymentRefundedActivity; +use App\Listeners\Activity\PaymentUpdatedActivity; +use App\Listeners\Activity\PaymentVoidedActivity; +use App\Listeners\Activity\QuoteUpdatedActivity; +use App\Listeners\Activity\RestoreClientActivity; +use App\Listeners\Activity\SubscriptionArchivedActivity; +use App\Listeners\Activity\SubscriptionDeletedActivity; +use App\Listeners\Activity\SubscriptionRestoredActivity; +use App\Listeners\Activity\SubscriptionUpdatedActivity; +use App\Listeners\Activity\TaskArchivedActivity; +use App\Listeners\Activity\TaskDeletedActivity; +use App\Listeners\Activity\TaskRestoredActivity; +use App\Listeners\Activity\TaskUpdatedActivity; +use App\Listeners\Activity\UpdatedCreditActivity; +use App\Listeners\Activity\VendorArchivedActivity; +use App\Listeners\Activity\VendorDeletedActivity; +use App\Listeners\Activity\VendorRestoredActivity; +use App\Listeners\Activity\VendorUpdatedActivity; +use App\Listeners\Contact\UpdateContactLastLogin; +use App\Listeners\Credit\CreditCreatedNotification; +use App\Listeners\Credit\CreditEmailedNotification; +use App\Listeners\Credit\CreditRestoredActivity; +use App\Listeners\Credit\CreditViewedActivity; +use App\Listeners\Document\DeleteCompanyDocuments; +use App\Listeners\Invoice\CreateInvoiceActivity; +use App\Listeners\Invoice\CreateInvoicePdf; +use App\Listeners\Invoice\InvoiceArchivedActivity; +use App\Listeners\Invoice\InvoiceCancelledActivity; +use App\Listeners\Invoice\InvoiceCreatedNotification; +use App\Listeners\Invoice\InvoiceDeletedActivity; +use App\Listeners\Invoice\InvoiceEmailActivity; +use App\Listeners\Invoice\InvoiceEmailedNotification; +use App\Listeners\Invoice\InvoiceEmailFailedActivity; +use App\Listeners\Invoice\InvoiceFailedEmailNotification; +use App\Listeners\Invoice\InvoicePaidActivity; +use App\Listeners\Invoice\InvoiceReminderEmailActivity; +use App\Listeners\Invoice\InvoiceRestoredActivity; +use App\Listeners\Invoice\InvoiceReversedActivity; +use App\Listeners\Invoice\InvoiceViewedActivity; +use App\Listeners\Invoice\UpdateInvoiceActivity; +use App\Listeners\Mail\MailSentListener; +use App\Listeners\Misc\InvitationViewedListener; +use App\Listeners\Payment\PaymentBalanceActivity; +use App\Listeners\Payment\PaymentEmailedActivity; +use App\Listeners\Payment\PaymentNotification; +use App\Listeners\Payment\PaymentRestoredActivity; +use App\Listeners\PurchaseOrder\CreatePurchaseOrderActivity; +use App\Listeners\PurchaseOrder\PurchaseOrderAcceptedActivity; +use App\Listeners\PurchaseOrder\PurchaseOrderAcceptedListener; +use App\Listeners\PurchaseOrder\PurchaseOrderArchivedActivity; +use App\Listeners\PurchaseOrder\PurchaseOrderCreatedListener; +use App\Listeners\PurchaseOrder\PurchaseOrderDeletedActivity; +use App\Listeners\PurchaseOrder\PurchaseOrderEmailActivity; +use App\Listeners\PurchaseOrder\PurchaseOrderEmailedNotification; +use App\Listeners\PurchaseOrder\PurchaseOrderRestoredActivity; +use App\Listeners\PurchaseOrder\PurchaseOrderViewedActivity; +use App\Listeners\PurchaseOrder\UpdatePurchaseOrderActivity; +use App\Listeners\Quote\QuoteApprovedActivity; +use App\Listeners\Quote\QuoteApprovedNotification; +use App\Listeners\Quote\QuoteApprovedWebhook; +use App\Listeners\Quote\QuoteArchivedActivity; +use App\Listeners\Quote\QuoteCreatedNotification; +use App\Listeners\Quote\QuoteDeletedActivity; +use App\Listeners\Quote\QuoteEmailActivity; +use App\Listeners\Quote\QuoteEmailedNotification; +use App\Listeners\Quote\QuoteRestoredActivity; +use App\Listeners\Quote\QuoteViewedActivity; +use App\Listeners\Quote\ReachWorkflowSettings; +use App\Listeners\RecurringExpense\CreatedRecurringExpenseActivity; +use App\Listeners\RecurringExpense\RecurringExpenseArchivedActivity; +use App\Listeners\RecurringExpense\RecurringExpenseDeletedActivity; +use App\Listeners\RecurringExpense\RecurringExpenseRestoredActivity; +use App\Listeners\RecurringExpense\RecurringExpenseUpdatedActivity; +use App\Listeners\RecurringInvoice\CreateRecurringInvoiceActivity; +use App\Listeners\RecurringInvoice\RecurringInvoiceArchivedActivity; +use App\Listeners\RecurringInvoice\RecurringInvoiceDeletedActivity; +use App\Listeners\RecurringInvoice\RecurringInvoiceRestoredActivity; +use App\Listeners\RecurringInvoice\UpdateRecurringInvoiceActivity; +use App\Listeners\RecurringQuote\CreateRecurringQuoteActivity; +use App\Listeners\RecurringQuote\RecurringQuoteArchivedActivity; +use App\Listeners\RecurringQuote\RecurringQuoteDeletedActivity; +use App\Listeners\RecurringQuote\RecurringQuoteRestoredActivity; +use App\Listeners\RecurringQuote\UpdateRecurringQuoteActivity; +use App\Listeners\SendVerificationNotification; +use App\Listeners\User\ArchivedUserActivity; +use App\Listeners\User\CreatedUserActivity; +use App\Listeners\User\DeletedUserActivity; +use App\Listeners\User\RestoredUserActivity; +use App\Listeners\User\UpdatedUserActivity; +use App\Listeners\User\UpdateUserLastLogin; use App\Models\Account; +use App\Models\Client; +use App\Models\ClientContact; use App\Models\Company; +use App\Models\CompanyGateway; +use App\Models\CompanyToken; +use App\Models\Credit; use App\Models\Expense; use App\Models\Invoice; use App\Models\Payment; use App\Models\Product; use App\Models\Project; use App\Models\Proposal; -use App\Models\CompanyToken; -use App\Models\Subscription; -use App\Models\ClientContact; use App\Models\PurchaseOrder; +use App\Models\Quote; +use App\Models\Subscription; +use App\Models\Task; +use App\Models\User; +use App\Models\Vendor; use App\Models\VendorContact; -use App\Models\CompanyGateway; -use App\Observers\TaskObserver; -use App\Observers\UserObserver; -use App\Observers\QuoteObserver; -use App\Events\User\UserLoggedIn; -use App\Observers\ClientObserver; -use App\Observers\CreditObserver; -use App\Observers\VendorObserver; use App\Observers\AccountObserver; +use App\Observers\ClientContactObserver; +use App\Observers\ClientObserver; +use App\Observers\CompanyGatewayObserver; use App\Observers\CompanyObserver; +use App\Observers\CompanyTokenObserver; +use App\Observers\CreditObserver; use App\Observers\ExpenseObserver; use App\Observers\InvoiceObserver; use App\Observers\PaymentObserver; use App\Observers\ProductObserver; use App\Observers\ProjectObserver; -use App\Events\Task\TaskWasCreated; -use App\Events\Task\TaskWasDeleted; -use App\Events\Task\TaskWasUpdated; -use App\Events\User\UserWasCreated; -use App\Events\User\UserWasDeleted; -use App\Events\User\UserWasUpdated; use App\Observers\ProposalObserver; -use App\Events\Quote\QuoteWasViewed; -use App\Events\Task\TaskWasArchived; -use App\Events\Task\TaskWasRestored; -use App\Events\User\UserWasArchived; -use App\Events\User\UserWasRestored; -use App\Events\Quote\QuoteWasCreated; -use App\Events\Quote\QuoteWasDeleted; -use App\Events\Quote\QuoteWasEmailed; -use App\Events\Quote\QuoteWasUpdated; -use App\Events\Account\AccountCreated; -use App\Events\Credit\CreditWasViewed; -use App\Events\Invoice\InvoiceWasPaid; -use App\Events\Quote\QuoteWasApproved; -use App\Events\Quote\QuoteWasArchived; -use App\Events\Quote\QuoteWasRestored; -use App\Events\Client\ClientWasCreated; -use App\Events\Client\ClientWasDeleted; -use App\Events\Client\ClientWasUpdated; -use App\Events\Client\DesignWasDeleted; -use App\Events\Client\DesignWasUpdated; -use App\Events\Contact\ContactLoggedIn; -use App\Events\Credit\CreditWasCreated; -use App\Events\Credit\CreditWasDeleted; -use App\Events\Credit\CreditWasEmailed; -use App\Events\Credit\CreditWasUpdated; -use App\Events\Vendor\VendorWasCreated; -use App\Events\Vendor\VendorWasDeleted; -use App\Events\Vendor\VendorWasUpdated; -use App\Observers\CompanyTokenObserver; -use App\Observers\SubscriptionObserver; -use Illuminate\Mail\Events\MessageSent; -use App\Events\Client\ClientWasArchived; -use App\Events\Client\ClientWasRestored; -use App\Events\Client\DesignWasRestored; -use App\Events\Credit\CreditWasArchived; -use App\Events\Credit\CreditWasRestored; -use App\Events\Design\DesignWasArchived; -use App\Events\Invoice\InvoiceWasViewed; -use App\Events\Misc\InvitationWasViewed; -use App\Events\Payment\PaymentWasVoided; -use App\Events\Vendor\VendorWasArchived; -use App\Events\Vendor\VendorWasRestored; -use App\Listeners\Mail\MailSentListener; -use App\Observers\ClientContactObserver; use App\Observers\PurchaseOrderObserver; +use App\Observers\QuoteObserver; +use App\Observers\SubscriptionObserver; +use App\Observers\TaskObserver; +use App\Observers\UserObserver; use App\Observers\VendorContactObserver; -use App\Events\Expense\ExpenseWasCreated; -use App\Events\Expense\ExpenseWasDeleted; -use App\Events\Expense\ExpenseWasUpdated; -use App\Events\Invoice\InvoiceWasCreated; -use App\Events\Invoice\InvoiceWasDeleted; -use App\Events\Invoice\InvoiceWasEmailed; -use App\Events\Invoice\InvoiceWasUpdated; -use App\Events\Payment\PaymentWasCreated; -use App\Events\Payment\PaymentWasDeleted; -use App\Events\Payment\PaymentWasEmailed; -use App\Events\Payment\PaymentWasUpdated; -use App\Observers\CompanyGatewayObserver; -use App\Events\Credit\CreditWasMarkedSent; -use App\Events\Expense\ExpenseWasArchived; -use App\Events\Expense\ExpenseWasRestored; -use App\Events\Invoice\InvoiceWasArchived; -use App\Events\Invoice\InvoiceWasRestored; -use App\Events\Invoice\InvoiceWasReversed; -use App\Events\Payment\PaymentWasArchived; -use App\Events\Payment\PaymentWasRefunded; -use App\Events\Payment\PaymentWasRestored; -use Illuminate\Mail\Events\MessageSending; -use App\Events\Invoice\InvoiceWasCancelled; -use App\Listeners\Invoice\CreateInvoicePdf; -use App\Listeners\Quote\QuoteEmailActivity; -use App\Listeners\User\CreatedUserActivity; -use App\Listeners\User\DeletedUserActivity; -use App\Listeners\User\UpdatedUserActivity; -use App\Listeners\User\UpdateUserLastLogin; -use App\Events\Invoice\InvoiceWasMarkedSent; -use App\Listeners\Quote\QuoteViewedActivity; -use App\Listeners\User\ArchivedUserActivity; -use App\Listeners\User\RestoredUserActivity; -use App\Listeners\Quote\QuoteApprovedWebhook; -use App\Listeners\Quote\QuoteDeletedActivity; -use App\Listeners\Credit\CreditViewedActivity; -use App\Listeners\Invoice\InvoicePaidActivity; -use App\Listeners\Payment\PaymentNotification; -use App\Listeners\Quote\QuoteApprovedActivity; -use App\Listeners\Quote\QuoteArchivedActivity; -use App\Listeners\Quote\QuoteRestoredActivity; -use App\Listeners\Quote\ReachWorkflowSettings; -use App\Events\Company\CompanyDocumentsDeleted; -use App\Listeners\Activity\CreatedTaskActivity; -use App\Listeners\Activity\TaskDeletedActivity; -use App\Listeners\Activity\TaskUpdatedActivity; -use App\Listeners\Invoice\InvoiceEmailActivity; -use App\Listeners\SendVerificationNotification; -use App\Events\Credit\CreditWasEmailedAndFailed; -use App\Listeners\Activity\CreatedQuoteActivity; -use App\Listeners\Activity\DeleteClientActivity; -use App\Listeners\Activity\DeleteCreditActivity; -use App\Listeners\Activity\QuoteUpdatedActivity; -use App\Listeners\Activity\TaskArchivedActivity; -use App\Listeners\Activity\TaskRestoredActivity; -use App\Listeners\Credit\CreditRestoredActivity; -use App\Listeners\Invoice\CreateInvoiceActivity; -use App\Listeners\Invoice\InvoiceViewedActivity; -use App\Listeners\Invoice\UpdateInvoiceActivity; -use App\Listeners\Misc\InvitationViewedListener; -use App\Events\Invoice\InvoiceReminderWasEmailed; -use App\Listeners\Activity\ClientUpdatedActivity; -use App\Listeners\Activity\CreatedClientActivity; -use App\Listeners\Activity\CreatedCreditActivity; -use App\Listeners\Activity\CreatedVendorActivity; -use App\Listeners\Activity\PaymentVoidedActivity; -use App\Listeners\Activity\RestoreClientActivity; -use App\Listeners\Activity\UpdatedCreditActivity; -use App\Listeners\Activity\VendorDeletedActivity; -use App\Listeners\Activity\VendorUpdatedActivity; -use App\Listeners\Contact\UpdateContactLastLogin; -use App\Listeners\Invoice\InvoiceDeletedActivity; -use App\Listeners\Payment\PaymentBalanceActivity; -use App\Listeners\Payment\PaymentEmailedActivity; -use App\Listeners\Quote\QuoteCreatedNotification; -use App\Listeners\Quote\QuoteEmailedNotification; -use App\Events\Invoice\InvoiceWasEmailedAndFailed; -use App\Events\Payment\PaymentWasEmailedAndFailed; -use App\Listeners\Activity\ArchivedClientActivity; -use App\Listeners\Activity\CreatedExpenseActivity; -use App\Listeners\Activity\CreditArchivedActivity; -use App\Listeners\Activity\ExpenseDeletedActivity; -use App\Listeners\Activity\ExpenseUpdatedActivity; -use App\Listeners\Activity\PaymentCreatedActivity; -use App\Listeners\Activity\PaymentDeletedActivity; -use App\Listeners\Activity\PaymentUpdatedActivity; -use App\Listeners\Activity\VendorArchivedActivity; -use App\Listeners\Activity\VendorRestoredActivity; -use App\Listeners\Document\DeleteCompanyDocuments; -use App\Listeners\Invoice\InvoiceArchivedActivity; -use App\Listeners\Invoice\InvoiceRestoredActivity; -use App\Listeners\Invoice\InvoiceReversedActivity; -use App\Listeners\Payment\PaymentRestoredActivity; -use App\Listeners\Quote\QuoteApprovedNotification; -use App\Events\Subscription\SubscriptionWasCreated; -use App\Events\Subscription\SubscriptionWasDeleted; -use App\Events\Subscription\SubscriptionWasUpdated; -use App\Listeners\Activity\ExpenseArchivedActivity; -use App\Listeners\Activity\ExpenseRestoredActivity; -use App\Listeners\Activity\PaymentArchivedActivity; -use App\Listeners\Activity\PaymentRefundedActivity; -use App\Listeners\Credit\CreditCreatedNotification; -use App\Listeners\Credit\CreditEmailedNotification; -use App\Listeners\Invoice\InvoiceCancelledActivity; -use App\Events\PurchaseOrder\PurchaseOrderWasViewed; -use App\Events\Subscription\SubscriptionWasArchived; -use App\Events\Subscription\SubscriptionWasRestored; -use App\Events\PurchaseOrder\PurchaseOrderWasCreated; -use App\Events\PurchaseOrder\PurchaseOrderWasDeleted; -use App\Events\PurchaseOrder\PurchaseOrderWasEmailed; -use App\Events\PurchaseOrder\PurchaseOrderWasUpdated; -use App\Listeners\Invoice\InvoiceCreatedNotification; -use App\Listeners\Invoice\InvoiceEmailedNotification; -use App\Listeners\Invoice\InvoiceEmailFailedActivity; -use App\Events\PurchaseOrder\PurchaseOrderWasAccepted; -use App\Events\PurchaseOrder\PurchaseOrderWasArchived; -use App\Events\PurchaseOrder\PurchaseOrderWasRestored; -use App\Events\RecurringQuote\RecurringQuoteWasCreated; -use App\Events\RecurringQuote\RecurringQuoteWasDeleted; -use App\Events\RecurringQuote\RecurringQuoteWasUpdated; -use App\Listeners\Activity\CreatedSubscriptionActivity; -use App\Listeners\Activity\SubscriptionDeletedActivity; -use App\Listeners\Activity\SubscriptionUpdatedActivity; -use App\Listeners\Invoice\InvoiceReminderEmailActivity; -use App\Events\RecurringQuote\RecurringQuoteWasArchived; -use App\Events\RecurringQuote\RecurringQuoteWasRestored; -use App\Listeners\Activity\SubscriptionArchivedActivity; -use App\Listeners\Activity\SubscriptionRestoredActivity; -use App\Listeners\Invoice\InvoiceFailedEmailNotification; -use App\Events\RecurringExpense\RecurringExpenseWasCreated; -use App\Events\RecurringExpense\RecurringExpenseWasDeleted; -use App\Events\RecurringExpense\RecurringExpenseWasUpdated; -use App\Events\RecurringInvoice\RecurringInvoiceWasCreated; -use App\Events\RecurringInvoice\RecurringInvoiceWasDeleted; -use App\Events\RecurringInvoice\RecurringInvoiceWasUpdated; -use App\Listeners\PurchaseOrder\PurchaseOrderEmailActivity; -use App\Events\RecurringExpense\RecurringExpenseWasArchived; -use App\Events\RecurringExpense\RecurringExpenseWasRestored; -use App\Events\RecurringInvoice\RecurringInvoiceWasArchived; -use App\Events\RecurringInvoice\RecurringInvoiceWasRestored; -use App\Listeners\PurchaseOrder\CreatePurchaseOrderActivity; -use App\Listeners\PurchaseOrder\PurchaseOrderViewedActivity; -use App\Listeners\PurchaseOrder\UpdatePurchaseOrderActivity; -use App\Listeners\PurchaseOrder\PurchaseOrderCreatedListener; -use App\Listeners\PurchaseOrder\PurchaseOrderDeletedActivity; -use App\Listeners\PurchaseOrder\PurchaseOrderAcceptedActivity; -use App\Listeners\PurchaseOrder\PurchaseOrderAcceptedListener; -use App\Listeners\PurchaseOrder\PurchaseOrderArchivedActivity; -use App\Listeners\PurchaseOrder\PurchaseOrderRestoredActivity; -use App\Listeners\RecurringQuote\CreateRecurringQuoteActivity; -use App\Listeners\RecurringQuote\UpdateRecurringQuoteActivity; -use App\Listeners\RecurringQuote\RecurringQuoteDeletedActivity; -use App\Listeners\RecurringQuote\RecurringQuoteArchivedActivity; -use App\Listeners\RecurringQuote\RecurringQuoteRestoredActivity; -use App\Listeners\PurchaseOrder\PurchaseOrderEmailedNotification; -use App\Listeners\RecurringInvoice\CreateRecurringInvoiceActivity; -use App\Listeners\RecurringInvoice\UpdateRecurringInvoiceActivity; -use App\Listeners\RecurringExpense\CreatedRecurringExpenseActivity; -use App\Listeners\RecurringExpense\RecurringExpenseDeletedActivity; -use App\Listeners\RecurringExpense\RecurringExpenseUpdatedActivity; -use App\Listeners\RecurringInvoice\RecurringInvoiceDeletedActivity; -use App\Listeners\RecurringExpense\RecurringExpenseArchivedActivity; -use App\Listeners\RecurringExpense\RecurringExpenseRestoredActivity; -use App\Listeners\RecurringInvoice\RecurringInvoiceArchivedActivity; -use App\Listeners\RecurringInvoice\RecurringInvoiceRestoredActivity; +use App\Observers\VendorObserver; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; +use Illuminate\Mail\Events\MessageSending; +use Illuminate\Mail\Events\MessageSent; class EventServiceProvider extends ServiceProvider { diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 73b6e6a118b0..86a681d00160 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -11,14 +11,14 @@ namespace App\Providers; -use App\Utils\Ninja; use App\Models\Scheduler; +use App\Utils\Ninja; use App\Utils\Traits\MakesHash; -use Illuminate\Support\Facades\Route; use Illuminate\Cache\RateLimiting\Limit; -use Illuminate\Support\Facades\RateLimiter; use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; +use Illuminate\Support\Facades\RateLimiter; +use Illuminate\Support\Facades\Route; class RouteServiceProvider extends ServiceProvider { @@ -45,35 +45,28 @@ class RouteServiceProvider extends ServiceProvider }); RateLimiter::for('login', function () { - if (Ninja::isSelfHost()) { return Limit::none(); - }else { + } else { return Limit::perMinute(50); } - }); RateLimiter::for('api', function () { - if (Ninja::isSelfHost()) { return Limit::none(); - }else { + } else { return Limit::perMinute(300); } - }); RateLimiter::for('refresh', function () { - if (Ninja::isSelfHost()) { return Limit::none(); - }else { + } else { return Limit::perMinute(200); } - }); - } /** diff --git a/app/Repositories/InvoiceRepository.php b/app/Repositories/InvoiceRepository.php index f88c5a295776..969d228c28ab 100644 --- a/app/Repositories/InvoiceRepository.php +++ b/app/Repositories/InvoiceRepository.php @@ -83,8 +83,9 @@ class InvoiceRepository extends BaseRepository */ public function restore($invoice) :Invoice { - if($invoice->is_proforma) + if ($invoice->is_proforma) { return $invoice; + } //if we have just archived, only perform a soft restore if (! $invoice->is_deleted) { diff --git a/app/Services/Client/ClientService.php b/app/Services/Client/ClientService.php index dd5d944285e5..b8a5a8a6279c 100644 --- a/app/Services/Client/ClientService.php +++ b/app/Services/Client/ClientService.php @@ -11,16 +11,16 @@ namespace App\Services\Client; -use App\Utils\Number; use App\Models\Client; use App\Models\Credit; use App\Models\Payment; use App\Services\Email\Email; -use App\Utils\Traits\MakesDates; -use Illuminate\Support\Facades\DB; use App\Services\Email\EmailObject; use App\Services\Email\EmailService; +use App\Utils\Number; +use App\Utils\Traits\MakesDates; use Illuminate\Mail\Mailables\Address; +use Illuminate\Support\Facades\DB; class ClientService { @@ -173,7 +173,6 @@ class ClientService $email_object = $this->buildStatementMailableData($pdf); Email::dispatch($email_object, $this->client->company); - } /** diff --git a/app/Services/ClientPortal/InstantPayment.php b/app/Services/ClientPortal/InstantPayment.php index 1b0daac41314..2e5feffd85ea 100644 --- a/app/Services/ClientPortal/InstantPayment.php +++ b/app/Services/ClientPortal/InstantPayment.php @@ -217,9 +217,9 @@ class InstantPayment /** $hash_data = mixed[] */ $hash_data = [ - 'invoices' => $payable_invoices->toArray(), - 'credits' => $credit_totals, - 'amount_with_fee' => max(0, (($invoice_totals + $fee_totals) - $credit_totals)), + 'invoices' => $payable_invoices->toArray(), + 'credits' => $credit_totals, + 'amount_with_fee' => max(0, (($invoice_totals + $fee_totals) - $credit_totals)), 'pre_payment' => $this->request->pre_payment, 'frequency_id' => $this->request->frequency_id, 'remaining_cycles' => $this->request->remaining_cycles, diff --git a/app/Services/Email/Email.php b/app/Services/Email/Email.php index 4daf13338e20..7c8d7f072aee 100644 --- a/app/Services/Email/Email.php +++ b/app/Services/Email/Email.php @@ -11,43 +11,42 @@ namespace App\Services\Email; -use App\Models\User; -use App\Utils\Ninja; +use App\DataMapper\Analytics\EmailFailure; +use App\DataMapper\Analytics\EmailSuccess; +use App\Events\Invoice\InvoiceWasEmailedAndFailed; +use App\Events\Payment\PaymentWasEmailedAndFailed; +use App\Jobs\Util\SystemLogger; +use App\Libraries\Google\Google; +use App\Libraries\MultiDB; use App\Models\Client; -use App\Models\Vendor; +use App\Models\ClientContact; use App\Models\Company; use App\Models\Invoice; use App\Models\Payment; use App\Models\SystemLog; -use App\Utils\HtmlEngine; -use App\Libraries\MultiDB; -use App\Models\ClientContact; +use App\Models\User; +use App\Models\Vendor; use App\Models\VendorContact; -use Illuminate\Bus\Queueable; -use Illuminate\Mail\Mailable; -use App\Jobs\Util\SystemLogger; +use App\Utils\HtmlEngine; +use App\Utils\Ninja; use App\Utils\Traits\MakesHash; use App\Utils\VendorHtmlEngine; -use App\Libraries\Google\Google; -use Illuminate\Support\Facades\Mail; -use App\Services\Email\EmailMailable; -use Illuminate\Support\Facades\Cache; -use Illuminate\Queue\SerializesModels; -use Turbo124\Beacon\Facades\LightLogs; -use Illuminate\Queue\InteractsWithQueue; use GuzzleHttp\Exception\ClientException; -use App\DataMapper\Analytics\EmailFailure; -use App\DataMapper\Analytics\EmailSuccess; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; -use App\Events\Invoice\InvoiceWasEmailedAndFailed; -use App\Events\Payment\PaymentWasEmailedAndFailed; +use Illuminate\Mail\Mailable; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Mail; +use Turbo124\Beacon\Facades\LightLogs; class Email implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesHash; - public $tries = 4; + public $tries = 4; public $deleteWhenMissingModels = true; @@ -79,7 +78,6 @@ class Email implements ShouldQueue public function handle() { - MultiDB::setDb($this->company->db); $this->setOverride() @@ -87,13 +85,13 @@ class Email implements ShouldQueue ->setDefaults() ->buildMailable(); - if($this->preFlightChecksFail()) + if ($this->preFlightChecksFail()) { return; + } $this->email(); $this->tearDown(); - } /** @@ -115,7 +113,6 @@ class Email implements ShouldQueue */ public function initModels(): self { - $this->email_object->entity_id ? $this->email_object->entity = $this->email_object->entity_class::withTrashed()->with('invitations')->find($this->email_object->entity_id) : $this->email_object->entity = null; $this->email_object->invitation_id ? $this->email_object->invitation = $this->email_object->entity->invitations()->where('id', $this->email_object->invitation_id)->first() : $this->email_object->invitation = null; @@ -126,13 +123,10 @@ class Email implements ShouldQueue $this->email_object->vendor_id ? $this->email_object->vendor = Vendor::withTrashed()->find($this->email_object->vendor_id) : $this->email_object->vendor = null; - if (!$this->email_object->contact) - { - + if (!$this->email_object->contact) { $this->email_object->vendor_contact_id ? $this->email_object->contact = VendorContact::withTrashed()->find($this->email_object->vendor_contact_id) : null; $this->email_object->client_contact_id ? $this->email_object->contact = ClientContact::withTrashed()->find($this->email_object->client_contact_id) : null; - } $this->email_object->user_id ? $this->email_object->user = User::withTrashed()->find($this->email_object->user_id) : $this->email_object->user = $this->company->owner(); @@ -163,7 +157,7 @@ class Email implements ShouldQueue { $_variables = $this->email_object->variables; - match(class_basename($this->email_object->entity)){ + match (class_basename($this->email_object->entity)) { "Invoice" => $this->email_object->variables = (new HtmlEngine($this->email_object->invitation))->makeValues(), "Quote" => $this->email_object->variables = (new HtmlEngine($this->email_object->invitation))->makeValues(), "Credit" => $this->email_object->variables = (new HtmlEngine($this->email_object->invitation))->makeValues(), @@ -172,8 +166,7 @@ class Email implements ShouldQueue }; /** If we have passed some variable overrides we insert them here */ - foreach($_variables as $key => $value) - { + foreach ($_variables as $key => $value) { $this->email_object->variables[$key] = $value; } @@ -187,7 +180,6 @@ class Email implements ShouldQueue */ private function tearDown(): self { - $this->email_object->entity = null; $this->email_object->invitation = null; $this->email_object->client = null; @@ -197,7 +189,6 @@ class Email implements ShouldQueue $this->email_object->settings = null; return $this; - } /** @@ -207,11 +198,9 @@ class Email implements ShouldQueue */ public function setDefaults(): self { - (new EmailDefaults($this))->run(); return $this; - } /** @@ -221,11 +210,9 @@ class Email implements ShouldQueue */ public function buildMailable(): self { - $this->mailable = new EmailMailable($this->email_object); return $this; - } /** @@ -235,7 +222,6 @@ class Email implements ShouldQueue */ public function email() { - $this->setMailDriver(); /* Init the mailer*/ @@ -260,7 +246,6 @@ class Email implements ShouldQueue LightLogs::create(new EmailSuccess($this->company->company_key)) ->send(); - } catch(\Symfony\Component\Mime\Exception\RfcComplianceException $e) { nlog("Mailer failed with a Logic Exception {$e->getMessage()}"); $this->fail(); @@ -274,8 +259,7 @@ class Email implements ShouldQueue $this->logMailError($e->getMessage(), $this->company->clients()->first()); return; } catch (\Exception | \RuntimeException | \Google\Service\Exception $e) { - - nlog("Mailer failed with {$e->getMessage()}"); + nlog("Mailer failed with {$e->getMessage()}"); $message = $e->getMessage(); if (stripos($e->getMessage(), 'code 406') || stripos($e->getMessage(), 'code 300') || stripos($e->getMessage(), 'code 413')) { @@ -326,7 +310,6 @@ class Email implements ShouldQueue } $this->cleanUpMailers(); - } /** @@ -765,13 +748,10 @@ class Email implements ShouldQueue public function failed($exception = null) { - - if($exception) + if ($exception) { nlog($exception->getMessage()); + } config(['queue.failed.driver' => null]); - } - - -} \ No newline at end of file +} diff --git a/app/Services/Email/EmailDefaults.php b/app/Services/Email/EmailDefaults.php index c76575e0a7a4..b63b506c7d2f 100644 --- a/app/Services/Email/EmailDefaults.php +++ b/app/Services/Email/EmailDefaults.php @@ -11,22 +11,22 @@ namespace App\Services\Email; -use App\Models\Task; -use App\Utils\Ninja; -use App\Models\Quote; -use App\Models\Credit; +use App\DataMapper\EmailTemplateDefaults; +use App\Jobs\Entity\CreateRawPdf; +use App\Jobs\Invoice\CreateUbl; +use App\Jobs\Vendor\CreatePurchaseOrderPdf; use App\Models\Account; +use App\Models\Credit; use App\Models\Expense; use App\Models\Invoice; use App\Models\PurchaseOrder; -use App\Jobs\Invoice\CreateUbl; +use App\Models\Quote; +use App\Models\Task; +use App\Utils\Ninja; use App\Utils\Traits\MakesHash; -use App\Jobs\Entity\CreateRawPdf; -use Illuminate\Support\Facades\App; use Illuminate\Mail\Mailables\Address; -use App\DataMapper\EmailTemplateDefaults; +use Illuminate\Support\Facades\App; use League\CommonMark\CommonMarkConverter; -use App\Jobs\Vendor\CreatePurchaseOrderPdf; class EmailDefaults { @@ -66,7 +66,7 @@ class EmailDefaults { $this->settings = $this->email->email_object->settings; - $this->setLocale() + $this->setLocale() ->setFrom() ->setTo() ->setCc() @@ -128,7 +128,6 @@ class EmailDefaults private function setFrom(): self { if (Ninja::isHosted() && $this->email->email_object->settings->email_sending_method == 'default') { - if ($this->email->company->account->isPaid() && property_exists($this->email->email_object->settings, 'email_from_name') && strlen($this->email->email_object->settings->email_from_name) > 1) { $email_from_name = $this->email->email_object->settings->email_from_name; } else { @@ -168,7 +167,6 @@ class EmailDefaults */ private function setBody(): self { - if ($this->template == 'email.template.custom') { $this->email->email_object->body = (str_replace('$body', $this->email->email_object->body, $this->email->email_object->settings->email_style_custom)); return $this; @@ -291,20 +289,16 @@ class EmailDefaults /** Purchase Order / Invoice / Credit / Quote PDF */ if ($this->email->email_object->settings->pdf_email_attachment && $this->email->email_object->entity instanceof PurchaseOrder) { - $pdf = (new CreatePurchaseOrderPdf($this->email->email_object->invitation))->rawPdf(); $this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($pdf), 'name' => $this->email->email_object->entity->numberFormatter().'.pdf']]); - } elseif ($this->email->email_object->settings->pdf_email_attachment && ($this->email->email_object->entity instanceof Invoice || $this->email->email_object->entity instanceof Quote || $this->email->email_object->entity instanceof Credit)) { - $pdf = ((new CreateRawPdf($this->email->email_object->invitation, $this->email->company->db))->handle()); $this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($pdf), 'name' => $this->email->email_object->entity->numberFormatter().'.pdf']]); - } /** UBL xml file */ @@ -316,8 +310,9 @@ class EmailDefaults } } - if(!$this->email->email_object->settings->document_email_attachment || !$this->email->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) + if (!$this->email->email_object->settings->document_email_attachment || !$this->email->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) { return $this; + } /* Company Documents */ $this->email->email_object->documents = array_merge($this->email->email_object->documents, $this->email->company->documents->pluck('id')->toArray()); diff --git a/app/Services/Email/EmailMailable.php b/app/Services/Email/EmailMailable.php index 50ae63181bd2..91c0ea407121 100644 --- a/app/Services/Email/EmailMailable.php +++ b/app/Services/Email/EmailMailable.php @@ -12,16 +12,15 @@ namespace App\Services\Email; use App\Models\Document; -use Illuminate\Mail\Mailable; use Illuminate\Mail\Attachment; -use Illuminate\Support\Facades\URL; +use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailables\Content; -use Illuminate\Mail\Mailables\Headers; use Illuminate\Mail\Mailables\Envelope; +use Illuminate\Mail\Mailables\Headers; +use Illuminate\Support\Facades\URL; class EmailMailable extends Mailable { - public int $max_attachment_size = 3000000; /** @@ -41,7 +40,7 @@ class EmailMailable extends Mailable public function envelope() { return new Envelope( - subject: str_replace("
","",$this->email_object->subject), + subject: str_replace("
", "", $this->email_object->subject), tags: [$this->email_object->company_key], replyTo: $this->email_object->reply_to, from: $this->email_object->from, @@ -58,15 +57,12 @@ class EmailMailable extends Mailable */ public function content() { - - $links = Document::whereIn('id',$this->email_object->documents) + $links = Document::whereIn('id', $this->email_object->documents) ->where('size', '>', $this->max_attachment_size) ->cursor() - ->map(function ($document){ - - return " $document->hash]) ."'>". $document->name .""; - - }); + ->map(function ($document) { + return " $document->hash]) ."'>". $document->name .""; + }); return new Content( view: $this->email_object->html_template, @@ -94,18 +90,16 @@ class EmailMailable extends Mailable { $attachments = []; - $attachments = collect($this->email_object->attachments)->map(function ($file){ + $attachments = collect($this->email_object->attachments)->map(function ($file) { return Attachment::fromData(fn () => base64_decode($file['file']), $file['name']); }); - $documents = Document::whereIn('id',$this->email_object->documents) + $documents = Document::whereIn('id', $this->email_object->documents) ->where('size', '<', $this->max_attachment_size) ->cursor() - ->map(function ($document){ - - return Attachment::fromData(fn () => $document->getFile(), $document->name); - - }); + ->map(function ($document) { + return Attachment::fromData(fn () => $document->getFile(), $document->name); + }); return $attachments->merge($documents)->toArray(); } diff --git a/app/Services/Email/EmailObject.php b/app/Services/Email/EmailObject.php index e11e45c82419..74334965f6d4 100644 --- a/app/Services/Email/EmailObject.php +++ b/app/Services/Email/EmailObject.php @@ -11,22 +11,22 @@ namespace App\Services\Email; -use App\Models\User; -use App\Models\Quote; use App\Models\Client; -use App\Models\Credit; -use App\Models\Vendor; -use App\Models\Company; -use App\Models\Invoice; -use App\Models\Payment; use App\Models\ClientContact; -use App\Models\PurchaseOrder; -use App\Models\VendorContact; -use App\Models\QuoteInvitation; +use App\Models\Company; +use App\Models\Credit; use App\Models\CreditInvitation; +use App\Models\Invoice; use App\Models\InvoiceInvitation; -use Illuminate\Mail\Mailables\Address; +use App\Models\Payment; +use App\Models\PurchaseOrder; use App\Models\PurchaseOrderInvitation; +use App\Models\Quote; +use App\Models\QuoteInvitation; +use App\Models\User; +use App\Models\Vendor; +use App\Models\VendorContact; +use Illuminate\Mail\Mailables\Address; /** * EmailObject. diff --git a/app/Services/Invoice/ApplyNumber.php b/app/Services/Invoice/ApplyNumber.php index 93c5adb187b5..7ac46b942e04 100644 --- a/app/Services/Invoice/ApplyNumber.php +++ b/app/Services/Invoice/ApplyNumber.php @@ -41,7 +41,7 @@ class ApplyNumber extends AbstractService } /** Do no give pro forma invoices a proper invoice number */ - if($this->invoice->is_proforma) { + if ($this->invoice->is_proforma) { $this->invoice->number = ctrans('texts.pre_payment') . " " . now()->format('Y-m-d : H:i:s'); $this->invoice->saveQuietly(); return $this->invoice; diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index d60a14fa0953..5d10f2e74fff 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -122,12 +122,12 @@ class AutoBillInvoice extends AbstractService $payment_hash = PaymentHash::create([ 'hash' => Str::random(64), 'data' => [ - 'amount_with_fee' => $amount + $fee, + 'amount_with_fee' => $amount + $fee, 'invoices' => [ [ - 'invoice_id' => $this->invoice->hashed_id, - 'amount' => $amount, - 'invoice_number' => $this->invoice->number, + 'invoice_id' => $this->invoice->hashed_id, + 'amount' => $amount, + 'invoice_number' => $this->invoice->number, 'pre_payment' => $this->invoice->is_proforma, ], ], diff --git a/app/Services/Invoice/MarkSent.php b/app/Services/Invoice/MarkSent.php index 54ed2a141045..87c3a89f0664 100644 --- a/app/Services/Invoice/MarkSent.php +++ b/app/Services/Invoice/MarkSent.php @@ -21,7 +21,8 @@ use App\Utils\Ninja; class MarkSent extends AbstractService { public function __construct(public Client $client, public Invoice $invoice) - {} + { + } public function run($fire_webhook = false) { diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php index eec109408172..f5c02d1e86e5 100644 --- a/app/Services/Payment/DeletePayment.php +++ b/app/Services/Payment/DeletePayment.php @@ -74,7 +74,6 @@ class DeletePayment if ($this->payment->invoices()->exists()) { $this->payment->invoices()->each(function ($paymentable_invoice) { - $net_deletable = $paymentable_invoice->pivot->amount - $paymentable_invoice->pivot->refunded; $this->_paid_to_date_deleted += $net_deletable; @@ -105,7 +104,6 @@ class DeletePayment } else { $paymentable_invoice->service()->setStatus(Invoice::STATUS_PARTIAL)->save(); } - } else { $paymentable_invoice->restore(); $paymentable_invoice->service() diff --git a/app/Services/Payment/SendEmail.php b/app/Services/Payment/SendEmail.php index a16e6ea926b2..0deb487c0a68 100644 --- a/app/Services/Payment/SendEmail.php +++ b/app/Services/Payment/SendEmail.php @@ -11,17 +11,17 @@ namespace App\Services\Payment; -use App\Utils\Ninja; -use App\Models\Payment; -use App\Models\ClientContact; -use App\Jobs\Payment\EmailPayment; use App\Events\Payment\PaymentWasEmailed; +use App\Jobs\Payment\EmailPayment; +use App\Models\ClientContact; +use App\Models\Payment; +use App\Utils\Ninja; class SendEmail { - public function __construct(public Payment $payment, public ?ClientContact $contact) - {} + { + } /** * Builds the correct template to send. @@ -31,18 +31,18 @@ class SendEmail { $this->payment->load('company', 'client.contacts', 'invoices'); - if(!$this->contact) + if (!$this->contact) { $this->contact = $this->payment->client->contacts()->first(); + } // $this->payment->invoices->sortByDesc('id')->first(function ($invoice) { // $invoice->invitations->each(function ($invitation) { // if (!$invitation->contact->trashed() && $invitation->contact->email) { - EmailPayment::dispatch($this->payment, $this->payment->company, $this->contact); + EmailPayment::dispatch($this->payment, $this->payment->company, $this->contact); - event(new PaymentWasEmailed($this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); + event(new PaymentWasEmailed($this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); // } // }); // }); - } } diff --git a/app/Services/Payment/UpdateInvoicePayment.php b/app/Services/Payment/UpdateInvoicePayment.php index aba182f80668..4f088eacfc9f 100644 --- a/app/Services/Payment/UpdateInvoicePayment.php +++ b/app/Services/Payment/UpdateInvoicePayment.php @@ -11,14 +11,14 @@ namespace App\Services\Payment; -use App\Utils\Ninja; +use App\Events\Invoice\InvoiceWasUpdated; +use App\Factory\RecurringInvoiceFactory; use App\Models\Invoice; use App\Models\Payment; use App\Models\PaymentHash; -use App\Utils\Traits\MakesHash; use App\Models\RecurringInvoice; -use App\Factory\RecurringInvoiceFactory; -use App\Events\Invoice\InvoiceWasUpdated; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; class UpdateInvoicePayment { @@ -84,10 +84,8 @@ class UpdateInvoicePayment ->save(); if ($invoice->is_proforma) { - //keep proforma's hidden - if(property_exists($this->payment_hash->data, 'pre_payment') && $this->payment_hash->data->pre_payment == "1"){ - + if (property_exists($this->payment_hash->data, 'pre_payment') && $this->payment_hash->data->pre_payment == "1") { $invoice->payments()->each(function ($p) { $p->pivot->forceDelete(); }); @@ -117,7 +115,6 @@ class UpdateInvoicePayment $recurring_invoice->next_send_date = $recurring_invoice->nextSendDate(); $recurring_invoice->next_send_date_client = $recurring_invoice->nextSendDateClient(); $recurring_invoice->service()->applyNumber()->save(); - } return; @@ -125,8 +122,9 @@ class UpdateInvoicePayment - if (strlen($invoice->number) > 1 && str_starts_with($invoice->number, "####")) - $invoice->number = ''; + if (strlen($invoice->number) > 1 && str_starts_with($invoice->number, "####")) { + $invoice->number = ''; + } $invoice->is_proforma = false; diff --git a/app/Services/Pdf/PdfService.php b/app/Services/Pdf/PdfService.php index 77c99919ed1d..d7fde2b8cc5a 100644 --- a/app/Services/Pdf/PdfService.php +++ b/app/Services/Pdf/PdfService.php @@ -11,7 +11,6 @@ namespace App\Services\Pdf; -use App\Models\Account; use App\Models\Company; use App\Models\CreditInvitation; use App\Models\InvoiceInvitation; @@ -72,7 +71,7 @@ class PdfService * Resolves the PDF generation type and * attempts to generate a PDF from the HTML * string. - * + * * @return mixed | Exception * */ @@ -102,7 +101,6 @@ class PdfService */ public function getHtml(): string { - $html = $this->builder->getCompiledHTML(); if (config('ninja.log_pdf_html')) { diff --git a/app/Services/PdfMaker/Design.php b/app/Services/PdfMaker/Design.php index eccdb0d4dfc3..b2ffd3792db5 100644 --- a/app/Services/PdfMaker/Design.php +++ b/app/Services/PdfMaker/Design.php @@ -681,8 +681,9 @@ class Design extends BaseDesign $table_type = "{$type}_columns"; - if($type == 'product' && $this->entity instanceof Quote && !$this->settings_object->getSetting('sync_invoice_quote_columns')) + if ($type == 'product' && $this->entity instanceof Quote && !$this->settings_object->getSetting('sync_invoice_quote_columns')) { $table_type = "product_quote_columns"; + } foreach ($this->context['pdf_variables'][$table_type] as $column) { if (array_key_exists($column, $aliases)) { @@ -788,7 +789,6 @@ class Design extends BaseDesign } } } else { - foreach ($this->context['pdf_variables'][$table_type] as $key => $cell) { // We want to keep aliases like these: // $task.cost => $task.rate diff --git a/app/Services/PdfMaker/PdfMakerUtilities.php b/app/Services/PdfMaker/PdfMakerUtilities.php index 95be78b0b1e1..d38ef430b170 100644 --- a/app/Services/PdfMaker/PdfMakerUtilities.php +++ b/app/Services/PdfMaker/PdfMakerUtilities.php @@ -178,7 +178,7 @@ trait PdfMakerUtilities foreach ($children as $key => &$child) { if (isset($child['content']) && isset($child['show_empty']) && $child['show_empty'] === false) { $value = strtr($child['content'], $variables['values']); - if ($value === '' || $value === ' ' || $value === ' '){ + if ($value === '' || $value === ' ' || $value === ' ') { $child['is_empty'] = true; } } diff --git a/app/Services/Quote/GetQuotePdf.php b/app/Services/Quote/GetQuotePdf.php index 095b62650079..5ae880e33052 100644 --- a/app/Services/Quote/GetQuotePdf.php +++ b/app/Services/Quote/GetQuotePdf.php @@ -15,7 +15,6 @@ use App\Jobs\Entity\CreateEntityPdf; use App\Models\ClientContact; use App\Models\Quote; use App\Services\AbstractService; -use Illuminate\Support\Facades\Storage; class GetQuotePdf extends AbstractService { @@ -34,8 +33,9 @@ class GetQuotePdf extends AbstractService $invitation = $this->quote->invitations->where('client_contact_id', $this->contact->id)->first(); - if(!$invitation) + if (!$invitation) { $invitation = $this->quote->invitations->first(); + } $path = $this->quote->client->quote_filepath($invitation); @@ -48,6 +48,5 @@ class GetQuotePdf extends AbstractService $file_path = (new CreateEntityPdf($invitation))->handle(); return $file_path; - } } diff --git a/app/Services/Quote/SendEmail.php b/app/Services/Quote/SendEmail.php index 3fb32229612e..2530fe598bbf 100644 --- a/app/Services/Quote/SendEmail.php +++ b/app/Services/Quote/SendEmail.php @@ -14,7 +14,6 @@ namespace App\Services\Quote; use App\Jobs\Entity\EmailEntity; use App\Models\ClientContact; - class SendEmail { public $quote; @@ -48,7 +47,7 @@ class SendEmail $this->quote->service()->markSent()->save(); - $this->quote->invitations->each(function ($invitation) { + $this->quote->invitations->each(function ($invitation) { if (! $invitation->contact->trashed() && $invitation->contact->email) { EmailEntity::dispatch($invitation, $invitation->company, $this->reminder_template); diff --git a/app/Services/Recurring/IncreasePrice.php b/app/Services/Recurring/IncreasePrice.php index b8486a206710..168790e8f1f5 100644 --- a/app/Services/Recurring/IncreasePrice.php +++ b/app/Services/Recurring/IncreasePrice.php @@ -16,28 +16,18 @@ use App\Services\AbstractService; class IncreasePrice extends AbstractService { - public function __construct(public RecurringInvoice $recurring_invoice, public float $percentage) { - } public function run() { - $line_items = $this->recurring_invoice->line_items; foreach ($line_items as $key => $line_item) { - $line_items[$key]->cost = $line_item->cost * (1 + round(($this->percentage / 100), 2)); - } $this->recurring_invoice->line_items = $line_items; $this->recurring_invoice->calc()->getInvoice()->save(); - - - } - - } diff --git a/app/Services/Recurring/RecurringService.php b/app/Services/Recurring/RecurringService.php index 5c20a19bc5ed..e9c81b870dc1 100644 --- a/app/Services/Recurring/RecurringService.php +++ b/app/Services/Recurring/RecurringService.php @@ -11,20 +11,14 @@ namespace App\Services\Recurring; +use App\Jobs\RecurringInvoice\SendRecurring; use App\Jobs\Util\UnlinkFile; -use Illuminate\Support\Carbon; use App\Models\RecurringExpense; use App\Models\RecurringInvoice; -use App\Services\Recurring\ApplyNumber; -use App\Services\Recurring\UpdatePrice; -use App\Services\Recurring\GetInvoicePdf; -use App\Services\Recurring\IncreasePrice; -use App\Jobs\RecurringInvoice\SendRecurring; -use App\Services\Recurring\CreateRecurringInvitations; +use Illuminate\Support\Carbon; class RecurringService { - public function __construct(public RecurringInvoice | RecurringExpense $recurring_entity) { } @@ -58,8 +52,9 @@ class RecurringService return $this; } - if($this->recurring_entity->trashed()) + if ($this->recurring_entity->trashed()) { $this->recurring_entity->restore(); + } $this->setStatus(RecurringInvoice::STATUS_ACTIVE); @@ -145,7 +140,6 @@ class RecurringService (new IncreasePrice($this->recurring_entity, $percentage))->run(); return $this; - } public function updatePrice() diff --git a/app/Services/Recurring/UpdatePrice.php b/app/Services/Recurring/UpdatePrice.php index 1e196c68bc90..1666f1c4a4f1 100644 --- a/app/Services/Recurring/UpdatePrice.php +++ b/app/Services/Recurring/UpdatePrice.php @@ -23,28 +23,20 @@ class UpdatePrice extends AbstractService public function run() { - - $line_items = $this->recurring_invoice->line_items; - foreach($line_items as $key => $line_item) - { - + foreach ($line_items as $key => $line_item) { $product = Product::where('company_id', $this->recurring_invoice->company_id) ->where('product_key', $line_item->product_key) ->where('is_deleted', 0) ->first(); - if($product){ - + if ($product) { $line_items[$key]->cost = $product->cost; } - } $this->recurring_invoice->line_items = $line_items; $this->recurring_invoice->calc()->getInvoice()->save(); - - } -} \ No newline at end of file +} diff --git a/app/Services/Scheduler/SchedulerService.php b/app/Services/Scheduler/SchedulerService.php index eacd84b0e926..675812b670b0 100644 --- a/app/Services/Scheduler/SchedulerService.php +++ b/app/Services/Scheduler/SchedulerService.php @@ -38,8 +38,9 @@ class SchedulerService */ public function runTask(): void { - if(method_exists($this, $this->scheduler->template)) + if (method_exists($this, $this->scheduler->template)) { $this->{$this->scheduler->template}(); + } } private function email_statement() diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index 49f44eca53ad..d011bdba4867 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -11,42 +11,42 @@ namespace App\Services\Subscription; -use Carbon\Carbon; +use App\DataMapper\InvoiceItem; +use App\Factory\CreditFactory; +use App\Factory\InvoiceFactory; +use App\Factory\PaymentFactory; +use App\Factory\RecurringInvoiceFactory; +use App\Jobs\Mail\NinjaMailer; +use App\Jobs\Mail\NinjaMailerJob; +use App\Jobs\Mail\NinjaMailerObject; +use App\Jobs\Util\SystemLogger; +use App\Libraries\MultiDB; +use App\Mail\RecurringInvoice\ClientContactRequestCancellationObject; use App\Models\Client; +use App\Models\ClientContact; use App\Models\Credit; use App\Models\Invoice; use App\Models\License; -use App\Models\Product; -use App\Models\SystemLog; -use App\Libraries\MultiDB; use App\Models\PaymentHash; use App\Models\PaymentType; -use Illuminate\Support\Str; -use App\Models\Subscription; -use App\Models\ClientContact; -use App\Services\Email\Email; -use App\Factory\CreditFactory; -use App\Jobs\Mail\NinjaMailer; -use App\DataMapper\InvoiceItem; -use App\Factory\InvoiceFactory; -use App\Factory\PaymentFactory; -use App\Jobs\Util\SystemLogger; -use App\Utils\Traits\MakesHash; +use App\Models\Product; use App\Models\RecurringInvoice; -use App\Jobs\Mail\NinjaMailerJob; -use App\Services\Email\EmailObject; -use App\Jobs\Mail\NinjaMailerObject; -use App\Utils\Traits\CleanLineItems; +use App\Models\Subscription; +use App\Models\SystemLog; use App\Repositories\CreditRepository; use App\Repositories\InvoiceRepository; use App\Repositories\PaymentRepository; -use App\Factory\RecurringInvoiceFactory; -use App\Utils\Traits\SubscriptionHooker; -use App\Repositories\SubscriptionRepository; use App\Repositories\RecurringInvoiceRepository; +use App\Repositories\SubscriptionRepository; +use App\Services\Email\Email; +use App\Services\Email\EmailObject; +use App\Utils\Traits\CleanLineItems; +use App\Utils\Traits\MakesHash; use App\Utils\Traits\Notifications\UserNotifies; +use App\Utils\Traits\SubscriptionHooker; +use Carbon\Carbon; use Illuminate\Contracts\Container\BindingResolutionException; -use App\Mail\RecurringInvoice\ClientContactRequestCancellationObject; +use Illuminate\Support\Str; class SubscriptionService { @@ -121,10 +121,9 @@ class SubscriptionService 'account_key' => $recurring_invoice->client->custom_value2, ]; - $response = $this->triggerWebhook($context); + $response = $this->triggerWebhook($context); return $this->handleRedirect('/client/recurring_invoices/'.$recurring_invoice->hashed_id); - } else { $invoice = Invoice::withTrashed()->find($payment_hash->fee_invoice_id); @@ -169,7 +168,7 @@ class SubscriptionService //send license to the user. $invoice = $payment_hash->fee_invoice; $license_key = Str::uuid()->toString(); - $invoice->footer = ctrans('texts.white_label_body',['license_key' => $license_key]); + $invoice->footer = ctrans('texts.white_label_body', ['license_key' => $license_key]); $recurring_invoice = $this->convertInvoiceToRecurring($payment_hash->payment->client_id); @@ -207,7 +206,7 @@ class SubscriptionService $email_object = new EmailObject; $email_object->to = [$contact->email]; $email_object->subject = ctrans('texts.white_label_link') . " " .ctrans('texts.payment_subject'); - $email_object->body = ctrans('texts.white_label_body',['license_key' => $license_key]); + $email_object->body = ctrans('texts.white_label_body', ['license_key' => $license_key]); $email_object->client_id = $invoice->client_id; $email_object->client_contact_id = $contact->id; $email_object->invitation_key = $invitation->invitation_key; @@ -219,7 +218,6 @@ class SubscriptionService Email::dispatch($email_object, $invoice->company); return true; - } /* Starts the process to create a trial @@ -436,10 +434,11 @@ class SubscriptionService $days_of_subscription_used = $start_date->diffInDays($current_date); - if($subscription) + if ($subscription) { $days_in_frequency = $subscription->service()->getDaysInFrequency(); - else + } else { $days_in_frequency = $this->getDaysInFrequency(); + } if ($days_of_subscription_used >= $days_in_frequency) { return 0; diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index c889bd675f58..5a2a51e1dc44 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -981,9 +981,9 @@ html { */ private function buildViewButton(string $link, string $text): string { - -if($this->settings->email_style == 'plain') - return ''. $text .''; + if ($this->settings->email_style == 'plain') { + return ''. $text .''; + } return '
diff --git a/app/Utils/Number.php b/app/Utils/Number.php index 5dc8fd1975b5..3876bb3da385 100644 --- a/app/Utils/Number.php +++ b/app/Utils/Number.php @@ -238,9 +238,9 @@ class Number $precision = 2; } elseif ($v < 1) { $precision = strlen($v) - strrpos($v, '.') - 1; - } + } - if(is_array($parts) && $parts[0] != 0) { + if (is_array($parts) && $parts[0] != 0) { $precision = 2; } @@ -254,7 +254,6 @@ class Number } elseif ($swapSymbol) { return "{$value} ".trim($symbol); } elseif ($entity->getSetting('show_currency_code') === false) { - if ($_value < 0) { $value = substr($value, 1); $symbol = "-{$symbol}"; diff --git a/app/Utils/PaymentHtmlEngine.php b/app/Utils/PaymentHtmlEngine.php index 48d847f37c0c..399446aa68c9 100644 --- a/app/Utils/PaymentHtmlEngine.php +++ b/app/Utils/PaymentHtmlEngine.php @@ -11,12 +11,10 @@ namespace App\Utils; - use App\Models\Client; -use App\Utils\Helpers; +use App\Models\ClientContact; use App\Models\Company; use App\Models\Payment; -use App\Models\ClientContact; use App\Utils\Traits\MakesDates; use Illuminate\Support\Facades\App; @@ -54,7 +52,7 @@ class PaymentHtmlEngine App::setLocale($this->contact->preferredLocale()); $t->replace(Ninja::transformTranslations($this->client->getMergedSettings())); - $data = []; + $data = []; $data['$from'] = ['value' => '', 'label' => ctrans('texts.from')]; $data['$to'] = ['value' => '', 'label' => ctrans('texts.to')]; @@ -190,7 +188,6 @@ class PaymentHtmlEngine array_multisort($arrKeysLength, SORT_DESC, $data); return $data; - } private function formatInvoiceField($field) @@ -342,8 +339,4 @@ class PaymentHtmlEngine '; } - - - - -} \ No newline at end of file +} diff --git a/app/Utils/TemplateEngine.php b/app/Utils/TemplateEngine.php index 778a0083fcfc..c0f4292da9d4 100644 --- a/app/Utils/TemplateEngine.php +++ b/app/Utils/TemplateEngine.php @@ -12,28 +12,27 @@ namespace App\Utils; -use DB; -use App\Models\Quote; -use App\Models\Client; -use App\Models\Vendor; -use App\Models\Invoice; -use App\Models\Payment; -use Illuminate\Support\Str; -use App\Models\ClientContact; -use App\Models\PurchaseOrder; -use App\Models\VendorContact; -use App\Services\Pdf\PdfMock; -use App\Models\QuoteInvitation; -use App\Utils\Traits\MakesHash; -use App\Models\InvoiceInvitation; -use Illuminate\Support\Facades\App; -use App\Utils\Traits\MakesInvoiceHtml; -use App\Mail\Engine\PaymentEmailEngine; -use App\Models\PurchaseOrderInvitation; -use App\Utils\Traits\MakesTemplateData; use App\DataMapper\EmailTemplateDefaults; -use League\CommonMark\CommonMarkConverter; +use App\Mail\Engine\PaymentEmailEngine; +use App\Models\Client; +use App\Models\ClientContact; +use App\Models\Invoice; +use App\Models\InvoiceInvitation; +use App\Models\Payment; +use App\Models\PurchaseOrder; +use App\Models\PurchaseOrderInvitation; +use App\Models\Quote; +use App\Models\QuoteInvitation; +use App\Models\Vendor; +use App\Models\VendorContact; use App\Services\PdfMaker\Designs\Utilities\DesignHelpers; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\MakesInvoiceHtml; +use App\Utils\Traits\MakesTemplateData; +use DB; +use Illuminate\Support\Facades\App; +use Illuminate\Support\Str; +use League\CommonMark\CommonMarkConverter; class TemplateEngine { @@ -97,19 +96,15 @@ class TemplateEngine if (strlen($this->entity) > 1 && strlen($this->entity_id) > 1) { $class = 'App\Models\\' . ucfirst(Str::camel($this->entity)); $this->entity_obj = $class::withTrashed()->where('id', $this->decodePrimaryKey($this->entity_id))->company()->first(); - } - elseif(stripos($this->template, 'quote') !== false && $quote = Quote::whereHas('invitations')->withTrashed()->company()->first()){ + } elseif (stripos($this->template, 'quote') !== false && $quote = Quote::whereHas('invitations')->withTrashed()->company()->first()) { $this->entity = 'quote'; $this->entity_obj = $quote; - } - elseif(stripos($this->template, 'purchase') !== false && $purchase_order = PurchaseOrder::whereHas('invitations')->withTrashed()->company()->first()){ + } elseif (stripos($this->template, 'purchase') !== false && $purchase_order = PurchaseOrder::whereHas('invitations')->withTrashed()->company()->first()) { $this->entity = 'purchase_order'; $this->entity_obj = $purchase_order; - } - elseif ($invoice = Invoice::whereHas('invitations')->withTrashed()->company()->first()){ + } elseif ($invoice = Invoice::whereHas('invitations')->withTrashed()->company()->first()) { $this->entity_obj = $invoice; - } - else { + } else { $this->mockEntity(); } @@ -196,7 +191,6 @@ class TemplateEngine private function entityValues($contact) { - if (in_array($this->entity, ['purchaseOrder', 'purchase_order'])) { $this->labels_and_values = (new VendorHtmlEngine($this->entity_obj->invitations->first()))->generateLabelsAndValues(); } elseif ($this->entity == 'payment') { @@ -407,7 +401,6 @@ class TemplateEngine $this->entity_obj->load('client'); $client->setRelation('company', auth()->user()->company()); $client->load('company'); - } } diff --git a/app/Utils/Traits/Uploadable.php b/app/Utils/Traits/Uploadable.php index 2e3987a329fe..6f24bd21b272 100644 --- a/app/Utils/Traits/Uploadable.php +++ b/app/Utils/Traits/Uploadable.php @@ -13,7 +13,6 @@ namespace App\Utils\Traits; use App\Jobs\Util\UnlinkFile; use App\Jobs\Util\UploadAvatar; -use Illuminate\Support\Facades\Storage; /** * Class Uploadable. diff --git a/app/Utils/VendorHtmlEngine.php b/app/Utils/VendorHtmlEngine.php index 87072df5b703..0910c318c2ff 100644 --- a/app/Utils/VendorHtmlEngine.php +++ b/app/Utils/VendorHtmlEngine.php @@ -808,11 +808,9 @@ html { */ private function buildViewButton(string $link, string $text): string { - - -if ($this->settings->email_style == 'plain') { - return ''. $text .''; -} + if ($this->settings->email_style == 'plain') { + return ''. $text .''; + } return ' From 222806eeebf0f54def70db7a74b4a59d3c8215c0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 19:06:32 +1100 Subject: [PATCH 07/32] Schedule Entity --- ...ScheduleInvoice.php => ScheduleEntity.php} | 6 +- .../TaskScheduler/StoreSchedulerRequest.php | 2 + app/Jobs/PurchaseOrder/PurchaseOrderEmail.php | 1 + app/Models/Scheduler.php | 60 +++++++++ app/Services/Invoice/SendEmail.php | 1 - .../PurchaseOrder/PurchaseOrderService.php | 11 +- app/Services/PurchaseOrder/SendEmail.php | 116 +++++++++++++++++ .../Scheduler/EmailStatementService.php | 95 ++++++++++++++ app/Services/Scheduler/ScheduleEntity.php | 29 +++++ app/Services/Scheduler/SchedulerService.php | 122 +----------------- 10 files changed, 323 insertions(+), 120 deletions(-) rename app/DataMapper/Schedule/{ScheduleInvoice.php => ScheduleEntity.php} (80%) create mode 100644 app/Services/PurchaseOrder/SendEmail.php create mode 100644 app/Services/Scheduler/EmailStatementService.php create mode 100644 app/Services/Scheduler/ScheduleEntity.php diff --git a/app/DataMapper/Schedule/ScheduleInvoice.php b/app/DataMapper/Schedule/ScheduleEntity.php similarity index 80% rename from app/DataMapper/Schedule/ScheduleInvoice.php rename to app/DataMapper/Schedule/ScheduleEntity.php index cf22aaa7e224..649360f4354c 100644 --- a/app/DataMapper/Schedule/ScheduleInvoice.php +++ b/app/DataMapper/Schedule/ScheduleEntity.php @@ -11,21 +11,21 @@ namespace App\DataMapper\Schedule; -class ScheduleInvoice +class ScheduleEntity { /** * Defines the template name * * @var string */ - public string $template = 'schedule_invoice'; + public string $template = 'schedule_entity'; /** * Defines the template name * * @var string */ - public string $entity = ''; + public string $entity = ''; // invoice, credit, quote, purchase_order /** * Defines the template name diff --git a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php index aea0fee893a4..632cd8cb80b3 100644 --- a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php +++ b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php @@ -43,6 +43,8 @@ class StoreSchedulerRequest extends Request 'parameters.date_range' => 'bail|sometimes|string|in:last7_days,last30_days,last365_days,this_month,last_month,this_quarter,last_quarter,this_year,last_year,custom', 'parameters.start_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom'], 'parameters.end_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom', 'after_or_equal:parameters.start_date'], + 'parameters.entity' => ['bail', 'sometimes', 'string', 'in:invoice,credit,quote,purchase_order'], + 'parameters.entity_id' => ['bail', 'sometimes', 'string'], ]; return $rules; diff --git a/app/Jobs/PurchaseOrder/PurchaseOrderEmail.php b/app/Jobs/PurchaseOrder/PurchaseOrderEmail.php index ace474991c4e..b00622effc98 100644 --- a/app/Jobs/PurchaseOrder/PurchaseOrderEmail.php +++ b/app/Jobs/PurchaseOrder/PurchaseOrderEmail.php @@ -57,6 +57,7 @@ class PurchaseOrderEmail implements ShouldQueue MultiDB::setDb($this->company->db); $this->purchase_order->last_sent_date = now(); + $this->purchase_order->save(); $this->purchase_order->invitations->load('contact.vendor.country', 'purchase_order.vendor.country', 'purchase_order.company')->each(function ($invitation) { /* Don't fire emails if the company is disabled */ diff --git a/app/Models/Scheduler.php b/app/Models/Scheduler.php index f657dfee6a99..83506410843c 100644 --- a/app/Models/Scheduler.php +++ b/app/Models/Scheduler.php @@ -11,6 +11,9 @@ namespace App\Models; +use App\Models\Company; +use App\Models\BaseModel; +use App\Models\RecurringInvoice; use App\Services\Scheduler\SchedulerService; use Illuminate\Database\Eloquent\SoftDeletes; @@ -134,4 +137,61 @@ class Scheduler extends BaseModel return $this->remaining_cycles - 1; } } + + public function calculateNextRun() + { + if (! $this->next_run) { + return null; + } + + $offset = $this->company->timezone_offset(); + + switch ($this->frequency_id) { + case RecurringInvoice::FREQUENCY_DAILY: + $next_run = now()->startOfDay()->addDay(); + break; + case RecurringInvoice::FREQUENCY_WEEKLY: + $next_run = now()->startOfDay()->addWeek(); + break; + case RecurringInvoice::FREQUENCY_TWO_WEEKS: + $next_run = now()->startOfDay()->addWeeks(2); + break; + case RecurringInvoice::FREQUENCY_FOUR_WEEKS: + $next_run = now()->startOfDay()->addWeeks(4); + break; + case RecurringInvoice::FREQUENCY_MONTHLY: + $next_run = now()->startOfDay()->addMonthNoOverflow(); + break; + case RecurringInvoice::FREQUENCY_TWO_MONTHS: + $next_run = now()->startOfDay()->addMonthsNoOverflow(2); + break; + case RecurringInvoice::FREQUENCY_THREE_MONTHS: + $next_run = now()->startOfDay()->addMonthsNoOverflow(3); + break; + case RecurringInvoice::FREQUENCY_FOUR_MONTHS: + $next_run = now()->startOfDay()->addMonthsNoOverflow(4); + break; + case RecurringInvoice::FREQUENCY_SIX_MONTHS: + $next_run = now()->startOfDay()->addMonthsNoOverflow(6); + break; + case RecurringInvoice::FREQUENCY_ANNUALLY: + $next_run = now()->startOfDay()->addYear(); + break; + case RecurringInvoice::FREQUENCY_TWO_YEARS: + $next_run = now()->startOfDay()->addYears(2); + break; + case RecurringInvoice::FREQUENCY_THREE_YEARS: + $next_run = now()->startOfDay()->addYears(3); + break; + default: + $next_run = null; + } + + + $this->next_run_client = $next_run ?: null; + $this->next_run = $next_run ? $next_run->copy()->addSeconds($offset) : null; + $this->save(); + } + + } diff --git a/app/Services/Invoice/SendEmail.php b/app/Services/Invoice/SendEmail.php index 833d777c533e..b71677457307 100644 --- a/app/Services/Invoice/SendEmail.php +++ b/app/Services/Invoice/SendEmail.php @@ -35,7 +35,6 @@ class SendEmail extends AbstractService /** * Builds the correct template to send. - * @return void */ public function run() { diff --git a/app/Services/PurchaseOrder/PurchaseOrderService.php b/app/Services/PurchaseOrder/PurchaseOrderService.php index d1ab465d262c..f9bc5d7c75e1 100644 --- a/app/Services/PurchaseOrder/PurchaseOrderService.php +++ b/app/Services/PurchaseOrder/PurchaseOrderService.php @@ -11,9 +11,10 @@ namespace App\Services\PurchaseOrder; -use App\Jobs\Vendor\CreatePurchaseOrderPdf; use App\Models\PurchaseOrder; use App\Utils\Traits\MakesHash; +use App\Services\PurchaseOrder\SendEmail; +use App\Jobs\Vendor\CreatePurchaseOrderPdf; class PurchaseOrderService { @@ -145,6 +146,14 @@ class PurchaseOrderService return $expense; } + public function sendEmail($contact = null) + { + $send_email = new SendEmail($this->purchase_order, null, $contact); + + return $send_email->run(); + } + + /** * Saves the purchase order. * @return \App\Models\PurchaseOrder object diff --git a/app/Services/PurchaseOrder/SendEmail.php b/app/Services/PurchaseOrder/SendEmail.php new file mode 100644 index 000000000000..900d5380bc6a --- /dev/null +++ b/app/Services/PurchaseOrder/SendEmail.php @@ -0,0 +1,116 @@ +purchase_order->last_sent_date = now(); + + $this->purchase_order->invitations->load('contact.vendor.country', 'purchase_order.vendor.country', 'purchase_order.company')->each(function ($invitation) { + + App::forgetInstance('translator'); + $t = app('translator'); + App::setLocale($invitation->contact->preferredLocale()); + $t->replace(Ninja::transformTranslations($this->purchase_order->company->settings)); + + /* Mark entity sent */ + $invitation->purchase_order->service()->markSent()->save(); + + $template = 'purchase_order'; + + $email_builder = (new PurchaseOrderEmailEngine($invitation, $template, null))->build(); + + $nmo = new NinjaMailerObject; + $nmo->mailable = new VendorTemplateEmail($email_builder, $invitation->contact, $invitation); + $nmo->company = $this->purchase_order->company; + $nmo->settings = $this->purchase_order->company->settings; + $nmo->to_user = $invitation->contact; + $nmo->entity_string = 'purchase_order'; + $nmo->invitation = $invitation; + $nmo->reminder_template = 'email_template_purchase_order'; + $nmo->entity = $invitation->purchase_order; + + NinjaMailerJob::dispatch($nmo); + }); + + if ($this->purchase_order->invitations->count() >= 1) { + event(new PurchaseOrderWasEmailed($this->purchase_order->invitations->first(), $this->purchase_order->invitations->first()->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); + } + + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/Services/Scheduler/EmailStatementService.php b/app/Services/Scheduler/EmailStatementService.php new file mode 100644 index 000000000000..c1c93ba941c5 --- /dev/null +++ b/app/Services/Scheduler/EmailStatementService.php @@ -0,0 +1,95 @@ +where('company_id', $this->scheduler->company_id) + ->where('is_deleted', 0); + + //Email only the selected clients + if (count($this->scheduler->parameters['clients']) >= 1) { + $query->whereIn('id', $this->transformKeys($this->scheduler->parameters['clients'])); + } + + $query->cursor() + ->each(function ($_client) { + $this->client = $_client; + + //work out the date range + $statement_properties = $this->calculateStatementProperties(); + + $_client->service()->statement($statement_properties, true); + }); + + //calculate next run dates; + $this->scheduler->calculateNextRun(); + + } + + /** + * Hydrates the array needed to generate the statement + * + * @return array The statement options array + */ + private function calculateStatementProperties(): array + { + $start_end = $this->calculateStartAndEndDates(); + + return [ + 'start_date' =>$start_end[0], + 'end_date' =>$start_end[1], + 'show_payments_table' => $this->scheduler->parameters['show_payments_table'], + 'show_aging_table' => $this->scheduler->parameters['show_aging_table'], + 'status' => $this->scheduler->parameters['status'] + ]; + } + + /** + * Start and end date of the statement + * + * @return array [$start_date, $end_date]; + */ + private function calculateStartAndEndDates(): array + { + return match ($this->scheduler->parameters['date_range']) { + EmailStatement::LAST7 => [now()->startOfDay()->subDays(7)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')], + EmailStatement::LAST30 => [now()->startOfDay()->subDays(30)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')], + EmailStatement::LAST365 => [now()->startOfDay()->subDays(365)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')], + EmailStatement::THIS_MONTH => [now()->startOfDay()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->lastOfMonth()->format('Y-m-d')], + EmailStatement::LAST_MONTH => [now()->startOfDay()->subMonthNoOverflow()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->subMonthNoOverflow()->lastOfMonth()->format('Y-m-d')], + EmailStatement::THIS_QUARTER => [now()->startOfDay()->firstOfQuarter()->format('Y-m-d'), now()->startOfDay()->lastOfQuarter()->format('Y-m-d')], + EmailStatement::LAST_QUARTER => [now()->startOfDay()->subQuarterNoOverflow()->firstOfQuarter()->format('Y-m-d'), now()->startOfDay()->subQuarterNoOverflow()->lastOfQuarter()->format('Y-m-d')], + EmailStatement::THIS_YEAR => [now()->startOfDay()->firstOfYear()->format('Y-m-d'), now()->startOfDay()->lastOfYear()->format('Y-m-d')], + EmailStatement::LAST_YEAR => [now()->startOfDay()->subYearNoOverflow()->firstOfYear()->format('Y-m-d'), now()->startOfDay()->subYearNoOverflow()->lastOfYear()->format('Y-m-d')], + EmailStatement::CUSTOM_RANGE => [$this->scheduler->parameters['start_date'], $this->scheduler->parameters['end_date']], + default => [now()->startOfDay()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->lastOfMonth()->format('Y-m-d')], + }; + } + +} diff --git a/app/Services/Scheduler/ScheduleEntity.php b/app/Services/Scheduler/ScheduleEntity.php new file mode 100644 index 000000000000..84229c16863f --- /dev/null +++ b/app/Services/Scheduler/ScheduleEntity.php @@ -0,0 +1,29 @@ +scheduler))->run(); + } + + private function email_statement() { - $query = Client::query() - ->where('company_id', $this->scheduler->company_id) - ->where('is_deleted', 0); - - //Email only the selected clients - if (count($this->scheduler->parameters['clients']) >= 1) { - $query->whereIn('id', $this->transformKeys($this->scheduler->parameters['clients'])); - } - - $query->cursor() - ->each(function ($_client) { - $this->client = $_client; - - //work out the date range - $statement_properties = $this->calculateStatementProperties(); - - $_client->service()->statement($statement_properties, true); - }); - - //calculate next run dates; - $this->calculateNextRun(); + (new EmailStatementService($this->scheduler))->run(); } - /** - * Hydrates the array needed to generate the statement - * - * @return array The statement options array - */ - private function calculateStatementProperties(): array - { - $start_end = $this->calculateStartAndEndDates(); - - return [ - 'start_date' =>$start_end[0], - 'end_date' =>$start_end[1], - 'show_payments_table' => $this->scheduler->parameters['show_payments_table'], - 'show_aging_table' => $this->scheduler->parameters['show_aging_table'], - 'status' => $this->scheduler->parameters['status'] - ]; - } - - /** - * Start and end date of the statement - * - * @return array [$start_date, $end_date]; - */ - private function calculateStartAndEndDates(): array - { - return match ($this->scheduler->parameters['date_range']) { - EmailStatement::LAST7 => [now()->startOfDay()->subDays(7)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')], - EmailStatement::LAST30 => [now()->startOfDay()->subDays(30)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')], - EmailStatement::LAST365 => [now()->startOfDay()->subDays(365)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')], - EmailStatement::THIS_MONTH => [now()->startOfDay()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->lastOfMonth()->format('Y-m-d')], - EmailStatement::LAST_MONTH => [now()->startOfDay()->subMonthNoOverflow()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->subMonthNoOverflow()->lastOfMonth()->format('Y-m-d')], - EmailStatement::THIS_QUARTER => [now()->startOfDay()->firstOfQuarter()->format('Y-m-d'), now()->startOfDay()->lastOfQuarter()->format('Y-m-d')], - EmailStatement::LAST_QUARTER => [now()->startOfDay()->subQuarterNoOverflow()->firstOfQuarter()->format('Y-m-d'), now()->startOfDay()->subQuarterNoOverflow()->lastOfQuarter()->format('Y-m-d')], - EmailStatement::THIS_YEAR => [now()->startOfDay()->firstOfYear()->format('Y-m-d'), now()->startOfDay()->lastOfYear()->format('Y-m-d')], - EmailStatement::LAST_YEAR => [now()->startOfDay()->subYearNoOverflow()->firstOfYear()->format('Y-m-d'), now()->startOfDay()->subYearNoOverflow()->lastOfYear()->format('Y-m-d')], - EmailStatement::CUSTOM_RANGE => [$this->scheduler->parameters['start_date'], $this->scheduler->parameters['end_date']], - default => [now()->startOfDay()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->lastOfMonth()->format('Y-m-d')], - }; - } /** * Sets the next run date of the scheduled task * */ - private function calculateNextRun() - { - if (! $this->scheduler->next_run) { - return null; - } - $offset = $this->scheduler->company->timezone_offset(); - - switch ($this->scheduler->frequency_id) { - case RecurringInvoice::FREQUENCY_DAILY: - $next_run = now()->startOfDay()->addDay(); - break; - case RecurringInvoice::FREQUENCY_WEEKLY: - $next_run = now()->startOfDay()->addWeek(); - break; - case RecurringInvoice::FREQUENCY_TWO_WEEKS: - $next_run = now()->startOfDay()->addWeeks(2); - break; - case RecurringInvoice::FREQUENCY_FOUR_WEEKS: - $next_run = now()->startOfDay()->addWeeks(4); - break; - case RecurringInvoice::FREQUENCY_MONTHLY: - $next_run = now()->startOfDay()->addMonthNoOverflow(); - break; - case RecurringInvoice::FREQUENCY_TWO_MONTHS: - $next_run = now()->startOfDay()->addMonthsNoOverflow(2); - break; - case RecurringInvoice::FREQUENCY_THREE_MONTHS: - $next_run = now()->startOfDay()->addMonthsNoOverflow(3); - break; - case RecurringInvoice::FREQUENCY_FOUR_MONTHS: - $next_run = now()->startOfDay()->addMonthsNoOverflow(4); - break; - case RecurringInvoice::FREQUENCY_SIX_MONTHS: - $next_run = now()->startOfDay()->addMonthsNoOverflow(6); - break; - case RecurringInvoice::FREQUENCY_ANNUALLY: - $next_run = now()->startOfDay()->addYear(); - break; - case RecurringInvoice::FREQUENCY_TWO_YEARS: - $next_run = now()->startOfDay()->addYears(2); - break; - case RecurringInvoice::FREQUENCY_THREE_YEARS: - $next_run = now()->startOfDay()->addYears(3); - break; - default: - $next_run = null; - } - - - $this->scheduler->next_run_client = $next_run ?: null; - $this->scheduler->next_run = $next_run ? $next_run->copy()->addSeconds($offset) : null; - $this->scheduler->save(); - } //handle when the scheduler has been paused. } From 139843a1296d0be0914548633c67898d7eb9bc7b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 19:52:52 +1100 Subject: [PATCH 08/32] Fixes for scheduler tests after refactor --- tests/Feature/Scheduler/SchedulerTest.php | 28 +++++++++++------------ 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/tests/Feature/Scheduler/SchedulerTest.php b/tests/Feature/Scheduler/SchedulerTest.php index 955f285b3718..5248b221942e 100644 --- a/tests/Feature/Scheduler/SchedulerTest.php +++ b/tests/Feature/Scheduler/SchedulerTest.php @@ -25,6 +25,7 @@ use App\DataMapper\Schedule\EmailStatement; use App\Services\Scheduler\SchedulerService; use Illuminate\Validation\ValidationException; use Illuminate\Foundation\Testing\WithoutEvents; +use App\Services\Scheduler\EmailStatementService; use Illuminate\Routing\Middleware\ThrottleRequests; /** @@ -399,12 +400,13 @@ class SchedulerTest extends TestCase $scheduler->fill($data); $scheduler->save(); + $scheduler->calculateNextRun(); - $service_object = new SchedulerService($scheduler); + // $service_object = new SchedulerService($scheduler); - $reflectionMethod = new \ReflectionMethod(SchedulerService::class, 'calculateNextRun'); - $reflectionMethod->setAccessible(true); - $method = $reflectionMethod->invoke(new SchedulerService($scheduler)); + // $reflectionMethod = new \ReflectionMethod(SchedulerService::class, 'calculateNextRun'); + // $reflectionMethod->setAccessible(true); + // $method = $reflectionMethod->invoke(new SchedulerService($scheduler)); $scheduler->fresh(); $offset = $this->company->timezone_offset(); @@ -434,12 +436,13 @@ class SchedulerTest extends TestCase $scheduler->fill($data); $scheduler->save(); + $scheduler->calculateNextRun(); - $service_object = new SchedulerService($scheduler); + $service_object = new EmailStatementService($scheduler); - $reflectionMethod = new \ReflectionMethod(SchedulerService::class, 'calculateStartAndEndDates'); + $reflectionMethod = new \ReflectionMethod(EmailStatementService::class, 'calculateStartAndEndDates'); $reflectionMethod->setAccessible(true); - $method = $reflectionMethod->invoke(new SchedulerService($scheduler)); + $method = $reflectionMethod->invoke(new EmailStatementService($scheduler)); $this->assertIsArray($method); @@ -469,16 +472,11 @@ class SchedulerTest extends TestCase $scheduler->fill($data); $scheduler->save(); - $service_object = new SchedulerService($scheduler); + $service_object = new EmailStatementService($scheduler); - // $reflection = new \ReflectionClass(get_class($service_object)); - // $method = $reflection->getMethod('calculateStatementProperties'); - // $method->setAccessible(true); - // $method->invokeArgs($service_object, []); - - $reflectionMethod = new \ReflectionMethod(SchedulerService::class, 'calculateStatementProperties'); + $reflectionMethod = new \ReflectionMethod(EmailStatementService::class, 'calculateStatementProperties'); $reflectionMethod->setAccessible(true); - $method = $reflectionMethod->invoke(new SchedulerService($scheduler)); // 'baz' + $method = $reflectionMethod->invoke(new EmailStatementService($scheduler)); // 'baz' $this->assertIsArray($method); From 47caaa0be388f5e84b13f7d53b64ee2be6fee527 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 19:54:59 +1100 Subject: [PATCH 09/32] Update user input for po number when approving a quote --- app/Http/Controllers/ClientPortal/QuoteController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/ClientPortal/QuoteController.php b/app/Http/Controllers/ClientPortal/QuoteController.php index ca99bdfe64d0..36064e8f62d2 100644 --- a/app/Http/Controllers/ClientPortal/QuoteController.php +++ b/app/Http/Controllers/ClientPortal/QuoteController.php @@ -178,7 +178,7 @@ class QuoteController extends Controller if ($process) { foreach ($quotes as $quote) { if (request()->has('user_input') && strlen(request()->input('user_input')) > 2) { - $quote->public_notes .= $quote->public_notes . "\n" . request()->input('user_input'); + $quote->po_number = substr(request()->input('user_input'), 0, 180); $quote->saveQuietly(); } From 46dceaf17d73ecd099ec34180cfb6e657495e040 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 19:58:54 +1100 Subject: [PATCH 10/32] Update quote input from notes to purchase order number --- .../ninja2020/quotes/includes/user-input.blade.php | 6 +++--- .../views/portal/ninja2020/quotes/show.blade.php | 13 ------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/resources/views/portal/ninja2020/quotes/includes/user-input.blade.php b/resources/views/portal/ninja2020/quotes/includes/user-input.blade.php index afafe6d6863f..3b3f340c4dc8 100644 --- a/resources/views/portal/ninja2020/quotes/includes/user-input.blade.php +++ b/resources/views/portal/ninja2020/quotes/includes/user-input.blade.php @@ -7,11 +7,11 @@

- {{ ctrans('texts.notes') }} + {{ ctrans('texts.po_number') }}

-
- +
+
diff --git a/resources/views/portal/ninja2020/quotes/show.blade.php b/resources/views/portal/ninja2020/quotes/show.blade.php index 3e297cb4d03b..3b39a8cb81de 100644 --- a/resources/views/portal/ninja2020/quotes/show.blade.php +++ b/resources/views/portal/ninja2020/quotes/show.blade.php @@ -120,18 +120,5 @@ var clipboard = new ClipboardJS('.btn'); - // clipboard.on('success', function(e) { - // console.info('Action:', e.action); - // console.info('Text:', e.text); - // console.info('Trigger:', e.trigger); - - // e.clearSelection(); - // }); - - // clipboard.on('error', function(e) { - // console.error('Action:', e.action); - // console.error('Trigger:', e.trigger); - // }); - @endsection From b47bac317c9b012c588eb7279d8685dc36d1c691 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 20:06:42 +1100 Subject: [PATCH 11/32] Schedule Entity --- app/Services/Scheduler/ScheduleEntity.php | 7 ++++++- app/Services/Scheduler/SchedulerService.php | 3 --- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/Services/Scheduler/ScheduleEntity.php b/app/Services/Scheduler/ScheduleEntity.php index 84229c16863f..857198491e8f 100644 --- a/app/Services/Scheduler/ScheduleEntity.php +++ b/app/Services/Scheduler/ScheduleEntity.php @@ -12,6 +12,7 @@ namespace App\Services\Scheduler; use App\Models\Scheduler; +use Illuminate\Support\Str; use App\Utils\Traits\MakesHash; class ScheduleEntity @@ -23,7 +24,11 @@ class ScheduleEntity } public function run() - { + {nlog("here"); + $class = 'App\\Models\\' . Str::camel($this->scheduler->parameters['entity']); + nlog($class); + $class::find($this->decodePrimaryKey($this->scheduler->parameters['entity_id']))->service()->sendEmail(); + $this->scheduler->forceDelete(); } } diff --git a/app/Services/Scheduler/SchedulerService.php b/app/Services/Scheduler/SchedulerService.php index 9328cc81cc54..7a670ada6ab8 100644 --- a/app/Services/Scheduler/SchedulerService.php +++ b/app/Services/Scheduler/SchedulerService.php @@ -11,9 +11,6 @@ namespace App\Services\Scheduler; -use App\DataMapper\Schedule\EmailStatement; -use App\Models\Client; -use App\Models\RecurringInvoice; use App\Models\Scheduler; use App\Utils\Traits\MakesDates; use App\Utils\Traits\MakesHash; From 171c182bd666e53713fc2d67da394c5dcdf2b6f1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 20:15:02 +1100 Subject: [PATCH 12/32] Add Invoice Reference Subject --- app/Mail/Engine/PaymentEmailEngine.php | 19 +++++++++++++++++++ app/Services/Scheduler/ScheduleEntity.php | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php index b16cd3f7133a..bda1dfc226ad 100644 --- a/app/Mail/Engine/PaymentEmailEngine.php +++ b/app/Mail/Engine/PaymentEmailEngine.php @@ -251,6 +251,7 @@ class PaymentEmailEngine extends BaseEmailEngine $data['$emailSignature'] = &$data['$signature']; $data['$invoices'] = ['value' => $this->formatInvoices(), 'label' => ctrans('texts.invoices')]; + $data['$invoice_references_subject'] = ['value' => $this->formatInvoiceReferencesSubject(), 'label' => ctrans('texts.invoices')]; $data['$invoice_references'] = ['value' => $this->formatInvoiceReferences(), 'label' => ctrans('texts.invoices')]; $data['$invoice'] = ['value' => $this->formatInvoice(), 'label' => ctrans('texts.invoices')]; $data['$invoice.po_number'] = ['value' => $this->formatPoNumber(), 'label' => ctrans('texts.po_number')]; @@ -329,6 +330,24 @@ class PaymentEmailEngine extends BaseEmailEngine return $invoice_list; } + private function formatInvoiceReferencesSubject() + { + $invoice_list = ''; + + foreach ($this->payment->invoices as $invoice) { + if (strlen($invoice->po_number) > 1) { + $invoice_list .= ctrans('texts.po_number')." {$invoice->po_number}
"; + } + + $invoice_list .= ctrans('texts.invoice_number_short')." {$invoice->number} " . Number::formatMoney($invoice->pivot->amount, $this->client).', '; + + } + + return $invoice_list; + + } + + private function formatInvoiceReferences() { $invoice_list = '

'; diff --git a/app/Services/Scheduler/ScheduleEntity.php b/app/Services/Scheduler/ScheduleEntity.php index 857198491e8f..b7a93bd8f1e7 100644 --- a/app/Services/Scheduler/ScheduleEntity.php +++ b/app/Services/Scheduler/ScheduleEntity.php @@ -24,9 +24,9 @@ class ScheduleEntity } public function run() - {nlog("here"); + { $class = 'App\\Models\\' . Str::camel($this->scheduler->parameters['entity']); - nlog($class); + $class::find($this->decodePrimaryKey($this->scheduler->parameters['entity_id']))->service()->sendEmail(); $this->scheduler->forceDelete(); From f483ffabde13dd4d1f311a4798dce53a38d5fe1d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 20:18:11 +1100 Subject: [PATCH 13/32] Add tests for scheduling email entity --- .../Feature/Scheduler/ScheduleEntityTest.php | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 tests/Feature/Scheduler/ScheduleEntityTest.php diff --git a/tests/Feature/Scheduler/ScheduleEntityTest.php b/tests/Feature/Scheduler/ScheduleEntityTest.php new file mode 100644 index 000000000000..76a4ddb02522 --- /dev/null +++ b/tests/Feature/Scheduler/ScheduleEntityTest.php @@ -0,0 +1,128 @@ +faker = \Faker\Factory::create(); + + Model::reguard(); + + $this->makeTestData(); + + $this->withoutMiddleware( + ThrottleRequests::class + ); + } + + public function testSchedulerStore() + { + + $data = [ + 'name' => 'A test entity email scheduler', + 'frequency_id' => RecurringInvoice::FREQUENCY_MONTHLY, + 'next_run' => now()->format('Y-m-d'), + 'template' => 'schedule_entity', + 'parameters' => [ + 'entity' => 'invoice', + 'entity_id' => $this->invoice->hashed_id, + ], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/task_schedulers', $data); + + $response->assertStatus(200); + + } + + + public function testSchedulerStore2() + { + + $data = [ + 'name' => 'A test entity email scheduler', + 'frequency_id' => 0, + 'next_run' => now()->format('Y-m-d'), + 'template' => 'schedule_entity', + 'parameters' => [ + 'entity' => 'invoice', + 'entity_id' => $this->invoice->hashed_id, + ], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/task_schedulers', $data); + + $response->assertStatus(200); + + } + + public function testSchedulerStore4() + { + + $data = [ + 'name' => 'A test entity email scheduler', + 'next_run' => now()->format('Y-m-d'), + 'template' => 'schedule_entity', + 'parameters' => [ + 'entity' => 'invoice', + 'entity_id' => $this->invoice->hashed_id, + ], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/task_schedulers', $data); + + $response->assertStatus(200); + + } + + +} \ No newline at end of file From 8a35eaf1b133a8b08fd02eeed06001d5d8ca6aeb Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 18 Mar 2023 23:06:32 +1100 Subject: [PATCH 14/32] Stub global tax rates --- app/DataMapper/Tax/de/Rule.php | 87 ++++++++++++++++++++++++++++++++++ app/DataMapper/Tax/us/Rule.php | 70 +++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 app/DataMapper/Tax/de/Rule.php create mode 100644 app/DataMapper/Tax/us/Rule.php diff --git a/app/DataMapper/Tax/de/Rule.php b/app/DataMapper/Tax/de/Rule.php new file mode 100644 index 000000000000..5640215eda65 --- /dev/null +++ b/app/DataMapper/Tax/de/Rule.php @@ -0,0 +1,87 @@ + Date: Sun, 19 Mar 2023 10:39:21 +1100 Subject: [PATCH 15/32] Updates for openapi definitions --- openapi/api-docs.yaml | 5021 +++++++++-------- openapi/components/schemas.yaml | 3575 +----------- .../schemas/bank_transaction_rule.yaml | 48 + openapi/components/schemas/client.yaml | 160 + .../components/schemas/client_contact.yaml | 113 + .../schemas/client_gateway_token.yaml | 31 + openapi/components/schemas/company.yaml | 91 + .../components/schemas/company_gateway.yaml | 42 + .../components/schemas/company_ledger.yaml | 31 + .../components/schemas/company_settings.yaml | 592 ++ openapi/components/schemas/company_token.yaml | 15 + openapi/components/schemas/company_user.yaml | 43 + openapi/components/schemas/credit.yaml | 222 + openapi/components/schemas/design.yaml | 42 + openapi/components/schemas/document.yaml | 70 + openapi/components/schemas/error.yaml | 11 + openapi/components/schemas/expense.yaml | 155 + .../components/schemas/expense_category.yaml | 27 + .../components/schemas/fees_and_limits.yaml | 58 + .../components/schemas/fillable_invoice.yaml | 123 + openapi/components/schemas/invoice.yaml | 218 + openapi/components/schemas/payment.yaml | 86 + openapi/components/schemas/payment_term.yaml | 26 + openapi/components/schemas/paymentable.yaml | 35 + openapi/components/schemas/quote.yaml | 218 + .../components/schemas/recurring_expense.yaml | 171 + .../components/schemas/recurring_invoice.yaml | 227 + .../components/schemas/recurring_quote.yaml | 226 + openapi/components/schemas/subscription.yaml | 111 + openapi/components/schemas/system_log.yaml | 43 + openapi/components/schemas/task.yaml | 94 + openapi/components/schemas/user.yaml | 43 + openapi/components/schemas/vendor.yaml | 128 + .../components/schemas/vendor_contact.yaml | 70 + 34 files changed, 6102 insertions(+), 6064 deletions(-) create mode 100644 openapi/components/schemas/bank_transaction_rule.yaml create mode 100644 openapi/components/schemas/client.yaml create mode 100644 openapi/components/schemas/client_contact.yaml create mode 100644 openapi/components/schemas/client_gateway_token.yaml create mode 100644 openapi/components/schemas/company.yaml create mode 100644 openapi/components/schemas/company_gateway.yaml create mode 100644 openapi/components/schemas/company_ledger.yaml create mode 100644 openapi/components/schemas/company_settings.yaml create mode 100644 openapi/components/schemas/company_token.yaml create mode 100644 openapi/components/schemas/company_user.yaml create mode 100644 openapi/components/schemas/credit.yaml create mode 100644 openapi/components/schemas/design.yaml create mode 100644 openapi/components/schemas/document.yaml create mode 100644 openapi/components/schemas/error.yaml create mode 100644 openapi/components/schemas/expense.yaml create mode 100644 openapi/components/schemas/expense_category.yaml create mode 100644 openapi/components/schemas/fees_and_limits.yaml create mode 100644 openapi/components/schemas/fillable_invoice.yaml create mode 100644 openapi/components/schemas/invoice.yaml create mode 100644 openapi/components/schemas/payment.yaml create mode 100644 openapi/components/schemas/payment_term.yaml create mode 100644 openapi/components/schemas/paymentable.yaml create mode 100644 openapi/components/schemas/quote.yaml create mode 100644 openapi/components/schemas/recurring_expense.yaml create mode 100644 openapi/components/schemas/recurring_invoice.yaml create mode 100644 openapi/components/schemas/recurring_quote.yaml create mode 100644 openapi/components/schemas/subscription.yaml create mode 100644 openapi/components/schemas/system_log.yaml create mode 100644 openapi/components/schemas/task.yaml create mode 100644 openapi/components/schemas/user.yaml create mode 100644 openapi/components/schemas/vendor.yaml create mode 100644 openapi/components/schemas/vendor_contact.yaml diff --git a/openapi/api-docs.yaml b/openapi/api-docs.yaml index 92111a435447..7498ad9ac37d 100644 --- a/openapi/api-docs.yaml +++ b/openapi/api-docs.yaml @@ -13239,6 +13239,1214 @@ components: ########################### Generic filters available across all filter ################################## schemas: + CreditPaymentable: + properties: + credit_id: + description: 'The credit hashed id' + type: string + example: Opnel5aKBz + amount: + description: 'The credit amount' + type: string + example: '2' + type: object + GenericReportSchema: + properties: + date_range: + description: 'The string representation of the date range of data to be returned' + type: string + example: last7 + date_key: + description: 'The date column to search between.' + type: string + example: created_at + start_date: + description: 'The start date to search between' + type: string + example: '2000-10-31' + end_date: + description: 'The end date to search between' + type: string + example: '2' + report_keys: + type: array + items: + description: 'Array of Keys to export' + type: string + example: '[''name'',''date'']' + type: object + GroupSetting: + properties: + id: + description: 'The group setting hashed id' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: Opnel5aKBz + company_id: + description: 'The company hashed id' + type: string + example: Opnel5aKBz + name: + description: 'The name of the group' + type: string + example: 'A groupies group' + settings: + description: 'The settings object' + type: object + example: '' + type: object + InvoicePaymentable: + properties: + invoice_id: + description: ______ + type: string + example: Opnel5aKBz + amount: + description: ______ + type: string + example: '2' + type: object + + + + Product: + properties: + id: + description: 'The product hashed id' + type: string + example: Opnel5aKBz + type: object + Project: + properties: + id: + description: 'The project hashed id' + type: string + example: Opnel5aKBz + name: + description: 'The project name' + type: string + example: 'New Project' + type: object + PurchaseOrder: + properties: + id: + description: 'The purchase order hashed id' + type: string + example: Opnel5aKBz + type: object + + + + + + TaskSchedulerSchema: + properties: + paused: + description: 'The scheduler paused state' + type: boolean + example: 'false' + repeat_every: + description: 'Accepted values (DAY,WEEK,MONTH,3MONTHS,YEAR)' + type: string + example: DAY + start_from: + description: 'Timestamp when we should start the scheduler, default is today' + type: integer + example: '1652898504' + job: + description: 'Job, we can find list of available jobs in Scheduler model' + type: string + example: create_credit_report + date_range: + description: 'The string representation of the date range of data to be returned' + type: string + example: last7 + date_key: + description: 'The date column to search between.' + type: string + example: created_at + start_date: + description: 'The start date to search between' + type: string + example: '2022-10-31' + end_date: + description: 'The end date to search between' + type: string + example: '2022-10-31' + report_keys: + type: array + items: + description: 'Array of Keys to export' + type: string + example: '[''name'',''date'']' + type: object + UpdateTaskSchedulerSchema: + properties: + paused: + description: 'The scheduler paused state' + type: boolean + example: 'false' + repeat_every: + description: 'Accepted values (DAY,WEEK,MONTH,3MONTHS,YEAR)' + type: string + example: DAY + start_from: + description: 'Timestamp when we should start the scheduler, default is today' + type: integer + example: '1652898504' + job: + description: 'Job, we can find list of available jobs in Scheduler model' + type: string + example: create_credit_report + date_range: + description: 'The string representation of the date range of data to be returned' + type: string + example: last7 + date_key: + description: 'The date column to search between.' + type: string + example: created_at + start_date: + description: 'The start date to search between' + type: string + example: '2022-10-31' + end_date: + description: 'The end date to search between' + type: string + example: '2022-10-31' + type: object + UpdateJobForASchedulerSchema: + properties: + job: + description: 'Set action name, action names can be found in Scheduler Model' + type: string + example: create_client_report + type: object + + TaskStatus: + properties: + name: + description: 'The task status name' + type: string + example: Backlog + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + is_deleted: + description: 'A boolean flag determining if the task status has been deleted' + type: boolean + example: true + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + archived_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + type: object + TaxRate: + properties: + id: + description: 'Thie hashed id of the tax' + type: string + example: Opnel5aKBz + name: + description: 'The tax name' + type: string + example: GST + rate: + description: 'The tax rate' + type: number + example: '10' + is_deleted: + description: 'Boolean flag determining if the tax has been deleted' + type: boolean + example: true + type: object + Template: + properties: + html: + description: 'The template HTML' + type: string + example: '' + type: object + + AuthenticationError: + type: object + properties: + message: + description: 'These credentials do not match our records / Invalid Token' + type: string + example: 'These credentials do not match our records / Invalid Token' + ValidationError: + properties: + message: + description: 'The error message' + type: string + example: 'The given data was invalid.' + errors: + properties: + value: + type: array + items: + type: string + type: object + type: object + AuthorizationError: + properties: + message: + description: 'Insufficient permissions for this resource.' + type: string + example: 'Insufficient permissions for this resource.' + errors: + properties: + value: + type: array + items: + type: string + type: object + type: object + + + Webhook: + properties: + id: + description: 'The subscription hashed id' + type: string + example: AS3df3A + event_id: + description: 'The subscription event id' + type: string + example: AS3df3A + target_url: + description: 'The api endpoint' + type: string + example: AS3df3A + format: + description: 'JSON or UBL' + type: string + example: JSON + type: object + Task: + properties: + id: + description: 'The hashed id of the task' + type: string + example: Opnel5aKBz + user_id: + description: 'The hashed id of the user who created the task' + type: string + example: Opnel5aKBz + assigned_user_id: + description: 'The assigned user of the task' + type: string + example: Opnel5aKBz + company_id: + description: 'The hashed id of the company' + type: string + example: Opnel5aKBz + client_id: + description: 'The hashed if of the client' + type: string + example: Opnel5aKBz + invoice_id: + description: 'The hashed id of the invoice associated with the task' + type: string + example: Opnel5aKBz + project_id: + description: 'The hashed id of the project associated with the task' + type: string + example: Opnel5aKBz + number: + description: 'The number of the task' + type: string + example: TASK-123 + time_log: + description: 'An array of unix time stamps defining the start and end times of the task' + type: string + example: '[[1,2],[3,4]]' + is_running: + description: 'Determines if the task is still running' + type: boolean + example: true + is_deleted: + description: 'Boolean flag determining if the task has been deleted' + type: boolean + example: true + task_status_id: + description: 'The hashed id of the task status' + type: string + example: Opnel5aKBz + description: + description: 'The task description' + type: string + example: 'A wonder task to work on' + duration: + description: 'The task duration' + type: integer + example: '' + task_status_order: + description: 'The order of the task' + type: integer + example: '4' + custom_value1: + description: 'A custom value' + type: string + example: '2022-10-10' + custom_value2: + description: 'A custom value' + type: string + example: $1100 + custom_value3: + description: 'A custom value' + type: string + example: 'I need help' + custom_value4: + description: 'A custom value' + type: string + example: INV-3343 + created_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + type: object + RecurringInvoice: + properties: + id: + description: 'The hashed id of the recurring invoice' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: Opnel5aKBz + assigned_user_id: + description: 'The assigned user hashed id' + type: string + example: Opnel5aKBz + company_id: + description: 'The company hashed id' + type: string + example: Opnel5aKBz + client_id: + description: 'The client hashed id' + type: string + example: Opnel5aKBz + status_id: + description: 'The invoice status variable' + type: string + example: '4' + frequency_id: + description: 'The recurring invoice frequency' + type: number + example: '4' + remaining_cycles: + description: 'The number of invoices left to be generated' + type: number + example: '4' + number: + description: 'The recurringinvoice number - is a unique alpha numeric number per invoice per company' + type: string + example: INV_101 + po_number: + description: 'The purchase order associated with this recurring invoice' + type: string + example: PO-1234 + terms: + description: 'The invoice terms' + type: string + example: 'These are invoice terms' + public_notes: + description: 'The public notes of the invoice' + type: string + example: 'These are some public notes' + private_notes: + description: 'The private notes of the invoice' + type: string + example: 'These are some private notes' + footer: + description: 'The invoice footer notes' + type: string + example: '' + custom_value1: + description: 'A custom field value' + type: string + example: '2022-10-01' + custom_value2: + description: 'A custom field value' + type: string + example: 'Something custom' + custom_value3: + description: 'A custom field value' + type: string + example: '' + custom_value4: + description: 'A custom field value' + type: string + example: '' + tax_name1: + description: 'The tax name' + type: string + example: '' + tax_name2: + description: 'The tax name' + type: string + example: '' + tax_rate1: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_rate2: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_name3: + description: 'The tax name' + type: string + example: '' + tax_rate3: + description: 'The tax rate' + type: number + format: float + example: '10.00' + total_taxes: + description: 'The total taxes for the invoice' + type: number + format: float + example: '10.00' + line_items: + description: 'An array of objects which define the line items of the invoice' + type: object + example: '' + amount: + description: 'The invoice amount' + type: number + format: float + example: '10.00' + balance: + description: 'The invoice balance' + type: number + format: float + example: '10.00' + paid_to_date: + description: 'The amount paid on the invoice to date' + type: number + format: float + example: '10.00' + discount: + description: 'The invoice discount, can be an amount or a percentage' + type: number + format: float + example: '10.00' + partial: + description: 'The deposit/partial amount' + type: number + format: float + example: '10.00' + is_amount_discount: + description: 'Flag determining if the discount is an amount or a percentage' + type: boolean + example: true + is_deleted: + description: 'Defines if the invoice has been deleted' + type: boolean + example: true + uses_inclusive_taxes: + description: 'Defines the type of taxes used as either inclusive or exclusive' + type: boolean + example: true + date: + description: 'The Invoice Date' + type: string + format: date + example: '1994-07-30' + last_sent_date: + description: 'The last date the invoice was sent out' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The Next date for a reminder to be sent' + type: string + format: date + example: '1994-07-30' + partial_due_date: + description: 'The due date for the deposit/partial amount' + type: string + format: date + example: '1994-07-30' + due_date: + description: 'The due date of the invoice' + type: string + format: date + example: '1994-07-30' + settings: + $ref: '#/components/schemas/CompanySettings' + last_viewed: + description: Timestamp + type: number + format: integer + example: '1434342123' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + custom_surcharge1: + description: 'First Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge2: + description: 'Second Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge3: + description: 'Third Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge4: + description: 'Fourth Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge_tax1: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + type: object + + Client: + properties: + id: + description: 'The unique identifier of the client' + type: string + example: Opnel5aKBz + user_id: + description: 'The unique identifier of the user who created the client' + type: string + example: Ua6Rw4pVbS + company_id: + description: 'The unique identifier of the company the client belongs to' + type: string + example: Co7Vn3yLmW + contacts: + type: array + items: + $ref: '#/components/schemas/ClientContact' + name: + description: 'The name of the client company or organization' + type: string + example: "Jim's Housekeeping" + website: + description: 'The website URL of the client company or organization' + type: string + example: 'https://www.jims-housekeeping.com' + private_notes: + description: 'Notes that are only visible to the user who created the client' + type: string + example: 'Client prefers email communication over phone calls' + client_hash: + description: 'A unique hash value for the client' + type: string + example: asdfkjhk342hjhbfdvmnfb1 + industry_id: + description: 'The unique identifier of the industry the client operates in' + type: number + example: '5' + size_id: + description: 'The unique identifier for the size category of the client company or organization' + type: number + example: '2' + address1: + description: "First line of the client's address" + type: string + example: '123 Main St' + address2: + description: "Second line of the client's address, if needed" + type: string + example: 'Apt 4B' + city: + description: 'The city the client is located in' + type: string + example: 'Beverly Hills' + state: + description: 'The state, province, or locality the client is located in' + type: string + example: 'California' + postal_code: + description: 'The postal code or ZIP code of the client' + type: string + example: '90210' + phone: + description: "The client's phone number" + type: string + example: '555-3434-3434' + country_id: + description: "The unique identifier of the client's country" + type: number + format: integer + example: '1' + custom_value1: + description: 'A custom field for storing additional information' + type: string + example: 'Preferred contact: Email' + custom_value2: + description: 'A custom field for storing additional information' + type: string + example: 'Account manager: John Doe' + custom_value3: + description: 'A custom field for storing additional information' + type: string + example: 'VIP client: Yes' + custom_value4: + description: 'A custom field for storing additional information' + type: string + example: 'Annual contract value: $50,000' + vat_number: + description: "The client's VAT (Value Added Tax) number, if applicable" + type: string + example: 'VAT123456' + id_number: + description: 'A unique identification number for the client, such as a tax ID or business registration number' + type: string + number: + description: 'A system-assigned unique number for the client, typically used for invoicing purposes' + type: string + example: 'CL-0001' + shipping_address1: + description: "First line of the client's shipping address" + type: string + example: '5 Wallaby Way' + shipping_address2: + description: "Second line of the client's shipping address, if needed" + type: string + example: 'Suite 5' + shipping_city: + description: "The city of the client's shipping address" + type: string + example: 'Perth' + shipping_state: + description: "The state, province, or locality of the client's shipping address" + type: string + example: 'Western Australia' + shipping_postal_code: + description: "The postal code or ZIP code of the client's shipping address" + type: string + example: '6110' + shipping_country_id: + description: "The unique identifier of the country for the client's shipping address" + type: number + format: integer + example: '4' + is_deleted: + description: 'A boolean value indicating whether the client has been deleted or not' + type: boolean + example: false + balance: + description: 'The outstanding balance the client owes' + type: number + format: float + example: '500.00' + paid_to_date: + description: 'The total amount the client has paid to date' + type: number + format: float + example: '2000.00' + credit_balance: + description: 'The available credit balance for the client to use on future purchases' + type: number + format: float + example: '100.00' + last_login: + description: "The timestamp of the client's last login" + type: number + format: integer + example: '1628686031' + created_at: + description: 'The timestamp when the client was created' + type: number + format: integer + example: '1617629031' + updated_at: + description: 'The timestamp when the client was last updated' + type: number + format: integer + example: '1628445631' + settings: + $ref: '#/components/schemas/CompanySettings' + type: object + SystemLog: + properties: + id: + description: 'The account hashed id' + type: string + example: AS3df3A + company_id: + description: 'The company hashed id' + type: string + example: AS3df3A + user_id: + description: 'The user_id hashed id' + type: string + example: AS3df3A + client_id: + description: 'The client_id hashed id' + type: string + example: AS3df3A + event_id: + description: 'The Log Type ID' + type: integer + example: 1 + category_id: + description: 'The Category Type ID' + type: integer + example: 1 + type_id: + description: 'The Type Type ID' + type: integer + example: 1 + log: + description: 'The json object of the error' + type: object + example: '{''key'':''value''}' + updated_at: + description: Timestamp + type: string + example: '2' + created_at: + description: Timestamp + type: string + example: '2' + type: object + CompanyLedger: + properties: + entity_id: + description: 'This field will reference one of the following entity hashed ID payment_id, invoice_id or credit_id' + type: string + example: AS3df3A + notes: + description: 'The notes which reference this entry of the ledger' + type: string + example: 'Credit note for invoice #3212' + balance: + description: 'The client balance' + type: number + format: float + example: '10.00' + adjustment: + description: 'The amount the client balance is adjusted by' + type: number + format: float + example: '10.00' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + created_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + type: object + Credit: + properties: + id: + description: "The unique hashed ID of the credit" + type: string + example: Opnel5aKBz + user_id: + description: "The unique hashed ID of the user associated with the credit" + type: string + example: 1a2b3c4d5e + assigned_user_id: + description: "The unique hashed ID of the assigned user responsible for the credit" + type: string + example: 6f7g8h9i0j + company_id: + description: "The unique hashed ID of the company associated with the credit" + type: string + example: k1l2m3n4o5 + client_id: + description: "The unique hashed ID of the client associated with the credit" + type: string + example: p1q2r3s4t5 + status_id: + description: "The ID representing the current status of the credit" + type: string + example: 3 + invoice_id: + description: "The unique hashed ID of the linked invoice to which the credit is applied" + type: string + example: u1v2w3x4y5 + number: + description: "The unique alphanumeric credit number per company" + type: string + example: QUOTE_101 + po_number: + description: "The purchase order number referred to by the credit" + type: string + example: PO_12345 + terms: + description: "The terms associated with the credit" + type: string + example: "Net 30" + public_notes: + description: "Public notes for the credit" + type: string + example: "Thank you for your business." + private_notes: + description: "Private notes for internal use, not visible to the client" + type: string + example: "Client is requesting a discount." + footer: + description: "The footer text for the credit" + type: string + example: "Footer text goes here." + custom_value1: + description: "Custom value 1 for additional credit information" + type: string + example: "Custom data 1" + custom_value2: + description: "Custom value 2 for additional credit information" + type: string + example: "Custom data 2" + custom_value3: + description: "Custom value 3 for additional credit information" + type: string + example: "Custom data 3" + custom_value4: + description: "Custom value 4 for additional credit information" + type: string + example: "Custom data 4" + tax_name1: + description: "The name of the first tax applied to the credit" + type: string + example: "VAT" + tax_name2: + description: "The name of the second tax applied to the credit" + type: string + example: "GST" + tax_rate1: + description: "The rate of the first tax applied to the credit" + type: number + format: float + example: 10.00 + tax_rate2: + description: "The rate of the second tax applied to the credit" + type: number + format: float + example: 5.00 + tax_name3: + description: "The name of the third tax applied to the credit" + type: string + example: "PST" + tax_rate3: + description: "The rate of the third tax applied to the credit" + type: number + format: float + example: 8.00 + total_taxes: + description: "The total amount of taxes for the credit" + type: number + format: float + example: 23.00 + line_items: + description: "The array of line items included in the credit" + type: object + example: "[{item1}, {item2}]" + amount: + description: "The total amount of the credit" + type: number + format: float + example: 100.00 + balance: + description: "The outstanding balance of the credit" + type: number + format: float + example: 50.00 + paid_to_date: + description: "The total amount paid to date for the credit" + type: number + format: float + example: 50.00 + discount: + description: "The discount applied to the credit" + type: number + format: float + example: 10.00 + partial: + description: "The partial amount applied to the credit" + type: number + format: float + example: 20.00 + is_amount_discount: + description: "Indicates whether the discount applied is a fixed amount or a percentage" + type: boolean + example: true + is_deleted: + description: "Indicates whether the credit has been deleted" + type: boolean + example: false + uses_inclusive_taxes: + description: "Indicates whether the tax rates applied to the credit are inclusive or exclusive" + type: boolean + example: true + date: + description: "The date the credit was issued" + type: string + format: date + example: "1994-07-30" + last_sent_date: + description: "The date the credit was last sent out" + type: string + format: date + example: "1994-07-30" + next_send_date: + description: "The next scheduled date for sending a credit reminder" + type: string + format: date + example: "1994-07-30" + partial_due_date: + description: "The due date for the partial amount of the credit" + type: string + format: date + example: "1994-07-30" + due_date: + description: "The due date for the total amount of the credit" + type: string + format: date + example: "1994-07-30" + settings: + $ref: "#/components/schemas/CompanySettings" + last_viewed: + description: "The timestamp of the last time the credit was viewed" + type: number + format: integer + example: 1434342123 + updated_at: + description: "The timestamp of the last time the credit was updated" + type: number + format: integer + example: 1434342123 + archived_at: + description: "The timestamp of the last time the credit was archived" + type: number + format: integer + example: 1434342123 + custom_surcharge1: + description: "First custom surcharge amount" + type: number + format: float + example: 10.00 + custom_surcharge2: + description: 'Second Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge3: + description: 'Third Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge4: + description: 'Fourth Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge_tax1: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + type: object + Activity: + properties: + id: + description: 'The id field of the activity' + type: string + example: Opnel5aKBz + activity_type_id: + description: 'The activity type id' + type: string + example: Opnel5aKBz + client_id: + description: 'The client hashed id' + type: string + example: Opnel5aKBz + company_id: + description: 'The company hashed id' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: Opnel5aKBz + invoice_id: + description: 'The invoice hashed id' + type: string + example: Opnel5aKBz + payment_id: + description: 'The payment hashed id' + type: string + example: Opnel5aKBz + credit_id: + description: 'The credit hashed id' + type: string + example: Opnel5aKBz + updated_at: + description: 'Unixtimestamp the last time the record was updated' + type: integer + example: '343421434' + expense_id: + description: 'The expense hashed id' + type: string + example: Opnel5aKBz + is_system: + description: 'Defines is the activity was performed by the system' + type: boolean + example: true + contact_id: + description: 'The contact hashed id' + type: string + example: Opnel5aKBz + task_id: + description: 'The task hashed id' + type: string + example: Opnel5aKBz + notes: + description: 'Activity Notes' + type: string + example: Opnel5aKBz + token_id: + description: 'The hashed ID of the token who performed the action' + type: string + example: Opnel5aKBz + ip: + description: 'The IP Address of the user who performed the action' + type: string + example: 192.168.1.252 + user: + $ref: '#/components/schemas/User' + client: + $ref: '#/components/schemas/Client' + contact: + $ref: '#/components/schemas/ClientContact' + recurring_invoice: + $ref: '#/components/schemas/RecurringInvoice' + invoice: + $ref: '#/components/schemas/Invoice' + credit: + $ref: '#/components/schemas/Credit' + quote: + $ref: '#/components/schemas/Quote' + payment: + $ref: '#/components/schemas/Payment' + expense: + $ref: '#/components/schemas/Expense' + task: + $ref: '#/components/schemas/Task' + purchase_order: + $ref: '#/components/schemas/PurchaseOrder' + vendor: + $ref: '#/components/schemas/Vendor' + vendor_contact: + $ref: '#/components/schemas/VendorContact' + type: object + CompanyGateway: + properties: + id: + description: 'The hashed id of the company gateway' + type: string + example: Opnel5aKBz + company_id: + description: 'The company hashed id' + type: string + example: '2' + gateway_key: + description: 'The gateway key (hash)' + type: string + example: '2' + accepted_credit_cards: + description: 'Bitmask representation of cards' + type: integer + example: '32' + require_billing_address: + description: 'Determines if the the billing address is required prior to payment.' + type: boolean + example: true + require_shipping_address: + description: 'Determines if the the billing address is required prior to payment.' + type: boolean + example: true + config: + description: 'The configuration map for the gateway' + type: string + example: dfadsfdsafsafd + update_details: + description: 'Determines if the client details should be updated.' + type: boolean + example: true + fees_and_limits: + description: 'A mapped collection of the fees and limits for the configured gateway' + type: array + items: + $ref: '#/components/schemas/FeesAndLimits' + type: object + + BankTransactionRule: properties: id: @@ -13287,30 +14495,65 @@ components: type: string example: AS3df3A type: object + Paymentable: + properties: + id: + description: 'The paymentable hashed id' + type: string + example: AS3df3A + invoice_id: + description: 'The invoice hashed id' + type: string + example: AS3df3A + credit_id: + description: 'The credit hashed id' + type: string + example: AS3df3A + refunded: + description: 'The amount that has been refunded for this payment' + type: number + format: float + example: '10.00' + amount: + description: 'The amount that has been applied to the payment' + type: number + format: float + example: '10.00' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + created_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + type: object Subscription: properties: id: - description: ______ + description: Unique identifier for the subscription type: string example: Opnel5aKBz user_id: - description: ______ + description: Unique identifier for the user associated with the subscription type: string - example: Opnel5aKBz + example: Ua6Rw4pVbS product_id: - description: ______ + description: Unique identifier for the product associated with the subscription type: string - example: Opnel5aKBz + example: Pr5Ft7yBmC company_id: - description: ______ + description: Unique identifier for the company associated with the subscription type: string - example: Opnel5aKBz + example: Co7Vn3yLmW recurring_invoice_id: - description: ______ + description: Unique identifier for the recurring invoice associated with the subscription type: string - example: Opnel5aKBz + example: Ri2Yt8zJkP is_recurring: - description: ______ + description: Indicates whether the subscription is recurring type: boolean example: 'true' frequency_id: @@ -13322,61 +14565,61 @@ components: type: string example: always promo_code: - description: ______ + description: Promotional code applied to the subscription type: string example: PROMOCODE4U promo_discount: - description: ______ + description: Discount percentage or amount applied to the subscription type: number example: 10 is_amount_discount: - description: ______ + description: Indicates whether the discount is a fixed amount type: boolean example: 'true' allow_cancellation: - description: ______ + description: Indicates whether the subscription can be cancelled type: boolean example: 'true' per_seat_enabled: - description: ______ + description: Indicates whether the subscription pricing is per seat type: boolean example: 'true' currency_id: - description: ______ + description: Unique identifier for the currency used in the subscription type: integer example: '1' max_seats_limit: - description: ______ + description: Maximum number of seats allowed for the subscription type: integer example: '100' trial_enabled: - description: ______ + description: Indicates whether the subscription has a trial period type: boolean example: 'true' trial_duration: - description: ______ + description: Duration of the trial period in days type: integer - example: '2' + example: '14' allow_query_overrides: - description: ______ + description: Indicates whether query overrides are allowed for the subscription type: boolean example: 'true' allow_plan_changes: - description: ______ + description: Indicates whether plan changes are allowed for the subscription type: boolean example: 'true' refund_period: - description: ______ + description: Number of days within which refunds can be requested type: integer - example: '2' + example: '30' webhook_configuration: - description: ______ + description: Webhook configuration for the subscription type: string - example: '2' + example: 'expand reference for this' is_deleted: - description: ______ + description: Indicates whether the subscription has been deleted type: boolean - example: 'true' + example: 'false' archived_at: description: Timestamp type: number @@ -13398,474 +14641,630 @@ components: items: type: integer example: '[0,1,2,3,]' - ClientContact: + Invoice: properties: id: - description: 'The hashed if of the contact' + description: 'The invoice hashed id' type: string example: Opnel5aKBz user_id: - description: 'The hashed id of the user who created the contact' + description: 'The user hashed id' type: string example: Opnel5aKBz - company_id: - description: 'The hashed id of the company' - type: string - example: Opnel5aKBz - client_id: - description: 'The hashed id of the client' - type: string - example: Opnel5aKBz - first_name: - description: 'The first name of the contact' - type: string - example: John - last_name: - description: 'The last name of the contact' - type: string - example: Doe - phone: - description: 'The phone number of the contact' - type: string - example: 555-152-4524 - custom_value1: - description: 'A Custom field value' - type: string - example: '' - custom_value2: - description: 'A Custom field value' - type: string - example: '' - custom_value3: - description: 'A Custom field value' - type: string - example: '' - custom_value4: - description: 'A Custom field value' - type: string - example: '' - email: - description: 'The email of the contact' - type: string - example: '' - accepted_terms_version: - description: 'The terms of service which the contact has accpeted' - type: string - example: 'A long set of ToS' - password: - description: 'The hashed password of the contact' - type: string - example: '*****' - confirmation-code: - description: 'The confirmation code used to authenticate the contacts email address' - type: string - example: 333-sdjkh34gbasd - token: - description: 'A uuid based token.' - type: string - example: 333-sdjkh34gbasd - is_primary: - description: 'Defines is this contact is the primary contact for the client' - type: boolean - example: true - confirmed: - description: 'Boolean value confirms the user has confirmed their account.' - type: boolean - example: true - is_locked: - description: 'Boolean value defines if the contact has been locked out.' - type: boolean - example: true - send_email: - description: 'Boolean value determines is this contact should receive emails' - type: boolean - example: true - failed_logins: - description: 'The number of failed logins the contact has had' - type: number - format: integer - example: '3' - email_verified_at: - description: 'The date which the contact confirmed their email' - type: number - format: integer - example: '134341234234' - last_login: - description: Timestamp - type: number - format: integer - example: '134341234234' - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - deleted_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object - ClientGatewayToken: - properties: - id: - description: 'The hashed id of the client gateway token' - type: string - example: Opnel5aKBz - company_id: - description: 'The hashed id of the company' - type: string - example: '2' - client_id: - description: 'The hashed_id of the client' - type: string - example: '2' - token: - description: 'The payment token' - type: string - example: '2' - routing_number: - description: 'THe bank account routing number' - type: string - example: '2' - company_gateway_id: - description: 'The hashed id of the company gateway' - type: string - example: '2' - is_default: - description: 'Flag determining if the token is the default payment method' - type: boolean - example: 'true' - type: object - Client: - properties: - id: - description: 'The hashed id of the client' - type: string - example: Opnel5aKBz - user_id: - description: 'The hashed id of the user' - type: string - example: '' - company_id: - description: 'The hashed id of the company' - type: string - example: '' - contacts: - type: array - items: - $ref: '#/components/schemas/ClientContact' - name: - description: 'The client name' - type: string - example: 'Jims housekeeping' - website: - description: 'The client website' - type: string - example: www.jims.com - private_notes: - description: 'Private notes on the client' - type: string - example: 'These are very private notes' - client_hash: - description: 'The client hash' - type: string - example: asdfkjhk342hjhbfdvmnfb1 - industry_id: - description: 'The industry id of the client' - type: number - example: '5' - size_id: - description: 'The size id of the client' - type: number - example: '2' - address1: - description: 'Address line 1' - type: string - example: '' - address2: - description: 'Address line 2' - type: string - example: '' - city: - description: City - type: string - example: 'Beverley Hills' - state: - description: State/Locality - type: string - example: Californnia - postal_code: - description: 'Zip / Postal code' - type: string - example: '90210' - phone: - description: 'The client phone number' - type: string - example: 555-3434-3434 - country_id: - description: 'The client country id' - type: number - format: integer - example: '1' - custom_value1: - description: 'A custom value' - type: string - example: 'Something custom' - custom_value2: - description: 'A custom value' - type: string - example: '2002-01-01' - custom_value3: - description: 'A custom value' - type: string - example: 'Something custom' - custom_value4: - description: 'A custom value' - type: string - example: 'Something custom' - vat_number: - description: 'The client VAT number' - type: string - example: VAT123 - id_number: - description: ' The client id number' - type: string - example: CLIENT_ID_NUMBER - number: - description: 'The client number - assigned by the system typically' - type: string - example: '' - shipping_address1: - description: 'The shipping address line 1' - type: string - example: '5 Wallaby Way' - shipping_address2: - description: 'The shipping address line 2' - type: string - example: 'Suite 5' - shipping_city: - description: 'The shipping city' - type: string - example: Perth - shipping_state: - description: 'The shipping state' - type: string - example: 'Western Australia' - shipping_postal_code: - description: 'The shipping postal code' - type: string - example: '6110' - shipping_country_id: - description: 'The shipping country id' - type: number - format: integer - example: '4' - is_deleted: - description: 'Boolean flagged determining if the client has been deleted' - type: boolean - example: true - balance: - description: 'The client balance' - type: number - format: float - example: '10.00' - paid_to_date: - description: 'The amount the client has paid to date.' - type: number - format: float - example: '10.00' - credit_balance: - description: 'An amount which is available to the client for future use.' - type: number - format: float - example: '10.00' - last_login: - description: Timestamp - type: number - format: integer - example: '134341234234' - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - settings: - $ref: '#/components/schemas/CompanySettings' - type: object - CompanyGateway: - properties: - id: - description: 'The hashed id of the company gateway' + assigned_user_id: + description: 'The assigned user hashed id' type: string example: Opnel5aKBz company_id: description: 'The company hashed id' type: string - example: '2' - gateway_key: - description: 'The gateway key (hash)' + example: Opnel5aKBz + client_id: + description: 'The client hashed id' type: string - example: '2' - accepted_credit_cards: - description: 'Bitmask representation of cards' - type: integer - example: '32' - require_billing_address: - description: 'Determines if the the billing address is required prior to payment.' - type: boolean - example: true - require_shipping_address: - description: 'Determines if the the billing address is required prior to payment.' - type: boolean - example: true - config: - description: 'The configuration map for the gateway' + example: Opnel5aKBz + status_id: + description: 'The invoice status variable' type: string - example: dfadsfdsafsafd - update_details: - description: 'Determines if the client details should be updated.' - type: boolean - example: true - fees_and_limits: - description: 'A mapped collection of the fees and limits for the configured gateway' - type: array - items: - $ref: '#/components/schemas/FeesAndLimits' - type: object - CompanyLedger: - properties: - entity_id: - description: 'This field will reference one of the following entity hashed ID payment_id, invoice_id or credit_id' + example: '4' + number: + description: 'The invoice number - is a unique alpha numeric number per invoice per company' type: string - example: AS3df3A - notes: - description: 'The notes which reference this entry of the ledger' + example: INV_101 + po_number: + description: 'The purchase order associated with this invoice' type: string - example: 'Credit note for invoice #3212' + example: PO-1234 + terms: + description: 'The invoice terms' + type: string + example: 'These are invoice terms' + public_notes: + description: 'The public notes of the invoice' + type: string + example: 'These are some public notes' + private_notes: + description: 'The private notes of the invoice' + type: string + example: 'These are some private notes' + footer: + description: 'The invoice footer notes' + type: string + example: '' + custom_value1: + description: 'A custom field value' + type: string + example: '2022-10-01' + custom_value2: + description: 'A custom field value' + type: string + example: 'Something custom' + custom_value3: + description: 'A custom field value' + type: string + example: '' + custom_value4: + description: 'A custom field value' + type: string + example: '' + tax_name1: + description: 'The tax name' + type: string + example: '' + tax_name2: + description: 'The tax name' + type: string + example: '' + tax_rate1: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_rate2: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_name3: + description: 'The tax name' + type: string + example: '' + tax_rate3: + description: 'The tax rate' + type: number + format: float + example: '10.00' + total_taxes: + description: 'The total taxes for the invoice' + type: number + format: float + example: '10.00' + line_items: + description: 'An array of objects which define the line items of the invoice' + type: object + example: '' + amount: + description: 'The invoice amount' + type: number + format: float + example: '10.00' balance: - description: 'The client balance' + description: 'The invoice balance' type: number format: float example: '10.00' - adjustment: - description: 'The amount the client balance is adjusted by' + paid_to_date: + description: 'The amount paid on the invoice to date' type: number format: float example: '10.00' + discount: + description: 'The invoice discount, can be an amount or a percentage' + type: number + format: float + example: '10.00' + partial: + description: 'The deposit/partial amount' + type: number + format: float + example: '10.00' + is_amount_discount: + description: 'Flag determining if the discount is an amount or a percentage' + type: boolean + example: true + is_deleted: + description: 'Defines if the invoice has been deleted' + type: boolean + example: true + uses_inclusive_taxes: + description: 'Defines the type of taxes used as either inclusive or exclusive' + type: boolean + example: true + date: + description: 'The Invoice Date' + type: string + format: date + example: '1994-07-30' + last_sent_date: + description: 'The last date the invoice was sent out' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The Next date for a reminder to be sent' + type: string + format: date + example: '1994-07-30' + partial_due_date: + description: 'The due date for the deposit/partial amount' + type: string + format: date + example: '1994-07-30' + due_date: + description: 'The due date of the invoice' + type: string + format: date + example: '1994-07-30' + settings: + $ref: '#/components/schemas/CompanySettings' + last_viewed: + description: Timestamp + type: number + format: integer + example: '1434342123' updated_at: description: Timestamp type: number format: integer example: '1434342123' - created_at: + archived_at: description: Timestamp type: number format: integer example: '1434342123' + custom_surcharge1: + description: 'First Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge2: + description: 'Second Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge3: + description: 'Third Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge4: + description: 'Fourth Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge_tax1: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + type: object + + FeesAndLimits: + properties: + min_limit: + description: 'The minimum amount accepted for this gateway' + type: string + example: '2' + max_limit: + description: 'The maximum amount accepted for this gateway' + type: string + example: '2' + fee_amount: + description: 'The gateway fee amount' + type: number + format: float + example: '2.0' + fee_percent: + description: 'The gateway fee percentage' + type: number + format: float + example: '2.0' + fee_tax_name1: + description: 'Fee tax name' + type: string + example: GST + fee_tax_name2: + description: 'Fee tax name' + type: string + example: VAT + fee_tax_name3: + description: 'Fee tax name' + type: string + example: 'CA Sales Tax' + fee_tax_rate1: + description: 'The tax rate' + type: number + format: float + example: '10.0' + fee_tax_rate2: + description: 'The tax rate' + type: number + format: float + example: '17.5' + fee_tax_rate3: + description: 'The tax rate' + type: number + format: float + example: '25.0' + fee_cap: + description: 'If set the fee amount will be no higher than this amount' + type: number + format: float + example: '2.0' + adjust_fee_percent: + description: 'Adjusts the fee to match the exact gateway fee.' + type: boolean + example: true + type: object + BankTransaction: + properties: + id: + description: 'The bank integration hashed id' + type: string + example: AS3df3A + company_id: + description: 'The company hashed id' + type: string + example: AS3df3A + user_id: + description: 'The user hashed id' + type: string + example: AS3df3A + transaction_id: + description: 'The id of the transaction rule' + type: integer + example: 343434 + amount: + description: 'The transaction amount' + type: number + example: 10 + currency_id: + description: 'The currency ID of the currency' + type: string + example: '1' + account_type: + description: 'The account type' + type: string + example: creditCard + description: + description: 'The description of the transaction' + type: string + example: 'Potato purchases for kevin' + category_id: + description: 'The category id' + type: integer + example: 1 + category_type: + description: 'The category description' + type: string + example: Expenses + base_type: + description: 'Either CREDIT or DEBIT' + type: string + example: CREDIT + date: + description: 'The date of the transaction' + type: string + example: '2022-09-01' + bank_account_id: + description: 'The ID number of the bank account' + type: integer + example: '1' type: object Company: properties: id: - description: 'The company hash id' + description: "The unique hashed identifier for the company" type: string example: WJxbojagwO size_id: - description: 'The company size ID' + description: "The unique identifier representing the company's size category" type: string - example: '1' + example: '2' industry_id: - description: 'The company industry ID' + description: "The unique identifier representing the company's industry category" type: string - example: '1' + example: '5' slack_webhook_url: - description: 'The slack webhook notification URL' + description: "The URL for the company's Slack webhook notifications" type: string - example: 'https://slack.com/sh328sj' + example: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX' google_analytics_key: - description: 'The google analytics key' + description: "The company's Google Analytics tracking ID" type: string - example: '1' + example: 'UA-123456789-1' portal_mode: - description: 'Determines the client facing urls ie: subdomain,domain,iframe' + description: "The mode determining how client-facing URLs are structured (e.g., subdomain, domain, or iframe)" type: string example: subdomain subdomain: - description: 'Specifies the first part of the company domain ie acme in acme.domain.com' + description: "The subdomain prefix for the company's domain (e.g., 'acme' in acme.domain.com)" type: string - example: aceme + example: acme portal_domain: - description: 'The fully qualified domain for client facing URLS' + description: "The fully qualified domain used for client-facing URLs" type: string example: 'https://subdomain.invoicing.co' enabled_tax_rates: - description: 'Number of taxes rates used per entity' + description: "The number of tax rates used per entity" type: integer - example: '1' + example: '2' fill_products: - description: 'Toggles filling a product description based on product key' + description: "A flag determining whether to auto-fill product descriptions based on the product key" type: boolean example: true convert_products: - description: ___________ + description: "A flag determining whether to convert products between different types or units" type: boolean example: true update_products: - description: 'Toggles updating a product description which description changes' + description: "A flag determining whether to update product descriptions when the description changes" type: boolean example: true show_product_details: - description: 'Toggles showing a product description which description changes' + description: "A flag determining whether to display product details in the user interface" type: boolean example: true custom_fields: - description: 'Custom fields map' + description: "A mapping of custom fields for various objects within the company" type: object enable_product_cost: - description: 'Show/Hide the product cost field in the UI' + description: "A flag determining whether to show or hide the product cost field in the user interface" type: boolean example: true enable_product_quantity: - description: 'Show/hide the product quantity field (used in the UI to show the default quantity)' + description: "A flag determining whether to show or hide the product quantity field in the user interface" type: boolean example: true default_quantity: - description: 'Enable/Disable whether to use a default quantity' + description: "A flag determining whether to use a default quantity for products" type: boolean example: true custom_surcharge_taxes1: - description: 'Toggles charging taxes on custom surcharge amounts' + description: "A flag determining whether to apply taxes on custom surcharge amounts for the first custom surcharge field" type: boolean example: true custom_surcharge_taxes2: - description: 'Toggles charging taxes on custom surcharge amounts' + description: "A flag determining whether to apply taxes on custom surcharge amounts for the second custom surcharge field" type: boolean example: true custom_surcharge_taxes3: - description: 'Toggles charging taxes on custom surcharge amounts' + description: "A flag determining whether to apply taxes on custom surcharge amounts for the third custom surcharge field" type: boolean example: true custom_surcharge_taxes4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true + description: "A flag determining whether to apply taxes on custom surcharge amounts for the fourth custom" logo: - description: 'The company logo - binary' - type: object + description: "The company logo file in binary format" + type: string + format: binary example: logo.png settings: $ref: '#/components/schemas/CompanySettings' type: object + Vendor: + properties: + id: + description: 'The hashed id of the vendor' + type: string + example: Opnel5aKBz + user_id: + description: 'The hashed id of the user who created the vendor' + type: string + example: Opnel5aKBz + assigned_user_id: + description: 'The hashed id of the assigned user to this vendor' + type: string + example: Opnel5aKBz + company_id: + description: 'The hashed id of the company' + type: string + example: Opnel5aKBz + client_id: + description: 'The hashed id of the client' + type: string + example: Opnel5aKBz + contacts: + type: array + items: + $ref: '#/components/schemas/VendorContact' + name: + description: 'The vendor name' + type: string + example: 'Harry''s cafe de wheels' + website: + description: 'The website of the vendor' + type: string + example: www.harry.com + private_notes: + description: 'The private notes of the vendor' + type: string + example: 'Shhh, don''t tell the vendor' + industry_id: + description: 'The industry id of the vendor' + type: string + example: '1' + size_id: + description: ________ + type: string + example: '' + address1: + description: ________ + type: string + example: '' + address2: + description: ________ + type: string + example: '' + city: + description: ________ + type: string + example: '' + state: + description: ________ + type: string + example: '' + postal_code: + description: ________ + type: string + example: '' + phone: + description: 'The client phone number' + type: string + example: 555-3434-3434 + country_id: + description: ________ + type: string + example: '' + currency_id: + description: ________ + type: string + example: '4' + custom_value1: + description: ________ + type: string + example: '' + custom_value2: + description: ________ + type: string + example: '' + custom_value3: + description: ________ + type: string + example: '' + custom_value4: + description: ________ + type: string + example: '' + vat_number: + description: ________ + type: string + example: '' + id_number: + description: ________ + type: string + example: '' + number: + description: ________ + type: string + example: '' + is_deleted: + description: ________ + type: boolean + example: true + last_login: + description: Timestamp + type: number + format: integer + example: '134341234234' + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + settings: + $ref: '#/components/schemas/CompanySettings' + type: object + BankIntegration: + properties: + id: + description: 'The bank integration hashed id' + type: string + example: AS3df3A + company_id: + description: 'The company hashed id' + type: string + example: AS3df3A + user_id: + description: 'The user hashed id' + type: string + example: AS3df3A + provider_bank_name: + description: 'The providers bank name' + type: string + example: 'Chase Bank' + bank_account_id: + description: 'The bank account id' + type: integer + example: '1233434' + bank_account_name: + description: 'The name of the account' + type: string + example: 'My Checking Acc' + bank_account_number: + description: 'The account number' + type: string + example: '111 234 2332' + bank_account_status: + description: 'The status of the bank account' + type: string + example: ACTIVE + bank_account_type: + description: 'The type of account' + type: string + example: CREDITCARD + balance: + description: 'The current bank balance if available' + type: number + example: '1000000' + currency: + description: 'iso_3166_3 code' + type: string + example: USD + type: object + ExpenseCategory: + properties: + id: + description: 'The expense hashed id' + type: string + example: Opnel5aKBz + name: + description: 'The expense category name' + type: string + example: Accounting + user_id: + description: 'The user hashed id' + type: string + example: XS987sD + is_deleted: + description: 'Flag determining whether the expense category has been deleted' + type: boolean + example: true + updated_at: + description: 'The updated at timestamp' + type: integer + example: '2' + created_at: + description: 'The created at timestamp' + type: integer + example: '2' + type: object CompanySettings: properties: timezone_id: @@ -14458,405 +15857,6 @@ components: type: boolean example: false type: object - CompanyToken: - properties: - name: - description: 'The token name' - type: string - example: 'Token Name' - token: - description: 'The token value' - type: string - example: AS3df3jUUH765fhfd9KJuidj3JShjA - is_system: - description: 'Determines whether the token is created by the system rather than a user' - type: boolean - example: 'true' - type: object - CompanyUser: - properties: - permissions: - description: 'The company user permissions' - type: string - example: '[create_invoice]' - settings: - description: 'Settings that are used for the frontend applications to store user preferences / metadata' - type: object - example: 'json object' - is_owner: - description: 'Determines whether the user owns this company' - type: boolean - example: true - is_admin: - description: 'Determines whether the user is the admin of this company' - type: boolean - example: true - is_locked: - description: 'Determines whether the users access to this company has been locked' - type: boolean - example: true - updated_at: - description: 'The last time the record was modified, format Unix Timestamp' - type: integer - example: '1231232312321' - deleted_at: - description: 'Timestamp when the user was archived, format Unix Timestamp' - type: integer - example: '12312312321' - account: - $ref: '#/components/schemas/Account' - company: - $ref: '#/components/schemas/Company' - user: - $ref: '#/components/schemas/User' - token: - $ref: '#/components/schemas/CompanyToken' - type: object - CreditPaymentable: - properties: - credit_id: - description: 'The credit hashed id' - type: string - example: Opnel5aKBz - amount: - description: 'The credit amount' - type: string - example: '2' - type: object - Credit: - properties: - id: - description: 'The credit hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: '' - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: '' - company_id: - description: 'The company hashed id' - type: string - example: '' - client_id: - description: 'The client hashed id' - type: string - example: '' - status_id: - description: 'The status field id infors of the current status of the credit' - type: string - example: '' - invoice_id: - description: 'The linked invoice this credit is applied to' - type: string - example: '' - number: - description: 'The credit number - is a unique alpha numeric number per credit per company' - type: string - example: QUOTE_101 - po_number: - description: 'The purchase order number this credit refers to' - type: string - example: '' - terms: - description: 'The credit terms field' - type: string - example: '' - public_notes: - description: 'The public notes field of the credit' - type: string - example: '' - private_notes: - description: 'The private notes field of the credit' - type: string - example: '' - footer: - description: 'The credit footer text' - type: string - example: '' - custom_value1: - description: 'A Custom value' - type: string - example: '' - custom_value2: - description: 'A Custom value' - type: string - example: '' - custom_value3: - description: 'A Custom value' - type: string - example: '' - custom_value4: - description: 'A Custom value' - type: string - example: '' - tax_name1: - description: 'The tax name' - type: string - example: '' - tax_name2: - description: 'The tax rate' - type: string - example: '' - tax_rate1: - description: 'The tax name' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - total_taxes: - description: 'The total taxes for the credit' - type: number - format: float - example: '10.00' - line_items: - description: 'The line items array containing the line items of the credit' - type: object - example: '' - amount: - description: 'The total credit amount' - type: number - format: float - example: '10.00' - balance: - description: 'The credit balance' - type: number - format: float - example: '10.00' - paid_to_date: - description: _________ - type: number - format: float - example: '10.00' - discount: - description: _________ - type: number - format: float - example: '10.00' - partial: - description: _________ - type: number - format: float - example: '10.00' - is_amount_discount: - description: _________ - type: boolean - example: true - is_deleted: - description: _________ - type: boolean - example: true - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' - type: boolean - example: true - date: - description: 'The Credit Date' - type: string - format: date - example: '1994-07-30' - last_sent_date: - description: 'The last date the credit was sent out' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The Next date for a reminder to be sent' - type: string - format: date - example: '1994-07-30' - partial_due_date: - description: _________ - type: string - format: date - example: '1994-07-30' - due_date: - description: _________ - type: string - format: date - example: '1994-07-30' - settings: - $ref: '#/components/schemas/CompanySettings' - last_viewed: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge_tax1: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax2: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - type: object - Design: - properties: - id: - description: 'The design hashed id' - type: string - example: AS3df3A - name: - description: 'The design name' - type: string - example: Beauty - design: - description: 'The design HTML' - type: string - example: '' - is_custom: - description: 'Flag to determine if the design is a custom user design' - type: boolean - example: true - is_active: - description: 'Flag to determine if the design is available for use' - type: boolean - example: true - is_deleted: - description: 'Flag to determine if the design is deleted' - type: boolean - example: true - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - deleted_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object - Document: - properties: - id: - description: 'The document hashed id' - type: string - example: AS3df3A - user_id: - description: 'The user hashed id' - type: string - example: '' - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: '' - project_id: - description: 'The project associated with this document' - type: string - example: '' - vendor_id: - description: 'The vendor associated with this documents' - type: string - example: '' - name: - description: 'The document name' - type: string - example: Beauty - url: - description: 'The document url' - type: string - example: Beauty - preview: - description: 'The document preview url' - type: string - example: Beauty - type: - description: 'The document type' - type: string - example: Beauty - disk: - description: 'The document disk' - type: string - example: Beauty - hash: - description: 'The document hashed' - type: string - example: Beauty - is_deleted: - description: 'Flag to determine if the document is deleted' - type: boolean - example: true - is_default: - description: 'Flag to determine if the document is a default doc' - type: boolean - example: true - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - deleted_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object Error: properties: message: @@ -14868,644 +15868,128 @@ components: type: integer example: '500' type: object - ExpenseCategory: - properties: - id: - description: 'The expense hashed id' - type: string - example: Opnel5aKBz - name: - description: 'The expense category name' - type: string - example: Accounting - user_id: - description: 'The user hashed id' - type: string - example: XS987sD - is_deleted: - description: 'Flag determining whether the expense category has been deleted' - type: boolean - example: true - updated_at: - description: 'The updated at timestamp' - type: integer - example: '2' - created_at: - description: 'The created at timestamp' - type: integer - example: '2' - type: object - Expense: - properties: - id: - description: 'The expense hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: '' - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: '' - company_id: - description: 'The company hashed id' - type: string - example: '' - client_id: - description: 'The client hashed id' - type: string - example: '' - invoice_id: - description: 'The related invoice hashed id' - type: string - example: '' - bank_id: - description: 'The bank id related to this expense' - type: string - example: '' - invoice_currency_id: - description: 'The currency id of the related invoice' - type: string - example: '' - expense_currency_id: - description: 'The currency id of the expense' - type: string - example: '' - invoice_category_id: - description: 'The invoice category id' - type: string - example: '' - payment_type_id: - description: 'The payment type id' - type: string - example: '' - recurring_expense_id: - description: 'The related recurring expense this expense was created from' - type: string - example: '' - private_notes: - description: 'The private notes of the expense' - type: string - example: '' - public_notes: - description: 'The public notes of the expense' - type: string - example: '' - transaction_reference: - description: 'The transaction references of the expense' - type: string - example: '' - transcation_id: - description: 'The transaction id of the expense' - type: string - example: '' - custom_value1: - description: 'A custom value' - type: string - example: '' - custom_value2: - description: 'A custom value' - type: string - example: '' - custom_value3: - description: 'A custom value' - type: string - example: '' - custom_value4: - description: 'A custom value' - type: string - example: '' - tax_name1: - description: 'Tax name' - type: string - example: '' - tax_name2: - description: 'Tax name' - type: string - example: '' - tax_rate1: - description: 'Tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'Tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'Tax name' - type: string - example: '' - tax_rate3: - description: 'Tax rate' - type: number - format: float - example: '10.00' - amount: - description: 'The total expense amont' - type: number - format: float - example: '10.00' - foreign_amount: - description: 'The total foreign amount of the expense' - type: number - format: float - example: '10.00' - exchange_rate: - description: 'The exchange rate at the time of the expense' - type: number - format: float - example: '0.80' - date: - description: 'The expense date formate Y-m-d' - type: string - example: '2022-12-01' - payment_date: - description: 'The date of payment for the expense, format Y-m-d' - type: string - example: '' - should_be_invoiced: - description: 'Flag whether the expense should be invoiced' - type: boolean - example: true - is_deleted: - description: 'Boolean determining whether the expense has been deleted' - type: boolean - example: true - invoice_documents: - description: 'Passing the expense documents over to the invoice' - type: boolean - example: true - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - type: object - FeesAndLimits: - properties: - min_limit: - description: 'The minimum amount accepted for this gateway' - type: string - example: '2' - max_limit: - description: 'The maximum amount accepted for this gateway' - type: string - example: '2' - fee_amount: - description: 'The gateway fee amount' - type: number - format: float - example: '2.0' - fee_percent: - description: 'The gateway fee percentage' - type: number - format: float - example: '2.0' - fee_tax_name1: - description: 'Fee tax name' - type: string - example: GST - fee_tax_name2: - description: 'Fee tax name' - type: string - example: VAT - fee_tax_name3: - description: 'Fee tax name' - type: string - example: 'CA Sales Tax' - fee_tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.0' - fee_tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '17.5' - fee_tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '25.0' - fee_cap: - description: 'If set the fee amount will be no higher than this amount' - type: number - format: float - example: '2.0' - adjust_fee_percent: - description: 'Adjusts the fee to match the exact gateway fee.' - type: boolean - example: true - type: object FillableInvoice: properties: assigned_user_id: - description: __________ + description: "The assigned user's hashed ID" type: string - example: '' + example: 'a1b2c3d4' client_id: - description: ________ + description: "The client's hashed ID" type: string - example: '' + example: 'x1y2z3a4' number: - description: 'The invoice number - is a unique alpha numeric number per invoice per company' + description: "The unique alphanumeric invoice number for each invoice per company" type: string example: INV_101 po_number: - description: ________ + description: "The purchase order number associated with the invoice" type: string - example: '' + example: 'PO12345' terms: - description: ________ + description: "The terms and conditions for the invoice" type: string - example: '' + example: 'Net 30' public_notes: - description: ________ + description: "Public notes visible to the client on the invoice" type: string - example: '' + example: 'Thank you for your business.' private_notes: - description: ________ + description: "Private notes for internal use only" type: string - example: '' + example: 'Client is a slow payer.' footer: - description: ________ + description: "The footer text displayed on the invoice" type: string - example: '' + example: 'Authorized Signature' custom_value1: - description: ________ + description: "First custom value for additional information" type: string - example: '' + example: 'Project ABC' custom_value2: - description: ________ + description: "Second custom value for additional information" type: string - example: '' + example: 'Department XYZ' custom_value3: - description: ________ + description: "Third custom value for additional information" type: string - example: '' + example: 'Location 123' custom_value4: - description: ________ + description: "Fourth custom value for additional information" type: string - example: '' + example: 'Currency USD' tax_name1: - description: ________ + description: "Name of the first tax applied to the invoice" type: string - example: '' + example: 'VAT' tax_name2: - description: ________ + description: "Name of the second tax applied to the invoice" type: string - example: '' + example: 'GST' tax_rate1: - description: _________ + description: "Rate of the first tax applied to the invoice" type: number - example: '10.00' + example: 10.00 tax_rate2: - description: _________ + description: "Rate of the second tax applied to the invoice" type: number - example: '10.00' + example: 5.00 tax_name3: - description: ________ + description: "Name of the third tax applied to the invoice" type: string - example: '' + example: 'PST' tax_rate3: - description: _________ + description: "Rate of the third tax applied to the invoice" type: number - example: '10.00' + example: 8.00 line_items: - description: _________ + description: "Array of line items included in the invoice" type: object - example: '' + example: "[{item1}, {item2}]" discount: - description: _________ + description: "The discount applied to the invoice" type: number - example: '10.00' + example: 10.00 partial: - description: _________ + description: "The partial amount applied to the invoice" type: number - example: '10.00' + example: 20.00 is_amount_discount: - description: _________ - type: boolean - example: '1' - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' - type: boolean - example: '1' - date: - description: 'The Invoice Date' - type: string - example: '1994-07-30' - partial_due_date: - description: _________ - type: string - example: '1994-07-30' - due_date: - description: _________ - type: string - example: '1994-07-30' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - example: '10.00' - type: object - GenericReportSchema: - properties: - date_range: - description: 'The string representation of the date range of data to be returned' - type: string - example: last7 - date_key: - description: 'The date column to search between.' - type: string - example: created_at - start_date: - description: 'The start date to search between' - type: string - example: '2000-10-31' - end_date: - description: 'The end date to search between' - type: string - example: '2' - report_keys: - type: array - items: - description: 'Array of Keys to export' - type: string - example: '[''name'',''date'']' - type: object - GroupSetting: - properties: - id: - description: 'The group setting hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: Opnel5aKBz - company_id: - description: 'The company hashed id' - type: string - example: Opnel5aKBz - name: - description: 'The name of the group' - type: string - example: 'A groupies group' - settings: - description: 'The settings object' - type: object - example: '' - type: object - InvoicePaymentable: - properties: - invoice_id: - description: ______ - type: string - example: Opnel5aKBz - amount: - description: ______ - type: string - example: '2' - type: object - Invoice: - properties: - id: - description: 'The invoice hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: Opnel5aKBz - company_id: - description: 'The company hashed id' - type: string - example: Opnel5aKBz - client_id: - description: 'The client hashed id' - type: string - example: Opnel5aKBz - status_id: - description: 'The invoice status variable' - type: string - example: '4' - number: - description: 'The invoice number - is a unique alpha numeric number per invoice per company' - type: string - example: INV_101 - po_number: - description: 'The purchase order associated with this invoice' - type: string - example: PO-1234 - terms: - description: 'The invoice terms' - type: string - example: 'These are invoice terms' - public_notes: - description: 'The public notes of the invoice' - type: string - example: 'These are some public notes' - private_notes: - description: 'The private notes of the invoice' - type: string - example: 'These are some private notes' - footer: - description: 'The invoice footer notes' - type: string - example: '' - custom_value1: - description: 'A custom field value' - type: string - example: '2022-10-01' - custom_value2: - description: 'A custom field value' - type: string - example: 'Something custom' - custom_value3: - description: 'A custom field value' - type: string - example: '' - custom_value4: - description: 'A custom field value' - type: string - example: '' - tax_name1: - description: 'The tax name' - type: string - example: '' - tax_name2: - description: 'The tax name' - type: string - example: '' - tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - total_taxes: - description: 'The total taxes for the invoice' - type: number - format: float - example: '10.00' - line_items: - description: 'An array of objects which define the line items of the invoice' - type: object - example: '' - amount: - description: 'The invoice amount' - type: number - format: float - example: '10.00' - balance: - description: 'The invoice balance' - type: number - format: float - example: '10.00' - paid_to_date: - description: 'The amount paid on the invoice to date' - type: number - format: float - example: '10.00' - discount: - description: 'The invoice discount, can be an amount or a percentage' - type: number - format: float - example: '10.00' - partial: - description: 'The deposit/partial amount' - type: number - format: float - example: '10.00' - is_amount_discount: - description: 'Flag determining if the discount is an amount or a percentage' - type: boolean - example: true - is_deleted: - description: 'Defines if the invoice has been deleted' + description: "Indicates whether the discount applied is a fixed amount or a percentage" type: boolean example: true uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' + description: "Indicates whether the tax rates applied to the invoice are inclusive or exclusive" type: boolean example: true date: - description: 'The Invoice Date' + description: "The date the invoice was issued" type: string - format: date - example: '1994-07-30' - last_sent_date: - description: 'The last date the invoice was sent out' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The Next date for a reminder to be sent' - type: string - format: date example: '1994-07-30' partial_due_date: - description: 'The due date for the deposit/partial amount' + description: "The due date for the partial payment" type: string - format: date - example: '1994-07-30' + example: '1994-08-15' due_date: - description: 'The due date of the invoice' + description: "The due date for the invoice" type: string - format: date - example: '1994-07-30' - settings: - $ref: '#/components/schemas/CompanySettings' - last_viewed: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' + example: '1994-08-30' custom_surcharge1: - description: 'First Custom Surcharge' + description: "First custom surcharge applied to the invoice" type: number - format: float - example: '10.00' + example: 10.00 custom_surcharge2: - description: 'Second Custom Surcharge' + description: "Second custom surcharge applied to the invoice" type: number - format: float - example: '10.00' + example: 15.00 custom_surcharge3: - description: 'Third Custom Surcharge' + description: "Third custom surcharge applied to the invoice" type: number - format: float - example: '10.00' + example: 5.00 custom_surcharge4: - description: 'Fourth Custom Surcharge' + description: "Fourth custom surcharge applied to the invoice" type: number - format: float - example: '10.00' - custom_surcharge_tax1: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax2: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true + example: 20.00 type: object Payment: properties: @@ -15592,98 +16076,99 @@ components: items: $ref: '#/components/schemas/CreditPaymentable' type: object - PaymentTerm: + + User: properties: - num_days: - description: 'The payment term length in days' + id: + description: 'The hashed id of the user' + type: string + example: Opnel5aKBz + first_name: + description: 'The first name of the user' + type: string + example: Brad + last_name: + description: 'The last name of the user' + type: string + example: Pitt + email: + description: 'The users email address' + type: string + example: brad@pitt.com + phone: + description: 'The users phone number' + type: string + example: 555-1233-23232 + signature: + description: 'The users sign off signature' + type: string + example: 'Have a nice day!' + avatar: + description: 'The users avatar' + type: string + example: 'https://url.to.your/avatar.png' + accepted_terms_version: + description: 'The version of the invoice ninja terms that has been accepted by the user' + type: string + example: 1.0.1 + oauth_user_id: + description: 'The provider id of the oauth entity' + type: string + example: jkhasdf789as6f675sdf768sdfs + oauth_provider_id: + description: 'The oauth entity id' + type: string + example: google + type: object + CompanyUser: + properties: + permissions: + description: 'The company user permissions' + type: string + example: '[create_invoice]' + settings: + description: 'Settings that are used for the frontend applications to store user preferences / metadata' + type: object + example: 'json object' + react_settings: + description: 'Dedicated settings object for the react web application' + type: object' + example: 'json object' + is_owner: + description: 'Determines whether the user owns this company' + type: boolean + example: true + is_admin: + description: 'Determines whether the user is the admin of this company' + type: boolean + example: true + is_locked: + description: 'Determines whether the users access to this company has been locked' + type: boolean + example: true + updated_at: + description: 'The last time the record was modified, format Unix Timestamp' type: integer - example: '1' - name: - description: 'The payment term length in string format' - type: string - example: 'NET 1' - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - archived_at: - description: Timestamp - type: number - format: integer - example: '134341234234' + example: '1231232312321' + deleted_at: + description: 'Timestamp when the user was archived, format Unix Timestamp' + type: integer + example: '12312312321' + account: + $ref: '#/components/schemas/Account' + company: + $ref: '#/components/schemas/Company' + user: + $ref: '#/components/schemas/User' + token: + $ref: '#/components/schemas/CompanyToken' type: object - Paymentable: + Document: properties: id: - description: 'The paymentable hashed id' + description: 'The document hashed id' type: string example: AS3df3A - invoice_id: - description: 'The invoice hashed id' - type: string - example: AS3df3A - credit_id: - description: 'The credit hashed id' - type: string - example: AS3df3A - refunded: - description: 'The amount that has been refunded for this payment' - type: number - format: float - example: '10.00' - amount: - description: 'The amount that has been applied to the payment' - type: number - format: float - example: '10.00' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - created_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - type: object - Product: - properties: - id: - description: 'The product hashed id' - type: string - example: Opnel5aKBz - type: object - Project: - properties: - id: - description: 'The project hashed id' - type: string - example: Opnel5aKBz - name: - description: 'The project name' - type: string - example: 'New Project' - type: object - PurchaseOrder: - properties: - id: - description: 'The purchase order hashed id' - type: string - example: Opnel5aKBz - type: object - Quote: - properties: - id: - description: 'The quote hashed id' - type: string - example: Opnel5aKBz user_id: description: 'The user hashed id' type: string @@ -15692,209 +16177,103 @@ components: description: 'The assigned user hashed id' type: string example: '' - company_id: - description: 'The company hashed id' + project_id: + description: 'The project associated with this document' type: string example: '' - client_id: - description: 'The client hashed id' + vendor_id: + description: 'The vendor associated with this documents' type: string example: '' - status_id: - description: 'The status of the quote' + name: + description: 'The document name' type: string - example: '' - number: - description: 'The quote number - is a unique alpha numeric number per quote per company' + example: Beauty + url: + description: 'The document url' type: string - example: QUOTE_101 - po_number: - description: 'The purchase order number associated with this quote' + example: Beauty + preview: + description: 'The document preview url' type: string - example: PO-1234 - terms: - description: 'The quote terms' + example: Beauty + type: + description: 'The document type' type: string - example: 'These are some quote terms. Valid for 14 days.' - public_notes: - description: 'Public notes for the quote' + example: Beauty + disk: + description: 'The document disk' type: string - example: 'These are public notes which the client may see' - private_notes: - description: 'Private notes for the quote' + example: Beauty + hash: + description: 'The document hashed' type: string - example: 'These are private notes, not to be disclosed to the client' - footer: - description: 'Footer text of quote' - type: string - example: 'The text goes in the footer of the quote' - custom_value1: - description: 'Custom value field' - type: string - example: 'A custom value' - custom_value2: - description: 'Custom value field' - type: string - example: 'A custom value' - custom_value3: - description: 'Custom value field' - type: string - example: 'A custom value' - custom_value4: - description: 'Custom value field' - type: string - example: 'A custom value' - tax_name1: - description: 'The tax name' - type: string - example: GST - tax_name2: - description: 'The tax name' - type: string - example: VAT - tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - total_taxes: - description: 'The total taxes for the quote' - type: number - format: float - example: '10.00' - line_items: - description: 'An array of line items of the quote' - type: object - example: '' - amount: - description: 'The total amount of the quote' - type: number - format: float - example: '10.00' - balance: - description: 'The balance due of the quote' - type: number - format: float - example: '10.00' - paid_to_date: - description: 'The amount that has been paid to date on the quote' - type: number - format: float - example: '10.00' - discount: - description: 'The quote discount' - type: number - format: float - example: '10.00' - partial: - description: 'The partial/deposit amount' - type: number - format: float - example: '10.00' - is_amount_discount: - description: 'Boolean flag determining if the quote is an amount or percentage' - type: boolean - example: true + example: Beauty is_deleted: - description: 'Boolean flag determining if the quote has been deleted' + description: 'Flag to determine if the document is deleted' type: boolean example: true - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' + is_default: + description: 'Flag to determine if the document is a default doc' type: boolean example: true - date: - description: 'The Quote Date' - type: string - format: date - example: '1994-07-30' - last_sent_date: - description: 'The last date the quote was sent out' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The Next date for a reminder to be sent' - type: string - format: date - example: '1994-07-30' - partial_due_date: - description: 'The date when the partial/deposit is due' - type: string - format: date - example: '1994-07-30' - due_date: - description: 'The date the quote is valid until' - type: string - format: date - example: '1994-07-30' - settings: - $ref: '#/components/schemas/CompanySettings' - last_viewed: + created_at: description: Timestamp type: number format: integer - example: '1434342123' + example: '134341234234' updated_at: description: Timestamp type: number format: integer - example: '1434342123' - archived_at: + example: '134341234234' + deleted_at: description: Timestamp type: number format: integer - example: '1434342123' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge_tax1: - description: 'Toggles charging taxes on custom surcharge amounts' + example: '134341234234' + type: object + Design: + properties: + id: + description: 'The design hashed id' + type: string + example: AS3df3A + name: + description: 'The design name' + type: string + example: Beauty + design: + description: 'The design HTML' + type: string + example: '' + is_custom: + description: 'Flag to determine if the design is a custom user design' type: boolean example: true - custom_surcharge_tax2: - description: 'Toggles charging taxes on custom surcharge amounts' + is_active: + description: 'Flag to determine if the design is available for use' type: boolean example: true - custom_surcharge_tax3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax4: - description: 'Toggles charging taxes on custom surcharge amounts' + is_deleted: + description: 'Flag to determine if the design is deleted' type: boolean example: true + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + deleted_at: + description: Timestamp + type: number + format: integer + example: '134341234234' type: object RecurringExpense: properties: @@ -16067,232 +16446,6 @@ components: format: integer example: '1434342123' type: object - RecurringInvoice: - properties: - id: - description: 'The hashed id of the recurring invoice' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: Opnel5aKBz - company_id: - description: 'The company hashed id' - type: string - example: Opnel5aKBz - client_id: - description: 'The client hashed id' - type: string - example: Opnel5aKBz - status_id: - description: 'The invoice status variable' - type: string - example: '4' - frequency_id: - description: 'The recurring invoice frequency' - type: number - example: '4' - remaining_cycles: - description: 'The number of invoices left to be generated' - type: number - example: '4' - number: - description: 'The recurringinvoice number - is a unique alpha numeric number per invoice per company' - type: string - example: INV_101 - po_number: - description: 'The purchase order associated with this recurring invoice' - type: string - example: PO-1234 - terms: - description: 'The invoice terms' - type: string - example: 'These are invoice terms' - public_notes: - description: 'The public notes of the invoice' - type: string - example: 'These are some public notes' - private_notes: - description: 'The private notes of the invoice' - type: string - example: 'These are some private notes' - footer: - description: 'The invoice footer notes' - type: string - example: '' - custom_value1: - description: 'A custom field value' - type: string - example: '2022-10-01' - custom_value2: - description: 'A custom field value' - type: string - example: 'Something custom' - custom_value3: - description: 'A custom field value' - type: string - example: '' - custom_value4: - description: 'A custom field value' - type: string - example: '' - tax_name1: - description: 'The tax name' - type: string - example: '' - tax_name2: - description: 'The tax name' - type: string - example: '' - tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - total_taxes: - description: 'The total taxes for the invoice' - type: number - format: float - example: '10.00' - line_items: - description: 'An array of objects which define the line items of the invoice' - type: object - example: '' - amount: - description: 'The invoice amount' - type: number - format: float - example: '10.00' - balance: - description: 'The invoice balance' - type: number - format: float - example: '10.00' - paid_to_date: - description: 'The amount paid on the invoice to date' - type: number - format: float - example: '10.00' - discount: - description: 'The invoice discount, can be an amount or a percentage' - type: number - format: float - example: '10.00' - partial: - description: 'The deposit/partial amount' - type: number - format: float - example: '10.00' - is_amount_discount: - description: 'Flag determining if the discount is an amount or a percentage' - type: boolean - example: true - is_deleted: - description: 'Defines if the invoice has been deleted' - type: boolean - example: true - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' - type: boolean - example: true - date: - description: 'The Invoice Date' - type: string - format: date - example: '1994-07-30' - last_sent_date: - description: 'The last date the invoice was sent out' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The Next date for a reminder to be sent' - type: string - format: date - example: '1994-07-30' - partial_due_date: - description: 'The due date for the deposit/partial amount' - type: string - format: date - example: '1994-07-30' - due_date: - description: 'The due date of the invoice' - type: string - format: date - example: '1994-07-30' - settings: - $ref: '#/components/schemas/CompanySettings' - last_viewed: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge_tax1: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax2: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - type: object RecurringQuote: properties: id: @@ -16519,144 +16672,184 @@ components: type: boolean example: true type: object - SystemLog: + BTRules: + properties: + data_key: + description: 'The key to search' + type: string + example: 'description,amount' + operator: + description: 'The operator flag of the search' + type: string + example: '>' + value: + description: 'The value to search for' + type: string + example: bob + type: object + Expense: properties: id: - description: 'The account hashed id' + description: 'The expense hashed id' type: string - example: AS3df3A + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: '' + assigned_user_id: + description: 'The assigned user hashed id' + type: string + example: '' company_id: description: 'The company hashed id' type: string - example: AS3df3A - user_id: - description: 'The user_id hashed id' - type: string - example: AS3df3A + example: '' client_id: - description: 'The client_id hashed id' + description: 'The client hashed id' type: string - example: AS3df3A - event_id: - description: 'The Log Type ID' - type: integer - example: 1 - category_id: - description: 'The Category Type ID' - type: integer - example: 1 - type_id: - description: 'The Type Type ID' - type: integer - example: 1 - log: - description: 'The json object of the error' - type: object - example: '{''key'':''value''}' + example: '' + invoice_id: + description: 'The related invoice hashed id' + type: string + example: '' + bank_id: + description: 'The bank id related to this expense' + type: string + example: '' + invoice_currency_id: + description: 'The currency id of the related invoice' + type: string + example: '' + expense_currency_id: + description: 'The currency id of the expense' + type: string + example: '' + invoice_category_id: + description: 'The invoice category id' + type: string + example: '' + payment_type_id: + description: 'The payment type id' + type: string + example: '' + recurring_expense_id: + description: 'The related recurring expense this expense was created from' + type: string + example: '' + private_notes: + description: 'The private notes of the expense' + type: string + example: '' + public_notes: + description: 'The public notes of the expense' + type: string + example: '' + transaction_reference: + description: 'The transaction references of the expense' + type: string + example: '' + transcation_id: + description: 'The transaction id of the expense' + type: string + example: '' + custom_value1: + description: 'A custom value' + type: string + example: '' + custom_value2: + description: 'A custom value' + type: string + example: '' + custom_value3: + description: 'A custom value' + type: string + example: '' + custom_value4: + description: 'A custom value' + type: string + example: '' + tax_name1: + description: 'Tax name' + type: string + example: '' + tax_name2: + description: 'Tax name' + type: string + example: '' + tax_rate1: + description: 'Tax rate' + type: number + format: float + example: '10.00' + tax_rate2: + description: 'Tax rate' + type: number + format: float + example: '10.00' + tax_name3: + description: 'Tax name' + type: string + example: '' + tax_rate3: + description: 'Tax rate' + type: number + format: float + example: '10.00' + amount: + description: 'The total expense amont' + type: number + format: float + example: '10.00' + foreign_amount: + description: 'The total foreign amount of the expense' + type: number + format: float + example: '10.00' + exchange_rate: + description: 'The exchange rate at the time of the expense' + type: number + format: float + example: '0.80' + date: + description: 'The expense date formate Y-m-d' + type: string + example: '2022-12-01' + payment_date: + description: 'The date of payment for the expense, format Y-m-d' + type: string + example: '' + should_be_invoiced: + description: 'Flag whether the expense should be invoiced' + type: boolean + example: true + is_deleted: + description: 'Boolean determining whether the expense has been deleted' + type: boolean + example: true + invoice_documents: + description: 'Passing the expense documents over to the invoice' + type: boolean + example: true updated_at: description: Timestamp - type: string - example: '2' - created_at: + type: number + format: integer + example: '1434342123' + archived_at: description: Timestamp - type: string - example: '2' + type: number + format: integer + example: '1434342123' type: object - TaskSchedulerSchema: - properties: - paused: - description: 'The scheduler paused state' - type: boolean - example: 'false' - repeat_every: - description: 'Accepted values (DAY,WEEK,MONTH,3MONTHS,YEAR)' - type: string - example: DAY - start_from: - description: 'Timestamp when we should start the scheduler, default is today' - type: integer - example: '1652898504' - job: - description: 'Job, we can find list of available jobs in Scheduler model' - type: string - example: create_credit_report - date_range: - description: 'The string representation of the date range of data to be returned' - type: string - example: last7 - date_key: - description: 'The date column to search between.' - type: string - example: created_at - start_date: - description: 'The start date to search between' - type: string - example: '2022-10-31' - end_date: - description: 'The end date to search between' - type: string - example: '2022-10-31' - report_keys: - type: array - items: - description: 'Array of Keys to export' - type: string - example: '[''name'',''date'']' - type: object - UpdateTaskSchedulerSchema: - properties: - paused: - description: 'The scheduler paused state' - type: boolean - example: 'false' - repeat_every: - description: 'Accepted values (DAY,WEEK,MONTH,3MONTHS,YEAR)' - type: string - example: DAY - start_from: - description: 'Timestamp when we should start the scheduler, default is today' - type: integer - example: '1652898504' - job: - description: 'Job, we can find list of available jobs in Scheduler model' - type: string - example: create_credit_report - date_range: - description: 'The string representation of the date range of data to be returned' - type: string - example: last7 - date_key: - description: 'The date column to search between.' - type: string - example: created_at - start_date: - description: 'The start date to search between' - type: string - example: '2022-10-31' - end_date: - description: 'The end date to search between' - type: string - example: '2022-10-31' - type: object - UpdateJobForASchedulerSchema: - properties: - job: - description: 'Set action name, action names can be found in Scheduler Model' - type: string - example: create_client_report - type: object - Task: + ClientContact: properties: id: - description: 'The hashed id of the task' + description: 'The hashed if of the contact' type: string example: Opnel5aKBz user_id: - description: 'The hashed id of the user who created the task' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The assigned user of the task' + description: 'The hashed id of the user who created the contact' type: string example: Opnel5aKBz company_id: @@ -16664,210 +16857,367 @@ components: type: string example: Opnel5aKBz client_id: - description: 'The hashed if of the client' - type: string - example: Opnel5aKBz - invoice_id: - description: 'The hashed id of the invoice associated with the task' - type: string - example: Opnel5aKBz - project_id: - description: 'The hashed id of the project associated with the task' - type: string - example: Opnel5aKBz - number: - description: 'The number of the task' - type: string - example: TASK-123 - time_log: - description: 'An array of unix time stamps defining the start and end times of the task' - type: string - example: '[[1,2],[3,4]]' - is_running: - description: 'Determines if the task is still running' - type: boolean - example: true - is_deleted: - description: 'Boolean flag determining if the task has been deleted' - type: boolean - example: true - task_status_id: - description: 'The hashed id of the task status' - type: string - example: Opnel5aKBz - description: - description: 'The task description' - type: string - example: 'A wonder task to work on' - duration: - description: 'The task duration' - type: integer - example: '' - task_status_order: - description: 'The order of the task' - type: integer - example: '4' - custom_value1: - description: 'A custom value' - type: string - example: '2022-10-10' - custom_value2: - description: 'A custom value' - type: string - example: $1100 - custom_value3: - description: 'A custom value' - type: string - example: 'I need help' - custom_value4: - description: 'A custom value' - type: string - example: INV-3343 - created_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - type: object - TaskStatus: - properties: - name: - description: 'The task status name' - type: string - example: Backlog - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - is_deleted: - description: 'A boolean flag determining if the task status has been deleted' - type: boolean - example: true - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - archived_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object - TaxRate: - properties: - id: - description: 'Thie hashed id of the tax' - type: string - example: Opnel5aKBz - name: - description: 'The tax name' - type: string - example: GST - rate: - description: 'The tax rate' - type: number - example: '10' - is_deleted: - description: 'Boolean flag determining if the tax has been deleted' - type: boolean - example: true - type: object - Template: - properties: - html: - description: 'The template HTML' - type: string - example: '' - type: object - User: - properties: - id: - description: 'The hashed id of the user' + description: 'The hashed id of the client' type: string example: Opnel5aKBz first_name: - description: 'The first name of the user' + description: 'The first name of the contact' type: string - example: Brad + example: John last_name: - description: 'The last name of the user' + description: 'The last name of the contact' type: string - example: Pitt - email: - description: 'The users email address' - type: string - example: brad@pitt.com + example: Doe phone: - description: 'The users phone number' + description: 'The phone number of the contact' type: string - example: 555-1233-23232 - signature: - description: 'The users sign off signature' + example: 555-152-4524 + custom_value1: + description: 'A Custom field value' type: string - example: 'Have a nice day!' - avatar: - description: 'The users avatar' + example: '' + custom_value2: + description: 'A Custom field value' type: string - example: 'https://url.to.your/avatar.png' + example: '' + custom_value3: + description: 'A Custom field value' + type: string + example: '' + custom_value4: + description: 'A Custom field value' + type: string + example: '' + email: + description: 'The email of the contact' + type: string + example: '' accepted_terms_version: - description: 'The version of the invoice ninja terms that has been accepted by the user' + description: 'The terms of service which the contact has accpeted' type: string - example: 1.0.1 - oauth_user_id: - description: 'The provider id of the oauth entity' + example: 'A long set of ToS' + password: + description: 'The hashed password of the contact' type: string - example: jkhasdf789as6f675sdf768sdfs - oauth_provider_id: - description: 'The oauth entity id' + example: '*****' + confirmation-code: + description: 'The confirmation code used to authenticate the contacts email address' type: string - example: google + example: 333-sdjkh34gbasd + token: + description: 'A uuid based token.' + type: string + example: 333-sdjkh34gbasd + is_primary: + description: 'Defines is this contact is the primary contact for the client' + type: boolean + example: true + confirmed: + description: 'Boolean value confirms the user has confirmed their account.' + type: boolean + example: true + is_locked: + description: 'Boolean value defines if the contact has been locked out.' + type: boolean + example: true + send_email: + description: 'Boolean value determines is this contact should receive emails' + type: boolean + example: true + failed_logins: + description: 'The number of failed logins the contact has had' + type: number + format: integer + example: '3' + email_verified_at: + description: 'The date which the contact confirmed their email' + type: number + format: integer + example: '134341234234' + last_login: + description: Timestamp + type: number + format: integer + example: '134341234234' + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + deleted_at: + description: Timestamp + type: number + format: integer + example: '134341234234' type: object - AuthenticationError: - type: object + ClientGatewayToken: properties: - message: - description: 'These credentials do not match our records / Invalid Token' + id: + description: 'The hashed id of the client gateway token' type: string - example: 'These credentials do not match our records / Invalid Token' - ValidationError: - properties: - message: - description: 'The error message' + example: Opnel5aKBz + company_id: + description: 'The hashed id of the company' type: string - example: 'The given data was invalid.' - errors: - properties: - value: - type: array - items: - type: string - type: object + example: '2' + client_id: + description: 'The hashed_id of the client' + type: string + example: '2' + token: + description: 'The payment token' + type: string + example: '2' + routing_number: + description: 'THe bank account routing number' + type: string + example: '2' + company_gateway_id: + description: 'The hashed id of the company gateway' + type: string + example: '2' + is_default: + description: 'Flag determining if the token is the default payment method' + type: boolean + example: 'true' type: object - AuthorizationError: + Quote: properties: - message: - description: 'Insufficient permissions for this resource.' + id: + description: 'The unique hashed identifier for the quote' type: string - example: 'Insufficient permissions for this resource.' - errors: - properties: - value: - type: array - items: - type: string + example: Opnel5aKBz + user_id: + description: 'The unique hashed identifier for the user who created the quote' + type: string + example: '' + assigned_user_id: + description: 'The unique hashed identifier for the user assigned to the quote' + type: string + example: '' + company_id: + description: 'The unique hashed identifier for the company associated with the quote' + type: string + example: '' + client_id: + description: 'The unique hashed identifier for the client associated with the quote' + type: string + example: '' + status_id: + description: 'The status of the quote represented by a unique identifier' + type: string + example: '' + number: + description: 'The unique alpha-numeric quote number for the quote per company' + type: string + example: QUOTE_101 + po_number: + description: 'The purchase order number associated with the quote' + type: string + example: PO-1234 + terms: + description: 'The terms and conditions for the quote' + type: string + example: 'These are some quote terms. Valid for 14 days.' + public_notes: + description: 'Publicly visible notes associated with the quote' + type: string + example: 'These are public notes which the client may see' + private_notes: + description: 'Privately visible notes associated with the quote, not disclosed to the client' + type: string + example: 'These are private notes, not to be disclosed to the client' + footer: + description: 'The footer text of the quote' + type: string + example: 'The text goes in the footer of the quote' + custom_value1: + description: 'First custom value field for additional information' + type: string + example: 'A custom value' + custom_value2: + description: 'Second custom value field for additional information' + type: string + example: 'A custom value' + custom_value3: + description: 'Third custom value field for additional information' + type: string + example: 'A custom value' + custom_value4: + description: 'Fourth custom value field for additional information' + type: string + example: 'A custom value' + tax_name1: + description: 'The name of the first tax applied to the quote' + type: string + example: GST + tax_name2: + description: 'The name of the second tax applied to the quote' + type: string + example: VAT + tax_rate1: + description: 'The rate of the first tax applied to the quote' + type: number + format: float + example: 10.00 + tax_rate2: + description: 'The rate of the second tax applied to the quote' + type: number + format: float + example: 10.00 + tax_name3: + description: 'The name of the third tax applied to the quote' + type: string + example: '' + tax_rate3: + description: 'The rate of the third tax applied to the quote' + type: number + format: float + example: 10.00 + total_taxes: + description: 'The total amount of taxes for the quote' + type: number + format: float + example: 10.00 + line_items: + description: 'An array of line items associated with the quote' type: object + example: '' + amount: + description: 'The total amount of the quote before taxes and discounts' + type: number + format: float + example: 10.00 + balance: + description: 'The balance due for the quote after accounting for payments' + type: number + format: float + example: 10.00 + paid_to_date: + description: 'The total amount paid on the quote so far' + type: number + format: float + example: 10.00 + discount: + description: 'The discount amount or percentage applied to the quote' + type: number + format: float + example: 10.00 + partial: + description: 'The partial or deposit amount for the quote' + type: number + format: float + example: 10.00 + is_amount_discount: + description: 'Boolean flag indicating if the discount is a fixed amount or a percentage' + type: boolean + example: true + is_deleted: + description: 'Boolean flag indicating if the quote has been deleted' + type: boolean + example: false + uses_inclusive_taxes: + description: 'Boolean flag indicating if the taxes used are inclusive or exclusive' + type: boolean + example: true + date: + description: 'The date the quote was created' + type: string + format: date + example: '1994-07-30' + last_sent_date: + description: 'The last date the quote was sent to the client' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The next scheduled date for sending a reminder for the quote' + type: string + format: date + example: '1994-07-30' + partial_due_date: + description: 'The due date for the partial or deposit amount' + type: string + format: date + example: '1994-07-30' + due_date: + description: 'The due date for the total amount of the quote' + type: string + format: date + example: '1994-07-30' + settings: + $ref: '#/components/schemas/CompanySettings' + last_viewed: + description: 'The timestamp of the last time the quote was viewed' + type: number + format: integer + example: 1434342123 + updated_at: + description: 'The timestamp of the last update to the quote' + type: number + format: integer + example: 1434342123 + archived_at: + description: 'The timestamp of when the quote was archived' + type: number + format: integer + example: 1434342123 + custom_surcharge1: + description: 'First custom surcharge amount for the quote' + type: number + format: float + example: 10.00 + custom_surcharge2: + description: 'Second custom surcharge amount for the quote' + type: number + format: float + example: 10.00 + custom_surcharge3: + description: 'Third custom surcharge amount for the quote' + type: number + format: float + example: 10.00 + custom_surcharge4: + description: 'Fourth custom surcharge amount for the quote' + type: number + format: float + example: 10.00 + custom_surcharge_tax1: + description: 'Boolean flag indicating if taxes are charged on the first custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Boolean flag indicating if taxes are charged on the second custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Boolean flag indicating if taxes are charged on the third custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Boolean flag indicating if taxes are charged on the fourth custom surcharge amount' + type: boolean + example: true + type: object + CompanyToken: + properties: + name: + description: 'The token name' + type: string + example: 'Token Name' + token: + description: 'The token value' + type: string + example: AS3df3jUUH765fhfd9KJuidj3JShjA + is_system: + description: 'Determines whether the token is created by the system rather than a user' + type: boolean + example: 'true' type: object VendorContact: properties: @@ -16939,121 +17289,16 @@ components: format: integer example: '134341234234' type: object - Vendor: + PaymentTerm: properties: - id: - description: 'The hashed id of the vendor' - type: string - example: Opnel5aKBz - user_id: - description: 'The hashed id of the user who created the vendor' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The hashed id of the assigned user to this vendor' - type: string - example: Opnel5aKBz - company_id: - description: 'The hashed id of the company' - type: string - example: Opnel5aKBz - client_id: - description: 'The hashed id of the client' - type: string - example: Opnel5aKBz - contacts: - type: array - items: - $ref: '#/components/schemas/VendorContact' - name: - description: 'The vendor name' - type: string - example: 'Harry''s cafe de wheels' - website: - description: 'The website of the vendor' - type: string - example: www.harry.com - private_notes: - description: 'The private notes of the vendor' - type: string - example: 'Shhh, don''t tell the vendor' - industry_id: - description: 'The industry id of the vendor' - type: string + num_days: + description: 'The payment term length in days' + type: integer example: '1' - size_id: - description: ________ + name: + description: 'The payment term length in string format' type: string - example: '' - address1: - description: ________ - type: string - example: '' - address2: - description: ________ - type: string - example: '' - city: - description: ________ - type: string - example: '' - state: - description: ________ - type: string - example: '' - postal_code: - description: ________ - type: string - example: '' - phone: - description: 'The client phone number' - type: string - example: 555-3434-3434 - country_id: - description: ________ - type: string - example: '' - currency_id: - description: ________ - type: string - example: '4' - custom_value1: - description: ________ - type: string - example: '' - custom_value2: - description: ________ - type: string - example: '' - custom_value3: - description: ________ - type: string - example: '' - custom_value4: - description: ________ - type: string - example: '' - vat_number: - description: ________ - type: string - example: '' - id_number: - description: ________ - type: string - example: '' - number: - description: ________ - type: string - example: '' - is_deleted: - description: ________ - type: boolean - example: true - last_login: - description: Timestamp - type: number - format: integer - example: '134341234234' + example: 'NET 1' created_at: description: Timestamp type: number @@ -17064,237 +17309,11 @@ components: type: number format: integer example: '134341234234' - settings: - $ref: '#/components/schemas/CompanySettings' - type: object - Webhook: - properties: - id: - description: 'The subscription hashed id' - type: string - example: AS3df3A - event_id: - description: 'The subscription event id' - type: string - example: AS3df3A - target_url: - description: 'The api endpoint' - type: string - example: AS3df3A - format: - description: 'JSON or UBL' - type: string - example: JSON - type: object - Activity: - properties: - id: - description: 'The id field of the activity' - type: string - example: Opnel5aKBz - activity_type_id: - description: 'The activity type id' - type: string - example: Opnel5aKBz - client_id: - description: 'The client hashed id' - type: string - example: Opnel5aKBz - company_id: - description: 'The company hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: Opnel5aKBz - invoice_id: - description: 'The invoice hashed id' - type: string - example: Opnel5aKBz - payment_id: - description: 'The payment hashed id' - type: string - example: Opnel5aKBz - credit_id: - description: 'The credit hashed id' - type: string - example: Opnel5aKBz - updated_at: - description: 'Unixtimestamp the last time the record was updated' - type: integer - example: '343421434' - expense_id: - description: 'The expense hashed id' - type: string - example: Opnel5aKBz - is_system: - description: 'Defines is the activity was performed by the system' - type: boolean - example: true - contact_id: - description: 'The contact hashed id' - type: string - example: Opnel5aKBz - task_id: - description: 'The task hashed id' - type: string - example: Opnel5aKBz - notes: - description: 'Activity Notes' - type: string - example: Opnel5aKBz - token_id: - description: 'The hashed ID of the token who performed the action' - type: string - example: Opnel5aKBz - ip: - description: 'The IP Address of the user who performed the action' - type: string - example: 192.168.1.252 - user: - $ref: '#/components/schemas/User' - client: - $ref: '#/components/schemas/Client' - contact: - $ref: '#/components/schemas/ClientContact' - recurring_invoice: - $ref: '#/components/schemas/RecurringInvoice' - invoice: - $ref: '#/components/schemas/Invoice' - credit: - $ref: '#/components/schemas/Credit' - quote: - $ref: '#/components/schemas/Quote' - payment: - $ref: '#/components/schemas/Payment' - expense: - $ref: '#/components/schemas/Expense' - task: - $ref: '#/components/schemas/Task' - purchase_order: - $ref: '#/components/schemas/PurchaseOrder' - vendor: - $ref: '#/components/schemas/Vendor' - vendor_contact: - $ref: '#/components/schemas/VendorContact' - type: object - BankTransaction: - properties: - id: - description: 'The bank integration hashed id' - type: string - example: AS3df3A - company_id: - description: 'The company hashed id' - type: string - example: AS3df3A - user_id: - description: 'The user hashed id' - type: string - example: AS3df3A - transaction_id: - description: 'The id of the transaction rule' - type: integer - example: 343434 - amount: - description: 'The transaction amount' + archived_at: + description: Timestamp type: number - example: 10 - currency_id: - description: 'The currency ID of the currency' - type: string - example: '1' - account_type: - description: 'The account type' - type: string - example: creditCard - description: - description: 'The description of the transaction' - type: string - example: 'Potato purchases for kevin' - category_id: - description: 'The category id' - type: integer - example: 1 - category_type: - description: 'The category description' - type: string - example: Expenses - base_type: - description: 'Either CREDIT or DEBIT' - type: string - example: CREDIT - date: - description: 'The date of the transaction' - type: string - example: '2022-09-01' - bank_account_id: - description: 'The ID number of the bank account' - type: integer - example: '1' - type: object - BankIntegration: - properties: - id: - description: 'The bank integration hashed id' - type: string - example: AS3df3A - company_id: - description: 'The company hashed id' - type: string - example: AS3df3A - user_id: - description: 'The user hashed id' - type: string - example: AS3df3A - provider_bank_name: - description: 'The providers bank name' - type: string - example: 'Chase Bank' - bank_account_id: - description: 'The bank account id' - type: integer - example: '1233434' - bank_account_name: - description: 'The name of the account' - type: string - example: 'My Checking Acc' - bank_account_number: - description: 'The account number' - type: string - example: '111 234 2332' - bank_account_status: - description: 'The status of the bank account' - type: string - example: ACTIVE - bank_account_type: - description: 'The type of account' - type: string - example: CREDITCARD - balance: - description: 'The current bank balance if available' - type: number - example: '1000000' - currency: - description: 'iso_3166_3 code' - type: string - example: USD - type: object - BTRules: - properties: - data_key: - description: 'The key to search' - type: string - example: 'description,amount' - operator: - description: 'The operator flag of the search' - type: string - example: '>' - value: - description: 'The value to search for' - type: string - example: bob + format: integer + example: '134341234234' type: object Account: properties: diff --git a/openapi/components/schemas.yaml b/openapi/components/schemas.yaml index 575dea7f8a21..54ea8bb76f32 100644 --- a/openapi/components/schemas.yaml +++ b/openapi/components/schemas.yaml @@ -1,1277 +1,4 @@ schemas: - BankTransactionRule: - properties: - id: - description: 'The bank transaction rules hashed id' - type: string - example: AS3df3A - company_id: - description: 'The company hashed id' - type: string - example: AS3df3A - user_id: - description: 'The user hashed id' - type: string - example: AS3df3A - name: - description: 'The name of the transaction' - type: string - example: 'Rule 1' - rules: - description: 'A mapped collection of the sub rules for the BankTransactionRule' - type: array - items: - $ref: '#/components/schemas/BTRules' - auto_convert: - description: 'Flags whether the rule converts the transaction automatically' - type: boolean - example: true - matches_on_all: - description: 'Flags whether all subrules are required for the match' - type: boolean - example: true - applies_to: - description: 'Flags whether the rule applies to a CREDIT or DEBIT' - type: string - example: CREDIT - client_id: - description: 'The client hashed id' - type: string - example: AS3df3A - vendor_id: - description: 'The vendor hashed id' - type: string - example: AS3df3A - category_id: - description: 'The category hashed id' - type: string - example: AS3df3A - type: object - Subscription: - properties: - id: - description: ______ - type: string - example: Opnel5aKBz - user_id: - description: ______ - type: string - example: Opnel5aKBz - product_id: - description: ______ - type: string - example: Opnel5aKBz - company_id: - description: ______ - type: string - example: Opnel5aKBz - recurring_invoice_id: - description: ______ - type: string - example: Opnel5aKBz - is_recurring: - description: ______ - type: boolean - example: 'true' - frequency_id: - description: 'integer const representation of the frequency' - type: string - example: '1' - auto_bill: - description: 'enum setting' - type: string - example: always - promo_code: - description: ______ - type: string - example: PROMOCODE4U - promo_discount: - description: ______ - type: number - example: 10 - is_amount_discount: - description: ______ - type: boolean - example: 'true' - allow_cancellation: - description: ______ - type: boolean - example: 'true' - per_seat_enabled: - description: ______ - type: boolean - example: 'true' - currency_id: - description: ______ - type: integer - example: '1' - max_seats_limit: - description: ______ - type: integer - example: '100' - trial_enabled: - description: ______ - type: boolean - example: 'true' - trial_duration: - description: ______ - type: integer - example: '2' - allow_query_overrides: - description: ______ - type: boolean - example: 'true' - allow_plan_changes: - description: ______ - type: boolean - example: 'true' - refund_period: - description: ______ - type: integer - example: '2' - webhook_configuration: - description: ______ - type: string - example: '2' - is_deleted: - description: ______ - type: boolean - example: 'true' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object - BulkAction: - type: array - items: - type: integer - example: '[0,1,2,3,]' - ClientContact: - properties: - id: - description: 'The hashed if of the contact' - type: string - example: Opnel5aKBz - user_id: - description: 'The hashed id of the user who created the contact' - type: string - example: Opnel5aKBz - company_id: - description: 'The hashed id of the company' - type: string - example: Opnel5aKBz - client_id: - description: 'The hashed id of the client' - type: string - example: Opnel5aKBz - first_name: - description: 'The first name of the contact' - type: string - example: John - last_name: - description: 'The last name of the contact' - type: string - example: Doe - phone: - description: 'The phone number of the contact' - type: string - example: 555-152-4524 - custom_value1: - description: 'A Custom field value' - type: string - example: '' - custom_value2: - description: 'A Custom field value' - type: string - example: '' - custom_value3: - description: 'A Custom field value' - type: string - example: '' - custom_value4: - description: 'A Custom field value' - type: string - example: '' - email: - description: 'The email of the contact' - type: string - example: '' - accepted_terms_version: - description: 'The terms of service which the contact has accpeted' - type: string - example: 'A long set of ToS' - password: - description: 'The hashed password of the contact' - type: string - example: '*****' - confirmation-code: - description: 'The confirmation code used to authenticate the contacts email address' - type: string - example: 333-sdjkh34gbasd - token: - description: 'A uuid based token.' - type: string - example: 333-sdjkh34gbasd - is_primary: - description: 'Defines is this contact is the primary contact for the client' - type: boolean - example: true - confirmed: - description: 'Boolean value confirms the user has confirmed their account.' - type: boolean - example: true - is_locked: - description: 'Boolean value defines if the contact has been locked out.' - type: boolean - example: true - send_email: - description: 'Boolean value determines is this contact should receive emails' - type: boolean - example: true - failed_logins: - description: 'The number of failed logins the contact has had' - type: number - format: integer - example: '3' - email_verified_at: - description: 'The date which the contact confirmed their email' - type: number - format: integer - example: '134341234234' - last_login: - description: Timestamp - type: number - format: integer - example: '134341234234' - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - deleted_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object - ClientGatewayToken: - properties: - id: - description: 'The hashed id of the client gateway token' - type: string - example: Opnel5aKBz - company_id: - description: 'The hashed id of the company' - type: string - example: '2' - client_id: - description: 'The hashed_id of the client' - type: string - example: '2' - token: - description: 'The payment token' - type: string - example: '2' - routing_number: - description: 'THe bank account routing number' - type: string - example: '2' - company_gateway_id: - description: 'The hashed id of the company gateway' - type: string - example: '2' - is_default: - description: 'Flag determining if the token is the default payment method' - type: boolean - example: 'true' - type: object - Client: - properties: - id: - description: 'The hashed id of the client' - type: string - example: Opnel5aKBz - user_id: - description: 'The hashed id of the user' - type: string - example: '' - company_id: - description: 'The hashed id of the company' - type: string - example: '' - contacts: - type: array - items: - $ref: '#/components/schemas/ClientContact' - name: - description: 'The client name' - type: string - example: 'Jims housekeeping' - website: - description: 'The client website' - type: string - example: www.jims.com - private_notes: - description: 'Private notes on the client' - type: string - example: 'These are very private notes' - client_hash: - description: 'The client hash' - type: string - example: asdfkjhk342hjhbfdvmnfb1 - industry_id: - description: 'The industry id of the client' - type: number - example: '5' - size_id: - description: 'The size id of the client' - type: number - example: '2' - address1: - description: 'Address line 1' - type: string - example: '' - address2: - description: 'Address line 2' - type: string - example: '' - city: - description: City - type: string - example: 'Beverley Hills' - state: - description: State/Locality - type: string - example: Californnia - postal_code: - description: 'Zip / Postal code' - type: string - example: '90210' - phone: - description: 'The client phone number' - type: string - example: 555-3434-3434 - country_id: - description: 'The client country id' - type: number - format: integer - example: '1' - custom_value1: - description: 'A custom value' - type: string - example: 'Something custom' - custom_value2: - description: 'A custom value' - type: string - example: '2002-01-01' - custom_value3: - description: 'A custom value' - type: string - example: 'Something custom' - custom_value4: - description: 'A custom value' - type: string - example: 'Something custom' - vat_number: - description: 'The client VAT number' - type: string - example: VAT123 - id_number: - description: ' The client id number' - type: string - example: CLIENT_ID_NUMBER - number: - description: 'The client number - assigned by the system typically' - type: string - example: '' - shipping_address1: - description: 'The shipping address line 1' - type: string - example: '5 Wallaby Way' - shipping_address2: - description: 'The shipping address line 2' - type: string - example: 'Suite 5' - shipping_city: - description: 'The shipping city' - type: string - example: Perth - shipping_state: - description: 'The shipping state' - type: string - example: 'Western Australia' - shipping_postal_code: - description: 'The shipping postal code' - type: string - example: '6110' - shipping_country_id: - description: 'The shipping country id' - type: number - format: integer - example: '4' - is_deleted: - description: 'Boolean flagged determining if the client has been deleted' - type: boolean - example: true - balance: - description: 'The client balance' - type: number - format: float - example: '10.00' - paid_to_date: - description: 'The amount the client has paid to date.' - type: number - format: float - example: '10.00' - credit_balance: - description: 'An amount which is available to the client for future use.' - type: number - format: float - example: '10.00' - last_login: - description: Timestamp - type: number - format: integer - example: '134341234234' - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - settings: - $ref: '#/components/schemas/CompanySettings' - type: object - CompanyGateway: - properties: - id: - description: 'The hashed id of the company gateway' - type: string - example: Opnel5aKBz - company_id: - description: 'The company hashed id' - type: string - example: '2' - gateway_key: - description: 'The gateway key (hash)' - type: string - example: '2' - accepted_credit_cards: - description: 'Bitmask representation of cards' - type: integer - example: '32' - require_billing_address: - description: 'Determines if the the billing address is required prior to payment.' - type: boolean - example: true - require_shipping_address: - description: 'Determines if the the billing address is required prior to payment.' - type: boolean - example: true - config: - description: 'The configuration map for the gateway' - type: string - example: dfadsfdsafsafd - update_details: - description: 'Determines if the client details should be updated.' - type: boolean - example: true - fees_and_limits: - description: 'A mapped collection of the fees and limits for the configured gateway' - type: array - items: - $ref: '#/components/schemas/FeesAndLimits' - type: object - CompanyLedger: - properties: - entity_id: - description: 'This field will reference one of the following entity hashed ID payment_id, invoice_id or credit_id' - type: string - example: AS3df3A - notes: - description: 'The notes which reference this entry of the ledger' - type: string - example: 'Credit note for invoice #3212' - balance: - description: 'The client balance' - type: number - format: float - example: '10.00' - adjustment: - description: 'The amount the client balance is adjusted by' - type: number - format: float - example: '10.00' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - created_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - type: object - Company: - properties: - id: - description: 'The company hash id' - type: string - example: WJxbojagwO - size_id: - description: 'The company size ID' - type: string - example: '1' - industry_id: - description: 'The company industry ID' - type: string - example: '1' - slack_webhook_url: - description: 'The slack webhook notification URL' - type: string - example: 'https://slack.com/sh328sj' - google_analytics_key: - description: 'The google analytics key' - type: string - example: '1' - portal_mode: - description: 'Determines the client facing urls ie: subdomain,domain,iframe' - type: string - example: subdomain - subdomain: - description: 'Specifies the first part of the company domain ie acme in acme.domain.com' - type: string - example: aceme - portal_domain: - description: 'The fully qualified domain for client facing URLS' - type: string - example: 'https://subdomain.invoicing.co' - enabled_tax_rates: - description: 'Number of taxes rates used per entity' - type: integer - example: '1' - fill_products: - description: 'Toggles filling a product description based on product key' - type: boolean - example: true - convert_products: - description: ___________ - type: boolean - example: true - update_products: - description: 'Toggles updating a product description which description changes' - type: boolean - example: true - show_product_details: - description: 'Toggles showing a product description which description changes' - type: boolean - example: true - custom_fields: - description: 'Custom fields map' - type: object - enable_product_cost: - description: 'Show/Hide the product cost field in the UI' - type: boolean - example: true - enable_product_quantity: - description: 'Show/hide the product quantity field (used in the UI to show the default quantity)' - type: boolean - example: true - default_quantity: - description: 'Enable/Disable whether to use a default quantity' - type: boolean - example: true - custom_surcharge_taxes1: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_taxes2: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_taxes3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_taxes4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - logo: - description: 'The company logo - binary' - type: object - example: logo.png - settings: - $ref: '#/components/schemas/CompanySettings' - type: object - CompanySettings: - properties: - timezone_id: - description: 'The timezone id' - type: string - example: '15' - date_format_id: - description: 'The date format id' - type: string - example: '15' - military_time: - description: 'Toggles 12/24 hour time' - type: boolean - example: true - language_id: - description: 'The language id' - type: string - example: '1' - show_currency_code: - description: 'Toggles whether the currency symbol or code is shown' - type: boolean - example: true - currency_id: - description: 'The default currency id' - type: string - example: true - payment_terms: - description: '-1 sets no payment term, 0 sets payment due immediately, positive integers indicates payment terms in days' - type: integer - example: '1' - company_gateway_ids: - description: 'A commad separate list of available gateways' - type: string - example: '1,2,3,4' - custom_value1: - description: 'A Custom Label' - type: string - example: 'Custom Label' - custom_value2: - description: 'A Custom Label' - type: string - example: 'Custom Label' - custom_value3: - description: 'A Custom Label' - type: string - example: 'Custom Label' - custom_value4: - description: 'A Custom Label' - type: string - example: 'Custom Label' - default_task_rate: - description: 'The default task rate' - type: number - format: float - example: '10.00' - send_reminders: - description: 'Toggles whether reminders are sent' - type: boolean - example: true - enable_client_portal_tasks: - description: 'Show/hide the tasks panel in the client portal' - type: boolean - example: true - email_style: - description: 'options include plain,light,dark,custom' - type: string - example: light - reply_to_email: - description: 'The reply to email address' - type: string - example: email@gmail.com - bcc_email: - description: 'A comma separate list of BCC emails' - type: string - example: 'email@gmail.com, contact@gmail.com' - pdf_email_attachment: - description: 'Toggles whether to attach PDF as attachment' - type: boolean - example: true - ubl_email_attachment: - description: 'Toggles whether to attach UBL as attachment' - type: boolean - example: true - email_style_custom: - description: 'The custom template' - type: string - example: '' - counter_number_applied: - description: 'enum when the invoice number counter is set, ie when_saved, when_sent, when_paid' - type: string - example: when_sent - quote_number_applied: - description: 'enum when the quote number counter is set, ie when_saved, when_sent' - type: string - example: when_sent - custom_message_dashboard: - description: 'A custom message which is displayed on the dashboard' - type: string - example: 'Please pay invoices immediately' - custom_message_unpaid_invoice: - description: 'A custom message which is displayed in the client portal when a client is viewing a unpaid invoice.' - type: string - example: 'Please pay invoices immediately' - custom_message_paid_invoice: - description: 'A custom message which is displayed in the client portal when a client is viewing a paid invoice.' - type: string - example: 'Thanks for paying this invoice!' - custom_message_unapproved_quote: - description: 'A custom message which is displayed in the client portal when a client is viewing a unapproved quote.' - type: string - example: 'Please approve quote' - lock_invoices: - description: 'Toggles whether invoices are locked once sent and cannot be modified further' - type: boolean - example: true - auto_archive_invoice: - description: 'Toggles whether a invoice is archived immediately following payment' - type: boolean - example: true - auto_archive_quote: - description: 'Toggles whether a quote is archived after being converted to a invoice' - type: boolean - example: true - auto_convert_quote: - description: 'Toggles whether a quote is converted to a invoice when approved' - type: boolean - example: true - inclusive_taxes: - description: 'Boolean flag determining whether inclusive or exclusive taxes are used' - type: boolean - example: true - translations: - description: 'JSON payload of customized translations' - type: object - example: '' - task_number_pattern: - description: 'Allows customisation of the task number pattern' - type: string - example: '{$year}-{$counter}' - task_number_counter: - description: 'The incrementing counter for tasks' - type: integer - example: '1' - reminder_send_time: - description: 'Time from UTC +0 when the email will be sent to the client' - type: integer - example: '32400' - expense_number_pattern: - description: 'Allows customisation of the expense number pattern' - type: string - example: '{$year}-{$counter}' - expense_number_counter: - description: 'The incrementing counter for expenses' - type: integer - example: '1' - vendor_number_pattern: - description: 'Allows customisation of the vendor number pattern' - type: string - example: '{$year}-{$counter}' - vendor_number_counter: - description: 'The incrementing counter for vendors' - type: integer - example: '1' - ticket_number_pattern: - description: 'Allows customisation of the ticket number pattern' - type: string - example: '{$year}-{$counter}' - ticket_number_counter: - description: 'The incrementing counter for tickets' - type: integer - example: '1' - payment_number_pattern: - description: 'Allows customisation of the payment number pattern' - type: string - example: '{$year}-{$counter}' - payment_number_counter: - description: 'The incrementing counter for payments' - type: integer - example: '1' - invoice_number_pattern: - description: 'Allows customisation of the invoice number pattern' - type: string - example: '{$year}-{$counter}' - invoice_number_counter: - description: 'The incrementing counter for invoices' - type: integer - example: '1' - quote_number_pattern: - description: 'Allows customisation of the quote number pattern' - type: string - example: '{$year}-{$counter}' - quote_number_counter: - description: 'The incrementing counter for quotes' - type: integer - example: '1' - client_number_pattern: - description: 'Allows customisation of the client number pattern' - type: string - example: '{$year}-{$counter}' - client_number_counter: - description: 'The incrementing counter for clients' - type: integer - example: '1' - credit_number_pattern: - description: 'Allows customisation of the credit number pattern' - type: string - example: '{$year}-{$counter}' - credit_number_counter: - description: 'The incrementing counter for credits' - type: integer - example: '1' - recurring_invoice_number_prefix: - description: 'This string is prepended to the recurring invoice number' - type: string - example: R - reset_counter_frequency_id: - description: 'CONSTANT which is used to apply the frequency which the counters are reset' - type: integer - example: '1' - reset_counter_date: - description: 'The explicit date which is used to reset counters' - type: string - example: '2019-01-01' - counter_padding: - description: 'Pads the counter with leading zeros' - type: integer - example: '1' - shared_invoice_quote_counter: - description: 'Flags whether to share the counter for invoices and quotes' - type: boolean - example: true - update_products: - description: 'Determines if client fields are updated from third party APIs' - type: boolean - example: true - convert_products: - description: '' - type: boolean - example: true - fill_products: - description: 'Automatically fill products based on product_key' - type: boolean - example: true - invoice_terms: - description: 'The default invoice terms' - type: string - example: 'Invoice Terms are...' - quote_terms: - description: 'The default quote terms' - type: string - example: 'Quote Terms are...' - invoice_taxes: - description: 'Taxes can be applied to the invoice' - type: number - example: '1' - invoice_design_id: - description: 'The default design id (invoice, quote etc)' - type: string - example: '1' - quote_design_id: - description: 'The default design id (invoice, quote etc)' - type: string - example: '1' - invoice_footer: - description: 'The default invoice footer' - type: string - example: '1' - invoice_labels: - description: 'JSON string of invoice labels' - type: string - example: '1' - tax_rate1: - description: 'The tax rate (float)' - type: number - example: '10' - tax_name1: - description: 'The tax name' - type: string - example: GST - tax_rate2: - description: 'The tax rate (float)' - type: number - example: '10' - tax_name2: - description: 'The tax name' - type: string - example: GST - tax_rate3: - description: 'The tax rate (float)' - type: number - example: '10' - tax_name3: - description: 'The tax name' - type: string - example: GST - payment_type_id: - description: 'The default payment type id' - type: string - example: '1' - custom_fields: - description: 'JSON string of custom fields' - type: string - example: '{}' - email_footer: - description: 'The default email footer' - type: string - example: 'A default email footer' - email_sending_method: - description: 'The email driver to use to send email, options include default, gmail' - type: string - example: default - gmail_sending_user_id: - description: 'The hashed_id of the user account to send email from' - type: string - example: F76sd34D - email_subject_invoice: - description: '' - type: string - example: 'Your Invoice Subject' - email_subject_quote: - description: '' - type: string - example: 'Your Quote Subject' - email_subject_payment: - description: '' - type: string - example: 'Your Payment Subject' - email_template_invoice: - description: 'The full template for invoice emails' - type: string - example: '' - email_template_quote: - description: 'The full template for quote emails' - type: string - example: '' - email_template_payment: - description: 'The full template for payment emails' - type: string - example: '' - email_subject_reminder1: - description: 'Email subject for Reminder' - type: string - example: '' - email_subject_reminder2: - description: 'Email subject for Reminder' - type: string - example: '' - email_subject_reminder3: - description: 'Email subject for Reminder' - type: string - example: '' - email_subject_reminder_endless: - description: 'Email subject for endless reminders' - type: string - example: '' - email_template_reminder1: - description: 'The full template for Reminder 1' - type: string - example: '' - email_template_reminder2: - description: 'The full template for Reminder 2' - type: string - example: '' - email_template_reminder3: - description: 'The full template for Reminder 3' - type: string - example: '' - email_template_reminder_endless: - description: 'The full template for enless reminders' - type: string - example: '' - enable_portal_password: - description: 'Toggles whether a password is required to log into the client portal' - type: boolean - example: true - show_accept_invoice_terms: - description: 'Toggles whether the terms dialogue is shown to the client' - type: boolean - example: true - show_accept_quote_terms: - description: 'Toggles whether the terms dialogue is shown to the client' - type: boolean - example: true - require_invoice_signature: - description: 'Toggles whether a invoice signature is required' - type: boolean - example: true - require_quote_signature: - description: 'Toggles whether a quote signature is required' - type: boolean - example: true - name: - description: 'The company name' - type: string - example: 'Acme Co' - company_logo: - description: 'The company logo file' - type: object - example: logo.png - website: - description: 'The company website URL' - type: string - example: www.acme.com - address1: - description: 'The company address line 1' - type: string - example: 'Suite 888' - address2: - description: 'The company address line 2' - type: string - example: '5 Jimbo Way' - city: - description: 'The company city' - type: string - example: Sydney - state: - description: 'The company state' - type: string - example: Florisa - postal_code: - description: 'The company zip/postal code' - type: string - example: '90210' - phone: - description: 'The company phone' - type: string - example: 555-213-3948 - email: - description: 'The company email' - type: string - example: joe@acme.co - country_id: - description: 'The country ID' - type: string - example: '1' - vat_number: - description: 'The company VAT/TAX ID number' - type: string - example: '32 120 377 720' - page_size: - description: 'The default page size' - type: string - example: A4 - font_size: - description: 'The font size' - type: number - example: '9' - primary_font: - description: 'The primary font' - type: string - example: roboto - secondary_font: - description: 'The secondary font' - type: string - example: roboto - hide_paid_to_date: - description: 'Flags whether to hide the paid to date field' - type: boolean - example: false - embed_documents: - description: 'Toggled whether to embed documents in the PDF' - type: boolean - example: false - all_pages_header: - description: 'The header for the PDF' - type: boolean - example: false - all_pages_footer: - description: 'The footer for the PDF' - type: boolean - example: false - document_email_attachment: - description: 'Toggles whether to attach documents in the email' - type: boolean - example: false - enable_client_portal_password: - description: 'Toggles password protection of the client portal' - type: boolean - example: false - enable_email_markup: - description: 'Toggles the use of markdown in emails' - type: boolean - example: false - enable_client_portal_dashboard: - description: 'Toggles whether the client dashboard is shown in the client portal' - type: boolean - example: false - enable_client_portal: - description: 'Toggles whether the entire client portal is displayed to the client, or only the context' - type: boolean - example: false - email_template_statement: - description: 'The body of the email for statements' - type: string - example: 'template matter' - email_subject_statement: - description: 'The subject of the email for statements' - type: string - example: 'subject matter' - signature_on_pdf: - description: 'Toggles whether the signature (if available) is displayed on the PDF' - type: boolean - example: false - quote_footer: - description: 'The default quote footer' - type: string - example: 'the quote footer' - email_subject_custom1: - description: 'Custom reminder template subject' - type: string - example: 'Custom Subject 1' - email_subject_custom2: - description: 'Custom reminder template subject' - type: string - example: 'Custom Subject 2' - email_subject_custom3: - description: 'Custom reminder template subject' - type: string - example: 'Custom Subject 3' - email_template_custom1: - description: 'Custom reminder template body' - type: string - example: '' - email_template_custom2: - description: 'Custom reminder template body' - type: string - example: '' - email_template_custom3: - description: 'Custom reminder template body' - type: string - example: '' - enable_reminder1: - description: 'Toggles whether this reminder is enabled' - type: boolean - example: false - enable_reminder2: - description: 'Toggles whether this reminder is enabled' - type: boolean - example: false - enable_reminder3: - description: 'Toggles whether this reminder is enabled' - type: boolean - example: false - num_days_reminder1: - description: 'The Reminder interval' - type: number - example: '9' - num_days_reminder2: - description: 'The Reminder interval' - type: number - example: '9' - num_days_reminder3: - description: 'The Reminder interval' - type: number - example: '9' - schedule_reminder1: - description: '(enum: after_invoice_date, before_due_date, after_due_date)' - type: string - example: after_invoice_date - schedule_reminder2: - description: '(enum: after_invoice_date, before_due_date, after_due_date)' - type: string - example: after_invoice_date - schedule_reminder3: - description: '(enum: after_invoice_date, before_due_date, after_due_date)' - type: string - example: after_invoice_date - late_fee_amount1: - description: 'The late fee amount for reminder 1' - type: number - example: 10 - late_fee_amount2: - description: 'The late fee amount for reminder 2' - type: number - example: 20 - late_fee_amount3: - description: 'The late fee amount for reminder 2' - type: number - example: 100 - endless_reminder_frequency_id: - description: 'The frequency id of the endless reminder' - type: string - example: '1' - client_online_payment_notification: - description: 'Determines if a client should receive the notification for a online payment' - type: boolean - example: false - client_manual_payment_notification: - description: 'Determines if a client should receive the notification for a manually entered payment' - type: boolean - example: false - type: object - CompanyToken: - properties: - name: - description: 'The token name' - type: string - example: 'Token Name' - token: - description: 'The token value' - type: string - example: AS3df3jUUH765fhfd9KJuidj3JShjA - is_system: - description: 'Determines whether the token is created by the system rather than a user' - type: boolean - example: 'true' - type: object - CompanyUser: - properties: - permissions: - description: 'The company user permissions' - type: string - example: '[create_invoice]' - settings: - description: 'Settings that are used for the frontend applications to store user preferences / metadata' - type: object - example: 'json object' - is_owner: - description: 'Determines whether the user owns this company' - type: boolean - example: true - is_admin: - description: 'Determines whether the user is the admin of this company' - type: boolean - example: true - is_locked: - description: 'Determines whether the users access to this company has been locked' - type: boolean - example: true - updated_at: - description: 'The last time the record was modified, format Unix Timestamp' - type: integer - example: '1231232312321' - deleted_at: - description: 'Timestamp when the user was archived, format Unix Timestamp' - type: integer - example: '12312312321' - account: - $ref: '#/components/schemas/Account' - company: - $ref: '#/components/schemas/Company' - user: - $ref: '#/components/schemas/User' - token: - $ref: '#/components/schemas/CompanyToken' - type: object CreditPaymentable: properties: credit_id: @@ -1283,713 +10,6 @@ type: string example: '2' type: object - Credit: - properties: - id: - description: 'The credit hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: '' - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: '' - company_id: - description: 'The company hashed id' - type: string - example: '' - client_id: - description: 'The client hashed id' - type: string - example: '' - status_id: - description: 'The status field id infors of the current status of the credit' - type: string - example: '' - invoice_id: - description: 'The linked invoice this credit is applied to' - type: string - example: '' - number: - description: 'The credit number - is a unique alpha numeric number per credit per company' - type: string - example: QUOTE_101 - po_number: - description: 'The purchase order number this credit refers to' - type: string - example: '' - terms: - description: 'The credit terms field' - type: string - example: '' - public_notes: - description: 'The public notes field of the credit' - type: string - example: '' - private_notes: - description: 'The private notes field of the credit' - type: string - example: '' - footer: - description: 'The credit footer text' - type: string - example: '' - custom_value1: - description: 'A Custom value' - type: string - example: '' - custom_value2: - description: 'A Custom value' - type: string - example: '' - custom_value3: - description: 'A Custom value' - type: string - example: '' - custom_value4: - description: 'A Custom value' - type: string - example: '' - tax_name1: - description: 'The tax name' - type: string - example: '' - tax_name2: - description: 'The tax rate' - type: string - example: '' - tax_rate1: - description: 'The tax name' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - total_taxes: - description: 'The total taxes for the credit' - type: number - format: float - example: '10.00' - line_items: - description: 'The line items array containing the line items of the credit' - type: object - example: '' - amount: - description: 'The total credit amount' - type: number - format: float - example: '10.00' - balance: - description: 'The credit balance' - type: number - format: float - example: '10.00' - paid_to_date: - description: _________ - type: number - format: float - example: '10.00' - discount: - description: _________ - type: number - format: float - example: '10.00' - partial: - description: _________ - type: number - format: float - example: '10.00' - is_amount_discount: - description: _________ - type: boolean - example: true - is_deleted: - description: _________ - type: boolean - example: true - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' - type: boolean - example: true - date: - description: 'The Credit Date' - type: string - format: date - example: '1994-07-30' - last_sent_date: - description: 'The last date the credit was sent out' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The Next date for a reminder to be sent' - type: string - format: date - example: '1994-07-30' - partial_due_date: - description: _________ - type: string - format: date - example: '1994-07-30' - due_date: - description: _________ - type: string - format: date - example: '1994-07-30' - settings: - $ref: '#/components/schemas/CompanySettings' - last_viewed: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge_tax1: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax2: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - type: object - Design: - properties: - id: - description: 'The design hashed id' - type: string - example: AS3df3A - name: - description: 'The design name' - type: string - example: Beauty - design: - description: 'The design HTML' - type: string - example: '' - is_custom: - description: 'Flag to determine if the design is a custom user design' - type: boolean - example: true - is_active: - description: 'Flag to determine if the design is available for use' - type: boolean - example: true - is_deleted: - description: 'Flag to determine if the design is deleted' - type: boolean - example: true - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - deleted_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object - Document: - properties: - id: - description: 'The document hashed id' - type: string - example: AS3df3A - user_id: - description: 'The user hashed id' - type: string - example: '' - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: '' - project_id: - description: 'The project associated with this document' - type: string - example: '' - vendor_id: - description: 'The vendor associated with this documents' - type: string - example: '' - name: - description: 'The document name' - type: string - example: Beauty - url: - description: 'The document url' - type: string - example: Beauty - preview: - description: 'The document preview url' - type: string - example: Beauty - type: - description: 'The document type' - type: string - example: Beauty - disk: - description: 'The document disk' - type: string - example: Beauty - hash: - description: 'The document hashed' - type: string - example: Beauty - is_deleted: - description: 'Flag to determine if the document is deleted' - type: boolean - example: true - is_default: - description: 'Flag to determine if the document is a default doc' - type: boolean - example: true - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - deleted_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object - Error: - properties: - message: - description: 'Something terrible went wrong' - type: string - example: 'Unexpected error' - code: - description: 'The HTTP error code, ie 5xx 4xx' - type: integer - example: '500' - type: object - ExpenseCategory: - properties: - id: - description: 'The expense hashed id' - type: string - example: Opnel5aKBz - name: - description: 'The expense category name' - type: string - example: Accounting - user_id: - description: 'The user hashed id' - type: string - example: XS987sD - is_deleted: - description: 'Flag determining whether the expense category has been deleted' - type: boolean - example: true - updated_at: - description: 'The updated at timestamp' - type: integer - example: '2' - created_at: - description: 'The created at timestamp' - type: integer - example: '2' - type: object - Expense: - properties: - id: - description: 'The expense hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: '' - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: '' - company_id: - description: 'The company hashed id' - type: string - example: '' - client_id: - description: 'The client hashed id' - type: string - example: '' - invoice_id: - description: 'The related invoice hashed id' - type: string - example: '' - bank_id: - description: 'The bank id related to this expense' - type: string - example: '' - invoice_currency_id: - description: 'The currency id of the related invoice' - type: string - example: '' - expense_currency_id: - description: 'The currency id of the expense' - type: string - example: '' - invoice_category_id: - description: 'The invoice category id' - type: string - example: '' - payment_type_id: - description: 'The payment type id' - type: string - example: '' - recurring_expense_id: - description: 'The related recurring expense this expense was created from' - type: string - example: '' - private_notes: - description: 'The private notes of the expense' - type: string - example: '' - public_notes: - description: 'The public notes of the expense' - type: string - example: '' - transaction_reference: - description: 'The transaction references of the expense' - type: string - example: '' - transcation_id: - description: 'The transaction id of the expense' - type: string - example: '' - custom_value1: - description: 'A custom value' - type: string - example: '' - custom_value2: - description: 'A custom value' - type: string - example: '' - custom_value3: - description: 'A custom value' - type: string - example: '' - custom_value4: - description: 'A custom value' - type: string - example: '' - tax_name1: - description: 'Tax name' - type: string - example: '' - tax_name2: - description: 'Tax name' - type: string - example: '' - tax_rate1: - description: 'Tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'Tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'Tax name' - type: string - example: '' - tax_rate3: - description: 'Tax rate' - type: number - format: float - example: '10.00' - amount: - description: 'The total expense amont' - type: number - format: float - example: '10.00' - foreign_amount: - description: 'The total foreign amount of the expense' - type: number - format: float - example: '10.00' - exchange_rate: - description: 'The exchange rate at the time of the expense' - type: number - format: float - example: '0.80' - date: - description: 'The expense date formate Y-m-d' - type: string - example: '2022-12-01' - payment_date: - description: 'The date of payment for the expense, format Y-m-d' - type: string - example: '' - should_be_invoiced: - description: 'Flag whether the expense should be invoiced' - type: boolean - example: true - is_deleted: - description: 'Boolean determining whether the expense has been deleted' - type: boolean - example: true - invoice_documents: - description: 'Passing the expense documents over to the invoice' - type: boolean - example: true - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - type: object - FeesAndLimits: - properties: - min_limit: - description: 'The minimum amount accepted for this gateway' - type: string - example: '2' - max_limit: - description: 'The maximum amount accepted for this gateway' - type: string - example: '2' - fee_amount: - description: 'The gateway fee amount' - type: number - format: float - example: '2.0' - fee_percent: - description: 'The gateway fee percentage' - type: number - format: float - example: '2.0' - fee_tax_name1: - description: 'Fee tax name' - type: string - example: GST - fee_tax_name2: - description: 'Fee tax name' - type: string - example: VAT - fee_tax_name3: - description: 'Fee tax name' - type: string - example: 'CA Sales Tax' - fee_tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.0' - fee_tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '17.5' - fee_tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '25.0' - fee_cap: - description: 'If set the fee amount will be no higher than this amount' - type: number - format: float - example: '2.0' - adjust_fee_percent: - description: 'Adjusts the fee to match the exact gateway fee.' - type: boolean - example: true - type: object - FillableInvoice: - properties: - assigned_user_id: - description: __________ - type: string - example: '' - client_id: - description: ________ - type: string - example: '' - number: - description: 'The invoice number - is a unique alpha numeric number per invoice per company' - type: string - example: INV_101 - po_number: - description: ________ - type: string - example: '' - terms: - description: ________ - type: string - example: '' - public_notes: - description: ________ - type: string - example: '' - private_notes: - description: ________ - type: string - example: '' - footer: - description: ________ - type: string - example: '' - custom_value1: - description: ________ - type: string - example: '' - custom_value2: - description: ________ - type: string - example: '' - custom_value3: - description: ________ - type: string - example: '' - custom_value4: - description: ________ - type: string - example: '' - tax_name1: - description: ________ - type: string - example: '' - tax_name2: - description: ________ - type: string - example: '' - tax_rate1: - description: _________ - type: number - example: '10.00' - tax_rate2: - description: _________ - type: number - example: '10.00' - tax_name3: - description: ________ - type: string - example: '' - tax_rate3: - description: _________ - type: number - example: '10.00' - line_items: - description: _________ - type: object - example: '' - discount: - description: _________ - type: number - example: '10.00' - partial: - description: _________ - type: number - example: '10.00' - is_amount_discount: - description: _________ - type: boolean - example: '1' - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' - type: boolean - example: '1' - date: - description: 'The Invoice Date' - type: string - example: '1994-07-30' - partial_due_date: - description: _________ - type: string - example: '1994-07-30' - due_date: - description: _________ - type: string - example: '1994-07-30' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - example: '10.00' - type: object GenericReportSchema: properties: date_range: @@ -2049,370 +69,9 @@ type: string example: '2' type: object - Invoice: - properties: - id: - description: 'The invoice hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: Opnel5aKBz - company_id: - description: 'The company hashed id' - type: string - example: Opnel5aKBz - client_id: - description: 'The client hashed id' - type: string - example: Opnel5aKBz - status_id: - description: 'The invoice status variable' - type: string - example: '4' - number: - description: 'The invoice number - is a unique alpha numeric number per invoice per company' - type: string - example: INV_101 - po_number: - description: 'The purchase order associated with this invoice' - type: string - example: PO-1234 - terms: - description: 'The invoice terms' - type: string - example: 'These are invoice terms' - public_notes: - description: 'The public notes of the invoice' - type: string - example: 'These are some public notes' - private_notes: - description: 'The private notes of the invoice' - type: string - example: 'These are some private notes' - footer: - description: 'The invoice footer notes' - type: string - example: '' - custom_value1: - description: 'A custom field value' - type: string - example: '2022-10-01' - custom_value2: - description: 'A custom field value' - type: string - example: 'Something custom' - custom_value3: - description: 'A custom field value' - type: string - example: '' - custom_value4: - description: 'A custom field value' - type: string - example: '' - tax_name1: - description: 'The tax name' - type: string - example: '' - tax_name2: - description: 'The tax name' - type: string - example: '' - tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - total_taxes: - description: 'The total taxes for the invoice' - type: number - format: float - example: '10.00' - line_items: - description: 'An array of objects which define the line items of the invoice' - type: object - example: '' - amount: - description: 'The invoice amount' - type: number - format: float - example: '10.00' - balance: - description: 'The invoice balance' - type: number - format: float - example: '10.00' - paid_to_date: - description: 'The amount paid on the invoice to date' - type: number - format: float - example: '10.00' - discount: - description: 'The invoice discount, can be an amount or a percentage' - type: number - format: float - example: '10.00' - partial: - description: 'The deposit/partial amount' - type: number - format: float - example: '10.00' - is_amount_discount: - description: 'Flag determining if the discount is an amount or a percentage' - type: boolean - example: true - is_deleted: - description: 'Defines if the invoice has been deleted' - type: boolean - example: true - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' - type: boolean - example: true - date: - description: 'The Invoice Date' - type: string - format: date - example: '1994-07-30' - last_sent_date: - description: 'The last date the invoice was sent out' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The Next date for a reminder to be sent' - type: string - format: date - example: '1994-07-30' - partial_due_date: - description: 'The due date for the deposit/partial amount' - type: string - format: date - example: '1994-07-30' - due_date: - description: 'The due date of the invoice' - type: string - format: date - example: '1994-07-30' - settings: - $ref: '#/components/schemas/CompanySettings' - last_viewed: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge_tax1: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax2: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - type: object - Payment: - properties: - id: - description: 'The payment hashed id' - type: string - example: Opnel5aKBz - client_id: - description: 'The client hashed id' - type: string - example: Opnel5aKBz - invitation_id: - description: 'The invitation hashed id' - type: string - example: Opnel5aKBz - client_contact_id: - description: 'The client contact hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: Opnel5aKBz - type_id: - description: 'The Payment Type ID' - type: string - example: '1' - date: - description: 'The Payment date' - type: string - example: 1-1-2014 - transaction_reference: - description: 'The transaction reference as defined by the payment gateway' - type: string - example: xcsSxcs124asd - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: Opnel5aKBz - private_notes: - description: 'The private notes of the payment' - type: string - example: 'The payment was refunded due to error' - is_manual: - description: 'Flags whether the payment was made manually or processed via a gateway' - type: boolean - example: true - is_deleted: - description: 'Defines if the payment has been deleted' - type: boolean - example: true - amount: - description: 'The amount of this payment' - type: number - example: 10 - refunded: - description: 'The refunded amount of this payment' - type: number - example: 10 - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - company_gateway_id: - description: 'The company gateway id' - type: string - example: '3' - paymentables: - $ref: '#/components/schemas/Paymentable' - invoices: - description: '' - type: array - items: - $ref: '#/components/schemas/InvoicePaymentable' - credits: - description: '' - type: array - items: - $ref: '#/components/schemas/CreditPaymentable' - type: object - PaymentTerm: - properties: - num_days: - description: 'The payment term length in days' - type: integer - example: '1' - name: - description: 'The payment term length in string format' - type: string - example: 'NET 1' - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - archived_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object - Paymentable: - properties: - id: - description: 'The paymentable hashed id' - type: string - example: AS3df3A - invoice_id: - description: 'The invoice hashed id' - type: string - example: AS3df3A - credit_id: - description: 'The credit hashed id' - type: string - example: AS3df3A - refunded: - description: 'The amount that has been refunded for this payment' - type: number - format: float - example: '10.00' - amount: - description: 'The amount that has been applied to the payment' - type: number - format: float - example: '10.00' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - created_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - type: object + + + Product: properties: id: @@ -2438,890 +97,11 @@ type: string example: Opnel5aKBz type: object - Quote: - properties: - id: - description: 'The quote hashed id' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: '' - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: '' - company_id: - description: 'The company hashed id' - type: string - example: '' - client_id: - description: 'The client hashed id' - type: string - example: '' - status_id: - description: 'The status of the quote' - type: string - example: '' - number: - description: 'The quote number - is a unique alpha numeric number per quote per company' - type: string - example: QUOTE_101 - po_number: - description: 'The purchase order number associated with this quote' - type: string - example: PO-1234 - terms: - description: 'The quote terms' - type: string - example: 'These are some quote terms. Valid for 14 days.' - public_notes: - description: 'Public notes for the quote' - type: string - example: 'These are public notes which the client may see' - private_notes: - description: 'Private notes for the quote' - type: string - example: 'These are private notes, not to be disclosed to the client' - footer: - description: 'Footer text of quote' - type: string - example: 'The text goes in the footer of the quote' - custom_value1: - description: 'Custom value field' - type: string - example: 'A custom value' - custom_value2: - description: 'Custom value field' - type: string - example: 'A custom value' - custom_value3: - description: 'Custom value field' - type: string - example: 'A custom value' - custom_value4: - description: 'Custom value field' - type: string - example: 'A custom value' - tax_name1: - description: 'The tax name' - type: string - example: GST - tax_name2: - description: 'The tax name' - type: string - example: VAT - tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - total_taxes: - description: 'The total taxes for the quote' - type: number - format: float - example: '10.00' - line_items: - description: 'An array of line items of the quote' - type: object - example: '' - amount: - description: 'The total amount of the quote' - type: number - format: float - example: '10.00' - balance: - description: 'The balance due of the quote' - type: number - format: float - example: '10.00' - paid_to_date: - description: 'The amount that has been paid to date on the quote' - type: number - format: float - example: '10.00' - discount: - description: 'The quote discount' - type: number - format: float - example: '10.00' - partial: - description: 'The partial/deposit amount' - type: number - format: float - example: '10.00' - is_amount_discount: - description: 'Boolean flag determining if the quote is an amount or percentage' - type: boolean - example: true - is_deleted: - description: 'Boolean flag determining if the quote has been deleted' - type: boolean - example: true - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' - type: boolean - example: true - date: - description: 'The Quote Date' - type: string - format: date - example: '1994-07-30' - last_sent_date: - description: 'The last date the quote was sent out' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The Next date for a reminder to be sent' - type: string - format: date - example: '1994-07-30' - partial_due_date: - description: 'The date when the partial/deposit is due' - type: string - format: date - example: '1994-07-30' - due_date: - description: 'The date the quote is valid until' - type: string - format: date - example: '1994-07-30' - settings: - $ref: '#/components/schemas/CompanySettings' - last_viewed: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge_tax1: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax2: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - type: object - RecurringExpense: - properties: - id: - description: 'The hashed id of the recurring expense' - type: string - example: Opnel5aKBz - user_id: - description: 'The hashed id of the user who created the recurring expense' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The hashed id of the user assigned to this recurring expense' - type: string - example: Opnel5aKBz - company_id: - description: 'The hashed id of the company' - type: string - example: Opnel5aKBz - client_id: - description: 'The hashed id of the client' - type: string - example: Opnel5aKBz - invoice_id: - description: 'The hashed id of the invoice' - type: string - example: Opnel5aKBz - bank_id: - description: 'The id of the bank associated with this recurring expense' - type: string - example: '22' - invoice_currency_id: - description: 'The currency id of the invoice associated with this recurring expense' - type: string - example: '1' - expense_currency_id: - description: 'The currency id of the expense associated with this recurring expense' - type: string - example: '1' - invoice_category_id: - description: 'The category id of the invoice' - type: string - example: '1' - payment_type_id: - description: 'The payment type id' - type: string - example: '1' - private_notes: - description: 'The recurring expense private notes' - type: string - example: 'Private and confidential' - public_notes: - description: 'The recurring expense public notes' - type: string - example: 'This is the best client in the world' - transaction_reference: - description: 'The recurring expense transaction reference' - type: string - example: EXP-1223-2333 - transcation_id: - description: 'The transaction id of the recurring expense' - type: string - example: '1233312312' - custom_value1: - description: 'Custom value field' - type: string - example: $1000 - custom_value2: - description: 'Custom value field' - type: string - example: '2022-10-10' - custom_value3: - description: 'Custom value field' - type: string - example: 'short text' - custom_value4: - description: 'Custom value field' - type: string - example: 'very long text' - tax_name1: - description: 'The tax name' - type: string - example: GST - tax_name2: - description: 'The tax name' - type: string - example: VAT - tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - amount: - description: 'The total amount of the recurring expense' - type: number - format: float - example: '10.00' - frequency_id: - description: 'The frequency this recurring expense fires' - type: number - format: int - example: '1' - remaining_cycles: - description: 'The number of remaining cycles for this recurring expense' - type: number - format: int - example: '1' - foreign_amount: - description: 'The foreign currency amount of the recurring expense' - type: number - format: float - example: '10.00' - exchange_rate: - description: 'The exchange rate for the expernse' - type: number - format: float - example: '0.80' - date: - description: 'The date of the expense' - type: string - example: '' - payment_date: - description: 'The date the expense was paid' - type: string - example: '' - should_be_invoiced: - description: 'Boolean flag determining if the expense should be invoiced' - type: boolean - example: true - is_deleted: - description: 'Boolean flag determining if the recurring expense is deleted' - type: boolean - example: true - last_sent_date: - description: 'The Date it was sent last' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The next send date' - type: string - format: date - example: '1994-07-30' - invoice_documents: - description: 'Boolean flag determining if the documents associated with this expense should be passed onto the invoice if it is converted to an invoice' - type: boolean - example: true - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - type: object - RecurringInvoice: - properties: - id: - description: 'The hashed id of the recurring invoice' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: Opnel5aKBz - company_id: - description: 'The company hashed id' - type: string - example: Opnel5aKBz - client_id: - description: 'The client hashed id' - type: string - example: Opnel5aKBz - status_id: - description: 'The invoice status variable' - type: string - example: '4' - frequency_id: - description: 'The recurring invoice frequency' - type: number - example: '4' - remaining_cycles: - description: 'The number of invoices left to be generated' - type: number - example: '4' - number: - description: 'The recurringinvoice number - is a unique alpha numeric number per invoice per company' - type: string - example: INV_101 - po_number: - description: 'The purchase order associated with this recurring invoice' - type: string - example: PO-1234 - terms: - description: 'The invoice terms' - type: string - example: 'These are invoice terms' - public_notes: - description: 'The public notes of the invoice' - type: string - example: 'These are some public notes' - private_notes: - description: 'The private notes of the invoice' - type: string - example: 'These are some private notes' - footer: - description: 'The invoice footer notes' - type: string - example: '' - custom_value1: - description: 'A custom field value' - type: string - example: '2022-10-01' - custom_value2: - description: 'A custom field value' - type: string - example: 'Something custom' - custom_value3: - description: 'A custom field value' - type: string - example: '' - custom_value4: - description: 'A custom field value' - type: string - example: '' - tax_name1: - description: 'The tax name' - type: string - example: '' - tax_name2: - description: 'The tax name' - type: string - example: '' - tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - total_taxes: - description: 'The total taxes for the invoice' - type: number - format: float - example: '10.00' - line_items: - description: 'An array of objects which define the line items of the invoice' - type: object - example: '' - amount: - description: 'The invoice amount' - type: number - format: float - example: '10.00' - balance: - description: 'The invoice balance' - type: number - format: float - example: '10.00' - paid_to_date: - description: 'The amount paid on the invoice to date' - type: number - format: float - example: '10.00' - discount: - description: 'The invoice discount, can be an amount or a percentage' - type: number - format: float - example: '10.00' - partial: - description: 'The deposit/partial amount' - type: number - format: float - example: '10.00' - is_amount_discount: - description: 'Flag determining if the discount is an amount or a percentage' - type: boolean - example: true - is_deleted: - description: 'Defines if the invoice has been deleted' - type: boolean - example: true - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' - type: boolean - example: true - date: - description: 'The Invoice Date' - type: string - format: date - example: '1994-07-30' - last_sent_date: - description: 'The last date the invoice was sent out' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The Next date for a reminder to be sent' - type: string - format: date - example: '1994-07-30' - partial_due_date: - description: 'The due date for the deposit/partial amount' - type: string - format: date - example: '1994-07-30' - due_date: - description: 'The due date of the invoice' - type: string - format: date - example: '1994-07-30' - settings: - $ref: '#/components/schemas/CompanySettings' - last_viewed: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge_tax1: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax2: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - type: object - RecurringQuote: - properties: - id: - description: 'The hashed id of the recurring quote' - type: string - example: Opnel5aKBz - user_id: - description: 'The user hashed id' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The assigned user hashed id' - type: string - example: Opnel5aKBz - company_id: - description: 'The company hashed id' - type: string - example: Opnel5aKBz - client_id: - description: 'The client hashed id' - type: string - example: Opnel5aKBz - status_id: - description: 'The quote status variable' - type: string - example: '4' - frequency_id: - description: 'The recurring quote frequency' - type: number - example: '4' - remaining_cycles: - description: 'The number of quotes left to be generated' - type: number - example: '4' - number: - description: 'The recurringquote number - is a unique alpha numeric number per quote per company' - type: string - example: INV_101 - po_number: - description: 'The purchase order associated with this recurring quote' - type: string - example: PO-1234 - terms: - description: 'The quote terms' - type: string - example: 'These are quote terms' - public_notes: - description: 'The public notes of the quote' - type: string - example: 'These are some public notes' - private_notes: - description: 'The private notes of the quote' - type: string - example: 'These are some private notes' - footer: - description: 'The quote footer notes' - type: string - example: '' - custom_value1: - description: 'A custom field value' - type: string - example: '2022-10-01' - custom_value2: - description: 'A custom field value' - type: string - example: 'Something custom' - custom_value3: - description: 'A custom field value' - type: string - example: '' - custom_value4: - description: 'A custom field value' - type: string - example: '' - tax_name1: - description: 'The tax name' - type: string - example: '' - tax_name2: - description: 'The tax name' - type: string - example: '' - tax_rate1: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_rate2: - description: 'The tax rate' - type: number - format: float - example: '10.00' - tax_name3: - description: 'The tax name' - type: string - example: '' - tax_rate3: - description: 'The tax rate' - type: number - format: float - example: '10.00' - total_taxes: - description: 'The total taxes for the quote' - type: number - format: float - example: '10.00' - line_items: - description: 'An array of objects which define the line items of the quote' - type: object - example: '' - amount: - description: 'The quote amount' - type: number - format: float - example: '10.00' - balance: - description: 'The quote balance' - type: number - format: float - example: '10.00' - paid_to_date: - description: 'The amount paid on the quote to date' - type: number - format: float - example: '10.00' - discount: - description: 'The quote discount, can be an amount or a percentage' - type: number - format: float - example: '10.00' - partial: - description: 'The deposit/partial amount' - type: number - format: float - example: '10.00' - is_amount_discount: - description: 'Flag determining if the discount is an amount or a percentage' - type: boolean - example: true - is_deleted: - description: 'Defines if the quote has been deleted' - type: boolean - example: true - uses_inclusive_taxes: - description: 'Defines the type of taxes used as either inclusive or exclusive' - type: boolean - example: true - date: - description: 'The quote Date' - type: string - format: date - example: '1994-07-30' - last_sent_date: - description: 'The last date the quote was sent out' - type: string - format: date - example: '1994-07-30' - next_send_date: - description: 'The Next date for a reminder to be sent' - type: string - format: date - example: '1994-07-30' - partial_due_date: - description: 'The due date for the deposit/partial amount' - type: string - format: date - example: '1994-07-30' - due_date: - description: 'The due date of the quote' - type: string - format: date - example: '1994-07-30' - settings: - $ref: '#/components/schemas/CompanySettings' - last_viewed: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - custom_surcharge1: - description: 'First Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge2: - description: 'Second Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge3: - description: 'Third Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge4: - description: 'Fourth Custom Surcharge' - type: number - format: float - example: '10.00' - custom_surcharge_tax1: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax2: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax3: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - custom_surcharge_tax4: - description: 'Toggles charging taxes on custom surcharge amounts' - type: boolean - example: true - type: object - SystemLog: - properties: - id: - description: 'The account hashed id' - type: string - example: AS3df3A - company_id: - description: 'The company hashed id' - type: string - example: AS3df3A - user_id: - description: 'The user_id hashed id' - type: string - example: AS3df3A - client_id: - description: 'The client_id hashed id' - type: string - example: AS3df3A - event_id: - description: 'The Log Type ID' - type: integer - example: 1 - category_id: - description: 'The Category Type ID' - type: integer - example: 1 - type_id: - description: 'The Type Type ID' - type: integer - example: 1 - log: - description: 'The json object of the error' - type: object - example: '{''key'':''value''}' - updated_at: - description: Timestamp - type: string - example: '2' - created_at: - description: Timestamp - type: string - example: '2' - type: object + + + + + TaskSchedulerSchema: properties: paused: @@ -3405,100 +185,7 @@ type: string example: create_client_report type: object - Task: - properties: - id: - description: 'The hashed id of the task' - type: string - example: Opnel5aKBz - user_id: - description: 'The hashed id of the user who created the task' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The assigned user of the task' - type: string - example: Opnel5aKBz - company_id: - description: 'The hashed id of the company' - type: string - example: Opnel5aKBz - client_id: - description: 'The hashed if of the client' - type: string - example: Opnel5aKBz - invoice_id: - description: 'The hashed id of the invoice associated with the task' - type: string - example: Opnel5aKBz - project_id: - description: 'The hashed id of the project associated with the task' - type: string - example: Opnel5aKBz - number: - description: 'The number of the task' - type: string - example: TASK-123 - time_log: - description: 'An array of unix time stamps defining the start and end times of the task' - type: string - example: '[[1,2],[3,4]]' - is_running: - description: 'Determines if the task is still running' - type: boolean - example: true - is_deleted: - description: 'Boolean flag determining if the task has been deleted' - type: boolean - example: true - task_status_id: - description: 'The hashed id of the task status' - type: string - example: Opnel5aKBz - description: - description: 'The task description' - type: string - example: 'A wonder task to work on' - duration: - description: 'The task duration' - type: integer - example: '' - task_status_order: - description: 'The order of the task' - type: integer - example: '4' - custom_value1: - description: 'A custom value' - type: string - example: '2022-10-10' - custom_value2: - description: 'A custom value' - type: string - example: $1100 - custom_value3: - description: 'A custom value' - type: string - example: 'I need help' - custom_value4: - description: 'A custom value' - type: string - example: INV-3343 - created_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - updated_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - archived_at: - description: Timestamp - type: number - format: integer - example: '1434342123' - type: object + TaskStatus: properties: name: @@ -3551,49 +238,7 @@ type: string example: '' type: object - User: - properties: - id: - description: 'The hashed id of the user' - type: string - example: Opnel5aKBz - first_name: - description: 'The first name of the user' - type: string - example: Brad - last_name: - description: 'The last name of the user' - type: string - example: Pitt - email: - description: 'The users email address' - type: string - example: brad@pitt.com - phone: - description: 'The users phone number' - type: string - example: 555-1233-23232 - signature: - description: 'The users sign off signature' - type: string - example: 'Have a nice day!' - avatar: - description: 'The users avatar' - type: string - example: 'https://url.to.your/avatar.png' - accepted_terms_version: - description: 'The version of the invoice ninja terms that has been accepted by the user' - type: string - example: 1.0.1 - oauth_user_id: - description: 'The provider id of the oauth entity' - type: string - example: jkhasdf789as6f675sdf768sdfs - oauth_provider_id: - description: 'The oauth entity id' - type: string - example: google - type: object + AuthenticationError: type: object properties: @@ -3629,204 +274,8 @@ type: string type: object type: object - VendorContact: - properties: - id: - description: 'The hashed id of the vendor contact' - type: string - example: Opnel5aKBz - user_id: - description: 'The hashed id of the user id' - type: string - example: Opnel5aKBz - company_id: - description: 'The hashed id of the company' - type: string - example: Opnel5aKBz - vendor_id: - description: 'The hashed id of the vendor' - type: string - example: Opnel5aKBz - first_name: - description: 'The first name of the contact' - type: string - example: Harry - last_name: - description: 'The last name of the contact' - type: string - example: Windsor - phone: - description: 'The contacts phone number' - type: string - example: 555-123-1234 - custom_value1: - description: 'A custom value' - type: string - example: '2022-10-10' - custom_value2: - description: 'A custom value' - type: string - example: $1000 - custom_value3: - description: 'A custom value' - type: string - example: '' - custom_value4: - description: 'A custom value' - type: string - example: '' - email: - description: 'The contact email address' - type: string - example: harry@windsor.com - is_primary: - description: 'Boolean flag determining if the contact is the primary contact for the vendor' - type: boolean - example: true - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - deleted_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - type: object - Vendor: - properties: - id: - description: 'The hashed id of the vendor' - type: string - example: Opnel5aKBz - user_id: - description: 'The hashed id of the user who created the vendor' - type: string - example: Opnel5aKBz - assigned_user_id: - description: 'The hashed id of the assigned user to this vendor' - type: string - example: Opnel5aKBz - company_id: - description: 'The hashed id of the company' - type: string - example: Opnel5aKBz - client_id: - description: 'The hashed id of the client' - type: string - example: Opnel5aKBz - contacts: - type: array - items: - $ref: '#/components/schemas/VendorContact' - name: - description: 'The vendor name' - type: string - example: 'Harry''s cafe de wheels' - website: - description: 'The website of the vendor' - type: string - example: www.harry.com - private_notes: - description: 'The private notes of the vendor' - type: string - example: 'Shhh, don''t tell the vendor' - industry_id: - description: 'The industry id of the vendor' - type: string - example: '1' - size_id: - description: ________ - type: string - example: '' - address1: - description: ________ - type: string - example: '' - address2: - description: ________ - type: string - example: '' - city: - description: ________ - type: string - example: '' - state: - description: ________ - type: string - example: '' - postal_code: - description: ________ - type: string - example: '' - phone: - description: 'The client phone number' - type: string - example: 555-3434-3434 - country_id: - description: ________ - type: string - example: '' - currency_id: - description: ________ - type: string - example: '4' - custom_value1: - description: ________ - type: string - example: '' - custom_value2: - description: ________ - type: string - example: '' - custom_value3: - description: ________ - type: string - example: '' - custom_value4: - description: ________ - type: string - example: '' - vat_number: - description: ________ - type: string - example: '' - id_number: - description: ________ - type: string - example: '' - number: - description: ________ - type: string - example: '' - is_deleted: - description: ________ - type: boolean - example: true - last_login: - description: Timestamp - type: number - format: integer - example: '134341234234' - created_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - updated_at: - description: Timestamp - type: number - format: integer - example: '134341234234' - settings: - $ref: '#/components/schemas/CompanySettings' - type: object + + Webhook: properties: id: diff --git a/openapi/components/schemas/bank_transaction_rule.yaml b/openapi/components/schemas/bank_transaction_rule.yaml new file mode 100644 index 000000000000..07c22d3d157c --- /dev/null +++ b/openapi/components/schemas/bank_transaction_rule.yaml @@ -0,0 +1,48 @@ + BankTransactionRule: + properties: + id: + description: 'The bank transaction rules hashed id' + type: string + example: AS3df3A + company_id: + description: 'The company hashed id' + type: string + example: AS3df3A + user_id: + description: 'The user hashed id' + type: string + example: AS3df3A + name: + description: 'The name of the transaction' + type: string + example: 'Rule 1' + rules: + description: 'A mapped collection of the sub rules for the BankTransactionRule' + type: array + items: + $ref: '#/components/schemas/BTRules' + auto_convert: + description: 'Flags whether the rule converts the transaction automatically' + type: boolean + example: true + matches_on_all: + description: 'Flags whether all subrules are required for the match' + type: boolean + example: true + applies_to: + description: 'Flags whether the rule applies to a CREDIT or DEBIT' + type: string + example: CREDIT + client_id: + description: 'The client hashed id' + type: string + example: AS3df3A + vendor_id: + description: 'The vendor hashed id' + type: string + example: AS3df3A + category_id: + description: 'The category hashed id' + type: string + example: AS3df3A + type: object \ No newline at end of file diff --git a/openapi/components/schemas/client.yaml b/openapi/components/schemas/client.yaml new file mode 100644 index 000000000000..f8df77644ee0 --- /dev/null +++ b/openapi/components/schemas/client.yaml @@ -0,0 +1,160 @@ + Client: + properties: + id: + description: 'The unique identifier of the client' + type: string + example: Opnel5aKBz + user_id: + description: 'The unique identifier of the user who created the client' + type: string + example: Ua6Rw4pVbS + company_id: + description: 'The unique identifier of the company the client belongs to' + type: string + example: Co7Vn3yLmW + contacts: + type: array + items: + $ref: '#/components/schemas/ClientContact' + name: + description: 'The name of the client company or organization' + type: string + example: "Jim's Housekeeping" + website: + description: 'The website URL of the client company or organization' + type: string + example: 'https://www.jims-housekeeping.com' + private_notes: + description: 'Notes that are only visible to the user who created the client' + type: string + example: 'Client prefers email communication over phone calls' + client_hash: + description: 'A unique hash value for the client' + type: string + example: asdfkjhk342hjhbfdvmnfb1 + industry_id: + description: 'The unique identifier of the industry the client operates in' + type: number + example: '5' + size_id: + description: 'The unique identifier for the size category of the client company or organization' + type: number + example: '2' + address1: + description: "First line of the client's address" + type: string + example: '123 Main St' + address2: + description: "Second line of the client's address, if needed" + type: string + example: 'Apt 4B' + city: + description: 'The city the client is located in' + type: string + example: 'Beverly Hills' + state: + description: 'The state, province, or locality the client is located in' + type: string + example: 'California' + postal_code: + description: 'The postal code or ZIP code of the client' + type: string + example: '90210' + phone: + description: "The client's phone number" + type: string + example: '555-3434-3434' + country_id: + description: "The unique identifier of the client's country" + type: number + format: integer + example: '1' + custom_value1: + description: 'A custom field for storing additional information' + type: string + example: 'Preferred contact: Email' + custom_value2: + description: 'A custom field for storing additional information' + type: string + example: 'Account manager: John Doe' + custom_value3: + description: 'A custom field for storing additional information' + type: string + example: 'VIP client: Yes' + custom_value4: + description: 'A custom field for storing additional information' + type: string + example: 'Annual contract value: $50,000' + vat_number: + description: "The client's VAT (Value Added Tax) number, if applicable" + type: string + example: 'VAT123456' + id_number: + description: 'A unique identification number for the client, such as a tax ID or business registration number' + type: string + number: + description: 'A system-assigned unique number for the client, typically used for invoicing purposes' + type: string + example: 'CL-0001' + shipping_address1: + description: "First line of the client's shipping address" + type: string + example: '5 Wallaby Way' + shipping_address2: + description: "Second line of the client's shipping address, if needed" + type: string + example: 'Suite 5' + shipping_city: + description: "The city of the client's shipping address" + type: string + example: 'Perth' + shipping_state: + description: "The state, province, or locality of the client's shipping address" + type: string + example: 'Western Australia' + shipping_postal_code: + description: "The postal code or ZIP code of the client's shipping address" + type: string + example: '6110' + shipping_country_id: + description: "The unique identifier of the country for the client's shipping address" + type: number + format: integer + example: '4' + is_deleted: + description: 'A boolean value indicating whether the client has been deleted or not' + type: boolean + example: false + balance: + description: 'The outstanding balance the client owes' + type: number + format: float + example: '500.00' + paid_to_date: + description: 'The total amount the client has paid to date' + type: number + format: float + example: '2000.00' + credit_balance: + description: 'The available credit balance for the client to use on future purchases' + type: number + format: float + example: '100.00' + last_login: + description: "The timestamp of the client's last login" + type: number + format: integer + example: '1628686031' + created_at: + description: 'The timestamp when the client was created' + type: number + format: integer + example: '1617629031' + updated_at: + description: 'The timestamp when the client was last updated' + type: number + format: integer + example: '1628445631' + settings: + $ref: '#/components/schemas/CompanySettings' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/client_contact.yaml b/openapi/components/schemas/client_contact.yaml new file mode 100644 index 000000000000..aaf1c1bef6e3 --- /dev/null +++ b/openapi/components/schemas/client_contact.yaml @@ -0,0 +1,113 @@ + ClientContact: + properties: + id: + description: 'The hashed if of the contact' + type: string + example: Opnel5aKBz + user_id: + description: 'The hashed id of the user who created the contact' + type: string + example: Opnel5aKBz + company_id: + description: 'The hashed id of the company' + type: string + example: Opnel5aKBz + client_id: + description: 'The hashed id of the client' + type: string + example: Opnel5aKBz + first_name: + description: 'The first name of the contact' + type: string + example: John + last_name: + description: 'The last name of the contact' + type: string + example: Doe + phone: + description: 'The phone number of the contact' + type: string + example: 555-152-4524 + custom_value1: + description: 'A Custom field value' + type: string + example: '' + custom_value2: + description: 'A Custom field value' + type: string + example: '' + custom_value3: + description: 'A Custom field value' + type: string + example: '' + custom_value4: + description: 'A Custom field value' + type: string + example: '' + email: + description: 'The email of the contact' + type: string + example: '' + accepted_terms_version: + description: 'The terms of service which the contact has accpeted' + type: string + example: 'A long set of ToS' + password: + description: 'The hashed password of the contact' + type: string + example: '*****' + confirmation-code: + description: 'The confirmation code used to authenticate the contacts email address' + type: string + example: 333-sdjkh34gbasd + token: + description: 'A uuid based token.' + type: string + example: 333-sdjkh34gbasd + is_primary: + description: 'Defines is this contact is the primary contact for the client' + type: boolean + example: true + confirmed: + description: 'Boolean value confirms the user has confirmed their account.' + type: boolean + example: true + is_locked: + description: 'Boolean value defines if the contact has been locked out.' + type: boolean + example: true + send_email: + description: 'Boolean value determines is this contact should receive emails' + type: boolean + example: true + failed_logins: + description: 'The number of failed logins the contact has had' + type: number + format: integer + example: '3' + email_verified_at: + description: 'The date which the contact confirmed their email' + type: number + format: integer + example: '134341234234' + last_login: + description: Timestamp + type: number + format: integer + example: '134341234234' + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + deleted_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/client_gateway_token.yaml b/openapi/components/schemas/client_gateway_token.yaml new file mode 100644 index 000000000000..b10587611278 --- /dev/null +++ b/openapi/components/schemas/client_gateway_token.yaml @@ -0,0 +1,31 @@ + ClientGatewayToken: + properties: + id: + description: 'The hashed id of the client gateway token' + type: string + example: Opnel5aKBz + company_id: + description: 'The hashed id of the company' + type: string + example: '2' + client_id: + description: 'The hashed_id of the client' + type: string + example: '2' + token: + description: 'The payment token' + type: string + example: '2' + routing_number: + description: 'THe bank account routing number' + type: string + example: '2' + company_gateway_id: + description: 'The hashed id of the company gateway' + type: string + example: '2' + is_default: + description: 'Flag determining if the token is the default payment method' + type: boolean + example: 'true' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/company.yaml b/openapi/components/schemas/company.yaml new file mode 100644 index 000000000000..3dbd83639eb0 --- /dev/null +++ b/openapi/components/schemas/company.yaml @@ -0,0 +1,91 @@ + Company: + properties: + id: + description: "The unique hashed identifier for the company" + type: string + example: WJxbojagwO + size_id: + description: "The unique identifier representing the company's size category" + type: string + example: '2' + industry_id: + description: "The unique identifier representing the company's industry category" + type: string + example: '5' + slack_webhook_url: + description: "The URL for the company's Slack webhook notifications" + type: string + example: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX' + google_analytics_key: + description: "The company's Google Analytics tracking ID" + type: string + example: 'UA-123456789-1' + portal_mode: + description: "The mode determining how client-facing URLs are structured (e.g., subdomain, domain, or iframe)" + type: string + example: subdomain + subdomain: + description: "The subdomain prefix for the company's domain (e.g., 'acme' in acme.domain.com)" + type: string + example: acme + portal_domain: + description: "The fully qualified domain used for client-facing URLs" + type: string + example: 'https://subdomain.invoicing.co' + enabled_tax_rates: + description: "The number of tax rates used per entity" + type: integer + example: '2' + fill_products: + description: "A flag determining whether to auto-fill product descriptions based on the product key" + type: boolean + example: true + convert_products: + description: "A flag determining whether to convert products between different types or units" + type: boolean + example: true + update_products: + description: "A flag determining whether to update product descriptions when the description changes" + type: boolean + example: true + show_product_details: + description: "A flag determining whether to display product details in the user interface" + type: boolean + example: true + custom_fields: + description: "A mapping of custom fields for various objects within the company" + type: object + enable_product_cost: + description: "A flag determining whether to show or hide the product cost field in the user interface" + type: boolean + example: true + enable_product_quantity: + description: "A flag determining whether to show or hide the product quantity field in the user interface" + type: boolean + example: true + default_quantity: + description: "A flag determining whether to use a default quantity for products" + type: boolean + example: true + custom_surcharge_taxes1: + description: "A flag determining whether to apply taxes on custom surcharge amounts for the first custom surcharge field" + type: boolean + example: true + custom_surcharge_taxes2: + description: "A flag determining whether to apply taxes on custom surcharge amounts for the second custom surcharge field" + type: boolean + example: true + custom_surcharge_taxes3: + description: "A flag determining whether to apply taxes on custom surcharge amounts for the third custom surcharge field" + type: boolean + example: true + custom_surcharge_taxes4: + description: "A flag determining whether to apply taxes on custom surcharge amounts for the fourth custom" + logo: + description: "The company logo file in binary format" + type: string + format: binary + example: logo.png + settings: + $ref: '#/components/schemas/CompanySettings' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/company_gateway.yaml b/openapi/components/schemas/company_gateway.yaml new file mode 100644 index 000000000000..35196f5f1d25 --- /dev/null +++ b/openapi/components/schemas/company_gateway.yaml @@ -0,0 +1,42 @@ + CompanyGateway: + properties: + id: + description: 'The hashed id of the company gateway' + type: string + example: Opnel5aKBz + company_id: + description: 'The company hashed id' + type: string + example: '2' + gateway_key: + description: 'The gateway key (hash)' + type: string + example: '2' + accepted_credit_cards: + description: 'Bitmask representation of cards' + type: integer + example: '32' + require_billing_address: + description: 'Determines if the the billing address is required prior to payment.' + type: boolean + example: true + require_shipping_address: + description: 'Determines if the the billing address is required prior to payment.' + type: boolean + example: true + config: + description: 'The configuration map for the gateway' + type: string + example: dfadsfdsafsafd + update_details: + description: 'Determines if the client details should be updated.' + type: boolean + example: true + fees_and_limits: + description: 'A mapped collection of the fees and limits for the configured gateway' + type: array + items: + $ref: '#/components/schemas/FeesAndLimits' + type: object + + \ No newline at end of file diff --git a/openapi/components/schemas/company_ledger.yaml b/openapi/components/schemas/company_ledger.yaml new file mode 100644 index 000000000000..8527c105cfbe --- /dev/null +++ b/openapi/components/schemas/company_ledger.yaml @@ -0,0 +1,31 @@ + CompanyLedger: + properties: + entity_id: + description: 'This field will reference one of the following entity hashed ID payment_id, invoice_id or credit_id' + type: string + example: AS3df3A + notes: + description: 'The notes which reference this entry of the ledger' + type: string + example: 'Credit note for invoice #3212' + balance: + description: 'The client balance' + type: number + format: float + example: '10.00' + adjustment: + description: 'The amount the client balance is adjusted by' + type: number + format: float + example: '10.00' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + created_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/company_settings.yaml b/openapi/components/schemas/company_settings.yaml new file mode 100644 index 000000000000..04902e8a4613 --- /dev/null +++ b/openapi/components/schemas/company_settings.yaml @@ -0,0 +1,592 @@ + CompanySettings: + properties: + timezone_id: + description: 'The timezone id' + type: string + example: '15' + date_format_id: + description: 'The date format id' + type: string + example: '15' + military_time: + description: 'Toggles 12/24 hour time' + type: boolean + example: true + language_id: + description: 'The language id' + type: string + example: '1' + show_currency_code: + description: 'Toggles whether the currency symbol or code is shown' + type: boolean + example: true + currency_id: + description: 'The default currency id' + type: string + example: true + payment_terms: + description: '-1 sets no payment term, 0 sets payment due immediately, positive integers indicates payment terms in days' + type: integer + example: '1' + company_gateway_ids: + description: 'A commad separate list of available gateways' + type: string + example: '1,2,3,4' + custom_value1: + description: 'A Custom Label' + type: string + example: 'Custom Label' + custom_value2: + description: 'A Custom Label' + type: string + example: 'Custom Label' + custom_value3: + description: 'A Custom Label' + type: string + example: 'Custom Label' + custom_value4: + description: 'A Custom Label' + type: string + example: 'Custom Label' + default_task_rate: + description: 'The default task rate' + type: number + format: float + example: '10.00' + send_reminders: + description: 'Toggles whether reminders are sent' + type: boolean + example: true + enable_client_portal_tasks: + description: 'Show/hide the tasks panel in the client portal' + type: boolean + example: true + email_style: + description: 'options include plain,light,dark,custom' + type: string + example: light + reply_to_email: + description: 'The reply to email address' + type: string + example: email@gmail.com + bcc_email: + description: 'A comma separate list of BCC emails' + type: string + example: 'email@gmail.com, contact@gmail.com' + pdf_email_attachment: + description: 'Toggles whether to attach PDF as attachment' + type: boolean + example: true + ubl_email_attachment: + description: 'Toggles whether to attach UBL as attachment' + type: boolean + example: true + email_style_custom: + description: 'The custom template' + type: string + example: '' + counter_number_applied: + description: 'enum when the invoice number counter is set, ie when_saved, when_sent, when_paid' + type: string + example: when_sent + quote_number_applied: + description: 'enum when the quote number counter is set, ie when_saved, when_sent' + type: string + example: when_sent + custom_message_dashboard: + description: 'A custom message which is displayed on the dashboard' + type: string + example: 'Please pay invoices immediately' + custom_message_unpaid_invoice: + description: 'A custom message which is displayed in the client portal when a client is viewing a unpaid invoice.' + type: string + example: 'Please pay invoices immediately' + custom_message_paid_invoice: + description: 'A custom message which is displayed in the client portal when a client is viewing a paid invoice.' + type: string + example: 'Thanks for paying this invoice!' + custom_message_unapproved_quote: + description: 'A custom message which is displayed in the client portal when a client is viewing a unapproved quote.' + type: string + example: 'Please approve quote' + lock_invoices: + description: 'Toggles whether invoices are locked once sent and cannot be modified further' + type: boolean + example: true + auto_archive_invoice: + description: 'Toggles whether a invoice is archived immediately following payment' + type: boolean + example: true + auto_archive_quote: + description: 'Toggles whether a quote is archived after being converted to a invoice' + type: boolean + example: true + auto_convert_quote: + description: 'Toggles whether a quote is converted to a invoice when approved' + type: boolean + example: true + inclusive_taxes: + description: 'Boolean flag determining whether inclusive or exclusive taxes are used' + type: boolean + example: true + translations: + description: 'JSON payload of customized translations' + type: object + example: '' + task_number_pattern: + description: 'Allows customisation of the task number pattern' + type: string + example: '{$year}-{$counter}' + task_number_counter: + description: 'The incrementing counter for tasks' + type: integer + example: '1' + reminder_send_time: + description: 'Time from UTC +0 when the email will be sent to the client' + type: integer + example: '32400' + expense_number_pattern: + description: 'Allows customisation of the expense number pattern' + type: string + example: '{$year}-{$counter}' + expense_number_counter: + description: 'The incrementing counter for expenses' + type: integer + example: '1' + vendor_number_pattern: + description: 'Allows customisation of the vendor number pattern' + type: string + example: '{$year}-{$counter}' + vendor_number_counter: + description: 'The incrementing counter for vendors' + type: integer + example: '1' + ticket_number_pattern: + description: 'Allows customisation of the ticket number pattern' + type: string + example: '{$year}-{$counter}' + ticket_number_counter: + description: 'The incrementing counter for tickets' + type: integer + example: '1' + payment_number_pattern: + description: 'Allows customisation of the payment number pattern' + type: string + example: '{$year}-{$counter}' + payment_number_counter: + description: 'The incrementing counter for payments' + type: integer + example: '1' + invoice_number_pattern: + description: 'Allows customisation of the invoice number pattern' + type: string + example: '{$year}-{$counter}' + invoice_number_counter: + description: 'The incrementing counter for invoices' + type: integer + example: '1' + quote_number_pattern: + description: 'Allows customisation of the quote number pattern' + type: string + example: '{$year}-{$counter}' + quote_number_counter: + description: 'The incrementing counter for quotes' + type: integer + example: '1' + client_number_pattern: + description: 'Allows customisation of the client number pattern' + type: string + example: '{$year}-{$counter}' + client_number_counter: + description: 'The incrementing counter for clients' + type: integer + example: '1' + credit_number_pattern: + description: 'Allows customisation of the credit number pattern' + type: string + example: '{$year}-{$counter}' + credit_number_counter: + description: 'The incrementing counter for credits' + type: integer + example: '1' + recurring_invoice_number_prefix: + description: 'This string is prepended to the recurring invoice number' + type: string + example: R + reset_counter_frequency_id: + description: 'CONSTANT which is used to apply the frequency which the counters are reset' + type: integer + example: '1' + reset_counter_date: + description: 'The explicit date which is used to reset counters' + type: string + example: '2019-01-01' + counter_padding: + description: 'Pads the counter with leading zeros' + type: integer + example: '1' + shared_invoice_quote_counter: + description: 'Flags whether to share the counter for invoices and quotes' + type: boolean + example: true + update_products: + description: 'Determines if client fields are updated from third party APIs' + type: boolean + example: true + convert_products: + description: '' + type: boolean + example: true + fill_products: + description: 'Automatically fill products based on product_key' + type: boolean + example: true + invoice_terms: + description: 'The default invoice terms' + type: string + example: 'Invoice Terms are...' + quote_terms: + description: 'The default quote terms' + type: string + example: 'Quote Terms are...' + invoice_taxes: + description: 'Taxes can be applied to the invoice' + type: number + example: '1' + invoice_design_id: + description: 'The default design id (invoice, quote etc)' + type: string + example: '1' + quote_design_id: + description: 'The default design id (invoice, quote etc)' + type: string + example: '1' + invoice_footer: + description: 'The default invoice footer' + type: string + example: '1' + invoice_labels: + description: 'JSON string of invoice labels' + type: string + example: '1' + tax_rate1: + description: 'The tax rate (float)' + type: number + example: '10' + tax_name1: + description: 'The tax name' + type: string + example: GST + tax_rate2: + description: 'The tax rate (float)' + type: number + example: '10' + tax_name2: + description: 'The tax name' + type: string + example: GST + tax_rate3: + description: 'The tax rate (float)' + type: number + example: '10' + tax_name3: + description: 'The tax name' + type: string + example: GST + payment_type_id: + description: 'The default payment type id' + type: string + example: '1' + custom_fields: + description: 'JSON string of custom fields' + type: string + example: '{}' + email_footer: + description: 'The default email footer' + type: string + example: 'A default email footer' + email_sending_method: + description: 'The email driver to use to send email, options include default, gmail' + type: string + example: default + gmail_sending_user_id: + description: 'The hashed_id of the user account to send email from' + type: string + example: F76sd34D + email_subject_invoice: + description: '' + type: string + example: 'Your Invoice Subject' + email_subject_quote: + description: '' + type: string + example: 'Your Quote Subject' + email_subject_payment: + description: '' + type: string + example: 'Your Payment Subject' + email_template_invoice: + description: 'The full template for invoice emails' + type: string + example: '' + email_template_quote: + description: 'The full template for quote emails' + type: string + example: '' + email_template_payment: + description: 'The full template for payment emails' + type: string + example: '' + email_subject_reminder1: + description: 'Email subject for Reminder' + type: string + example: '' + email_subject_reminder2: + description: 'Email subject for Reminder' + type: string + example: '' + email_subject_reminder3: + description: 'Email subject for Reminder' + type: string + example: '' + email_subject_reminder_endless: + description: 'Email subject for endless reminders' + type: string + example: '' + email_template_reminder1: + description: 'The full template for Reminder 1' + type: string + example: '' + email_template_reminder2: + description: 'The full template for Reminder 2' + type: string + example: '' + email_template_reminder3: + description: 'The full template for Reminder 3' + type: string + example: '' + email_template_reminder_endless: + description: 'The full template for enless reminders' + type: string + example: '' + enable_portal_password: + description: 'Toggles whether a password is required to log into the client portal' + type: boolean + example: true + show_accept_invoice_terms: + description: 'Toggles whether the terms dialogue is shown to the client' + type: boolean + example: true + show_accept_quote_terms: + description: 'Toggles whether the terms dialogue is shown to the client' + type: boolean + example: true + require_invoice_signature: + description: 'Toggles whether a invoice signature is required' + type: boolean + example: true + require_quote_signature: + description: 'Toggles whether a quote signature is required' + type: boolean + example: true + name: + description: 'The company name' + type: string + example: 'Acme Co' + company_logo: + description: 'The company logo file' + type: object + example: logo.png + website: + description: 'The company website URL' + type: string + example: www.acme.com + address1: + description: 'The company address line 1' + type: string + example: 'Suite 888' + address2: + description: 'The company address line 2' + type: string + example: '5 Jimbo Way' + city: + description: 'The company city' + type: string + example: Sydney + state: + description: 'The company state' + type: string + example: Florisa + postal_code: + description: 'The company zip/postal code' + type: string + example: '90210' + phone: + description: 'The company phone' + type: string + example: 555-213-3948 + email: + description: 'The company email' + type: string + example: joe@acme.co + country_id: + description: 'The country ID' + type: string + example: '1' + vat_number: + description: 'The company VAT/TAX ID number' + type: string + example: '32 120 377 720' + page_size: + description: 'The default page size' + type: string + example: A4 + font_size: + description: 'The font size' + type: number + example: '9' + primary_font: + description: 'The primary font' + type: string + example: roboto + secondary_font: + description: 'The secondary font' + type: string + example: roboto + hide_paid_to_date: + description: 'Flags whether to hide the paid to date field' + type: boolean + example: false + embed_documents: + description: 'Toggled whether to embed documents in the PDF' + type: boolean + example: false + all_pages_header: + description: 'The header for the PDF' + type: boolean + example: false + all_pages_footer: + description: 'The footer for the PDF' + type: boolean + example: false + document_email_attachment: + description: 'Toggles whether to attach documents in the email' + type: boolean + example: false + enable_client_portal_password: + description: 'Toggles password protection of the client portal' + type: boolean + example: false + enable_email_markup: + description: 'Toggles the use of markdown in emails' + type: boolean + example: false + enable_client_portal_dashboard: + description: 'Toggles whether the client dashboard is shown in the client portal' + type: boolean + example: false + enable_client_portal: + description: 'Toggles whether the entire client portal is displayed to the client, or only the context' + type: boolean + example: false + email_template_statement: + description: 'The body of the email for statements' + type: string + example: 'template matter' + email_subject_statement: + description: 'The subject of the email for statements' + type: string + example: 'subject matter' + signature_on_pdf: + description: 'Toggles whether the signature (if available) is displayed on the PDF' + type: boolean + example: false + quote_footer: + description: 'The default quote footer' + type: string + example: 'the quote footer' + email_subject_custom1: + description: 'Custom reminder template subject' + type: string + example: 'Custom Subject 1' + email_subject_custom2: + description: 'Custom reminder template subject' + type: string + example: 'Custom Subject 2' + email_subject_custom3: + description: 'Custom reminder template subject' + type: string + example: 'Custom Subject 3' + email_template_custom1: + description: 'Custom reminder template body' + type: string + example: '' + email_template_custom2: + description: 'Custom reminder template body' + type: string + example: '' + email_template_custom3: + description: 'Custom reminder template body' + type: string + example: '' + enable_reminder1: + description: 'Toggles whether this reminder is enabled' + type: boolean + example: false + enable_reminder2: + description: 'Toggles whether this reminder is enabled' + type: boolean + example: false + enable_reminder3: + description: 'Toggles whether this reminder is enabled' + type: boolean + example: false + num_days_reminder1: + description: 'The Reminder interval' + type: number + example: '9' + num_days_reminder2: + description: 'The Reminder interval' + type: number + example: '9' + num_days_reminder3: + description: 'The Reminder interval' + type: number + example: '9' + schedule_reminder1: + description: '(enum: after_invoice_date, before_due_date, after_due_date)' + type: string + example: after_invoice_date + schedule_reminder2: + description: '(enum: after_invoice_date, before_due_date, after_due_date)' + type: string + example: after_invoice_date + schedule_reminder3: + description: '(enum: after_invoice_date, before_due_date, after_due_date)' + type: string + example: after_invoice_date + late_fee_amount1: + description: 'The late fee amount for reminder 1' + type: number + example: 10 + late_fee_amount2: + description: 'The late fee amount for reminder 2' + type: number + example: 20 + late_fee_amount3: + description: 'The late fee amount for reminder 2' + type: number + example: 100 + endless_reminder_frequency_id: + description: 'The frequency id of the endless reminder' + type: string + example: '1' + client_online_payment_notification: + description: 'Determines if a client should receive the notification for a online payment' + type: boolean + example: false + client_manual_payment_notification: + description: 'Determines if a client should receive the notification for a manually entered payment' + type: boolean + example: false + type: object \ No newline at end of file diff --git a/openapi/components/schemas/company_token.yaml b/openapi/components/schemas/company_token.yaml new file mode 100644 index 000000000000..5602f33169a8 --- /dev/null +++ b/openapi/components/schemas/company_token.yaml @@ -0,0 +1,15 @@ + CompanyToken: + properties: + name: + description: 'The token name' + type: string + example: 'Token Name' + token: + description: 'The token value' + type: string + example: AS3df3jUUH765fhfd9KJuidj3JShjA + is_system: + description: 'Determines whether the token is created by the system rather than a user' + type: boolean + example: 'true' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/company_user.yaml b/openapi/components/schemas/company_user.yaml new file mode 100644 index 000000000000..5d67b726ad55 --- /dev/null +++ b/openapi/components/schemas/company_user.yaml @@ -0,0 +1,43 @@ + CompanyUser: + properties: + permissions: + description: 'The company user permissions' + type: string + example: '[create_invoice]' + settings: + description: 'Settings that are used for the frontend applications to store user preferences / metadata' + type: object + example: 'json object' + react_settings: + description: 'Dedicated settings object for the react web application' + type: object' + example: 'json object' + is_owner: + description: 'Determines whether the user owns this company' + type: boolean + example: true + is_admin: + description: 'Determines whether the user is the admin of this company' + type: boolean + example: true + is_locked: + description: 'Determines whether the users access to this company has been locked' + type: boolean + example: true + updated_at: + description: 'The last time the record was modified, format Unix Timestamp' + type: integer + example: '1231232312321' + deleted_at: + description: 'Timestamp when the user was archived, format Unix Timestamp' + type: integer + example: '12312312321' + account: + $ref: '#/components/schemas/Account' + company: + $ref: '#/components/schemas/Company' + user: + $ref: '#/components/schemas/User' + token: + $ref: '#/components/schemas/CompanyToken' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/credit.yaml b/openapi/components/schemas/credit.yaml new file mode 100644 index 000000000000..54df65e21de2 --- /dev/null +++ b/openapi/components/schemas/credit.yaml @@ -0,0 +1,222 @@ + Credit: + properties: + id: + description: "The unique hashed ID of the credit" + type: string + example: Opnel5aKBz + user_id: + description: "The unique hashed ID of the user associated with the credit" + type: string + example: 1a2b3c4d5e + assigned_user_id: + description: "The unique hashed ID of the assigned user responsible for the credit" + type: string + example: 6f7g8h9i0j + company_id: + description: "The unique hashed ID of the company associated with the credit" + type: string + example: k1l2m3n4o5 + client_id: + description: "The unique hashed ID of the client associated with the credit" + type: string + example: p1q2r3s4t5 + status_id: + description: "The ID representing the current status of the credit" + type: string + example: 3 + invoice_id: + description: "The unique hashed ID of the linked invoice to which the credit is applied" + type: string + example: u1v2w3x4y5 + number: + description: "The unique alphanumeric credit number per company" + type: string + example: QUOTE_101 + po_number: + description: "The purchase order number referred to by the credit" + type: string + example: PO_12345 + terms: + description: "The terms associated with the credit" + type: string + example: "Net 30" + public_notes: + description: "Public notes for the credit" + type: string + example: "Thank you for your business." + private_notes: + description: "Private notes for internal use, not visible to the client" + type: string + example: "Client is requesting a discount." + footer: + description: "The footer text for the credit" + type: string + example: "Footer text goes here." + custom_value1: + description: "Custom value 1 for additional credit information" + type: string + example: "Custom data 1" + custom_value2: + description: "Custom value 2 for additional credit information" + type: string + example: "Custom data 2" + custom_value3: + description: "Custom value 3 for additional credit information" + type: string + example: "Custom data 3" + custom_value4: + description: "Custom value 4 for additional credit information" + type: string + example: "Custom data 4" + tax_name1: + description: "The name of the first tax applied to the credit" + type: string + example: "VAT" + tax_name2: + description: "The name of the second tax applied to the credit" + type: string + example: "GST" + tax_rate1: + description: "The rate of the first tax applied to the credit" + type: number + format: float + example: 10.00 + tax_rate2: + description: "The rate of the second tax applied to the credit" + type: number + format: float + example: 5.00 + tax_name3: + description: "The name of the third tax applied to the credit" + type: string + example: "PST" + tax_rate3: + description: "The rate of the third tax applied to the credit" + type: number + format: float + example: 8.00 + total_taxes: + description: "The total amount of taxes for the credit" + type: number + format: float + example: 23.00 + line_items: + description: "The array of line items included in the credit" + type: object + example: "[{item1}, {item2}]" + amount: + description: "The total amount of the credit" + type: number + format: float + example: 100.00 + balance: + description: "The outstanding balance of the credit" + type: number + format: float + example: 50.00 + paid_to_date: + description: "The total amount paid to date for the credit" + type: number + format: float + example: 50.00 + discount: + description: "The discount applied to the credit" + type: number + format: float + example: 10.00 + partial: + description: "The partial amount applied to the credit" + type: number + format: float + example: 20.00 + is_amount_discount: + description: "Indicates whether the discount applied is a fixed amount or a percentage" + type: boolean + example: true + is_deleted: + description: "Indicates whether the credit has been deleted" + type: boolean + example: false + uses_inclusive_taxes: + description: "Indicates whether the tax rates applied to the credit are inclusive or exclusive" + type: boolean + example: true + date: + description: "The date the credit was issued" + type: string + format: date + example: "1994-07-30" + last_sent_date: + description: "The date the credit was last sent out" + type: string + format: date + example: "1994-07-30" + next_send_date: + description: "The next scheduled date for sending a credit reminder" + type: string + format: date + example: "1994-07-30" + partial_due_date: + description: "The due date for the partial amount of the credit" + type: string + format: date + example: "1994-07-30" + due_date: + description: "The due date for the total amount of the credit" + type: string + format: date + example: "1994-07-30" + settings: + $ref: "#/components/schemas/CompanySettings" + last_viewed: + description: "The timestamp of the last time the credit was viewed" + type: number + format: integer + example: 1434342123 + updated_at: + description: "The timestamp of the last time the credit was updated" + type: number + format: integer + example: 1434342123 + archived_at: + description: "The timestamp of the last time the credit was archived" + type: number + format: integer + example: 1434342123 + custom_surcharge1: + description: "First custom surcharge amount" + type: number + format: float + example: 10.00 + custom_surcharge2: + description: 'Second Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge3: + description: 'Third Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge4: + description: 'Fourth Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge_tax1: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + type: object \ No newline at end of file diff --git a/openapi/components/schemas/design.yaml b/openapi/components/schemas/design.yaml new file mode 100644 index 000000000000..b5ca557d7c70 --- /dev/null +++ b/openapi/components/schemas/design.yaml @@ -0,0 +1,42 @@ + Design: + properties: + id: + description: 'The design hashed id' + type: string + example: AS3df3A + name: + description: 'The design name' + type: string + example: Beauty + design: + description: 'The design HTML' + type: string + example: '' + is_custom: + description: 'Flag to determine if the design is a custom user design' + type: boolean + example: true + is_active: + description: 'Flag to determine if the design is available for use' + type: boolean + example: true + is_deleted: + description: 'Flag to determine if the design is deleted' + type: boolean + example: true + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + deleted_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/document.yaml b/openapi/components/schemas/document.yaml new file mode 100644 index 000000000000..96d8029e9b5b --- /dev/null +++ b/openapi/components/schemas/document.yaml @@ -0,0 +1,70 @@ + Document: + properties: + id: + description: 'The document hashed id' + type: string + example: AS3df3A + user_id: + description: 'The user hashed id' + type: string + example: '' + assigned_user_id: + description: 'The assigned user hashed id' + type: string + example: '' + project_id: + description: 'The project associated with this document' + type: string + example: '' + vendor_id: + description: 'The vendor associated with this documents' + type: string + example: '' + name: + description: 'The document name' + type: string + example: Beauty + url: + description: 'The document url' + type: string + example: Beauty + preview: + description: 'The document preview url' + type: string + example: Beauty + type: + description: 'The document type' + type: string + example: Beauty + disk: + description: 'The document disk' + type: string + example: Beauty + hash: + description: 'The document hashed' + type: string + example: Beauty + is_deleted: + description: 'Flag to determine if the document is deleted' + type: boolean + example: true + is_default: + description: 'Flag to determine if the document is a default doc' + type: boolean + example: true + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + deleted_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/error.yaml b/openapi/components/schemas/error.yaml new file mode 100644 index 000000000000..e404d014fce9 --- /dev/null +++ b/openapi/components/schemas/error.yaml @@ -0,0 +1,11 @@ + Error: + properties: + message: + description: 'Something terrible went wrong' + type: string + example: 'Unexpected error' + code: + description: 'The HTTP error code, ie 5xx 4xx' + type: integer + example: '500' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/expense.yaml b/openapi/components/schemas/expense.yaml new file mode 100644 index 000000000000..5801a73287b1 --- /dev/null +++ b/openapi/components/schemas/expense.yaml @@ -0,0 +1,155 @@ + Expense: + properties: + id: + description: 'The expense hashed id' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: '' + assigned_user_id: + description: 'The assigned user hashed id' + type: string + example: '' + company_id: + description: 'The company hashed id' + type: string + example: '' + client_id: + description: 'The client hashed id' + type: string + example: '' + invoice_id: + description: 'The related invoice hashed id' + type: string + example: '' + bank_id: + description: 'The bank id related to this expense' + type: string + example: '' + invoice_currency_id: + description: 'The currency id of the related invoice' + type: string + example: '' + expense_currency_id: + description: 'The currency id of the expense' + type: string + example: '' + invoice_category_id: + description: 'The invoice category id' + type: string + example: '' + payment_type_id: + description: 'The payment type id' + type: string + example: '' + recurring_expense_id: + description: 'The related recurring expense this expense was created from' + type: string + example: '' + private_notes: + description: 'The private notes of the expense' + type: string + example: '' + public_notes: + description: 'The public notes of the expense' + type: string + example: '' + transaction_reference: + description: 'The transaction references of the expense' + type: string + example: '' + transcation_id: + description: 'The transaction id of the expense' + type: string + example: '' + custom_value1: + description: 'A custom value' + type: string + example: '' + custom_value2: + description: 'A custom value' + type: string + example: '' + custom_value3: + description: 'A custom value' + type: string + example: '' + custom_value4: + description: 'A custom value' + type: string + example: '' + tax_name1: + description: 'Tax name' + type: string + example: '' + tax_name2: + description: 'Tax name' + type: string + example: '' + tax_rate1: + description: 'Tax rate' + type: number + format: float + example: '10.00' + tax_rate2: + description: 'Tax rate' + type: number + format: float + example: '10.00' + tax_name3: + description: 'Tax name' + type: string + example: '' + tax_rate3: + description: 'Tax rate' + type: number + format: float + example: '10.00' + amount: + description: 'The total expense amont' + type: number + format: float + example: '10.00' + foreign_amount: + description: 'The total foreign amount of the expense' + type: number + format: float + example: '10.00' + exchange_rate: + description: 'The exchange rate at the time of the expense' + type: number + format: float + example: '0.80' + date: + description: 'The expense date formate Y-m-d' + type: string + example: '2022-12-01' + payment_date: + description: 'The date of payment for the expense, format Y-m-d' + type: string + example: '' + should_be_invoiced: + description: 'Flag whether the expense should be invoiced' + type: boolean + example: true + is_deleted: + description: 'Boolean determining whether the expense has been deleted' + type: boolean + example: true + invoice_documents: + description: 'Passing the expense documents over to the invoice' + type: boolean + example: true + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/expense_category.yaml b/openapi/components/schemas/expense_category.yaml new file mode 100644 index 000000000000..707d7d21ddc0 --- /dev/null +++ b/openapi/components/schemas/expense_category.yaml @@ -0,0 +1,27 @@ + ExpenseCategory: + properties: + id: + description: 'The expense hashed id' + type: string + example: Opnel5aKBz + name: + description: 'The expense category name' + type: string + example: Accounting + user_id: + description: 'The user hashed id' + type: string + example: XS987sD + is_deleted: + description: 'Flag determining whether the expense category has been deleted' + type: boolean + example: true + updated_at: + description: 'The updated at timestamp' + type: integer + example: '2' + created_at: + description: 'The created at timestamp' + type: integer + example: '2' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/fees_and_limits.yaml b/openapi/components/schemas/fees_and_limits.yaml new file mode 100644 index 000000000000..25ab01450014 --- /dev/null +++ b/openapi/components/schemas/fees_and_limits.yaml @@ -0,0 +1,58 @@ + + FeesAndLimits: + properties: + min_limit: + description: 'The minimum amount accepted for this gateway' + type: string + example: '2' + max_limit: + description: 'The maximum amount accepted for this gateway' + type: string + example: '2' + fee_amount: + description: 'The gateway fee amount' + type: number + format: float + example: '2.0' + fee_percent: + description: 'The gateway fee percentage' + type: number + format: float + example: '2.0' + fee_tax_name1: + description: 'Fee tax name' + type: string + example: GST + fee_tax_name2: + description: 'Fee tax name' + type: string + example: VAT + fee_tax_name3: + description: 'Fee tax name' + type: string + example: 'CA Sales Tax' + fee_tax_rate1: + description: 'The tax rate' + type: number + format: float + example: '10.0' + fee_tax_rate2: + description: 'The tax rate' + type: number + format: float + example: '17.5' + fee_tax_rate3: + description: 'The tax rate' + type: number + format: float + example: '25.0' + fee_cap: + description: 'If set the fee amount will be no higher than this amount' + type: number + format: float + example: '2.0' + adjust_fee_percent: + description: 'Adjusts the fee to match the exact gateway fee.' + type: boolean + example: true + type: object \ No newline at end of file diff --git a/openapi/components/schemas/fillable_invoice.yaml b/openapi/components/schemas/fillable_invoice.yaml new file mode 100644 index 000000000000..d6593eefe1fe --- /dev/null +++ b/openapi/components/schemas/fillable_invoice.yaml @@ -0,0 +1,123 @@ + FillableInvoice: + properties: + assigned_user_id: + description: "The assigned user's hashed ID" + type: string + example: 'a1b2c3d4' + client_id: + description: "The client's hashed ID" + type: string + example: 'x1y2z3a4' + number: + description: "The unique alphanumeric invoice number for each invoice per company" + type: string + example: INV_101 + po_number: + description: "The purchase order number associated with the invoice" + type: string + example: 'PO12345' + terms: + description: "The terms and conditions for the invoice" + type: string + example: 'Net 30' + public_notes: + description: "Public notes visible to the client on the invoice" + type: string + example: 'Thank you for your business.' + private_notes: + description: "Private notes for internal use only" + type: string + example: 'Client is a slow payer.' + footer: + description: "The footer text displayed on the invoice" + type: string + example: 'Authorized Signature' + custom_value1: + description: "First custom value for additional information" + type: string + example: 'Project ABC' + custom_value2: + description: "Second custom value for additional information" + type: string + example: 'Department XYZ' + custom_value3: + description: "Third custom value for additional information" + type: string + example: 'Location 123' + custom_value4: + description: "Fourth custom value for additional information" + type: string + example: 'Currency USD' + tax_name1: + description: "Name of the first tax applied to the invoice" + type: string + example: 'VAT' + tax_name2: + description: "Name of the second tax applied to the invoice" + type: string + example: 'GST' + tax_rate1: + description: "Rate of the first tax applied to the invoice" + type: number + example: 10.00 + tax_rate2: + description: "Rate of the second tax applied to the invoice" + type: number + example: 5.00 + tax_name3: + description: "Name of the third tax applied to the invoice" + type: string + example: 'PST' + tax_rate3: + description: "Rate of the third tax applied to the invoice" + type: number + example: 8.00 + line_items: + description: "Array of line items included in the invoice" + type: object + example: "[{item1}, {item2}]" + discount: + description: "The discount applied to the invoice" + type: number + example: 10.00 + partial: + description: "The partial amount applied to the invoice" + type: number + example: 20.00 + is_amount_discount: + description: "Indicates whether the discount applied is a fixed amount or a percentage" + type: boolean + example: true + uses_inclusive_taxes: + description: "Indicates whether the tax rates applied to the invoice are inclusive or exclusive" + type: boolean + example: true + date: + description: "The date the invoice was issued" + type: string + example: '1994-07-30' + partial_due_date: + description: "The due date for the partial payment" + type: string + example: '1994-08-15' + due_date: + description: "The due date for the invoice" + type: string + example: '1994-08-30' + custom_surcharge1: + description: "First custom surcharge applied to the invoice" + type: number + example: 10.00 + custom_surcharge2: + description: "Second custom surcharge applied to the invoice" + type: number + example: 15.00 + custom_surcharge3: + description: "Third custom surcharge applied to the invoice" + type: number + example: 5.00 + custom_surcharge4: + description: "Fourth custom surcharge applied to the invoice" + type: number + example: 20.00 + type: object \ No newline at end of file diff --git a/openapi/components/schemas/invoice.yaml b/openapi/components/schemas/invoice.yaml new file mode 100644 index 000000000000..5b00cef8ad09 --- /dev/null +++ b/openapi/components/schemas/invoice.yaml @@ -0,0 +1,218 @@ + Invoice: + properties: + id: + description: 'The invoice hashed id' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: Opnel5aKBz + assigned_user_id: + description: 'The assigned user hashed id' + type: string + example: Opnel5aKBz + company_id: + description: 'The company hashed id' + type: string + example: Opnel5aKBz + client_id: + description: 'The client hashed id' + type: string + example: Opnel5aKBz + status_id: + description: 'The invoice status variable' + type: string + example: '4' + number: + description: 'The invoice number - is a unique alpha numeric number per invoice per company' + type: string + example: INV_101 + po_number: + description: 'The purchase order associated with this invoice' + type: string + example: PO-1234 + terms: + description: 'The invoice terms' + type: string + example: 'These are invoice terms' + public_notes: + description: 'The public notes of the invoice' + type: string + example: 'These are some public notes' + private_notes: + description: 'The private notes of the invoice' + type: string + example: 'These are some private notes' + footer: + description: 'The invoice footer notes' + type: string + example: '' + custom_value1: + description: 'A custom field value' + type: string + example: '2022-10-01' + custom_value2: + description: 'A custom field value' + type: string + example: 'Something custom' + custom_value3: + description: 'A custom field value' + type: string + example: '' + custom_value4: + description: 'A custom field value' + type: string + example: '' + tax_name1: + description: 'The tax name' + type: string + example: '' + tax_name2: + description: 'The tax name' + type: string + example: '' + tax_rate1: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_rate2: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_name3: + description: 'The tax name' + type: string + example: '' + tax_rate3: + description: 'The tax rate' + type: number + format: float + example: '10.00' + total_taxes: + description: 'The total taxes for the invoice' + type: number + format: float + example: '10.00' + line_items: + description: 'An array of objects which define the line items of the invoice' + type: object + example: '' + amount: + description: 'The invoice amount' + type: number + format: float + example: '10.00' + balance: + description: 'The invoice balance' + type: number + format: float + example: '10.00' + paid_to_date: + description: 'The amount paid on the invoice to date' + type: number + format: float + example: '10.00' + discount: + description: 'The invoice discount, can be an amount or a percentage' + type: number + format: float + example: '10.00' + partial: + description: 'The deposit/partial amount' + type: number + format: float + example: '10.00' + is_amount_discount: + description: 'Flag determining if the discount is an amount or a percentage' + type: boolean + example: true + is_deleted: + description: 'Defines if the invoice has been deleted' + type: boolean + example: true + uses_inclusive_taxes: + description: 'Defines the type of taxes used as either inclusive or exclusive' + type: boolean + example: true + date: + description: 'The Invoice Date' + type: string + format: date + example: '1994-07-30' + last_sent_date: + description: 'The last date the invoice was sent out' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The Next date for a reminder to be sent' + type: string + format: date + example: '1994-07-30' + partial_due_date: + description: 'The due date for the deposit/partial amount' + type: string + format: date + example: '1994-07-30' + due_date: + description: 'The due date of the invoice' + type: string + format: date + example: '1994-07-30' + settings: + $ref: '#/components/schemas/CompanySettings' + last_viewed: + description: Timestamp + type: number + format: integer + example: '1434342123' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + custom_surcharge1: + description: 'First Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge2: + description: 'Second Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge3: + description: 'Third Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge4: + description: 'Fourth Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge_tax1: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + type: object \ No newline at end of file diff --git a/openapi/components/schemas/payment.yaml b/openapi/components/schemas/payment.yaml new file mode 100644 index 000000000000..978497cac19e --- /dev/null +++ b/openapi/components/schemas/payment.yaml @@ -0,0 +1,86 @@ + Payment: + properties: + id: + description: 'The payment hashed id' + type: string + example: Opnel5aKBz + client_id: + description: 'The client hashed id' + type: string + example: Opnel5aKBz + invitation_id: + description: 'The invitation hashed id' + type: string + example: Opnel5aKBz + client_contact_id: + description: 'The client contact hashed id' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: Opnel5aKBz + type_id: + description: 'The Payment Type ID' + type: string + example: '1' + date: + description: 'The Payment date' + type: string + example: 1-1-2014 + transaction_reference: + description: 'The transaction reference as defined by the payment gateway' + type: string + example: xcsSxcs124asd + assigned_user_id: + description: 'The assigned user hashed id' + type: string + example: Opnel5aKBz + private_notes: + description: 'The private notes of the payment' + type: string + example: 'The payment was refunded due to error' + is_manual: + description: 'Flags whether the payment was made manually or processed via a gateway' + type: boolean + example: true + is_deleted: + description: 'Defines if the payment has been deleted' + type: boolean + example: true + amount: + description: 'The amount of this payment' + type: number + example: 10 + refunded: + description: 'The refunded amount of this payment' + type: number + example: 10 + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + company_gateway_id: + description: 'The company gateway id' + type: string + example: '3' + paymentables: + $ref: '#/components/schemas/Paymentable' + invoices: + description: '' + type: array + items: + $ref: '#/components/schemas/InvoicePaymentable' + credits: + description: '' + type: array + items: + $ref: '#/components/schemas/CreditPaymentable' + type: object + \ No newline at end of file diff --git a/openapi/components/schemas/payment_term.yaml b/openapi/components/schemas/payment_term.yaml new file mode 100644 index 000000000000..a69d25cb11b6 --- /dev/null +++ b/openapi/components/schemas/payment_term.yaml @@ -0,0 +1,26 @@ + PaymentTerm: + properties: + num_days: + description: 'The payment term length in days' + type: integer + example: '1' + name: + description: 'The payment term length in string format' + type: string + example: 'NET 1' + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + archived_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/paymentable.yaml b/openapi/components/schemas/paymentable.yaml new file mode 100644 index 000000000000..bb099f8d47cd --- /dev/null +++ b/openapi/components/schemas/paymentable.yaml @@ -0,0 +1,35 @@ + Paymentable: + properties: + id: + description: 'The paymentable hashed id' + type: string + example: AS3df3A + invoice_id: + description: 'The invoice hashed id' + type: string + example: AS3df3A + credit_id: + description: 'The credit hashed id' + type: string + example: AS3df3A + refunded: + description: 'The amount that has been refunded for this payment' + type: number + format: float + example: '10.00' + amount: + description: 'The amount that has been applied to the payment' + type: number + format: float + example: '10.00' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + created_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/quote.yaml b/openapi/components/schemas/quote.yaml new file mode 100644 index 000000000000..1aaea7e2c32f --- /dev/null +++ b/openapi/components/schemas/quote.yaml @@ -0,0 +1,218 @@ + Quote: + properties: + id: + description: 'The unique hashed identifier for the quote' + type: string + example: Opnel5aKBz + user_id: + description: 'The unique hashed identifier for the user who created the quote' + type: string + example: '' + assigned_user_id: + description: 'The unique hashed identifier for the user assigned to the quote' + type: string + example: '' + company_id: + description: 'The unique hashed identifier for the company associated with the quote' + type: string + example: '' + client_id: + description: 'The unique hashed identifier for the client associated with the quote' + type: string + example: '' + status_id: + description: 'The status of the quote represented by a unique identifier' + type: string + example: '' + number: + description: 'The unique alpha-numeric quote number for the quote per company' + type: string + example: QUOTE_101 + po_number: + description: 'The purchase order number associated with the quote' + type: string + example: PO-1234 + terms: + description: 'The terms and conditions for the quote' + type: string + example: 'These are some quote terms. Valid for 14 days.' + public_notes: + description: 'Publicly visible notes associated with the quote' + type: string + example: 'These are public notes which the client may see' + private_notes: + description: 'Privately visible notes associated with the quote, not disclosed to the client' + type: string + example: 'These are private notes, not to be disclosed to the client' + footer: + description: 'The footer text of the quote' + type: string + example: 'The text goes in the footer of the quote' + custom_value1: + description: 'First custom value field for additional information' + type: string + example: 'A custom value' + custom_value2: + description: 'Second custom value field for additional information' + type: string + example: 'A custom value' + custom_value3: + description: 'Third custom value field for additional information' + type: string + example: 'A custom value' + custom_value4: + description: 'Fourth custom value field for additional information' + type: string + example: 'A custom value' + tax_name1: + description: 'The name of the first tax applied to the quote' + type: string + example: GST + tax_name2: + description: 'The name of the second tax applied to the quote' + type: string + example: VAT + tax_rate1: + description: 'The rate of the first tax applied to the quote' + type: number + format: float + example: 10.00 + tax_rate2: + description: 'The rate of the second tax applied to the quote' + type: number + format: float + example: 10.00 + tax_name3: + description: 'The name of the third tax applied to the quote' + type: string + example: '' + tax_rate3: + description: 'The rate of the third tax applied to the quote' + type: number + format: float + example: 10.00 + total_taxes: + description: 'The total amount of taxes for the quote' + type: number + format: float + example: 10.00 + line_items: + description: 'An array of line items associated with the quote' + type: object + example: '' + amount: + description: 'The total amount of the quote before taxes and discounts' + type: number + format: float + example: 10.00 + balance: + description: 'The balance due for the quote after accounting for payments' + type: number + format: float + example: 10.00 + paid_to_date: + description: 'The total amount paid on the quote so far' + type: number + format: float + example: 10.00 + discount: + description: 'The discount amount or percentage applied to the quote' + type: number + format: float + example: 10.00 + partial: + description: 'The partial or deposit amount for the quote' + type: number + format: float + example: 10.00 + is_amount_discount: + description: 'Boolean flag indicating if the discount is a fixed amount or a percentage' + type: boolean + example: true + is_deleted: + description: 'Boolean flag indicating if the quote has been deleted' + type: boolean + example: false + uses_inclusive_taxes: + description: 'Boolean flag indicating if the taxes used are inclusive or exclusive' + type: boolean + example: true + date: + description: 'The date the quote was created' + type: string + format: date + example: '1994-07-30' + last_sent_date: + description: 'The last date the quote was sent to the client' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The next scheduled date for sending a reminder for the quote' + type: string + format: date + example: '1994-07-30' + partial_due_date: + description: 'The due date for the partial or deposit amount' + type: string + format: date + example: '1994-07-30' + due_date: + description: 'The due date for the total amount of the quote' + type: string + format: date + example: '1994-07-30' + settings: + $ref: '#/components/schemas/CompanySettings' + last_viewed: + description: 'The timestamp of the last time the quote was viewed' + type: number + format: integer + example: 1434342123 + updated_at: + description: 'The timestamp of the last update to the quote' + type: number + format: integer + example: 1434342123 + archived_at: + description: 'The timestamp of when the quote was archived' + type: number + format: integer + example: 1434342123 + custom_surcharge1: + description: 'First custom surcharge amount for the quote' + type: number + format: float + example: 10.00 + custom_surcharge2: + description: 'Second custom surcharge amount for the quote' + type: number + format: float + example: 10.00 + custom_surcharge3: + description: 'Third custom surcharge amount for the quote' + type: number + format: float + example: 10.00 + custom_surcharge4: + description: 'Fourth custom surcharge amount for the quote' + type: number + format: float + example: 10.00 + custom_surcharge_tax1: + description: 'Boolean flag indicating if taxes are charged on the first custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Boolean flag indicating if taxes are charged on the second custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Boolean flag indicating if taxes are charged on the third custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Boolean flag indicating if taxes are charged on the fourth custom surcharge amount' + type: boolean + example: true + type: object \ No newline at end of file diff --git a/openapi/components/schemas/recurring_expense.yaml b/openapi/components/schemas/recurring_expense.yaml new file mode 100644 index 000000000000..747b89baeff7 --- /dev/null +++ b/openapi/components/schemas/recurring_expense.yaml @@ -0,0 +1,171 @@ + RecurringExpense: + properties: + id: + description: 'The hashed id of the recurring expense' + type: string + example: Opnel5aKBz + user_id: + description: 'The hashed id of the user who created the recurring expense' + type: string + example: Opnel5aKBz + assigned_user_id: + description: 'The hashed id of the user assigned to this recurring expense' + type: string + example: Opnel5aKBz + company_id: + description: 'The hashed id of the company' + type: string + example: Opnel5aKBz + client_id: + description: 'The hashed id of the client' + type: string + example: Opnel5aKBz + invoice_id: + description: 'The hashed id of the invoice' + type: string + example: Opnel5aKBz + bank_id: + description: 'The id of the bank associated with this recurring expense' + type: string + example: '22' + invoice_currency_id: + description: 'The currency id of the invoice associated with this recurring expense' + type: string + example: '1' + expense_currency_id: + description: 'The currency id of the expense associated with this recurring expense' + type: string + example: '1' + invoice_category_id: + description: 'The category id of the invoice' + type: string + example: '1' + payment_type_id: + description: 'The payment type id' + type: string + example: '1' + private_notes: + description: 'The recurring expense private notes' + type: string + example: 'Private and confidential' + public_notes: + description: 'The recurring expense public notes' + type: string + example: 'This is the best client in the world' + transaction_reference: + description: 'The recurring expense transaction reference' + type: string + example: EXP-1223-2333 + transcation_id: + description: 'The transaction id of the recurring expense' + type: string + example: '1233312312' + custom_value1: + description: 'Custom value field' + type: string + example: $1000 + custom_value2: + description: 'Custom value field' + type: string + example: '2022-10-10' + custom_value3: + description: 'Custom value field' + type: string + example: 'short text' + custom_value4: + description: 'Custom value field' + type: string + example: 'very long text' + tax_name1: + description: 'The tax name' + type: string + example: GST + tax_name2: + description: 'The tax name' + type: string + example: VAT + tax_rate1: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_rate2: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_name3: + description: 'The tax name' + type: string + example: '' + tax_rate3: + description: 'The tax rate' + type: number + format: float + example: '10.00' + amount: + description: 'The total amount of the recurring expense' + type: number + format: float + example: '10.00' + frequency_id: + description: 'The frequency this recurring expense fires' + type: number + format: int + example: '1' + remaining_cycles: + description: 'The number of remaining cycles for this recurring expense' + type: number + format: int + example: '1' + foreign_amount: + description: 'The foreign currency amount of the recurring expense' + type: number + format: float + example: '10.00' + exchange_rate: + description: 'The exchange rate for the expernse' + type: number + format: float + example: '0.80' + date: + description: 'The date of the expense' + type: string + example: '' + payment_date: + description: 'The date the expense was paid' + type: string + example: '' + should_be_invoiced: + description: 'Boolean flag determining if the expense should be invoiced' + type: boolean + example: true + is_deleted: + description: 'Boolean flag determining if the recurring expense is deleted' + type: boolean + example: true + last_sent_date: + description: 'The Date it was sent last' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The next send date' + type: string + format: date + example: '1994-07-30' + invoice_documents: + description: 'Boolean flag determining if the documents associated with this expense should be passed onto the invoice if it is converted to an invoice' + type: boolean + example: true + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/recurring_invoice.yaml b/openapi/components/schemas/recurring_invoice.yaml new file mode 100644 index 000000000000..933592f5c04e --- /dev/null +++ b/openapi/components/schemas/recurring_invoice.yaml @@ -0,0 +1,227 @@ + RecurringInvoice: + properties: + id: + description: 'The hashed id of the recurring invoice' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: Opnel5aKBz + assigned_user_id: + description: 'The assigned user hashed id' + type: string + example: Opnel5aKBz + company_id: + description: 'The company hashed id' + type: string + example: Opnel5aKBz + client_id: + description: 'The client hashed id' + type: string + example: Opnel5aKBz + status_id: + description: 'The invoice status variable' + type: string + example: '4' + frequency_id: + description: 'The recurring invoice frequency' + type: number + example: '4' + remaining_cycles: + description: 'The number of invoices left to be generated' + type: number + example: '4' + number: + description: 'The recurringinvoice number - is a unique alpha numeric number per invoice per company' + type: string + example: INV_101 + po_number: + description: 'The purchase order associated with this recurring invoice' + type: string + example: PO-1234 + terms: + description: 'The invoice terms' + type: string + example: 'These are invoice terms' + public_notes: + description: 'The public notes of the invoice' + type: string + example: 'These are some public notes' + private_notes: + description: 'The private notes of the invoice' + type: string + example: 'These are some private notes' + footer: + description: 'The invoice footer notes' + type: string + example: '' + custom_value1: + description: 'A custom field value' + type: string + example: '2022-10-01' + custom_value2: + description: 'A custom field value' + type: string + example: 'Something custom' + custom_value3: + description: 'A custom field value' + type: string + example: '' + custom_value4: + description: 'A custom field value' + type: string + example: '' + tax_name1: + description: 'The tax name' + type: string + example: '' + tax_name2: + description: 'The tax name' + type: string + example: '' + tax_rate1: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_rate2: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_name3: + description: 'The tax name' + type: string + example: '' + tax_rate3: + description: 'The tax rate' + type: number + format: float + example: '10.00' + total_taxes: + description: 'The total taxes for the invoice' + type: number + format: float + example: '10.00' + line_items: + description: 'An array of objects which define the line items of the invoice' + type: object + example: '' + amount: + description: 'The invoice amount' + type: number + format: float + example: '10.00' + balance: + description: 'The invoice balance' + type: number + format: float + example: '10.00' + paid_to_date: + description: 'The amount paid on the invoice to date' + type: number + format: float + example: '10.00' + discount: + description: 'The invoice discount, can be an amount or a percentage' + type: number + format: float + example: '10.00' + partial: + description: 'The deposit/partial amount' + type: number + format: float + example: '10.00' + is_amount_discount: + description: 'Flag determining if the discount is an amount or a percentage' + type: boolean + example: true + is_deleted: + description: 'Defines if the invoice has been deleted' + type: boolean + example: true + uses_inclusive_taxes: + description: 'Defines the type of taxes used as either inclusive or exclusive' + type: boolean + example: true + date: + description: 'The Invoice Date' + type: string + format: date + example: '1994-07-30' + last_sent_date: + description: 'The last date the invoice was sent out' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The Next date for a reminder to be sent' + type: string + format: date + example: '1994-07-30' + partial_due_date: + description: 'The due date for the deposit/partial amount' + type: string + format: date + example: '1994-07-30' + due_date: + description: 'The due date of the invoice' + type: string + format: date + example: '1994-07-30' + settings: + $ref: '#/components/schemas/CompanySettings' + last_viewed: + description: Timestamp + type: number + format: integer + example: '1434342123' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + custom_surcharge1: + description: 'First Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge2: + description: 'Second Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge3: + description: 'Third Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge4: + description: 'Fourth Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge_tax1: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + type: object + \ No newline at end of file diff --git a/openapi/components/schemas/recurring_quote.yaml b/openapi/components/schemas/recurring_quote.yaml new file mode 100644 index 000000000000..98e67953cd73 --- /dev/null +++ b/openapi/components/schemas/recurring_quote.yaml @@ -0,0 +1,226 @@ + RecurringQuote: + properties: + id: + description: 'The hashed id of the recurring quote' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: Opnel5aKBz + assigned_user_id: + description: 'The assigned user hashed id' + type: string + example: Opnel5aKBz + company_id: + description: 'The company hashed id' + type: string + example: Opnel5aKBz + client_id: + description: 'The client hashed id' + type: string + example: Opnel5aKBz + status_id: + description: 'The quote status variable' + type: string + example: '4' + frequency_id: + description: 'The recurring quote frequency' + type: number + example: '4' + remaining_cycles: + description: 'The number of quotes left to be generated' + type: number + example: '4' + number: + description: 'The recurringquote number - is a unique alpha numeric number per quote per company' + type: string + example: INV_101 + po_number: + description: 'The purchase order associated with this recurring quote' + type: string + example: PO-1234 + terms: + description: 'The quote terms' + type: string + example: 'These are quote terms' + public_notes: + description: 'The public notes of the quote' + type: string + example: 'These are some public notes' + private_notes: + description: 'The private notes of the quote' + type: string + example: 'These are some private notes' + footer: + description: 'The quote footer notes' + type: string + example: '' + custom_value1: + description: 'A custom field value' + type: string + example: '2022-10-01' + custom_value2: + description: 'A custom field value' + type: string + example: 'Something custom' + custom_value3: + description: 'A custom field value' + type: string + example: '' + custom_value4: + description: 'A custom field value' + type: string + example: '' + tax_name1: + description: 'The tax name' + type: string + example: '' + tax_name2: + description: 'The tax name' + type: string + example: '' + tax_rate1: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_rate2: + description: 'The tax rate' + type: number + format: float + example: '10.00' + tax_name3: + description: 'The tax name' + type: string + example: '' + tax_rate3: + description: 'The tax rate' + type: number + format: float + example: '10.00' + total_taxes: + description: 'The total taxes for the quote' + type: number + format: float + example: '10.00' + line_items: + description: 'An array of objects which define the line items of the quote' + type: object + example: '' + amount: + description: 'The quote amount' + type: number + format: float + example: '10.00' + balance: + description: 'The quote balance' + type: number + format: float + example: '10.00' + paid_to_date: + description: 'The amount paid on the quote to date' + type: number + format: float + example: '10.00' + discount: + description: 'The quote discount, can be an amount or a percentage' + type: number + format: float + example: '10.00' + partial: + description: 'The deposit/partial amount' + type: number + format: float + example: '10.00' + is_amount_discount: + description: 'Flag determining if the discount is an amount or a percentage' + type: boolean + example: true + is_deleted: + description: 'Defines if the quote has been deleted' + type: boolean + example: true + uses_inclusive_taxes: + description: 'Defines the type of taxes used as either inclusive or exclusive' + type: boolean + example: true + date: + description: 'The quote Date' + type: string + format: date + example: '1994-07-30' + last_sent_date: + description: 'The last date the quote was sent out' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The Next date for a reminder to be sent' + type: string + format: date + example: '1994-07-30' + partial_due_date: + description: 'The due date for the deposit/partial amount' + type: string + format: date + example: '1994-07-30' + due_date: + description: 'The due date of the quote' + type: string + format: date + example: '1994-07-30' + settings: + $ref: '#/components/schemas/CompanySettings' + last_viewed: + description: Timestamp + type: number + format: integer + example: '1434342123' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + custom_surcharge1: + description: 'First Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge2: + description: 'Second Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge3: + description: 'Third Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge4: + description: 'Fourth Custom Surcharge' + type: number + format: float + example: '10.00' + custom_surcharge_tax1: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Toggles charging taxes on custom surcharge amounts' + type: boolean + example: true + type: object \ No newline at end of file diff --git a/openapi/components/schemas/subscription.yaml b/openapi/components/schemas/subscription.yaml new file mode 100644 index 000000000000..da8346dcfbc5 --- /dev/null +++ b/openapi/components/schemas/subscription.yaml @@ -0,0 +1,111 @@ + Subscription: + properties: + id: + description: Unique identifier for the subscription + type: string + example: Opnel5aKBz + user_id: + description: Unique identifier for the user associated with the subscription + type: string + example: Ua6Rw4pVbS + product_id: + description: Unique identifier for the product associated with the subscription + type: string + example: Pr5Ft7yBmC + company_id: + description: Unique identifier for the company associated with the subscription + type: string + example: Co7Vn3yLmW + recurring_invoice_id: + description: Unique identifier for the recurring invoice associated with the subscription + type: string + example: Ri2Yt8zJkP + is_recurring: + description: Indicates whether the subscription is recurring + type: boolean + example: 'true' + frequency_id: + description: 'integer const representation of the frequency' + type: string + example: '1' + auto_bill: + description: 'enum setting' + type: string + example: always + promo_code: + description: Promotional code applied to the subscription + type: string + example: PROMOCODE4U + promo_discount: + description: Discount percentage or amount applied to the subscription + type: number + example: 10 + is_amount_discount: + description: Indicates whether the discount is a fixed amount + type: boolean + example: 'true' + allow_cancellation: + description: Indicates whether the subscription can be cancelled + type: boolean + example: 'true' + per_seat_enabled: + description: Indicates whether the subscription pricing is per seat + type: boolean + example: 'true' + currency_id: + description: Unique identifier for the currency used in the subscription + type: integer + example: '1' + max_seats_limit: + description: Maximum number of seats allowed for the subscription + type: integer + example: '100' + trial_enabled: + description: Indicates whether the subscription has a trial period + type: boolean + example: 'true' + trial_duration: + description: Duration of the trial period in days + type: integer + example: '14' + allow_query_overrides: + description: Indicates whether query overrides are allowed for the subscription + type: boolean + example: 'true' + allow_plan_changes: + description: Indicates whether plan changes are allowed for the subscription + type: boolean + example: 'true' + refund_period: + description: Number of days within which refunds can be requested + type: integer + example: '30' + webhook_configuration: + description: Webhook configuration for the subscription + type: string + example: 'expand reference for this' + is_deleted: + description: Indicates whether the subscription has been deleted + type: boolean + example: 'false' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + type: object + BulkAction: + type: array + items: + type: integer + example: '[0,1,2,3,]' \ No newline at end of file diff --git a/openapi/components/schemas/system_log.yaml b/openapi/components/schemas/system_log.yaml new file mode 100644 index 000000000000..cdce0ebd4b62 --- /dev/null +++ b/openapi/components/schemas/system_log.yaml @@ -0,0 +1,43 @@ + SystemLog: + properties: + id: + description: 'The account hashed id' + type: string + example: AS3df3A + company_id: + description: 'The company hashed id' + type: string + example: AS3df3A + user_id: + description: 'The user_id hashed id' + type: string + example: AS3df3A + client_id: + description: 'The client_id hashed id' + type: string + example: AS3df3A + event_id: + description: 'The Log Type ID' + type: integer + example: 1 + category_id: + description: 'The Category Type ID' + type: integer + example: 1 + type_id: + description: 'The Type Type ID' + type: integer + example: 1 + log: + description: 'The json object of the error' + type: object + example: '{''key'':''value''}' + updated_at: + description: Timestamp + type: string + example: '2' + created_at: + description: Timestamp + type: string + example: '2' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/task.yaml b/openapi/components/schemas/task.yaml new file mode 100644 index 000000000000..a1968dc1d572 --- /dev/null +++ b/openapi/components/schemas/task.yaml @@ -0,0 +1,94 @@ + Task: + properties: + id: + description: 'The hashed id of the task' + type: string + example: Opnel5aKBz + user_id: + description: 'The hashed id of the user who created the task' + type: string + example: Opnel5aKBz + assigned_user_id: + description: 'The assigned user of the task' + type: string + example: Opnel5aKBz + company_id: + description: 'The hashed id of the company' + type: string + example: Opnel5aKBz + client_id: + description: 'The hashed if of the client' + type: string + example: Opnel5aKBz + invoice_id: + description: 'The hashed id of the invoice associated with the task' + type: string + example: Opnel5aKBz + project_id: + description: 'The hashed id of the project associated with the task' + type: string + example: Opnel5aKBz + number: + description: 'The number of the task' + type: string + example: TASK-123 + time_log: + description: 'An array of unix time stamps defining the start and end times of the task' + type: string + example: '[[1,2],[3,4]]' + is_running: + description: 'Determines if the task is still running' + type: boolean + example: true + is_deleted: + description: 'Boolean flag determining if the task has been deleted' + type: boolean + example: true + task_status_id: + description: 'The hashed id of the task status' + type: string + example: Opnel5aKBz + description: + description: 'The task description' + type: string + example: 'A wonder task to work on' + duration: + description: 'The task duration' + type: integer + example: '' + task_status_order: + description: 'The order of the task' + type: integer + example: '4' + custom_value1: + description: 'A custom value' + type: string + example: '2022-10-10' + custom_value2: + description: 'A custom value' + type: string + example: $1100 + custom_value3: + description: 'A custom value' + type: string + example: 'I need help' + custom_value4: + description: 'A custom value' + type: string + example: INV-3343 + created_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + updated_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + archived_at: + description: Timestamp + type: number + format: integer + example: '1434342123' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/user.yaml b/openapi/components/schemas/user.yaml new file mode 100644 index 000000000000..10c5fd6def26 --- /dev/null +++ b/openapi/components/schemas/user.yaml @@ -0,0 +1,43 @@ + User: + properties: + id: + description: 'The hashed id of the user' + type: string + example: Opnel5aKBz + first_name: + description: 'The first name of the user' + type: string + example: Brad + last_name: + description: 'The last name of the user' + type: string + example: Pitt + email: + description: 'The users email address' + type: string + example: brad@pitt.com + phone: + description: 'The users phone number' + type: string + example: 555-1233-23232 + signature: + description: 'The users sign off signature' + type: string + example: 'Have a nice day!' + avatar: + description: 'The users avatar' + type: string + example: 'https://url.to.your/avatar.png' + accepted_terms_version: + description: 'The version of the invoice ninja terms that has been accepted by the user' + type: string + example: 1.0.1 + oauth_user_id: + description: 'The provider id of the oauth entity' + type: string + example: jkhasdf789as6f675sdf768sdfs + oauth_provider_id: + description: 'The oauth entity id' + type: string + example: google + type: object \ No newline at end of file diff --git a/openapi/components/schemas/vendor.yaml b/openapi/components/schemas/vendor.yaml new file mode 100644 index 000000000000..2d8413a6e0b9 --- /dev/null +++ b/openapi/components/schemas/vendor.yaml @@ -0,0 +1,128 @@ + Vendor: + properties: + id: + description: 'The hashed id of the vendor' + type: string + example: Opnel5aKBz + user_id: + description: 'The hashed id of the user who created the vendor' + type: string + example: Opnel5aKBz + assigned_user_id: + description: 'The hashed id of the assigned user to this vendor' + type: string + example: Opnel5aKBz + company_id: + description: 'The hashed id of the company' + type: string + example: Opnel5aKBz + client_id: + description: 'The hashed id of the client' + type: string + example: Opnel5aKBz + contacts: + type: array + items: + $ref: '#/components/schemas/VendorContact' + name: + description: 'The vendor name' + type: string + example: 'Harry''s cafe de wheels' + website: + description: 'The website of the vendor' + type: string + example: www.harry.com + private_notes: + description: 'The private notes of the vendor' + type: string + example: 'Shhh, don''t tell the vendor' + industry_id: + description: 'The industry id of the vendor' + type: string + example: '1' + size_id: + description: ________ + type: string + example: '' + address1: + description: ________ + type: string + example: '' + address2: + description: ________ + type: string + example: '' + city: + description: ________ + type: string + example: '' + state: + description: ________ + type: string + example: '' + postal_code: + description: ________ + type: string + example: '' + phone: + description: 'The client phone number' + type: string + example: 555-3434-3434 + country_id: + description: ________ + type: string + example: '' + currency_id: + description: ________ + type: string + example: '4' + custom_value1: + description: ________ + type: string + example: '' + custom_value2: + description: ________ + type: string + example: '' + custom_value3: + description: ________ + type: string + example: '' + custom_value4: + description: ________ + type: string + example: '' + vat_number: + description: ________ + type: string + example: '' + id_number: + description: ________ + type: string + example: '' + number: + description: ________ + type: string + example: '' + is_deleted: + description: ________ + type: boolean + example: true + last_login: + description: Timestamp + type: number + format: integer + example: '134341234234' + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + settings: + $ref: '#/components/schemas/CompanySettings' + type: object \ No newline at end of file diff --git a/openapi/components/schemas/vendor_contact.yaml b/openapi/components/schemas/vendor_contact.yaml new file mode 100644 index 000000000000..6e9e6934c90f --- /dev/null +++ b/openapi/components/schemas/vendor_contact.yaml @@ -0,0 +1,70 @@ + VendorContact: + properties: + id: + description: 'The hashed id of the vendor contact' + type: string + example: Opnel5aKBz + user_id: + description: 'The hashed id of the user id' + type: string + example: Opnel5aKBz + company_id: + description: 'The hashed id of the company' + type: string + example: Opnel5aKBz + vendor_id: + description: 'The hashed id of the vendor' + type: string + example: Opnel5aKBz + first_name: + description: 'The first name of the contact' + type: string + example: Harry + last_name: + description: 'The last name of the contact' + type: string + example: Windsor + phone: + description: 'The contacts phone number' + type: string + example: 555-123-1234 + custom_value1: + description: 'A custom value' + type: string + example: '2022-10-10' + custom_value2: + description: 'A custom value' + type: string + example: $1000 + custom_value3: + description: 'A custom value' + type: string + example: '' + custom_value4: + description: 'A custom value' + type: string + example: '' + email: + description: 'The contact email address' + type: string + example: harry@windsor.com + is_primary: + description: 'Boolean flag determining if the contact is the primary contact for the vendor' + type: boolean + example: true + created_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + updated_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + deleted_at: + description: Timestamp + type: number + format: integer + example: '134341234234' + type: object \ No newline at end of file From 30c64b64b9b0889b79a56a6533f96da728818f25 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Mar 2023 11:15:52 +1100 Subject: [PATCH 16/32] Updates for openapi definitions --- openapi/api-docs.yaml | 589 ++++++++++++++++-- openapi/components/schemas.yaml | 33 +- openapi/components/schemas/credit.yaml | 7 +- openapi/components/schemas/invoice.yaml | 6 +- openapi/components/schemas/invoice_item.yaml | 83 +++ openapi/components/schemas/payment.yaml | 4 + openapi/components/schemas/product.yaml | 138 ++++ openapi/components/schemas/project.yaml | 88 +++ .../components/schemas/purchase_order.yaml | 220 +++++++ openapi/components/schemas/quote.yaml | 7 +- 10 files changed, 1099 insertions(+), 76 deletions(-) create mode 100644 openapi/components/schemas/invoice_item.yaml create mode 100644 openapi/components/schemas/product.yaml create mode 100644 openapi/components/schemas/project.yaml create mode 100644 openapi/components/schemas/purchase_order.yaml diff --git a/openapi/api-docs.yaml b/openapi/api-docs.yaml index 7498ad9ac37d..7531e69a90ce 100644 --- a/openapi/api-docs.yaml +++ b/openapi/api-docs.yaml @@ -13312,36 +13312,9 @@ components: - Product: - properties: - id: - description: 'The product hashed id' - type: string - example: Opnel5aKBz - type: object - Project: - properties: - id: - description: 'The project hashed id' - type: string - example: Opnel5aKBz - name: - description: 'The project name' - type: string - example: 'New Project' - type: object - PurchaseOrder: - properties: - id: - description: 'The purchase order hashed id' - type: string - example: Opnel5aKBz - type: object - - - - - + + + TaskSchedulerSchema: properties: paused: @@ -14193,9 +14166,10 @@ components: format: float example: 23.00 line_items: - description: "The array of line items included in the credit" - type: object - example: "[{item1}, {item2}]" + type: array + description: 'An array of objects which define the line items of the credit' + items: + $ref: '#/components/schemas/InvoiceItem' amount: description: "The total amount of the credit" type: number @@ -14740,9 +14714,11 @@ components: format: float example: '10.00' line_items: + type: array description: 'An array of objects which define the line items of the invoice' - type: object - example: '' + items: + $ref: '#/components/schemas/InvoiceItem' + amount: description: 'The invoice amount' type: number @@ -16075,6 +16051,10 @@ components: type: array items: $ref: '#/components/schemas/CreditPaymentable' + number: + description: 'The payment number - is a unique alpha numeric number per payment per company' + type: string + example: PAY_101 type: object User: @@ -16120,6 +16100,178 @@ components: type: string example: google type: object + Project: + type: object + properties: + id: + description: 'The project hashed id' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: Opnel5aKBz + assigned_user_id: + description: The assigned user identifier associated with the project + type: string + example: Opnel5aKBz + client_id: + type: string + example: Opnel5aKBz + description: The client identifier associated with the project + name: + type: string + description: The name of the project + example: 'New Project' + task_rate: + type: number + format: float + example: 10 + description: The default rate per task for the project + due_date: + type: string + format: date + example: '2019-01-01' + description: The due date for the project + private_notes: + type: string + description: Private notes associated with the project + budgeted_hours: + type: number + format: float + description: The number of budgeted hours for the project + custom_value1: + type: string + description: Custom value field 1 + custom_value2: + type: string + description: Custom value field 2 + custom_value3: + type: string + description: Custom value field 3 + custom_value4: + type: string + description: Custom value field 4 + created_at: + type: number + format: integer + example: 134341234234 + description: The timestamp of the project creation + updated_at: + type: number + format: integer + example: 134341234234 + description: The timestamp of the last project update + archived_at: + type: number + format: integer + example: 134341234234 + description: The timestamp of the project deletion + public_notes: + type: string + description: Public notes associated with the project + is_deleted: + type: boolean + description: A flag indicating if the project is deleted + number: + type: string + description: The project number + color: + type: string + description: The color associated with the project + required: + - id + - user_id + - company_id + - name + - task_rate + - budgeted_hours + - is_deleted + - color + + InvoiceItem: + type: object + properties: + quantity: + type: integer + example: 1 + cost: + type: number + format: float + example: 10.00 + product_key: + type: string + example: 'Product key' + product_cost: + type: number + format: float + example: 10.00 + notes: + type: string + example: 'Item notes' + discount: + type: number + format: float + example: 5.00 + is_amount_discount: + type: boolean + example: false + tax_name1: + type: string + example: 'Tax name 1' + tax_rate1: + type: number + format: float + example: 10.00 + tax_name2: + type: string + example: 'Tax name 2' + tax_rate2: + type: number + format: float + example: 5.00 + tax_name3: + type: string + example: 'Tax name 3' + tax_rate3: + type: number + format: float + example: 3.00 + sort_id: + type: string + example: '0' + line_total: + type: number + format: float + example: 10.00 + gross_line_total: + type: number + format: float + example: 15.00 + tax_amount: + type: number + format: float + example: 1.00 + date: + type: string + format: date-time + example: '2023-03-19T00:00:00Z' + custom_value1: + type: string + example: 'Custom value 1' + custom_value2: + type: string + example: 'Custom value 2' + custom_value3: + type: string + example: 'Custom value 3' + custom_value4: + type: string + example: 'Custom value 4' + type_id: + type: string + example: '1' + description: '1 = product, 2 = service, 3 unpaid gateway fee, 4 paid gateway fee, 5 late fee, 6 expense' CompanyUser: properties: permissions: @@ -16842,6 +16994,227 @@ components: format: integer example: '1434342123' type: object + PurchaseOrder: + properties: + id: + description: 'The unique hashed identifier for the purchase order' + type: string + example: Opnel5aKBz + user_id: + description: 'The unique hashed identifier for the user who created the purchase order' + type: string + example: '' + assigned_user_id: + description: 'The unique hashed identifier for the user assigned to the purchase order' + type: string + example: '' + company_id: + description: 'The unique hashed identifier for the company associated with the purchase order' + type: string + example: '' + vendor_id: + description: 'The unique hashed identifier for the vendor associated with the purchase order' + type: string + example: '' + status_id: + description: 'The status of the purchase order represented by a unique identifier' + type: string + example: '' + number: + description: 'The unique alpha-numeric purchase order number per company' + type: string + example: PO_101 + quote_number: + description: 'The quote number associated with this purchase order' + type: string + example: QUOTE_101 + terms: + description: 'The terms and conditions for the purchase order' + type: string + example: 'These are some purchase order terms. Valid for 14 days.' + public_notes: + description: 'Publicly visible notes associated with the purchase order' + type: string + example: 'These are public notes which the vendor may see' + private_notes: + description: 'Privately visible notes associated with the purchase order, not disclosed to the vendor' + type: string + example: 'These are private notes, not to be disclosed to the vendor' + footer: + description: 'The footer text of the purchase order' + type: string + example: 'The text goes in the footer of the purchase order' + custom_value1: + description: 'First custom value field for additional information' + type: string + example: 'A custom value' + custom_value2: + description: 'Second custom value field for additional information' + type: string + example: 'A custom value' + custom_value3: + description: 'Third custom value field for additional information' + type: string + example: 'A custom value' + custom_value4: + description: 'Fourth custom value field for additional information' + type: string + example: 'A custom value' + tax_name1: + description: 'The name of the first tax applied to the purchase order' + type: string + example: GST + tax_name2: + description: 'The name of the second tax applied to the purchase order' + type: string + example: VAT + tax_rate1: + description: 'The rate of the first tax applied to the purchase order' + type: number + format: float + example: 10.00 + tax_rate2: + description: 'The rate of the second tax applied to the purchase order' + type: number + format: float + example: 10.00 + tax_name3: + description: 'The name of the third tax applied to the purchase order' + type: string + example: '' + tax_rate3: + description: 'The rate of the third tax applied to the purchase order' + type: number + format: float + example: 10.00 + total_taxes: + description: 'The total amount of taxes applied to the purchase order' + type: number + format: float + example: 10.00 + line_items: + type: array + description: 'An array of objects which define the line items of the purchase order' + items: + $ref: '#/components/schemas/InvoiceItem' + amount: + description: 'The total amount of the purchase order before taxes and discounts' + type: number + format: float + example: 10.00 + balance: + description: 'The balance due for the purchase order after accounting for payments' + type: number + format: float + example: 10.00 + paid_to_date: + description: 'The total amount paid on the purchase order so far' + type: number + format: float + example: 10.00 + discount: + description: 'The discount amount or percentage applied to the purchase order' + type: number + format: float + example: 10.00 + partial: + description: 'The partial or deposit amount for the purchase order' + type: number + format: float + example: 10.00 + is_amount_discount: + description: 'Boolean flag indicating if the discount is a fixed amount or a percentage' + type: boolean + example: true + is_deleted: + description: 'Boolean flag indicating if the purchase order has been deleted' + type: boolean + example: false + uses_inclusive_taxes: + description: 'Boolean flag indicating if the taxes used are inclusive or exclusive' + type: boolean + example: true + date: + description: 'The date the purchase order was created' + type: string + format: date + example: '1994-07-30' + last_sent_date: + description: 'The last date the purchase order was sent to the vendor' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The next scheduled date for sending a reminder for the purchase order' + type: string + format: date + example: '1994-07-30' + partial_due_date: + description: 'The due date for the partial or deposit amount' + type: string + format: date + example: '1994-07-30' + due_date: + description: 'The due date for the total amount of the purchase order' + type: string + format: date + example: '1994-07-30' + settings: + $ref: '#/components/schemas/CompanySettings' + last_viewed: + description: Timestamp + type: number + format: integer + example: 1434342123 + updated_at: + description: Timestamp + type: number + format: integer + example: 1434342123 + archived_at: + description: Timestamp + type: number + format: integer + example: 1434342123 + custom_surcharge1: + description: 'First custom surcharge amount for the purchase order' + type: number + format: float + example: 10.00 + custom_surcharge2: + description: 'Second custom surcharge amount for the purchase order' + type: number + format: float + example: 10.00 + custom_surcharge3: + description: 'Third custom surcharge amount for the purchase order' + type: number + format: float + example: 10.00 + custom_surcharge4: + description: 'Fourth custom surcharge amount for the purchase order' + type: number + format: float + example: 10.00 + custom_surcharge_tax1: + description: 'Boolean flag indicating if taxes are charged on the first custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Boolean flag indicating if taxes are charged on the second custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Boolean flag indicating if taxes are charged on the third custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Boolean flag indicating if taxes are charged on the fourth custom surcharge amount' + type: boolean + example: true + type: object + + ClientContact: properties: id: @@ -16986,6 +17359,145 @@ components: type: boolean example: 'true' type: object + Product: + type: object + properties: + id: + type: string + description: 'The hashed product ID.' + example: eP01N + company_id: + type: string + description: 'The hashed ID of the company that owns this product.' + example: eP01N + user_id: + type: string + description: 'The hashed ID of the user that created this product.' + example: n30m4 + assigned_user_id: + type: string + description: 'The hashed ID of the user assigned to this product.' + example: pR0j3 + project_id: + type: string + description: 'The hashed ID of the project that this product is associated with.' + example: pR0j3 + vendor_id: + type: string + description: 'The hashed ID of the vendor that this product is associated with.' + example: pR0j3 + custom_value1: + type: string + description: 'Custom value field 1.' + example: 'Custom value 1' + custom_value2: + type: string + description: 'Custom value field 2.' + example: 'Custom value 2' + custom_value3: + type: string + description: 'Custom value field 3.' + example: 'Custom value 3' + custom_value4: + type: string + description: 'Custom value field 4.' + example: 'Custom value 4' + product_key: + type: string + description: 'The product key.' + example: '1234' + notes: + type: string + description: 'Notes about the product.' + example: 'These are some notes about the product.' + cost: + type: number + format: float + description: 'The cost of the product.' + example: 10.0 + price: + type: number + format: float + description: 'The price of the product.' + example: 20.0 + quantity: + type: number + format: float + description: 'The quantity of the product.' + example: 5.0 + tax_name1: + type: string + description: 'The name of tax 1.' + example: 'Tax 1' + tax_rate1: + type: number + format: float + description: 'The rate of tax 1.' + example: 10.0 + tax_name2: + type: string + description: 'The name of tax 2.' + example: 'Tax 2' + tax_rate2: + type: number + format: float + description: 'The rate of tax 2.' + example: 5.0 + tax_name3: + type: string + description: 'The name of tax 3.' + example: 'Tax 3' + tax_rate3: + type: number + format: float + description: 'The rate of tax 3.' + example: 0.0 + archived_at: + type: integer + format: timestamp + description: 'The timestamp when the product was archived.' + example: '2022-03-18T15:00:00Z' + created_at: + type: integer + format: timestamp + description: 'The timestamp when the product was created.' + example: '2022-03-18T15:00:00Z' + updated_at: + description: Timestamp + type: integer + format: timestamp + example: '2022-03-18T12:34:56.789Z' + is_deleted: + type: boolean + description: 'Boolean flag determining if the product has been deleted' + example: false + in_stock_quantity: + type: integer + format: int32 + description: The quantity of the product that is currently in stock + default: 0 + + stock_notification: + type: boolean + description: Indicates whether stock notifications are enabled for this product + default: true + + stock_notification_threshold: + type: integer + format: int32 + description: The minimum quantity threshold for which stock notifications will be triggered + default: 0 + + max_quantity: + type: integer + format: int32 + description: The maximum quantity that can be ordered for this product + + product_image: + type: string + description: The URL of the product image + format: uri-reference + Quote: properties: id: @@ -17085,9 +17597,10 @@ components: format: float example: 10.00 line_items: - description: 'An array of line items associated with the quote' - type: object - example: '' + type: array + description: 'An array of objects which define the line items of the quote' + items: + $ref: '#/components/schemas/InvoiceItem' amount: description: 'The total amount of the quote before taxes and discounts' type: number diff --git a/openapi/components/schemas.yaml b/openapi/components/schemas.yaml index 54ea8bb76f32..3a579727752c 100644 --- a/openapi/components/schemas.yaml +++ b/openapi/components/schemas.yaml @@ -72,36 +72,9 @@ - Product: - properties: - id: - description: 'The product hashed id' - type: string - example: Opnel5aKBz - type: object - Project: - properties: - id: - description: 'The project hashed id' - type: string - example: Opnel5aKBz - name: - description: 'The project name' - type: string - example: 'New Project' - type: object - PurchaseOrder: - properties: - id: - description: 'The purchase order hashed id' - type: string - example: Opnel5aKBz - type: object - - - - - + + + TaskSchedulerSchema: properties: paused: diff --git a/openapi/components/schemas/credit.yaml b/openapi/components/schemas/credit.yaml index 54df65e21de2..bc06f457ea1d 100644 --- a/openapi/components/schemas/credit.yaml +++ b/openapi/components/schemas/credit.yaml @@ -101,9 +101,10 @@ format: float example: 23.00 line_items: - description: "The array of line items included in the credit" - type: object - example: "[{item1}, {item2}]" + type: array + description: 'An array of objects which define the line items of the credit' + items: + $ref: '#/components/schemas/InvoiceItem' amount: description: "The total amount of the credit" type: number diff --git a/openapi/components/schemas/invoice.yaml b/openapi/components/schemas/invoice.yaml index 5b00cef8ad09..6a09eb246788 100644 --- a/openapi/components/schemas/invoice.yaml +++ b/openapi/components/schemas/invoice.yaml @@ -97,9 +97,11 @@ format: float example: '10.00' line_items: + type: array description: 'An array of objects which define the line items of the invoice' - type: object - example: '' + items: + $ref: '#/components/schemas/InvoiceItem' + amount: description: 'The invoice amount' type: number diff --git a/openapi/components/schemas/invoice_item.yaml b/openapi/components/schemas/invoice_item.yaml new file mode 100644 index 000000000000..94c512f49e1b --- /dev/null +++ b/openapi/components/schemas/invoice_item.yaml @@ -0,0 +1,83 @@ + InvoiceItem: + type: object + properties: + quantity: + type: integer + example: 1 + cost: + type: number + format: float + example: 10.00 + product_key: + type: string + example: 'Product key' + product_cost: + type: number + format: float + example: 10.00 + notes: + type: string + example: 'Item notes' + discount: + type: number + format: float + example: 5.00 + is_amount_discount: + type: boolean + example: false + tax_name1: + type: string + example: 'Tax name 1' + tax_rate1: + type: number + format: float + example: 10.00 + tax_name2: + type: string + example: 'Tax name 2' + tax_rate2: + type: number + format: float + example: 5.00 + tax_name3: + type: string + example: 'Tax name 3' + tax_rate3: + type: number + format: float + example: 3.00 + sort_id: + type: string + example: '0' + line_total: + type: number + format: float + example: 10.00 + gross_line_total: + type: number + format: float + example: 15.00 + tax_amount: + type: number + format: float + example: 1.00 + date: + type: string + format: date-time + example: '2023-03-19T00:00:00Z' + custom_value1: + type: string + example: 'Custom value 1' + custom_value2: + type: string + example: 'Custom value 2' + custom_value3: + type: string + example: 'Custom value 3' + custom_value4: + type: string + example: 'Custom value 4' + type_id: + type: string + example: '1' + description: '1 = product, 2 = service, 3 unpaid gateway fee, 4 paid gateway fee, 5 late fee, 6 expense' \ No newline at end of file diff --git a/openapi/components/schemas/payment.yaml b/openapi/components/schemas/payment.yaml index 978497cac19e..d9c3f437f68d 100644 --- a/openapi/components/schemas/payment.yaml +++ b/openapi/components/schemas/payment.yaml @@ -82,5 +82,9 @@ type: array items: $ref: '#/components/schemas/CreditPaymentable' + number: + description: 'The payment number - is a unique alpha numeric number per payment per company' + type: string + example: PAY_101 type: object \ No newline at end of file diff --git a/openapi/components/schemas/product.yaml b/openapi/components/schemas/product.yaml new file mode 100644 index 000000000000..34fe77b8d77a --- /dev/null +++ b/openapi/components/schemas/product.yaml @@ -0,0 +1,138 @@ + Product: + type: object + properties: + id: + type: string + description: 'The hashed product ID.' + example: eP01N + company_id: + type: string + description: 'The hashed ID of the company that owns this product.' + example: eP01N + user_id: + type: string + description: 'The hashed ID of the user that created this product.' + example: n30m4 + assigned_user_id: + type: string + description: 'The hashed ID of the user assigned to this product.' + example: pR0j3 + project_id: + type: string + description: 'The hashed ID of the project that this product is associated with.' + example: pR0j3 + vendor_id: + type: string + description: 'The hashed ID of the vendor that this product is associated with.' + example: pR0j3 + custom_value1: + type: string + description: 'Custom value field 1.' + example: 'Custom value 1' + custom_value2: + type: string + description: 'Custom value field 2.' + example: 'Custom value 2' + custom_value3: + type: string + description: 'Custom value field 3.' + example: 'Custom value 3' + custom_value4: + type: string + description: 'Custom value field 4.' + example: 'Custom value 4' + product_key: + type: string + description: 'The product key.' + example: '1234' + notes: + type: string + description: 'Notes about the product.' + example: 'These are some notes about the product.' + cost: + type: number + format: float + description: 'The cost of the product.' + example: 10.0 + price: + type: number + format: float + description: 'The price of the product.' + example: 20.0 + quantity: + type: number + format: float + description: 'The quantity of the product.' + example: 5.0 + tax_name1: + type: string + description: 'The name of tax 1.' + example: 'Tax 1' + tax_rate1: + type: number + format: float + description: 'The rate of tax 1.' + example: 10.0 + tax_name2: + type: string + description: 'The name of tax 2.' + example: 'Tax 2' + tax_rate2: + type: number + format: float + description: 'The rate of tax 2.' + example: 5.0 + tax_name3: + type: string + description: 'The name of tax 3.' + example: 'Tax 3' + tax_rate3: + type: number + format: float + description: 'The rate of tax 3.' + example: 0.0 + archived_at: + type: integer + format: timestamp + description: 'The timestamp when the product was archived.' + example: '2022-03-18T15:00:00Z' + created_at: + type: integer + format: timestamp + description: 'The timestamp when the product was created.' + example: '2022-03-18T15:00:00Z' + updated_at: + description: Timestamp + type: integer + format: timestamp + example: '2022-03-18T12:34:56.789Z' + is_deleted: + type: boolean + description: 'Boolean flag determining if the product has been deleted' + example: false + in_stock_quantity: + type: integer + format: int32 + description: The quantity of the product that is currently in stock + default: 0 + + stock_notification: + type: boolean + description: Indicates whether stock notifications are enabled for this product + default: true + + stock_notification_threshold: + type: integer + format: int32 + description: The minimum quantity threshold for which stock notifications will be triggered + default: 0 + + max_quantity: + type: integer + format: int32 + description: The maximum quantity that can be ordered for this product + + product_image: + type: string + description: The URL of the product image + format: uri-reference diff --git a/openapi/components/schemas/project.yaml b/openapi/components/schemas/project.yaml new file mode 100644 index 000000000000..3588dbb4610e --- /dev/null +++ b/openapi/components/schemas/project.yaml @@ -0,0 +1,88 @@ + Project: + type: object + properties: + id: + description: 'The project hashed id' + type: string + example: Opnel5aKBz + user_id: + description: 'The user hashed id' + type: string + example: Opnel5aKBz + assigned_user_id: + description: The assigned user identifier associated with the project + type: string + example: Opnel5aKBz + client_id: + type: string + example: Opnel5aKBz + description: The client identifier associated with the project + name: + type: string + description: The name of the project + example: 'New Project' + task_rate: + type: number + format: float + example: 10 + description: The default rate per task for the project + due_date: + type: string + format: date + example: '2019-01-01' + description: The due date for the project + private_notes: + type: string + description: Private notes associated with the project + budgeted_hours: + type: number + format: float + description: The number of budgeted hours for the project + custom_value1: + type: string + description: Custom value field 1 + custom_value2: + type: string + description: Custom value field 2 + custom_value3: + type: string + description: Custom value field 3 + custom_value4: + type: string + description: Custom value field 4 + created_at: + type: number + format: integer + example: 134341234234 + description: The timestamp of the project creation + updated_at: + type: number + format: integer + example: 134341234234 + description: The timestamp of the last project update + archived_at: + type: number + format: integer + example: 134341234234 + description: The timestamp of the project deletion + public_notes: + type: string + description: Public notes associated with the project + is_deleted: + type: boolean + description: A flag indicating if the project is deleted + number: + type: string + description: The project number + color: + type: string + description: The color associated with the project + required: + - id + - user_id + - company_id + - name + - task_rate + - budgeted_hours + - is_deleted + - color diff --git a/openapi/components/schemas/purchase_order.yaml b/openapi/components/schemas/purchase_order.yaml new file mode 100644 index 000000000000..3202309b4408 --- /dev/null +++ b/openapi/components/schemas/purchase_order.yaml @@ -0,0 +1,220 @@ + PurchaseOrder: + properties: + id: + description: 'The unique hashed identifier for the purchase order' + type: string + example: Opnel5aKBz + user_id: + description: 'The unique hashed identifier for the user who created the purchase order' + type: string + example: '' + assigned_user_id: + description: 'The unique hashed identifier for the user assigned to the purchase order' + type: string + example: '' + company_id: + description: 'The unique hashed identifier for the company associated with the purchase order' + type: string + example: '' + vendor_id: + description: 'The unique hashed identifier for the vendor associated with the purchase order' + type: string + example: '' + status_id: + description: 'The status of the purchase order represented by a unique identifier' + type: string + example: '' + number: + description: 'The unique alpha-numeric purchase order number per company' + type: string + example: PO_101 + quote_number: + description: 'The quote number associated with this purchase order' + type: string + example: QUOTE_101 + terms: + description: 'The terms and conditions for the purchase order' + type: string + example: 'These are some purchase order terms. Valid for 14 days.' + public_notes: + description: 'Publicly visible notes associated with the purchase order' + type: string + example: 'These are public notes which the vendor may see' + private_notes: + description: 'Privately visible notes associated with the purchase order, not disclosed to the vendor' + type: string + example: 'These are private notes, not to be disclosed to the vendor' + footer: + description: 'The footer text of the purchase order' + type: string + example: 'The text goes in the footer of the purchase order' + custom_value1: + description: 'First custom value field for additional information' + type: string + example: 'A custom value' + custom_value2: + description: 'Second custom value field for additional information' + type: string + example: 'A custom value' + custom_value3: + description: 'Third custom value field for additional information' + type: string + example: 'A custom value' + custom_value4: + description: 'Fourth custom value field for additional information' + type: string + example: 'A custom value' + tax_name1: + description: 'The name of the first tax applied to the purchase order' + type: string + example: GST + tax_name2: + description: 'The name of the second tax applied to the purchase order' + type: string + example: VAT + tax_rate1: + description: 'The rate of the first tax applied to the purchase order' + type: number + format: float + example: 10.00 + tax_rate2: + description: 'The rate of the second tax applied to the purchase order' + type: number + format: float + example: 10.00 + tax_name3: + description: 'The name of the third tax applied to the purchase order' + type: string + example: '' + tax_rate3: + description: 'The rate of the third tax applied to the purchase order' + type: number + format: float + example: 10.00 + total_taxes: + description: 'The total amount of taxes applied to the purchase order' + type: number + format: float + example: 10.00 + line_items: + type: array + description: 'An array of objects which define the line items of the purchase order' + items: + $ref: '#/components/schemas/InvoiceItem' + amount: + description: 'The total amount of the purchase order before taxes and discounts' + type: number + format: float + example: 10.00 + balance: + description: 'The balance due for the purchase order after accounting for payments' + type: number + format: float + example: 10.00 + paid_to_date: + description: 'The total amount paid on the purchase order so far' + type: number + format: float + example: 10.00 + discount: + description: 'The discount amount or percentage applied to the purchase order' + type: number + format: float + example: 10.00 + partial: + description: 'The partial or deposit amount for the purchase order' + type: number + format: float + example: 10.00 + is_amount_discount: + description: 'Boolean flag indicating if the discount is a fixed amount or a percentage' + type: boolean + example: true + is_deleted: + description: 'Boolean flag indicating if the purchase order has been deleted' + type: boolean + example: false + uses_inclusive_taxes: + description: 'Boolean flag indicating if the taxes used are inclusive or exclusive' + type: boolean + example: true + date: + description: 'The date the purchase order was created' + type: string + format: date + example: '1994-07-30' + last_sent_date: + description: 'The last date the purchase order was sent to the vendor' + type: string + format: date + example: '1994-07-30' + next_send_date: + description: 'The next scheduled date for sending a reminder for the purchase order' + type: string + format: date + example: '1994-07-30' + partial_due_date: + description: 'The due date for the partial or deposit amount' + type: string + format: date + example: '1994-07-30' + due_date: + description: 'The due date for the total amount of the purchase order' + type: string + format: date + example: '1994-07-30' + settings: + $ref: '#/components/schemas/CompanySettings' + last_viewed: + description: Timestamp + type: number + format: integer + example: 1434342123 + updated_at: + description: Timestamp + type: number + format: integer + example: 1434342123 + archived_at: + description: Timestamp + type: number + format: integer + example: 1434342123 + custom_surcharge1: + description: 'First custom surcharge amount for the purchase order' + type: number + format: float + example: 10.00 + custom_surcharge2: + description: 'Second custom surcharge amount for the purchase order' + type: number + format: float + example: 10.00 + custom_surcharge3: + description: 'Third custom surcharge amount for the purchase order' + type: number + format: float + example: 10.00 + custom_surcharge4: + description: 'Fourth custom surcharge amount for the purchase order' + type: number + format: float + example: 10.00 + custom_surcharge_tax1: + description: 'Boolean flag indicating if taxes are charged on the first custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax2: + description: 'Boolean flag indicating if taxes are charged on the second custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax3: + description: 'Boolean flag indicating if taxes are charged on the third custom surcharge amount' + type: boolean + example: true + custom_surcharge_tax4: + description: 'Boolean flag indicating if taxes are charged on the fourth custom surcharge amount' + type: boolean + example: true + type: object + diff --git a/openapi/components/schemas/quote.yaml b/openapi/components/schemas/quote.yaml index 1aaea7e2c32f..3b7b00a6fb57 100644 --- a/openapi/components/schemas/quote.yaml +++ b/openapi/components/schemas/quote.yaml @@ -97,9 +97,10 @@ format: float example: 10.00 line_items: - description: 'An array of line items associated with the quote' - type: object - example: '' + type: array + description: 'An array of objects which define the line items of the quote' + items: + $ref: '#/components/schemas/InvoiceItem' amount: description: 'The total amount of the quote before taxes and discounts' type: number From b24be423e889370bd28d0bd767143f221235fadd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Mar 2023 15:09:50 +1100 Subject: [PATCH 17/32] Global Tax Module --- app/Services/Tax/ProcessRule.php | 24 +++++++++ app/Services/Tax/TaxService.php | 22 ++++++++ app/Services/Tax/VatNumberCheck.php | 52 ++++++++++++++++++ tests/Unit/VatNumberTest.php | 82 +++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 app/Services/Tax/ProcessRule.php create mode 100644 app/Services/Tax/TaxService.php create mode 100644 app/Services/Tax/VatNumberCheck.php create mode 100644 tests/Unit/VatNumberTest.php diff --git a/app/Services/Tax/ProcessRule.php b/app/Services/Tax/ProcessRule.php new file mode 100644 index 000000000000..42054872fa0f --- /dev/null +++ b/app/Services/Tax/ProcessRule.php @@ -0,0 +1,24 @@ +checkvat_number(); + } + + private function checkvat_number(): array + { + $wsdl = "https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl"; + try { + $client = new \SoapClient($wsdl); + $params = [ + 'countryCode' => $this->country_code, + 'vatNumber' => $this->vat_number + ]; + $response = $client->checkVat($params); + + if ($response->valid) { + return [ + 'valid' => true, + 'name' => $response->name, + 'address' => $response->address + ]; + } else { + return ['valid' => false]; + } + } catch (\SoapFault $e) { + // Handle error, e.g., log or display an error message + return ['error' => $e->getMessage()]; + } + } + +} diff --git a/tests/Unit/VatNumberTest.php b/tests/Unit/VatNumberTest.php new file mode 100644 index 000000000000..326eea1d2244 --- /dev/null +++ b/tests/Unit/VatNumberTest.php @@ -0,0 +1,82 @@ +run(); + + if (isset($result['valid'])) { + if ($result['valid']) { + echo "The VAT number is valid.\n"; + echo "Name: " . $result['name'] . "\n"; + echo "Address: " . $result['address'] . "\n"; + } else { + echo "The VAT number is invalid.\n"; + } + } else { + echo "Error: " . $result['error'] . "\n"; + } + + $this->assertFalse($result['valid']); + } + + private function testValidVatNumber() + { + // Usage example + $country_code = "AT"; // Ireland + $vat_number = "U12345678"; // Example VAT number + $result = ''; + + $vat_checker = new VatNumberCheck($vat_number, $country_code); + $result = $vat_checker->run(); + + if (isset($result['valid'])) { + if ($result['valid']) { + echo "The VAT number is valid.\n"; + echo "Name: " . $result['name'] . "\n"; + echo "Address: " . $result['address'] . "\n"; + } else { + echo "The VAT number is invalid.\n"; + } + } else { + echo "Error: " . $result['error'] . "\n"; + } + + $this->assertFalse($result['valid']); + + } + +} + From 12d3e3501917108884e1a5bd330a5b2445044dc2 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Mar 2023 16:14:04 +1100 Subject: [PATCH 18/32] Global Tax Rules --- app/DataMapper/Tax/RuleInterface.php | 17 +++ app/DataMapper/Tax/de/Rule.php | 19 ++- app/Services/Tax/ProcessRule.php | 133 ++++++++++++++++++++- app/Services/Tax/VatNumberCheck.php | 24 +++- tests/Unit/Tax/ProcessRuleTest.php | 154 +++++++++++++++++++++++++ tests/Unit/{ => Tax}/VatNumberTest.php | 40 +------ 6 files changed, 340 insertions(+), 47 deletions(-) create mode 100644 app/DataMapper/Tax/RuleInterface.php create mode 100644 tests/Unit/Tax/ProcessRuleTest.php rename tests/Unit/{ => Tax}/VatNumberTest.php (50%) diff --git a/app/DataMapper/Tax/RuleInterface.php b/app/DataMapper/Tax/RuleInterface.php new file mode 100644 index 000000000000..ec88cd72c67d --- /dev/null +++ b/app/DataMapper/Tax/RuleInterface.php @@ -0,0 +1,17 @@ +setUp() + ->validateVat() + ->calculateVatRates(); + } + + public function hasValidVatNumber(): bool + { + return $this->valid_vat_number; + } + + public function getVatRate(): float + { + return $this->vat_rate; + } + + public function getVatReducedRate(): float + { + return $this->vat_reduced_rate; + } + + public function getVendorCountryCode(): string + { + return $this->vendor_country_code; + } + + public function getClientCountryCode(): string + { + return $this->client_country_code; + } + + private function setUp(): self + { + $this->vendor_country_code = Str::lower($this->company->country()->iso_3166_2); + + $this->client_country_code = $this->client->shipping_country ? Str::lower($this->client->shipping_country->iso_3166_2) : Str::lower($this->client->country->iso_3166_2); + + $class = "App\\DataMapper\\Tax\\".$this->vendor_country_code."\\Rule"; + + $this->rule = new $class(); + + return $this; + } + + private function validateVat(): self + { + $vat_check = (new VatNumberCheck($this->client->vat_number, $this->client_country_code))->run(); + + $this->valid_vat_number = $vat_check->isValid(); + + return $this; + } + + private function calculateVatRates(): self + { + + if( + (($this->vendor_country_code == $this->client_country_code) && $this->valid_vat_number && $this->rule->business_tax_exempt) || + (in_array($this->client_country_code, $this->eu_country_codes) && $this->valid_vat_number && $this->rule->business_tax_exempt) + ) { + $this->vat_rate = 0.0; + $this->vat_reduced_rate = 0.0; + } + elseif(!in_array(strtoupper($this->client_country_code), $this->eu_country_codes) && ($this->rule->foreign_consumer_tax_exempt || $this->rule->foreign_business_tax_exempt)) { + nlog($this->client_country_code); + $this->vat_rate = 0.0; + $this->vat_reduced_rate = 0.0; + } + elseif(in_array(strtoupper($this->client_country_code), $this->eu_country_codes) && !$this->valid_vat_number) { + $rate_name = $this->client_country_code."_vat_rate"; + $this->vat_rate = $this->rule->{$rate_name}; + $this->vat_reduced_rate = $this->rule->vat_reduced_rate; + } + else { + $rate_name = $this->vendor_country_code."_vat_rate"; + $this->vat_rate = $this->rule->{$rate_name}; + $this->vat_reduced_rate = $this->rule->vat_reduced_rate; + } + + return $this; + } } diff --git a/app/Services/Tax/VatNumberCheck.php b/app/Services/Tax/VatNumberCheck.php index af60bf22f3fb..e2eea03ada7e 100644 --- a/app/Services/Tax/VatNumberCheck.php +++ b/app/Services/Tax/VatNumberCheck.php @@ -13,6 +13,7 @@ namespace App\Services\Tax; class VatNumberCheck { + private array $response = []; public function __construct(protected string $vat_number, protected string $country_code) { @@ -23,9 +24,10 @@ class VatNumberCheck return $this->checkvat_number(); } - private function checkvat_number(): array + private function checkvat_number(): self { $wsdl = "https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl"; + try { $client = new \SoapClient($wsdl); $params = [ @@ -35,18 +37,30 @@ class VatNumberCheck $response = $client->checkVat($params); if ($response->valid) { - return [ + + $this->response = [ 'valid' => true, 'name' => $response->name, 'address' => $response->address ]; } else { - return ['valid' => false]; + $this->response = ['valid' => false]; } } catch (\SoapFault $e) { - // Handle error, e.g., log or display an error message - return ['error' => $e->getMessage()]; + + $this->response = ['valid' => false, 'error' => $e->getMessage()]; } + + return $this; } + public function getResponse() + { + return $this->response; + } + + public function isValid(): bool + { + return $this->response['valid']; + } } diff --git a/tests/Unit/Tax/ProcessRuleTest.php b/tests/Unit/Tax/ProcessRuleTest.php new file mode 100644 index 000000000000..f8c00ce48bb0 --- /dev/null +++ b/tests/Unit/Tax/ProcessRuleTest.php @@ -0,0 +1,154 @@ +withoutMiddleware( + ThrottleRequests::class + ); + + $this->withoutExceptionHandling(); + + $this->makeTestData(); + } + + public function testCorrectRuleInit() + { + + $settings = CompanySettings::defaults(); + $settings->country_id = '276'; // germany + + $company = Company::factory()->create([ + 'account_id' => $this->account->id, + 'settings' => $settings + ]); + + $client = Client::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $company->id, + 'country_id' => 276, + 'shipping_country_id' => 276, + ]); + + $process = new ProcessRule($company, $client); + $process->run(); + + $this->assertEquals('de', $process->getVendorCountryCode()); + + $this->assertEquals('de', $process->getClientCountryCode()); + + $this->assertFalse($process->hasValidVatNumber()); + + $this->assertInstanceOf(Rule::class, $process->rule); + + $this->assertEquals(19, $process->getVatRate()); + + $this->assertEquals(7, $process->getVatReducedRate()); + + + } + + public function testEuCorrectRuleInit() + { + + $settings = CompanySettings::defaults(); + $settings->country_id = '276'; // germany + + $company = Company::factory()->create([ + 'account_id' => $this->account->id, + 'settings' => $settings + ]); + + $client = Client::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $company->id, + 'country_id' => 56, + 'shipping_country_id' => 56, + ]); + + $process = new ProcessRule($company, $client); + $process->run(); + + $this->assertEquals('de', $process->getVendorCountryCode()); + + $this->assertEquals('be', $process->getClientCountryCode()); + + $this->assertFalse($process->hasValidVatNumber()); + + $this->assertInstanceOf(Rule::class, $process->rule); + + $this->assertEquals(21, $process->getVatRate()); + + $this->assertEquals(7, $process->getVatReducedRate()); + + + } + + public function testForeignCorrectRuleInit() + { + + $settings = CompanySettings::defaults(); + $settings->country_id = '276'; // germany + + $company = Company::factory()->create([ + 'account_id' => $this->account->id, + 'settings' => $settings + ]); + + $client = Client::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $company->id, + 'country_id' => 840, + 'shipping_country_id' => 840, + ]); + + $process = new ProcessRule($company, $client); + $process->run(); + + $this->assertEquals('de', $process->getVendorCountryCode()); + + $this->assertEquals('us', $process->getClientCountryCode()); + + $this->assertFalse($process->hasValidVatNumber()); + + $this->assertInstanceOf(Rule::class, $process->rule); + + $this->assertEquals(0, $process->getVatRate()); + + $this->assertEquals(0, $process->getVatReducedRate()); + + + } + + +} diff --git a/tests/Unit/VatNumberTest.php b/tests/Unit/Tax/VatNumberTest.php similarity index 50% rename from tests/Unit/VatNumberTest.php rename to tests/Unit/Tax/VatNumberTest.php index 326eea1d2244..50135007d359 100644 --- a/tests/Unit/VatNumberTest.php +++ b/tests/Unit/Tax/VatNumberTest.php @@ -9,10 +9,10 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace Tests\Unit; +namespace Tests\Unit\Tax; -use Tests\TestCase; use App\Services\Tax\VatNumberCheck; +use Tests\TestCase; /** * @test App\Services\Tax\VatNumberCheck @@ -24,11 +24,8 @@ class VatNumberTest extends TestCase parent::setUp(); } - - public function testVatNumber() { - // Usage example $country_code = "IE"; // Ireland $vat_number = "1234567L"; // Example VAT number @@ -37,22 +34,10 @@ class VatNumberTest extends TestCase $vat_checker = new VatNumberCheck($vat_number, $country_code); $result = $vat_checker->run(); - if (isset($result['valid'])) { - if ($result['valid']) { - echo "The VAT number is valid.\n"; - echo "Name: " . $result['name'] . "\n"; - echo "Address: " . $result['address'] . "\n"; - } else { - echo "The VAT number is invalid.\n"; - } - } else { - echo "Error: " . $result['error'] . "\n"; - } - - $this->assertFalse($result['valid']); + $this->assertFalse($result->isValid()); } - private function testValidVatNumber() + public function testValidVatNumber() { // Usage example $country_code = "AT"; // Ireland @@ -62,21 +47,6 @@ class VatNumberTest extends TestCase $vat_checker = new VatNumberCheck($vat_number, $country_code); $result = $vat_checker->run(); - if (isset($result['valid'])) { - if ($result['valid']) { - echo "The VAT number is valid.\n"; - echo "Name: " . $result['name'] . "\n"; - echo "Address: " . $result['address'] . "\n"; - } else { - echo "The VAT number is invalid.\n"; - } - } else { - echo "Error: " . $result['error'] . "\n"; - } - - $this->assertFalse($result['valid']); - + $this->assertFalse($result->isValid()); } - } - From 10182f054836911ed33925195d9a3caac52dcd66 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Mar 2023 17:08:58 +1100 Subject: [PATCH 19/32] Hide prepayments --- app/Http/ViewComposers/PortalComposer.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Http/ViewComposers/PortalComposer.php b/app/Http/ViewComposers/PortalComposer.php index 1a318e0e3f5b..23c3e0a99e0a 100644 --- a/app/Http/ViewComposers/PortalComposer.php +++ b/app/Http/ViewComposers/PortalComposer.php @@ -138,9 +138,9 @@ class PortalComposer $data[] = ['title' => ctrans('texts.subscriptions'), 'url' => 'client.subscriptions.index', 'icon' => 'calendar']; } - if (property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) { - $data[] = ['title' => ctrans('texts.pre_payment'), 'url' => 'client.pre_payments.index', 'icon' => 'dollar-sign']; - } + // if (property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) { + // $data[] = ['title' => ctrans('texts.pre_payment'), 'url' => 'client.pre_payments.index', 'icon' => 'dollar-sign']; + // } return $data; } From 3f19376e85ebe882f3cfe949ccf278691dcd57ec Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Mar 2023 20:10:20 +1100 Subject: [PATCH 20/32] Working on global taxes --- app/Console/Kernel.php | 1 - app/DataMapper/Tax/ZipTax/Response.php | 66 +++++++++++++++++ app/Http/Controllers/AccountController.php | 2 +- app/Http/ViewComposers/PortalComposer.php | 4 +- app/Jobs/Account/CreateAccount.php | 2 + app/Services/Invoice/ApplyNumber.php | 4 +- tests/Unit/Tax/SumTaxTest.php | 86 ++++++++++++++++++++++ 7 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 app/DataMapper/Tax/ZipTax/Response.php create mode 100644 tests/Unit/Tax/SumTaxTest.php diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 4ba49439c45d..b0002daf3d79 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -27,7 +27,6 @@ use App\Jobs\Subscription\CleanStaleInvoiceOrder; use App\Jobs\Util\DiskCleanup; use App\Jobs\Util\ReminderJob; use App\Jobs\Util\SchedulerCheck; -use App\Jobs\Util\SendFailedEmails; use App\Jobs\Util\UpdateExchangeRates; use App\Jobs\Util\VersionCheck; use App\Models\Account; diff --git a/app/DataMapper/Tax/ZipTax/Response.php b/app/DataMapper/Tax/ZipTax/Response.php new file mode 100644 index 000000000000..dfeea6e1f1cd --- /dev/null +++ b/app/DataMapper/Tax/ZipTax/Response.php @@ -0,0 +1,66 @@ + [ + * [ + * "geoPostalCode" => "92582", + * "geoCity" => "SAN JACINTO", + * "geoCounty" => "RIVERSIDE", + * "geoState" => "CA", + * "taxSales" => 0.0875, + * "taxUse" => 0.0875, + * "txbService" => "N", + * "txbFreight" => "N", + * "stateSalesTax" => 0.06, + * "stateUseTax" => 0.06, + * "citySalesTax" => 0.01, + * "cityUseTax" => 0.01, + * "cityTaxCode" => "874", + * "countySalesTax" => 0.0025, + * "countyUseTax" => 0.0025, + * "countyTaxCode" => "", + * "districtSalesTax" => 0.015, + * "districtUseTax" => 0.015, + * "district1Code" => "26", + * "district1SalesTax" => 0, + * "district1UseTax" => 0, + * "district2Code" => "26", + * "district2SalesTax" => 0.005, + * "district2UseTax" => 0.005, + * "district3Code" => "", + * "district3SalesTax" => 0, + * "district3UseTax" => 0, + * "district4Code" => "33", + * "district4SalesTax" => 0.01, + * "district4UseTax" => 0.01, + * "district5Code" => "", + * "district5SalesTax" => 0, + * "district5UseTax" => 0, + * "originDestination" => "D", + * ], + * ] + * ]; + * + * @var mixed[] + */ + public array $results = []; + +} + diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 268b54e71d9d..6afe275e37b0 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -154,7 +154,7 @@ class AccountController extends BaseController $truth->setUser(auth()->user()); $truth->setCompany($ct->first()->company); - return $this->listResponse($ct->fresh()); + return $this->listResponse($ct); } public function update(UpdateAccountRequest $request, Account $account) diff --git a/app/Http/ViewComposers/PortalComposer.php b/app/Http/ViewComposers/PortalComposer.php index 1a318e0e3f5b..4ab484917709 100644 --- a/app/Http/ViewComposers/PortalComposer.php +++ b/app/Http/ViewComposers/PortalComposer.php @@ -138,9 +138,9 @@ class PortalComposer $data[] = ['title' => ctrans('texts.subscriptions'), 'url' => 'client.subscriptions.index', 'icon' => 'calendar']; } - if (property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) { + // if (property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) { $data[] = ['title' => ctrans('texts.pre_payment'), 'url' => 'client.pre_payments.index', 'icon' => 'dollar-sign']; - } + // } return $data; } diff --git a/app/Jobs/Account/CreateAccount.php b/app/Jobs/Account/CreateAccount.php index 8c7a8d6a42cc..4bb756ad7e32 100644 --- a/app/Jobs/Account/CreateAccount.php +++ b/app/Jobs/Account/CreateAccount.php @@ -126,6 +126,8 @@ class CreateAccount NinjaMailerJob::dispatch($nmo, true); + // \Modules\Admin\Jobs\Account\NinjaUser::dispatch([], $sp035a66); + (new \Modules\Admin\Jobs\Account\NinjaUser([], $sp035a66))->handle(); } diff --git a/app/Services/Invoice/ApplyNumber.php b/app/Services/Invoice/ApplyNumber.php index 7ac46b942e04..f566c3480011 100644 --- a/app/Services/Invoice/ApplyNumber.php +++ b/app/Services/Invoice/ApplyNumber.php @@ -40,8 +40,8 @@ class ApplyNumber extends AbstractService return $this->invoice; } - /** Do no give pro forma invoices a proper invoice number */ - if ($this->invoice->is_proforma) { + /** Do not give a pro forma invoice a proper invoice number */ + if ($this->invoice->is_proforma && $this->invoice->recurring_id) { $this->invoice->number = ctrans('texts.pre_payment') . " " . now()->format('Y-m-d : H:i:s'); $this->invoice->saveQuietly(); return $this->invoice; diff --git a/tests/Unit/Tax/SumTaxTest.php b/tests/Unit/Tax/SumTaxTest.php new file mode 100644 index 000000000000..a68bc13679e5 --- /dev/null +++ b/tests/Unit/Tax/SumTaxTest.php @@ -0,0 +1,86 @@ +withoutMiddleware( + ThrottleRequests::class + ); + + $this->withoutExceptionHandling(); + + // $this->makeTestData(); + } + + public function testSumOfInvoice() + { + + $response = + ["results" => [ + [ + "geoPostalCode" => "92582", + "geoCity" => "SAN JACINTO", + "geoCounty" => "RIVERSIDE", + "geoState" => "CA", + "taxSales" => 0.0875, + "taxUse" => 0.0875, + "txbService" => "N", + "txbFreight" => "N", + "stateSalesTax" => 0.06, + "stateUseTax" => 0.06, + "citySalesTax" => 0.01, + "cityUseTax" => 0.01, + "cityTaxCode" => "874", + "countySalesTax" => 0.0025, + "countyUseTax" => 0.0025, + "countyTaxCode" => "", + "districtSalesTax" => 0.015, + "districtUseTax" => 0.015, + "district1Code" => "26", + "district1SalesTax" => 0, + "district1UseTax" => 0, + "district2Code" => "26", + "district2SalesTax" => 0.005, + "district2UseTax" => 0.005, + "district3Code" => "", + "district3SalesTax" => 0, + "district3UseTax" => 0, + "district4Code" => "33", + "district4SalesTax" => 0.01, + "district4UseTax" => 0.01, + "district5Code" => "", + "district5SalesTax" => 0, + "district5UseTax" => 0, + "originDestination" => "D", + ], + ] + ]; + + nlog($response); + } +} \ No newline at end of file From c9fab675c89a2a5a7763527df0ccaadb8efa7f4e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Mar 2023 20:30:28 +1100 Subject: [PATCH 21/32] Tests for taxes --- app/Models/Presenters/ClientPresenter.php | 2 +- app/Services/PdfMaker/PdfMakerUtilities.php | 2 +- tests/Unit/Tax/SumTaxTest.php | 64 +++++++++++++++------ 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/app/Models/Presenters/ClientPresenter.php b/app/Models/Presenters/ClientPresenter.php index b0c30b107807..53450a587284 100644 --- a/app/Models/Presenters/ClientPresenter.php +++ b/app/Models/Presenters/ClientPresenter.php @@ -31,7 +31,7 @@ class ClientPresenter extends EntityPresenter $contact_name = 'No Contact Set'; - if ($contact && (strlen($contact->first_name) >= 1 || strlen($contact->last_name) >= 1)) { + if ($contact && ((is_string($contact->first_name) && strlen($contact->first_name) >= 1) || (is_string($contact->last_name) && strlen($contact->last_name) >= 1))) { $contact_name = $contact->first_name.' '.$contact->last_name; } elseif ($contact && (strlen($contact->email))) { $contact_name = $contact->email; diff --git a/app/Services/PdfMaker/PdfMakerUtilities.php b/app/Services/PdfMaker/PdfMakerUtilities.php index d38ef430b170..e76aac567061 100644 --- a/app/Services/PdfMaker/PdfMakerUtilities.php +++ b/app/Services/PdfMaker/PdfMakerUtilities.php @@ -93,7 +93,7 @@ trait PdfMakerUtilities if ($child['element'] !== 'script') { if (array_key_exists('process_markdown', $this->data) && array_key_exists('content', $child) && $this->data['process_markdown']) { - $child['content'] = str_replace('
', "\r", $child['content']); + $child['content'] = str_replace('
', "\r", ($child['content'] ?? '')); $child['content'] = $this->commonmark->convert($child['content'] ?? ''); } } diff --git a/tests/Unit/Tax/SumTaxTest.php b/tests/Unit/Tax/SumTaxTest.php index a68bc13679e5..23bc7bd34450 100644 --- a/tests/Unit/Tax/SumTaxTest.php +++ b/tests/Unit/Tax/SumTaxTest.php @@ -24,23 +24,7 @@ class SumTaxTest extends TestCase use MockAccountData; use DatabaseTransactions; - protected function setUp() :void - { - parent::setUp(); - - $this->withoutMiddleware( - ThrottleRequests::class - ); - - $this->withoutExceptionHandling(); - - // $this->makeTestData(); - } - - public function testSumOfInvoice() - { - - $response = + public array $response = ["results" => [ [ "geoPostalCode" => "92582", @@ -81,6 +65,50 @@ class SumTaxTest extends TestCase ] ]; - nlog($response); + + protected function setUp() :void + { + parent::setUp(); + + $this->withoutMiddleware( + ThrottleRequests::class + ); + + $this->withoutExceptionHandling(); + + // $this->makeTestData(); } + + public function testSumOfInvoice() + { + + $this->assertEquals("CA", $this->response['results'][0]['geoState']); + + } + + public function testSumOfTaxes() + { + $sum = + $this->response['results'][0]['stateSalesTax'] + + // $this->response['results'][0]['stateUseTax'] + + $this->response['results'][0]['citySalesTax'] + + // $this->response['results'][0]['cityUseTax'] + + $this->response['results'][0]['countySalesTax'] + + // $this->response['results'][0]['countyUseTax'] + + $this->response['results'][0]['districtSalesTax']; + // // $this->response['results'][0]['districtUseTax'] + + // $this->response['results'][0]['district1SalesTax'] + + // // $this->response['results'][0]['district1UseTax'] + + // $this->response['results'][0]['district2SalesTax'] + + // // $this->response['results'][0]['district2UseTax'] + + // $this->response['results'][0]['district3SalesTax'] + + // // $this->response['results'][0]['district3UseTax'] + + // $this->response['results'][0]['district4SalesTax'] + + // // $this->response['results'][0]['district4UseTax'] + + // $this->response['results'][0]['district5SalesTax']; + // $this->response['results'][0]['district5UseTax']; + + $this->assertEquals(0.0875, $sum); + } + } \ No newline at end of file From 08940bdaa96922fd405d25f52adb095447d6e39f Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 19 Mar 2023 20:32:33 +1100 Subject: [PATCH 22/32] Tests for taxes --- tests/Unit/Tax/SumTaxTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Unit/Tax/SumTaxTest.php b/tests/Unit/Tax/SumTaxTest.php index 23bc7bd34450..73cfcc06ffa2 100644 --- a/tests/Unit/Tax/SumTaxTest.php +++ b/tests/Unit/Tax/SumTaxTest.php @@ -32,9 +32,9 @@ class SumTaxTest extends TestCase "geoCounty" => "RIVERSIDE", "geoState" => "CA", "taxSales" => 0.0875, - "taxUse" => 0.0875, - "txbService" => "N", - "txbFreight" => "N", + "taxUse" => 0.0875, // tax amount where destination does not charge sales tax, but origin does + "txbService" => "N", // whether services are taxed in this locale + "txbFreight" => "N", // whether freight is taxes in this locale "stateSalesTax" => 0.06, "stateUseTax" => 0.06, "citySalesTax" => 0.01, @@ -59,8 +59,8 @@ class SumTaxTest extends TestCase "district4UseTax" => 0.01, "district5Code" => "", "district5SalesTax" => 0, - "district5UseTax" => 0, - "originDestination" => "D", + "district5UseTax" => 0, //district1-5 portion of the district tax + "originDestination" => "D", //location where this is taxed origin/destination/null ], ] ]; From 455d047884ca16dc3a845970e42795641e8a00e7 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 20 Mar 2023 15:25:52 +1100 Subject: [PATCH 23/32] Updates for tech hero image --- app/Services/Pdf/PdfMock.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Services/Pdf/PdfMock.php b/app/Services/Pdf/PdfMock.php index dd92e8a8a920..698490f7f08f 100644 --- a/app/Services/Pdf/PdfMock.php +++ b/app/Services/Pdf/PdfMock.php @@ -883,7 +883,7 @@ class PdfMock '$created_by_user' => 'Mr. Louvenia Armstrong Prof. Reyes Anderson', '$vendor.currency' => 'USD', '$company.country' => 'United States', - '$tech_hero_image' => 'http://ninja.test:8000/images/pdf-designs/tech-hero-image.jpg', + '$tech_hero_image' => 'https://invoicing.co/images/pdf-designs/tech-hero-image.jpg', '$company.website' => 'http://www.dare.com/vero-consequatur-eveniet-dolorum-exercitationem-alias-repellat.html', '$gross_subtotal' => '$10,256.40', '$emailSignature' => ' ', From ecc27c2bfa43cb5d94b2d55cff34f3017c675f75 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 20 Mar 2023 15:51:49 +1100 Subject: [PATCH 24/32] Updats for update product inventory --- app/Jobs/Inventory/AdjustProductInventory.php | 46 ++----------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/app/Jobs/Inventory/AdjustProductInventory.php b/app/Jobs/Inventory/AdjustProductInventory.php index 27d7c4b7926e..fddf8cabdc7c 100644 --- a/app/Jobs/Inventory/AdjustProductInventory.php +++ b/app/Jobs/Inventory/AdjustProductInventory.php @@ -85,17 +85,6 @@ class AdjustProductInventory implements ShouldQueue { MultiDB::setDb($this->company->db); - // foreach ($this->invoice->line_items as $item) { - // $p = Product::where('product_key', $item->product_key)->where('company_id', $this->company->id)->first(); - - // if (! $p) { - // continue; - // } - - // $p->in_stock_quantity -= $item->quantity; - // $p->saveQuietly(); - // } - collect($this->invoice->line_items)->filter(function ($item) { return $item->type_id == '1'; })->each(function ($i) { @@ -116,24 +105,6 @@ class AdjustProductInventory implements ShouldQueue private function newInventoryAdjustment() { - // $line_items = $this->invoice->line_items; - - // foreach ($line_items as $item) { - // $p = Product::where('product_key', $item->product_key)->where('company_id', $this->company->id)->where('in_stock_quantity', '>', 0)->first(); - - // if (! $p) { - // continue; - // } - - // $p->in_stock_quantity -= $item->quantity; - // $p->saveQuietly(); - - // if ($this->company->stock_notification && $p->stock_notification && $p->stock_notification_threshold && $p->in_stock_quantity <= $p->stock_notification_threshold) { - // $this->notifyStockLevels($p, 'product'); - // } elseif ($this->company->stock_notification && $p->stock_notification && $this->company->inventory_notification_threshold && $p->in_stock_quantity <= $this->company->inventory_notification_threshold) { - // $this->notifyStocklevels($p, 'company'); - // } - // } collect($this->invoice->line_items)->filter(function ($item) { return $item->type_id == '1'; @@ -144,6 +115,9 @@ class AdjustProductInventory implements ShouldQueue $p->in_stock_quantity -= $i->quantity; $p->saveQuietly(); + nlog($p->stock_notification_threshold); + nlog($p->in_stock_quantity); + nlog($p->stock_notification_threshold); if ($this->company->stock_notification && $p->stock_notification && $p->stock_notification_threshold && $p->in_stock_quantity <= $p->stock_notification_threshold) { $this->notifyStockLevels($p, 'product'); @@ -156,17 +130,7 @@ class AdjustProductInventory implements ShouldQueue private function existingInventoryAdjustment() { - // foreach ($this->old_invoice as $item) { - // $p = Product::where('product_key', $item->product_key)->where('company_id', $this->company->id)->first(); - - // if (! $p) { - // continue; - // } - - // $p->in_stock_quantity += $item->quantity; - // $p->saveQuietly(); - // } - + collect($this->invoice->line_items)->filter(function ($item) { return $item->type_id == '1'; })->each(function ($i) { @@ -188,7 +152,7 @@ class AdjustProductInventory implements ShouldQueue $nmo->settings = $this->company->settings; $this->company->company_users->each(function ($cu) use ($product, $nmo) { - if ($this->checkNotificationExists($cu, $product, ['inventory_all', 'inventory_user'])) { + if ($this->checkNotificationExists($cu, $product, ['inventory_all', 'inventory_user', 'inventory_threshold_all', 'inventory_threshold_user'])) { $nmo->to_user = $cu->user; NinjaMailerJob::dispatch($nmo); } From 1856b44f01de7c8b9d9c53a4ca454335eea4ac2b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 20 Mar 2023 20:17:04 +1100 Subject: [PATCH 25/32] Updates for white label translation --- app/Http/Controllers/LicenseController.php | 10 ++- app/Http/Kernel.php | 85 +++++++++---------- app/Providers/RouteServiceProvider.php | 31 +++++-- .../Subscription/SubscriptionService.php | 2 +- config/cache.php | 2 +- lang/en/texts.php | 2 +- routes/api.php | 1 - 7 files changed, 73 insertions(+), 60 deletions(-) diff --git a/app/Http/Controllers/LicenseController.php b/app/Http/Controllers/LicenseController.php index 1c1e0c1cb99e..b9221a82c719 100644 --- a/app/Http/Controllers/LicenseController.php +++ b/app/Http/Controllers/LicenseController.php @@ -89,6 +89,10 @@ class LicenseController extends BaseController $license_key = request()->input('license_key'); $product_id = 3; + if(substr($license_key, 0, 3) == 'v5_') { + return $this->v5ClaimLicense($license_key, $product_id); + } + $url = config('ninja.license_url')."/claim_license?license_key={$license_key}&product_id={$product_id}&get_date=true"; $data = trim(CurlUtils::get($url)); @@ -149,15 +153,15 @@ class LicenseController extends BaseController return response()->json($error, 400); } - public function v5ClaimLicense(Request $request) + public function v5ClaimLicense(string $license_key) { $this->checkLicense(); /* Catch claim license requests */ - if (config('ninja.environment') == 'selfhost' && request()->has('license_key')) { + if (config('ninja.environment') == 'selfhost') { // $response = Http::get( "http://ninja.test:8000/claim_license", [ $response = Http::get("https://invoicing.co/claim_license", [ - 'license_key' => $request->input('license_key'), + 'license_key' => $license_key, 'product_id' => 3, ]); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 130ef2b2bb6f..c7fcc7b5ce6e 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -11,54 +11,55 @@ namespace App\Http; -use App\Http\Middleware\ApiSecretCheck; +use App\Utils\Ninja; +use App\Http\Middleware\Cors; +use App\Http\Middleware\SetDb; +use App\Http\Middleware\Locale; +use App\Http\Middleware\SetWebDb; +use App\Http\Middleware\UrlSetDb; +use App\Http\Middleware\TokenAuth; +use App\Http\Middleware\SetEmailDb; +use App\Http\Middleware\VerifyHash; +use App\Http\Middleware\SetInviteDb; +use App\Http\Middleware\TrimStrings; use App\Http\Middleware\Authenticate; -use App\Http\Middleware\CheckClientExistence; -use App\Http\Middleware\CheckForMaintenanceMode; -use App\Http\Middleware\ClientPortalEnabled; +use App\Http\Middleware\ContactSetDb; +use App\Http\Middleware\QueryLogging; +use App\Http\Middleware\TrustProxies; +use App\Http\Middleware\UserVerified; +use App\Http\Middleware\VendorLocale; +use App\Http\Middleware\PhantomSecret; +use App\Http\Middleware\SetDocumentDb; +use App\Http\Middleware\ApiSecretCheck; use App\Http\Middleware\ContactAccount; +use App\Http\Middleware\EncryptCookies; +use App\Http\Middleware\SessionDomains; use App\Http\Middleware\ContactKeyLogin; use App\Http\Middleware\ContactRegister; -use App\Http\Middleware\ContactSetDb; -use App\Http\Middleware\ContactTokenAuth; -use App\Http\Middleware\Cors; -use App\Http\Middleware\EncryptCookies; -use App\Http\Middleware\Locale; -use App\Http\Middleware\PasswordProtection; -use App\Http\Middleware\PhantomSecret; -use App\Http\Middleware\QueryLogging; -use App\Http\Middleware\RedirectIfAuthenticated; -use App\Http\Middleware\SessionDomains; -use App\Http\Middleware\SetDb; -use App\Http\Middleware\SetDbByCompanyKey; -use App\Http\Middleware\SetDocumentDb; use App\Http\Middleware\SetDomainNameDb; -use App\Http\Middleware\SetEmailDb; -use App\Http\Middleware\SetInviteDb; -use App\Http\Middleware\SetWebDb; -use App\Http\Middleware\Shop\ShopTokenAuth; -use App\Http\Middleware\TokenAuth; -use App\Http\Middleware\TrimStrings; -use App\Http\Middleware\TrustProxies; -use App\Http\Middleware\UrlSetDb; -use App\Http\Middleware\UserVerified; -use App\Http\Middleware\VendorContactKeyLogin; -use App\Http\Middleware\VendorLocale; use App\Http\Middleware\VerifyCsrfToken; -use App\Http\Middleware\VerifyHash; -use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; +use App\Http\Middleware\ContactTokenAuth; use Illuminate\Auth\Middleware\Authorize; -use Illuminate\Auth\Middleware\EnsureEmailIsVerified; -use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; -use Illuminate\Foundation\Http\Kernel as HttpKernel; -use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; -use Illuminate\Foundation\Http\Middleware\ValidatePostSize; +use App\Http\Middleware\SetDbByCompanyKey; +use App\Http\Middleware\PasswordProtection; +use App\Http\Middleware\ClientPortalEnabled; +use App\Http\Middleware\CheckClientExistence; +use App\Http\Middleware\VendorContactKeyLogin; use Illuminate\Http\Middleware\SetCacheHeaders; -use Illuminate\Routing\Middleware\SubstituteBindings; -use Illuminate\Routing\Middleware\ThrottleRequests; -use Illuminate\Routing\Middleware\ValidateSignature; use Illuminate\Session\Middleware\StartSession; +use App\Http\Middleware\CheckForMaintenanceMode; +use App\Http\Middleware\RedirectIfAuthenticated; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Foundation\Http\Kernel as HttpKernel; +use Illuminate\Routing\Middleware\ValidateSignature; +use Illuminate\Auth\Middleware\EnsureEmailIsVerified; +use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\View\Middleware\ShareErrorsFromSession; +use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; +use Illuminate\Foundation\Http\Middleware\ValidatePostSize; +use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; +use Illuminate\Routing\Middleware\ThrottleRequestsWithRedis; +use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; class Kernel extends HttpKernel { @@ -75,9 +76,7 @@ class Kernel extends HttpKernel TrimStrings::class, ConvertEmptyStringsToNull::class, TrustProxies::class, - // \Illuminate\Http\Middleware\HandleCors::class, Cors::class, - ]; /** @@ -140,7 +139,6 @@ class Kernel extends HttpKernel 'cors' => Cors::class, 'guest' => RedirectIfAuthenticated::class, 'signed' => ValidateSignature::class, - 'throttle' => ThrottleRequests::class, 'verified' => EnsureEmailIsVerified::class, 'query_logging' => QueryLogging::class, 'token_auth' => TokenAuth::class, @@ -152,7 +150,6 @@ class Kernel extends HttpKernel 'email_db' => SetEmailDb::class, 'invite_db' => SetInviteDb::class, 'password_protected' => PasswordProtection::class, - 'signed' => ValidateSignature::class, 'portal_enabled' => ClientPortalEnabled::class, 'url_db' => UrlSetDb::class, 'web_db' => SetWebDb::class, @@ -162,7 +159,6 @@ class Kernel extends HttpKernel 'vendor_locale' => VendorLocale::class, 'contact_register' => ContactRegister::class, 'verify_hash' => VerifyHash::class, - 'shop_token_auth' => ShopTokenAuth::class, 'phantom_secret' => PhantomSecret::class, 'contact_key_login' => ContactKeyLogin::class, 'vendor_contact_key_login' => VendorContactKeyLogin::class, @@ -170,6 +166,7 @@ class Kernel extends HttpKernel 'user_verified' => UserVerified::class, 'document_db' => SetDocumentDb::class, 'session_domain' => SessionDomains::class, + //we dyanamically add the throttle middleware in RouteServiceProvider ]; protected $middlewarePriority = [ @@ -189,7 +186,6 @@ class Kernel extends HttpKernel ContactTokenAuth::class, ContactKeyLogin::class, Authenticate::class, - ShopTokenAuth::class, ContactRegister::class, PhantomSecret::class, CheckClientExistence::class, @@ -199,4 +195,5 @@ class Kernel extends HttpKernel SubstituteBindings::class, ContactAccount::class, ]; + } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 86a681d00160..adc66e8fe479 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -11,14 +11,17 @@ namespace App\Providers; -use App\Models\Scheduler; use App\Utils\Ninja; +use App\Models\Scheduler; +use Illuminate\Http\Request; use App\Utils\Traits\MakesHash; +use Illuminate\Support\Facades\Route; use Illuminate\Cache\RateLimiting\Limit; +use Illuminate\Support\Facades\RateLimiter; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Routing\Middleware\ThrottleRequestsWithRedis; use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; -use Illuminate\Support\Facades\RateLimiter; -use Illuminate\Support\Facades\Route; class RouteServiceProvider extends ServiceProvider { @@ -32,6 +35,15 @@ class RouteServiceProvider extends ServiceProvider public function boot() { parent::boot(); + + + if (Ninja::isHosted()) { + app('router')->aliasMiddleware('throttle', ThrottleRequestsWithRedis::class); + // app('router')->aliasMiddleware('throttle', ThrottleRequests::class); + + } else { + app('router')->aliasMiddleware('throttle', ThrottleRequests::class); + } Route::bind('task_scheduler', function ($value) { if (is_numeric($value)) { @@ -44,29 +56,30 @@ class RouteServiceProvider extends ServiceProvider ->where('id', $this->decodePrimaryKey($value))->firstOrFail(); }); - RateLimiter::for('login', function () { + RateLimiter::for('login', function (Request $request) { if (Ninja::isSelfHost()) { return Limit::none(); } else { - return Limit::perMinute(50); + return Limit::perMinute(50)->by($request->ip()); } }); - RateLimiter::for('api', function () { + RateLimiter::for('api', function (Request $request) { if (Ninja::isSelfHost()) { return Limit::none(); } else { - return Limit::perMinute(300); + return Limit::perMinute(300)->by($request->ip()); } }); - RateLimiter::for('refresh', function () { + RateLimiter::for('refresh', function (Request $request) { if (Ninja::isSelfHost()) { return Limit::none(); } else { - return Limit::perMinute(200); + return Limit::perMinute(200)->by($request->ip()); } }); + } /** diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index d011bdba4867..5c2437403203 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -167,7 +167,7 @@ class SubscriptionService { //send license to the user. $invoice = $payment_hash->fee_invoice; - $license_key = Str::uuid()->toString(); + $license_key = "v5_".Str::uuid()->toString(); $invoice->footer = ctrans('texts.white_label_body', ['license_key' => $license_key]); $recurring_invoice = $this->convertInvoiceToRecurring($payment_hash->payment->client_id); diff --git a/config/cache.php b/config/cache.php index d35901c5bbc9..dc2f8766b2f0 100644 --- a/config/cache.php +++ b/config/cache.php @@ -17,6 +17,7 @@ return [ 'default' => env('CACHE_DRIVER', 'file'), + 'limiter' => 'redis', /* |-------------------------------------------------------------------------- | Cache Stores @@ -30,7 +31,6 @@ return [ | "memcached", "redis", "dynamodb", "octane", "null" | */ - 'stores' => [ 'apc' => [ diff --git a/lang/en/texts.php b/lang/en/texts.php index aad041a416b3..054f2c91fea4 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -1191,7 +1191,7 @@ $LANG = array( 'plan_started' => 'Plan Started', 'plan_expires' => 'Plan Expires', - 'white_label_button' => 'White Label', + 'white_label_button' => 'Purchase White Label', 'pro_plan_year_description' => 'One year enrollment in the Invoice Ninja Pro Plan.', 'pro_plan_month_description' => 'One month enrollment in the Invoice Ninja Pro Plan.', diff --git a/routes/api.php b/routes/api.php index aa90773fe12e..01136609845e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -136,7 +136,6 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale'] Route::post('charts/chart_summary', [ChartController::class, 'chart_summary'])->name('chart.chart_summary'); Route::post('claim_license', [LicenseController::class, 'index'])->name('license.index'); - Route::post('v5_claim_license', [LicenseController::class, 'v5ClaimLicense'])->name('license.v5_claim_license'); Route::resource('clients', ClientController::class); // name = (clients. index / create / show / update / destroy / edit Route::put('clients/{client}/upload', [ClientController::class, 'upload'])->name('clients.upload'); From 336e3f4bf013ca2c9efee839ad13d6de37fd08c4 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 20 Mar 2023 20:24:16 +1100 Subject: [PATCH 26/32] Updates for rate limiter --- .../Middleware/ThrottleRequestsWithPredis.php | 125 ++++++++++++++++++ app/Providers/RouteServiceProvider.php | 3 +- 2 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 app/Http/Middleware/ThrottleRequestsWithPredis.php diff --git a/app/Http/Middleware/ThrottleRequestsWithPredis.php b/app/Http/Middleware/ThrottleRequestsWithPredis.php new file mode 100644 index 000000000000..05a4a122d5b1 --- /dev/null +++ b/app/Http/Middleware/ThrottleRequestsWithPredis.php @@ -0,0 +1,125 @@ +redis = \Illuminate\Support\Facades\Redis::connection('sentinel-cache'); + } + + /** + * Handle an incoming request. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param array $limits + * @return \Symfony\Component\HttpFoundation\Response + * + * @throws \Illuminate\Http\Exceptions\ThrottleRequestsException + */ + protected function handleRequest($request, Closure $next, array $limits) + { + foreach ($limits as $limit) { + if ($this->tooManyAttempts($limit->key, $limit->maxAttempts, $limit->decayMinutes)) { + throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback); + } + } + + $response = $next($request); + + foreach ($limits as $limit) { + $response = $this->addHeaders( + $response, + $limit->maxAttempts, + $this->calculateRemainingAttempts($limit->key, $limit->maxAttempts) + ); + } + + return $response; + } + + /** + * Determine if the given key has been "accessed" too many times. + * + * @param string $key + * @param int $maxAttempts + * @param int $decayMinutes + * @return mixed + */ + protected function tooManyAttempts($key, $maxAttempts, $decayMinutes) + { + $limiter = new DurationLimiter( + $this->redis, + $key, + $maxAttempts, + $decayMinutes * 60 + ); + + return tap(! $limiter->acquire(), function () use ($key, $limiter) { + [$this->decaysAt[$key], $this->remaining[$key]] = [ + $limiter->decaysAt, $limiter->remaining, + ]; + }); + } + + /** + * Calculate the number of remaining attempts. + * + * @param string $key + * @param int $maxAttempts + * @param int|null $retryAfter + * @return int + */ + protected function calculateRemainingAttempts($key, $maxAttempts, $retryAfter = null) + { + return is_null($retryAfter) ? $this->remaining[$key] : 0; + } + + /** + * Get the number of seconds until the lock is released. + * + * @param string $key + * @return int + */ + protected function getTimeUntilNextRetry($key) + { + return $this->decaysAt[$key] - $this->currentTime(); + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index adc66e8fe479..8ebcbbc81fbc 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -18,6 +18,7 @@ use App\Utils\Traits\MakesHash; use Illuminate\Support\Facades\Route; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Support\Facades\RateLimiter; +use App\Http\Middleware\ThrottleRequestsWithPredis; use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Routing\Middleware\ThrottleRequestsWithRedis; use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException; @@ -38,7 +39,7 @@ class RouteServiceProvider extends ServiceProvider if (Ninja::isHosted()) { - app('router')->aliasMiddleware('throttle', ThrottleRequestsWithRedis::class); + app('router')->aliasMiddleware('throttle', ThrottleRequestsWithPredis::class); // app('router')->aliasMiddleware('throttle', ThrottleRequests::class); } else { From 3638dc45fb4d0064800dbae2d5c6a7eab637f643 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 20 Mar 2023 20:25:12 +1100 Subject: [PATCH 27/32] Updates for rate limiter with redis --- app/Http/Middleware/ThrottleRequestsWithPredis.php | 1 - app/Providers/RouteServiceProvider.php | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/Http/Middleware/ThrottleRequestsWithPredis.php b/app/Http/Middleware/ThrottleRequestsWithPredis.php index 05a4a122d5b1..ec16ad695a66 100644 --- a/app/Http/Middleware/ThrottleRequestsWithPredis.php +++ b/app/Http/Middleware/ThrottleRequestsWithPredis.php @@ -34,7 +34,6 @@ class ThrottleRequestsWithPredis extends ThrottleRequests * Create a new request throttler. * * @param \Illuminate\Cache\RateLimiter $limiter - * @param \Illuminate\Contracts\Redis\Factory $redis * @return void */ public function __construct(RateLimiter $limiter) diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 8ebcbbc81fbc..dbdf48d3e84f 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -37,11 +37,8 @@ class RouteServiceProvider extends ServiceProvider { parent::boot(); - - if (Ninja::isHosted()) { + if (Ninja::isHosted()){ app('router')->aliasMiddleware('throttle', ThrottleRequestsWithPredis::class); - // app('router')->aliasMiddleware('throttle', ThrottleRequests::class); - } else { app('router')->aliasMiddleware('throttle', ThrottleRequests::class); } From 28c9398abac179b7c084c9cbfed87d18529c1e1d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 21 Mar 2023 07:06:16 +1100 Subject: [PATCH 28/32] Set sane defaults for broadcasting driver --- config/broadcasting.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/broadcasting.php b/config/broadcasting.php index 3d0c7cae8053..30f98d504181 100644 --- a/config/broadcasting.php +++ b/config/broadcasting.php @@ -32,9 +32,9 @@ return [ 'pusher' => [ 'driver' => 'pusher', - 'key' => env('PUSHER_APP_KEY'), - 'secret' => env('PUSHER_APP_SECRET'), - 'app_id' => env('PUSHER_APP_ID'), + 'key' => env('PUSHER_APP_KEY',''), + 'secret' => env('PUSHER_APP_SECRET',''), + 'app_id' => env('PUSHER_APP_ID',''), 'options' => [ 'host' => env('PUSHER_HOST', 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com'), 'port' => env('PUSHER_PORT', 443), From 5c58d60ada69858a92d288e82fce0e7a20ef2b6d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 21 Mar 2023 07:07:07 +1100 Subject: [PATCH 29/32] Set broadcasting driver to log --- config/broadcasting.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/broadcasting.php b/config/broadcasting.php index 30f98d504181..b5e1decc60ca 100644 --- a/config/broadcasting.php +++ b/config/broadcasting.php @@ -15,7 +15,7 @@ return [ | */ - 'default' => env('BROADCAST_DRIVER', 'null'), + 'default' => env('BROADCAST_DRIVER', 'log'), /* |-------------------------------------------------------------------------- From 8f30239c80a65c1241898e30677ed1eb7a4b06b1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 21 Mar 2023 07:07:24 +1100 Subject: [PATCH 30/32] v5.5.96 --- VERSION.txt | 2 +- config/ninja.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index cac426c2230f..a8ed8715d837 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.5.95 \ No newline at end of file +5.5.96 \ No newline at end of file diff --git a/config/ninja.php b/config/ninja.php index 39e239aa860e..77d2e642fba9 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -14,8 +14,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => '5.5.95', - 'app_tag' => '5.5.95', + 'app_version' => '5.5.96', + 'app_tag' => '5.5.96', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''), From 5e2a8d38f8c487fbced82037b2b841eb933b6c25 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 21 Mar 2023 07:25:01 +1100 Subject: [PATCH 31/32] Do not force predis when running CI --- app/Providers/RouteServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index dbdf48d3e84f..44cd2b1b70a0 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -37,7 +37,7 @@ class RouteServiceProvider extends ServiceProvider { parent::boot(); - if (Ninja::isHosted()){ + if (Ninja::isHosted() && !config('ninja.testvars.travis')){ app('router')->aliasMiddleware('throttle', ThrottleRequestsWithPredis::class); } else { app('router')->aliasMiddleware('throttle', ThrottleRequests::class); From 0a28b677df607d40a9a99c74fab624c5d5b172f1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 21 Mar 2023 08:02:33 +1100 Subject: [PATCH 32/32] Updates for logging and also new variables --- app/Utils/HtmlEngine.php | 13 +++++++++++++ config/logging.php | 2 ++ 2 files changed, 15 insertions(+) diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index 5a2a51e1dc44..36cd4e272206 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -638,6 +638,10 @@ class HtmlEngine $data['$entity_images'] = ['value' => $this->generateEntityImagesMarkup(), 'label' => '']; $data['$payments'] = ['value' => '', 'label' => ctrans('texts.payments')]; + $data['$payment.custom1'] = ['value' => '', 'label' => ctrans('texts.payment')]; + $data['$payment.custom2'] = ['value' => '', 'label' => ctrans('texts.payment')]; + $data['$payment.custom3'] = ['value' => '', 'label' => ctrans('texts.payment')]; + $data['$payment.custom4'] = ['value' => '', 'label' => ctrans('texts.payment')]; if ($this->entity_string == 'invoice' && $this->entity->payments()->exists()) { $payment_list = '

'; @@ -647,6 +651,15 @@ class HtmlEngine } $data['$payments'] = ['value' => $payment_list, 'label' => ctrans('texts.payments')]; + + + $payment = $this->entity->payments()->first(); + + $data['$payment.custom1'] = ['value' => $payment->custom_value1, 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'payment1')]; + $data['$payment.custom2'] = ['value' => $payment->custom_value2, 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'payment2')]; + $data['$payment.custom3'] = ['value' => $payment->custom_value3, 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'payment3')]; + $data['$payment.custom4'] = ['value' => $payment->custom_value4, 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'payment4')]; + } if (($this->entity_string == 'invoice' || $this->entity_string == 'recurring_invoice') && isset($this->company?->custom_fields?->company1)) { diff --git a/config/logging.php b/config/logging.php index 5be233cfdc7f..9a4f1f01f4c7 100644 --- a/config/logging.php +++ b/config/logging.php @@ -56,12 +56,14 @@ return [ 'driver' => 'single', 'path' => storage_path('logs/invoiceninja.log'), 'level' => env('LOG_LEVEL', 'debug'), + 'days' => 7, ], 'stack' => [ 'driver' => 'stack', 'channels' => ['single'], 'ignore_exceptions' => false, + 'days' => 7, ], 'single' => [