mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-07 19:04:41 -04:00
Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses
This commit is contained in:
commit
13dae4f524
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -8,7 +8,7 @@ assignees: ''
|
|||||||
---
|
---
|
||||||
|
|
||||||
<!-- Before posting please check our "Troubleshooting" category in the docs:
|
<!-- Before posting please check our "Troubleshooting" category in the docs:
|
||||||
https://invoiceninja.github.io/docs/self-host-troubleshooting/ -->
|
https://invoiceninja.github.io/en/self-host-troubleshooting/ -->
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
- Version: <!-- i.e. v4.5.25 / v5.0.30 -->
|
- Version: <!-- i.e. v4.5.25 / v5.0.30 -->
|
||||||
|
@ -51,7 +51,9 @@ All Pro and Enterprise features from the hosted app are included in the open-sou
|
|||||||
* [Docker File](https://hub.docker.com/r/invoiceninja/invoiceninja/)
|
* [Docker File](https://hub.docker.com/r/invoiceninja/invoiceninja/)
|
||||||
* [Cloudron](https://www.cloudron.io/store/com.invoiceninja.cloudronapp2.html)
|
* [Cloudron](https://www.cloudron.io/store/com.invoiceninja.cloudronapp2.html)
|
||||||
* [Softaculous](https://www.softaculous.com/apps/ecommerce/Invoice_Ninja)
|
* [Softaculous](https://www.softaculous.com/apps/ecommerce/Invoice_Ninja)
|
||||||
|
* [Elestio](https://elest.io/open-source/invoiceninja)
|
||||||
|
* [YunoHost](https://apps.yunohost.org/app/invoiceninja5)
|
||||||
|
|
||||||
### Recommended Providers
|
### Recommended Providers
|
||||||
* [Stripe](https://stripe.com/)
|
* [Stripe](https://stripe.com/)
|
||||||
* [Postmark](https://postmarkapp.com/)
|
* [Postmark](https://postmarkapp.com/)
|
||||||
|
@ -1 +1 @@
|
|||||||
5.10.16
|
5.10.26
|
50
app/Casts/QuickbooksSettingsCast.php
Normal file
50
app/Casts/QuickbooksSettingsCast.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Casts;
|
||||||
|
|
||||||
|
use App\DataMapper\QuickbooksSettings;
|
||||||
|
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
||||||
|
|
||||||
|
class QuickbooksSettingsCast implements CastsAttributes
|
||||||
|
{
|
||||||
|
public function get($model, string $key, $value, array $attributes)
|
||||||
|
{
|
||||||
|
$data = json_decode($value, true);
|
||||||
|
|
||||||
|
if(!is_array($data))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
$qb = new QuickbooksSettings();
|
||||||
|
$qb->accessTokenKey = $data['accessTokenKey'];
|
||||||
|
$qb->refresh_token = $data['refresh_token'];
|
||||||
|
$qb->realmID = $data['realmID'];
|
||||||
|
$qb->accessTokenExpiresAt = $data['accessTokenExpiresAt'];
|
||||||
|
$qb->refreshTokenExpiresAt = $data['refreshTokenExpiresAt'];
|
||||||
|
$qb->settings = $data['settings'] ?? [];
|
||||||
|
|
||||||
|
return $qb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set($model, string $key, $value, array $attributes)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
$key => json_encode([
|
||||||
|
'accessTokenKey' => $value->accessTokenKey,
|
||||||
|
'refresh_token' => $value->refresh_token,
|
||||||
|
'realmID' => $value->realmID,
|
||||||
|
'accessTokenExpiresAt' => $value->accessTokenExpiresAt,
|
||||||
|
'refreshTokenExpiresAt' => $value->refreshTokenExpiresAt,
|
||||||
|
'settings' => $value->settings,
|
||||||
|
])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -1169,10 +1169,10 @@ class CheckData extends Command
|
|||||||
->whereNull('exchange_rate')
|
->whereNull('exchange_rate')
|
||||||
->orWhere('exchange_rate', 0)
|
->orWhere('exchange_rate', 0)
|
||||||
->cursor()
|
->cursor()
|
||||||
->each(function ($expense){
|
->each(function ($expense) {
|
||||||
$expense->exchange_rate = 1;
|
$expense->exchange_rate = 1;
|
||||||
$expense->saveQuietly();
|
$expense->saveQuietly();
|
||||||
|
|
||||||
$this->logMessage("Fixing - exchange rate for expense :: {$expense->id}");
|
$this->logMessage("Fixing - exchange rate for expense :: {$expense->id}");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1116,7 +1116,7 @@ class CreateSingleAccount extends Command
|
|||||||
|
|
||||||
private function countryClients($company, $user)
|
private function countryClients($company, $user)
|
||||||
{
|
{
|
||||||
|
|
||||||
Client::unguard();
|
Client::unguard();
|
||||||
|
|
||||||
Client::create([
|
Client::create([
|
||||||
|
@ -15,7 +15,6 @@ use App\Jobs\Cron\AutoBillCron;
|
|||||||
use App\Jobs\Cron\RecurringExpensesCron;
|
use App\Jobs\Cron\RecurringExpensesCron;
|
||||||
use App\Jobs\Cron\RecurringInvoicesCron;
|
use App\Jobs\Cron\RecurringInvoicesCron;
|
||||||
use App\Jobs\Cron\SubscriptionCron;
|
use App\Jobs\Cron\SubscriptionCron;
|
||||||
use App\Jobs\Cron\UpdateCalculatedFields;
|
|
||||||
use App\Jobs\Invoice\InvoiceCheckLateWebhook;
|
use App\Jobs\Invoice\InvoiceCheckLateWebhook;
|
||||||
use App\Jobs\Ninja\AdjustEmailQuota;
|
use App\Jobs\Ninja\AdjustEmailQuota;
|
||||||
use App\Jobs\Ninja\BankTransactionSync;
|
use App\Jobs\Ninja\BankTransactionSync;
|
||||||
@ -33,6 +32,7 @@ use App\Jobs\Util\SchedulerCheck;
|
|||||||
use App\Jobs\Util\UpdateExchangeRates;
|
use App\Jobs\Util\UpdateExchangeRates;
|
||||||
use App\Jobs\Util\VersionCheck;
|
use App\Jobs\Util\VersionCheck;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
|
use App\PaymentDrivers\Rotessa\Jobs\TransactionReport;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
@ -65,11 +65,11 @@ class Kernel extends ConsoleKernel
|
|||||||
/* Checks for scheduled tasks */
|
/* Checks for scheduled tasks */
|
||||||
$schedule->job(new TaskScheduler())->hourlyAt(10)->withoutOverlapping()->name('task-scheduler-job')->onOneServer();
|
$schedule->job(new TaskScheduler())->hourlyAt(10)->withoutOverlapping()->name('task-scheduler-job')->onOneServer();
|
||||||
|
|
||||||
/* Stale Invoice Cleanup*/
|
/* Checks Rotessa Transactions */
|
||||||
$schedule->job(new CleanStaleInvoiceOrder())->hourlyAt(30)->withoutOverlapping()->name('stale-invoice-job')->onOneServer();
|
$schedule->job(new TransactionReport())->dailyAt('01:48')->withoutOverlapping()->name('rotessa-transaction-report')->onOneServer();
|
||||||
|
|
||||||
/* Stale Invoice Cleanup*/
|
/* Stale Invoice Cleanup*/
|
||||||
$schedule->job(new UpdateCalculatedFields())->hourlyAt(40)->withoutOverlapping()->name('update-calculated-fields-job')->onOneServer();
|
$schedule->job(new CleanStaleInvoiceOrder())->hourlyAt(30)->withoutOverlapping()->name('stale-invoice-job')->onOneServer();
|
||||||
|
|
||||||
/* Checks for large companies and marked them as is_large */
|
/* Checks for large companies and marked them as is_large */
|
||||||
$schedule->job(new CompanySizeCheck())->dailyAt('23:20')->withoutOverlapping()->name('company-size-job')->onOneServer();
|
$schedule->job(new CompanySizeCheck())->dailyAt('23:20')->withoutOverlapping()->name('company-size-job')->onOneServer();
|
||||||
|
@ -515,10 +515,11 @@ class CompanySettings extends BaseSettings
|
|||||||
public $quote_schedule_reminder1 = ''; //before_valid_until_date,after_valid_until_date,after_quote_date
|
public $quote_schedule_reminder1 = ''; //before_valid_until_date,after_valid_until_date,after_quote_date
|
||||||
public $quote_late_fee_amount1 = 0;
|
public $quote_late_fee_amount1 = 0;
|
||||||
public $quote_late_fee_percent1 = 0;
|
public $quote_late_fee_percent1 = 0;
|
||||||
|
|
||||||
|
|
||||||
|
public string $payment_flow = 'default'; //smooth
|
||||||
|
|
||||||
public static $casts = [
|
public static $casts = [
|
||||||
|
'payment_flow' => 'string',
|
||||||
'enable_quote_reminder1' => 'bool',
|
'enable_quote_reminder1' => 'bool',
|
||||||
'quote_num_days_reminder1' => 'int',
|
'quote_num_days_reminder1' => 'int',
|
||||||
'quote_schedule_reminder1' => 'string',
|
'quote_schedule_reminder1' => 'string',
|
||||||
|
@ -120,7 +120,7 @@ class EmailTemplateDefaults
|
|||||||
|
|
||||||
case 'email_quote_subject_reminder1':
|
case 'email_quote_subject_reminder1':
|
||||||
return self::emailQuoteReminder1Subject();
|
return self::emailQuoteReminder1Subject();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return self::emailInvoiceTemplate();
|
return self::emailInvoiceTemplate();
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ class EmailTemplateDefaults
|
|||||||
{
|
{
|
||||||
return ctrans('texts.quote_reminder_subject', ['quote' => '$number', 'company' => '$company.name']);
|
return ctrans('texts.quote_reminder_subject', ['quote' => '$number', 'company' => '$company.name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function emailQuoteReminder1Body()
|
public static function emailQuoteReminder1Body()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ class EmailTemplateDefaults
|
|||||||
return $invoice_message;
|
return $invoice_message;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function emailVendorNotificationSubject()
|
public static function emailVendorNotificationSubject()
|
||||||
{
|
{
|
||||||
return self::transformText('vendor_notification_subject');
|
return self::transformText('vendor_notification_subject');
|
||||||
|
59
app/DataMapper/QuickbooksSettings.php
Normal file
59
app/DataMapper/QuickbooksSettings.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\DataMapper;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Database\Eloquent\Castable;
|
||||||
|
use App\Casts\QuickbooksSettingsCast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuickbooksSettings.
|
||||||
|
*/
|
||||||
|
class QuickbooksSettings implements Castable
|
||||||
|
{
|
||||||
|
public string $accessTokenKey;
|
||||||
|
|
||||||
|
public string $refresh_token;
|
||||||
|
|
||||||
|
public string $realmID;
|
||||||
|
|
||||||
|
public int $accessTokenExpiresAt;
|
||||||
|
|
||||||
|
public int $refreshTokenExpiresAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* entity client,invoice,quote,purchase_order,vendor,payment
|
||||||
|
* sync true/false
|
||||||
|
* update_record true/false
|
||||||
|
* direction push/pull/birectional
|
||||||
|
* */
|
||||||
|
public array $settings = [
|
||||||
|
'client' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
|
||||||
|
'vendor' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
|
||||||
|
'invoice' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
|
||||||
|
'quote' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
|
||||||
|
'purchase_order' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
|
||||||
|
'product' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
|
||||||
|
'payment' => ['sync' => true, 'update_record' => true, 'direction' => 'bidirectional'],
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 QuickbooksSettingsCast::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,6 +17,7 @@ use App\Models\Invoice;
|
|||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use App\DataProviders\USStates;
|
use App\DataProviders\USStates;
|
||||||
use App\DataMapper\Tax\ZipTax\Response;
|
use App\DataMapper\Tax\ZipTax\Response;
|
||||||
|
use App\Models\RecurringInvoice;
|
||||||
|
|
||||||
class BaseRule implements RuleInterface
|
class BaseRule implements RuleInterface
|
||||||
{
|
{
|
||||||
@ -132,7 +133,7 @@ class BaseRule implements RuleInterface
|
|||||||
|
|
||||||
public function shouldCalcTax(): bool
|
public function shouldCalcTax(): bool
|
||||||
{
|
{
|
||||||
return $this->should_calc_tax;
|
return $this->should_calc_tax && $this->checkIfInvoiceLocked();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Initializes the tax rule for the entity.
|
* Initializes the tax rule for the entity.
|
||||||
@ -215,7 +216,7 @@ class BaseRule implements RuleInterface
|
|||||||
|
|
||||||
$this->invoice->tax_data = $tax_data;
|
$this->invoice->tax_data = $tax_data;
|
||||||
|
|
||||||
if(\DB::transactionLevel() == 0) {
|
if(\DB::transactionLevel() == 0 && isset($this->invoice->id)) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->invoice->saveQuietly();
|
$this->invoice->saveQuietly();
|
||||||
@ -400,4 +401,40 @@ class BaseRule implements RuleInterface
|
|||||||
return ! in_array($iso_3166_2, array_merge($this->eu_country_codes, array_keys($this->region_codes)));
|
return ! in_array($iso_3166_2, array_merge($this->eu_country_codes, array_keys($this->region_codes)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function checkIfInvoiceLocked(): bool
|
||||||
|
{
|
||||||
|
$lock_invoices = $this->client->getSetting('lock_invoices');
|
||||||
|
|
||||||
|
if($this->invoice instanceof RecurringInvoice) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($lock_invoices) {
|
||||||
|
case 'off':
|
||||||
|
return true;
|
||||||
|
case 'when_sent':
|
||||||
|
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 'when_paid':
|
||||||
|
if ($this->invoice->status_id == Invoice::STATUS_PAID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//if now is greater than the end of month the invoice was dated - do not modify
|
||||||
|
case 'end_of_month':
|
||||||
|
if(\Carbon\Carbon::parse($this->invoice->date)->setTimezone($this->invoice->company->timezone()->name)->endOfMonth()->lte(now())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,8 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
public float $reduced_tax_rate = 0;
|
public float $reduced_tax_rate = 0;
|
||||||
|
|
||||||
public string $tax_name1 = 'MwSt.';
|
public string $tax_name1 = 'MwSt.';
|
||||||
|
|
||||||
|
private string $tax_name;
|
||||||
/**
|
/**
|
||||||
* Initializes the rules and builds any required data.
|
* Initializes the rules and builds any required data.
|
||||||
*
|
*
|
||||||
@ -50,6 +52,7 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
*/
|
*/
|
||||||
public function init(): self
|
public function init(): self
|
||||||
{
|
{
|
||||||
|
$this->tax_name = $this->tax_name1;
|
||||||
$this->calculateRates();
|
$this->calculateRates();
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -91,6 +94,7 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
*/
|
*/
|
||||||
public function reverseTax($item): self
|
public function reverseTax($item): self
|
||||||
{
|
{
|
||||||
|
$this->tax_name1 = $this->tax_name;
|
||||||
$this->tax_rate1 = 0;
|
$this->tax_rate1 = 0;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -103,6 +107,8 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
*/
|
*/
|
||||||
public function taxReduced($item): self
|
public function taxReduced($item): self
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$this->tax_name1 = $this->tax_name;
|
||||||
$this->tax_rate1 = $this->reduced_tax_rate;
|
$this->tax_rate1 = $this->reduced_tax_rate;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -115,6 +121,8 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
*/
|
*/
|
||||||
public function zeroRated($item): self
|
public function zeroRated($item): self
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$this->tax_name1 = $this->tax_name;
|
||||||
$this->tax_rate1 = 0;
|
$this->tax_rate1 = 0;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -142,6 +150,7 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
public function taxDigital($item): self
|
public function taxDigital($item): self
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$this->tax_name1 = $this->tax_name;
|
||||||
$this->tax_rate1 = $this->tax_rate;
|
$this->tax_rate1 = $this->tax_rate;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -155,6 +164,7 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
public function taxService($item): self
|
public function taxService($item): self
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$this->tax_name1 = $this->tax_name;
|
||||||
$this->tax_rate1 = $this->tax_rate;
|
$this->tax_rate1 = $this->tax_rate;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -168,6 +178,7 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
public function taxShipping($item): self
|
public function taxShipping($item): self
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$this->tax_name1 = $this->tax_name;
|
||||||
$this->tax_rate1 = $this->tax_rate;
|
$this->tax_rate1 = $this->tax_rate;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -181,6 +192,7 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
public function taxPhysical($item): self
|
public function taxPhysical($item): self
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$this->tax_name1 = $this->tax_name;
|
||||||
$this->tax_rate1 = $this->tax_rate;
|
$this->tax_rate1 = $this->tax_rate;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -229,8 +241,7 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
// nlog("tax exempt");
|
// nlog("tax exempt");
|
||||||
$this->tax_rate = 0;
|
$this->tax_rate = 0;
|
||||||
$this->reduced_tax_rate = 0;
|
$this->reduced_tax_rate = 0;
|
||||||
} elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->vat_number && $this->eu_business_tax_exempt) {
|
} elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->vat_number && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt) {
|
||||||
// elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt)
|
|
||||||
// nlog("euro zone and tax exempt");
|
// nlog("euro zone and tax exempt");
|
||||||
$this->tax_rate = 0;
|
$this->tax_rate = 0;
|
||||||
$this->reduced_tax_rate = 0;
|
$this->reduced_tax_rate = 0;
|
||||||
@ -240,8 +251,8 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
$this->reduced_tax_rate = 0;
|
$this->reduced_tax_rate = 0;
|
||||||
} elseif(!in_array($this->client_subregion, $this->eu_country_codes)) {
|
} elseif(!in_array($this->client_subregion, $this->eu_country_codes)) {
|
||||||
$this->defaultForeign();
|
$this->defaultForeign();
|
||||||
} elseif(in_array($this->client_subregion, $this->eu_country_codes) && !$this->client->vat_number) { //eu country / no valid vat
|
} elseif(in_array($this->client_subregion, $this->eu_country_codes) && ((strlen($this->client->vat_number ?? '') == 1) || !$this->client->has_valid_vat_number)) { //eu country / no valid vat
|
||||||
if(($this->client->company->tax_data->seller_subregion != $this->client_subregion) && $this->client->company->tax_data->regions->EU->has_sales_above_threshold) {
|
if($this->client->company->tax_data->seller_subregion != $this->client_subregion) {
|
||||||
// nlog("eu zone with sales above threshold");
|
// nlog("eu zone with sales above threshold");
|
||||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->tax_rate ?? 0;
|
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->tax_rate ?? 0;
|
||||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_tax_rate ?? 0;
|
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_tax_rate ?? 0;
|
||||||
|
@ -34,10 +34,10 @@ class TaxModel
|
|||||||
if(!$model) {
|
if(!$model) {
|
||||||
$this->regions = $this->init();
|
$this->regions = $this->init();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//@phpstan-ignore-next-line
|
//@phpstan-ignore-next-line
|
||||||
foreach($model as $key => $value) {
|
foreach($model as $key => $value) {
|
||||||
$this->{$key} = $value;
|
$this->{$key} = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -48,8 +48,7 @@ class TaxModel
|
|||||||
public function migrate(): self
|
public function migrate(): self
|
||||||
{
|
{
|
||||||
|
|
||||||
if($this->version == 'alpha')
|
if($this->version == 'alpha') {
|
||||||
{
|
|
||||||
$this->regions->EU->subregions->PL = new \stdClass();
|
$this->regions->EU->subregions->PL = new \stdClass();
|
||||||
$this->regions->EU->subregions->PL->tax_rate = 23;
|
$this->regions->EU->subregions->PL->tax_rate = 23;
|
||||||
$this->regions->EU->subregions->PL->tax_name = 'VAT';
|
$this->regions->EU->subregions->PL->tax_name = 'VAT';
|
||||||
|
68
app/DataProviders/CAProvinces.php
Normal file
68
app/DataProviders/CAProvinces.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\DataProviders;
|
||||||
|
|
||||||
|
final class CAProvinces
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The provinces and territories of Canada
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $provinces = [
|
||||||
|
'AB' => 'Alberta',
|
||||||
|
'BC' => 'British Columbia',
|
||||||
|
'MB' => 'Manitoba',
|
||||||
|
'NB' => 'New Brunswick',
|
||||||
|
'NL' => 'Newfoundland And Labrador',
|
||||||
|
'NS' => 'Nova Scotia',
|
||||||
|
'ON' => 'Ontario',
|
||||||
|
'PE' => 'Prince Edward Island',
|
||||||
|
'QC' => 'Quebec',
|
||||||
|
'SK' => 'Saskatchewan',
|
||||||
|
'NT' => 'Northwest Territories',
|
||||||
|
'NU' => 'Nunavut',
|
||||||
|
'YT' => 'Yukon'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the province or territory for a given abbreviation.
|
||||||
|
*
|
||||||
|
* @param string $abbreviation
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getName($abbreviation)
|
||||||
|
{
|
||||||
|
return self::$provinces[$abbreviation];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all provinces and territories.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function get()
|
||||||
|
{
|
||||||
|
return self::$provinces;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the abbreviation for a given province or territory name.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getAbbreviation($name)
|
||||||
|
{
|
||||||
|
return array_search(ucwords($name), self::$provinces);
|
||||||
|
}
|
||||||
|
}
|
@ -58,7 +58,7 @@ class ClientWasArchived implements ShouldBroadcast
|
|||||||
|
|
||||||
public function broadcastWith()
|
public function broadcastWith()
|
||||||
{
|
{
|
||||||
|
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
$manager->setSerializer(new ArraySerializer());
|
$manager->setSerializer(new ArraySerializer());
|
||||||
$class = sprintf('App\\Transformers\\%sTransformer', class_basename($this->client));
|
$class = sprintf('App\\Transformers\\%sTransformer', class_basename($this->client));
|
||||||
@ -79,7 +79,7 @@ class ClientWasArchived implements ShouldBroadcast
|
|||||||
*/
|
*/
|
||||||
public function broadcastOn()
|
public function broadcastOn()
|
||||||
{
|
{
|
||||||
|
|
||||||
return [
|
return [
|
||||||
new PrivateChannel("company-{$this->company->company_key}"),
|
new PrivateChannel("company-{$this->company->company_key}"),
|
||||||
];
|
];
|
||||||
|
@ -39,6 +39,6 @@ class DuplicatePaymentException extends Exception
|
|||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Duplicate request',
|
'message' => 'Duplicate request',
|
||||||
], 400);
|
], 400);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,8 +129,8 @@ class ActivityExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($entity) {
|
->each(function ($entity) {
|
||||||
|
|
||||||
/** @var \App\Models\Activity $entity */
|
/** @var \App\Models\Activity $entity */
|
||||||
|
|
||||||
$this->buildRow($entity);
|
$this->buildRow($entity);
|
||||||
});
|
});
|
||||||
|
@ -451,6 +451,7 @@ class BaseExport
|
|||||||
'project' => 'task.project_id',
|
'project' => 'task.project_id',
|
||||||
'billable' => 'task.billable',
|
'billable' => 'task.billable',
|
||||||
'item_notes' => 'task.item_notes',
|
'item_notes' => 'task.item_notes',
|
||||||
|
'time_log' => 'task.time_log',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected array $forced_client_fields = [
|
protected array $forced_client_fields = [
|
||||||
@ -1040,7 +1041,7 @@ class BaseExport
|
|||||||
|
|
||||||
$recurring_filters = [];
|
$recurring_filters = [];
|
||||||
|
|
||||||
if($this->company->getSetting('report_include_drafts')){
|
if($this->company->getSetting('report_include_drafts')) {
|
||||||
$recurring_filters[] = RecurringInvoice::STATUS_DRAFT;
|
$recurring_filters[] = RecurringInvoice::STATUS_DRAFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1188,7 +1189,7 @@ class BaseExport
|
|||||||
*/
|
*/
|
||||||
protected function addInvoiceStatusFilter(Builder $query, string $status): Builder
|
protected function addInvoiceStatusFilter(Builder $query, string $status): Builder
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var array $status_parameters */
|
/** @var array $status_parameters */
|
||||||
$status_parameters = explode(',', $status);
|
$status_parameters = explode(',', $status);
|
||||||
|
|
||||||
@ -1258,7 +1259,7 @@ class BaseExport
|
|||||||
|
|
||||||
$date_range = $this->input['date_range'];
|
$date_range = $this->input['date_range'];
|
||||||
|
|
||||||
if (array_key_exists('date_key', $this->input) && strlen($this->input['date_key']) > 1 && ($table_name && $this->columnExists($table_name, $this->input['date_key']))) {
|
if (array_key_exists('date_key', $this->input) && strlen($this->input['date_key'] ?? '') > 1 && ($table_name && $this->columnExists($table_name, $this->input['date_key']))) {
|
||||||
$this->date_key = $this->input['date_key'];
|
$this->date_key = $this->input['date_key'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1615,10 +1616,10 @@ class BaseExport
|
|||||||
ZipDocuments::dispatch($documents, $this->company, $user);
|
ZipDocuments::dispatch($documents, $this->company, $user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that the column exists
|
* Tests that the column exists
|
||||||
* on the table prior to adding it to
|
* on the table prior to adding it to
|
||||||
* the query builder
|
* the query builder
|
||||||
*
|
*
|
||||||
* @param string $table
|
* @param string $table
|
||||||
|
@ -102,7 +102,7 @@ class ClientExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($client) {
|
->map(function ($client) {
|
||||||
|
|
||||||
/** @var \App\Models\Client $client */
|
/** @var \App\Models\Client $client */
|
||||||
$row = $this->buildRow($client);
|
$row = $this->buildRow($client);
|
||||||
return $this->processMetaData($row, $client);
|
return $this->processMetaData($row, $client);
|
||||||
@ -133,7 +133,7 @@ class ClientExport extends BaseExport
|
|||||||
$query->where('is_deleted', 0);
|
$query->where('is_deleted', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $this->addDateRange($query,' clients');
|
$query = $this->addDateRange($query, ' clients');
|
||||||
|
|
||||||
if($this->input['document_email_attachment'] ?? false) {
|
if($this->input['document_email_attachment'] ?? false) {
|
||||||
$this->queueDocuments($query);
|
$this->queueDocuments($query);
|
||||||
@ -156,8 +156,8 @@ class ClientExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($client) {
|
->each(function ($client) {
|
||||||
|
|
||||||
/** @var \App\Models\Client $client */
|
/** @var \App\Models\Client $client */
|
||||||
$this->csv->insertOne($this->buildRow($client));
|
$this->csv->insertOne($this->buildRow($client));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class CreditExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($credit) {
|
->map(function ($credit) {
|
||||||
|
|
||||||
/** @var \App\Models\Credit $credit */
|
/** @var \App\Models\Credit $credit */
|
||||||
$row = $this->buildRow($credit);
|
$row = $this->buildRow($credit);
|
||||||
return $this->processMetaData($row, $credit);
|
return $this->processMetaData($row, $credit);
|
||||||
|
@ -54,7 +54,7 @@ class DocumentExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($document) {
|
->map(function ($document) {
|
||||||
|
|
||||||
/** @var \App\Models\Document $document */
|
/** @var \App\Models\Document $document */
|
||||||
$row = $this->buildRow($document);
|
$row = $this->buildRow($document);
|
||||||
return $this->processMetaData($row, $document);
|
return $this->processMetaData($row, $document);
|
||||||
@ -101,7 +101,7 @@ class DocumentExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($entity) {
|
->each(function ($entity) {
|
||||||
/** @var mixed $entity */
|
/** @var mixed $entity */
|
||||||
$this->csv->insertOne($this->buildRow($entity));
|
$this->csv->insertOne($this->buildRow($entity));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class ExpenseExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($resource) {
|
->map(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\Expense $resource */
|
/** @var \App\Models\Expense $resource */
|
||||||
$row = $this->buildRow($resource);
|
$row = $this->buildRow($resource);
|
||||||
return $this->processMetaData($row, $resource);
|
return $this->processMetaData($row, $resource);
|
||||||
@ -134,7 +134,7 @@ class ExpenseExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($expense) {
|
->each(function ($expense) {
|
||||||
|
|
||||||
/** @var \App\Models\Expense $expense */
|
/** @var \App\Models\Expense $expense */
|
||||||
$this->csv->insertOne($this->buildRow($expense));
|
$this->csv->insertOne($this->buildRow($expense));
|
||||||
});
|
});
|
||||||
@ -266,11 +266,10 @@ class ExpenseExport extends BaseExport
|
|||||||
if($expense->calculate_tax_by_amount) {
|
if($expense->calculate_tax_by_amount) {
|
||||||
|
|
||||||
$total_tax_amount = round($expense->tax_amount1 + $expense->tax_amount2 + $expense->tax_amount3, $precision);
|
$total_tax_amount = round($expense->tax_amount1 + $expense->tax_amount2 + $expense->tax_amount3, $precision);
|
||||||
|
|
||||||
if($expense->uses_inclusive_taxes) {
|
if($expense->uses_inclusive_taxes) {
|
||||||
$entity['expense.net_amount'] = round($expense->amount, $precision) - $total_tax_amount;
|
$entity['expense.net_amount'] = round($expense->amount, $precision) - $total_tax_amount;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$entity['expense.net_amount'] = round($expense->amount, $precision);
|
$entity['expense.net_amount'] = round($expense->amount, $precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class InvoiceExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($resource) {
|
->map(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\Invoice $resource */
|
/** @var \App\Models\Invoice $resource */
|
||||||
$row = $this->buildRow($resource);
|
$row = $this->buildRow($resource);
|
||||||
return $this->processMetaData($row, $resource);
|
return $this->processMetaData($row, $resource);
|
||||||
@ -121,7 +121,7 @@ class InvoiceExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($invoice) {
|
->each(function ($invoice) {
|
||||||
|
|
||||||
/** @var \App\Models\Invoice $invoice */
|
/** @var \App\Models\Invoice $invoice */
|
||||||
$this->csv->insertOne($this->buildRow($invoice));
|
$this->csv->insertOne($this->buildRow($invoice));
|
||||||
});
|
});
|
||||||
|
@ -113,7 +113,7 @@ class InvoiceItemExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($resource) {
|
->each(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\Invoice $resource */
|
/** @var \App\Models\Invoice $resource */
|
||||||
$this->iterateItems($resource);
|
$this->iterateItems($resource);
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ class InvoiceItemExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($invoice) {
|
->each(function ($invoice) {
|
||||||
|
|
||||||
/** @var \App\Models\Invoice $invoice */
|
/** @var \App\Models\Invoice $invoice */
|
||||||
$this->iterateItems($invoice);
|
$this->iterateItems($invoice);
|
||||||
});
|
});
|
||||||
@ -229,10 +229,6 @@ class InvoiceItemExport extends BaseExport
|
|||||||
// $entity['currency'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
|
// $entity['currency'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// if(array_key_exists('type', $entity)) {
|
|
||||||
// $entity['type'] = $invoice->typeIdString($entity['type']);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if(array_key_exists('tax_category', $entity)) {
|
// if(array_key_exists('tax_category', $entity)) {
|
||||||
// $entity['tax_category'] = $invoice->taxTypeString($entity['tax_category']);
|
// $entity['tax_category'] = $invoice->taxTypeString($entity['tax_category']);
|
||||||
// }
|
// }
|
||||||
@ -266,9 +262,9 @@ class InvoiceItemExport extends BaseExport
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (in_array('invoice.project', $this->input['report_keys'])) {
|
if (in_array('invoice.project', $this->input['report_keys'])) {
|
||||||
$entity['invoice.project'] = $invoice->project ? $invoice->project->name : '';// @phpstan-ignore-line
|
$entity['invoice.project'] = $invoice->project ? $invoice->project->name : '';// @phpstan-ignore-line
|
||||||
}
|
}
|
||||||
|
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ class PaymentExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($resource) {
|
->map(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\Payment $resource */
|
/** @var \App\Models\Payment $resource */
|
||||||
$row = $this->buildRow($resource);
|
$row = $this->buildRow($resource);
|
||||||
return $this->processMetaData($row, $resource);
|
return $this->processMetaData($row, $resource);
|
||||||
@ -114,8 +114,8 @@ class PaymentExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($entity) {
|
->each(function ($entity) {
|
||||||
|
|
||||||
/** @var \App\Models\Payment $entity */
|
/** @var \App\Models\Payment $entity */
|
||||||
$this->csv->insertOne($this->buildRow($entity));
|
$this->csv->insertOne($this->buildRow($entity));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class ProductExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($resource) {
|
->map(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\Product $resource */
|
/** @var \App\Models\Product $resource */
|
||||||
$row = $this->buildRow($resource);
|
$row = $this->buildRow($resource);
|
||||||
return $this->processMetaData($row, $resource);
|
return $this->processMetaData($row, $resource);
|
||||||
@ -106,8 +106,8 @@ class ProductExport extends BaseExport
|
|||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($entity) {
|
->each(function ($entity) {
|
||||||
|
|
||||||
/** @var \App\Models\Product $entity */
|
/** @var \App\Models\Product $entity */
|
||||||
$this->csv->insertOne($this->buildRow($entity));
|
$this->csv->insertOne($this->buildRow($entity));
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this->csv->toString();
|
return $this->csv->toString();
|
||||||
|
@ -98,7 +98,7 @@ class PurchaseOrderExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($resource) {
|
->map(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\PurchaseOrder $resource */
|
/** @var \App\Models\PurchaseOrder $resource */
|
||||||
$row = $this->buildRow($resource);
|
$row = $this->buildRow($resource);
|
||||||
return $this->processMetaData($row, $resource);
|
return $this->processMetaData($row, $resource);
|
||||||
@ -121,9 +121,9 @@ class PurchaseOrderExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($purchase_order) {
|
->each(function ($purchase_order) {
|
||||||
|
|
||||||
/** @var \App\Models\PurchaseOrder $purchase_order */
|
/** @var \App\Models\PurchaseOrder $purchase_order */
|
||||||
$this->csv->insertOne($this->buildRow($purchase_order));
|
$this->csv->insertOne($this->buildRow($purchase_order));
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this->csv->toString();
|
return $this->csv->toString();
|
||||||
|
@ -101,15 +101,15 @@ class PurchaseOrderItemExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($resource) {
|
->each(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\PurchaseOrder $resource */
|
|
||||||
$this->iterateItems($resource);
|
|
||||||
|
|
||||||
foreach($this->storage_array as $row) {
|
/** @var \App\Models\PurchaseOrder $resource */
|
||||||
$this->storage_item_array[] = $this->processItemMetaData($row, $resource);
|
$this->iterateItems($resource);
|
||||||
}
|
|
||||||
|
|
||||||
$this->storage_array = [];
|
foreach($this->storage_array as $row) {
|
||||||
|
$this->storage_item_array[] = $this->processItemMetaData($row, $resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->storage_array = [];
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -129,9 +129,9 @@ class PurchaseOrderItemExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($purchase_order) {
|
->each(function ($purchase_order) {
|
||||||
|
|
||||||
/** @var \App\Models\PurchaseOrder $purchase_order */
|
/** @var \App\Models\PurchaseOrder $purchase_order */
|
||||||
$this->iterateItems($purchase_order);
|
$this->iterateItems($purchase_order);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->csv->insertAll($this->storage_array);
|
$this->csv->insertAll($this->storage_array);
|
||||||
@ -213,10 +213,6 @@ class PurchaseOrderItemExport extends BaseExport
|
|||||||
// $entity['currency'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
|
// $entity['currency'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// if(array_key_exists('type', $entity)) {
|
|
||||||
// $entity['type'] = $purchase_order->typeIdString($entity['type']);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if(array_key_exists('tax_category', $entity)) {
|
// if(array_key_exists('tax_category', $entity)) {
|
||||||
// $entity['tax_category'] = $purchase_order->taxTypeString($entity['tax_category']);
|
// $entity['tax_category'] = $purchase_order->taxTypeString($entity['tax_category']);
|
||||||
// }
|
// }
|
||||||
|
@ -127,7 +127,7 @@ class QuoteExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($quote) {
|
->each(function ($quote) {
|
||||||
|
|
||||||
/** @var \App\Models\Quote $quote */
|
/** @var \App\Models\Quote $quote */
|
||||||
$this->csv->insertOne($this->buildRow($quote));
|
$this->csv->insertOne($this->buildRow($quote));
|
||||||
});
|
});
|
||||||
|
@ -104,7 +104,7 @@ class QuoteItemExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($resource) {
|
->each(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\Quote $resource */
|
/** @var \App\Models\Quote $resource */
|
||||||
$this->iterateItems($resource);
|
$this->iterateItems($resource);
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ class QuoteItemExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($quote) {
|
->each(function ($quote) {
|
||||||
|
|
||||||
/** @var \App\Models\Quote $quote */
|
/** @var \App\Models\Quote $quote */
|
||||||
$this->iterateItems($quote);
|
$this->iterateItems($quote);
|
||||||
});
|
});
|
||||||
|
@ -93,7 +93,7 @@ class RecurringInvoiceExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($invoice) {
|
->each(function ($invoice) {
|
||||||
|
|
||||||
/** @var \App\Models\RecurringInvoice $invoice */
|
/** @var \App\Models\RecurringInvoice $invoice */
|
||||||
$this->csv->insertOne($this->buildRow($invoice));
|
$this->csv->insertOne($this->buildRow($invoice));
|
||||||
});
|
});
|
||||||
@ -114,7 +114,7 @@ class RecurringInvoiceExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($resource) {
|
->map(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\RecurringInvoice $resource */
|
/** @var \App\Models\RecurringInvoice $resource */
|
||||||
$row = $this->buildRow($resource);
|
$row = $this->buildRow($resource);
|
||||||
return $this->processMetaData($row, $resource);
|
return $this->processMetaData($row, $resource);
|
||||||
|
@ -29,7 +29,7 @@ class TaskExport extends BaseExport
|
|||||||
{
|
{
|
||||||
private $entity_transformer;
|
private $entity_transformer;
|
||||||
|
|
||||||
public string $date_key = 'created_at';
|
public string $date_key = 'calculated_start_date';
|
||||||
|
|
||||||
private string $date_format = 'Y-m-d';
|
private string $date_format = 'Y-m-d';
|
||||||
|
|
||||||
@ -106,9 +106,9 @@ class TaskExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($entity) {
|
->each(function ($entity) {
|
||||||
|
|
||||||
/** @var \App\Models\Task $entity*/
|
/** @var \App\Models\Task $entity*/
|
||||||
$this->buildRow($entity);
|
$this->buildRow($entity);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->csv->insertAll($this->storage_array);
|
$this->csv->insertAll($this->storage_array);
|
||||||
@ -156,7 +156,7 @@ class TaskExport extends BaseExport
|
|||||||
$entity[$key] = $transformed_entity[$parts[1]];
|
$entity[$key] = $transformed_entity[$parts[1]];
|
||||||
} elseif (array_key_exists($key, $transformed_entity)) {
|
} elseif (array_key_exists($key, $transformed_entity)) {
|
||||||
$entity[$key] = $transformed_entity[$key];
|
$entity[$key] = $transformed_entity[$key];
|
||||||
} elseif (in_array($key, ['task.start_date', 'task.end_date', 'task.duration', 'task.billable', 'task.item_notes'])) {
|
} elseif (in_array($key, ['task.start_date', 'task.end_date', 'task.duration', 'task.billable', 'task.item_notes', 'task.time_log'])) {
|
||||||
$entity[$key] = '';
|
$entity[$key] = '';
|
||||||
} else {
|
} else {
|
||||||
$entity[$key] = $this->decorator->transform($key, $task);
|
$entity[$key] = $this->decorator->transform($key, $task);
|
||||||
@ -207,6 +207,9 @@ class TaskExport extends BaseExport
|
|||||||
$seconds = $task->calcDuration();
|
$seconds = $task->calcDuration();
|
||||||
$entity['task.duration'] = $seconds;
|
$entity['task.duration'] = $seconds;
|
||||||
$entity['task.duration_words'] = $seconds > 86400 ? CarbonInterval::seconds($seconds)->locale($this->company->locale())->cascade()->forHumans() : now()->startOfDay()->addSeconds($seconds)->format('H:i:s');
|
$entity['task.duration_words'] = $seconds > 86400 ? CarbonInterval::seconds($seconds)->locale($this->company->locale())->cascade()->forHumans() : now()->startOfDay()->addSeconds($seconds)->format('H:i:s');
|
||||||
|
|
||||||
|
$entity['task.time_log'] = (isset($item[1]) && $item[1] != 0) ? $item[1] - $item[0] : ctrans('texts.is_running');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array('task.billable', $this->input['report_keys']) || in_array('billable', $this->input['report_keys'])) {
|
if (in_array('task.billable', $this->input['report_keys']) || in_array('billable', $this->input['report_keys'])) {
|
||||||
|
@ -90,7 +90,7 @@ class VendorExport extends BaseExport
|
|||||||
|
|
||||||
$report = $query->cursor()
|
$report = $query->cursor()
|
||||||
->map(function ($resource) {
|
->map(function ($resource) {
|
||||||
|
|
||||||
/** @var \App\Models\Vendor $resource */
|
/** @var \App\Models\Vendor $resource */
|
||||||
$row = $this->buildRow($resource);
|
$row = $this->buildRow($resource);
|
||||||
return $this->processMetaData($row, $resource);
|
return $this->processMetaData($row, $resource);
|
||||||
@ -109,9 +109,9 @@ class VendorExport extends BaseExport
|
|||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($vendor) {
|
->each(function ($vendor) {
|
||||||
|
|
||||||
/** @var \App\Models\Vendor $vendor */
|
/** @var \App\Models\Vendor $vendor */
|
||||||
$this->csv->insertOne($this->buildRow($vendor));
|
$this->csv->insertOne($this->buildRow($vendor));
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this->csv->toString();
|
return $this->csv->toString();
|
||||||
|
@ -96,7 +96,7 @@ class TaskDecorator extends Decorator implements DecoratorInterface
|
|||||||
return '';
|
return '';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* billable
|
* billable
|
||||||
*
|
*
|
||||||
@ -106,7 +106,7 @@ class TaskDecorator extends Decorator implements DecoratorInterface
|
|||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* items_notes
|
* items_notes
|
||||||
* @todo
|
* @todo
|
||||||
@ -115,7 +115,7 @@ class TaskDecorator extends Decorator implements DecoratorInterface
|
|||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function duration(Task $task)
|
public function duration(Task $task)
|
||||||
{
|
{
|
||||||
return $task->calcDuration();
|
return $task->calcDuration();
|
||||||
|
@ -149,43 +149,43 @@ class RecurringExpenseToExpenseFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if (Str::contains($match, '|')) {
|
// if (Str::contains($match, '|')) {
|
||||||
$parts = explode('|', $match); // [ '[MONTH', 'MONTH+2]' ]
|
$parts = explode('|', $match); // [ '[MONTH', 'MONTH+2]' ]
|
||||||
|
|
||||||
$left = substr($parts[0], 1); // 'MONTH'
|
$left = substr($parts[0], 1); // 'MONTH'
|
||||||
$right = substr($parts[1], 0, -1); // MONTH+2
|
$right = substr($parts[1], 0, -1); // MONTH+2
|
||||||
|
|
||||||
// If left side is not part of replacements, skip.
|
// If left side is not part of replacements, skip.
|
||||||
if (! array_key_exists($left, $replacements['ranges'])) {
|
if (! array_key_exists($left, $replacements['ranges'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$_left = Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F Y');
|
$_left = Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F Y');
|
||||||
$_right = '';
|
$_right = '';
|
||||||
|
|
||||||
// If right side doesn't have any calculations, replace with raw ranges keyword.
|
// If right side doesn't have any calculations, replace with raw ranges keyword.
|
||||||
if (! Str::contains($right, ['-', '+', '/', '*'])) {
|
if (! Str::contains($right, ['-', '+', '/', '*'])) {
|
||||||
$_right = Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F Y');
|
$_right = Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F Y');
|
||||||
}
|
}
|
||||||
|
|
||||||
// If right side contains one of math operations, calculate.
|
// If right side contains one of math operations, calculate.
|
||||||
if (Str::contains($right, ['+'])) {
|
if (Str::contains($right, ['+'])) {
|
||||||
$operation = preg_match_all('/(?!^-)[+*\/-](\s?-)?/', $right, $_matches);
|
$operation = preg_match_all('/(?!^-)[+*\/-](\s?-)?/', $right, $_matches);
|
||||||
|
|
||||||
$_operation = array_shift($_matches)[0]; // + -
|
$_operation = array_shift($_matches)[0]; // + -
|
||||||
|
|
||||||
$_value = explode($_operation, $right); // [MONTHYEAR, 4]
|
$_value = explode($_operation, $right); // [MONTHYEAR, 4]
|
||||||
|
|
||||||
$_right = Carbon::createFromDate(now()->year, now()->month)->addMonths($_value[1])->translatedFormat('F Y'); //@phpstan-ignore-line
|
$_right = Carbon::createFromDate(now()->year, now()->month)->addMonths($_value[1])->translatedFormat('F Y'); //@phpstan-ignore-line
|
||||||
}
|
}
|
||||||
|
|
||||||
$replacement = sprintf('%s to %s', $_left, $_right);
|
$replacement = sprintf('%s to %s', $_left, $_right);
|
||||||
|
|
||||||
$value = preg_replace(
|
$value = preg_replace(
|
||||||
sprintf('/%s/', preg_quote($match)),
|
sprintf('/%s/', preg_quote($match)),
|
||||||
$replacement,
|
$replacement,
|
||||||
$value,
|
$value,
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,14 @@ class CreditFilters extends QueryFilters
|
|||||||
->orWhere('last_name', 'like', '%'.$filter.'%')
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
->orWhere('email', 'like', '%'.$filter.'%');
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
})
|
})
|
||||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
->orWhereRaw("
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(
|
||||||
|
JSON_ARRAY(
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||||
|
), '$[*]')
|
||||||
|
) LIKE ?", ['%'.$filter.'%']);
|
||||||
|
// ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +158,19 @@ class ExpenseFilters extends QueryFilters
|
|||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function categories(string $categories = ''): Builder
|
||||||
|
{
|
||||||
|
$categories_exploded = explode(",", $categories);
|
||||||
|
|
||||||
|
if(empty($categories) || count(array_filter($categories_exploded)) == 0) {
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
$categories_keys = $this->transformKeys($categories_exploded);
|
||||||
|
|
||||||
|
return $this->builder->whereIn('category_id', $categories_keys);
|
||||||
|
}
|
||||||
|
|
||||||
public function number(string $number = ''): Builder
|
public function number(string $number = ''): Builder
|
||||||
{
|
{
|
||||||
if (strlen($number) == 0) {
|
if (strlen($number) == 0) {
|
||||||
@ -205,6 +218,11 @@ class ExpenseFilters extends QueryFilters
|
|||||||
->whereColumn('expense_categories.id', 'expenses.category_id'), $sort_col[1]);
|
->whereColumn('expense_categories.id', 'expenses.category_id'), $sort_col[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($sort_col[0] == 'payment_date' && in_array($sort_col[1], ['asc', 'desc'])) {
|
||||||
|
return $this->builder
|
||||||
|
->orderByRaw('ISNULL(payment_date), payment_date '. $sort_col[1]);
|
||||||
|
}
|
||||||
|
|
||||||
if($sort_col[0] == 'number') {
|
if($sort_col[0] == 'number') {
|
||||||
return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir);
|
return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir);
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,14 @@ class InvoiceFilters extends QueryFilters
|
|||||||
->orWhere('last_name', 'like', '%'.$filter.'%')
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
->orWhere('email', 'like', '%'.$filter.'%');
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
})
|
})
|
||||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
->orWhereRaw("
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(
|
||||||
|
JSON_ARRAY(
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||||
|
), '$[*]')
|
||||||
|
) LIKE ?", ['%'.$filter.'%']);
|
||||||
|
// ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class ProjectFilters extends QueryFilters
|
|||||||
{
|
{
|
||||||
$sort_col = explode('|', $sort);
|
$sort_col = explode('|', $sort);
|
||||||
|
|
||||||
if (!is_array($sort_col) || count($sort_col) != 2) {
|
if (!is_array($sort_col) || count($sort_col) != 2 || !in_array($sort_col[0], \Illuminate\Support\Facades\Schema::getColumnListing('projects'))) {
|
||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,14 @@ class PurchaseOrderFilters extends QueryFilters
|
|||||||
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
->orWhere('custom_value4', 'like', '%'.$filter.'%')
|
||||||
->orWhereHas('vendor', function ($q) use ($filter) {
|
->orWhereHas('vendor', function ($q) use ($filter) {
|
||||||
$q->where('name', 'like', '%'.$filter.'%');
|
$q->where('name', 'like', '%'.$filter.'%');
|
||||||
});
|
})
|
||||||
|
->orWhereRaw("
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(
|
||||||
|
JSON_ARRAY(
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||||
|
), '$[*]')
|
||||||
|
) LIKE ?", ['%'.$filter.'%']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,14 @@ class QuoteFilters extends QueryFilters
|
|||||||
->orWhere('last_name', 'like', '%'.$filter.'%')
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
->orWhere('email', 'like', '%'.$filter.'%');
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
})
|
})
|
||||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
->orWhereRaw("
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(
|
||||||
|
JSON_ARRAY(
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||||
|
), '$[*]')
|
||||||
|
) LIKE ?", ['%'.$filter.'%']);
|
||||||
|
// ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,14 @@ class RecurringInvoiceFilters extends QueryFilters
|
|||||||
->orWhere('last_name', 'like', '%'.$filter.'%')
|
->orWhere('last_name', 'like', '%'.$filter.'%')
|
||||||
->orWhere('email', 'like', '%'.$filter.'%');
|
->orWhere('email', 'like', '%'.$filter.'%');
|
||||||
})
|
})
|
||||||
->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
->orWhereRaw("
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(
|
||||||
|
JSON_ARRAY(
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')),
|
||||||
|
JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].product_key'))
|
||||||
|
), '$[*]')
|
||||||
|
) LIKE ?", ['%'.$filter.'%']);
|
||||||
|
//->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(line_items, '$[*].notes')) LIKE ?", ['%'.$filter.'%']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +141,7 @@ class RecurringInvoiceFilters extends QueryFilters
|
|||||||
return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir);
|
return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($sort_col[0] == 'status_id'){
|
if($sort_col[0] == 'status_id') {
|
||||||
return $this->builder->orderBy('status_id', $dir)->orderBy('last_sent_date', $dir);
|
return $this->builder->orderBy('status_id', $dir)->orderBy('last_sent_date', $dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,10 @@ class TaskFilters extends QueryFilters
|
|||||||
$this->builder->whereNull('invoice_id');
|
$this->builder->whereNull('invoice_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (in_array('is_running', $status_parameters)) {
|
||||||
|
$this->builder->where('is_running', true);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class TransactionTransformer implements BankRevenueInterface
|
|||||||
} elseif (array_key_exists('internalTransactionId', $transaction)) {
|
} elseif (array_key_exists('internalTransactionId', $transaction)) {
|
||||||
$transactionId = $transaction["internalTransactionId"];
|
$transactionId = $transaction["internalTransactionId"];
|
||||||
} else {
|
} else {
|
||||||
nlog(`Invalid Input for nordigen transaction transformer: ` . $transaction);
|
nlog('Invalid Input for nordigen transaction transformer: ' . $transaction);
|
||||||
throw new \Exception('invalid dataset: missing transactionId - Please report this error to the developer');
|
throw new \Exception('invalid dataset: missing transactionId - Please report this error to the developer');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ class TransactionTransformer implements BankRevenueInterface
|
|||||||
|
|
||||||
/** @var \App\Models\Currency $currency */
|
/** @var \App\Models\Currency $currency */
|
||||||
return $currency ? $currency->id : 1; //@phpstan-ignore-line
|
return $currency ? $currency->id : 1; //@phpstan-ignore-line
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function formatDate(string $input)
|
private function formatDate(string $input)
|
||||||
|
@ -61,7 +61,7 @@ class EpcQrGenerator
|
|||||||
} catch(\Throwable $e) {
|
} catch(\Throwable $e) {
|
||||||
nlog("EPC QR failure => ".$e->getMessage());
|
nlog("EPC QR failure => ".$e->getMessage());
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ use App\Models\Quote;
|
|||||||
use App\Utils\Number;
|
use App\Utils\Number;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
|
use App\Models\Vendor;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\PurchaseOrder;
|
use App\Models\PurchaseOrder;
|
||||||
use App\Models\RecurringQuote;
|
use App\Models\RecurringQuote;
|
||||||
@ -121,7 +122,7 @@ class InvoiceItemSum
|
|||||||
|
|
||||||
private $tax_collection;
|
private $tax_collection;
|
||||||
|
|
||||||
private ?Client $client;
|
private Client | Vendor $client;
|
||||||
|
|
||||||
private bool $calc_tax = false;
|
private bool $calc_tax = false;
|
||||||
|
|
||||||
@ -132,10 +133,10 @@ class InvoiceItemSum
|
|||||||
$this->tax_collection = collect([]);
|
$this->tax_collection = collect([]);
|
||||||
|
|
||||||
$this->invoice = $invoice;
|
$this->invoice = $invoice;
|
||||||
|
$this->client = $invoice->client ?? $invoice->vendor;
|
||||||
|
|
||||||
if ($this->invoice->client) {
|
if ($this->invoice->client) {
|
||||||
$this->currency = $this->invoice->client->currency();
|
$this->currency = $this->invoice->client->currency();
|
||||||
$this->client = $this->invoice->client;
|
|
||||||
$this->shouldCalculateTax();
|
$this->shouldCalculateTax();
|
||||||
} else {
|
} else {
|
||||||
$this->currency = $this->invoice->vendor->currency();
|
$this->currency = $this->invoice->vendor->currency();
|
||||||
|
@ -15,6 +15,7 @@ use App\Models\Quote;
|
|||||||
use App\Utils\Number;
|
use App\Utils\Number;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
|
use App\Models\Vendor;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\PurchaseOrder;
|
use App\Models\PurchaseOrder;
|
||||||
use App\Models\RecurringQuote;
|
use App\Models\RecurringQuote;
|
||||||
@ -110,7 +111,7 @@ class InvoiceItemSumInclusive
|
|||||||
|
|
||||||
private bool $calc_tax = false;
|
private bool $calc_tax = false;
|
||||||
|
|
||||||
private ?Client $client;
|
private Client | Vendor $client;
|
||||||
|
|
||||||
private RuleInterface $rule;
|
private RuleInterface $rule;
|
||||||
|
|
||||||
@ -119,10 +120,10 @@ class InvoiceItemSumInclusive
|
|||||||
$this->tax_collection = collect([]);
|
$this->tax_collection = collect([]);
|
||||||
|
|
||||||
$this->invoice = $invoice;
|
$this->invoice = $invoice;
|
||||||
|
$this->client = $invoice->client ?? $invoice->vendor;
|
||||||
|
|
||||||
if ($this->invoice->client) {
|
if ($this->invoice->client) {
|
||||||
$this->currency = $this->invoice->client->currency();
|
$this->currency = $this->invoice->client->currency();
|
||||||
$this->client = $this->invoice->client;
|
|
||||||
$this->shouldCalculateTax();
|
$this->shouldCalculateTax();
|
||||||
} else {
|
} else {
|
||||||
$this->currency = $this->invoice->vendor->currency();
|
$this->currency = $this->invoice->vendor->currency();
|
||||||
|
@ -11,12 +11,14 @@
|
|||||||
|
|
||||||
namespace App\Helpers\Invoice;
|
namespace App\Helpers\Invoice;
|
||||||
|
|
||||||
|
use App\Models\Client;
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\PurchaseOrder;
|
use App\Models\PurchaseOrder;
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
use App\Models\RecurringInvoice;
|
use App\Models\RecurringInvoice;
|
||||||
use App\Models\RecurringQuote;
|
use App\Models\RecurringQuote;
|
||||||
|
use App\Models\Vendor;
|
||||||
use App\Utils\Number;
|
use App\Utils\Number;
|
||||||
use App\Utils\Traits\NumberFormatter;
|
use App\Utils\Traits\NumberFormatter;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@ -50,6 +52,8 @@ class InvoiceSum
|
|||||||
|
|
||||||
private $precision;
|
private $precision;
|
||||||
|
|
||||||
|
private Client | Vendor $client;
|
||||||
|
|
||||||
public InvoiceItemSum $invoice_items;
|
public InvoiceItemSum $invoice_items;
|
||||||
|
|
||||||
private $rappen_rounding = false;
|
private $rappen_rounding = false;
|
||||||
@ -60,18 +64,15 @@ class InvoiceSum
|
|||||||
*/
|
*/
|
||||||
public function __construct($invoice)
|
public function __construct($invoice)
|
||||||
{
|
{
|
||||||
|
|
||||||
$this->invoice = $invoice;
|
$this->invoice = $invoice;
|
||||||
|
$this->client = $invoice->client ?? $invoice->vendor;
|
||||||
|
|
||||||
if ($this->invoice->client) {
|
$this->precision = $this->client->currency()->precision;
|
||||||
$this->precision = $this->invoice->client->currency()->precision;
|
$this->rappen_rounding = $this->client->getSetting('enable_rappen_rounding');
|
||||||
$this->rappen_rounding = $this->invoice->client->getSetting('enable_rappen_rounding');
|
|
||||||
} else {
|
|
||||||
$this->precision = $this->invoice->vendor->currency()->precision;
|
|
||||||
$this->rappen_rounding = $this->invoice->vendor->getSetting('enable_rappen_rounding');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->tax_map = new Collection();
|
$this->tax_map = new Collection();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function build()
|
public function build()
|
||||||
@ -131,7 +132,7 @@ class InvoiceSum
|
|||||||
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name1, $this->invoice->tax_rate1);
|
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name1, $this->invoice->tax_rate1);
|
||||||
|
|
||||||
$this->total_taxes += $tax;
|
$this->total_taxes += $tax;
|
||||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate1), $this->invoice->client).'%', 'total' => $tax];
|
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate1), $this->client).'%', 'total' => $tax];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($this->invoice->tax_name2) && strlen($this->invoice->tax_name2) >= 2) {
|
if (is_string($this->invoice->tax_name2) && strlen($this->invoice->tax_name2) >= 2) {
|
||||||
@ -139,7 +140,7 @@ class InvoiceSum
|
|||||||
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name2, $this->invoice->tax_rate2);
|
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name2, $this->invoice->tax_rate2);
|
||||||
|
|
||||||
$this->total_taxes += $tax;
|
$this->total_taxes += $tax;
|
||||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate2), $this->invoice->client).'%', 'total' => $tax];
|
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate2), $this->client).'%', 'total' => $tax];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($this->invoice->tax_name3) && strlen($this->invoice->tax_name3) >= 2) {
|
if (is_string($this->invoice->tax_name3) && strlen($this->invoice->tax_name3) >= 2) {
|
||||||
@ -147,7 +148,7 @@ class InvoiceSum
|
|||||||
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name3, $this->invoice->tax_rate3);
|
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name3, $this->invoice->tax_rate3);
|
||||||
|
|
||||||
$this->total_taxes += $tax;
|
$this->total_taxes += $tax;
|
||||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate3), $this->invoice->client).'%', 'total' => $tax];
|
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate3), $this->client).'%', 'total' => $tax];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -13,7 +13,9 @@ namespace App\Helpers\Invoice;
|
|||||||
|
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
use App\Utils\Number;
|
use App\Utils\Number;
|
||||||
|
use App\Models\Client;
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
|
use App\Models\Vendor;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\PurchaseOrder;
|
use App\Models\PurchaseOrder;
|
||||||
use App\Models\RecurringQuote;
|
use App\Models\RecurringQuote;
|
||||||
@ -50,6 +52,8 @@ class InvoiceSumInclusive
|
|||||||
|
|
||||||
private $rappen_rounding = false;
|
private $rappen_rounding = false;
|
||||||
|
|
||||||
|
private Client | Vendor $client;
|
||||||
|
|
||||||
public InvoiceItemSumInclusive $invoice_items;
|
public InvoiceItemSumInclusive $invoice_items;
|
||||||
/**
|
/**
|
||||||
* Constructs the object with Invoice and Settings object.
|
* Constructs the object with Invoice and Settings object.
|
||||||
@ -59,14 +63,10 @@ class InvoiceSumInclusive
|
|||||||
public function __construct($invoice)
|
public function __construct($invoice)
|
||||||
{
|
{
|
||||||
$this->invoice = $invoice;
|
$this->invoice = $invoice;
|
||||||
|
$this->client = $invoice->client ?? $invoice->vendor;
|
||||||
|
|
||||||
if ($this->invoice->client) {
|
$this->precision = $this->client->currency()->precision;
|
||||||
$this->precision = $this->invoice->client->currency()->precision;
|
$this->rappen_rounding = $this->client->getSetting('enable_rappen_rounding');
|
||||||
$this->rappen_rounding = $this->invoice->client->getSetting('enable_rappen_rounding');
|
|
||||||
} else {
|
|
||||||
$this->precision = $this->invoice->vendor->currency()->precision;
|
|
||||||
$this->rappen_rounding = $this->invoice->vendor->getSetting('enable_rappen_rounding');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->tax_map = new Collection();
|
$this->tax_map = new Collection();
|
||||||
}
|
}
|
||||||
@ -158,19 +158,19 @@ class InvoiceSumInclusive
|
|||||||
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate1, $amount);
|
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate1, $amount);
|
||||||
$this->total_taxes += $tax;
|
$this->total_taxes += $tax;
|
||||||
|
|
||||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate1), $this->invoice->client).'%', 'total' => $tax];
|
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate1), $this->client).'%', 'total' => $tax];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($this->invoice->tax_name2) && strlen($this->invoice->tax_name2) > 1) {
|
if (is_string($this->invoice->tax_name2) && strlen($this->invoice->tax_name2) > 1) {
|
||||||
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate2, $amount);
|
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate2, $amount);
|
||||||
$this->total_taxes += $tax;
|
$this->total_taxes += $tax;
|
||||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate2), $this->invoice->client).'%', 'total' => $tax];
|
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate2), $this->client).'%', 'total' => $tax];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($this->invoice->tax_name3) && strlen($this->invoice->tax_name3) > 1) {
|
if (is_string($this->invoice->tax_name3) && strlen($this->invoice->tax_name3) > 1) {
|
||||||
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate3, $amount);
|
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate3, $amount);
|
||||||
$this->total_taxes += $tax;
|
$this->total_taxes += $tax;
|
||||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate3), $this->invoice->client).'%', 'total' => $tax];
|
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate3), $this->client).'%', 'total' => $tax];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -53,7 +53,7 @@ class GmailTransport extends AbstractTransport
|
|||||||
if ($bccs) {
|
if ($bccs) {
|
||||||
$bcc_list = 'Bcc: ';
|
$bcc_list = 'Bcc: ';
|
||||||
|
|
||||||
foreach ($bccs->getAddresses() as $address) {
|
foreach ($bccs->getAddresses() as $address) {
|
||||||
|
|
||||||
$bcc_list .= $address->getAddress() .',';
|
$bcc_list .= $address->getAddress() .',';
|
||||||
}
|
}
|
||||||
|
@ -22,5 +22,5 @@
|
|||||||
*/
|
*/
|
||||||
function ctrans(string $string, $replace = [], $locale = null): string
|
function ctrans(string $string, $replace = [], $locale = null): string
|
||||||
{
|
{
|
||||||
return trans($string, $replace, $locale);
|
return html_entity_decode(trans($string, $replace, $locale));
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ class ActivityController extends BaseController
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* downloadHistoricalEntity
|
* downloadHistoricalEntity
|
||||||
*
|
*
|
||||||
@ -204,7 +204,7 @@ class ActivityController extends BaseController
|
|||||||
$activity->user_id = $user->id;
|
$activity->user_id = $user->id;
|
||||||
$activity->ip = $request->ip();
|
$activity->ip = $request->ip();
|
||||||
$activity->activity_type_id = Activity::USER_NOTE;
|
$activity->activity_type_id = Activity::USER_NOTE;
|
||||||
|
|
||||||
switch (get_class($entity)) {
|
switch (get_class($entity)) {
|
||||||
case Invoice::class:
|
case Invoice::class:
|
||||||
$activity->invoice_id = $entity->id;
|
$activity->invoice_id = $entity->id;
|
||||||
@ -254,17 +254,20 @@ class ActivityController extends BaseController
|
|||||||
$activity->client_id = $entity->client_id;
|
$activity->client_id = $entity->client_id;
|
||||||
$activity->project_id = $entity->project_id;
|
$activity->project_id = $entity->project_id;
|
||||||
$activity->vendor_id = $entity->vendor_id;
|
$activity->vendor_id = $entity->vendor_id;
|
||||||
|
// no break
|
||||||
case Task::class:
|
case Task::class:
|
||||||
$activity->task_id = $entity->id;
|
$activity->task_id = $entity->id;
|
||||||
$activity->expense_id = $entity->id;
|
$activity->expense_id = $entity->id;
|
||||||
$activity->client_id = $entity->client_id;
|
$activity->client_id = $entity->client_id;
|
||||||
$activity->project_id = $entity->project_id;
|
$activity->project_id = $entity->project_id;
|
||||||
$activity->vendor_id = $entity->vendor_id;
|
$activity->vendor_id = $entity->vendor_id;
|
||||||
|
// no break
|
||||||
case Payment::class:
|
case Payment::class:
|
||||||
$activity->payment_id = $entity->id;
|
$activity->payment_id = $entity->id;
|
||||||
$activity->expense_id = $entity->id;
|
$activity->expense_id = $entity->id;
|
||||||
$activity->client_id = $entity->client_id;
|
$activity->client_id = $entity->client_id;
|
||||||
$activity->project_id = $entity->project_id;
|
$activity->project_id = $entity->project_id;
|
||||||
|
// no break
|
||||||
default:
|
default:
|
||||||
# code...
|
# code...
|
||||||
break;
|
break;
|
||||||
|
@ -41,9 +41,10 @@ class ContactLoginController extends Controller
|
|||||||
$company = false;
|
$company = false;
|
||||||
$account = false;
|
$account = false;
|
||||||
|
|
||||||
if($request->query('intended'))
|
if($request->query('intended')) {
|
||||||
$request->session()->put('url.intended', $request->query('intended'));
|
$request->session()->put('url.intended', $request->query('intended'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->session()->has('company_key')) {
|
if ($request->session()->has('company_key')) {
|
||||||
MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key'));
|
MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key'));
|
||||||
$company = Company::where('company_key', $request->session()->get('company_key'))->first();
|
$company = Company::where('company_key', $request->session()->get('company_key'))->first();
|
||||||
@ -141,9 +142,10 @@ class ContactLoginController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->setRedirectPath();
|
$this->setRedirectPath();
|
||||||
|
|
||||||
if($intended)
|
if($intended) {
|
||||||
$this->redirectTo = $intended;
|
$this->redirectTo = $intended;
|
||||||
|
}
|
||||||
|
|
||||||
return $request->wantsJson()
|
return $request->wantsJson()
|
||||||
? new JsonResponse([], 204)
|
? new JsonResponse([], 204)
|
||||||
|
@ -399,8 +399,8 @@ class LoginController extends BaseController
|
|||||||
$truth->setCompany($set_company);
|
$truth->setCompany($set_company);
|
||||||
|
|
||||||
//21-03-2024
|
//21-03-2024
|
||||||
|
|
||||||
|
|
||||||
$cu->each(function ($cu) {
|
$cu->each(function ($cu) {
|
||||||
/** @var \App\Models\CompanyUser $cu */
|
/** @var \App\Models\CompanyUser $cu */
|
||||||
if(CompanyToken::query()->where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()) {
|
if(CompanyToken::query()->where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()) {
|
||||||
|
@ -217,7 +217,7 @@ class BankIntegrationController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key') && (Ninja::isSelfHost() || (Ninja::isHosted() && $user_account->isEnterprisePaidClient()))) {
|
if (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key') && (Ninja::isSelfHost() || (Ninja::isHosted() && $user_account->isEnterprisePaidClient()))) {
|
||||||
$user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->each(function ($bank_integration) {
|
$user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->each(function ($bank_integration) {
|
||||||
/** @var \App\Models\BankIntegration $bank_integration */
|
/** @var \App\Models\BankIntegration $bank_integration */
|
||||||
ProcessBankTransactionsNordigen::dispatch($bank_integration);
|
ProcessBankTransactionsNordigen::dispatch($bank_integration);
|
||||||
});
|
});
|
||||||
|
@ -934,7 +934,7 @@ class BaseController extends Controller
|
|||||||
} elseif (in_array($this->entity_type, [Design::class, GroupSetting::class, PaymentTerm::class, TaskStatus::class])) {
|
} elseif (in_array($this->entity_type, [Design::class, GroupSetting::class, PaymentTerm::class, TaskStatus::class])) {
|
||||||
// nlog($this->entity_type);
|
// nlog($this->entity_type);
|
||||||
} else {
|
} else {
|
||||||
$query->where(function ($q) use ($user){ //grouping these together improves query performance significantly)
|
$query->where(function ($q) use ($user) { //grouping these together improves query performance significantly)
|
||||||
$q->where('user_id', '=', $user->id)->orWhere('assigned_user_id', $user->id);
|
$q->where('user_id', '=', $user->id)->orWhere('assigned_user_id', $user->id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -996,7 +996,7 @@ class BaseController extends Controller
|
|||||||
|
|
||||||
if(request()->has('einvoice')) {
|
if(request()->has('einvoice')) {
|
||||||
|
|
||||||
if(class_exists(Schema::class)){
|
if(class_exists(Schema::class)) {
|
||||||
$ro = new Schema();
|
$ro = new Schema();
|
||||||
$response_data['einvoice_schema'] = $ro('Peppol');
|
$response_data['einvoice_schema'] = $ro('Peppol');
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ use Illuminate\Http\Request;
|
|||||||
*/
|
*/
|
||||||
class BrevoController extends BaseController
|
class BrevoController extends BaseController
|
||||||
{
|
{
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ class ChartController extends BaseController
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$cs = new ChartService($user->company(), $user, $user->isAdmin());
|
$cs = new ChartService($user->company(), $user, $user->isAdmin());
|
||||||
$result = $cs->getCalculatedField($request->all());
|
$result = $cs->getCalculatedField($request->all());
|
||||||
|
|
||||||
return response()->json($result, 200);
|
return response()->json($result, 200);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -114,8 +114,8 @@ class InvitationController extends Controller
|
|||||||
'invitation_key' => $invitation_key
|
'invitation_key' => $invitation_key
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!auth()->guard('contact')->check()){
|
if(!auth()->guard('contact')->check()) {
|
||||||
$this->middleware('auth:contact');
|
$this->middleware('auth:contact');
|
||||||
return redirect()->route('client.login', ['intended' => route('client.'.$entity.'.show', [$entity => $this->encodePrimaryKey($invitation->{$key}), 'silent' => $is_silent])]);
|
return redirect()->route('client.login', ['intended' => route('client.'.$entity.'.show', [$entity => $this->encodePrimaryKey($invitation->{$key}), 'silent' => $is_silent])]);
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ class InvitationController extends Controller
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function fireEntityViewedEvent($invitation, $entity_string)
|
private function fireEntityViewedEvent($invitation, $entity_string)
|
||||||
{
|
{
|
||||||
switch ($entity_string) {
|
switch ($entity_string) {
|
||||||
|
@ -62,6 +62,7 @@ class InvoiceController extends Controller
|
|||||||
|
|
||||||
$invitation = $invoice->invitations()->where('client_contact_id', auth()->guard('contact')->user()->id)->first();
|
$invitation = $invoice->invitations()->where('client_contact_id', auth()->guard('contact')->user()->id)->first();
|
||||||
|
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
if ($invitation && auth()->guard('contact') && ! session()->get('is_silent') && ! $invitation->viewed_date) {
|
if ($invitation && auth()->guard('contact') && ! session()->get('is_silent') && ! $invitation->viewed_date) {
|
||||||
$invitation->markViewed();
|
$invitation->markViewed();
|
||||||
|
|
||||||
@ -77,13 +78,17 @@ class InvoiceController extends Controller
|
|||||||
'key' => $invitation ? $invitation->key : false,
|
'key' => $invitation ? $invitation->key : false,
|
||||||
'hash' => $hash,
|
'hash' => $hash,
|
||||||
'variables' => $variables,
|
'variables' => $variables,
|
||||||
|
'invoices' => [$invoice->hashed_id],
|
||||||
|
'db' => $invoice->company->db,
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($request->query('mode') === 'fullscreen') {
|
if ($request->query('mode') === 'fullscreen') {
|
||||||
return render('invoices.show-fullscreen', $data);
|
return render('invoices.show-fullscreen', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('invoices.show', $data);
|
return auth()->guard('contact')->user()->client->getSetting('payment_flow') == 'default' ? $this->render('invoices.show', $data) : $this->render('invoices.show_smooth', $data);
|
||||||
|
|
||||||
|
// return $this->render('invoices.show_smooth', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showBlob($hash)
|
public function showBlob($hash)
|
||||||
@ -235,9 +240,12 @@ class InvoiceController extends Controller
|
|||||||
'hashed_ids' => $invoices->pluck('hashed_id'),
|
'hashed_ids' => $invoices->pluck('hashed_id'),
|
||||||
'total' => $total,
|
'total' => $total,
|
||||||
'variables' => $variables,
|
'variables' => $variables,
|
||||||
|
'invitation' => $invitation,
|
||||||
|
'db' => $invitation->company->db,
|
||||||
];
|
];
|
||||||
|
|
||||||
return $this->render('invoices.payment', $data);
|
// return $this->render('invoices.payment', $data);
|
||||||
|
return auth()->guard('contact')->user()->client->getSetting('payment_flow') === 'default' ? $this->render('invoices.payment', $data) : $this->render('invoices.show_smooth_multi', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,6 +88,8 @@ class NinjaPlanController extends Controller
|
|||||||
{
|
{
|
||||||
$trial_started = "Trial Started @ ".now()->format('Y-m-d H:i:s');
|
$trial_started = "Trial Started @ ".now()->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
auth()->guard('contact')->user()->fill($request->only(['first_name','last_name']))->save();
|
||||||
|
|
||||||
$client = auth()->guard('contact')->user()->client;
|
$client = auth()->guard('contact')->user()->client;
|
||||||
$client->private_notes = $trial_started;
|
$client->private_notes = $trial_started;
|
||||||
$client->fill($request->all());
|
$client->fill($request->all());
|
||||||
|
@ -126,7 +126,7 @@ class PaymentController extends Controller
|
|||||||
// if($payment_hash)
|
// if($payment_hash)
|
||||||
$invoice = $payment_hash->fee_invoice;
|
$invoice = $payment_hash->fee_invoice;
|
||||||
// else
|
// else
|
||||||
// $invoice = Invoice::with('client')->where('id',$payment_hash->fee_invoice_id)->orderBy('id','desc')->first();
|
// $invoice = Invoice::with('client')->where('id',$payment_hash->fee_invoice_id)->orderBy('id','desc')->first();
|
||||||
|
|
||||||
// $invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
|
// $invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ class SubscriptionPurchaseController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function setLocale(string $locale): string
|
private function setLocale(string $locale): string
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \Illuminate\Support\Collection<\App\Models\Language> */
|
/** @var \Illuminate\Support\Collection<\App\Models\Language> */
|
||||||
$languages = app('languages');
|
$languages = app('languages');
|
||||||
|
|
||||||
@ -104,6 +104,6 @@ class SubscriptionPurchaseController extends Controller
|
|||||||
});
|
});
|
||||||
|
|
||||||
return $record ? $record->locale : 'en';
|
return $record ? $record->locale : 'en';
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -707,7 +707,7 @@ class CompanyController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse | \Illuminate\Http\JsonResponse
|
* @return \Symfony\Component\HttpFoundation\StreamedResponse | \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
|
@ -567,9 +567,9 @@ class CompanyGatewayController extends BaseController
|
|||||||
{
|
{
|
||||||
|
|
||||||
//Throttle here
|
//Throttle here
|
||||||
if (Cache::has("throttle_polling:import_customers:{$company_gateway->company->company_key}:{$company_gateway->hashed_id}")) {
|
// if (Cache::has("throttle_polling:import_customers:{$company_gateway->company->company_key}:{$company_gateway->hashed_id}")) {
|
||||||
return response()->json(['message' => 'Please wait whilst your previous attempts complete.'], 200);
|
// return response()->json(['message' => 'Please wait whilst your previous attempts complete.'], 200);
|
||||||
}
|
// }
|
||||||
|
|
||||||
dispatch(function () use ($company_gateway) {
|
dispatch(function () use ($company_gateway) {
|
||||||
MultiDB::setDb($company_gateway->company->db);
|
MultiDB::setDb($company_gateway->company->db);
|
||||||
|
@ -615,7 +615,7 @@ class CreditController extends BaseController
|
|||||||
return response()->streamDownload(function () use ($file) {
|
return response()->streamDownload(function () use ($file) {
|
||||||
echo $file;
|
echo $file;
|
||||||
}, $credit->numberFormatter() . '.pdf', ['Content-Type' => 'application/pdf']);
|
}, $credit->numberFormatter() . '.pdf', ['Content-Type' => 'application/pdf']);
|
||||||
|
|
||||||
case 'archive':
|
case 'archive':
|
||||||
$this->credit_repository->archive($credit);
|
$this->credit_repository->archive($credit);
|
||||||
|
|
||||||
|
@ -51,9 +51,9 @@ class EmailHistoryController extends BaseController
|
|||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
|
|
||||||
$data = SystemLog::where('company_id', $user->company()->id)
|
$data = SystemLog::where('company_id', $user->company()->id)
|
||||||
->where('category_id', SystemLog::CATEGORY_MAIL)
|
->where('category_id', SystemLog::CATEGORY_MAIL)
|
||||||
|
->whereJsonContains('log->history->entity', $request->entity)
|
||||||
->whereJsonContains('log->history->entity_id', $this->encodePrimaryKey($request->entity_id))
|
->whereJsonContains('log->history->entity_id', $this->encodePrimaryKey($request->entity_id))
|
||||||
->orderBy('id', 'DESC')
|
->orderBy('id', 'DESC')
|
||||||
->cursor()
|
->cursor()
|
||||||
|
@ -584,20 +584,14 @@ class ExpenseController extends BaseController
|
|||||||
return $this->itemResponse($expense->fresh());
|
return $this->itemResponse($expense->fresh());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edocument(EDocumentRequest $request): string
|
public function edocument(EDocumentRequest $request)
|
||||||
{
|
{
|
||||||
if ($request->hasFile("documents"))
|
$user = auth()->user();
|
||||||
try {
|
|
||||||
|
|
||||||
return (new ImportEDocument($request->file("documents")->get(), $request->file("documents")->getClientOriginalName(), $request->file("documents")->getMimeType()))->handle();
|
foreach ($request->file("documents") as $file) {
|
||||||
|
ImportEDocument::dispatch($file->get(), $file->getClientOriginalName(), $request->file("documents")->getMimeType(), $user->company());
|
||||||
|
}
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
return response()->json(['message' => 'Processing....'], 200);
|
||||||
if ($e->getCode() == 409)
|
|
||||||
return $e->getMessage();
|
|
||||||
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "No file found";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,9 +59,9 @@ class ExportController extends BaseController
|
|||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
$hash = Str::uuid();
|
$hash = Str::uuid()->toString();
|
||||||
$url = \Illuminate\Support\Facades\URL::temporarySignedRoute('protected_download', now()->addHour(), ['hash' => $hash]);
|
$url = \Illuminate\Support\Facades\URL::temporarySignedRoute('protected_download', now()->addHour(), ['hash' => $hash]);
|
||||||
Cache::put($hash, $url, now()->addHour());
|
Cache::put($hash, $url, 3600);
|
||||||
|
|
||||||
CompanyExport::dispatch($user->getCompany(), $user, $hash);
|
CompanyExport::dispatch($user->getCompany(), $user, $hash);
|
||||||
|
|
||||||
|
134
app/Http/Controllers/ImportQuickbooksController.php
Normal file
134
app/Http/Controllers/ImportQuickbooksController.php
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Requests\Quickbooks\AuthorizedQuickbooksRequest;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use App\Http\Requests\Quickbooks\AuthQuickbooksRequest;
|
||||||
|
use App\Services\Quickbooks\QuickbooksService;
|
||||||
|
|
||||||
|
class ImportQuickbooksController extends BaseController
|
||||||
|
{
|
||||||
|
// private array $import_entities = [
|
||||||
|
// 'client' => 'Customer',
|
||||||
|
// 'invoice' => 'Invoice',
|
||||||
|
// 'product' => 'Item',
|
||||||
|
// 'payment' => 'Payment'
|
||||||
|
// ];
|
||||||
|
|
||||||
|
public function onAuthorized(AuthorizedQuickbooksRequest $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']);
|
||||||
|
$company = $request->getCompany();
|
||||||
|
$qb = new QuickbooksService($company);
|
||||||
|
|
||||||
|
$realm = $request->query('realmId');
|
||||||
|
$access_token_object = $qb->sdk()->accessTokenFromCode($request->query('code'), $realm);
|
||||||
|
$qb->sdk()->saveOAuthToken($access_token_object);
|
||||||
|
|
||||||
|
return redirect(config('ninja.react_url'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function authorizeQuickbooks(AuthQuickbooksRequest $request, string $token)
|
||||||
|
{
|
||||||
|
|
||||||
|
MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']);
|
||||||
|
$company = $request->getCompany();
|
||||||
|
$qb = new QuickbooksService($company);
|
||||||
|
|
||||||
|
$authorizationUrl = $qb->sdk()->getAuthorizationUrl();
|
||||||
|
$state = $qb->sdk()->getState();
|
||||||
|
|
||||||
|
Cache::put($state, $token, 190);
|
||||||
|
|
||||||
|
return redirect()->to($authorizationUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function preimport(string $type, string $hash)
|
||||||
|
{
|
||||||
|
// // Check for authorization otherwise
|
||||||
|
// // Create a reference
|
||||||
|
// $data = [
|
||||||
|
// 'hash' => $hash,
|
||||||
|
// 'type' => $type
|
||||||
|
// ];
|
||||||
|
// $this->getData($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getData($data)
|
||||||
|
{
|
||||||
|
|
||||||
|
// $entity = $this->import_entities[$data['type']];
|
||||||
|
// $cache_name = "{$data['hash']}-{$data['type']}";
|
||||||
|
// // TODO: Get or put cache or DB?
|
||||||
|
// if(! Cache::has($cache_name)) {
|
||||||
|
// $contents = call_user_func([$this->service, "fetch{$entity}s"]);
|
||||||
|
// if($contents->isEmpty()) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Cache::put($cache_name, base64_encode($contents->toJson()), 600);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Post(
|
||||||
|
* path="/api/v1/import_json",
|
||||||
|
* operationId="getImportJson",
|
||||||
|
* tags={"import"},
|
||||||
|
* summary="Import data from the system",
|
||||||
|
* description="Import data from the system",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="success",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function import(Request $request)
|
||||||
|
{
|
||||||
|
// $hash = Str::random(32);
|
||||||
|
// foreach($request->input('import_types') as $type) {
|
||||||
|
// $this->preimport($type, $hash);
|
||||||
|
// }
|
||||||
|
// /** @var \App\Models\User $user */
|
||||||
|
// // $user = auth()->user() ?? Auth::loginUsingId(60);
|
||||||
|
// $data = ['import_types' => $request->input('import_types') ] + compact('hash');
|
||||||
|
// if (Ninja::isHosted()) {
|
||||||
|
// QuickbooksIngest::dispatch($data, $user->company());
|
||||||
|
// } else {
|
||||||
|
// QuickbooksIngest::dispatch($data, $user->company());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return response()->json(['message' => 'Processing'], 200);
|
||||||
|
}
|
||||||
|
}
|
@ -503,7 +503,7 @@ class InvoiceController extends BaseController
|
|||||||
|
|
||||||
$invoices = Invoice::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
$invoices = Invoice::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
||||||
|
|
||||||
if ($invoices->count() == 0 ) {
|
if ($invoices->count() == 0) {
|
||||||
return response()->json(['message' => 'No Invoices Found']);
|
return response()->json(['message' => 'No Invoices Found']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ use Illuminate\Support\Str;
|
|||||||
|
|
||||||
class OneTimeTokenController extends BaseController
|
class OneTimeTokenController extends BaseController
|
||||||
{
|
{
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
@ -25,7 +25,7 @@ class PaymentNotificationWebhookController extends Controller
|
|||||||
{
|
{
|
||||||
/** @var \App\Models\CompanyGateway $company_gateway */
|
/** @var \App\Models\CompanyGateway $company_gateway */
|
||||||
$company_gateway = CompanyGateway::find($this->decodePrimaryKey($company_gateway_id));
|
$company_gateway = CompanyGateway::find($this->decodePrimaryKey($company_gateway_id));
|
||||||
|
|
||||||
/** @var \App\Models\Client $client */
|
/** @var \App\Models\Client $client */
|
||||||
$client = Client::find($this->decodePrimaryKey($client_hash));
|
$client = Client::find($this->decodePrimaryKey($client_hash));
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ use Illuminate\Http\Request;
|
|||||||
*/
|
*/
|
||||||
class PostMarkController extends BaseController
|
class PostMarkController extends BaseController
|
||||||
{
|
{
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -297,6 +297,8 @@ class PreviewController extends BaseController
|
|||||||
->setTemplate($design_object)
|
->setTemplate($design_object)
|
||||||
->mock();
|
->mock();
|
||||||
} catch(SyntaxError $e) {
|
} catch(SyntaxError $e) {
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
return response()->json(['message' => 'invalid data access', 'errors' => ['design.design.body' => $e->getMessage()]], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request()->query('html') == 'true') {
|
if (request()->query('html') == 'true') {
|
||||||
|
@ -85,12 +85,12 @@ class SearchController extends Controller
|
|||||||
// ->whereHas('client', function ($q) {
|
// ->whereHas('client', function ($q) {
|
||||||
// $q->where('is_deleted', 0);
|
// $q->where('is_deleted', 0);
|
||||||
// })
|
// })
|
||||||
|
|
||||||
->leftJoin('clients', function ($join) {
|
->leftJoin('clients', function ($join) {
|
||||||
$join->on('invoices.client_id', '=', 'clients.id')
|
$join->on('invoices.client_id', '=', 'clients.id')
|
||||||
->where('clients.is_deleted', 0);
|
->where('clients.is_deleted', 0);
|
||||||
})
|
})
|
||||||
|
|
||||||
->when(!$user->hasPermission('view_all') || !$user->hasPermission('view_invoice'), function ($query) use ($user) {
|
->when(!$user->hasPermission('view_all') || !$user->hasPermission('view_invoice'), function ($query) use ($user) {
|
||||||
$query->where('invoices.user_id', $user->id);
|
$query->where('invoices.user_id', $user->id);
|
||||||
})
|
})
|
||||||
|
@ -181,8 +181,9 @@ class SelfUpdateController extends BaseController
|
|||||||
|
|
||||||
public function checkVersion()
|
public function checkVersion()
|
||||||
{
|
{
|
||||||
if(Ninja::isHosted())
|
if(Ninja::isHosted()) {
|
||||||
return '5.10.SaaS';
|
return '5.10.SaaS';
|
||||||
|
}
|
||||||
|
|
||||||
return trim(file_get_contents(config('ninja.version_url')));
|
return trim(file_get_contents(config('ninja.version_url')));
|
||||||
}
|
}
|
||||||
|
@ -11,23 +11,25 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\VendorPortal;
|
namespace App\Http\Controllers\VendorPortal;
|
||||||
|
|
||||||
use App\Events\Misc\InvitationWasViewed;
|
use App\Utils\Ninja;
|
||||||
use App\Events\PurchaseOrder\PurchaseOrderWasAccepted;
|
use App\Models\Webhook;
|
||||||
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
|
use Illuminate\View\View;
|
||||||
|
use App\Models\PurchaseOrder;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Utils\Traits\MakesDates;
|
||||||
|
use App\Jobs\Entity\CreateRawPdf;
|
||||||
|
use App\Jobs\Util\WebhookHandler;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ProcessPurchaseOrdersInBulkRequest;
|
use App\Jobs\Invoice\InjectSignature;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Illuminate\Contracts\View\Factory;
|
||||||
|
use App\Models\PurchaseOrderInvitation;
|
||||||
|
use App\Events\Misc\InvitationWasViewed;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasAccepted;
|
||||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrderRequest;
|
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrderRequest;
|
||||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrdersRequest;
|
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrdersRequest;
|
||||||
use App\Jobs\Entity\CreateRawPdf;
|
use App\Http\Requests\VendorPortal\PurchaseOrders\ProcessPurchaseOrdersInBulkRequest;
|
||||||
use App\Jobs\Invoice\InjectSignature;
|
|
||||||
use App\Models\PurchaseOrder;
|
|
||||||
use App\Models\PurchaseOrderInvitation;
|
|
||||||
use App\Utils\Ninja;
|
|
||||||
use App\Utils\Traits\MakesDates;
|
|
||||||
use App\Utils\Traits\MakesHash;
|
|
||||||
use Illuminate\Contracts\View\Factory;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Illuminate\View\View;
|
|
||||||
|
|
||||||
class PurchaseOrderController extends Controller
|
class PurchaseOrderController extends Controller
|
||||||
{
|
{
|
||||||
@ -187,6 +189,9 @@ class PurchaseOrderController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
event(new PurchaseOrderWasAccepted($purchase_order, auth()->guard('vendor')->user(), $purchase_order->company, Ninja::eventVars()));
|
event(new PurchaseOrderWasAccepted($purchase_order, auth()->guard('vendor')->user(), $purchase_order->company, Ninja::eventVars()));
|
||||||
|
|
||||||
|
WebhookHandler::dispatch(Webhook::EVENT_ACCEPTED_PURCHASE_ORDER, $purchase_order, $purchase_order->company, 'vendor')->delay(0);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($purchase_count_query->count() == 1) {
|
if ($purchase_count_query->count() == 1) {
|
||||||
|
@ -14,7 +14,7 @@ namespace App\Http\Controllers\VendorPortal;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\VendorContact;
|
use App\Models\VendorContact;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use App\Utils\TranslationHelper;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class VendorContactController extends Controller
|
class VendorContactController extends Controller
|
||||||
{
|
{
|
||||||
@ -58,14 +58,14 @@ class VendorContactController extends Controller
|
|||||||
'settings' => $vendor_contact->vendor->company->settings,
|
'settings' => $vendor_contact->vendor->company->settings,
|
||||||
'company' => $vendor_contact->vendor->company,
|
'company' => $vendor_contact->vendor->company,
|
||||||
'sidebar' => $this->sidebarMenu(),
|
'sidebar' => $this->sidebarMenu(),
|
||||||
'countries' => TranslationHelper::getCountries(),
|
'countries' => app('countries'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(VendorContact $vendor_contact)
|
public function update(Request $request, VendorContact $vendor_contact)
|
||||||
{
|
{
|
||||||
$vendor_contact->fill(request()->all());
|
$vendor_contact->fill($request->all());
|
||||||
$vendor_contact->vendor->fill(request()->all());
|
$vendor_contact->vendor->fill($request->all());
|
||||||
$vendor_contact->push();
|
$vendor_contact->push();
|
||||||
|
|
||||||
return back()->withSuccess(ctrans('texts.profile_updated_successfully'));
|
return back()->withSuccess(ctrans('texts.profile_updated_successfully'));
|
||||||
@ -76,16 +76,10 @@ class VendorContactController extends Controller
|
|||||||
$enabled_modules = auth()->guard('vendor')->user()->company->enabled_modules;
|
$enabled_modules = auth()->guard('vendor')->user()->company->enabled_modules;
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
// TODO: Enable dashboard once it's completed.
|
|
||||||
// $this->settings->enable_client_portal_dashboard
|
|
||||||
// $data[] = [ 'title' => ctrans('texts.dashboard'), 'url' => 'client.dashboard', 'icon' => 'activity'];
|
|
||||||
|
|
||||||
if (self::MODULE_PURCHASE_ORDERS & $enabled_modules) {
|
if (self::MODULE_PURCHASE_ORDERS & $enabled_modules) {
|
||||||
$data[] = ['title' => ctrans('texts.purchase_orders'), 'url' => 'vendor.purchase_orders.index', 'icon' => 'file-text'];
|
$data[] = ['title' => ctrans('texts.purchase_orders'), 'url' => 'vendor.purchase_orders.index', 'icon' => 'file-text'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// $data[] = ['title' => ctrans('texts.documents'), 'url' => 'client.documents.index', 'icon' => 'download'];
|
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ class VendorContactHashLoginController extends Controller
|
|||||||
{
|
{
|
||||||
return redirect($this->setRedirectPath());
|
return redirect($this->setRedirectPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* errorPage
|
* errorPage
|
||||||
*
|
*
|
||||||
|
@ -79,7 +79,7 @@ class ContactRegister
|
|||||||
// As a fallback for self-hosted, it will use default company in the system
|
// As a fallback for self-hosted, it will use default company in the system
|
||||||
// if key isn't provided in the url.
|
// if key isn't provided in the url.
|
||||||
if (! $request->route()->parameter('company_key') && Ninja::isSelfHost()) {
|
if (! $request->route()->parameter('company_key') && Ninja::isSelfHost()) {
|
||||||
$company = Account::query()->first()->default_company;
|
$company = Account::query()->first()->default_company ?? Account::query()->first()->companies->first();
|
||||||
|
|
||||||
if (! $company->client_can_register) {
|
if (! $company->client_can_register) {
|
||||||
abort(400, 'Registration disabled');
|
abort(400, 'Registration disabled');
|
||||||
|
@ -4,15 +4,15 @@ namespace App\Http\Middleware;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Cache\RateLimiter;
|
use Illuminate\Cache\RateLimiter;
|
||||||
|
use Illuminate\Contracts\Redis\Factory as Redis;
|
||||||
use Illuminate\Redis\Limiters\DurationLimiter;
|
use Illuminate\Redis\Limiters\DurationLimiter;
|
||||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
|
||||||
|
|
||||||
class ThrottleRequestsWithPredis extends ThrottleRequests
|
class ThrottleRequestsWithPredis extends \Illuminate\Routing\Middleware\ThrottleRequests
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The Redis factory implementation.
|
* The Redis factory implementation.
|
||||||
*
|
*
|
||||||
* @var \Illuminate\Redis\Connections\Connection
|
* @var \Illuminate\Contracts\Redis\Factory
|
||||||
*/
|
*/
|
||||||
protected $redis;
|
protected $redis;
|
||||||
|
|
||||||
@ -32,14 +32,14 @@ class ThrottleRequestsWithPredis extends ThrottleRequests
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new request throttler.
|
* Create a new request throttler.
|
||||||
*
|
|
||||||
* @param \Illuminate\Cache\RateLimiter $limiter
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(RateLimiter $limiter)
|
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
|
public function __construct(RateLimiter $limiter, Redis $redis)
|
||||||
{
|
{
|
||||||
parent::__construct($limiter);
|
parent::__construct($limiter);
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$this->redis = \Illuminate\Support\Facades\Redis::connection('sentinel-cache');
|
$this->redis = \Illuminate\Support\Facades\Redis::connection('sentinel-cache');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ class ThrottleRequestsWithPredis extends ThrottleRequests
|
|||||||
protected function handleRequest($request, Closure $next, array $limits)
|
protected function handleRequest($request, Closure $next, array $limits)
|
||||||
{
|
{
|
||||||
foreach ($limits as $limit) {
|
foreach ($limits as $limit) {
|
||||||
if ($this->tooManyAttempts($limit->key, $limit->maxAttempts, $limit->decayMinutes)) {
|
if ($this->tooManyAttempts($limit->key, $limit->maxAttempts, $limit->decaySeconds)) {
|
||||||
throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback);
|
throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,16 +79,16 @@ class ThrottleRequestsWithPredis extends ThrottleRequests
|
|||||||
*
|
*
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param int $maxAttempts
|
* @param int $maxAttempts
|
||||||
* @param int $decayMinutes
|
* @param int $decaySeconds
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
protected function tooManyAttempts($key, $maxAttempts, $decayMinutes)
|
protected function tooManyAttempts($key, $maxAttempts, $decaySeconds)
|
||||||
{
|
{
|
||||||
$limiter = new DurationLimiter(
|
$limiter = new DurationLimiter(
|
||||||
$this->redis,
|
$this->getRedisConnection(),
|
||||||
$key,
|
$key,
|
||||||
$maxAttempts,
|
$maxAttempts,
|
||||||
$decayMinutes * 60
|
$decaySeconds
|
||||||
);
|
);
|
||||||
|
|
||||||
return tap(! $limiter->acquire(), function () use ($key, $limiter) {
|
return tap(! $limiter->acquire(), function () use ($key, $limiter) {
|
||||||
@ -121,4 +121,13 @@ class ThrottleRequestsWithPredis extends ThrottleRequests
|
|||||||
{
|
{
|
||||||
return $this->decaysAt[$key] - $this->currentTime();
|
return $this->decaysAt[$key] - $this->currentTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Redis connection that should be used for throttling.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function getRedisConnection()
|
||||||
|
{
|
||||||
|
return $this->redis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,11 +68,12 @@ class StoreNoteRequest extends Request
|
|||||||
|
|
||||||
public function getEntity()
|
public function getEntity()
|
||||||
{
|
{
|
||||||
if(!$this->entity)
|
if(!$this->entity) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$class = "\\App\\Models\\".ucfirst(Str::camel(rtrim($this->entity, 's')));
|
$class = "\\App\\Models\\".ucfirst(Str::camel(rtrim($this->entity, 's')));
|
||||||
return $class::withTrashed()->find(is_string($this->entity_id) ? $this->decodePrimaryKey($this->entity_id) : $this->entity_id);
|
return $class::withTrashed()->find(is_string($this->entity_id) ? $this->decodePrimaryKey($this->entity_id) : $this->entity_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,8 @@ class StoreBankTransactionRuleRequest extends Request
|
|||||||
'rules.*.value' => 'bail|required|nullable',
|
'rules.*.value' => 'bail|required|nullable',
|
||||||
'auto_convert' => 'bail|sometimes|bool',
|
'auto_convert' => 'bail|sometimes|bool',
|
||||||
'matches_on_all' => 'bail|sometimes|bool',
|
'matches_on_all' => 'bail|sometimes|bool',
|
||||||
'applies_to' => 'bail|sometimes|string',
|
'applies_to' => 'bail|sometimes|string|in:CREDIT,DEBIT',
|
||||||
|
'on_credit_match' => 'bail|sometimes|in:create_payment,link_payment'
|
||||||
];
|
];
|
||||||
|
|
||||||
$rules['category_id'] = 'bail|sometimes|nullable|exists:expense_categories,id,company_id,'.$user->company()->id.',is_deleted,0';
|
$rules['category_id'] = 'bail|sometimes|nullable|exists:expense_categories,id,company_id,'.$user->company()->id.',is_deleted,0';
|
||||||
|
@ -66,8 +66,7 @@ class ShowCalculatedFieldRequest extends Request
|
|||||||
$input['end_date'] = now()->format('Y-m-d');
|
$input['end_date'] = now()->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($input['period']) && $input['period'] == 'previous')
|
if(isset($input['period']) && $input['period'] == 'previous') {
|
||||||
{
|
|
||||||
$dates = $this->calculatePreviousPeriodStartAndEndDates($input, $user->company());
|
$dates = $this->calculatePreviousPeriodStartAndEndDates($input, $user->company());
|
||||||
$input['start_date'] = $dates[0];
|
$input['start_date'] = $dates[0];
|
||||||
$input['end_date'] = $dates[1];
|
$input['end_date'] = $dates[1];
|
||||||
|
@ -200,7 +200,7 @@ class StoreClientRequest extends Request
|
|||||||
|
|
||||||
private function getCountryCode(string $country_code)
|
private function getCountryCode(string $country_code)
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \Illuminate\Support\Collection<\App\Models\Country> */
|
/** @var \Illuminate\Support\Collection<\App\Models\Country> */
|
||||||
$countries = app('countries');
|
$countries = app('countries');
|
||||||
|
|
||||||
@ -209,12 +209,12 @@ class StoreClientRequest extends Request
|
|||||||
});
|
});
|
||||||
|
|
||||||
return $country ? (string) $country->id : '';
|
return $country ? (string) $country->id : '';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getCurrencyCode($code)
|
private function getCurrencyCode($code)
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \Illuminate\Support\Collection<\App\Models\Currency> */
|
/** @var \Illuminate\Support\Collection<\App\Models\Currency> */
|
||||||
$currencies = app('currencies');
|
$currencies = app('currencies');
|
||||||
|
|
||||||
@ -223,6 +223,6 @@ class StoreClientRequest extends Request
|
|||||||
});
|
});
|
||||||
|
|
||||||
return $currency ? (string)$currency->id : '';
|
return $currency ? (string)$currency->id : '';
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ class UpdateClientRequest extends Request
|
|||||||
|
|
||||||
private function getCountryCode($country_code)
|
private function getCountryCode($country_code)
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \Illuminate\Support\Collection<\App\Models\Country> */
|
/** @var \Illuminate\Support\Collection<\App\Models\Country> */
|
||||||
$countries = app('countries');
|
$countries = app('countries');
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ class UpdateClientRequest extends Request
|
|||||||
|
|
||||||
private function getLanguageId($language_code)
|
private function getLanguageId($language_code)
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \Illuminate\Support\Collection<\App\Models\Language> */
|
/** @var \Illuminate\Support\Collection<\App\Models\Language> */
|
||||||
$languages = app('languages');
|
$languages = app('languages');
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class ShowCreditRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
auth()->guard('contact')->user()->loadMissing(['company']);
|
auth()->guard('contact')->user()->loadMissing(['company']);
|
||||||
|
|
||||||
return ! $this->credit->is_deleted
|
return ! $this->credit->is_deleted
|
||||||
&& (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_CREDITS)
|
&& (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_CREDITS)
|
||||||
|
@ -19,7 +19,7 @@ class ProcessInvoicesInBulkRequest extends FormRequest
|
|||||||
{
|
{
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['company']);
|
auth()->guard('contact')->user()->loadMissing(['company']);
|
||||||
|
|
||||||
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES);
|
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES);
|
||||||
|
@ -23,7 +23,7 @@ class ShowInvoiceRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize(): bool
|
||||||
{
|
{
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['company']);
|
auth()->guard('contact')->user()->loadMissing(['company']);
|
||||||
|
|
||||||
return (int) auth()->guard('contact')->user()->client_id === (int) $this->invoice->client_id
|
return (int) auth()->guard('contact')->user()->client_id === (int) $this->invoice->client_id
|
||||||
|
@ -19,7 +19,7 @@ class ShowInvoicesRequest extends FormRequest
|
|||||||
{
|
{
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['company']);
|
auth()->guard('contact')->user()->loadMissing(['company']);
|
||||||
|
|
||||||
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES);
|
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES);
|
||||||
|
@ -18,7 +18,7 @@ class CreatePaymentMethodRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize(): bool
|
||||||
{
|
{
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['client' => function ($query) {
|
auth()->guard('contact')->user()->loadMissing(['client' => function ($query) {
|
||||||
$query->without('gateway_tokens', 'documents', 'contacts.company', 'contacts'); // Exclude 'grandchildren' relation of 'client'
|
$query->without('gateway_tokens', 'documents', 'contacts.company', 'contacts'); // Exclude 'grandchildren' relation of 'client'
|
||||||
}]);
|
}]);
|
||||||
|
@ -15,7 +15,7 @@ class StorePrePaymentRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['company']);
|
auth()->guard('contact')->user()->loadMissing(['company']);
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['client' => function ($query) {
|
auth()->guard('contact')->user()->loadMissing(['client' => function ($query) {
|
||||||
|
@ -21,7 +21,7 @@ class ProcessQuotesInBulkRequest extends FormRequest
|
|||||||
{
|
{
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['company']);
|
auth()->guard('contact')->user()->loadMissing(['company']);
|
||||||
|
|
||||||
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES);
|
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES);
|
||||||
|
@ -19,7 +19,7 @@ class ShowQuoteRequest extends FormRequest
|
|||||||
{
|
{
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['company']);
|
auth()->guard('contact')->user()->loadMissing(['company']);
|
||||||
|
|
||||||
return (int)auth()->guard('contact')->user()->client->id === (int) $this->quote->client_id
|
return (int)auth()->guard('contact')->user()->client->id === (int) $this->quote->client_id
|
||||||
|
@ -19,7 +19,7 @@ class ShowQuotesRequest extends FormRequest
|
|||||||
{
|
{
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['company']);
|
auth()->guard('contact')->user()->loadMissing(['company']);
|
||||||
|
|
||||||
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES);
|
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES);
|
||||||
|
@ -9,7 +9,7 @@ class RequestCancellationRequest extends FormRequest
|
|||||||
{
|
{
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
|
|
||||||
auth()->guard('contact')->user()->loadMissing(['company']);
|
auth()->guard('contact')->user()->loadMissing(['company']);
|
||||||
|
|
||||||
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_RECURRING_INVOICES);
|
return (bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_RECURRING_INVOICES);
|
||||||
|
@ -22,7 +22,7 @@ class StoreUploadRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @phpstan-ignore-next-line **/
|
/** @phpstan-ignore-next-line **/
|
||||||
auth()->guard('contact')->user()->loadMissing(['client' => function ($query) {
|
auth()->guard('contact')->user()->loadMissing(['client' => function ($query) {
|
||||||
$query->without('gateway_tokens', 'documents', 'contacts.company', 'contacts'); // Exclude 'grandchildren' relation of 'client'
|
$query->without('gateway_tokens', 'documents', 'contacts.company', 'contacts'); // Exclude 'grandchildren' relation of 'client'
|
||||||
|
@ -64,7 +64,7 @@ class StoreCreditRequest extends Request
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
||||||
|
|
||||||
$rules['invitations'] = 'sometimes|bail|array';
|
$rules['invitations'] = 'sometimes|bail|array';
|
||||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class UpdateCreditRequest extends Request
|
|||||||
$rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('credits')->where('company_id', $user->company()->id)->ignore($this->credit->id)];
|
$rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('credits')->where('company_id', $user->company()->id)->ignore($this->credit->id)];
|
||||||
|
|
||||||
$rules['client_id'] = ['bail', 'sometimes',Rule::in([$this->credit->client_id])];
|
$rules['client_id'] = ['bail', 'sometimes',Rule::in([$this->credit->client_id])];
|
||||||
|
|
||||||
$rules['invitations'] = 'sometimes|bail|array';
|
$rules['invitations'] = 'sometimes|bail|array';
|
||||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user