1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-22 01:11:34 +02:00

Merge pull request #8872 from turbo124/v5-stable

v5.7.30
This commit is contained in:
David Bomba 2023-10-14 08:44:10 +11:00 committed by GitHub
commit 03f3057311
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
558 changed files with 384900 additions and 373104 deletions

View File

@ -14,6 +14,11 @@ https://invoiceninja.github.io/docs/self-host-troubleshooting/ -->
- Version: <!-- i.e. v4.5.25 / v5.0.30 --> - Version: <!-- i.e. v4.5.25 / v5.0.30 -->
- Environment: <!-- Docker/Shared Hosting/ZIP/Other --> - Environment: <!-- Docker/Shared Hosting/ZIP/Other -->
## Interface
- Flutter: []
- React: []
- Both: []
## Checklist ## Checklist
- Can you replicate the issue on our v5 demo site https://demo.invoiceninja.com or https://react.invoicing.co/demo? - Can you replicate the issue on our v5 demo site https://demo.invoiceninja.com or https://react.invoicing.co/demo?
- Have you searched existing issues? - Have you searched existing issues?

View File

@ -19,7 +19,7 @@ jobs:
uses: actions/checkout@v1 uses: actions/checkout@v1
with: with:
ref: v5-develop ref: v5-develop
- name: Copy .env file - name: Copy .env file
run: | run: |
cp .env.example .env cp .env.example .env
@ -32,9 +32,9 @@ jobs:
- name: Prepare Laravel Application - name: Prepare Laravel Application
run: | run: |
cp .env.example .env cp .env.example .env
php artisan key:generate php artisan key:generate --force
php artisan optimize php artisan optimize
php artisan storage:link php artisan storage:link --force
sudo php artisan cache:clear sudo php artisan cache:clear
sudo find ./vendor/bin/ -type f -exec chmod +x {} \; sudo find ./vendor/bin/ -type f -exec chmod +x {} \;
sudo find ./ -type d -exec chmod 755 {} \; sudo find ./ -type d -exec chmod 755 {} \;
@ -46,7 +46,11 @@ jobs:
git checkout main git checkout main
npm i npm i
npm run build npm run build
cp -r dist/react/* ../public/react
mkdir -p ../public/react/${{ github.event.release.tag_name }}/
cp -r dist/react/* ../public/react/${{ github.event.release.tag_name }}/
cp -r dist/react/* ../public/react/
mkdir -p ../public/tinymce_6.4.2/tinymce/js/ mkdir -p ../public/tinymce_6.4.2/tinymce/js/
cp -r node_modules/tinymce ../public/tinymce_6.4.2/tinymce/js/ cp -r node_modules/tinymce ../public/tinymce_6.4.2/tinymce/js/
cd .. cd ..

View File

@ -50,8 +50,7 @@ We offer a $30 per year white-label license to remove the Invoice Ninja branding
## Quick Hosting Setup ## Quick Hosting Setup
```sh ```sh
git clone https://github.com/invoiceninja/invoiceninja.git git clone --single-branch --branch v5-stable https://github.com/invoiceninja/invoiceninja.git
git checkout v5-stable
cp .env.example .env cp .env.example .env
composer i -o --no-dev composer i -o --no-dev
php artisan key:generate php artisan key:generate

View File

@ -1 +1 @@
5.7.3 5.7.30

View File

@ -549,7 +549,7 @@ class CheckData extends Command
private function clientPaidToDateQuery() private function clientPaidToDateQuery()
{ {
$results = \DB::select(\DB::raw(" $results = \DB::select("
SELECT SELECT
clients.id as client_id, clients.id as client_id,
clients.paid_to_date as client_paid_to_date, clients.paid_to_date as client_paid_to_date,
@ -564,14 +564,14 @@ class CheckData extends Command
GROUP BY clients.id GROUP BY clients.id
HAVING payments_applied != client_paid_to_date HAVING payments_applied != client_paid_to_date
ORDER BY clients.id; ORDER BY clients.id;
")); ");
return $results; return $results;
} }
private function clientCreditPaymentables($client) private function clientCreditPaymentables($client)
{ {
$results = \DB::select(\DB::raw(" $results = \DB::select("
SELECT SELECT
SUM(paymentables.amount - paymentables.refunded) as credit_payment SUM(paymentables.amount - paymentables.refunded) as credit_payment
FROM payments FROM payments
@ -583,7 +583,7 @@ class CheckData extends Command
AND paymentables.amount > 0 AND paymentables.amount > 0
AND payments.is_deleted = 0 AND payments.is_deleted = 0
AND payments.client_id = ?; AND payments.client_id = ?;
"), [App\Models\Credit::class, $client->id]); ", [App\Models\Credit::class, $client->id]);
return $results; return $results;
} }
@ -619,110 +619,11 @@ class CheckData extends Command
} }
$this->logMessage("{$this->wrong_paid_to_dates} clients with incorrect paid to dates"); $this->logMessage("{$this->wrong_paid_to_dates} clients with incorrect paid to dates");
} }
private function checkPaidToDates()
{
$this->wrong_paid_to_dates = 0;
$credit_total_applied = 0;
$clients = DB::table('clients')
->leftJoin('payments', function ($join) {
$join->on('payments.client_id', '=', 'clients.id')
->where('payments.is_deleted', 0)
->whereIn('payments.status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED]);
})
->where('clients.is_deleted', 0)
->where('clients.updated_at', '>', now()->subDays(2))
->groupBy('clients.id')
->havingRaw('clients.paid_to_date != sum(coalesce(payments.amount - payments.refunded, 0))')
->get(['clients.id', 'clients.paid_to_date', DB::raw('sum(coalesce(payments.amount - payments.refunded, 0)) as amount')]);
/* Due to accounting differences we need to perform a second loop here to ensure there actually is an issue */
$clients->each(function ($client_record) use ($credit_total_applied) {
$client = Client::withTrashed()->find($client_record->id);
$total_invoice_payments = 0;
foreach ($client->invoices()->where('is_deleted', false)->where('status_id', '>', 1)->get() as $invoice) {
$total_invoice_payments += $invoice->payments()
->where('is_deleted', false)->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
->selectRaw('sum(paymentables.amount - paymentables.refunded) as p')
->pluck('p')
->first();
}
//commented IN 27/06/2021 - sums ALL client payments AND the unapplied amounts to match the client paid to date
$p = Payment::where('client_id', $client->id)
->where('is_deleted', 0)
->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
->sum(DB::Raw('amount - applied'));
$total_invoice_payments += $p;
// 10/02/21
foreach ($client->payments as $payment) {
$credit_total_applied += $payment->paymentables()
->where('paymentable_type', App\Models\Credit::class)
->selectRaw('sum(paymentables.amount - paymentables.refunded) as p')
->pluck('p')
->first();
}
if ($credit_total_applied < 0) {
$total_invoice_payments += $credit_total_applied;
}
if (round($total_invoice_payments, 2) != round($client->paid_to_date, 2)) {
$this->wrong_paid_to_dates++;
$this->logMessage($client->present()->name().' id = # '.$client->id." - Paid to date does not match Client Paid To Date = {$client->paid_to_date} - Invoice Payments = {$total_invoice_payments}");
$this->isValid = false;
if ($this->option('paid_to_date')) {
$this->logMessage("# {$client->id} " . $client->present()->name().' - '.$client->number." Fixing {$client->paid_to_date} to {$total_invoice_payments}");
$client->paid_to_date = $total_invoice_payments;
$client->save();
}
}
});
$this->logMessage("{$this->wrong_paid_to_dates} clients with incorrect paid to dates");
}
private function checkInvoicePayments()
{
$this->wrong_balances = 0;
Client::query()->cursor()->where('is_deleted', 0)->where('clients.updated_at', '>', now()->subDays(2))->each(function ($client) {
$client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($client) {
$total_paid = $invoice->payments()
->where('is_deleted', false)->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
->selectRaw('sum(paymentables.amount - paymentables.refunded) as p')
->pluck('p')
->first();
$total_credit = $invoice->credits()->get()->sum('amount');
$calculated_paid_amount = $invoice->amount - $invoice->balance - $total_credit;
if ((string)$total_paid != (string)($invoice->amount - $invoice->balance - $total_credit)) {
$this->wrong_balances++;
$this->logMessage($client->present()->name().' - '.$client->id." - Total Paid = {$total_paid} != Calculated Total = {$calculated_paid_amount}");
$this->isValid = false;
}
});
});
$this->logMessage("{$this->wrong_balances} clients with incorrect invoice balances");
}
private function clientBalanceQuery() private function clientBalanceQuery()
{ {
$results = \DB::select(\DB::raw(" $results = \DB::select("
SELECT SELECT
SUM(invoices.balance) as invoice_balance, SUM(invoices.balance) as invoice_balance,
clients.id as client_id, clients.id as client_id,
@ -736,7 +637,7 @@ class CheckData extends Command
GROUP BY clients.id GROUP BY clients.id
HAVING invoice_balance != clients.balance HAVING invoice_balance != clients.balance
ORDER BY clients.id; ORDER BY clients.id;
")); ");
return $results; return $results;
} }
@ -813,7 +714,7 @@ class CheckData extends Command
private function invoiceBalanceQuery() private function invoiceBalanceQuery()
{ {
$results = \DB::select(\DB::raw(" $results = \DB::select("
SELECT SELECT
clients.id, clients.id,
clients.balance, clients.balance,
@ -827,7 +728,7 @@ class CheckData extends Command
GROUP BY clients.id GROUP BY clients.id
HAVING(invoices_balance != clients.balance) HAVING(invoices_balance != clients.balance)
ORDER BY clients.id; ORDER BY clients.id;
")); ");
return $results; return $results;
} }
@ -961,7 +862,7 @@ class CheckData extends Command
} }
$records = DB::table($table) $records = DB::table($table)
->join($tableName, "{$tableName}.id", '=', "{$table}.{$field}_id") ->join($tableName, "{$tableName}.id", '=', "{$table}.{$field}_id")
->where("{$table}.{$company_id}", '!=', DB::raw("{$tableName}.company_id")) ->whereRaw("{$table}.{$company_id} != {$tableName}.company_id")
->get(["{$table}.id"]); ->get(["{$table}.id"]);
if ($records->count()) { if ($records->count()) {
@ -971,11 +872,6 @@ class CheckData extends Command
} }
} }
// foreach(User::cursor() as $user) {
// $records = Company::where('account_id',)
// }
} }
public function pluralizeEntityType($type) public function pluralizeEntityType($type)

View File

