From 86a6910e255e4c29c1bf6c387b2817857d5d7c84 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 12 Sep 2023 11:22:59 +1000 Subject: [PATCH] Fixes for Recurring Invoice Export --- app/Export/CSV/BaseExport.php | 51 +++++++- app/Export/CSV/InvoiceExport.php | 3 +- app/Export/CSV/InvoiceItemExport.php | 32 +---- app/Export/CSV/PurchaseOrderItemExport.php | 32 +---- app/Export/CSV/QuoteExport.php | 5 +- app/Export/CSV/QuoteItemExport.php | 25 ++-- app/Export/CSV/RecurringInvoiceExport.php | 116 +++++++----------- .../Reports/QuoteItemReportController.php | 23 +++- .../RecurringInvoiceReportController.php | 27 ++-- 9 files changed, 156 insertions(+), 158 deletions(-) diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index 63b1ec5c3c11..0fa46ba477a0 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -11,8 +11,10 @@ namespace App\Export\CSV; +use App\Models\Quote; use App\Utils\Number; use App\Models\Client; +use App\Models\Credit; use App\Utils\Helpers; use App\Models\Company; use App\Models\Expense; @@ -22,6 +24,7 @@ use App\Models\Document; use League\Fractal\Manager; use App\Models\ClientContact; use App\Models\PurchaseOrder; +use App\Models\RecurringInvoice; use Illuminate\Support\Carbon; use App\Utils\Traits\MakesHash; use App\Transformers\TaskTransformer; @@ -1037,9 +1040,12 @@ class BaseExport $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', @@ -1066,4 +1072,47 @@ class BaseExport 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; + } + } diff --git a/app/Export/CSV/InvoiceExport.php b/app/Export/CSV/InvoiceExport.php index 4123940a7695..f8cc1cfe9348 100644 --- a/app/Export/CSV/InvoiceExport.php +++ b/app/Export/CSV/InvoiceExport.php @@ -20,7 +20,7 @@ use App\Libraries\MultiDB; use App\Export\CSV\BaseExport; use Illuminate\Support\Facades\App; use App\Transformers\InvoiceTransformer; -use Illuminate\Contracts\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Builder; class InvoiceExport extends BaseExport { @@ -95,7 +95,6 @@ class InvoiceExport extends BaseExport //insert the header $this->csv->insertOne($this->buildHeader()); - $query->cursor() ->each(function ($invoice) { $this->csv->insertOne($this->buildRow($invoice)); diff --git a/app/Export/CSV/InvoiceItemExport.php b/app/Export/CSV/InvoiceItemExport.php index 1c420edbfbd6..4db01226725d 100644 --- a/app/Export/CSV/InvoiceItemExport.php +++ b/app/Export/CSV/InvoiceItemExport.php @@ -84,14 +84,13 @@ class InvoiceItemExport extends BaseExport return ['identifier' => $value, 'display_value' => $headerdisplay[$value]]; })->toArray(); - nlog($query->count()); $query->cursor() ->each(function ($resource) { $this->iterateItems($resource); foreach($this->storage_array as $row) { - $this->storage_item_array[] = $this->processMetaData($row, $resource); + $this->storage_item_array[] = $this->processItemMetaData($row, $resource); } $this->storage_array = []; @@ -204,33 +203,4 @@ class InvoiceItemExport extends BaseExport return $entity; } - public function processMetaData(array $row, $resource): array - { - $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; - } - } diff --git a/app/Export/CSV/PurchaseOrderItemExport.php b/app/Export/CSV/PurchaseOrderItemExport.php index a117279c2588..8859a431ce3b 100644 --- a/app/Export/CSV/PurchaseOrderItemExport.php +++ b/app/Export/CSV/PurchaseOrderItemExport.php @@ -80,10 +80,8 @@ class PurchaseOrderItemExport extends BaseExport ->each(function ($resource) { $this->iterateItems($resource); - $this->storage_item_array = []; - foreach($this->storage_array as $row) { - $this->storage_item_array[] = $this->processMetaData($row, $resource); + $this->storage_item_array[] = $this->processItemMetaData($row, $resource); } $this->storage_array = []; @@ -201,32 +199,4 @@ class PurchaseOrderItemExport extends BaseExport return $entity; } - public function processMetaData(array $row, $resource): array - { - $entity = 'purchase_order'; - $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; - } } diff --git a/app/Export/CSV/QuoteExport.php b/app/Export/CSV/QuoteExport.php index a84becb20eb2..de2813608537 100644 --- a/app/Export/CSV/QuoteExport.php +++ b/app/Export/CSV/QuoteExport.php @@ -16,7 +16,7 @@ use App\Models\Company; use App\Models\Quote; use App\Transformers\QuoteTransformer; use App\Utils\Ninja; -use Illuminate\Contracts\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -80,7 +80,8 @@ class QuoteExport extends BaseExport $report = $query->cursor() ->map(function ($resource) { - return $this->buildRow($resource); + $row = $this->buildRow($resource); + return $this->processMetaData($row, $resource); })->toArray(); return array_merge(['columns' => $header], $report); diff --git a/app/Export/CSV/QuoteItemExport.php b/app/Export/CSV/QuoteItemExport.php index a2f78d16ce41..774b50a774b2 100644 --- a/app/Export/CSV/QuoteItemExport.php +++ b/app/Export/CSV/QuoteItemExport.php @@ -16,7 +16,7 @@ use App\Models\Company; use App\Models\Quote; use App\Transformers\QuoteTransformer; use App\Utils\Ninja; -use Illuminate\Contracts\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -29,7 +29,8 @@ class QuoteItemExport extends BaseExport public Writer $csv; - private array $storage_array; + private array $storage_array = []; + private array $storage_item_array = []; private array $decorate_keys = [ 'client', @@ -77,12 +78,20 @@ class QuoteItemExport extends BaseExport return ['identifier' => $value, 'display_value' => $headerdisplay[$value]]; })->toArray(); - $query->cursor() - ->each(function ($resource) { - $this->iterateItems($resource); - }); - - return array_merge(['columns' => $header], $this->storage_array); + $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); + } diff --git a/app/Export/CSV/RecurringInvoiceExport.php b/app/Export/CSV/RecurringInvoiceExport.php index 330f29695c83..8daf3388ca19 100644 --- a/app/Export/CSV/RecurringInvoiceExport.php +++ b/app/Export/CSV/RecurringInvoiceExport.php @@ -16,6 +16,7 @@ use App\Models\Company; use App\Models\RecurringInvoice; use App\Transformers\RecurringInvoiceTransformer; use App\Utils\Ninja; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -28,55 +29,6 @@ class RecurringInvoiceExport extends BaseExport 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) { $this->company = $company; @@ -84,7 +36,7 @@ class RecurringInvoiceExport extends BaseExport $this->invoice_transformer = new RecurringInvoiceTransformer(); } - public function run() + public function init(): Builder { MultiDB::setDb($this->company->db); App::forgetInstance('translator'); @@ -92,23 +44,33 @@ class RecurringInvoiceExport extends BaseExport $t = app('translator'); $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) { - $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() ->withTrashed() - ->with('client')->where('company_id', $this->company->id) + ->with('client') + ->where('company_id', $this->company->id) ->where('is_deleted', 0); $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 ($invoice) { $this->csv->insertOne($this->buildRow($invoice)); @@ -117,6 +79,27 @@ class RecurringInvoiceExport extends BaseExport 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' => $value, '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 { $transformed_invoice = $this->invoice_transformer->transform($invoice); @@ -124,22 +107,13 @@ class RecurringInvoiceExport extends BaseExport $entity = []; foreach (array_values($this->input['report_keys']) as $key) { - $keyval = array_search($key, $this->entity_keys); - if(!$keyval) { - $keyval = array_search(str_replace("recurring_invoice.", "", $key), $this->entity_keys) ?? $key; - } + $parts = explode('.', $key); - 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]; + if (is_array($parts) && $parts[0] == 'recurring_invoice' && array_key_exists($parts[1], $transformed_invoice)) { + $entity[$key] = $transformed_invoice[$parts[1]]; } else { - $entity[$keyval] = $this->resolveKey($keyval, $invoice, $this->invoice_transformer); + $entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer); } } diff --git a/app/Http/Controllers/Reports/QuoteItemReportController.php b/app/Http/Controllers/Reports/QuoteItemReportController.php index 66fb6c5a5fe1..78295f1ddc7c 100644 --- a/app/Http/Controllers/Reports/QuoteItemReportController.php +++ b/app/Http/Controllers/Reports/QuoteItemReportController.php @@ -11,12 +11,13 @@ 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\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; -use App\Jobs\Report\SendToAdmin; -use App\Utils\Traits\MakesHash; -use Illuminate\Http\Response; class QuoteItemReportController extends BaseController { @@ -62,14 +63,26 @@ class QuoteItemReportController extends BaseController */ public function __invoke(GenericReportRequest $request) { + /** @var \App\Models\User $user */ + $user = auth()->user(); + 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); } // 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(); diff --git a/app/Http/Controllers/Reports/RecurringInvoiceReportController.php b/app/Http/Controllers/Reports/RecurringInvoiceReportController.php index eaae55bd1351..26eb279106f2 100644 --- a/app/Http/Controllers/Reports/RecurringInvoiceReportController.php +++ b/app/Http/Controllers/Reports/RecurringInvoiceReportController.php @@ -11,12 +11,13 @@ 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 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 { @@ -31,14 +32,26 @@ class RecurringInvoiceReportController extends BaseController public function __invoke(GenericReportRequest $request) { + /** @var \App\Models\User $user */ + $user = auth()->user(); + 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); } // 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();