Merge pull request #11718 from turbo124/preview

Preview
This commit is contained in:
David Bomba
2026-02-22 16:59:53 +11:00
committed by GitHub
2303 changed files with 202304 additions and 171874 deletions

View File

@@ -1 +1 @@
5.12.49
5.12.65

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -47,7 +47,7 @@ class ClientSyncCast implements CastsAttributes
return [
$key => json_encode([
'qb_id' => $value->qb_id,
])
]),
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -0,0 +1,52 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Casts;
use App\DataMapper\ExpenseSync;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class ExpenseSyncCast implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes)
{
if (is_null($value)) {
return null; // Return null if the value is null
}
$data = json_decode($value, true);
if (!is_array($data)) {
return null;
}
$es = new ExpenseSync();
$es->qb_id = $data['qb_id'];
return $es;
}
public function set($model, string $key, $value, array $attributes)
{
if (is_null($value)) {
return [$key => null];
}
$data = [
'qb_id' => $value->qb_id,
];
return [
$key => json_encode($data),
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www/elastic.co/licensing/elastic-license
*/
@@ -60,7 +60,7 @@ class InvoiceBackupCast implements CastsAttributes
'redirect' => $value->redirect,
'adjustable_amount' => $value->adjustable_amount,
'notes' => $value->notes,
])
]),
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -25,14 +25,11 @@ class InvoiceSyncCast implements CastsAttributes
$data = json_decode($value, true);
if (!is_array($data)) {
return null;
if (!is_array($data) || empty($data)) {
return null; // Return null if decoded data is not an array or is empty
}
$is = new InvoiceSync();
$is->qb_id = $data['qb_id'];
return $is;
return InvoiceSync::fromArray($data);
}
public function set($model, string $key, $value, array $attributes)
@@ -41,12 +38,12 @@ class InvoiceSyncCast implements CastsAttributes
return [$key => null];
}
$data = [
'qb_id' => $value->qb_id,
];
return [
$key => json_encode($data)
$key => json_encode([
'qb_id' => $value->qb_id,
'invitations' => $value->invitations,
'dn_completed' => $value->dn_completed,
])
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -46,7 +46,7 @@ class PaymentSyncCast implements CastsAttributes
return [
$key => json_encode([
'qb_id' => $value->qb_id,
])
]),
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -32,7 +32,6 @@ class ProductSyncCast implements CastsAttributes
$ps = new ProductSync();
$ps->qb_id = $data['qb_id'];
return $ps;
}
@@ -48,7 +47,7 @@ class ProductSyncCast implements CastsAttributes
return [
$key => json_encode([
'qb_id' => $value->qb_id,
])
]),
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -30,10 +30,9 @@ class QuickbooksSettingsCast implements CastsAttributes
public function set($model, string $key, $value, array $attributes)
{
if ($value instanceof QuickbooksSettings) {
return json_encode(get_object_vars($value));
return json_encode($value->toArray());
}
return null;
// return json_encode($value);
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -19,25 +19,21 @@ class QuoteSyncCast implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes)
{
if (is_null($value)) {
return null; // Return null if the value is null
}
$data = json_decode($value, true);
if (!is_array($data)) {
return null;
if (!is_array($data) || empty($data)) {
return null; // Return null if decoded data is not an array or is empty
}
$is = new QuoteSync($data);
return $is;
return QuoteSync::fromArray($data);
}
public function set($model, string $key, $value, array $attributes)
{
if (is_null($value)) {
return [$key => null];
}
@@ -45,8 +41,9 @@ class QuoteSyncCast implements CastsAttributes
return [
$key => json_encode([
'qb_id' => $value->qb_id,
'invitations' => $value->invitations,
'dn_completed' => $value->dn_completed,
])
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -39,7 +39,7 @@ class TransactionEventMetadataCast implements CastsAttributes
}
return [
$key => json_encode($value->toArray())
$key => json_encode($value->toArray()),
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -45,6 +45,7 @@ use App\Factory\ClientContactFactory;
use App\Factory\VendorContactFactory;
use App\Jobs\Company\CreateCompanyToken;
use App\Models\RecurringInvoiceInvitation;
use App\Utils\BcMath;
use App\Utils\Traits\CleanLineItems;
use Symfony\Component\Console\Input\InputOption;
@@ -194,8 +195,7 @@ class CheckData extends Command
if ($this->option('tasks') == 'true') {
$log = [(int) $log[0], (int) $log[1], (string) $log[2], (bool) $log[3]];
}
}
elseif(count($log) == 4){
} elseif (count($log) == 4) {
if ($this->option('tasks') == 'true') {
$log = [(int) $log[0], (int) $log[1], (string) $log[2], (bool) $log[3]];
@@ -757,7 +757,7 @@ class CheckData extends Command
$over_payment = $over_payment * -1;
if (floatval($over_payment) == floatval($client->balance)) {
if (BcMath::equal($over_payment, $client->balance)) {
} else {
$this->logMessage("# {$client->id} # {$client->name} {$client->balance} is invalid should be {$over_payment}");
}
@@ -868,9 +868,7 @@ class CheckData extends Command
$this->logMessage("{$this->wrong_balances} clients with incorrect ledger balances");
}
private function checkLogoFiles()
{
}
private function checkLogoFiles() {}
/**
* @return array

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -142,7 +142,7 @@ class CreateSingleAccount extends Command
'default_password_timeout' => 30 * 60000,
'portal_mode' => 'domain',
'portal_domain' => 'http://ninja.test:8000',
'track_inventory' => true
'track_inventory' => true,
]);
$custom_fields = new \stdClass();
@@ -223,21 +223,21 @@ class CreateSingleAccount extends Command
'user_id' => $user->id,
'company_id' => $company->id,
'name' => 'GST',
'rate' => 10
'rate' => 10,
]);
TaxRate::factory()->create([
'user_id' => $user->id,
'company_id' => $company->id,
'name' => 'VAT',
'rate' => 17.5
'rate' => 17.5,
]);
TaxRate::factory()->create([
'user_id' => $user->id,
'company_id' => $company->id,
'name' => 'CA Sales Tax',
'rate' => 5
'rate' => 5,
]);
$bi = BankIntegration::factory()->create([
@@ -261,7 +261,7 @@ class CreateSingleAccount extends Command
$client = Client::factory()->create([
'user_id' => $user->id,
'company_id' => $company->id,
'name' => 'cypress'
'name' => 'cypress',
]);
$client->custom_value1 = $company->company_key;
@@ -423,6 +423,18 @@ class CreateSingleAccount extends Command
'quantity' => 1,
]);
$p1a = Product::factory()->create([
'user_id' => $user->id,
'company_id' => $company->id,
'product_key' => 'pro_plan_annual',
'notes' => 'The Pro Plan Annual',
'cost' => 120,
'price' => 120,
'quantity' => 1,
]);
$p2 = Product::factory()->create([
'user_id' => $user->id,
'company_id' => $company->id,
@@ -558,6 +570,18 @@ class CreateSingleAccount extends Command
}
$sub = SubscriptionFactory::create($company->id, $user->id);
$sub->id = 66;
$sub->name = " PRO Pro Plan Annual";
$sub->group_id = $gs->id;
$sub->recurring_product_ids = "{$p1a->hashed_id}";
$sub->webhook_configuration = $webhook_config;
$sub->allow_plan_changes = true;
$sub->frequency_id = RecurringInvoice::FREQUENCY_ANNUALLY;
$sub->save();
$_sub = $sub->replicate();
$_sub->id = 41;
$_sub->name = "Enterprise Plan 3-5 Users";
@@ -613,7 +637,7 @@ class CreateSingleAccount extends Command
'company_id' => $company->id,
'product_key' => $key,
'notes' => $product['description'],
'price' => $product['price']
'price' => $product['price'],
]);
if (!Subscription::find($product['subscription_id'])) {
@@ -721,7 +745,7 @@ class CreateSingleAccount extends Command
'status_id' => $status->id ?? null,
'number' => rand(10000, 100000000),
'rate' => rand(1, 150),
'client_id' => $client->id
'client_id' => $client->id,
]);
}
@@ -739,7 +763,7 @@ class CreateSingleAccount extends Command
Carbon::now()->addSeconds($min)->timestamp,
Carbon::now()->addSeconds($min += $rando)->timestamp,
$this->faker->sentence,
rand(0, 1) === 0 ? false : true
rand(0, 1) === 0 ? false : true,
];
$min += 300;
@@ -1178,7 +1202,7 @@ class CreateSingleAccount extends Command
'company_id' => $company->id,
'name' => 'cypress',
'country_id' => 826,
'settings' => $c_settings
'settings' => $c_settings,
]);
$cg = new CompanyGateway();

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -34,7 +34,7 @@ class OpenApiYaml extends Command
private array $directories = [
'/components/schemas',
'/paths/'
'/paths/',
];
/**

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -0,0 +1,237 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Console\Commands;
use App\Utils\Ninja;
use App\Models\Account;
use App\Models\Company;
use App\Utils\TempFile;
use Illuminate\Console\Command;
use App\Utils\Traits\SavesDocuments;
use App\Services\EDocument\Gateway\Storecove\Storecove;
class PullPeppolDocs extends Command
{
use SavesDocuments;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'ninja:pull-peppol-docs';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Pull Peppol docs from the E-Invoice API';
/**
* Execute the console command.
*
* @return mixed
* @throws \Exception
*/
public function handle()
{
set_time_limit(3600);
if (Ninja::isHosted()) {
$this->info("Pulling Peppol docs is not supported on hosted.");
return;
}
$this->info("Pulling Peppol docs from the E-Invoice API");
$account = Account::first();
$quota_count = $account->e_invoice_quota;
$this->info("E-Invoice Quota Remaining: $quota_count");
$this->info("E-Invoice Token: " . $account->e_invoicing_token);
if (!isset($account->e_invoicing_token)) {
$this->info("No e-invoicing token found! You will not be able to authenticate with the E-Invoice API. Try logging out and back in again.");
$this->info("Updating Token...");
$response_array = $this->updateToken($account);
$this->info($response[1]);
if($response_array[0] != 200){
$this->error("Failed to update token exiting");
return;
}
}
$this->info("License key in use: " . config('ninja.license_key'));
Account::query()
->with('companies')
->where('e_invoice_quota', '>', 0)
->whereHas('companies', function ($q) {
$q->whereNotNull('legal_entity_id');
})
->cursor()
->each(function ($account) {
$account->companies->filter(function ($company) {
return $company->settings->e_invoice_type == 'PEPPOL' && ($company->tax_data->acts_as_receiver ?? false);
})
->each(function ($company) {
$this->info("Pulling Peppol docs for company: {$company->present()->name()}");
$response = \Illuminate\Support\Facades\Http::baseUrl(config('ninja.hosted_ninja_url'))
->withHeaders([
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'X-EInvoice-Token' => $company->account->e_invoicing_token,
])
->post('/api/einvoice/peppol/documents', data: [
'license_key' => config('ninja.license_key'),
'account_key' => $company->account->key,
'company_key' => $company->company_key,
'legal_entity_id' => $company->legal_entity_id,
]);
if ($response->successful()) {
$hash = $response->header('X-CONFIRMATION-HASH');
$this->info($response->body() );
$this->handleSuccess($response->json(), $company, $hash);
} else {
nlog($response->body());
}
});
});
}
private function updateToken(Account $account): array
{
$response = \Illuminate\Support\Facades\Http::baseUrl(config('ninja.hosted_ninja_url'))
->withHeaders([
'Content-Type' => 'application/json',
'Accept' => 'application/json',
])
->post('/api/einvoice/tokens/rotate', data: [
'license' => config('ninja.license_key'),
'account_key' => $account->key,
]);
if ($response->successful()) {
$account->update([
'e_invoicing_token' => $response->json('token'),
]);
return [200, $response->json('token')];
// return 'success';
}
return [422, $response->body()];
}
/**
* Handle the success of the Peppol docs pull
*
* @param array $received_documents
* @param Company $company
* @param string $hash
* @return void
*/
private function handleSuccess(array $received_documents, Company $company, string $hash): void
{
$storecove = new Storecove();
$doc_count = count($received_documents);
$this->info("{$doc_count} documents found.");
if ($doc_count > 0) {
$this->info('Processing documents...');
foreach ($received_documents as $document) {
$storecove_invoice = $storecove->expense->getStorecoveInvoice(json_encode($document['document']['invoice']));
$expense = $storecove->expense->createExpense($storecove_invoice, $company);
$file_name = $document['guid'];
if (strlen($document['html'] ?? '') > 5) {
$upload_document = TempFile::UploadedFileFromRaw($document['html'], "{$file_name}.html", 'text/html');
$this->saveDocument($upload_document, $expense, true);
$upload_document = null;
}
if (strlen($document['original_base64_xml'] ?? '') > 5) {
$upload_document = TempFile::UploadedFileFromBase64($document['original_base64_xml'], "{$file_name}.xml", 'application/xml');
$this->saveDocument($upload_document, $expense, true);
$upload_document = null;
}
foreach ($document['document']['invoice']['attachments'] as $attachment) {
$upload_document = TempFile::UploadedFileFromBase64($attachment['document'], $attachment['filename'], $attachment['mime_type']);
$this->saveDocument($upload_document, $expense, true);
$upload_document = null;
}
$this->info("Document {$file_name} processed.");
}
$this->info("Finished processing documents, flushing upstream...");
$response = \Illuminate\Support\Facades\Http::baseUrl(config('ninja.hosted_ninja_url'))
->withHeaders([
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'X-EInvoice-Token' => $company->account->e_invoicing_token,
])
->post('/api/einvoice/peppol/documents/flush', data: [
'license_key' => config('ninja.license_key'),
'account_key' => $company->account->key,
'company_key' => $company->company_key,
'legal_entity_id' => $company->legal_entity_id,
'hash' => $hash,
]);
if ($response->successful()) {
}
$this->info("Finished flushing upstream.");
$this->info("Finished task!");
}
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -205,9 +205,7 @@ class SendRemindersCron extends Command
}
}
private function webHookExpiredQuotes()
{
}
private function webHookExpiredQuotes() {}
private function executeWebhooks()
{

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www/elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -16,8 +16,8 @@ class ClientRegistrationFields
{
public static function generate()
{
$data =
[
$data
= [
[
'key' => 'first_name',
'required' => true,

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -1094,7 +1094,7 @@ class CompanySettings extends BaseSettings
],
'statement_details' => [
'$statement_date',
'$balance'
'$balance',
],
'delivery_note_columns' => [
'$product.item',

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -0,0 +1,10 @@
<?php
namespace App\DataMapper;
class DocuNinjaSync
{
public string $document_id = '';
public string $document_invitation_id = '';
public string $signature = '';
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -31,7 +31,7 @@ class EmailTemplateDefaults
'email_template_custom2',
'email_template_custom3',
'email_template_purchase_order',
'email_template_payment_failed'
'email_template_payment_failed',
];
public static function getDefaultTemplate($template, $locale)

View File

@@ -0,0 +1,45 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper;
use App\Casts\ExpenseSyncCast;
use App\DataMapper\TaxReport\TaxReport;
use Illuminate\Contracts\Database\Eloquent\Castable;
/**
* ExpenseSync.
*/
class ExpenseSync implements Castable
{
public string $qb_id;
public function __construct(array $attributes = [])
{
$this->qb_id = $attributes['qb_id'] ?? '';
}
/**
* Get the name of the caster class to use when casting from / to this cast target.
*
* @param array<string, mixed> $arguments
*/
public static function castUsing(array $arguments): string
{
return ExpenseSyncCast::class;
}
public static function fromArray(array $data): self
{
return new self($data);
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www/elastic.co/licensing/elastic-license
*/
@@ -103,4 +103,3 @@ class InvoiceBackup implements Castable
return $this->child_invoice_ids->toArray();
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -70,6 +70,8 @@ class InvoiceItem
public $unit_code = 'C62';
public $income_account_id = '';
public static $casts = [
'net_cost' => 'float',
'task_id' => 'string',
@@ -99,5 +101,6 @@ class InvoiceItem
'custom_value3' => 'string',
'custom_value4' => 'string',
'unit_code' => 'string',
'income_account_id' => 'string',
];
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -21,13 +21,12 @@ use Illuminate\Contracts\Database\Eloquent\Castable;
*/
class InvoiceSync implements Castable
{
public string $qb_id;
public function __construct(array $attributes = [])
{
$this->qb_id = $attributes['qb_id'] ?? '';
}
public function __construct(
public string $qb_id = '',
public array $invitations = [],
public bool $dn_completed = false,
){}
/**
* Get the name of the caster class to use when casting from / to this cast target.
*
@@ -40,6 +39,62 @@ class InvoiceSync implements Castable
public static function fromArray(array $data): self
{
return new self($data);
return new self(
qb_id: $data['qb_id'] ?? '',
invitations: $data['invitations'] ?? [],
dn_completed: $data['dn_completed'] ?? false,
);
}
/**
* Add an invitation to the invitations array
*
* @param string $invitation_key The invitation key
* @param string $dn_id The DocuNinja ID
* @param string $dn_invitation_id The DocuNinja invitation ID
* @param string $dn_sig The DocuNinja signature
*/
public function addInvitation(
string $invitation_key,
string $dn_id,
string $dn_invitation_id,
string $dn_sig
): void {
$this->invitations[] = [
'invitation_key' => $invitation_key,
'dn_id' => $dn_id,
'dn_invitation_id' => $dn_invitation_id,
'dn_sig' => $dn_sig,
];
}
/**
* Get invitation data by invitation key
*
* @param string $invitation_key The invitation key
* @return array|null The invitation data or null if not found
*/
public function getInvitation(string $invitation_key): ?array
{
foreach ($this->invitations as $invitation) {
if ($invitation['invitation_key'] === $invitation_key) {
return $invitation;
}
}
return null;
}
/**
* Remove an invitation by invitation key
*
* @param string $invitation_key The invitation key
*/
public function removeInvitation(string $invitation_key): void
{
$this->invitations = array_filter($this->invitations, function($invitation) use ($invitation_key) {
return $invitation['invitation_key'] !== $invitation_key;
});
// Re-index the array to maintain numeric keys
$this->invitations = array_values($this->invitations);
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -32,6 +32,8 @@ class QuickbooksSettings implements Castable
public string $baseURL;
public string $companyName;
public QuickbooksSync $settings;
public function __construct(array $attributes = [])
@@ -42,6 +44,7 @@ class QuickbooksSettings implements Castable
$this->accessTokenExpiresAt = $attributes['accessTokenExpiresAt'] ?? 0;
$this->refreshTokenExpiresAt = $attributes['refreshTokenExpiresAt'] ?? 0;
$this->baseURL = $attributes['baseURL'] ?? '';
$this->companyName = $attributes['companyName'] ?? '';
$this->settings = new QuickbooksSync($attributes['settings'] ?? []);
}
@@ -55,4 +58,75 @@ class QuickbooksSettings implements Castable
return new self($data);
}
public function toArray(): array
{
return [
'accessTokenKey' => $this->accessTokenKey,
'refresh_token' => $this->refresh_token,
'realmID' => $this->realmID,
'accessTokenExpiresAt' => $this->accessTokenExpiresAt,
'refreshTokenExpiresAt' => $this->refreshTokenExpiresAt,
'baseURL' => $this->baseURL,
'companyName' => $this->companyName,
'settings' => $this->settings->toArray(),
];
}
/**
*
* Patches our settings object with the
* selected changes we authorize.
*
* @param array $changes
* @return self
*/
public function with(array $changes): self
{
$settings = $this->settings->toArray();
$new_settings = [
'client' => [
'direction' => $changes['client']['direction'] ?? $this->settings->client->direction->value,
],
'invoice' => [
'direction' => $changes['invoice']['direction'] ?? $this->settings->invoice->direction->value,
],
'product' => [
'direction' => $changes['product']['direction'] ?? $this->settings->product->direction->value,
],
'qb_income_account_id' => $changes['qb_income_account_id'] ?? $this->settings->qb_income_account_id,
'automatic_taxes' => $changes['automatic_taxes'] ?? $this->settings->automatic_taxes,
];
$final_settings['settings'] = array_merge($settings, $new_settings);
return new self(array_merge($this->toArray(), $final_settings));
}
/**
* Check if this QuickbooksSettings instance represents actual data or is just a default empty object.
*
* @return bool True if this has actual QuickBooks connection data, false if it's just defaults
*/
public function isConfigured(): bool
{
// If accessTokenKey is set, we have a connection
return !empty($this->accessTokenKey);
}
/**
* Check if this QuickbooksSettings instance is empty (default values only).
*
* @return bool True if this is an empty/default instance
*/
public function isEmpty(): bool
{
return empty($this->accessTokenKey)
&& empty($this->refresh_token)
&& empty($this->realmID)
&& $this->accessTokenExpiresAt === 0
&& $this->refreshTokenExpiresAt === 0
&& empty($this->baseURL);
}
}

View File

@@ -5,15 +5,22 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper;
use App\Models\Product;
/**
* QuickbooksSync.
*
* Product type to income account mapping:
* Keys are Product::PRODUCT_TYPE_* constants (int). Values are QuickBooks account IDs (string|null).
* Example: [Product::PRODUCT_TYPE_SERVICE => '123', Product::PRODUCT_TYPE_PHYSICAL => '456']
* Null values indicate the account has not been configured for that product type.
*/
class QuickbooksSync
{
@@ -35,9 +42,25 @@ class QuickbooksSync
public QuickbooksSyncMap $expense;
public string $default_income_account = '';
public QuickbooksSyncMap $expense_category;
public string $default_expense_account = '';
/**
* QuickBooks income account ID per product type.
* Use getAccountId(int $productTypeId) or the typed properties (physical, service, etc.).
*/
public array $income_account_map;
public array $tax_rate_map;
public ?string $qb_income_account_id = null;
public bool $automatic_taxes = false;
public ?string $default_taxable_code = null;
public ?string $default_exempt_code = null;
public ?string $country = null;
public function __construct(array $attributes = [])
{
@@ -50,7 +73,36 @@ class QuickbooksSync
$this->product = new QuickbooksSyncMap($attributes['product'] ?? []);
$this->payment = new QuickbooksSyncMap($attributes['payment'] ?? []);
$this->expense = new QuickbooksSyncMap($attributes['expense'] ?? []);
$this->default_income_account = $attributes['default_income_account'] ?? '';
$this->default_expense_account = $attributes['default_expense_account'] ?? '';
$this->expense_category = new QuickbooksSyncMap($attributes['expense_category'] ?? []);
$this->income_account_map = $attributes['income_account_map'] ?? [];
$this->qb_income_account_id = $attributes['qb_income_account_id'] ?? null;
$this->tax_rate_map = $attributes['tax_rate_map'] ?? [];
$this->automatic_taxes = $attributes['automatic_taxes'] ?? false; //requires us to syncronously push the invoice to QB, and return fully formed Invoice with taxes included.
$this->default_taxable_code = $attributes['default_taxable_code'] ?? null;
$this->default_exempt_code = $attributes['default_exempt_code'] ?? null;
$this->country = $attributes['country'] ?? null;
}
public function toArray(): array
{
return [
'client' => $this->client->toArray(),
'vendor' => $this->vendor->toArray(),
'invoice' => $this->invoice->toArray(),
'sales' => $this->sales->toArray(),
'quote' => $this->quote->toArray(),
'purchase_order' => $this->purchase_order->toArray(),
'product' => $this->product->toArray(),
'payment' => $this->payment->toArray(),
'expense' => $this->expense->toArray(),
'expense_category' => $this->expense_category->toArray(),
'income_account_map' => $this->income_account_map,
'qb_income_account_id' => $this->qb_income_account_id,
'tax_rate_map' => $this->tax_rate_map,
'automatic_taxes' => $this->automatic_taxes,
'default_taxable_code' => $this->default_taxable_code,
'default_exempt_code' => $this->default_exempt_code,
'country' => $this->country,
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -19,13 +19,19 @@ use App\Enum\SyncDirection;
*/
class QuickbooksSyncMap
{
public SyncDirection $direction = SyncDirection::BIDIRECTIONAL;
public SyncDirection $direction = SyncDirection::NONE;
public function __construct(array $attributes = [])
{
$this->direction = isset($attributes['direction'])
? SyncDirection::from($attributes['direction'])
: SyncDirection::BIDIRECTIONAL;
: SyncDirection::NONE;
}
public function toArray(): array
{
return [
'direction' => $this->direction->value,
];
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -20,15 +20,11 @@ use Illuminate\Contracts\Database\Eloquent\Castable;
*/
class QuoteSync implements Castable
{
public string $qb_id;
public function __construct(array $attributes = [])
{
$this->qb_id = $attributes['qb_id'] ?? '';
}
public function __construct(
public string $qb_id = '',
public array $invitations = [],
public bool $dn_completed = false,
){}
/**
* Get the name of the caster class to use when casting from / to this cast target.
*
@@ -41,6 +37,62 @@ class QuoteSync implements Castable
public static function fromArray(array $data): self
{
return new self($data);
return new self(
qb_id: $data['qb_id'] ?? '',
invitations: $data['invitations'] ?? [],
dn_completed: $data['dn_completed'] ?? false,
);
}
/**
* Add an invitation to the invitations array
*
* @param string $invitation_key The invitation key
* @param string $dn_id The DocuNinja ID
* @param string $dn_invitation_id The DocuNinja invitation ID
* @param string $dn_sig The DocuNinja signature
*/
public function addInvitation(
string $invitation_key,
string $dn_id,
string $dn_invitation_id,
string $dn_sig
): void {
$this->invitations[] = [
'invitation_key' => $invitation_key,
'dn_id' => $dn_id,
'dn_invitation_id' => $dn_invitation_id,
'dn_sig' => $dn_sig,
];
}
/**
* Get invitation data by invitation key
*
* @param string $invitation_key The invitation key
* @return array|null The invitation data or null if not found
*/
public function getInvitation(string $invitation_key): ?array
{
foreach ($this->invitations as $invitation) {
if ($invitation['invitation_key'] === $invitation_key) {
return $invitation;
}
}
return null;
}
/**
* Remove an invitation by invitation key
*
* @param string $invitation_key The invitation key
*/
public function removeInvitation(string $invitation_key): void
{
$this->invitations = array_filter($this->invitations, function($invitation) use ($invitation_key) {
return $invitation['invitation_key'] !== $invitation_key;
});
// Re-index the array to maintain numeric keys
$this->invitations = array_values($this->invitations);
}
}

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -14,7 +14,6 @@ namespace App\DataMapper\Schedule;
class InvoiceOutstandingTasks
{
/**
* Defines the template name
*

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -276,6 +276,10 @@ class SettingsData
public string $email_template_reminder_endless = ''; //@implemented
public string $email_template_payment_failed = ''; //@implemented
public string $email_subject_payment_failed = ''; //@implemented
public string $email_signature = ''; //@implemented
public bool $enable_email_markup = true; //@TODO -

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
@@ -106,9 +106,7 @@ class PayPalBalanceAffecting
public $creditTransactionalFee;
public $originalInvoiceId;
public function __construct(private array $import_row)
{
}
public function __construct(private array $import_row) {}
public function run(): self
{

View File

@@ -5,7 +5,7 @@
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
* @copyright Copyright (c) 2026. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

Some files were not shown because too many files have changed in this diff Show More