@ -63,17 +63,25 @@ class CreateAccount extends Command
private function createAccount() private function createAccount()
{ {
$settings = CompanySettings::defaults();
$settings->name = "Untitled Company";
$settings->currency_id = '1';
$settings->language_id = '1';
$account = Account::factory()->create(); $account = Account::factory()->create();
$company = Company::factory()->create([ $company = Company::factory()->create([
'account_id' => $account->id, 'account_id' => $account->id,
'portal_domain' => config('ninja.app_url'), 'portal_domain' => config('ninja.app_url'),
'portal_mode' => 'domain', 'portal_mode' => 'domain',
'settings' => $settings,
]); ]);
$company->client_registration_fields = ClientRegistrationFields::generate(); $company->client_registration_fields = ClientRegistrationFields::generate();
$company->save(); $company->save();
$account->default_company_id = $company->id; $account->default_company_id = $company->id;
$account->set_react_as_default_ap = true;
$account->save(); $account->save();
$email = $this->option('email') ?? 'admin@example.com'; $email = $this->option('email') ?? 'admin@example.com';

View File

@ -61,6 +61,8 @@ class CreateTestData extends Command
protected $invoice_repo; protected $invoice_repo;
protected $count;
/** /**
* Execute the console command. * Execute the console command.
* *

View File

@ -48,8 +48,16 @@ class ReactBuilder extends Command
{ {
$includes = ''; $includes = '';
$directoryIterator = new \RecursiveDirectoryIterator(public_path('react'), \RecursiveDirectoryIterator::SKIP_DOTS); $directoryIterator = false;
try {
$directoryIterator = new \RecursiveDirectoryIterator(public_path('react/v'.config('ninja.app_version').'/'), \RecursiveDirectoryIterator::SKIP_DOTS);
}
catch (\Exception $e) {
$this->error('React files not found');
return;
}
foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) { foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) {
if ($file->getExtension() == 'js') { if ($file->getExtension() == 'js') {
if (str_contains($file->getFileName(), 'index-')) { if (str_contains($file->getFileName(), 'index-')) {

View File

@ -173,7 +173,7 @@ class SendRemindersCron extends Command
/**Refresh Invoice values*/ /**Refresh Invoice values*/
$invoice->calc()->getInvoice()->save(); $invoice->calc()->getInvoice()->save();
$invoice->fresh(); $invoice->fresh();
$invoice->service()->deletePdf()->save(); // $invoice->service()->deletePdf()->save();
if ($invoice->client->getSetting('enable_e_invoice')){ if ($invoice->client->getSetting('enable_e_invoice')){
$invoice->service()->deleteEInvoice()->save(); $invoice->service()->deleteEInvoice()->save();
} }

View File

@ -11,28 +11,29 @@
namespace App\Console; namespace App\Console;
use App\Jobs\Cron\AutoBillCron; use App\Utils\Ninja;
use App\Jobs\Cron\RecurringExpensesCron; use App\Models\Account;
use App\Jobs\Cron\RecurringInvoicesCron;
use App\Jobs\Cron\SubscriptionCron;
use App\Jobs\Cron\UpdateCalculatedFields;
use App\Jobs\Invoice\InvoiceCheckLateWebhook;
use App\Jobs\Ninja\AdjustEmailQuota;
use App\Jobs\Ninja\BankTransactionSync;
use App\Jobs\Ninja\CompanySizeCheck;
use App\Jobs\Ninja\QueueSize; use App\Jobs\Ninja\QueueSize;
use App\Jobs\Ninja\SystemMaintenance;
use App\Jobs\Ninja\TaskScheduler;
use App\Jobs\Quote\QuoteCheckExpired;
use App\Jobs\Subscription\CleanStaleInvoiceOrder;
use App\Jobs\Util\DiskCleanup; use App\Jobs\Util\DiskCleanup;
use App\Jobs\Util\ReminderJob; use App\Jobs\Util\ReminderJob;
use App\Jobs\Util\SchedulerCheck; use App\Jobs\Cron\AutoBillCron;
use App\Jobs\Util\UpdateExchangeRates;
use App\Jobs\Util\VersionCheck; use App\Jobs\Util\VersionCheck;
use App\Models\Account; use App\Jobs\Ninja\TaskScheduler;
use App\Utils\Ninja; use App\Jobs\Util\SchedulerCheck;
use App\Jobs\Ninja\CheckACHStatus;
use App\Jobs\Cron\SubscriptionCron;
use App\Jobs\Ninja\AdjustEmailQuota;
use App\Jobs\Ninja\CompanySizeCheck;
use App\Jobs\Ninja\SystemMaintenance;
use App\Jobs\Quote\QuoteCheckExpired;
use App\Jobs\Util\UpdateExchangeRates;
use App\Jobs\Ninja\BankTransactionSync;
use App\Jobs\Cron\RecurringExpensesCron;
use App\Jobs\Cron\RecurringInvoicesCron;
use App\Jobs\Cron\UpdateCalculatedFields;
use Illuminate\Console\Scheduling\Schedule; use Illuminate\Console\Scheduling\Schedule;
use App\Jobs\Invoice\InvoiceCheckLateWebhook;
use App\Jobs\Subscription\CleanStaleInvoiceOrder;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel; use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel class Kernel extends ConsoleKernel
@ -107,7 +108,10 @@ class Kernel extends ConsoleKernel
$schedule->job(new AdjustEmailQuota)->dailyAt('23:30')->withoutOverlapping(); $schedule->job(new AdjustEmailQuota)->dailyAt('23:30')->withoutOverlapping();
/* Pulls in bank transactions from third party services */ /* Pulls in bank transactions from third party services */
$schedule->job(new BankTransactionSync)->dailyAt('04:10')->withoutOverlapping()->name('bank-trans-sync-job')->onOneServer(); $schedule->job(new BankTransactionSync)->everyFourHours()->withoutOverlapping()->name('bank-trans-sync-job')->onOneServer();
/* Checks ACH verification status and updates state to authorize when verified */
$schedule->job(new CheckACHStatus)->everySixHours()->withoutOverlapping()->name('ach-status-job')->onOneServer();
$schedule->command('ninja:check-data --database=db-ninja-01')->dailyAt('02:10')->withoutOverlapping()->name('check-data-db-1-job')->onOneServer(); $schedule->command('ninja:check-data --database=db-ninja-01')->dailyAt('02:10')->withoutOverlapping()->name('check-data-db-1-job')->onOneServer();

View File

@ -481,8 +481,11 @@ class CompanySettings extends BaseSettings
public $enable_e_invoice = false; public $enable_e_invoice = false;
public $classification = ''; // individual, company, partnership, trust, charity, government, other
public static $casts = [ public static $casts = [
'enable_e_invoice' => 'bool', 'enable_e_invoice' => 'bool',
'classification' => 'string',
'default_expense_payment_type_id' => 'string', 'default_expense_payment_type_id' => 'string',
'e_invoice_type' => 'string', 'e_invoice_type' => 'string',
'mailgun_endpoint' => 'string', 'mailgun_endpoint' => 'string',
@ -838,11 +841,30 @@ class CompanySettings extends BaseSettings
{ {
$notification = new stdClass; $notification = new stdClass;
$notification->email = []; $notification->email = [];
$notification->email = ['invoice_sent_all'];
// $notification->email = ['all_notifications']; // $notification->email = ['all_notifications'];
return $notification; return $notification;
} }
/**
* Stubs the notification defaults
*
* @return stdClass
*/
public static function notificationAdminDefaults() :stdClass
{
$notification = new stdClass;
$notification->email = [];
$notification->email = ['invoice_sent_all'];
return $notification;
}
/** /**
* Defines entity variables for PDF generation * Defines entity variables for PDF generation
* *

View File

@ -363,7 +363,15 @@ class BaseRule implements RuleInterface
public function override($item): self public function override($item): self
{ {
$this->tax_rate1 = $item->tax_rate1;
$this->tax_name1 = $item->tax_name1;
$this->tax_rate2 = $item->tax_rate2;
$this->tax_name2 = $item->tax_name2;
$this->tax_rate3 = $item->tax_rate3;
$this->tax_name3 = $item->tax_name3;
return $this; return $this;
} }
public function calculateRates(): self public function calculateRates(): self

View File

@ -49,6 +49,10 @@ class Rule extends BaseRule implements RuleInterface
$this->tax_rate1 = $item->tax_rate1; $this->tax_rate1 = $item->tax_rate1;
$this->tax_name1 = $item->tax_name1; $this->tax_name1 = $item->tax_name1;
$this->tax_rate2 = $item->tax_rate2;
$this->tax_name2 = $item->tax_name2;
$this->tax_rate3 = $item->tax_rate3;
$this->tax_name3 = $item->tax_name3;
return $this; return $this;

View File

@ -26,7 +26,7 @@ class UserWasCreated
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(public User $user, public User $creating_user, public Company $company, public array $event_vars) public function __construct(public User $user, public User $creating_user, public Company $company, public array $event_vars, public $is_react = true)
{ {
} }

View File

@ -20,6 +20,7 @@ use App\Libraries\MultiDB;
use App\Models\DateFormat; use App\Models\DateFormat;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Database\Eloquent\Builder;
use App\Transformers\ActivityTransformer; use App\Transformers\ActivityTransformer;
class ActivityExport extends BaseExport class ActivityExport extends BaseExport
@ -39,10 +40,6 @@ class ActivityExport extends BaseExport
'address' => 'address', 'address' => 'address',
]; ];
private array $decorate_keys = [
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -50,47 +47,33 @@ class ActivityExport extends BaseExport
$this->entity_transformer = new ActivityTransformer(); $this->entity_transformer = new ActivityTransformer();
} }
public function run() public function returnJson()
{ {
MultiDB::setDb($this->company->db); $query = $this->init();
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
$this->date_format = DateFormat::find($this->company->settings->date_format_id)->format; $headerdisplay = $this->buildHeader();
//load the CSV document from a string $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
$this->csv = Writer::createFromString(); return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
ksort($this->entity_keys);
$report = $query->cursor()
if (count($this->input['report_keys']) == 0) { ->map(function ($resource) {
$this->input['report_keys'] = array_values($this->entity_keys); $row = $this->buildActivityRow($resource);
} return $this->processMetaData($row, $resource);
})->toArray();
//insert the header
$this->csv->insertOne($this->buildHeader()); return array_merge(['columns' => $header], $report);
$query = Activity::query()
->where('company_id', $this->company->id);
$query = $this->addDateRange($query);
$query->cursor()
->each(function ($entity) {
$this->buildRow($entity);
});
return $this->csv->toString();
} }
private function buildRow(Activity $activity) private function buildActivityRow(Activity $activity): array
{ {
return [
$this->csv->insertOne([
Carbon::parse($activity->created_at)->format($this->date_format), Carbon::parse($activity->created_at)->format($this->date_format),
ctrans("texts.activity_{$activity->activity_type_id}",[ ctrans("texts.activity_{$activity->activity_type_id}",[
'payment_amount' => $activity->payment ? $activity->payment->amount : '',
'adjustment' => $activity->payment ? $activity->payment->refunded : '',
'client' => $activity->client ? $activity->client->present()->name() : '', 'client' => $activity->client ? $activity->client->present()->name() : '',
'contact' => $activity->contact ? $activity->contact->present()->name() : '', 'contact' => $activity->contact ? $activity->contact->present()->name() : '',
'quote' => $activity->quote ? $activity->quote->number : '', 'quote' => $activity->quote ? $activity->quote->number : '',
@ -108,7 +91,57 @@ class ActivityExport extends BaseExport
'recurring_expense' => $activity->recurring_expense ? $activity->recurring_expense->number : '', 'recurring_expense' => $activity->recurring_expense ? $activity->recurring_expense->number : '',
]), ]),
$activity->ip, $activity->ip,
]); ];
}
private function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
$this->date_format = DateFormat::find($this->company->settings->date_format_id)->format;
// ksort($this->entity_keys);
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}
$query = Activity::query()
->where('company_id', $this->company->id);
$query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($entity) {
$this->buildRow($entity);
});
return $this->csv->toString();
}
private function buildRow(Activity $activity)
{
$this->csv->insertOne($this->buildActivityRow($activity));
} }
@ -117,4 +150,25 @@ class ActivityExport extends BaseExport
{ {
return $entity; return $entity;
} }
public function processMetaData(array $row, $resource): array
{
$clean_row = [];
foreach (array_values($this->input['report_keys']) as $key => $value) {
$clean_row[$key]['entity'] = 'activity';
$clean_row[$key]['id'] = $key;
$clean_row[$key]['hashed_id'] = null;
$clean_row[$key]['value'] = $row[$key];
$clean_row[$key]['identifier'] = $value;
$clean_row[$key]['display_value'] = $row[$key];
}
return $clean_row;
}
} }

View File

@ -11,24 +11,35 @@
namespace App\Export\CSV; namespace App\Export\CSV;
use App\Models\Activity;
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\Utils\Helpers;
use App\Models\Company; use App\Models\Company;
use App\Models\Expense; use App\Models\Expense;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\Document;
use League\Fractal\Manager; use League\Fractal\Manager;
use App\Models\ClientContact;
use App\Models\PurchaseOrder;
use App\Models\RecurringInvoice;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Transformers\TaskTransformer; use App\Transformers\TaskTransformer;
use App\Transformers\PaymentTransformer; use App\Transformers\PaymentTransformer;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use League\Fractal\Serializer\ArraySerializer; use League\Fractal\Serializer\ArraySerializer;
use App\Models\Product;
use App\Models\Task;
use App\Models\Vendor;
class BaseExport class BaseExport
{ {
use MakesHash; use MakesHash;
public Company $company; public Company $company;
public array $input; public array $input;
@ -43,8 +54,6 @@ class BaseExport
public string $client_description = 'All Clients'; public string $client_description = 'All Clients';
public array $forced_keys = [];
protected array $vendor_report_keys = [ protected array $vendor_report_keys = [
'address1' => 'vendor.address1', 'address1' => 'vendor.address1',
'address2' => 'vendor.address2', 'address2' => 'vendor.address2',
@ -57,7 +66,7 @@ class BaseExport
'id_number' => 'vendor.id_number', 'id_number' => 'vendor.id_number',
'name' => 'vendor.name', 'name' => 'vendor.name',
'number' => 'vendor.number', 'number' => 'vendor.number',
'client_phone' => 'vendor.phone', 'phone' => 'vendor.phone',
'postal_code' => 'vendor.postal_code', 'postal_code' => 'vendor.postal_code',
'private_notes' => 'vendor.private_notes', 'private_notes' => 'vendor.private_notes',
'public_notes' => 'vendor.public_notes', 'public_notes' => 'vendor.public_notes',
@ -74,6 +83,7 @@ class BaseExport
'contact_custom_value4' => 'vendor_contact.custom_value4', 'contact_custom_value4' => 'vendor_contact.custom_value4',
'email' => 'vendor_contact.email', 'email' => 'vendor_contact.email',
'status' => 'vendor.status', 'status' => 'vendor.status',
'classification' => 'vendor.classification',
]; ];
protected array $client_report_keys = [ protected array $client_report_keys = [
@ -116,10 +126,13 @@ class BaseExport
"contact_custom_value2" => "contact.custom_value2", "contact_custom_value2" => "contact.custom_value2",
"contact_custom_value3" => "contact.custom_value3", "contact_custom_value3" => "contact.custom_value3",
"contact_custom_value4" => "contact.custom_value4", "contact_custom_value4" => "contact.custom_value4",
'payment_balance' => 'client.payment_balance',
'credit_balance' => 'client.credit_balance',
'classification' => 'client.classification',
]; ];
protected array $invoice_report_keys = [ protected array $invoice_report_keys = [
'name' => 'client.name',
"invoice_number" => "invoice.number", "invoice_number" => "invoice.number",
"amount" => "invoice.amount", "amount" => "invoice.amount",
"balance" => "invoice.balance", "balance" => "invoice.balance",
@ -134,6 +147,7 @@ class BaseExport
"private_notes" => "invoice.private_notes", "private_notes" => "invoice.private_notes",
"uses_inclusive_taxes" => "invoice.uses_inclusive_taxes", "uses_inclusive_taxes" => "invoice.uses_inclusive_taxes",
"is_amount_discount" => "invoice.is_amount_discount", "is_amount_discount" => "invoice.is_amount_discount",
"discount" => "invoice.discount",
"partial" => "invoice.partial", "partial" => "invoice.partial",
"partial_due_date" => "invoice.partial_due_date", "partial_due_date" => "invoice.partial_due_date",
"surcharge1" => "invoice.custom_surcharge1", "surcharge1" => "invoice.custom_surcharge1",
@ -144,6 +158,16 @@ class BaseExport
"tax_amount" => "invoice.total_taxes", "tax_amount" => "invoice.total_taxes",
"assigned_user" => "invoice.assigned_user_id", "assigned_user" => "invoice.assigned_user_id",
"user" => "invoice.user_id", "user" => "invoice.user_id",
"custom_value1" => "invoice.custom_value1",
"custom_value2" => "invoice.custom_value2",
"custom_value3" => "invoice.custom_value3",
"custom_value4" => "invoice.custom_value4",
'tax_name1' => 'invoice.tax_name1',
'tax_name2' => 'invoice.tax_name2',
'tax_name3' => 'invoice.tax_name3',
'tax_rate1' => 'invoice.tax_rate1',
'tax_rate2' => 'invoice.tax_rate2',
'tax_rate3' => 'invoice.tax_rate3',
]; ];
protected array $recurring_invoice_report_keys = [ protected array $recurring_invoice_report_keys = [
@ -161,6 +185,7 @@ class BaseExport
"private_notes" => "recurring_invoice.private_notes", "private_notes" => "recurring_invoice.private_notes",
"uses_inclusive_taxes" => "recurring_invoice.uses_inclusive_taxes", "uses_inclusive_taxes" => "recurring_invoice.uses_inclusive_taxes",
"is_amount_discount" => "recurring_invoice.is_amount_discount", "is_amount_discount" => "recurring_invoice.is_amount_discount",
"discount" => "recurring_invoice.discount",
"partial" => "recurring_invoice.partial", "partial" => "recurring_invoice.partial",
"partial_due_date" => "recurring_invoice.partial_due_date", "partial_due_date" => "recurring_invoice.partial_due_date",
"surcharge1" => "recurring_invoice.custom_surcharge1", "surcharge1" => "recurring_invoice.custom_surcharge1",
@ -172,17 +197,23 @@ class BaseExport
"assigned_user" => "recurring_invoice.assigned_user_id", "assigned_user" => "recurring_invoice.assigned_user_id",
"user" => "recurring_invoice.user_id", "user" => "recurring_invoice.user_id",
"frequency_id" => "recurring_invoice.frequency_id", "frequency_id" => "recurring_invoice.frequency_id",
"next_send_date" => "recurring_invoice.next_send_date" "next_send_date" => "recurring_invoice.next_send_date",
"custom_value1" => "recurring_invoice.custom_value1",
"custom_value2" => "recurring_invoice.custom_value2",
"custom_value3" => "recurring_invoice.custom_value3",
"custom_value4" => "recurring_invoice.custom_value4",
'tax_name1' => 'recurring_invoice.tax_name1',
'tax_name2' => 'recurring_invoice.tax_name2',
'tax_name3' => 'recurring_invoice.tax_name3',
'tax_rate1' => 'recurring_invoice.tax_rate1',
'tax_rate2' => 'recurring_invoice.tax_rate2',
'tax_rate3' => 'recurring_invoice.tax_rate3',
]; ];
protected array $purchase_order_report_keys = [ protected array $purchase_order_report_keys = [
'amount' => 'purchase_order.amount', 'amount' => 'purchase_order.amount',
'balance' => 'purchase_order.balance', 'balance' => 'purchase_order.balance',
'vendor' => 'purchase_order.vendor_id', 'vendor' => 'purchase_order.vendor_id',
// 'custom_surcharge1' => 'purchase_order.custom_surcharge1',
// 'custom_surcharge2' => 'purchase_order.custom_surcharge2',
// 'custom_surcharge3' => 'purchase_order.custom_surcharge3',
// 'custom_surcharge4' => 'purchase_order.custom_surcharge4',
'custom_value1' => 'purchase_order.custom_value1', 'custom_value1' => 'purchase_order.custom_value1',
'custom_value2' => 'purchase_order.custom_value2', 'custom_value2' => 'purchase_order.custom_value2',
'custom_value3' => 'purchase_order.custom_value3', 'custom_value3' => 'purchase_order.custom_value3',
@ -211,17 +242,41 @@ class BaseExport
'currency_id' => 'purchase_order.currency_id', 'currency_id' => 'purchase_order.currency_id',
]; ];
protected array $product_report_keys = [
// 'project' => 'project_id',
// 'vendor' => 'vendor_id',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'product_key' => 'product_key',
'notes' => 'notes',
'cost' => 'cost',
'price' => 'price',
'quantity' => 'quantity',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'image' => 'product_image',
'tax_category' => 'tax_id',
'max_quantity' => 'max_quantity',
'in_stock_quantity' => 'in_stock_quantity',
];
protected array $item_report_keys = [ protected array $item_report_keys = [
"quantity" => "item.quantity", "quantity" => "item.quantity",
"cost" => "item.cost", "cost" => "item.cost",
"product_key" => "item.product_key", "product_key" => "item.product_key",
"notes" => "item.notes", "notes" => "item.notes",
"item_tax1" => "item.tax_name1", "tax_name1" => "item.tax_name1",
"item_tax_rate1" => "item.tax_rate1", "tax_rate1" => "item.tax_rate1",
"item_tax2" => "item.tax_name2", "tax_name2" => "item.tax_name2",
"item_tax_rate2" => "item.tax_rate2", "tax_rate2" => "item.tax_rate2",
"item_tax3" => "item.tax_name3", "tax_name3" => "item.tax_name3",
"item_tax_rate3" => "item.tax_rate3", "tax_rate3" => "item.tax_rate3",
"custom_value1" => "item.custom_value1", "custom_value1" => "item.custom_value1",
"custom_value2" => "item.custom_value2", "custom_value2" => "item.custom_value2",
"custom_value3" => "item.custom_value3", "custom_value3" => "item.custom_value3",
@ -229,6 +284,9 @@ class BaseExport
"discount" => "item.discount", "discount" => "item.discount",
"type" => "item.type_id", "type" => "item.type_id",
"tax_category" => "item.tax_id", "tax_category" => "item.tax_id",
'is_amount_discount' => 'item.is_amount_discount',
'line_total' => 'item.line_total',
'gross_line_total' => 'item.gross_line_total',
]; ];
protected array $quote_report_keys = [ protected array $quote_report_keys = [
@ -250,6 +308,7 @@ class BaseExport
"private_notes" => "quote.private_notes", "private_notes" => "quote.private_notes",
"uses_inclusive_taxes" => "quote.uses_inclusive_taxes", "uses_inclusive_taxes" => "quote.uses_inclusive_taxes",
"is_amount_discount" => "quote.is_amount_discount", "is_amount_discount" => "quote.is_amount_discount",
"discount" => "quote.discount",
"partial" => "quote.partial", "partial" => "quote.partial",
"partial_due_date" => "quote.partial_due_date", "partial_due_date" => "quote.partial_due_date",
"surcharge1" => "quote.custom_surcharge1", "surcharge1" => "quote.custom_surcharge1",
@ -260,6 +319,12 @@ class BaseExport
"tax_amount" => "quote.total_taxes", "tax_amount" => "quote.total_taxes",
"assigned_user" => "quote.assigned_user_id", "assigned_user" => "quote.assigned_user_id",
"user" => "quote.user_id", "user" => "quote.user_id",
'tax_name1' => 'quote.tax_name1',
'tax_name2' => 'quote.tax_name2',
'tax_name3' => 'quote.tax_name3',
'tax_rate1' => 'quote.tax_rate1',
'tax_rate2' => 'quote.tax_rate2',
'tax_rate3' => 'quote.tax_rate3',
]; ];
protected array $credit_report_keys = [ protected array $credit_report_keys = [
@ -271,6 +336,7 @@ class BaseExport
"date" => "credit.date", "date" => "credit.date",
"due_date" => "credit.due_date", "due_date" => "credit.due_date",
"terms" => "credit.terms", "terms" => "credit.terms",
"discount" => "credit.discount",
"footer" => "credit.footer", "footer" => "credit.footer",
"status" => "credit.status", "status" => "credit.status",
"public_notes" => "credit.public_notes", "public_notes" => "credit.public_notes",
@ -283,6 +349,10 @@ class BaseExport
"surcharge2" => "credit.custom_surcharge2", "surcharge2" => "credit.custom_surcharge2",
"surcharge3" => "credit.custom_surcharge3", "surcharge3" => "credit.custom_surcharge3",
"surcharge4" => "credit.custom_surcharge4", "surcharge4" => "credit.custom_surcharge4",
"custom_value1" => "credit.custom_value1",
"custom_value2" => "credit.custom_value2",
"custom_value3" => "credit.custom_value3",
"custom_value4" => "credit.custom_value4",
"exchange_rate" => "credit.exchange_rate", "exchange_rate" => "credit.exchange_rate",
"tax_amount" => "credit.total_taxes", "tax_amount" => "credit.total_taxes",
"assigned_user" => "credit.assigned_user_id", "assigned_user" => "credit.assigned_user_id",
@ -312,7 +382,7 @@ class BaseExport
protected array $expense_report_keys = [ protected array $expense_report_keys = [
'amount' => 'expense.amount', 'amount' => 'expense.amount',
'category' => 'expense.category_id', 'category' => 'expense.category_id',
'client' => 'expense.client_id', // 'client' => 'expense.client_id',
'custom_value1' => 'expense.custom_value1', 'custom_value1' => 'expense.custom_value1',
'custom_value2' => 'expense.custom_value2', 'custom_value2' => 'expense.custom_value2',
'custom_value3' => 'expense.custom_value3', 'custom_value3' => 'expense.custom_value3',
@ -526,31 +596,33 @@ class BaseExport
$manager->setSerializer(new ArraySerializer()); $manager->setSerializer(new ArraySerializer());
$transformed_client = $manager->createData($transformed_client)->toArray(); $transformed_client = $manager->createData($transformed_client)->toArray();
if($column == 'name') if(in_array($column, ['client.name', 'name']))
return $transformed_client['display_name']; return $transformed_client['display_name'];
if($column == 'user_id') if(in_array($column, ['client.user_id', 'user_id']))
return $entity->client->user->present()->name(); return $entity->client->user->present()->name();
if($column == 'country_id') if(in_array($column, ['client.assigned_user_id', 'assigned_user_id']))
return $entity->client->assigned_user->present()->name();
if(in_array($column, ['client.country_id', 'country_id']))
return $entity->client->country ? ctrans("texts.country_{$entity->client->country->name}") : ''; return $entity->client->country ? ctrans("texts.country_{$entity->client->country->name}") : '';
if($column == 'shipping_country_id') if(in_array($column, ['client.shipping_country_id', 'shipping_country_id']))
return $entity->client->shipping_country ? ctrans("texts.country_{$entity->client->shipping_country->name}") : ''; return $entity->client->shipping_country ? ctrans("texts.country_{$entity->client->shipping_country->name}") : '';
if($column == 'size_id') if(in_array($column, ['client.size_id', 'size_id']))
return $entity->client->size?->name ?? ''; return $entity->client->size?->name ?? '';
if($column == 'industry_id') if(in_array($column, ['client.industry_id', 'industry_id']))
return $entity->client->industry?->name ?? ''; return $entity->client->industry?->name ?? '';
if ($column == 'currency_id') { if (in_array($column, ['client.currency_id', 'currency_id']))
return $entity->client->currency() ? $entity->client->currency()->code : $entity->company->currency()->code; return $entity->client->currency() ? $entity->client->currency()->code : $entity->company->currency()->code;
}
if(in_array($column, ['payment_terms', 'client.payment_terms']))
if($column == 'client.payment_terms') {
return $entity->client->getSetting('payment_terms'); return $entity->client->getSetting('payment_terms');
}
if(array_key_exists($column, $transformed_client)) if(array_key_exists($column, $transformed_client))
return $transformed_client[$column]; return $transformed_client[$column];
@ -592,7 +664,7 @@ class BaseExport
// nlog("searching for {$column}"); // nlog("searching for {$column}");
$transformed_invoice = false; $transformed_invoice = false;
if($transformer instanceof PaymentTransformer) { if($transformer instanceof PaymentTransformer && ($entity->invoices ?? false)) {
$transformed_invoices = $transformer->includeInvoices($entity); $transformed_invoices = $transformer->includeInvoices($entity);
$manager = new Manager(); $manager = new Manager();
@ -614,7 +686,7 @@ class BaseExport
} }
if($transformer instanceof TaskTransformer) { if($transformer instanceof TaskTransformer && ($entity->invoice ?? false)) {
$transformed_invoice = $transformer->includeInvoice($entity); $transformed_invoice = $transformer->includeInvoice($entity);
if(!$transformed_invoice) if(!$transformed_invoice)
@ -829,17 +901,32 @@ class BaseExport
return $query->whereBetween($this->date_key, [now()->startOfYear(), now()])->orderBy($this->date_key, 'ASC'); return $query->whereBetween($this->date_key, [now()->startOfYear(), now()])->orderBy($this->date_key, 'ASC');
} }
} }
/**
* Returns the merged array of
* the entity with the matching
* item report keys
*
* @param string $entity_report_keys
* @return array
*/
public function mergeItemsKeys(string $entity_report_keys): array
{
return array_merge($this->{$entity_report_keys}, $this->item_report_keys);
}
public function buildHeader() :array public function buildHeader() :array
{ {
$helper = new Helpers();
$header = []; $header = [];
// nlog("header");
// nlog($this->input['report_keys']); foreach ($this->input['report_keys'] as $value) {
foreach (array_merge($this->input['report_keys'], $this->forced_keys) as $value) {
$key = array_search($value, $this->entity_keys); $key = array_search($value, $this->entity_keys);
nlog("{$key} => {$value}"); $original_key = $key;
// nlog("{$key} => {$value}");
$prefix = ''; $prefix = '';
if(!$key) { if(!$key) {
@ -880,6 +967,9 @@ class BaseExport
if(!$key) { if(!$key) {
$prefix = ctrans('texts.expense')." "; $prefix = ctrans('texts.expense')." ";
$key = array_search($value, $this->expense_report_keys); $key = array_search($value, $this->expense_report_keys);
if(!$key && $value == 'expense.category')
$key = 'category';
} }
if(!$key) { if(!$key) {
@ -899,8 +989,15 @@ class BaseExport
if(!$key) { if(!$key) {
$prefix = ''; $prefix = '';
$key = array_search($value, $this->product_report_keys);
} }
if(!$key) {
$prefix = '';
}
// nlog("key => {$key}");
$key = str_replace('item.', '', $key); $key = str_replace('item.', '', $key);
$key = str_replace('recurring_invoice.', '', $key); $key = str_replace('recurring_invoice.', '', $key);
$key = str_replace('purchase_order.', '', $key); $key = str_replace('purchase_order.', '', $key);
@ -913,11 +1010,42 @@ class BaseExport
$key = str_replace('contact.', '', $key); $key = str_replace('contact.', '', $key);
$key = str_replace('payment.', '', $key); $key = str_replace('payment.', '', $key);
$key = str_replace('expense.', '', $key); $key = str_replace('expense.', '', $key);
// nlog($key); $key = str_replace('product.', '', $key);
if(in_array($key, ['quote1','quote2','quote3','quote4','credit1','credit2','credit3','credit4','purchase_order1','purchase_order2','purchase_order3','purchase_order4'])) $key = str_replace('task.', '', $key);
if(stripos($value, 'custom_value') !== false)
{ {
$number = substr($key, -1); $parts = explode(".", $value);
$header[] = ctrans('texts.item') . " ". ctrans("texts.custom_value{$number}");
if(count($parts) == 2 && in_array($parts[0], ['credit','quote','invoice','purchase_order','recurring_invoice'])){
$entity = "invoice".substr($parts[1], -1);
$prefix = ctrans("texts.".$parts[0]);
$fallback = "custom_value".substr($parts[1], -1);
$custom_field_label = $helper->makeCustomField($this->company->custom_fields, $entity);
if(strlen($custom_field_label) > 1)
$header[] = $custom_field_label;
else {
$header[] = $prefix . " ". ctrans("texts.{$fallback}");
}
}
elseif(count($parts) == 2 && (stripos($parts[0], 'vendor_contact') !== false || stripos($parts[0], 'contact') !== false)) {
$parts[0] = str_replace('vendor_contact', 'contact', $parts[0]);
$entity = "contact".substr($parts[1], -1);
$custom_field_string = strlen($helper->makeCustomField($this->company->custom_fields, $entity)) > 1 ? $helper->makeCustomField($this->company->custom_fields, $entity) : ctrans("texts.{$parts[1]}");
$header[] = ctrans("texts.{$parts[0]}") . " " . $custom_field_string;
}
elseif(count($parts) == 2 && in_array(substr($original_key, 0, -1), ['credit','quote','invoice','purchase_order','recurring_invoice','task'])){
$custom_field_string = strlen($helper->makeCustomField($this->company->custom_fields, "product".substr($original_key,-1))) > 1 ? $helper->makeCustomField($this->company->custom_fields, "product".substr($original_key,-1)) : ctrans("texts.{$parts[1]}");
$header[] = ctrans("texts.{$parts[0]}") . " " . $custom_field_string;
}
else{
$header[] = "{$prefix}" . ctrans("texts.{$key}");
}
} }
else else
{ {
@ -926,7 +1054,103 @@ class BaseExport
} }
// nlog($header); // nlog($header);
return $header; return $header;
} }
public function processMetaData(array $row, $resource): array
{
$class = get_class($resource);
$entity = '';
match ($class) {
Invoice::class => $entity = 'invoice',
RecurringInvoice::class => $entity = 'recurring_invoice',
Quote::class => $entity = 'quote',
Credit::class => $entity = 'credit',
Expense::class => $entity = 'expense',
Document::class => $entity = 'document',
ClientContact::class => $entity = 'contact',
PurchaseOrder::class => $entity = 'purchase_order',
Payment::class => $entity = 'payment',
Product::class => $entity = 'product',
Task::class => $entity = 'task',
Vendor::class => $entity = 'vendor',
default => $entity = 'invoice',
};
$clean_row = [];
foreach (array_values($this->input['report_keys']) as $key => $value) {
$report_keys = explode(".", $value);
$column_key = $value;
if($value == 'product_image') {
$column_key = 'image';
$value = 'image';
}
if($value == 'tax_id') {
$column_key = 'tax_category';
$value = 'tax_category';
}
$clean_row[$key]['entity'] = $report_keys[0];
$clean_row[$key]['id'] = $report_keys[1] ?? $report_keys[0];
$clean_row[$key]['hashed_id'] = $report_keys[0] == $entity ? null : $resource->{$report_keys[0]}->hashed_id ?? null;
$clean_row[$key]['value'] = $row[$column_key];
$clean_row[$key]['identifier'] = $value;
$clean_row[$key]['display_value'] = $row[$column_key];
}
return $clean_row;
}
public function processItemMetaData(array $row, $resource): array
{
$class = get_class($resource);
$entity = '';
match ($class) {
Invoice::class => $entity = 'invoice',
Quote::class => $entity = 'quote',
Credit::class => $entity = 'credit',
Expense::class => $entity = 'expense',
Document::class => $entity = 'document',
ClientContact::class => $entity = 'contact',
PurchaseOrder::class => $entity = 'purchase_order',
default => $entity = 'invoice',
};
$clean_row = [];
foreach (array_values($this->input['report_keys']) as $key => $value) {
$report_keys = explode(".", $value);
$column_key = $value;
if($value == 'type_id' || $value == 'item.type_id')
$column_key = 'type';
if($value == 'tax_id' || $value == 'item.tax_id')
$column_key = 'tax_category';
$clean_row[$key]['entity'] = $report_keys[0];
$clean_row[$key]['id'] = $report_keys[1] ?? $report_keys[0];
$clean_row[$key]['hashed_id'] = $report_keys[0] == $entity ? null : $resource->{$report_keys[0]}->hashed_id ?? null;
$clean_row[$key]['value'] = isset($row[$column_key]) ? $row[$column_key] : $row[$report_keys[1]];
$clean_row[$key]['identifier'] = $value;
$clean_row[$key]['display_value'] = isset($row[$column_key]) ? $row[$column_key] : $row[$report_keys[1]];
}
return $clean_row;
}
} }

View File

@ -11,14 +11,16 @@
namespace App\Export\CSV; namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Models\Client;
use App\Models\Company;
use App\Transformers\ClientContactTransformer;
use App\Transformers\ClientTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Support\Facades\App; use App\Utils\Number;
use App\Models\Client;
use League\Csv\Writer; use League\Csv\Writer;
use App\Models\Company;
use App\Libraries\MultiDB;
use Illuminate\Support\Facades\App;
use App\Transformers\ClientTransformer;
use Illuminate\Database\Eloquent\Builder;
use App\Transformers\ClientContactTransformer;
class ClientExport extends BaseExport class ClientExport extends BaseExport
{ {
@ -69,17 +71,11 @@ class ClientExport extends BaseExport
'contact_custom_value3' => 'contact.custom_value3', 'contact_custom_value3' => 'contact.custom_value3',
'contact_custom_value4' => 'contact.custom_value4', 'contact_custom_value4' => 'contact.custom_value4',
'email' => 'contact.email', 'email' => 'contact.email',
'status' => 'status' 'status' => 'status',
]; 'payment_balance' => 'client.payment_balance',
'credit_balance' => 'client.credit_balance',
'classification' => 'client.classification',
private array $decorate_keys = [
'client.country_id',
'client.shipping_country_id',
'client.currency',
'client.industry',
];
public array $forced_keys = [
]; ];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
@ -90,7 +86,28 @@ class ClientExport extends BaseExport
$this->contact_transformer = new ClientContactTransformer(); $this->contact_transformer = new ClientContactTransformer();
} }
public function run() public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($client) {
$row = $this->buildRow($client);
return $this->processMetaData($row, $client);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
@ -98,15 +115,9 @@ class ClientExport extends BaseExport
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->client_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Client::query()->with('contacts') $query = Client::query()->with('contacts')
->withTrashed() ->withTrashed()
@ -115,6 +126,20 @@ class ClientExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($client) { ->each(function ($client) {
$this->csv->insertOne($this->buildRow($client)); $this->csv->insertOne($this->buildRow($client));
@ -152,6 +177,30 @@ class ClientExport extends BaseExport
return $this->decorateAdvancedFields($client, $entity); return $this->decorateAdvancedFields($client, $entity);
} }
public function processMetaData(array $row, $resource): array
{
$clean_row = [];
foreach (array_values($this->input['report_keys']) as $key => $value) {
$report_keys = explode(".", $value);
$column_key = $value;
$clean_row[$key]['entity'] = $report_keys[0];
$clean_row[$key]['id'] = $report_keys[1] ?? $report_keys[0];
$clean_row[$key]['hashed_id'] = $report_keys[0] == 'client' ? null : $resource->{$report_keys[0]}->hashed_id ?? null;
$clean_row[$key]['value'] = $row[$column_key];
$clean_row[$key]['identifier'] = $key;
if(in_array($clean_row[$key]['id'], ['paid_to_date', 'balance', 'credit_balance','payment_balance']))
$clean_row[$key]['display_value'] = Number::formatMoney($row[$column_key], $resource);
else
$clean_row[$key]['display_value'] = $row[$column_key];
}
return $clean_row;
}
private function decorateAdvancedFields(Client $client, array $entity) :array private function decorateAdvancedFields(Client $client, array $entity) :array
{ {
if (in_array('client.user', $this->input['report_keys'])) { if (in_array('client.user', $this->input['report_keys'])) {
@ -178,6 +227,10 @@ class ClientExport extends BaseExport
$entity['industry_id'] = $client->industry ? ctrans("texts.industry_{$client->industry->name}") : ''; $entity['industry_id'] = $client->industry ? ctrans("texts.industry_{$client->industry->name}") : '';
} }
if (in_array('client.classification', $this->input['report_keys']) && isset($client->classification)) {
$entity['client.classification'] = ctrans("texts.{$client->classification}") ?? '';
}
return $entity; return $entity;
} }

View File

@ -18,6 +18,7 @@ use App\Models\Company;
use App\Transformers\ClientContactTransformer; use App\Transformers\ClientContactTransformer;
use App\Transformers\ClientTransformer; use App\Transformers\ClientTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -32,54 +33,6 @@ class ContactExport extends BaseExport
public string $date_key = 'created_at'; public string $date_key = 'created_at';
public array $entity_keys = [
'address1' => 'client.address1',
'address2' => 'client.address2',
'balance' => 'client.balance',
'city' => 'client.city',
'country' => 'client.country_id',
'credit_balance' => 'client.credit_balance',
'custom_value1' => 'client.custom_value1',
'custom_value2' => 'client.custom_value2',
'custom_value3' => 'client.custom_value3',
'custom_value4' => 'client.custom_value4',
'id_number' => 'client.id_number',
'industry' => 'client.industry_id',
'last_login' => 'client.last_login',
'name' => 'client.name',
'number' => 'client.number',
'paid_to_date' => 'client.paid_to_date',
'client_phone' => 'client.phone',
'postal_code' => 'client.postal_code',
'private_notes' => 'client.private_notes',
'public_notes' => 'client.public_notes',
'shipping_address1' => 'client.shipping_address1',
'shipping_address2' => 'client.shipping_address2',
'shipping_city' => 'client.shipping_city',
'shipping_country' => 'client.shipping_country_id',
'shipping_postal_code' => 'client.shipping_postal_code',
'shipping_state' => 'client.shipping_state',
'state' => 'client.state',
'vat_number' => 'client.vat_number',
'website' => 'client.website',
'currency' => 'client.currency',
'first_name' => 'contact.first_name',
'last_name' => 'contact.last_name',
'contact_phone' => 'contact.phone',
'contact_custom_value1' => 'contact.custom_value1',
'contact_custom_value2' => 'contact.custom_value2',
'contact_custom_value3' => 'contact.custom_value3',
'contact_custom_value4' => 'contact.custom_value4',
'email' => 'contact.email',
];
private array $decorate_keys = [
'client.country_id',
'client.shipping_country_id',
'client.currency',
'client.industry',
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -88,29 +41,39 @@ class ContactExport extends BaseExport
$this->contact_transformer = new ClientContactTransformer(); $this->contact_transformer = new ClientContactTransformer();
} }
public function run() private function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->client_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = ClientContact::query() $query = ClientContact::query()
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()->each(function ($contact) { $query->cursor()->each(function ($contact) {
$this->csv->insertOne($this->buildRow($contact)); $this->csv->insertOne($this->buildRow($contact));
}); });
@ -118,6 +81,27 @@ class ContactExport extends BaseExport
return $this->csv->toString(); return $this->csv->toString();
} }
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($contact) {
$row = $this->buildRow($contact);
return $this->processMetaData($row, $contact);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function buildRow(ClientContact $contact) :array private function buildRow(ClientContact $contact) :array
{ {
$transformed_contact = false; $transformed_contact = false;
@ -129,14 +113,13 @@ class ContactExport extends BaseExport
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$parts = explode('.', $key); $parts = explode('.', $key);
$keyval = array_search($key, $this->entity_keys);
if ($parts[0] == 'client' && array_key_exists($parts[1], $transformed_client)) { if ($parts[0] == 'client' && array_key_exists($parts[1], $transformed_client)) {
$entity[$keyval] = $transformed_client[$parts[1]]; $entity[$key] = $transformed_client[$parts[1]];
} elseif ($parts[0] == 'contact' && array_key_exists($parts[1], $transformed_contact)) { } elseif ($parts[0] == 'contact' && array_key_exists($parts[1], $transformed_contact)) {
$entity[$keyval] = $transformed_contact[$parts[1]]; $entity[$key] = $transformed_contact[$parts[1]];
} else { } else {
$entity[$keyval] = ''; $entity[$key] = '';
} }
} }

View File

@ -19,7 +19,7 @@ use App\Models\Company;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use App\Transformers\CreditTransformer; use App\Transformers\CreditTransformer;
use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
class CreditExport extends BaseExport class CreditExport extends BaseExport
{ {
@ -30,51 +30,6 @@ class CreditExport extends BaseExport
public Writer $csv; public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'client' => 'client_id',
'country' => 'country_id',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'currency' => 'currency',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'invoice' => 'invoice_id',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
];
private array $decorate_keys = [
'country',
'client',
'invoice',
'currency',
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -86,35 +41,37 @@ class CreditExport extends BaseExport
{ {
$query = $this->init(); $query = $this->init();
$header = $this->buildHeader(); $headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor() $report = $query->cursor()
->map(function ($credit) { ->map(function ($credit) {
$row = $this->buildRow($credit); $row = $this->buildRow($credit);
return $this->processMetaData($row, $credit); return $this->processMetaData($row, $credit);
})->toArray(); })->toArray();
return array_merge([$header], $report); return array_merge(['columns' => $header], $report);
} }
private function processMetaData(array $row, Credit $credit): array public function processMetaData(array $row, $resource): array
{ {
$clean_row = []; $clean_row = [];
foreach (array_values($this->input['report_keys']) as $key => $value) {
foreach ($this->input['report_keys'] as $key => $value) {
$report_keys = explode(".", $value); $report_keys = explode(".", $value);
$column_key = str_replace("credit.", "", $value); $column_key = $value;
$column_key = array_search($column_key, $this->entity_keys);
$clean_row[$key]['entity'] = $report_keys[0]; $clean_row[$key]['entity'] = $report_keys[0];
$clean_row[$key]['id'] = $report_keys[1] ?? $report_keys[0]; $clean_row[$key]['id'] = $report_keys[1] ?? $report_keys[0];
$clean_row[$key]['hashed_id'] = $report_keys[0] == 'credit' ? null : $credit->{$report_keys[0]}->hashed_id ?? null; $clean_row[$key]['hashed_id'] = $report_keys[0] == 'credit' ? null : $resource->{$report_keys[0]}->hashed_id ?? null;
$clean_row[$key]['value'] = $row[$column_key]; $clean_row[$key]['value'] = $row[$column_key];
$clean_row[$key]['identifier'] = $value;
if(in_array($clean_row[$key]['id'], ['amount', 'balance', 'partial', 'refunded', 'applied','unit_cost','cost','price'])) if(in_array($clean_row[$key]['id'], ['paid_to_date','total_taxes','amount', 'balance', 'partial', 'refunded', 'applied','unit_cost','cost','price']))
$clean_row[$key]['display_value'] = Number::formatMoney($row[$column_key], $credit->client); $clean_row[$key]['display_value'] = Number::formatMoney($row[$column_key], $resource->client);
else else
$clean_row[$key]['display_value'] = $row[$column_key]; $clean_row[$key]['display_value'] = $row[$column_key];
@ -133,20 +90,13 @@ class CreditExport extends BaseExport
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->credit_report_keys);
// $this->input['report_keys'] = collect(array_values($this->entity_keys))->map(function ($value){
// // if(in_array($value,['client_id','country_id']))
// // return $value;
// // else
// return 'credit.'.$value;
// })->toArray();
} }
$query = Credit::query() $query = Credit::query()
->withTrashed() ->withTrashed()
->with('client')->where('company_id', $this->company->id) ->with('client')
->where('company_id', $this->company->id)
->where('is_deleted', 0); ->where('is_deleted', 0);
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
@ -162,11 +112,9 @@ class CreditExport extends BaseExport
//insert the header //insert the header
$this->csv->insertOne($this->buildHeader()); $this->csv->insertOne($this->buildHeader());
// nlog($this->input['report_keys']);
$query->cursor() $query->cursor()
->each(function ($credit) { ->each(function ($credit) {
// nlog($this->buildRow($credit));
$this->csv->insertOne($this->buildRow($credit)); $this->csv->insertOne($this->buildRow($credit));
}); });
@ -180,22 +128,22 @@ class CreditExport extends BaseExport
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
$keyval = $key;
if(!$keyval) $credit_key = str_replace("credit.", "", $key);
$keyval = array_search(str_replace("credit.", "", $key), $this->entity_keys) ?? $key; $searched_credit_key = array_search(str_replace("credit.", "", $key), $this->credit_report_keys) ?? $key;
if(!$keyval)
$keyval = $key;
if (array_key_exists($key, $transformed_credit)) { if (isset($transformed_credit[$credit_key])) {
$entity[$keyval] = $transformed_credit[$key]; $entity[$keyval] = $transformed_credit[$credit_key];
} elseif (array_key_exists($keyval, $transformed_credit)) { } elseif (isset($transformed_credit[$keyval])) {
$entity[$keyval] = $transformed_credit[$keyval]; $entity[$keyval] = $transformed_credit[$keyval];
} elseif(isset($transformed_credit[$searched_credit_key])){
$entity[$keyval] = $transformed_credit[$searched_credit_key];
} }
else { else {
$entity[$keyval] = $this->resolveKey($keyval, $credit, $this->credit_transformer); $entity[$keyval] = $this->resolveKey($keyval, $credit, $this->credit_transformer);
} }
} }
return $this->decorateAdvancedFields($credit, $entity); return $this->decorateAdvancedFields($credit, $entity);

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Document; use App\Models\Document;
use App\Transformers\DocumentTransformer; use App\Transformers\DocumentTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -30,16 +31,11 @@ class DocumentExport extends BaseExport
public array $entity_keys = [ public array $entity_keys = [
'record_type' => 'record_type', 'record_type' => 'record_type',
// 'record_name' => 'record_name',
'name' => 'name', 'name' => 'name',
'type' => 'type', 'type' => 'type',
'created_at' => 'created_at', 'created_at' => 'created_at',
]; ];
private array $decorate_keys = [
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -47,28 +43,56 @@ class DocumentExport extends BaseExport
$this->entity_transformer = new DocumentTransformer(); $this->entity_transformer = new DocumentTransformer();
} }
public function run() public function returnJson()
{ {
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($document) {
$row = $this->buildRow($document);
return $this->processMetaData($row, $document);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function init(): Builder
{
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->entity_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Document::query()->where('company_id', $this->company->id); $query = Document::query()->where('company_id', $this->company->id);
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($entity) { ->each(function ($entity) {
$this->csv->insertOne($this->buildRow($entity)); $this->csv->insertOne($this->buildRow($entity));

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Expense; use App\Models\Expense;
use App\Transformers\ExpenseTransformer; use App\Transformers\ExpenseTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -28,51 +29,6 @@ class ExpenseExport extends BaseExport
public Writer $csv; public Writer $csv;
public array $entity_keys = [
'amount' => 'expense.amount',
'category' => 'expense.category',
'client' => 'expense.client_id',
'custom_value1' => 'expense.custom_value1',
'custom_value2' => 'expense.custom_value2',
'custom_value3' => 'expense.custom_value3',
'custom_value4' => 'expense.custom_value4',
'currency' => 'expense.currency_id',
'date' => 'expense.date',
'exchange_rate' => 'expense.exchange_rate',
'converted_amount' => 'expense.foreign_amount',
'invoice_currency_id' => 'expense.invoice_currency_id',
'payment_date' => 'expense.payment_date',
'number' => 'expense.number',
'payment_type_id' => 'expense.payment_type_id',
'private_notes' => 'expense.private_notes',
'project' => 'expense.project_id',
'public_notes' => 'expense.public_notes',
'tax_amount1' => 'expense.tax_amount1',
'tax_amount2' => 'expense.tax_amount2',
'tax_amount3' => 'expense.tax_amount3',
'tax_name1' => 'expense.tax_name1',
'tax_name2' => 'expense.tax_name2',
'tax_name3' => 'expense.tax_name3',
'tax_rate1' => 'expense.tax_rate1',
'tax_rate2' => 'expense.tax_rate2',
'tax_rate3' => 'expense.tax_rate3',
'transaction_reference' => 'expense.transaction_reference',
'vendor' => 'expense.vendor_id',
'invoice' => 'expense.invoice_id',
'user' => 'expense.user',
'assigned_user' => 'expense.assigned_user',
];
private array $decorate_keys = [
'client',
'currency',
'invoice',
'category',
'vendor',
'project',
'payment_type_id',
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -80,24 +36,39 @@ class ExpenseExport extends BaseExport
$this->expense_transformer = new ExpenseTransformer(); $this->expense_transformer = new ExpenseTransformer();
} }
public function run()
public function returnJson()
{ {
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function init(): Builder
{
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->expense_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Expense::query() $query = Expense::query()
->with('client') ->with('client')
->withTrashed() ->withTrashed()
@ -106,6 +77,20 @@ class ExpenseExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($expense) { ->each(function ($expense) {
$this->csv->insertOne($this->buildRow($expense)); $this->csv->insertOne($this->buildRow($expense));
@ -122,7 +107,6 @@ class ExpenseExport extends BaseExport
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$parts = explode('.', $key); $parts = explode('.', $key);
$keyval = array_search($key, $this->entity_keys);
if (is_array($parts) && $parts[0] == 'expense' && array_key_exists($parts[1], $transformed_expense)) { if (is_array($parts) && $parts[0] == 'expense' && array_key_exists($parts[1], $transformed_expense)) {
$entity[$key] = $transformed_expense[$parts[1]]; $entity[$key] = $transformed_expense[$parts[1]];
@ -175,6 +159,10 @@ class ExpenseExport extends BaseExport
$entity['expense.assigned_user'] = $expense->assigned_user ? $expense->assigned_user->present()->name() : ''; $entity['expense.assigned_user'] = $expense->assigned_user ? $expense->assigned_user->present()->name() : '';
} }
if (in_array('expense.category_id', $this->input['report_keys'])) {
$entity['expense.category_id'] = $expense->category ? $expense->category->name : '';
}
return $entity; return $entity;
} }
} }

View File

@ -20,6 +20,7 @@ use App\Libraries\MultiDB;
use App\Export\CSV\BaseExport; use App\Export\CSV\BaseExport;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use App\Transformers\InvoiceTransformer; use App\Transformers\InvoiceTransformer;
use Illuminate\Database\Eloquent\Builder;
class InvoiceExport extends BaseExport class InvoiceExport extends BaseExport
{ {
@ -29,56 +30,6 @@ class InvoiceExport extends BaseExport
public Writer $csv; public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'client' => 'client_id',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency_id' => 'currency_id',
'payment_number' => 'payment_number',
'payment_date' => 'payment_date',
'payment_amount' => 'payment_amount',
'method' => 'method',
];
private array $decorate_keys = [
'country',
'client',
'currency_id',
'status',
'vendor',
'project',
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -86,24 +37,19 @@ class InvoiceExport extends BaseExport
$this->invoice_transformer = new InvoiceTransformer(); $this->invoice_transformer = new InvoiceTransformer();
} }
public function run() public function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->invoice_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Invoice::query() $query = Invoice::query()
->withTrashed() ->withTrashed()
->with('client') ->with('client')
@ -112,10 +58,43 @@ class InvoiceExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
if(isset($this->input['status'])){ if(isset($this->input['status'])) {
$query = $this->addInvoiceStatusFilter($query, $this->input['status']); $query = $this->addInvoiceStatusFilter($query, $this->input['status']);
} }
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($invoice) { ->each(function ($invoice) {
$this->csv->insertOne($this->buildRow($invoice)); $this->csv->insertOne($this->buildRow($invoice));
@ -131,24 +110,15 @@ class InvoiceExport extends BaseExport
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval) { $parts = explode('.', $key);
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
if (is_array($parts) && $parts[0] == 'invoice' && array_key_exists($parts[1], $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$parts[1]];
} else {
$entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
} }
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_invoice)) {
$entity[$keyval] = $transformed_invoice[$key];
} elseif (array_key_exists($keyval, $transformed_invoice)) {
$entity[$keyval] = $transformed_invoice[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $invoice, $this->invoice_transformer);
}
} }
return $this->decorateAdvancedFields($invoice, $entity); return $this->decorateAdvancedFields($invoice, $entity);
@ -156,31 +126,22 @@ class InvoiceExport extends BaseExport
private function decorateAdvancedFields(Invoice $invoice, array $entity) :array private function decorateAdvancedFields(Invoice $invoice, array $entity) :array
{ {
if (in_array('country_id', $this->input['report_keys'])) {
$entity['country'] = $invoice->client->country ? ctrans("texts.country_{$invoice->client->country->name}") : '';
}
if (in_array('currency_id', $this->input['report_keys'])) {
$entity['currency_id'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
}
if (in_array('client_id', $this->input['report_keys'])) {
$entity['client'] = $invoice->client->present()->name();
}
if (in_array('status_id', $this->input['report_keys'])) {
$entity['status'] = $invoice->stringStatus($invoice->status_id);
}
// $payment_exists = $invoice->payments()->exists(); if (in_array('invoice.country_id', $this->input['report_keys'])) {
$entity['invoice.country_id'] = $invoice->client->country ? ctrans("texts.country_{$invoice->client->country->name}") : '';
}
// $entity['payment_number'] = $payment_exists ? $invoice->payments()->pluck('number')->implode(',') : ''; if (in_array('invoice.currency_id', $this->input['report_keys'])) {
$entity['invoice.currency_id'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
}
// $entity['payment_date'] = $payment_exists ? $invoice->payments()->pluck('date')->implode(',') : ''; if (in_array('invoice.client_id', $this->input['report_keys'])) {
$entity['invoice.client_id'] = $invoice->client->present()->name();
}
// $entity['payment_amount'] = $payment_exists ? Number::formatMoney($invoice->payments()->sum('paymentables.amount'), $invoice->company) : ctrans('texts.unpaid'); if (in_array('invoice.status', $this->input['report_keys'])) {
$entity['invoice.status'] = $invoice->stringStatus($invoice->status_id);
// $entity['method'] = $payment_exists ? $invoice->payments()->first()->translatedType() : ""; }
return $entity; return $entity;
} }

View File

@ -12,11 +12,11 @@
namespace App\Export\CSV; namespace App\Export\CSV;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Client;
use App\Models\Company; use App\Models\Company;
use App\Models\Invoice; use App\Models\Invoice;
use App\Transformers\InvoiceTransformer; use App\Transformers\InvoiceTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -31,64 +31,9 @@ class InvoiceItemExport extends BaseExport
private bool $force_keys = false; private bool $force_keys = false;
public array $entity_keys = [ private array $storage_array = [];
'amount' => 'amount',
'balance' => 'balance', private array $storage_item_array = [];
'client' => 'client_id',
'client_number' => 'client.number',
'client_id_number' => 'client.id_number',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency' => 'currency_id',
'quantity' => 'item.quantity',
'cost' => 'item.cost',
'product_key' => 'item.product_key',
'buy_price' => 'item.product_cost',
'notes' => 'item.notes',
'discount' => 'item.discount',
'is_amount_discount' => 'item.is_amount_discount',
'tax_rate1' => 'item.tax_rate1',
'tax_rate2' => 'item.tax_rate2',
'tax_rate3' => 'item.tax_rate3',
'tax_name1' => 'item.tax_name1',
'tax_name2' => 'item.tax_name2',
'tax_name3' => 'item.tax_name3',
'line_total' => 'item.line_total',
'gross_line_total' => 'item.gross_line_total',
'invoice1' => 'item.custom_value1',
'invoice2' => 'item.custom_value2',
'invoice3' => 'item.custom_value3',
'invoice4' => 'item.custom_value4',
'tax_category' => 'item.tax_id',
'type' => 'item.type_id',
];
private array $decorate_keys = [ private array $decorate_keys = [
'client', 'client',
@ -103,37 +48,77 @@ class InvoiceItemExport extends BaseExport
$this->invoice_transformer = new InvoiceTransformer(); $this->invoice_transformer = new InvoiceTransformer();
} }
public function run() public function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->force_keys = true; $this->force_keys = true;
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->mergeItemsKeys('invoice_report_keys'));
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Invoice::query() $query = Invoice::query()
->withTrashed() ->withTrashed()
->with('client')->where('company_id', $this->company->id) ->with('client')
->where('company_id', $this->company->id)
->where('is_deleted', 0); ->where('is_deleted', 0);
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$query->cursor()
->each(function ($resource) {
$this->iterateItems($resource);
foreach($this->storage_array as $row) {
$this->storage_item_array[] = $this->processItemMetaData($row, $resource);
}
$this->storage_array = [];
});
return array_merge(['columns' => $header], $this->storage_item_array);
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($invoice) { ->each(function ($invoice) {
$this->iterateItems($invoice); $this->iterateItems($invoice);
}); });
$this->csv->insertAll($this->storage_array);
return $this->csv->toString(); return $this->csv->toString();
} }
@ -146,46 +131,32 @@ class InvoiceItemExport extends BaseExport
foreach ($invoice->line_items as $item) { foreach ($invoice->line_items as $item) {
$item_array = []; $item_array = [];
foreach (array_values($this->input['report_keys']) as $key) { //items iterator produces item array foreach (array_values(array_intersect($this->input['report_keys'], $this->item_report_keys)) as $key) { //items iterator produces item array
if (str_contains($key, "item.")) { if (str_contains($key, "item.")) {
$key = str_replace("item.", "", $key); $key = str_replace("item.", "", $key);
$keyval = $key;
$keyval = str_replace("custom_value", "invoice", $key);
if($key == 'type_id') if($key == 'type_id')
$keyval = 'type'; $key = 'type';
if($key == 'tax_id') if($key == 'tax_id')
$keyval = 'tax_category'; $key = 'tax_category';
if (property_exists($item, $key)) { if (property_exists($item, $key)) {
$item_array[$keyval] = $item->{$key}; $item_array[$key] = $item->{$key};
} else { }
$item_array[$keyval] = ''; else {
$item_array[$key] = '';
} }
} }
} }
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) { //create an array of report keys only
$keyval = array_search($key, $this->entity_keys);
if (array_key_exists($key, $transformed_items)) {
$entity[$keyval] = $transformed_items[$key];
} else {
$entity[$keyval] = "";
}
}
$transformed_items = array_merge($transformed_invoice, $item_array); $transformed_items = array_merge($transformed_invoice, $item_array);
$entity = $this->decorateAdvancedFields($invoice, $transformed_items); $entity = $this->decorateAdvancedFields($invoice, $transformed_items);
$this->csv->insertOne($entity); $this->storage_array[] = $entity;
} }
} }
@ -196,23 +167,19 @@ class InvoiceItemExport extends BaseExport
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
$parts = explode('.', $key);
if(!$keyval) { if(is_array($parts) && $parts[0] == 'item')
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key; continue;
}
if(!$keyval) { if (is_array($parts) && $parts[0] == 'invoice' && array_key_exists($parts[1], $transformed_invoice)) {
$keyval = $key; $entity[$key] = $transformed_invoice[$parts[1]];
} }else if (array_key_exists($key, $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$key];
if (array_key_exists($key, $transformed_invoice)) { }
$entity[$keyval] = $transformed_invoice[$key]; else {
} elseif (array_key_exists($keyval, $transformed_invoice)) { $entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
$entity[$keyval] = $transformed_invoice[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $invoice, $this->invoice_transformer);
} }
} }
@ -233,13 +200,7 @@ class InvoiceItemExport extends BaseExport
$entity['tax_category'] = $invoice->taxTypeString($entity['tax_category']); $entity['tax_category'] = $invoice->taxTypeString($entity['tax_category']);
} }
if($this->force_keys) {
$entity['client'] = $invoice->client->present()->name();
$entity['client_id_number'] = $invoice->client->id_number;
$entity['client_number'] = $invoice->client->number;
$entity['status'] = $invoice->stringStatus($invoice->status_id);
}
return $entity; return $entity;
} }
} }

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Payment; use App\Models\Payment;
use App\Transformers\PaymentTransformer; use App\Transformers\PaymentTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -27,40 +28,6 @@ class PaymentExport extends BaseExport
public Writer $csv; public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'applied' => 'applied',
'client' => 'client_id',
'currency' => 'currency_id',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'exchange_currency' => 'exchange_currency_id',
'gateway' => 'gateway_type_id',
'number' => 'number',
'private_notes' => 'private_notes',
'project' => 'project_id',
'refunded' => 'refunded',
'status' => 'status_id',
'transaction_reference' => 'transaction_reference',
'type' => 'type_id',
'vendor' => 'vendor_id',
'invoices' => 'invoices',
];
private array $decorate_keys = [
'vendor',
'status',
'project',
'client',
'currency',
'exchange_currency',
'type',
'invoices',
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -68,24 +35,19 @@ class PaymentExport extends BaseExport
$this->entity_transformer = new PaymentTransformer(); $this->entity_transformer = new PaymentTransformer();
} }
public function run() private function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->payment_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Payment::query() $query = Payment::query()
->withTrashed() ->withTrashed()
->where('company_id', $this->company->id) ->where('company_id', $this->company->id)
@ -93,6 +55,39 @@ class PaymentExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) {
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($entity) { ->each(function ($entity) {
$this->csv->insertOne($this->buildRow($entity)); $this->csv->insertOne($this->buildRow($entity));
@ -108,24 +103,17 @@ class PaymentExport extends BaseExport
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
$parts = explode('.', $key);
if(!$keyval) { if (is_array($parts) && $parts[0] == 'payment' && array_key_exists($parts[1], $transformed_entity)) {
$keyval = array_search(str_replace("payment.", "", $key), $this->entity_keys) ?? $key; $entity[$key] = $transformed_entity[$parts[1]];
} elseif (array_key_exists($key, $transformed_entity)) {
$entity[$key] = $transformed_entity[$key];
} else {
$entity[$key] = $this->resolveKey($key, $payment, $this->entity_transformer);
} }
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];
} elseif (array_key_exists($keyval, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $payment, $this->entity_transformer);
}
} }
return $this->decorateAdvancedFields($payment, $entity); return $this->decorateAdvancedFields($payment, $entity);

View File

@ -13,10 +13,10 @@ namespace App\Export\CSV;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Company; use App\Models\Company;
use App\Models\Document;
use App\Models\Product; use App\Models\Product;
use App\Transformers\ProductTransformer; use App\Transformers\ProductTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -28,31 +28,6 @@ class ProductExport extends BaseExport
public Writer $csv; public Writer $csv;
public array $entity_keys = [
'project' => 'project_id',
'vendor' => 'vendor_id',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'product_key' => 'product_key',
'notes' => 'notes',
'cost' => 'cost',
'price' => 'price',
'quantity' => 'quantity',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
];
private array $decorate_keys = [
'vendor',
'project',
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -60,24 +35,38 @@ class ProductExport extends BaseExport
$this->entity_transformer = new ProductTransformer(); $this->entity_transformer = new ProductTransformer();
} }
public function run() public function returnJson()
{ {
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function init(): Builder
{
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->product_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Product::query() $query = Product::query()
->withTrashed() ->withTrashed()
->where('company_id', $this->company->id) ->where('company_id', $this->company->id)
@ -85,6 +74,21 @@ class ProductExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($entity) { ->each(function ($entity) {
$this->csv->insertOne($this->buildRow($entity)); $this->csv->insertOne($this->buildRow($entity));
@ -100,7 +104,7 @@ class ProductExport extends BaseExport
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys); $keyval = array_search($key, $this->product_report_keys);
if (array_key_exists($key, $transformed_entity)) { if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key]; $entity[$keyval] = $transformed_entity[$key];

View File

@ -11,14 +11,15 @@
namespace App\Export\CSV; namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\PurchaseOrder;
use App\Transformers\PurchaseOrderTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Number; use App\Utils\Number;
use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
use App\Models\Company;
use App\Libraries\MultiDB;
use App\Models\PurchaseOrder;
use Illuminate\Support\Facades\App;
use App\Transformers\PurchaseOrderTransformer;
use Illuminate\Database\Eloquent\Builder;
class PurchaseOrderExport extends BaseExport class PurchaseOrderExport extends BaseExport
{ {
@ -81,24 +82,19 @@ class PurchaseOrderExport extends BaseExport
$this->purchase_order_transformer = new PurchaseOrderTransformer(); $this->purchase_order_transformer = new PurchaseOrderTransformer();
} }
public function run()
public function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->purchase_order_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = PurchaseOrder::query() $query = PurchaseOrder::query()
->withTrashed() ->withTrashed()
->with('vendor') ->with('vendor')
@ -107,9 +103,39 @@ class PurchaseOrderExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
// if(isset($this->input['status'])) { return $query;
// $query = $this->addPurchaseOrderStatusFilter($query, $this->input['status']);
// } }
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($purchase_order) { ->each(function ($purchase_order) {
@ -126,23 +152,16 @@ class PurchaseOrderExport extends BaseExport
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval) { $parts = explode('.', $key);
$keyval = array_search(str_replace("purchase_order.", "", $key), $this->entity_keys) ?? $key;
}
if(!$keyval) { if (is_array($parts) && $parts[0] == 'purchase_order' && array_key_exists($parts[1], $transformed_purchase_order)) {
$keyval = $key; $entity[$key] = $transformed_purchase_order[$parts[1]];
}
if (array_key_exists($key, $transformed_purchase_order)) {
$entity[$keyval] = $transformed_purchase_order[$key];
} elseif (array_key_exists($keyval, $transformed_purchase_order)) {
$entity[$keyval] = $transformed_purchase_order[$keyval];
} else { } else {
$entity[$keyval] = $this->resolveKey($keyval, $purchase_order, $this->purchase_order_transformer); $entity[$key] = $this->resolveKey($key, $purchase_order, $this->purchase_order_transformer);
} }
} }
return $this->decorateAdvancedFields($purchase_order, $entity); return $this->decorateAdvancedFields($purchase_order, $entity);

View File

@ -11,13 +11,14 @@
namespace App\Export\CSV; namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\PurchaseOrder;
use App\Transformers\PurchaseOrderTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
use App\Models\Company;
use App\Libraries\MultiDB;
use App\Models\PurchaseOrder;
use Illuminate\Support\Facades\App;
use Illuminate\Database\Eloquent\Builder;
use App\Transformers\PurchaseOrderTransformer;
class PurchaseOrderItemExport extends BaseExport class PurchaseOrderItemExport extends BaseExport
{ {
@ -30,70 +31,9 @@ class PurchaseOrderItemExport extends BaseExport
private bool $force_keys = false; private bool $force_keys = false;
public array $entity_keys = [ private array $storage_array = [];
'amount' => 'amount',
'balance' => 'balance',
'vendor' => 'vendor_id',
'vendor_number' => 'vendor.number',
'vendor_id_number' => 'vendor.id_number',
// 'custom_surcharge1' => 'custom_surcharge1',
// 'custom_surcharge2' => 'custom_surcharge2',
// 'custom_surcharge3' => 'custom_surcharge3',
// 'custom_surcharge4' => 'custom_surcharge4',
// 'custom_value1' => 'custom_value1',
// 'custom_value2' => 'custom_value2',
// 'custom_value3' => 'custom_value3',
// 'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency' => 'currency_id',
'quantity' => 'item.quantity',
'cost' => 'item.cost',
'product_key' => 'item.product_key',
'buy_price' => 'item.product_cost',
'notes' => 'item.notes',
'discount' => 'item.discount',
'is_amount_discount' => 'item.is_amount_discount',
'tax_rate1' => 'item.tax_rate1',
'tax_rate2' => 'item.tax_rate2',
'tax_rate3' => 'item.tax_rate3',
'tax_name1' => 'item.tax_name1',
'tax_name2' => 'item.tax_name2',
'tax_name3' => 'item.tax_name3',
'line_total' => 'item.line_total',
'gross_line_total' => 'item.gross_line_total',
'purchase_order1' => 'item.custom_value1',
'purchase_order2' => 'item.custom_value2',
'purchase_order3' => 'item.custom_value3',
'purchase_order4' => 'item.custom_value4',
'tax_category' => 'item.tax_id',
'type' => 'item.type_id',
];
private array $decorate_keys = [ private array $storage_item_array = [];
'client',
'currency_id',
'status'
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
@ -102,25 +42,19 @@ class PurchaseOrderItemExport extends BaseExport
$this->purchase_order_transformer = new PurchaseOrderTransformer(); $this->purchase_order_transformer = new PurchaseOrderTransformer();
} }
public function run() private function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->force_keys = true; $this->input['report_keys'] = array_values($this->mergeItemsKeys('purchase_order_report_keys'));
$this->input['report_keys'] = array_values($this->entity_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = PurchaseOrder::query() $query = PurchaseOrder::query()
->withTrashed() ->withTrashed()
->with('vendor')->where('company_id', $this->company->id) ->with('vendor')->where('company_id', $this->company->id)
@ -128,12 +62,54 @@ class PurchaseOrderItemExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$query->cursor()
->each(function ($resource) {
$this->iterateItems($resource);
foreach($this->storage_array as $row) {
$this->storage_item_array[] = $this->processItemMetaData($row, $resource);
}
$this->storage_array = [];
});
return array_merge(['columns' => $header], $this->storage_item_array);
}
public function run()
{
//load the CSV document from a string
$this->csv = Writer::createFromString();
$query = $this->init();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($purchase_order) { ->each(function ($purchase_order) {
$this->iterateItems($purchase_order); $this->iterateItems($purchase_order);
}); });
$this->csv->insertAll($this->storage_array);
return $this->csv->toString(); return $this->csv->toString();
} }
private function iterateItems(PurchaseOrder $purchase_order) private function iterateItems(PurchaseOrder $purchase_order)
@ -145,16 +121,12 @@ class PurchaseOrderItemExport extends BaseExport
foreach ($purchase_order->line_items as $item) { foreach ($purchase_order->line_items as $item) {
$item_array = []; $item_array = [];
foreach (array_values($this->input['report_keys']) as $key) { //items iterator produces item array foreach (array_values(array_intersect($this->input['report_keys'], $this->item_report_keys)) as $key) { //items iterator produces item array
if (str_contains($key, "item.")) { if (str_contains($key, "item.")) {
$key = str_replace("item.", "", $key); $key = str_replace("item.", "", $key);
$keyval = $key;
$keyval = str_replace("custom_value", "purchase_order", $key);
if($key == 'type_id') { if($key == 'type_id') {
$keyval = 'type'; $keyval = 'type';
} }
@ -164,29 +136,17 @@ class PurchaseOrderItemExport extends BaseExport
} }
if (property_exists($item, $key)) { if (property_exists($item, $key)) {
$item_array[$keyval] = $item->{$key}; $item_array[$key] = $item->{$key};
} else { } else {
$item_array[$keyval] = ''; $item_array[$key] = '';
} }
} }
} }
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) { //create an array of report keys only
$keyval = array_search($key, $this->entity_keys);
if (array_key_exists($key, $transformed_items)) {
$entity[$keyval] = $transformed_items[$key];
} else {
$entity[$keyval] = "";
}
}
$transformed_items = array_merge($transformed_purchase_order, $item_array); $transformed_items = array_merge($transformed_purchase_order, $item_array);
$entity = $this->decorateAdvancedFields($purchase_order, $transformed_items); $entity = $this->decorateAdvancedFields($purchase_order, $transformed_items);
$this->csv->insertOne($entity); $this->storage_array[] = $entity;
} }
} }
@ -197,22 +157,18 @@ class PurchaseOrderItemExport extends BaseExport
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys); $parts = explode('.', $key);
if(!$keyval) { if(is_array($parts) && $parts[0] == 'item') {
$keyval = array_search(str_replace("purchase_order.", "", $key), $this->entity_keys) ?? $key; continue;
} }
if(!$keyval) { if (is_array($parts) && $parts[0] == 'purchase_order' && array_key_exists($parts[1], $transformed_purchase_order)) {
$keyval = $key; $entity[$key] = $transformed_purchase_order[$parts[1]];
} } elseif (array_key_exists($key, $transformed_purchase_order)) {
$entity[$key] = $transformed_purchase_order[$key];
if (array_key_exists($key, $transformed_purchase_order)) {
$entity[$keyval] = $transformed_purchase_order[$key];
} elseif (array_key_exists($keyval, $transformed_purchase_order)) {
$entity[$keyval] = $transformed_purchase_order[$keyval];
} else { } else {
$entity[$keyval] = $this->resolveKey($keyval, $purchase_order, $this->purchase_order_transformer); $entity[$key] = $this->resolveKey($key, $purchase_order, $this->purchase_order_transformer);
} }
} }
@ -242,4 +198,5 @@ class PurchaseOrderItemExport extends BaseExport
return $entity; return $entity;
} }
} }

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Quote; use App\Models\Quote;
use App\Transformers\QuoteTransformer; use App\Transformers\QuoteTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -28,43 +29,6 @@ class QuoteExport extends BaseExport
public Writer $csv; public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'client' => 'client_id',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'valid_until' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency' => 'currency_id',
'invoice' => 'invoice_id',
];
private array $decorate_keys = [ private array $decorate_keys = [
'client', 'client',
'currency', 'currency',
@ -78,24 +42,20 @@ class QuoteExport extends BaseExport
$this->quote_transformer = new QuoteTransformer(); $this->quote_transformer = new QuoteTransformer();
} }
public function run() private function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->quote_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Quote::query() $query = Quote::query()
->withTrashed() ->withTrashed()
->with('client') ->with('client')
@ -104,6 +64,41 @@ class QuoteExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) {
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function run()
{
//load the CSV document from a string
$this->csv = Writer::createFromString();
$query = $this->init();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($quote) { ->each(function ($quote) {
$this->csv->insertOne($this->buildRow($quote)); $this->csv->insertOne($this->buildRow($quote));
@ -114,50 +109,42 @@ class QuoteExport extends BaseExport
private function buildRow(Quote $quote) :array private function buildRow(Quote $quote) :array
{ {
$transformed_entity = $this->quote_transformer->transform($quote); $transformed_invoice = $this->quote_transformer->transform($quote);
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval) { $parts = explode('.', $key);
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
if (is_array($parts) && $parts[0] == 'quote' && array_key_exists($parts[1], $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$parts[1]];
} else {
$entity[$key] = $this->resolveKey($key, $quote, $this->quote_transformer);
} }
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];
} elseif (array_key_exists($keyval, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $quote, $this->quote_transformer);
}
} }
return $this->decorateAdvancedFields($quote, $entity); return $this->decorateAdvancedFields($quote, $entity);
} }
private function decorateAdvancedFields(Quote $quote, array $entity) :array private function decorateAdvancedFields(Quote $quote, array $entity) :array
{ {
if (in_array('currency_id', $this->input['report_keys'])) { if (in_array('quote.currency_id', $this->input['report_keys'])) {
$entity['currency'] = $quote->client->currency()->code; $entity['quote.currency'] = $quote->client->currency()->code;
} }
if (in_array('client_id', $this->input['report_keys'])) { if (in_array('quote.client_id', $this->input['report_keys'])) {
$entity['client'] = $quote->client->present()->name(); $entity['quote.client'] = $quote->client->present()->name();
} }
if (in_array('status_id', $this->input['report_keys'])) { if (in_array('quote.status', $this->input['report_keys'])) {
$entity['status'] = $quote->stringStatus($quote->status_id); $entity['quote.status'] = $quote->stringStatus($quote->status_id);
} }
if (in_array('invoice_id', $this->input['report_keys'])) { if (in_array('quote.invoice_id', $this->input['report_keys'])) {
$entity['invoice'] = $quote->invoice ? $quote->invoice->number : ''; $entity['quote.invoice'] = $quote->invoice ? $quote->invoice->number : '';
} }
return $entity; return $entity;

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Quote; use App\Models\Quote;
use App\Transformers\QuoteTransformer; use App\Transformers\QuoteTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -28,63 +29,8 @@ class QuoteItemExport extends BaseExport
public Writer $csv; public Writer $csv;
public array $entity_keys = [ private array $storage_array = [];
'amount' => 'amount', private array $storage_item_array = [];
'balance' => 'balance',
'client' => 'client_id',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency' => 'currency_id',
'quantity' => 'item.quantity',
'cost' => 'item.cost',
'product_key' => 'item.product_key',
'buy_price' => 'item.product_cost',
'cost' => 'item.cost',
'notes' => 'item.notes',
'discount' => 'item.discount',
'is_amount_discount' => 'item.is_amount_discount',
'tax_rate1' => 'item.tax_rate1',
'tax_rate2' => 'item.tax_rate2',
'tax_rate3' => 'item.tax_rate3',
'tax_name1' => 'item.tax_name1',
'tax_name2' => 'item.tax_name2',
'tax_name3' => 'item.tax_name3',
'line_total' => 'item.line_total',
'gross_line_total' => 'item.gross_line_total',
'quote1' => 'item.custom_value1',
'quote2' => 'item.custom_value2',
'quote3' => 'item.custom_value3',
'quote4' => 'item.custom_value4',
'tax_category' => 'item.tax_id',
'type' => 'item.type_id',
];
private array $decorate_keys = [ private array $decorate_keys = [
'client', 'client',
@ -98,37 +44,78 @@ class QuoteItemExport extends BaseExport
$this->quote_transformer = new QuoteTransformer(); $this->quote_transformer = new QuoteTransformer();
} }
public function run() public function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->mergeItemsKeys('quote_report_keys'));
}
$query = Quote::query()
->withTrashed()
->with('client')->where('company_id', $this->company->id)
->where('is_deleted', 0);
$query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$query->cursor()
->each(function ($resource) {
$this->iterateItems($resource);
foreach($this->storage_array as $row) {
$this->storage_item_array[] = $this->processItemMetaData($row, $resource);
}
$this->storage_array = [];
});
return array_merge(['columns' => $header], $this->storage_item_array);
}
public function run()
{
//load the CSV document from a string //load the CSV document from a string
$this->csv = Writer::createFromString(); $this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { $query = $this->init();
$this->input['report_keys'] = array_values($this->entity_keys);
}
//insert the header //insert the header
$this->csv->insertOne($this->buildHeader()); $this->csv->insertOne($this->buildHeader());
$query = Quote::query()
->withTrashed()
->with('client')->where('company_id', $this->company->id)
->where('is_deleted', 0);
$query = $this->addDateRange($query);
$query->cursor() $query->cursor()
->each(function ($quote) { ->each(function ($quote) {
$this->iterateItems($quote); $this->iterateItems($quote);
}); });
$this->csv->insertAll($this->storage_array);
return $this->csv->toString(); return $this->csv->toString();
} }
private function iterateItems(Quote $quote) private function iterateItems(Quote $quote)
@ -137,51 +124,34 @@ class QuoteItemExport extends BaseExport
$transformed_items = []; $transformed_items = [];
$transformed_items = [];
foreach ($quote->line_items as $item) { foreach ($quote->line_items as $item) {
$item_array = []; $item_array = [];
foreach (array_values($this->input['report_keys']) as $key) { //items iterator produces item array foreach (array_values(array_intersect($this->input['report_keys'], $this->item_report_keys)) as $key) { //items iterator produces item array
if (str_contains($key, "item.")) { if (str_contains($key, "item.")) {
$key = str_replace("item.", "", $key); $key = str_replace("item.", "", $key);
$keyval = $key;
$keyval = str_replace("custom_value", "quote", $key);
if($key == 'type_id') if($key == 'type_id')
$keyval = 'type'; $key = 'type';
if($key == 'tax_id') if($key == 'tax_id')
$keyval = 'tax_category'; $key = 'tax_category';
if (property_exists($item, $key)) { if (property_exists($item, $key)) {
$item_array[$keyval] = $item->{$key}; $item_array[$key] = $item->{$key};
} else { }
$item_array[$keyval] = ''; else {
$item_array[$key] = '';
} }
} }
} }
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) { //create an array of report keys only
$keyval = array_search($key, $this->entity_keys);
if (array_key_exists($key, $transformed_items)) {
$entity[$keyval] = $transformed_items[$key];
} else {
$entity[$keyval] = "";
}
}
$transformed_items = array_merge($transformed_quote, $item_array); $transformed_items = array_merge($transformed_quote, $item_array);
$entity = $this->decorateAdvancedFields($quote, $transformed_items); $entity = $this->decorateAdvancedFields($quote, $transformed_items);
$this->csv->insertOne($entity); $this->storage_array[] = $entity;
} }
} }
@ -192,26 +162,23 @@ class QuoteItemExport extends BaseExport
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
$parts = explode('.', $key);
if(!$keyval) { if(is_array($parts) && $parts[0] == 'item') {
$keyval = array_search(str_replace("quote.", "", $key), $this->entity_keys) ?? $key; continue;
} }
if(!$keyval) { if (is_array($parts) && $parts[0] == 'quote' && array_key_exists($parts[1], $transformed_quote)) {
$keyval = $key; $entity[$key] = $transformed_quote[$parts[1]];
} } elseif (array_key_exists($key, $transformed_quote)) {
$entity[$key] = $transformed_quote[$key];
if (array_key_exists($key, $transformed_quote)) { } else {
$entity[$keyval] = $transformed_quote[$key]; $entity[$key] = $this->resolveKey($key, $quote, $this->quote_transformer);
} elseif (array_key_exists($keyval, $transformed_quote)) {
$entity[$keyval] = $transformed_quote[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $quote, $this->quote_transformer);
} }
} }
return $this->decorateAdvancedFields($quote, $entity); return $this->decorateAdvancedFields($quote, $entity);
} }
private function decorateAdvancedFields(Quote $quote, array $entity) :array private function decorateAdvancedFields(Quote $quote, array $entity) :array

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\RecurringInvoice; use App\Models\RecurringInvoice;
use App\Transformers\RecurringInvoiceTransformer; use App\Transformers\RecurringInvoiceTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -28,55 +29,6 @@ class RecurringInvoiceExport extends BaseExport
public Writer $csv; public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'client' => 'client_id',
// 'custom_surcharge1' => 'custom_surcharge1',
// 'custom_surcharge2' => 'custom_surcharge2',
// 'custom_surcharge3' => 'custom_surcharge3',
// 'custom_surcharge4' => 'custom_surcharge4',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'next_send_date' => 'next_send_date',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency' => 'currency_id',
'vendor' => 'vendor_id',
'project' => 'project_id',
'frequency_id' => 'frequency_id',
];
private array $decorate_keys = [
'country',
'client',
'currency',
'status',
'vendor',
'project',
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -84,7 +36,7 @@ class RecurringInvoiceExport extends BaseExport
$this->invoice_transformer = new RecurringInvoiceTransformer(); $this->invoice_transformer = new RecurringInvoiceTransformer();
} }
public function run() public function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
@ -92,23 +44,33 @@ class RecurringInvoiceExport extends BaseExport
$t = app('translator'); $t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->recurring_invoice_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = RecurringInvoice::query() $query = RecurringInvoice::query()
->withTrashed() ->withTrashed()
->with('client')->where('company_id', $this->company->id) ->with('client')
->where('company_id', $this->company->id)
->where('is_deleted', 0); ->where('is_deleted', 0);
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($invoice) { ->each(function ($invoice) {
$this->csv->insertOne($this->buildRow($invoice)); $this->csv->insertOne($this->buildRow($invoice));
@ -117,6 +79,27 @@ class RecurringInvoiceExport extends BaseExport
return $this->csv->toString(); return $this->csv->toString();
} }
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function buildRow(RecurringInvoice $invoice) :array private function buildRow(RecurringInvoice $invoice) :array
{ {
$transformed_invoice = $this->invoice_transformer->transform($invoice); $transformed_invoice = $this->invoice_transformer->transform($invoice);
@ -124,22 +107,13 @@ class RecurringInvoiceExport extends BaseExport
$entity = []; $entity = [];
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval) { $parts = explode('.', $key);
$keyval = array_search(str_replace("recurring_invoice.", "", $key), $this->entity_keys) ?? $key;
}
if(!$keyval) { if (is_array($parts) && $parts[0] == 'recurring_invoice' && array_key_exists($parts[1], $transformed_invoice)) {
$keyval = $key; $entity[$key] = $transformed_invoice[$parts[1]];
}
if (array_key_exists($key, $transformed_invoice)) {
$entity[$keyval] = $transformed_invoice[$key];
} elseif (array_key_exists($keyval, $transformed_invoice)) {
$entity[$keyval] = $transformed_invoice[$keyval];
} else { } else {
$entity[$keyval] = $this->resolveKey($keyval, $invoice, $this->invoice_transformer); $entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
} }
} }
@ -174,7 +148,7 @@ class RecurringInvoiceExport extends BaseExport
} }
if (in_array('recurring_invoice.frequency_id', $this->input['report_keys']) || in_array('frequency_id', $this->input['report_keys'])) { if (in_array('recurring_invoice.frequency_id', $this->input['report_keys']) || in_array('frequency_id', $this->input['report_keys'])) {
$entity['frequency_id'] = $invoice->frequencyForKey($invoice->frequency_id); $entity['recurring_invoice.frequency_id'] = $invoice->frequencyForKey($invoice->frequency_id);
} }
return $entity; return $entity;

View File

@ -18,6 +18,7 @@ use App\Models\Task;
use App\Models\Timezone; use App\Models\Timezone;
use App\Transformers\TaskTransformer; use App\Transformers\TaskTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -33,30 +34,9 @@ class TaskExport extends BaseExport
public Writer $csv; public Writer $csv;
public array $entity_keys = [ private array $storage_array = [];
'start_date' => 'start_date',
'end_date' => 'end_date',
'duration' => 'duration',
'rate' => 'rate',
'number' => 'number',
'description' => 'description',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'status' => 'status_id',
'project' => 'project_id',
];
private array $decorate_keys = [ private array $storage_item_array = [];
'status',
'project',
'client',
'invoice',
'start_date',
'end_date',
'duration',
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
@ -65,7 +45,7 @@ class TaskExport extends BaseExport
$this->entity_transformer = new TaskTransformer(); $this->entity_transformer = new TaskTransformer();
} }
public function run() public function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
@ -74,19 +54,12 @@ class TaskExport extends BaseExport
$t->replace(Ninja::transformTranslations($this->company->settings)); $t->replace(Ninja::transformTranslations($this->company->settings));
$this->date_format = DateFormat::find($this->company->settings->date_format_id)->format; $this->date_format = DateFormat::find($this->company->settings->date_format_id)->format;
//load the CSV document from a string
$this->csv = Writer::createFromString();
ksort($this->entity_keys); ksort($this->entity_keys);
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->task_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Task::query() $query = Task::query()
->withTrashed() ->withTrashed()
->where('company_id', $this->company->id) ->where('company_id', $this->company->id)
@ -94,51 +67,86 @@ class TaskExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($entity) { ->each(function ($entity) {
$this->buildRow($entity); $this->buildRow($entity);
}); });
$this->csv->insertAll($this->storage_array);
return $this->csv->toString(); return $this->csv->toString();
} }
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$query->cursor()
->each(function ($resource) {
$this->buildRow($resource);
foreach($this->storage_array as $row)
{
$this->storage_item_array[] = $this->processMetaData($row, $resource);
}
$this->storage_array = [];
});
// nlog($this->storage_item_array);
return array_merge(['columns' => $header], $this->storage_item_array);
}
private function buildRow(Task $task) private function buildRow(Task $task)
{ {
$entity = []; $entity = [];
$transformed_entity = $this->entity_transformer->transform($task); $transformed_entity = $this->entity_transformer->transform($task);
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval) { $parts = explode('.', $key);
$keyval = array_search(str_replace("task.", "", $key), $this->entity_keys) ?? $key;
if (is_array($parts) && $parts[0] == 'task' && array_key_exists($parts[1], $transformed_entity)) {
$entity[$key] = $transformed_entity[$parts[1]];
} elseif (array_key_exists($key, $transformed_entity)) {
$entity[$key] = $transformed_entity[$key];
} else {
$entity[$key] = $this->resolveKey($key, $task, $this->entity_transformer);
} }
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];
} elseif (array_key_exists($keyval, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $task, $this->entity_transformer);
}
} }
$entity['start_date'] = ''; $entity['task.start_date'] = '';
$entity['end_date'] = ''; $entity['task.end_date'] = '';
$entity['duration'] = ''; $entity['task.duration'] = '';
if (is_null($task->time_log) || (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) == 0)) { if (is_null($task->time_log) || (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) == 0)) {
$this->csv->insertOne($entity); $this->storage_array[] = $entity;
} else { } else {
$this->iterateLogs($task, $entity); $this->iterateLogs($task, $entity);
} }
} }
@ -163,41 +171,42 @@ class TaskExport extends BaseExport
foreach ($logs as $key => $item) { foreach ($logs as $key => $item) {
if (in_array('task.start_date', $this->input['report_keys']) || in_array('start_date', $this->input['report_keys'])) { if (in_array('task.start_date', $this->input['report_keys']) || in_array('start_date', $this->input['report_keys'])) {
$entity['start_date'] = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name)->format($date_format_default); $entity['task.start_date'] = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name)->format($date_format_default);
} }
if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] > 0) { if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] > 0) {
$entity['end_date'] = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name)->format($date_format_default); $entity['task.end_date'] = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name)->format($date_format_default);
} }
if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] == 0) { if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] == 0) {
$entity['end_date'] = ctrans('texts.is_running'); $entity['task.end_date'] = ctrans('texts.is_running');
} }
if (in_array('task.duration', $this->input['report_keys']) || in_array('duration', $this->input['report_keys'])) { if (in_array('task.duration', $this->input['report_keys']) || in_array('duration', $this->input['report_keys'])) {
$entity['duration'] = $task->calcDuration(); $entity['task.duration'] = $task->calcDuration();
} }
$entity = $this->decorateAdvancedFields($task, $entity); $entity = $this->decorateAdvancedFields($task, $entity);
$this->csv->insertOne($entity); $this->storage_array[] = $entity;
unset($entity['start_date']); unset($entity['task.start_date']);
unset($entity['end_date']); unset($entity['task.end_date']);
unset($entity['duration']); unset($entity['task.duration']);
} }
} }
private function decorateAdvancedFields(Task $task, array $entity) :array private function decorateAdvancedFields(Task $task, array $entity) :array
{ {
if (in_array('status_id', $this->input['report_keys'])) { if (in_array('task.status_id', $this->input['report_keys'])) {
$entity['status'] = $task->status()->exists() ? $task->status->name : ''; $entity['task.status_id'] = $task->status()->exists() ? $task->status->name : '';
} }
if (in_array('project_id', $this->input['report_keys'])) { if (in_array('task.project_id', $this->input['report_keys'])) {
$entity['project'] = $task->project()->exists() ? $task->project->name : ''; $entity['task.project_id'] = $task->project()->exists() ? $task->project->name : '';
} }
return $entity; return $entity;
} }
} }

View File

@ -17,6 +17,7 @@ use App\Models\Company;
use App\Transformers\VendorContactTransformer; use App\Transformers\VendorContactTransformer;
use App\Transformers\VendorTransformer; use App\Transformers\VendorTransformer;
use App\Utils\Ninja; use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use League\Csv\Writer; use League\Csv\Writer;
@ -31,46 +32,6 @@ class VendorExport extends BaseExport
public string $date_key = 'created_at'; public string $date_key = 'created_at';
public array $entity_keys = [
'address1' => 'vendor.address1',
'address2' => 'vendor.address2',
'city' => 'vendor.city',
'country' => 'vendor.country_id',
'custom_value1' => 'vendor.custom_value1',
'custom_value2' => 'vendor.custom_value2',
'custom_value3' => 'vendor.custom_value3',
'custom_value4' => 'vendor.custom_value4',
'id_number' => 'vendor.id_number',
'name' => 'vendor.name',
'number' => 'vendor.number',
'phone' => 'vendor.phone',
'postal_code' => 'vendor.postal_code',
'private_notes' => 'vendor.private_notes',
'public_notes' => 'vendor.public_notes',
'state' => 'vendor.state',
'vat_number' => 'vendor.vat_number',
'website' => 'vendor.website',
'currency' => 'vendor.currency',
'first_name' => 'vendor_contact.first_name',
'last_name' => 'vendor_contact.last_name',
'contact_phone' => 'vendor_contact.phone',
'contact_custom_value1' => 'vendor_contact.custom_value1',
'contact_custom_value2' => 'vendor_contact.custom_value2',
'contact_custom_value3' => 'vendor_contact.custom_value3',
'contact_custom_value4' => 'vendor_contact.custom_value4',
'email' => 'vendor_contact.email',
'status' => 'vendor.status'
];
private array $decorate_keys = [
'vendor.country_id',
'vendor.currency',
];
public array $forced_keys = [
// 'vendor.status'
];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
$this->company = $company; $this->company = $company;
@ -79,8 +40,9 @@ class VendorExport extends BaseExport
$this->contact_transformer = new VendorContactTransformer(); $this->contact_transformer = new VendorContactTransformer();
} }
public function run() public function init(): Builder
{ {
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::forgetInstance('translator'); App::forgetInstance('translator');
App::setLocale($this->company->locale()); App::setLocale($this->company->locale());
@ -91,19 +53,47 @@ class VendorExport extends BaseExport
$this->csv = Writer::createFromString(); $this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) { if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys); $this->input['report_keys'] = array_values($this->vendor_report_keys);
} }
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Vendor::query()->with('contacts') $query = Vendor::query()->with('contacts')
->withTrashed() ->withTrashed()
->where('company_id', $this->company->id) ->where('company_id', $this->company->id)
->where('is_deleted', 0); ->where('is_deleted', 0);
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
$row = $this->buildRow($resource);
return $this->processMetaData($row, $resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function run()
{
$query = $this->init();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor() $query->cursor()
->each(function ($vendor) { ->each(function ($vendor) {
$this->csv->insertOne($this->buildRow($vendor)); $this->csv->insertOne($this->buildRow($vendor));
@ -114,7 +104,7 @@ class VendorExport extends BaseExport
private function buildRow(Vendor $vendor) :array private function buildRow(Vendor $vendor) :array
{ {
$transformed_contact = []; $transformed_contact = false;
$transformed_vendor = $this->vendor_transformer->transform($vendor); $transformed_vendor = $this->vendor_transformer->transform($vendor);
@ -127,14 +117,12 @@ class VendorExport extends BaseExport
foreach (array_values($this->input['report_keys']) as $key) { foreach (array_values($this->input['report_keys']) as $key) {
$parts = explode('.', $key); $parts = explode('.', $key);
$keyval = array_search($key, $this->entity_keys);
if (is_array($parts) && $parts[0] == 'vendor' && array_key_exists($parts[1], $transformed_vendor)) { if (is_array($parts) && $parts[0] == 'vendor' && array_key_exists($parts[1], $transformed_vendor)) {
$entity[$keyval] = $transformed_vendor[$parts[1]]; $entity[$key] = $transformed_vendor[$parts[1]];
} elseif (is_array($parts) && $parts[0] == 'vendor_contact' && array_key_exists($parts[1], $transformed_contact)) { } elseif (is_array($parts) && $parts[0] == 'vendor_contact' && isset($transformed_contact[$parts[1]])) {
$entity[$keyval] = $transformed_contact[$parts[1]]; $entity[$key] = $transformed_contact[$parts[1]];
} else { } else {
$entity[$keyval] = ''; $entity[$key] = $this->resolveKey($key, $vendor, $this->vendor_transformer);
} }
} }
@ -151,7 +139,11 @@ class VendorExport extends BaseExport
$entity['currency'] = $vendor->currency() ? $vendor->currency()->code : $vendor->company->currency()->code; $entity['currency'] = $vendor->currency() ? $vendor->currency()->code : $vendor->company->currency()->code;
} }
$entity['status'] = $this->calculateStatus($vendor); if (in_array('vendor.classification', $this->input['report_keys']) && isset($vendor->classification)) {
$entity['vendor.classification'] = ctrans("texts.{$vendor->classification}") ?? '';
}
// $entity['status'] = $this->calculateStatus($vendor);
return $entity; return $entity;
} }

View File

@ -32,7 +32,8 @@ class ClientFactory
$client->is_deleted = 0; $client->is_deleted = 0;
$client->client_hash = Str::random(40); $client->client_hash = Str::random(40);
$client->settings = ClientSettings::defaults(); $client->settings = ClientSettings::defaults();
$client->classification = '';
return $client; return $client;
} }
} }

View File

@ -34,7 +34,7 @@ class ProductFactory
$product->custom_value2 = ''; $product->custom_value2 = '';
$product->custom_value3 = ''; $product->custom_value3 = '';
$product->custom_value4 = ''; $product->custom_value4 = '';
$product->is_deleted = 0; $product->is_deleted = false;
$product->tax_id = 1; $product->tax_id = 1;
return $product; return $product;

View File

@ -20,7 +20,6 @@ class ProjectFactory
$project = new Project; $project = new Project;
$project->company_id = $company_id; $project->company_id = $company_id;
$project->user_id = $user_id; $project->user_id = $user_id;
$project->public_notes = ''; $project->public_notes = '';
$project->private_notes = ''; $project->private_notes = '';
$project->budgeted_hours = 0; $project->budgeted_hours = 0;
@ -30,7 +29,7 @@ class ProjectFactory
$project->custom_value2 = ''; $project->custom_value2 = '';
$project->custom_value3 = ''; $project->custom_value3 = '';
$project->custom_value4 = ''; $project->custom_value4 = '';
$project->is_deleted = 0; $project->is_deleted = false;
return $project; return $project;
} }

View File

@ -34,7 +34,9 @@ class RecurringExpenseFactory
$recurring_expense->tax_amount1 = 0; $recurring_expense->tax_amount1 = 0;
$recurring_expense->tax_amount2 = 0; $recurring_expense->tax_amount2 = 0;
$recurring_expense->tax_amount3 = 0; $recurring_expense->tax_amount3 = 0;
$recurring_expense->date = null; $recurring_expense->date = now()->format('Y-m-d');
$recurring_expense->next_send_date = now()->format('Y-m-d');
$recurring_expense->next_send_date_client = now()->format('Y-m-d');
$recurring_expense->payment_date = null; $recurring_expense->payment_date = null;
$recurring_expense->amount = 0; $recurring_expense->amount = 0;
$recurring_expense->foreign_amount = 0; $recurring_expense->foreign_amount = 0;
@ -47,6 +49,7 @@ class RecurringExpenseFactory
$recurring_expense->custom_value4 = ''; $recurring_expense->custom_value4 = '';
$recurring_expense->uses_inclusive_taxes = true; $recurring_expense->uses_inclusive_taxes = true;
$recurring_expense->calculate_tax_by_amount = true; $recurring_expense->calculate_tax_by_amount = true;
$recurring_expense->remaining_cycles = -1;
return $recurring_expense; return $recurring_expense;
} }

View File

@ -65,6 +65,7 @@ class RecurringExpenseToExpenseFactory
$expense->tax_amount3 = $recurring_expense->tax_amount3 ?: 0; $expense->tax_amount3 = $recurring_expense->tax_amount3 ?: 0;
$expense->uses_inclusive_taxes = $recurring_expense->uses_inclusive_taxes; $expense->uses_inclusive_taxes = $recurring_expense->uses_inclusive_taxes;
$expense->calculate_tax_by_amount = $recurring_expense->calculate_tax_by_amount; $expense->calculate_tax_by_amount = $recurring_expense->calculate_tax_by_amount;
$expense->invoice_currency_id = $recurring_expense->invoice_currency_id;
return $expense; return $expense;
} }

View File

@ -28,6 +28,7 @@ class VendorFactory
$vendor->country_id = 4; $vendor->country_id = 4;
$vendor->is_deleted = 0; $vendor->is_deleted = 0;
$vendor->vendor_hash = Str::random(40); $vendor->vendor_hash = Str::random(40);
// $vendor->classification = '';
return $vendor; return $vendor;
} }

View File

@ -38,7 +38,10 @@ class ExpenseFilters extends QueryFilters
->orWhere('custom_value1', 'like', '%'.$filter.'%') ->orWhere('custom_value1', 'like', '%'.$filter.'%')
->orWhere('custom_value2', 'like', '%'.$filter.'%') ->orWhere('custom_value2', 'like', '%'.$filter.'%')
->orWhere('custom_value3', 'like', '%'.$filter.'%') ->orWhere('custom_value3', 'like', '%'.$filter.'%')
->orWhere('custom_value4', 'like', '%'.$filter.'%'); ->orWhere('custom_value4', 'like', '%'.$filter.'%')
->orWhereHas('category', function ($q) use ($filter) {
$q->where('name', 'like', '%'.$filter.'%');
});
}); });
} }
@ -166,16 +169,27 @@ class ExpenseFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
if ($sort_col[0] == 'client_id') { if ($sort_col[0] == 'client_id' && in_array($sort_col[1], ['asc', 'desc'])) {
return $this->builder->orderBy(\App\Models\Client::select('name') return $this->builder
->orderByRaw('ISNULL(client_id), client_id '. $sort_col[1])
->orderBy(\App\Models\Client::select('name')
->whereColumn('clients.id', 'expenses.client_id'), $sort_col[1]); ->whereColumn('clients.id', 'expenses.client_id'), $sort_col[1]);
} }
if ($sort_col[0] == 'vendor_id') { if ($sort_col[0] == 'vendor_id' && in_array($sort_col[1], ['asc', 'desc'])) {
return $this->builder->orderBy(\App\Models\Vendor::select('name') return $this->builder
->orderByRaw('ISNULL(vendor_id), vendor_id '. $sort_col[1])
->orderBy(\App\Models\Vendor::select('name')
->whereColumn('vendors.id', 'expenses.vendor_id'), $sort_col[1]); ->whereColumn('vendors.id', 'expenses.vendor_id'), $sort_col[1]);
} }
if ($sort_col[0] == 'category_id' && in_array($sort_col[1], ['asc', 'desc'])) {
return $this->builder
->orderByRaw('ISNULL(category_id), category_id '. $sort_col[1])
->orderBy(\App\Models\ExpenseCategory::select('name')
->whereColumn('expense_categories.id', 'expenses.category_id'), $sort_col[1]);
}
if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) { if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) {
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);

View File

@ -25,7 +25,8 @@ class GroupSettingFilters extends QueryFilters
* @return Builder * @return Builder
*/ */
public function name(string $name = ''): Builder public function name(string $name = ''): Builder
{nlog("filter"); {
if (strlen($name) == 0) { if (strlen($name) == 0) {
return $this->builder; return $this->builder;
} }

View File

@ -229,6 +229,32 @@ class InvoiceFilters extends QueryFilters
return $this->builder->where('due_date', '>=', $date); return $this->builder->where('due_date', '>=', $date);
} }
public function date_range(string $date_range = ''): Builder
{
$parts = explode(",", $date_range);
if (count($parts) != 3) {
return $this->builder;
}
if(!in_array($parts[0], ['date','due_date'])) {
return $this->builder;
}
try{
$start_date = Carbon::parse($parts[1]);
$end_date = Carbon::parse($parts[2]);
return $this->builder->whereBetween($parts[0], [$start_date, $end_date]);
}
catch(\Exception $e){
return $this->builder;
}
return $this->builder;
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.

View File

@ -12,8 +12,9 @@
namespace App\Filters; namespace App\Filters;
use App\Models\Payment; use App\Models\Payment;
use Illuminate\Contracts\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Contracts\Database\Eloquent\Builder as EloquentBuilder;
/** /**
* PaymentFilters. * PaymentFilters.
@ -113,7 +114,7 @@ class PaymentFilters extends QueryFilters
} }
if(in_array('partially_unapplied', $status_parameters)) { if(in_array('partially_unapplied', $status_parameters)) {
$query->where('amount', '>', 'applied')->where('refunded', 0); $query->whereColumn('amount', '>', 'applied')->where('refunded', 0);
} }
}); });
@ -177,6 +178,33 @@ class PaymentFilters extends QueryFilters
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }
public function date_range(string $date_range = ''): Builder
{
$parts = explode(",", $date_range);
if (count($parts) != 3) {
return $this->builder;
}
if(!in_array($parts[0], ['date'])) {
return $this->builder;
}
try{
$start_date = Carbon::parse($parts[1]);
$end_date = Carbon::parse($parts[2]);
return $this->builder->whereBetween($parts[0], [$start_date, $end_date]);
}
catch(\Exception $e){
return $this->builder;
}
return $this->builder;
}
/** /**
* Filters the query by the users company ID. * Filters the query by the users company ID.
* *

View File

@ -112,6 +112,12 @@ class QuoteFilters extends QueryFilters
->orderBy('due_date', 'DESC'); ->orderBy('due_date', 'DESC');
}); });
} }
if(in_array('converted', $status_parameters)) {
$query->orWhere(function ($q) {
$q->whereNotNull('invoice_id');
});
}
}); });
return $this->builder; return $this->builder;

View File

@ -41,22 +41,29 @@ class EpcQrGenerator
public function getQrCode() public function getQrCode()
{ {
$renderer = new ImageRenderer( $qr = '';
new RendererStyle(200),
new SvgImageBackEnd()
);
$writer = new Writer($renderer);
$this->validateFields();
try { try {
$renderer = new ImageRenderer(
new RendererStyle(200),
new SvgImageBackEnd()
);
$writer = new Writer($renderer);
$this->validateFields();
$qr = $writer->writeString($this->encodeMessage(), 'utf-8'); $qr = $writer->writeString($this->encodeMessage(), 'utf-8');
return "<svg viewBox='0 0 200 200' width='200' height='200' x='0' y='0' xmlns='http://www.w3.org/2000/svg'>
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
} catch(\Throwable $e) { } catch(\Throwable $e) {
return ''; return '';
} catch(\Exception $e) {
return '';
} }
return "<svg viewBox='0 0 200 200' width='200' height='200' x='0' y='0' xmlns='http://www.w3.org/2000/svg'>
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
} }
public function encodeMessage() public function encodeMessage()

View File

@ -144,7 +144,7 @@ class InvoiceItemSum
public function process(): self public function process(): self
{ {
if (!$this->invoice->line_items || !is_array($this->invoice->line_items)) { if (!$this->invoice->line_items || !is_iterable($this->invoice->line_items)) {
$this->items = []; $this->items = [];
return $this; return $this;
} }
@ -198,7 +198,7 @@ class InvoiceItemSum
private function push(): self private function push(): self
{ {
$this->sub_total += $this->getLineTotal(); $this->sub_total += round($this->getLineTotal(), $this->currency->precision);
$this->gross_sub_total += $this->getGrossLineTotal(); $this->gross_sub_total += $this->getGrossLineTotal();
@ -391,16 +391,16 @@ class InvoiceItemSum
{ {
$this->setGroupedTaxes(collect([])); $this->setGroupedTaxes(collect([]));
$item_tax = 0; foreach ($this->line_items as $key => $this->item) {
foreach ($this->line_items as $this->item) {
if ($this->item->line_total == 0) { if ($this->item->line_total == 0) {
continue; continue;
} }
$item_tax = 0;
//$amount = $this->item->line_total - ($this->item->line_total * ($this->invoice->discount / $this->sub_total)); //$amount = $this->item->line_total - ($this->item->line_total * ($this->invoice->discount / $this->sub_total));
$amount = ($this->sub_total > 0) ? $this->item->line_total - ($this->item->line_total * ($this->invoice->discount / $this->sub_total)) : 0; $amount = ($this->sub_total > 0) ? $this->item->line_total - ($this->invoice->discount * ( $this->item->line_total / $this->sub_total)) : 0;
$item_tax_rate1_total = $this->calcAmountLineTax($this->item->tax_rate1, $amount); $item_tax_rate1_total = $this->calcAmountLineTax($this->item->tax_rate1, $amount);
$item_tax += $item_tax_rate1_total; $item_tax += $item_tax_rate1_total;
@ -424,9 +424,19 @@ class InvoiceItemSum
if ($item_tax_rate3_total != 0) { if ($item_tax_rate3_total != 0) {
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total); $this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
} }
$this->item->gross_line_total = $this->getLineTotal() + $item_tax;
$this->item->tax_amount = $item_tax;
$this->line_items[$key] = $this->item;
$this->setTotalTaxes($this->getTotalTaxes() + $item_tax);
} }
$this->setTotalTaxes($item_tax);
return $this;
} }
/** /**

View File

@ -131,8 +131,7 @@ class InvoiceItemSumInclusive
public function process() public function process()
{ {
if (! $this->invoice->line_items || ! is_array($this->invoice->line_items) || count($this->invoice->line_items) == 0) { if (!$this->invoice->line_items || ! is_iterable($this->invoice->line_items) || count($this->invoice->line_items) == 0) {
return $this; return $this;
} }
@ -349,14 +348,16 @@ class InvoiceItemSumInclusive
{ {
$this->setGroupedTaxes(collect([])); $this->setGroupedTaxes(collect([]));
$item_tax = 0;
foreach ($this->line_items as $this->item) { foreach ($this->line_items as $this->item) {
if ($this->sub_total == 0) { if ($this->sub_total == 0) {
$amount = $this->item->line_total; $amount = $this->item->line_total;
} else { } else {
$amount = $this->item->line_total - ($this->item->line_total * ($this->invoice->discount / $this->sub_total)); $amount = ($this->sub_total > 0) ? $this->item->line_total - ($this->invoice->discount * ($this->item->line_total / $this->sub_total)) : 0;
// $amount = $this->item->line_total - ($this->item->line_total * ($this->invoice->discount / $this->sub_total));
} }
$item_tax = 0;
$item_tax_rate1_total = $this->calcInclusiveLineTax($this->item->tax_rate1, $amount); $item_tax_rate1_total = $this->calcInclusiveLineTax($this->item->tax_rate1, $amount);
@ -381,9 +382,17 @@ class InvoiceItemSumInclusive
if ($item_tax_rate3_total != 0) { if ($item_tax_rate3_total != 0) {
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total); $this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
} }
$this->setTotalTaxes($this->getTotalTaxes() + $item_tax);
$this->item->gross_line_total = $this->getLineTotal();
$this->item->tax_amount = $item_tax;
} }
$this->setTotalTaxes($item_tax); return $this;
// $this->setTotalTaxes($item_tax);
} }

View File

@ -308,8 +308,9 @@ class InvoiceSum
public function setTaxMap(): self public function setTaxMap(): self
{ {
if ($this->invoice->is_amount_discount == true) { if ($this->invoice->is_amount_discount) {
$this->invoice_items->calcTaxesWithAmountDiscount(); $this->invoice_items->calcTaxesWithAmountDiscount();
$this->invoice->line_items = $this->invoice_items->getLineItems();
} }
$this->tax_map = collect(); $this->tax_map = collect();
@ -327,8 +328,6 @@ class InvoiceSum
return $value['key'] == $key; return $value['key'] == $key;
})->sum('total'); })->sum('total');
//$total_line_tax -= $this->discount($total_line_tax);
$this->tax_map[] = ['name' => $tax_name, 'total' => $total_line_tax]; $this->tax_map[] = ['name' => $tax_name, 'total' => $total_line_tax];
$this->total_taxes += $total_line_tax; $this->total_taxes += $total_line_tax;
@ -377,16 +376,6 @@ class InvoiceSum
public function purgeTaxes(): self public function purgeTaxes(): self
{ {
// $this->tax_rate1 = 0;
// $this->tax_name1 = '';
// $this->tax_rate2 = 0;
// $this->tax_name2 = '';
// $this->tax_rate3 = 0;
// $this->tax_name3 = '';
// $this->discount = 0;
$line_items = collect($this->invoice->line_items); $line_items = collect($this->invoice->line_items);

View File

@ -315,8 +315,9 @@ class InvoiceSumInclusive
public function setTaxMap() public function setTaxMap()
{ {
if ($this->invoice->is_amount_discount == true) { if ($this->invoice->is_amount_discount) {
$this->invoice_items->calcTaxesWithAmountDiscount(); $this->invoice_items->calcTaxesWithAmountDiscount();
$this->invoice->line_items = $this->invoice_items->getLineItems();
} }
$this->tax_map = collect(); $this->tax_map = collect();

View File

@ -72,7 +72,7 @@ class AccountController extends BaseController
MultiDB::findAndSetDbByAccountKey($account->key); MultiDB::findAndSetDbByAccountKey($account->key);
$cu = CompanyUser::where('user_id', $account->users()->first()->id); $cu = CompanyUser::query()->where('user_id', $account->users()->first()->id);
$company_user = $cu->first(); $company_user = $cu->first();

View File

@ -80,6 +80,7 @@ class ContactForgotPasswordController extends Controller
'passwordEmailRoute' => 'client.password.email', 'passwordEmailRoute' => 'client.password.email',
'account' => $account, 'account' => $account,
'company' => $company, 'company' => $company,
'is_react' => false,
]); ]);
} }

View File

@ -90,6 +90,8 @@ class ForgotPasswordController extends Controller
$account = Account::find($account_id); $account = Account::find($account_id);
} }
return $this->render('auth.passwords.request', ['root' => 'themes', 'account' => $account]); $is_react = request()->has('react') ? true : false;
return $this->render('auth.passwords.request', ['root' => 'themes', 'account' => $account, 'is_react' => $is_react]);
} }
} }

View File

@ -12,37 +12,37 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use Google_Client;
use App\Models\User;
use App\Utils\Ninja;
use App\Models\Account;
use App\Libraries\MultiDB;
use App\Utils\TruthSource;
use Microsoft\Graph\Model;
use App\Models\CompanyUser;
use App\Models\CompanyToken;
use Illuminate\Http\Request;
use App\Libraries\OAuth\OAuth;
use App\Events\User\UserLoggedIn;
use Illuminate\Http\JsonResponse;
use PragmaRX\Google2FA\Google2FA;
use App\Jobs\Account\CreateAccount;
use Illuminate\Support\Facades\Auth;
use App\Utils\Traits\User\LoginCache;
use Illuminate\Support\Facades\Cache;
use Turbo124\Beacon\Facades\LightLogs;
use App\Http\Controllers\BaseController;
use App\Jobs\Company\CreateCompanyToken;
use Illuminate\Support\Facades\Response;
use Laravel\Socialite\Facades\Socialite;
use App\Http\Requests\Login\LoginRequest;
use App\Libraries\OAuth\Providers\Google;
use Illuminate\Database\Eloquent\Builder;
use App\DataMapper\Analytics\LoginFailure; use App\DataMapper\Analytics\LoginFailure;
use App\DataMapper\Analytics\LoginSuccess; use App\DataMapper\Analytics\LoginSuccess;
use App\Utils\Traits\UserSessionAttributes; use App\Events\User\UserLoggedIn;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Login\LoginRequest;
use App\Jobs\Account\CreateAccount;
use App\Jobs\Company\CreateCompanyToken;
use App\Libraries\MultiDB;
use App\Libraries\OAuth\OAuth;
use App\Libraries\OAuth\Providers\Google;
use App\Models\Account;
use App\Models\CompanyToken;
use App\Models\CompanyUser;
use App\Models\User;
use App\Transformers\CompanyUserTransformer; use App\Transformers\CompanyUserTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\User\LoginCache;
use App\Utils\Traits\UserSessionAttributes;
use App\Utils\TruthSource;
use Google_Client;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Response;
use Laravel\Socialite\Facades\Socialite;
use Microsoft\Graph\Model;
use PragmaRX\Google2FA\Google2FA;
use Turbo124\Beacon\Facades\LightLogs;
class LoginController extends BaseController class LoginController extends BaseController
{ {
@ -418,10 +418,12 @@ class LoginController extends BaseController
->setReturnType(Model\User::class) ->setReturnType(Model\User::class)
->execute(); ->execute();
nlog($user);
if ($user) { if ($user) {
$account = request()->input('account'); $account = request()->input('account');
$email = $user->getMail() ?: $user->getUserPrincipalName(); $email = $user->getUserPrincipalName() ?? false;
$query = [ $query = [
'oauth_user_id' => $user->getId(), 'oauth_user_id' => $user->getId(),
@ -436,8 +438,8 @@ class LoginController extends BaseController
return $this->existingOauthUser($existing_user); return $this->existingOauthUser($existing_user);
} }
//If this is a result user/email combo - lets add their OAuth details details // If this is a result user/email combo - lets add their OAuth details details
if ($existing_login_user = MultiDB::hasUser(['email' => $email])) { if ($email && $existing_login_user = MultiDB::hasUser(['email' => $email])) {
if (!$existing_login_user->account) { if (!$existing_login_user->account) {
return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400); return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400);
} }
@ -447,7 +449,6 @@ class LoginController extends BaseController
return $this->existingLoginUser($user->getId(), 'microsoft'); return $this->existingLoginUser($user->getId(), 'microsoft');
} }
// Signup! // Signup!
if (request()->has('create') && request()->input('create') == 'true') { if (request()->has('create') && request()->input('create') == 'true') {
$new_account = [ $new_account = [
@ -640,8 +641,9 @@ class LoginController extends BaseController
$parameters = ['response_type' => 'code', 'redirect_uri' => config('ninja.app_url') . "/auth/microsoft"]; $parameters = ['response_type' => 'code', 'redirect_uri' => config('ninja.app_url') . "/auth/microsoft"];
} }
if(request()->hasHeader('X-REACT') || request()->query('react')) if(request()->hasHeader('X-REACT') || request()->query('react')) {
Cache::put("react_redir:".auth()->user()?->account->key, 'true', 300); Cache::put("react_redir:".auth()->user()?->account->key, 'true', 300);
}
if (request()->has('code')) { if (request()->has('code')) {
return $this->handleProviderCallback($provider); return $this->handleProviderCallback($provider);
@ -698,7 +700,7 @@ class LoginController extends BaseController
$request_from_react = Cache::pull("react_redir:".auth()->user()?->account?->key); $request_from_react = Cache::pull("react_redir:".auth()->user()?->account?->key);
// if($request_from_react) // if($request_from_react)
$redirect_url = config('ninja.react_url')."/#/settings/user_details/connect"; $redirect_url = config('ninja.react_url')."/#/settings/user_details/connect";
return redirect($redirect_url); return redirect($redirect_url);
} }

View File

@ -70,6 +70,7 @@ class ResetPasswordController extends Controller
$account = Account::first(); $account = Account::first();
} }
return $this->render('auth.passwords.reset', ['root' => 'themes', 'token' => $token, 'account' => $account, 'email' => $request->email]); return $this->render('auth.passwords.reset', ['root' => 'themes', 'token' => $token, 'account' => $account, 'email' => $request->email]);
} }
@ -110,6 +111,9 @@ class ResetPasswordController extends Controller
{ {
auth()->logout(); auth()->logout();
if(request()->has('react') || request()->hasHeader('X-React'))
return redirect(config('ninja.react_url').'/#/login');
return redirect('/'); return redirect('/');
} }
@ -126,10 +130,10 @@ class ResetPasswordController extends Controller
return new JsonResponse(['message' => trans($response)], 200); return new JsonResponse(['message' => trans($response)], 200);
} }
if(Ninja::isHosted() && $request->hasHeader('X-React')){ if($request->hasHeader('X-REACT') || $request->has('react')){
return redirect('https://app.invoicing.co/#/login'); return redirect(config('ninja.react_url').'/#/login');
} }
elseif($request->hasHeader('X-React')) else
return redirect('/#/login'); return redirect('/#/login');
return redirect($this->redirectPath()) return redirect($this->redirectPath())

View File

@ -71,15 +71,21 @@ class BankTransactionController extends BaseController
public function create(CreateBankTransactionRequest $request) public function create(CreateBankTransactionRequest $request)
{ {
$bank_transaction = BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$bank_transaction = BankTransactionFactory::create($user->company()->id, $user->id);
return $this->itemResponse($bank_transaction); return $this->itemResponse($bank_transaction);
} }
public function store(StoreBankTransactionRequest $request) public function store(StoreBankTransactionRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
//stub to store the model //stub to store the model
$bank_transaction = $this->bank_transaction_repo->save($request->all(), BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id)); $bank_transaction = $this->bank_transaction_repo->save($request->all(), BankTransactionFactory::create($user->company()->id, $user->id));
return $this->itemResponse($bank_transaction); return $this->itemResponse($bank_transaction);
} }

View File

@ -12,9 +12,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Support\Collection;
use App\Models\BankTransactionRule; use App\Models\BankTransactionRule;
use App\Filters\BankTransactionFilters;
use App\Factory\BankTransactionRuleFactory; use App\Factory\BankTransactionRuleFactory;
use App\Filters\BankTransactionRuleFilters; use App\Filters\BankTransactionRuleFilters;
use App\Repositories\BankTransactionRuleRepository; use App\Repositories\BankTransactionRuleRepository;
@ -26,6 +24,7 @@ use App\Http\Requests\BankTransactionRule\StoreBankTransactionRuleRequest;
use App\Http\Requests\BankTransactionRule\CreateBankTransactionRuleRequest; use App\Http\Requests\BankTransactionRule\CreateBankTransactionRuleRequest;
use App\Http\Requests\BankTransactionRule\UpdateBankTransactionRuleRequest; use App\Http\Requests\BankTransactionRule\UpdateBankTransactionRuleRequest;
use App\Http\Requests\BankTransactionRule\DestroyBankTransactionRuleRequest; use App\Http\Requests\BankTransactionRule\DestroyBankTransactionRuleRequest;
use App\Services\Bank\BankMatchingService;
class BankTransactionRuleController extends BaseController class BankTransactionRuleController extends BaseController
{ {
@ -256,8 +255,12 @@ class BankTransactionRuleController extends BaseController
*/ */
public function update(UpdateBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule) public function update(UpdateBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule)
{ {
//stubs for updating the model /** @var \App\Models\User $user */
$bank_transaction = $this->bank_transaction_repo->save($request->all(), $bank_transaction_rule); $user = auth()->user();
$bank_transaction_rule = $this->bank_transaction_repo->save($request->all(), $bank_transaction_rule);
BankMatchingService::dispatch($user->company()->id, $user->company()->db);
return $this->itemResponse($bank_transaction_rule->fresh()); return $this->itemResponse($bank_transaction_rule->fresh());
} }
@ -304,6 +307,7 @@ class BankTransactionRuleController extends BaseController
{ {
/** @var \App\Models\User $user **/ /** @var \App\Models\User $user **/
$user = auth()->user(); $user = auth()->user();
$bank_transaction_rule = BankTransactionRuleFactory::create($user->company()->id, $user->id); $bank_transaction_rule = BankTransactionRuleFactory::create($user->company()->id, $user->id);
return $this->itemResponse($bank_transaction_rule); return $this->itemResponse($bank_transaction_rule);
@ -355,6 +359,8 @@ class BankTransactionRuleController extends BaseController
$bank_transaction_rule = $this->bank_transaction_repo->save($request->all(), BankTransactionRuleFactory::create($user->company()->id, $user->id)); $bank_transaction_rule = $this->bank_transaction_repo->save($request->all(), BankTransactionRuleFactory::create($user->company()->id, $user->id));
BankMatchingService::dispatch($user->company()->id, $user->company()->db);
return $this->itemResponse($bank_transaction_rule); return $this->itemResponse($bank_transaction_rule);
} }

View File

@ -1065,7 +1065,7 @@ class BaseController extends Controller
$data = $this->first_load; $data = $this->first_load;
} }
} else { } else {
$included = request()->input('include'); $included = request()->input('include', '');
$included = explode(',', $included); $included = explode(',', $included);
foreach ($included as $include) { foreach ($included as $include) {

View File

@ -123,11 +123,14 @@ class ClientController extends BaseController
return $request->disallowUpdate(); return $request->disallowUpdate();
} }
/** @var \App\Models\User $user */
$user = auth()->user();
$client = $this->client_repo->save($request->all(), $client); $client = $this->client_repo->save($request->all(), $client);
$this->uploadLogo($request->file('company_logo'), $client->company, $client); $this->uploadLogo($request->file('company_logo'), $client->company, $client);
event(new ClientWasUpdated($client, $client->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new ClientWasUpdated($client, $client->company, Ninja::eventVars($user ? $user->id : null)));
return $this->itemResponse($client->fresh()); return $this->itemResponse($client->fresh());
} }
@ -141,7 +144,10 @@ class ClientController extends BaseController
*/ */
public function create(CreateClientRequest $request) public function create(CreateClientRequest $request)
{ {
$client = ClientFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$client = ClientFactory::create($user->company()->id, $user->id);
return $this->itemResponse($client); return $this->itemResponse($client);
} }
@ -155,7 +161,10 @@ class ClientController extends BaseController
*/ */
public function store(StoreClientRequest $request) public function store(StoreClientRequest $request)
{ {
$client = $this->client_repo->save($request->all(), ClientFactory::create(auth()->user()->company()->id, auth()->user()->id)); /** @var \App\Models\User $user */
$user = auth()->user();
$client = $this->client_repo->save($request->all(), ClientFactory::create($user->company()->id, $user->id));
$client->load('contacts', 'primary_contact'); $client->load('contacts', 'primary_contact');
@ -166,7 +175,7 @@ class ClientController extends BaseController
$this->uploadLogo($request->file('company_logo'), $client->company, $client); $this->uploadLogo($request->file('company_logo'), $client->company, $client);
event(new ClientWasCreated($client, $client->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new ClientWasCreated($client, $client->company, Ninja::eventVars(auth()->user() ? $user->id : null)));
return $this->itemResponse($client); return $this->itemResponse($client);
} }
@ -273,9 +282,12 @@ class ClientController extends BaseController
public function merge(PurgeClientRequest $request, Client $client, string $mergeable_client) public function merge(PurgeClientRequest $request, Client $client, string $mergeable_client)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$m_client = Client::withTrashed() $m_client = Client::withTrashed()
->where('id', $this->decodePrimaryKey($mergeable_client)) ->where('id', $this->decodePrimaryKey($mergeable_client))
->where('company_id', auth()->user()->company()->id) ->where('company_id', $user->company()->id)
->first(); ->first();
if (!$m_client) { if (!$m_client) {

View File

@ -93,7 +93,7 @@ class ClientGatewayTokenController extends BaseController
*/ */
public function index(ListClientGatewayTokenRequest $request) public function index(ListClientGatewayTokenRequest $request)
{ {
$client_gateway_token_gateway_tokens = ClientGatewayToken::scope(); $client_gateway_token_gateway_tokens = ClientGatewayToken::query()->company();
return $this->listResponse($client_gateway_token_gateway_tokens); return $this->listResponse($client_gateway_token_gateway_tokens);
} }

View File

@ -17,6 +17,10 @@ use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\View\View; use Illuminate\View\View;
/**
* EntityViewController
* @deprecated 5.7 ?
*/
class EntityViewController extends Controller class EntityViewController extends Controller
{ {
use MakesHash; use MakesHash;

View File

@ -87,13 +87,20 @@ class InvoiceController extends Controller
public function showBlob($hash) public function showBlob($hash)
{ {
$data = Cache::get($hash); $data = Cache::get($hash);
if(!$data){
usleep(200000);
$data = Cache::get($hash);
}
$invitation = false; $invitation = false;
match($data['entity_type']){ match($data['entity_type'] ?? false){
'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']), 'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']),
'quote' => $invitation = QuoteInvitation::withTrashed()->find($data['invitation_id']), 'quote' => $invitation = QuoteInvitation::withTrashed()->find($data['invitation_id']),
'credit' => $invitation = CreditInvitation::withTrashed()->find($data['invitation_id']), 'credit' => $invitation = CreditInvitation::withTrashed()->find($data['invitation_id']),
'recurring_invoice' => $invitation = RecurringInvoiceInvitation::withTrashed()->find($data['invitation_id']), 'recurring_invoice' => $invitation = RecurringInvoiceInvitation::withTrashed()->find($data['invitation_id']),
false => $invitation = false,
}; };
if (! $invitation) { if (! $invitation) {
@ -188,7 +195,7 @@ class InvoiceController extends Controller
//format data //format data
$invoices->map(function ($invoice) { $invoices->map(function ($invoice) {
$invoice->service()->removeUnpaidGatewayFees(); // $invoice->service()->removeUnpaidGatewayFees();
$invoice->balance = $invoice->balance > 0 ? Number::formatValue($invoice->balance, $invoice->client->currency()) : 0; $invoice->balance = $invoice->balance > 0 ? Number::formatValue($invoice->balance, $invoice->client->currency()) : 0;
$invoice->partial = $invoice->partial > 0 ? Number::formatValue($invoice->partial, $invoice->client->currency()) : 0; $invoice->partial = $invoice->partial > 0 ? Number::formatValue($invoice->partial, $invoice->client->currency()) : 0;

View File

@ -12,21 +12,22 @@
namespace App\Http\Controllers\ClientPortal; namespace App\Http\Controllers\ClientPortal;
use App\Events\Misc\InvitationWasViewed; use App\Utils\Ninja;
use App\Models\Quote;
use Illuminate\View\View;
use Illuminate\Http\Request;
use App\Models\QuoteInvitation;
use App\Utils\Traits\MakesHash;
use App\Events\Quote\QuoteWasViewed; use App\Events\Quote\QuoteWasViewed;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\ClientPortal\Quotes\ProcessQuotesInBulkRequest; use App\Jobs\Invoice\InjectSignature;
use Illuminate\Contracts\View\Factory;
use Illuminate\Support\Facades\Storage;
use App\Events\Misc\InvitationWasViewed;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use App\Http\Requests\ClientPortal\Quotes\ShowQuoteRequest; use App\Http\Requests\ClientPortal\Quotes\ShowQuoteRequest;
use App\Http\Requests\ClientPortal\Quotes\ShowQuotesRequest; use App\Http\Requests\ClientPortal\Quotes\ShowQuotesRequest;
use App\Jobs\Invoice\InjectSignature; use App\Http\Requests\ClientPortal\Quotes\ProcessQuotesInBulkRequest;
use App\Models\Quote;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class QuoteController extends Controller class QuoteController extends Controller
{ {
@ -121,37 +122,38 @@ class QuoteController extends Controller
/** @var \App\Models\ClientContact $client_contact **/ /** @var \App\Models\ClientContact $client_contact **/
$client_contact = auth()->user(); $client_contact = auth()->user();
$quotes = Quote::query() $quote_invitations = QuoteInvitation::query()
->whereIn('id', $ids) ->with('quote','company')
->whereClientId($client_contact->client_id) ->whereIn('quote_id', $ids)
->where('client_contact_id', $client_contact->id)
->withTrashed() ->withTrashed()
->get(); ->get();
if (! $quotes || $quotes->count() == 0) { if (! $quote_invitations || $quote_invitations->count() == 0) {
return redirect() return redirect()
->route('client.quotes.index') ->route('client.quotes.index')
->with('message', ctrans('texts.no_quotes_available_for_download')); ->with('message', ctrans('texts.no_quotes_available_for_download'));
} }
if ($quotes->count() == 1) { if ($quote_invitations->count() == 1) {
$file = $quotes->first()->service()->getQuotePdf(); $invitation = $quote_invitations->first();
// return response()->download($file, basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle();
return response()->streamDownload(function () use ($file) { return response()->streamDownload(function () use ($file) {
echo Storage::get($file); echo $file;
}, basename($file), ['Content-Type' => 'application/pdf']); }, $invitation->quote->numberFormatter().".pdf", ['Content-Type' => 'application/pdf']);
} }
return $this->buildZip($quotes); return $this->buildZip($quote_invitations);
} }
private function buildZip($quotes) private function buildZip($quote_invitations)
{ {
// create new archive // create new archive
$zipFile = new \PhpZip\ZipFile(); $zipFile = new \PhpZip\ZipFile();
try { try {
foreach ($quotes as $quote) { foreach ($quote_invitations as $invitation) {
//add it to the zip $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle();
$zipFile->addFromString(basename($quote->pdf_file_path()), file_get_contents($quote->pdf_file_path(null, 'url', true))); $zipFile->addFromString($invitation->quote->numberFormatter() . '.pdf', $file);
} }
$filename = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.quotes')).'.zip'; $filename = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.quotes')).'.zip';
@ -162,7 +164,6 @@ class QuoteController extends Controller
return response()->download($filepath, $filename)->deleteFileAfterSend(true); return response()->download($filepath, $filename)->deleteFileAfterSend(true);
} catch (\PhpZip\Exception\ZipException $e) { } catch (\PhpZip\Exception\ZipException $e) {
// handle exception
} finally { } finally {
$zipFile->close(); $zipFile->close();
} }

View File

@ -22,9 +22,10 @@ class SwitchCompanyController extends Controller
public function __invoke(string $contact) public function __invoke(string $contact)
{ {
$client_contact = ClientContact::where('email', auth()->user()->email) $client_contact = ClientContact::query()
->where('id', $this->transformKeys($contact)) ->where('email', auth()->user()->email)
->first(); ->where('id', $this->transformKeys($contact))
->firstOrFail();
auth()->guard('contact')->loginUsingId($client_contact->id, true); auth()->guard('contact')->loginUsingId($client_contact->id, true);

View File

@ -697,4 +697,19 @@ class CompanyController extends BaseController
return $this->itemResponse($company->fresh()); return $this->itemResponse($company->fresh());
} }
public function logo()
{
/** @var \App\Models\User $user */
$user = auth()->user();
$company = $user->company();
$logo = strlen($company->settings->company_logo) > 5 ? $company->settings->company_logo : 'https://pdf.invoicing.co/favicon-v2.png';
$headers = ['Content-Disposition' => 'inline'];
return response()->streamDownload(function () use ($logo){
echo @file_get_contents($logo);
}, 'logo.png', $headers);
}
} }

View File

@ -111,10 +111,11 @@ class CompanyUserController extends BaseController
*/ */
public function update(UpdateCompanyUserRequest $request, User $user) public function update(UpdateCompanyUserRequest $request, User $user)
{ {
/** @var \App\Models\User $auth_user */
$auth_user = auth()->user();
$company = $auth_user->company();
$company = auth()->user()->company(); $company_user = CompanyUser::query()->where('user_id', $user->id)->where('company_id',$company->id)->first();
$company_user = CompanyUser::whereUserId($user->id)->whereCompanyId($company->id)->first();
if (! $company_user) { if (! $company_user) {
throw new ModelNotFoundException(ctrans('texts.company_user_not_found')); throw new ModelNotFoundException(ctrans('texts.company_user_not_found'));
@ -122,11 +123,16 @@ class CompanyUserController extends BaseController
return; return;
} }
if (auth()->user()->isAdmin()) { if ($auth_user->isAdmin()) {
$company_user->fill($request->input('company_user')); $company_user->fill($request->input('company_user'));
} else { } else {
$company_user->settings = $request->input('company_user')['settings']; $company_user->settings = $request->input('company_user')['settings'];
$company_user->notifications = $request->input('company_user')['notifications']; $company_user->notifications = $request->input('company_user')['notifications'];
if(isset($request->input('company_user')['react_settings'])) {
$company_user->react_settings = $request->input('company_user')['react_settings'];
}
} }
$company_user->save(); $company_user->save();
@ -136,8 +142,11 @@ class CompanyUserController extends BaseController
public function updatePreferences(UpdateCompanyUserPreferencesRequest $request, User $user) public function updatePreferences(UpdateCompanyUserPreferencesRequest $request, User $user)
{ {
/** @var \App\Models\User $auth_user */
$auth_user = auth()->user();
$company = $auth_user->company();
$company = auth()->user()->company(); $company = $auth_user->company();
$company_user = CompanyUser::whereUserId($user->id)->whereCompanyId($company->id)->first(); $company_user = CompanyUser::whereUserId($user->id)->whereCompanyId($company->id)->first();

View File

@ -105,7 +105,7 @@ class ConnectedAccountController extends BaseController
->execute(); ->execute();
if ($user) { if ($user) {
$email = $user->getMail() ?: $user->getUserPrincipalName(); $email = $user->getUserPrincipalName() ?? false;
nlog("microsoft"); nlog("microsoft");
nlog($email); nlog($email);

View File

@ -385,8 +385,8 @@ class CreditController extends BaseController
$credit = $this->credit_repository->save($request->all(), $credit); $credit = $this->credit_repository->save($request->all(), $credit);
$credit->service() $credit->service()
->triggeredActions($request) ->triggeredActions($request);
->deletePdf(); // ->deletePdf();
/** @var \App\Models\User $user**/ /** @var \App\Models\User $user**/
$user = auth()->user(); $user = auth()->user();
@ -529,20 +529,18 @@ class CreditController extends BaseController
if ($action == 'bulk_download' && $credits->count() > 1) { if ($action == 'bulk_download' && $credits->count() > 1) {
$credits->each(function ($credit) use($user){ $credits->each(function ($credit) use($user){
if ($user->cannot('view', $credit)) { if ($user->cannot('view', $credit)) {
nlog('access denied');
return response()->json(['message' => ctrans('text.access_denied')]); return response()->json(['message' => ctrans('text.access_denied')]);
} }
}); });
ZipCredits::dispatch($credits, $credits->first()->company, $user); ZipCredits::dispatch($credits->pluck('id')->toArray(), $credits->first()->company, $user);
return response()->json(['message' => ctrans('texts.sent_message')], 200); return response()->json(['message' => ctrans('texts.sent_message')], 200);
} }
if ($action == 'bulk_print' && $user->can('view', $credits->first())) { if ($action == 'bulk_print' && $user->can('view', $credits->first())) {
$paths = $credits->map(function ($credit) { $paths = $credits->map(function ($credit) {
return $credit->service()->getCreditPdf($credit->invitations->first()); return (new \App\Jobs\Entity\CreateRawPdf($credit->invitations->first(), $credit->company->db))->handle();
}); });
$merge = (new PdfMerge($paths->toArray()))->run(); $merge = (new PdfMerge($paths->toArray()))->run();
@ -592,11 +590,8 @@ class CreditController extends BaseController
} }
break; break;
case 'download': case 'download':
// $file = $credit->pdf_file_path();
$file = $credit->service()->getCreditPdf($credit->invitations->first()); $file = $credit->service()->getCreditPdf($credit->invitations->first());
// return response()->download($file, basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true);
return response()->streamDownload(function () use ($file) { return response()->streamDownload(function () use ($file) {
echo Storage::get($file); echo Storage::get($file);
}, basename($file), ['Content-Type' => 'application/pdf']); }, basename($file), ['Content-Type' => 'application/pdf']);

View File

@ -0,0 +1,68 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers;
use App\Http\Requests\Email\ClientEmailHistoryRequest;
use App\Http\Requests\Email\EntityEmailHistoryRequest;
use App\Models\Client;
use App\Models\SystemLog;
use App\Utils\Traits\MakesHash;
class EmailHistoryController extends BaseController
{
use MakesHash;
public function __construct()
{
}
public function clientHistory(ClientEmailHistoryRequest $request, Client $client)
{
$data = SystemLog::where('client_id', $client->id)
->where('category_id', SystemLog::CATEGORY_MAIL)
->orderBy('id', 'DESC')
->cursor()
->map(function ($system_log) {
if(($system_log->log['history'] && $system_log->log['history']['events'] && count($system_log->log['history']['events']) >=1) ?? false) {
return $system_log->log['history'];
}
});
return response()->json($data, 200);
}
/**
* May need to expand on this using
* just the message-id and search for the
* entity in the invitations
*/
public function entityHistory(EntityEmailHistoryRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$data = SystemLog::where('company_id', $user->company()->id)
->where('category_id', SystemLog::CATEGORY_MAIL)
->whereJsonContains('log->history->entity_id', $this->encodePrimaryKey($request->entity_id))
->orderBy('id', 'DESC')
->cursor()
->map(function ($system_log) {
if(($system_log->log['history'] && $system_log->log['history']['events'] && count($system_log->log['history']['events']) >=1) ?? false) {
return $system_log->log['history'];
}
});
return response()->json($data, 200);
}
}

View File

@ -139,7 +139,9 @@ class GroupSettingController extends BaseController
*/ */
public function update(UpdateGroupSettingRequest $request, GroupSetting $group_setting) public function update(UpdateGroupSettingRequest $request, GroupSetting $group_setting)
{ {
$group_setting = $this->group_setting_repo->save($request->all(), $group_setting); /** Need this to prevent settings from being overwritten */
if(!$request->file('company_logo'))
$group_setting = $this->group_setting_repo->save($request->all(), $group_setting);
$this->uploadLogo($request->file('company_logo'), $group_setting->company, $group_setting); $this->uploadLogo($request->file('company_logo'), $group_setting->company, $group_setting);

View File

@ -91,16 +91,83 @@ class ImportController extends Controller
$csv_array = $this->getCsvData($contents); $csv_array = $this->getCsvData($contents);
$class_map = $this->getEntityMap($entityType); $class_map = $this->getEntityMap($entityType);
$hints = $this->setImportHints($entityType, $class_map::importable(), $csv_array[0]);
$data['mappings'][$entityType] = [ $data['mappings'][$entityType] = [
'available' => $class_map::importable(), 'available' => $class_map::importable(),
'headers' => array_slice($csv_array, 0, 2), 'headers' => array_slice($csv_array, 0, 2),
'hints' => $hints,
]; ];
} }
return response()->json($data); return response()->json($data);
} }
private function setImportHints($entity_type, $available_keys, $headers): array
{
$hints = [];
$translated_keys = collect($available_keys)->map(function ($value,$key){
$parts = explode(".", $value);
$index = $parts[0];
$label = $parts[1] ?? $parts[0];
return ['key' => $key, 'index' => ctrans("texts.{$index}"), 'label' => ctrans("texts.{$label}")];
})->toArray();
foreach($headers as $key => $value) {
foreach($translated_keys as $tkey => $tvalue)
{
if($this->testMatch($value, $tvalue['label'])) {
$hit = $tvalue['key'];
$hints[$key] = $hit;
unset($translated_keys[$tkey]);
break;
}
else {
$hints[$key] = null;
}
}
}
//second pass using the index of the translation here
foreach($headers as $key => $value)
{
if(isset($hints[$key])) {
continue;
}
foreach($translated_keys as $tkey => $tvalue)
{
if($this->testMatch($value, $tvalue['index'])) {
$hit = $tvalue['key'];
$hints[$key] = $hit;
unset($translated_keys[$tkey]);
break;
} else {
$hints[$key] = null;
}
}
}
return $hints;
}
private function testMatch($haystack, $needle): bool
{
return stripos($haystack, $needle) !== false;
}
private function convertEncoding($data) private function convertEncoding($data)
{ {
@ -115,6 +182,9 @@ class ImportController extends Controller
public function import(ImportRequest $request) public function import(ImportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$data = $request->all(); $data = $request->all();
if (empty($data['hash'])) { if (empty($data['hash'])) {
@ -130,7 +200,7 @@ class ImportController extends Controller
} }
unset($data['files']); unset($data['files']);
CSVIngest::dispatch($data, auth()->user()->company()); CSVIngest::dispatch($data, $user->company());
return response()->json(['message' => ctrans('texts.import_started')], 200); return response()->json(['message' => ctrans('texts.import_started')], 200);
} }

View File

@ -415,7 +415,7 @@ class InvoiceController extends BaseController
$invoice->service() $invoice->service()
->triggeredActions($request) ->triggeredActions($request)
->deletePdf() // ->deletePdf()
->adjustInventory($old_invoice); ->adjustInventory($old_invoice);
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
@ -527,7 +527,7 @@ class InvoiceController extends BaseController
if ($action == 'bulk_print' && $user->can('view', $invoices->first())) { if ($action == 'bulk_print' && $user->can('view', $invoices->first())) {
$paths = $invoices->map(function ($invoice) { $paths = $invoices->map(function ($invoice) {
return $invoice->service()->getInvoicePdf(); return (new \App\Jobs\Entity\CreateRawPdf($invoice->invitations->first(), $invoice->company->db))->handle();
}); });
$merge = (new PdfMerge($paths->toArray()))->run(); $merge = (new PdfMerge($paths->toArray()))->run();
@ -700,7 +700,7 @@ class InvoiceController extends BaseController
} }
break; break;
case 'cancel': case 'cancel':
$invoice = $invoice->service()->handleCancellation()->deletePdf()->save(); $invoice = $invoice->service()->handleCancellation()->save();
if (! $bulk) { if (! $bulk) {
$this->itemResponse($invoice); $this->itemResponse($invoice);
} }

View File

@ -74,7 +74,7 @@ class OneTimeTokenController extends BaseController
'user_id' => $user->id, 'user_id' => $user->id,
'company_key'=> $user->company()->company_key, 'company_key'=> $user->company()->company_key,
'context' => $request->input('context'), 'context' => $request->input('context'),
'is_react' => $request->has('react') && $request->query('react') == 'true' ? true : false, 'is_react' => $request->hasHeader('X-REACT') ? true : false,
]; ];
Cache::put($hash, $data, 3600); Cache::put($hash, $data, 3600);

View File

@ -290,10 +290,14 @@ class PreviewController extends BaseController
return $maker->getCompiledHTML(); return $maker->getCompiledHTML();
} }
} catch(\Exception $e) { } catch(\Exception $e) {
// nlog($e->getMessage());
DB::connection(config('database.default'))->rollBack(); DB::connection(config('database.default'))->rollBack();
return; if (DB::connection(config('database.default'))->transactionLevel() > 0) {
DB::connection(config('database.default'))->rollBack();
}
return response()->json(['message' => 'Error generating preview. Please retry again shortly.'], 400);
} }
//if phantom js...... inject here.. //if phantom js...... inject here..

View File

@ -458,14 +458,15 @@ class ProductController extends BaseController
*/ */
public function bulk(BulkProductRequest $request) public function bulk(BulkProductRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$action = $request->input('action'); $action = $request->input('action');
$ids = $request->input('ids'); $ids = $request->input('ids');
$products = Product::withTrashed()->whereIn('id', $ids); $products = Product::withTrashed()->whereIn('id', $ids);
nlog($products->count());
if($action == 'set_tax_id'){ if($action == 'set_tax_id'){
$tax_id = $request->input('tax_id'); $tax_id = $request->input('tax_id');
@ -475,8 +476,8 @@ class ProductController extends BaseController
return $this->listResponse(Product::withTrashed()->whereIn('id', $ids)); return $this->listResponse(Product::withTrashed()->whereIn('id', $ids));
} }
$products->cursor()->each(function ($product, $key) use ($action) { $products->cursor()->each(function ($product, $key) use ($action, $user) {
if (auth()->user()->can('edit', $product)) { if ($user->can('edit', $product)) {
$this->product_repo->{$action}($product); $this->product_repo->{$action}($product);
} }
}); });

View File

@ -139,7 +139,10 @@ class PurchaseOrderController extends BaseController
*/ */
public function create(CreatePurchaseOrderRequest $request) public function create(CreatePurchaseOrderRequest $request)
{ {
$purchase_order = PurchaseOrderFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$purchase_order = PurchaseOrderFactory::create($user->company()->id, $user->id);
return $this->itemResponse($purchase_order); return $this->itemResponse($purchase_order);
} }
@ -183,7 +186,10 @@ class PurchaseOrderController extends BaseController
*/ */
public function store(StorePurchaseOrderRequest $request) public function store(StorePurchaseOrderRequest $request)
{ {
$purchase_order = $this->purchase_order_repository->save($request->all(), PurchaseOrderFactory::create(auth()->user()->company()->id, auth()->user()->id)); /** @var \App\Models\User $user */
$user = auth()->user();
$purchase_order = $this->purchase_order_repository->save($request->all(), PurchaseOrderFactory::create($user->company()->id, $user->id));
$purchase_order = $purchase_order->service() $purchase_order = $purchase_order->service()
->fillDefaults() ->fillDefaults()
@ -361,7 +367,7 @@ class PurchaseOrderController extends BaseController
$purchase_order = $purchase_order->service() $purchase_order = $purchase_order->service()
->triggeredActions($request) ->triggeredActions($request)
->touchPdf() // ->touchPdf()
->save(); ->save();
event(new PurchaseOrderWasUpdated($purchase_order, $purchase_order->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new PurchaseOrderWasUpdated($purchase_order, $purchase_order->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
@ -475,11 +481,14 @@ class PurchaseOrderController extends BaseController
*/ */
public function bulk(BulkPurchaseOrderRequest $request) public function bulk(BulkPurchaseOrderRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$action = $request->input('action'); $action = $request->input('action');
$ids = $request->input('ids'); $ids = $request->input('ids');
if (Ninja::isHosted() && (stripos($action, 'email') !== false) && !auth()->user()->company()->account->account_sms_verified) { if (Ninja::isHosted() && (stripos($action, 'email') !== false) && !$user->company()->account->account_sms_verified) {
return response(['message' => 'Please verify your account to send emails.'], 400); return response(['message' => 'Please verify your account to send emails.'], 400);
} }
@ -493,20 +502,20 @@ class PurchaseOrderController extends BaseController
* Download Purchase Order/s * Download Purchase Order/s
*/ */
if ($action == 'bulk_download' && $purchase_orders->count() >= 1) { if ($action == 'bulk_download' && $purchase_orders->count() >= 1) {
$purchase_orders->each(function ($purchase_order) { $purchase_orders->each(function ($purchase_order) use ($user){
if (auth()->user()->cannot('view', $purchase_order)) { if ($user->cannot('view', $purchase_order)) {
return response()->json(['message' => ctrans('text.access_denied')]); return response()->json(['message' => ctrans('text.access_denied')]);
} }
}); });
ZipPurchaseOrders::dispatch($purchase_orders, $purchase_orders->first()->company, auth()->user()); ZipPurchaseOrders::dispatch($purchase_orders->pluck("id")->toArray(), $purchase_orders->first()->company, auth()->user());
return response()->json(['message' => ctrans('texts.sent_message')], 200); return response()->json(['message' => ctrans('texts.sent_message')], 200);
} }
if ($action == 'bulk_print' && auth()->user()->can('view', $purchase_orders->first())) { if ($action == 'bulk_print' && $user->can('view', $purchase_orders->first())) {
$paths = $purchase_orders->map(function ($purchase_order) { $paths = $purchase_orders->map(function ($purchase_order) {
return $purchase_order->service()->getPurchaseOrderPdf(); return (new \App\Jobs\Vendor\CreatePurchaseOrderPdf($purchase_order->invitations->first()))->rawPdf();
}); });
$merge = (new PdfMerge($paths->toArray()))->run(); $merge = (new PdfMerge($paths->toArray()))->run();
@ -519,8 +528,8 @@ class PurchaseOrderController extends BaseController
/* /*
* Send the other actions to the switch * Send the other actions to the switch
*/ */
$purchase_orders->each(function ($purchase_order, $key) use ($action) { $purchase_orders->each(function ($purchase_order, $key) use ($action, $user) {
if (auth()->user()->can('edit', $purchase_order)) { if ($user->can('edit', $purchase_order)) {
$this->performAction($purchase_order, $action, true); $this->performAction($purchase_order, $action, true);
} }
}); });

View File

@ -16,6 +16,7 @@ use App\Models\Quote;
use App\Models\Client; use App\Models\Client;
use App\Models\Account; use App\Models\Account;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Project;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Factory\QuoteFactory; use App\Factory\QuoteFactory;
use App\Filters\QuoteFilters; use App\Filters\QuoteFilters;
@ -33,6 +34,7 @@ use App\Transformers\QuoteTransformer;
use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\GeneratesCounter;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use App\Transformers\InvoiceTransformer; use App\Transformers\InvoiceTransformer;
use App\Transformers\ProjectTransformer;
use App\Factory\CloneQuoteToInvoiceFactory; use App\Factory\CloneQuoteToInvoiceFactory;
use App\Factory\CloneQuoteToProjectFactory; use App\Factory\CloneQuoteToProjectFactory;
use App\Http\Requests\Quote\EditQuoteRequest; use App\Http\Requests\Quote\EditQuoteRequest;
@ -395,8 +397,8 @@ class QuoteController extends BaseController
$quote = $this->quote_repo->save($request->all(), $quote); $quote = $this->quote_repo->save($request->all(), $quote);
$quote->service() $quote->service()
->triggeredActions($request) ->triggeredActions($request);
->deletePdf(); // ->deletePdf();
event(new QuoteWasUpdated($quote, $quote->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new QuoteWasUpdated($quote, $quote->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
@ -524,16 +526,15 @@ class QuoteController extends BaseController
return response(['message' => 'Please verify your account to send emails.'], 400); return response(['message' => 'Please verify your account to send emails.'], 400);
} }
$quotes = Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get(); $quotes = Quote::query()->with('invitations')->withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
if (! $quotes) { if (! $quotes) {
return response()->json(['message' => ctrans('texts.quote_not_found')]); return response()->json(['message' => ctrans('texts.quote_not_found')]);
} }
/* /*
* Download Invoice/s * Download Quote/s
*/ */
if ($action == 'bulk_download' && $quotes->count() >= 1) { if ($action == 'bulk_download' && $quotes->count() >= 1) {
$quotes->each(function ($quote) use($user){ $quotes->each(function ($quote) use($user){
if ($user->cannot('view', $quote)) { if ($user->cannot('view', $quote)) {
@ -541,7 +542,7 @@ class QuoteController extends BaseController
} }
}); });
ZipQuotes::dispatch($quotes, $quotes->first()->company, auth()->user()); ZipQuotes::dispatch($quotes->pluck('id')->toArray(), $quotes->first()->company, auth()->user());
return response()->json(['message' => ctrans('texts.sent_message')], 200); return response()->json(['message' => ctrans('texts.sent_message')], 200);
} }
@ -556,12 +557,12 @@ class QuoteController extends BaseController
} }
}); });
return $this->listResponse(Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()); return $this->listResponse(Quote::query()->withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
} }
if ($action == 'bulk_print' && $user->can('view', $quotes->first())) { if ($action == 'bulk_print' && $user->can('view', $quotes->first())) {
$paths = $quotes->map(function ($quote) { $paths = $quotes->map(function ($quote) {
return $quote->service()->getQuotePdf(); return (new \App\Jobs\Entity\CreateRawPdf($quote->invitations->first(), $quote->company->db))->handle();
}); });
$merge = (new PdfMerge($paths->toArray()))->run(); $merge = (new PdfMerge($paths->toArray()))->run();
@ -575,18 +576,13 @@ class QuoteController extends BaseController
if ($action == 'convert_to_project') { if ($action == 'convert_to_project') {
$quotes->each(function ($quote, $key) use ($user) { $quotes->each(function ($quote, $key) use ($user) {
if ($user->can('edit', $quote)) { if ($user->can('edit', $quote)) {
$project = CloneQuoteToProjectFactory::create($quote, $user->id);
$quote->service()->convertToProject();
if (empty($project->number)) {
$project->number = $this->getNextProjectNumber($project);
}
$project->save();
$quote->project_id = $project->id;
$quote->save();
} }
}); });
return $this->listResponse(Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()); return $this->listResponse(Quote::query()->withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
} }
/* /*
@ -684,7 +680,14 @@ class QuoteController extends BaseController
private function performAction(Quote $quote, $action, $bulk = false) private function performAction(Quote $quote, $action, $bulk = false)
{ {
switch ($action) { switch ($action) {
case 'convert': case 'convert_to_project':
$this->entity_type = Project::class;
$this->entity_transformer = ProjectTransformer::class;
return $this->itemResponse($quote->service()->convertToProject());
case 'convert':
case 'convert_to_invoice': case 'convert_to_invoice':
$this->entity_type = Invoice::class; $this->entity_type = Invoice::class;
@ -692,8 +695,6 @@ class QuoteController extends BaseController
return $this->itemResponse($quote->service()->convertToInvoice()); return $this->itemResponse($quote->service()->convertToInvoice());
break;
case 'clone_to_invoice': case 'clone_to_invoice':
$this->entity_type = Invoice::class; $this->entity_type = Invoice::class;
@ -702,41 +703,38 @@ class QuoteController extends BaseController
$invoice = CloneQuoteToInvoiceFactory::create($quote, auth()->user()->id); $invoice = CloneQuoteToInvoiceFactory::create($quote, auth()->user()->id);
return $this->itemResponse($invoice); return $this->itemResponse($invoice);
break;
case 'clone_to_quote': case 'clone_to_quote':
$quote = CloneQuoteFactory::create($quote, auth()->user()->id); $quote = CloneQuoteFactory::create($quote, auth()->user()->id);
return $this->itemResponse($quote); return $this->itemResponse($quote);
break;
case 'approve': case 'approve':
if (! in_array($quote->status_id, [Quote::STATUS_SENT, Quote::STATUS_DRAFT])) { if (! in_array($quote->status_id, [Quote::STATUS_SENT, Quote::STATUS_DRAFT])) {
return response()->json(['message' => ctrans('texts.quote_unapprovable')], 400); return response()->json(['message' => ctrans('texts.quote_unapprovable')], 400);
} }
return $this->itemResponse($quote->service()->approveWithNoCoversion()->save()); return $this->itemResponse($quote->service()->approveWithNoCoversion()->save());
break;
case 'history': case 'history':
// code... // code...
break; break;
case 'download': case 'download':
//$file = $quote->pdf_file_path();
$file = $quote->service()->getQuotePdf(); $file = $quote->service()->getQuotePdf();
return response()->streamDownload(function () use ($file) { return response()->streamDownload(function () use ($file) {
echo Storage::get($file); echo Storage::get($file);
}, basename($file), ['Content-Type' => 'application/pdf']); }, basename($file), ['Content-Type' => 'application/pdf']);
break;
case 'restore': case 'restore':
$this->quote_repo->restore($quote); $this->quote_repo->restore($quote);
if (! $bulk) { if (! $bulk) {
return $this->itemResponse($quote); return $this->itemResponse($quote);
} }
break; break;
case 'archive': case 'archive':
$this->quote_repo->archive($quote); $this->quote_repo->archive($quote);
@ -754,16 +752,11 @@ class QuoteController extends BaseController
break; break;
case 'email': case 'email':
$quote->service()->sendEmail();
return response()->json(['message'=> ctrans('texts.sent_message')], 200);
break;
case 'send_email': case 'send_email':
$quote->service()->sendEmail(); $quote->service()->sendEmail();
return response()->json(['message'=> ctrans('texts.sent_message')], 200); return response()->json(['message'=> ctrans('texts.sent_message')], 200);
break;
case 'mark_sent': case 'mark_sent':
$quote->service()->markSent()->save(); $quote->service()->markSent()->save();

View File

@ -153,7 +153,10 @@ class RecurringInvoiceController extends BaseController
*/ */
public function create(CreateRecurringInvoiceRequest $request) public function create(CreateRecurringInvoiceRequest $request)
{ {
$recurring_invoice = RecurringInvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$recurring_invoice = RecurringInvoiceFactory::create($user->company()->id, $user->id);
return $this->itemResponse($recurring_invoice); return $this->itemResponse($recurring_invoice);
} }
@ -199,7 +202,10 @@ class RecurringInvoiceController extends BaseController
*/ */
public function store(StoreRecurringInvoiceRequest $request) public function store(StoreRecurringInvoiceRequest $request)
{ {
$recurring_invoice = $this->recurring_invoice_repo->save($request->all(), RecurringInvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id)); /** @var \App\Models\User $user */
$user = auth()->user();
$recurring_invoice = $this->recurring_invoice_repo->save($request->all(), RecurringInvoiceFactory::create($user->company()->id, $user->id));
$recurring_invoice->service() $recurring_invoice->service()
->triggeredActions($request) ->triggeredActions($request)
@ -380,7 +386,7 @@ class RecurringInvoiceController extends BaseController
$recurring_invoice->service() $recurring_invoice->service()
->triggeredActions($request) ->triggeredActions($request)
->deletePdf() // ->deletePdf()
->save(); ->save();
event(new RecurringInvoiceWasUpdated($recurring_invoice, $recurring_invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new RecurringInvoiceWasUpdated($recurring_invoice, $recurring_invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
@ -405,18 +411,21 @@ class RecurringInvoiceController extends BaseController
*/ */
public function bulk(BulkRecurringInvoiceRequest $request) public function bulk(BulkRecurringInvoiceRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$percentage_increase = request()->has('percentage_increase') ? request()->input('percentage_increase') : 0; $percentage_increase = request()->has('percentage_increase') ? request()->input('percentage_increase') : 0;
if (in_array($request->action, ['increase_prices', 'update_prices'])) { if (in_array($request->action, ['increase_prices', 'update_prices'])) {
UpdateRecurring::dispatch($request->ids, auth()->user()->company(), auth()->user(), $request->action, $percentage_increase); UpdateRecurring::dispatch($request->ids, $user->company(), $user, $request->action, $percentage_increase);
return response()->json(['message' => 'Update in progress.'], 200); return response()->json(['message' => 'Update in progress.'], 200);
} }
$recurring_invoices = RecurringInvoice::withTrashed()->find($request->ids); $recurring_invoices = RecurringInvoice::withTrashed()->find($request->ids);
$recurring_invoices->each(function ($recurring_invoice, $key) use ($request) { $recurring_invoices->each(function ($recurring_invoice, $key) use ($request, $user) {
if (auth()->user()->can('edit', $recurring_invoice)) { if ($user->can('edit', $recurring_invoice)) {
$this->performAction($recurring_invoice, $request->action, true); $this->performAction($recurring_invoice, $request->action, true);
} }
}); });

View File

@ -14,6 +14,7 @@ namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin; use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\ActivityExport; use App\Export\CSV\ActivityExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
@ -31,14 +32,27 @@ class ActivityReportController extends BaseController
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ActivityExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), ActivityExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new ActivityExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ActivityExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new ActivityExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\ContactExport; use App\Export\CSV\ContactExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ClientContactReportController extends BaseController class ClientContactReportController extends BaseController
{ {
@ -62,13 +63,29 @@ class ClientContactReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ContactExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), ContactExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new ContactExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ContactExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
// expect a list of visible fields, or use the default
$export = new ContactExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,13 +11,14 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Export\CSV\ClientExport; use App\Export\CSV\ClientExport;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ClientReportController extends BaseController class ClientReportController extends BaseController
{ {
@ -63,14 +64,26 @@ class ClientReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ClientExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), ClientExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default
$export = new ClientExport(auth()->user()->company(), $request->all()); // expect a list of visible fields, or use the default
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ClientExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new ClientExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\DocumentExport; use App\Export\CSV\DocumentExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class DocumentReportController extends BaseController class DocumentReportController extends BaseController
{ {
@ -62,14 +63,27 @@ class DocumentReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), DocumentExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), DocumentExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new DocumentExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), DocumentExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new DocumentExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,13 +11,14 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\ExpenseExport; use App\Export\CSV\ExpenseExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ExpenseReportController extends BaseController class ExpenseReportController extends BaseController
{ {
@ -63,14 +64,27 @@ class ExpenseReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ExpenseExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), ExpenseExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new ExpenseExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ExpenseExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new ExpenseExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Export\CSV\InvoiceItemExport; use App\Export\CSV\InvoiceItemExport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class InvoiceItemReportController extends BaseController class InvoiceItemReportController extends BaseController
{ {
@ -62,14 +63,25 @@ class InvoiceItemReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), InvoiceItemExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), InvoiceItemExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default
$export = new InvoiceItemExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), InvoiceItemExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new InvoiceItemExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\InvoiceExport; use App\Export\CSV\InvoiceExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class InvoiceReportController extends BaseController class InvoiceReportController extends BaseController
{ {
@ -62,14 +63,26 @@ class InvoiceReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), InvoiceExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), InvoiceExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default
$export = new InvoiceExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), InvoiceExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
// expect a list of visible fields, or use the default
$export = new InvoiceExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,13 +11,14 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\PaymentExport; use App\Export\CSV\PaymentExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class PaymentReportController extends BaseController class PaymentReportController extends BaseController
{ {
@ -63,14 +64,26 @@ class PaymentReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), PaymentExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), PaymentExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new PaymentExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), PaymentExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new PaymentExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,13 +11,14 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\ProductExport; use App\Export\CSV\ProductExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ProductReportController extends BaseController class ProductReportController extends BaseController
{ {
@ -63,14 +64,27 @@ class ProductReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ProductExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), ProductExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new ProductExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ProductExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new ProductExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,11 +11,12 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use App\Export\CSV\PurchaseOrderItemExport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Export\CSV\PurchaseOrderItemExport;
use App\Http\Requests\Report\GenericReportRequest;
class PurchaseOrderItemReportController extends BaseController class PurchaseOrderItemReportController extends BaseController
{ {
@ -30,14 +31,26 @@ class PurchaseOrderItemReportController extends BaseController
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), PurchaseOrderItemExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), PurchaseOrderItemExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new PurchaseOrderItemExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), PurchaseOrderItemExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new PurchaseOrderItemExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,11 +11,12 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Export\CSV\PurchaseOrderExport; use App\Export\CSV\PurchaseOrderExport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
class PurchaseOrderReportController extends BaseController class PurchaseOrderReportController extends BaseController
{ {
@ -30,14 +31,29 @@ class PurchaseOrderReportController extends BaseController
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), PurchaseOrderExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), PurchaseOrderExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new PurchaseOrderExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), PurchaseOrderExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new PurchaseOrderExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Export\CSV\QuoteItemExport; use App\Export\CSV\QuoteItemExport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class QuoteItemReportController extends BaseController class QuoteItemReportController extends BaseController
{ {
@ -62,14 +63,26 @@ class QuoteItemReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), QuoteItemExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), QuoteItemExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new QuoteItemExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), QuoteItemExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new QuoteItemExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Export\CSV\QuoteExport; use App\Export\CSV\QuoteExport;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class QuoteReportController extends BaseController class QuoteReportController extends BaseController
{ {
@ -62,14 +63,26 @@ class QuoteReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), QuoteExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), QuoteExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new QuoteExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), QuoteExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new QuoteExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use App\Export\CSV\RecurringInvoiceExport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Export\CSV\RecurringInvoiceExport;
use App\Http\Requests\Report\GenericReportRequest;
class RecurringInvoiceReportController extends BaseController class RecurringInvoiceReportController extends BaseController
{ {
@ -31,14 +32,26 @@ class RecurringInvoiceReportController extends BaseController
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), RecurringInvoiceExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), RecurringInvoiceExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new RecurringInvoiceExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), RecurringInvoiceExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new RecurringInvoiceExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Export\CSV\TaskExport; use App\Export\CSV\TaskExport;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class TaskReportController extends BaseController class TaskReportController extends BaseController
{ {
@ -62,14 +63,26 @@ class TaskReportController extends BaseController
*/ */
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), TaskExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), TaskExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new TaskExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), TaskExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new TaskExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -11,11 +11,12 @@
namespace App\Http\Controllers\Reports; namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Export\CSV\VendorExport; use App\Export\CSV\VendorExport;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest; use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
class VendorReportController extends BaseController class VendorReportController extends BaseController
{ {
@ -30,14 +31,26 @@ class VendorReportController extends BaseController
public function __invoke(GenericReportRequest $request) public function __invoke(GenericReportRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) { if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), VendorExport::class, $this->filename); SendToAdmin::dispatch($user->company(), $request->all(), VendorExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200); return response()->json(['message' => 'working...'], 200);
} }
// expect a list of visible fields, or use the default // expect a list of visible fields, or use the default
$export = new VendorExport(auth()->user()->company(), $request->all()); if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), VendorExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new VendorExport($user->company(), $request->all());
$csv = $export->run(); $csv = $export->run();

View File

@ -15,7 +15,10 @@ class SchedulerController extends Controller
{ {
public function index() public function index()
{ {
if (auth()->user()->company()->account->latest_version == '0.0.0') { /** @var \App\Models\User $user */
$user = auth()->user();
if ($user->company()->account->latest_version == '0.0.0') {
return response()->json(['message' => ctrans('texts.scheduler_has_never_run')], 400); return response()->json(['message' => ctrans('texts.scheduler_has_never_run')], 400);
} else { } else {
return response()->json(['message' => ctrans('texts.scheduler_has_run')], 200); return response()->json(['message' => ctrans('texts.scheduler_has_run')], 200);

View File

@ -0,0 +1,207 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers;
use App\Http\Requests\Search\GenericSearchRequest;
use App\Models\Client;
use App\Models\Invoice;
use App\Models\User;
class SearchController extends Controller
{
private array $clients = [];
private array $client_contacts = [];
private array $invoices = [];
public function __invoke(GenericSearchRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$this->clientMap($user);
$this->invoiceMap($user);
return response()->json([
'clients' => $this->clients,
'client_contacts' => $this->client_contacts,
'invoices' => $this->invoices,
'settings' => $this->settingsMap(),
], 200);
}
private function clientMap(User $user)
{
$clients = Client::query()
->company()
->where('is_deleted', 0)
->when(!$user->hasPermission('view_all') || !$user->hasPermission('view_client'), function ($query) use ($user) {
$query->where('user_id', $user->id);
})
->orderBy('id', 'desc')
->take(1000)
->get();
foreach($clients as $client) {
$this->clients[] = [
'name' => $client->present()->name(),
'type' => '/client',
'id' => $client->hashed_id,
'path' => "/clients/{$client->hashed_id}/edit"
];
$client->contacts->each(function ($contact) {
$this->client_contacts[] = [
'name' => $contact->present()->search_display(),
'type' => '/client_contact',
'id' => $contact->hashed_id,
'path' => "/clients/{$contact->hashed_id}"
];
});
}
}
private function invoiceMap(User $user)
{
$invoices = Invoice::query()
->company()
->with('client')
->where('is_deleted', 0)
->whereHas('client', function ($q) {
$q->where('is_deleted', 0);
})
->when(!$user->hasPermission('view_all') || !$user->hasPermission('view_invoice'), function ($query) use ($user) {
$query->where('user_id', $user->id);
})
->orderBy('id', 'desc')
->take(3000)
->get();
foreach($invoices as $invoice) {
$this->invoices[] = [
'name' => $invoice->client->present()->name() . ' - ' . $invoice->number,
'type' => '/invoice',
'id' => $invoice->hashed_id,
'path' => "/invoices/{$invoice->hashed_id}/edit"
];
}
}
private function settingsMap()
{
$paths = [
'user_details' => '/settings/user_details',
'password' => '/settings/user_details/password',
'connect' => '/settings/user_details/connect',
'accent_color' => '/settings/user_details/accent_color',
'notifications' => '/settings/user_details/notifications',
'enable_two_factor' => '/settings/user_details/enable_two_factor',
'custom_fields' => '/settings/user_details/custom_fields',
'preferences' => '/settings/user_details/preferences',
'company_details' => '/settings/company_details',
'company_details,details' => '/settings/company_details/details',
'company_details,address' => '/settings/company_details/address',
'company_details,logo' => '/settings/company_details/logo',
'company_details,defaults' => '/settings/company_details/defaults',
'company_details,documents' => '/settings/company_details/documents',
'company_details,custom_fields' => '/settings/company_details/custom_fields',
'localization' => '/settings/localization',
'localization,custom_labels' => '/settings/localization/custom_labels',
'online_payments' => '/settings/online_payments',
'tax_settings' => '/settings/tax_settings',
'product_settings' => '/settings/product_settings',
'task_settings' => '/settings/task_settings',
'expense_settings' => '/settings/expense_settings',
'workflow_settings' => '/settings/workflow_settings',
'import_export' => '/settings/import_export',
'account_management' => '/settings/account_management',
'account_management,overview' => '/settings/account_management/overview',
'account_management,enabled_modules' => '/settings/account_management/enabled_modules',
'account_management,integrations' => '/settings/account_management/integrations',
'account_management,security_settings' => '/settings/account_management/security_settings',
'account_management,danger_zone' => '/settings/account_management/danger_zone',
'backup_restore' => '/settings/backup_restore',
'backup_restore,restore' => '/settings/backup_restore/restore',
'backup_restore,backup' => '/settings/backup_restore/backup',
'custom_fields' => '/settings/custom_fields',
'custom_fields,company' => '/settings/custom_fields/company',
'custom_fields,clients' => '/settings/custom_fields/clients',
'custom_fields,products' => '/settings/custom_fields/products',
'custom_fields,invoices' => '/settings/custom_fields/invoices',
'custom_fields,payments' => '/settings/custom_fields/payments',
'custom_fields,projects' => '/settings/custom_fields/projects',
'custom_fields,tasks' => '/settings/custom_fields/tasks',
'custom_fields,vendors' => '/settings/custom_fields/vendors',
'custom_fields,expenses' => '/settings/custom_fields/expenses',
'custom_fields,users' => '/settings/custom_fields/users',
'custom_fields,quotes' => '/settings/custom_fields/quotes',
'custom_fields,credits' => '/settings/custom_fields/credits',
'generated_numbers' => '/settings/generated_numbers',
'client_portal' => '/settings/client_portal',
'email_settings' => '/settings/email_settings',
'templates_and_reminders' => '/settings/templates_and_reminders',
'bank_accounts' => '/settings/bank_accounts',
'group_settings' => '/settings/group_settings',
'subscriptions' => '/settings/subscriptions',
'schedules' => '/settings/schedules',
'users' => '/settings/users',
'system_logs' => '/settings/system_logs',
'payment_terms' => '/settings/payment_terms',
'tax_rates' => '/settings/tax_rates',
'task_statuses' => '/settings/task_statuses',
'expense_categories' => '/settings/expense_categories',
'integrations' => '/settings/integrations',
'integrations,api_tokens' => '/settings/integrations/api_tokens',
'integrations,api_webhooks' => '/settings/integrations/api_webhooks',
'integrations,analytics' => '/settings/integrations/analytics',
'gateways' => '/settings/gateways',
'gateways,create' => '/settings/gateways/create',
'bank_accounts,transaction_rules' => '/settings/bank_accounts/transaction_rules',
'bank_accounts,transaction_rules/create' => '/settings/bank_accounts/transaction_rules/create',
];
$data = [];
foreach($paths as $key => $value) {
$translation = '';
foreach(explode(",", $key) as $transkey) {
$translation .= ctrans("texts.{$transkey}")." ";
}
$translation = rtrim($translation, " ");
$data[] = [
'id' => $translation,
'path' => $value,
'type' => $transkey,
'name' => $translation,
];
}
ksort($data);
return $data;
}
}

View File

@ -11,13 +11,14 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Exceptions\FilePermissionsFailure;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Models\Company;
use App\Utils\Traits\AppSetup; use App\Utils\Traits\AppSetup;
use App\Utils\Traits\ClientGroupSettingsSaver;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use App\Exceptions\FilePermissionsFailure;
use Illuminate\Foundation\Bus\DispatchesJobs;
use App\Utils\Traits\ClientGroupSettingsSaver;
class SelfUpdateController extends BaseController class SelfUpdateController extends BaseController
{ {
@ -109,11 +110,33 @@ class SelfUpdateController extends BaseController
$this->buildCache(true); $this->buildCache(true);
$this->runModelChecks();
nlog('Called Artisan commands'); nlog('Called Artisan commands');
return response()->json(['message' => 'Update completed'], 200); return response()->json(['message' => 'Update completed'], 200);
} }
private function runModelChecks()
{
Company::query()
->cursor()
->each(function ($company){
$settings = $company->settings;
if(property_exists($settings->pdf_variables, 'purchase_order_details'))
return;
$pdf_variables = $settings->pdf_variables;
$pdf_variables->purchase_order_details = [];
$settings->pdf_variables = $pdf_variables;
$company->settings = $settings;
$company->save();
});
}
private function clearCacheDir() private function clearCacheDir()
{ {
$directoryIterator = new \RecursiveDirectoryIterator(base_path('bootstrap/cache'), \RecursiveDirectoryIterator::SKIP_DOTS); $directoryIterator = new \RecursiveDirectoryIterator(base_path('bootstrap/cache'), \RecursiveDirectoryIterator::SKIP_DOTS);

View File

@ -182,7 +182,8 @@ class SetupController extends Controller
* @return Application|ResponseFactory|JsonResponse|Response * @return Application|ResponseFactory|JsonResponse|Response
*/ */
public function checkDB(CheckDatabaseRequest $request) public function checkDB(CheckDatabaseRequest $request)
{nlog("trying"); {
try { try {
$status = SystemHealth::dbCheck($request); $status = SystemHealth::dbCheck($request);

View File

@ -56,7 +56,7 @@ class StaticController extends BaseController
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$user = auth()->user(); $user = auth()->user();
$response = Statics::company($user->company()->getLocale()); $response = Statics::company($user->getLocale() ?? $user->company()->getLocale());
return response()->json($response, 200, ['Content-type'=> 'application/json; charset=utf-8'], JSON_PRETTY_PRINT); return response()->json($response, 200, ['Content-type'=> 'application/json; charset=utf-8'], JSON_PRETTY_PRINT);
} }

View File

@ -15,11 +15,9 @@ use App\DataMapper\FeesAndLimits;
use App\Factory\CompanyGatewayFactory; use App\Factory\CompanyGatewayFactory;
use App\Http\Requests\StripeConnect\InitializeStripeConnectRequest; use App\Http\Requests\StripeConnect\InitializeStripeConnectRequest;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Client;
use App\Models\Company; use App\Models\Company;
use App\Models\CompanyGateway; use App\Models\CompanyGateway;
use App\Models\GatewayType; use App\Models\GatewayType;
use App\PaymentDrivers\Stripe\Jobs\StripeWebhook;
use Stripe\Exception\ApiErrorException; use Stripe\Exception\ApiErrorException;
class StripeConnectController extends BaseController class StripeConnectController extends BaseController
@ -124,12 +122,27 @@ class StripeConnectController extends BaseController
$company_gateway->setConfig($payload); $company_gateway->setConfig($payload);
$company_gateway->save(); $company_gateway->save();
try{
$stripe = $company_gateway->driver()->init();
$a = \Stripe\Account::retrieve($response->stripe_user_id, $stripe->stripe_connect_auth);
if($a->business_name ?? false) {
$company_gateway->label = substr("Stripe - {$a->business_name}", 0, 250);
$company_gateway->save();
}
}
catch(\Exception $e){
nlog("could not harvest stripe company name");
}
// nlog("Stripe Connect Redirect URI = {$redirect_uri}");
// StripeWebhook::dispatch($company->company_key, $company_gateway->id); // StripeWebhook::dispatch($company->company_key, $company_gateway->id);
// if(isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react']) { if(isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react']) {
$redirect_uri = 'https://app.invoicing.co/#/settings/online_payments'; $redirect_uri = 'https://app.invoicing.co/#/settings/online_payments';
// } else { } else {
// $redirect_uri = 'https://invoicing.co/stripe/completed'; $redirect_uri = 'https://invoicing.co/stripe/completed';
// } }
//response here //response here
return view('auth.connect.completed', ['url' => $redirect_uri]); return view('auth.connect.completed', ['url' => $redirect_uri]);

View File

@ -73,7 +73,10 @@ class TaskStatusController extends BaseController
*/ */
public function create(CreateTaskStatusRequest $request) public function create(CreateTaskStatusRequest $request)
{ {
$task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$task_status = TaskStatusFactory::create($user->company()->id, auth()->user()->id);
return $this->itemResponse($task_status); return $this->itemResponse($task_status);
} }
@ -87,8 +90,10 @@ class TaskStatusController extends BaseController
*/ */
public function store(StoreTaskStatusRequest $request) public function store(StoreTaskStatusRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id); $task_status = TaskStatusFactory::create($user->company()->id, auth()->user()->id);
$task_status->fill($request->all()); $task_status->fill($request->all());
$task_status->save(); $task_status->save();

View File

@ -125,7 +125,10 @@ class TaxRateController extends BaseController
*/ */
public function create(CreateTaxRateRequest $request) public function create(CreateTaxRateRequest $request)
{ {
$tax_rate = TaxRateFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$tax_rate = TaxRateFactory::create($user->company()->id, auth()->user()->id);
return $this->itemResponse($tax_rate); return $this->itemResponse($tax_rate);
} }
@ -138,7 +141,10 @@ class TaxRateController extends BaseController
*/ */
public function store(StoreTaxRateRequest $request) public function store(StoreTaxRateRequest $request)
{ {
$tax_rate = TaxRateFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$tax_rate = TaxRateFactory::create($user->company()->id, $user->id);
$tax_rate->fill($request->all()); $tax_rate->fill($request->all());
$tax_rate->save(); $tax_rate->save();
@ -417,15 +423,33 @@ class TaxRateController extends BaseController
*/ */
public function bulk() public function bulk()
{ {
$action = request()->input('action'); /** @var \App\Models\User $user */
$user = auth()->user();
$action = request()->input('action');
$ids = request()->input('ids'); $ids = request()->input('ids');
$tax_rates = TaxRate::withTrashed()->find($this->transformKeys($ids)); $tax_rates = TaxRate::withTrashed()->find($this->transformKeys($ids));
$tax_rates->each(function ($tax_rate, $key) use ($action) { $tax_rates->each(function ($tax_rate, $key) use ($action, $user) {
if (auth()->user()->can('edit', $tax_rate)) { if ($user->can('edit', $tax_rate)) {
if(in_array($action, ['archive','delete'])) {
$settings = $user->company()->settings;
foreach(['tax_name1','tax_name2','tax_name3'] as $tax_name) {
if($settings->{$tax_name} == $tax_rate->name) {
$settings->{$tax_name} = '';
$settings->{str_replace("name", "rate", $tax_name)} = '';
}
}
$user->company()->saveSettings($settings, $user->company());
}
$this->base_repo->{$action}($tax_rate); $this->base_repo->{$action}($tax_rate);
} }
}); });

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