diff --git a/app/Export/CSV/ActivityExport.php b/app/Export/CSV/ActivityExport.php index 21aa0ecb0979..4ae02fb63e4e 100644 --- a/app/Export/CSV/ActivityExport.php +++ b/app/Export/CSV/ActivityExport.php @@ -20,6 +20,7 @@ use App\Libraries\MultiDB; use App\Models\DateFormat; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\App; +use Illuminate\Database\Eloquent\Builder; use App\Transformers\ActivityTransformer; class ActivityExport extends BaseExport @@ -39,10 +40,6 @@ class ActivityExport extends BaseExport 'address' => 'address', ]; - private array $decorate_keys = [ - - ]; - public function __construct(Company $company, array $input) { $this->company = $company; @@ -50,45 +47,27 @@ class ActivityExport extends BaseExport $this->entity_transformer = new ActivityTransformer(); } - public function run() + public function returnJson() { - MultiDB::setDb($this->company->db); - App::forgetInstance('translator'); - App::setLocale($this->company->locale()); - $t = app('translator'); - $t->replace(Ninja::transformTranslations($this->company->settings)); + $query = $this->init(); - $this->date_format = DateFormat::find($this->company->settings->date_format_id)->format; + $headerdisplay = $this->buildHeader(); - //load the CSV document from a string - $this->csv = Writer::createFromString(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ + return ['identifier' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); - ksort($this->entity_keys); - - if (count($this->input['report_keys']) == 0) { - $this->input['report_keys'] = array_values($this->entity_keys); - } - - //insert the header - $this->csv->insertOne($this->buildHeader()); - - $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(); + $report = $query->cursor() + ->map(function ($credit) { + return $this->buildActivityRow($credit); + })->toArray(); + + return array_merge(['columns' => $header], $report); } - private function buildRow(Activity $activity) + private function buildActivityRow(Activity $activity): array { - - $this->csv->insertOne([ + return [ Carbon::parse($activity->created_at)->format($this->date_format), ctrans("texts.activity_{$activity->activity_type_id}",[ 'client' => $activity->client ? $activity->client->present()->name() : '', @@ -108,7 +87,57 @@ class ActivityExport extends BaseExport 'recurring_expense' => $activity->recurring_expense ? $activity->recurring_expense->number : '', ]), $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)); } diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index e4c743923c4c..6be20cafa90f 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -13,6 +13,7 @@ namespace App\Export\CSV; use App\Utils\Number; use App\Models\Client; +use App\Utils\Helpers; use App\Models\Company; use App\Models\Expense; use App\Models\Invoice; @@ -28,7 +29,7 @@ use League\Fractal\Serializer\ArraySerializer; class BaseExport { use MakesHash; - + public Company $company; public array $input; @@ -43,8 +44,6 @@ class BaseExport public string $client_description = 'All Clients'; - public array $forced_keys = []; - protected array $vendor_report_keys = [ 'address1' => 'vendor.address1', 'address2' => 'vendor.address2', @@ -134,6 +133,7 @@ class BaseExport "private_notes" => "invoice.private_notes", "uses_inclusive_taxes" => "invoice.uses_inclusive_taxes", "is_amount_discount" => "invoice.is_amount_discount", + "discount" => "invoice.discount", "partial" => "invoice.partial", "partial_due_date" => "invoice.partial_due_date", "surcharge1" => "invoice.custom_surcharge1", @@ -144,6 +144,16 @@ class BaseExport "tax_amount" => "invoice.total_taxes", "assigned_user" => "invoice.assigned_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 = [ @@ -161,6 +171,7 @@ class BaseExport "private_notes" => "recurring_invoice.private_notes", "uses_inclusive_taxes" => "recurring_invoice.uses_inclusive_taxes", "is_amount_discount" => "recurring_invoice.is_amount_discount", + "discount" => "recurring_invoice.discount", "partial" => "recurring_invoice.partial", "partial_due_date" => "recurring_invoice.partial_due_date", "surcharge1" => "recurring_invoice.custom_surcharge1", @@ -172,17 +183,23 @@ class BaseExport "assigned_user" => "recurring_invoice.assigned_user_id", "user" => "recurring_invoice.user_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 = [ 'amount' => 'purchase_order.amount', 'balance' => 'purchase_order.balance', '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_value2' => 'purchase_order.custom_value2', 'custom_value3' => 'purchase_order.custom_value3', @@ -211,17 +228,37 @@ class BaseExport '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', + ]; + protected array $item_report_keys = [ "quantity" => "item.quantity", "cost" => "item.cost", "product_key" => "item.product_key", "notes" => "item.notes", - "item_tax1" => "item.tax_name1", - "item_tax_rate1" => "item.tax_rate1", - "item_tax2" => "item.tax_name2", - "item_tax_rate2" => "item.tax_rate2", - "item_tax3" => "item.tax_name3", - "item_tax_rate3" => "item.tax_rate3", + "tax_name1" => "item.tax_name1", + "tax_rate1" => "item.tax_rate1", + "tax_name2" => "item.tax_name2", + "tax_rate2" => "item.tax_rate2", + "tax_name3" => "item.tax_name3", + "tax_rate3" => "item.tax_rate3", "custom_value1" => "item.custom_value1", "custom_value2" => "item.custom_value2", "custom_value3" => "item.custom_value3", @@ -229,6 +266,9 @@ class BaseExport "discount" => "item.discount", "type" => "item.type_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 = [ @@ -250,6 +290,7 @@ class BaseExport "private_notes" => "quote.private_notes", "uses_inclusive_taxes" => "quote.uses_inclusive_taxes", "is_amount_discount" => "quote.is_amount_discount", + "discount" => "quote.discount", "partial" => "quote.partial", "partial_due_date" => "quote.partial_due_date", "surcharge1" => "quote.custom_surcharge1", @@ -260,6 +301,12 @@ class BaseExport "tax_amount" => "quote.total_taxes", "assigned_user" => "quote.assigned_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 = [ @@ -271,6 +318,7 @@ class BaseExport "date" => "credit.date", "due_date" => "credit.due_date", "terms" => "credit.terms", + "discount" => "credit.discount", "footer" => "credit.footer", "status" => "credit.status", "public_notes" => "credit.public_notes", @@ -283,6 +331,10 @@ class BaseExport "surcharge2" => "credit.custom_surcharge2", "surcharge3" => "credit.custom_surcharge3", "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", "tax_amount" => "credit.total_taxes", "assigned_user" => "credit.assigned_user_id", @@ -829,17 +881,32 @@ class BaseExport 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 { + $helper = new Helpers(); + $header = []; - // nlog($this->input['report_keys']); - - foreach (array_merge($this->input['report_keys'], $this->forced_keys) as $value) { - + foreach ($this->input['report_keys'] as $value) { + $key = array_search($value, $this->entity_keys); - nlog("{$key} => {$value}"); + $original_key = $key; + + // nlog("{$key} => {$value}"); $prefix = ''; if(!$key) { @@ -897,6 +964,11 @@ class BaseExport $key = array_search($value, $this->purchase_order_report_keys); } + if(!$key) { + $prefix = ''; + $key = array_search($value, $this->product_report_keys); + } + if(!$key) { $prefix = ''; } @@ -913,11 +985,38 @@ class BaseExport $key = str_replace('contact.', '', $key); $key = str_replace('payment.', '', $key); $key = str_replace('expense.', '', $key); -// nlog($key); - if(in_array($key, ['quote1','quote2','quote3','quote4','credit1','credit2','credit3','credit4','purchase_order1','purchase_order2','purchase_order3','purchase_order4'])) + $key = str_replace('product.', '', $key); + + if(stripos($value, 'custom_value') !== false) { - $number = substr($key, -1); - $header[] = ctrans('texts.item') . " ". ctrans("texts.custom_value{$number}"); + $parts = explode(".", $value); + + 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], 'contact') !== false) { + $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'])){ + $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 { @@ -926,7 +1025,7 @@ class BaseExport } // nlog($header); - + return $header; } } diff --git a/app/Export/CSV/ClientExport.php b/app/Export/CSV/ClientExport.php index 6e4dded88159..608595196fea 100644 --- a/app/Export/CSV/ClientExport.php +++ b/app/Export/CSV/ClientExport.php @@ -17,6 +17,7 @@ use App\Models\Company; use App\Transformers\ClientContactTransformer; use App\Transformers\ClientTransformer; use App\Utils\Ninja; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -72,16 +73,6 @@ class ClientExport extends BaseExport 'status' => 'status' ]; - 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) { $this->company = $company; @@ -90,7 +81,27 @@ class ClientExport extends BaseExport $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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $report = $query->cursor() + ->map(function ($client) { + return $this->buildRow($client); + })->toArray(); + + return array_merge(['columns' => $header], $report); + } + + + + public function init(): Builder { MultiDB::setDb($this->company->db); App::forgetInstance('translator'); @@ -98,15 +109,9 @@ class ClientExport 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->client_report_keys); } - - //insert the header - $this->csv->insertOne($this->buildHeader()); $query = Client::query()->with('contacts') ->withTrashed() @@ -115,6 +120,20 @@ class ClientExport extends BaseExport $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 ($client) { $this->csv->insertOne($this->buildRow($client)); diff --git a/app/Export/CSV/ContactExport.php b/app/Export/CSV/ContactExport.php index 04ca04797d82..5efddeaade90 100644 --- a/app/Export/CSV/ContactExport.php +++ b/app/Export/CSV/ContactExport.php @@ -18,6 +18,7 @@ use App\Models\Company; use App\Transformers\ClientContactTransformer; use App\Transformers\ClientTransformer; use App\Utils\Ninja; +use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -32,54 +33,6 @@ class ContactExport extends BaseExport 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) { $this->company = $company; @@ -88,29 +41,39 @@ class ContactExport extends BaseExport $this->contact_transformer = new ClientContactTransformer(); } - public function run() + 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)); - //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->client_report_keys); } - //insert the header - $this->csv->insertOne($this->buildHeader()); - $query = ClientContact::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 ($contact) { $this->csv->insertOne($this->buildRow($contact)); }); @@ -118,6 +81,26 @@ class ContactExport 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 ($contact) { + return $this->buildRow($contact); + })->toArray(); + + return array_merge(['columns' => $header], $report); + } + + private function buildRow(ClientContact $contact) :array { $transformed_contact = false; @@ -129,14 +112,13 @@ class ContactExport extends BaseExport foreach (array_values($this->input['report_keys']) as $key) { $parts = explode('.', $key); - $keyval = array_search($key, $this->entity_keys); 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)) { - $entity[$keyval] = $transformed_contact[$parts[1]]; + $entity[$key] = $transformed_contact[$parts[1]]; } else { - $entity[$keyval] = ''; + $entity[$key] = ''; } } diff --git a/app/Export/CSV/CreditExport.php b/app/Export/CSV/CreditExport.php index 234a9f9c10e4..d9641895371b 100644 --- a/app/Export/CSV/CreditExport.php +++ b/app/Export/CSV/CreditExport.php @@ -30,51 +30,6 @@ class CreditExport extends BaseExport 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) { $this->company = $company; @@ -86,34 +41,36 @@ class CreditExport extends BaseExport { $query = $this->init(); - $header = $this->buildHeader(); + $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 ($credit) { $row = $this->buildRow($credit); return $this->processMetaData($row, $credit); })->toArray(); - - return array_merge([$header], $report); + + return array_merge(['columns' => $header], $report); } private function processMetaData(array $row, Credit $credit): array { $clean_row = []; - - foreach ($this->input['report_keys'] as $key => $value) { - + foreach (array_values($this->input['report_keys']) as $key => $value) { + $report_keys = explode(".", $value); - $column_key = str_replace("credit.", "", $value); - $column_key = array_search($column_key, $this->entity_keys); - + $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] == 'credit' ? null : $credit->{$report_keys[0]}->hashed_id ?? null; $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); else $clean_row[$key]['display_value'] = $row[$column_key]; @@ -133,20 +90,13 @@ class CreditExport extends BaseExport $t->replace(Ninja::transformTranslations($this->company->settings)); if (count($this->input['report_keys']) == 0) { - $this->input['report_keys'] = array_values($this->entity_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(); - + $this->input['report_keys'] = array_values($this->credit_report_keys); } $query = Credit::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); @@ -162,11 +112,9 @@ class CreditExport extends BaseExport //insert the header $this->csv->insertOne($this->buildHeader()); - // nlog($this->input['report_keys']); $query->cursor() ->each(function ($credit) { - // nlog($this->buildRow($credit)); $this->csv->insertOne($this->buildRow($credit)); }); @@ -180,22 +128,22 @@ class CreditExport 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("credit.", "", $key), $this->entity_keys) ?? $key; - - if(!$keyval) - $keyval = $key; + + $keyval = $key; + $credit_key = str_replace("credit.", "", $key); + $searched_credit_key = array_search(str_replace("credit.", "", $key), $this->credit_report_keys) ?? $key; - if (array_key_exists($key, $transformed_credit)) { - $entity[$keyval] = $transformed_credit[$key]; - } elseif (array_key_exists($keyval, $transformed_credit)) { + if (isset($transformed_credit[$credit_key])) { + $entity[$keyval] = $transformed_credit[$credit_key]; + } elseif (isset($transformed_credit[$keyval])) { $entity[$keyval] = $transformed_credit[$keyval]; + } elseif(isset($transformed_credit[$searched_credit_key])){ + $entity[$keyval] = $transformed_credit[$searched_credit_key]; } else { $entity[$keyval] = $this->resolveKey($keyval, $credit, $this->credit_transformer); } + } return $this->decorateAdvancedFields($credit, $entity); diff --git a/app/Export/CSV/DocumentExport.php b/app/Export/CSV/DocumentExport.php index b43a759b5254..26d55840e431 100644 --- a/app/Export/CSV/DocumentExport.php +++ b/app/Export/CSV/DocumentExport.php @@ -16,6 +16,7 @@ use App\Models\Company; use App\Models\Document; use App\Transformers\DocumentTransformer; use App\Utils\Ninja; +use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -30,16 +31,11 @@ class DocumentExport extends BaseExport public array $entity_keys = [ 'record_type' => 'record_type', - // 'record_name' => 'record_name', 'name' => 'name', 'type' => 'type', 'created_at' => 'created_at', ]; - private array $decorate_keys = [ - - ]; - public function __construct(Company $company, array $input) { $this->company = $company; @@ -47,28 +43,55 @@ class DocumentExport extends BaseExport $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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $report = $query->cursor() + ->map(function ($document) { + $row = $this->buildRow($document); + })->toArray(); + + return array_merge(['columns' => $header], $report); + } + + 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)); - //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); } - //insert the header - $this->csv->insertOne($this->buildHeader()); - $query = Document::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->csv->insertOne($this->buildRow($entity)); diff --git a/app/Export/CSV/ExpenseExport.php b/app/Export/CSV/ExpenseExport.php index 70bb8c841edb..1eb5747cc16f 100644 --- a/app/Export/CSV/ExpenseExport.php +++ b/app/Export/CSV/ExpenseExport.php @@ -16,6 +16,7 @@ use App\Models\Company; use App\Models\Expense; use App\Transformers\ExpenseTransformer; use App\Utils\Ninja; +use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -28,51 +29,6 @@ class ExpenseExport extends BaseExport 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) { $this->company = $company; @@ -80,24 +36,38 @@ class ExpenseExport extends BaseExport $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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $report = $query->cursor() + ->map(function ($resource) { + return $this->buildRow($resource); + })->toArray(); + + return array_merge(['columns' => $header], $report); + } + + 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)); - //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->expense_report_keys); } - //insert the header - $this->csv->insertOne($this->buildHeader()); - $query = Expense::query() ->with('client') ->withTrashed() @@ -106,6 +76,20 @@ class ExpenseExport extends BaseExport $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 ($expense) { $this->csv->insertOne($this->buildRow($expense)); @@ -122,7 +106,6 @@ class ExpenseExport extends BaseExport foreach (array_values($this->input['report_keys']) as $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)) { $entity[$key] = $transformed_expense[$parts[1]]; diff --git a/app/Export/CSV/InvoiceExport.php b/app/Export/CSV/InvoiceExport.php index 853da158d23d..bf999f9177f7 100644 --- a/app/Export/CSV/InvoiceExport.php +++ b/app/Export/CSV/InvoiceExport.php @@ -20,6 +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; class InvoiceExport extends BaseExport { @@ -29,56 +30,6 @@ class InvoiceExport 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', - '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) { $this->company = $company; @@ -86,24 +37,19 @@ class InvoiceExport extends BaseExport $this->invoice_transformer = new InvoiceTransformer(); } - public function run() + public 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)); - //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->invoice_report_keys); } - //insert the header - $this->csv->insertOne($this->buildHeader()); - $query = Invoice::query() ->withTrashed() ->with('client') @@ -112,10 +58,43 @@ class InvoiceExport extends BaseExport $query = $this->addDateRange($query); - if(isset($this->input['status'])){ + if(isset($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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $report = $query->cursor() + ->map(function ($resource) { + return $this->buildRow($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() ->each(function ($invoice) { $this->csv->insertOne($this->buildRow($invoice)); @@ -131,24 +110,15 @@ class InvoiceExport 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("invoice.", "", $key), $this->entity_keys) ?? $key; + $parts = explode('.', $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); @@ -156,31 +126,22 @@ class InvoiceExport extends BaseExport 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'); - - // $entity['method'] = $payment_exists ? $invoice->payments()->first()->translatedType() : ""; + if (in_array('invoice.status', $this->input['report_keys'])) { + $entity['invoice.status'] = $invoice->stringStatus($invoice->status_id); + } return $entity; } diff --git a/app/Export/CSV/InvoiceItemExport.php b/app/Export/CSV/InvoiceItemExport.php index 943844bc125a..d7db46889269 100644 --- a/app/Export/CSV/InvoiceItemExport.php +++ b/app/Export/CSV/InvoiceItemExport.php @@ -12,11 +12,11 @@ namespace App\Export\CSV; use App\Libraries\MultiDB; -use App\Models\Client; use App\Models\Company; use App\Models\Invoice; use App\Transformers\InvoiceTransformer; use App\Utils\Ninja; +use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -31,64 +31,7 @@ class InvoiceItemExport extends BaseExport private bool $force_keys = false; - public array $entity_keys = [ - 'amount' => 'amount', - 'balance' => 'balance', - '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 $storage_array = []; private array $decorate_keys = [ 'client', @@ -103,25 +46,20 @@ class InvoiceItemExport extends BaseExport $this->invoice_transformer = new InvoiceTransformer(); } - public function run() + public 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)); - //load the CSV document from a string - $this->csv = Writer::createFromString(); - if (count($this->input['report_keys']) == 0) { $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() ->withTrashed() ->with('client')->where('company_id', $this->company->id) @@ -129,11 +67,46 @@ class InvoiceItemExport extends BaseExport $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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $query->cursor() + ->each(function ($resource) { + $this->iterateItems($resource); + }); + + return array_merge(['columns' => $header], $this->storage_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() ->each(function ($invoice) { $this->iterateItems($invoice); }); + $this->csv->insertAll($this->storage_array); + return $this->csv->toString(); } @@ -146,46 +119,32 @@ class InvoiceItemExport extends BaseExport foreach ($invoice->line_items as $item) { $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.")) { $key = str_replace("item.", "", $key); - $keyval = $key; - - $keyval = str_replace("custom_value", "invoice", $key); - if($key == 'type_id') - $keyval = 'type'; + $key = 'type'; if($key == 'tax_id') - $keyval = 'tax_category'; + $key = 'tax_category'; if (property_exists($item, $key)) { - $item_array[$keyval] = $item->{$key}; - } else { - $item_array[$keyval] = ''; + $item_array[$key] = $item->{$key}; + } + 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); $entity = $this->decorateAdvancedFields($invoice, $transformed_items); - $this->csv->insertOne($entity); + $this->storage_array[] = $entity; + } } @@ -196,23 +155,19 @@ class InvoiceItemExport extends BaseExport $entity = []; foreach (array_values($this->input['report_keys']) as $key) { - $keyval = array_search($key, $this->entity_keys); + + $parts = explode('.', $key); - if(!$keyval) { - $keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key; - } + if(is_array($parts) && $parts[0] == 'item') + continue; - 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); + if (is_array($parts) && $parts[0] == 'invoice' && array_key_exists($parts[1], $transformed_invoice)) { + $entity[$key] = $transformed_invoice[$parts[1]]; + }else if (array_key_exists($key, $transformed_invoice)) { + $entity[$key] = $transformed_invoice[$key]; + } + else { + $entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer); } } @@ -233,12 +188,12 @@ class InvoiceItemExport extends BaseExport $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); - } + // 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; } diff --git a/app/Export/CSV/PaymentExport.php b/app/Export/CSV/PaymentExport.php index dab8054c132f..930be240b75f 100644 --- a/app/Export/CSV/PaymentExport.php +++ b/app/Export/CSV/PaymentExport.php @@ -16,6 +16,7 @@ use App\Models\Company; use App\Models\Payment; use App\Transformers\PaymentTransformer; use App\Utils\Ninja; +use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -27,39 +28,39 @@ class PaymentExport extends BaseExport 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', - ]; + // 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', - ]; + // private array $decorate_keys = [ + // 'vendor', + // 'status', + // 'project', + // 'client', + // 'currency', + // 'exchange_currency', + // 'type', + // 'invoices', + // ]; public function __construct(Company $company, array $input) { @@ -68,24 +69,19 @@ class PaymentExport extends BaseExport $this->entity_transformer = new PaymentTransformer(); } - public function run() + 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)); - //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->payment_report_keys); } - //insert the header - $this->csv->insertOne($this->buildHeader()); - $query = Payment::query() ->withTrashed() ->where('company_id', $this->company->id) @@ -93,6 +89,39 @@ class PaymentExport extends BaseExport $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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $report = $query->cursor() + ->map(function ($resource) { + return $this->buildRow($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() ->each(function ($entity) { $this->csv->insertOne($this->buildRow($entity)); @@ -108,24 +137,17 @@ class PaymentExport extends BaseExport $entity = []; foreach (array_values($this->input['report_keys']) as $key) { - $keyval = array_search($key, $this->entity_keys); + + $parts = explode('.', $key); - if(!$keyval) { - $keyval = array_search(str_replace("payment.", "", $key), $this->entity_keys) ?? $key; + if (is_array($parts) && $parts[0] == 'payment' && 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, $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); diff --git a/app/Export/CSV/ProductExport.php b/app/Export/CSV/ProductExport.php index f1a24d49b48b..a4c5bbf7535c 100644 --- a/app/Export/CSV/ProductExport.php +++ b/app/Export/CSV/ProductExport.php @@ -17,6 +17,7 @@ use App\Models\Document; use App\Models\Product; use App\Transformers\ProductTransformer; use App\Utils\Ninja; +use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -28,31 +29,6 @@ class ProductExport extends BaseExport 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) { $this->company = $company; @@ -60,24 +36,37 @@ class ProductExport extends BaseExport $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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $report = $query->cursor() + ->map(function ($resource) { + return $this->buildRow($resource); + })->toArray(); + + return array_merge(['columns' => $header], $report); + } + + 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)); - //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->product_report_keys); } - //insert the header - $this->csv->insertOne($this->buildHeader()); - $query = Product::query() ->withTrashed() ->where('company_id', $this->company->id) @@ -85,6 +74,21 @@ class ProductExport extends BaseExport $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->csv->insertOne($this->buildRow($entity)); @@ -100,7 +104,7 @@ class ProductExport extends BaseExport $entity = []; 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)) { $entity[$keyval] = $transformed_entity[$key]; diff --git a/app/Export/CSV/PurchaseOrderExport.php b/app/Export/CSV/PurchaseOrderExport.php index bfba71830f3c..ffee39eee336 100644 --- a/app/Export/CSV/PurchaseOrderExport.php +++ b/app/Export/CSV/PurchaseOrderExport.php @@ -11,14 +11,15 @@ 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\Number; -use Illuminate\Support\Facades\App; 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\Contracts\Database\Eloquent\Builder; class PurchaseOrderExport extends BaseExport { @@ -81,24 +82,19 @@ class PurchaseOrderExport extends BaseExport $this->purchase_order_transformer = new PurchaseOrderTransformer(); } - public function run() + + public 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)); - //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->purchase_order_report_keys); } - - //insert the header - $this->csv->insertOne($this->buildHeader()); - $query = PurchaseOrder::query() ->withTrashed() ->with('vendor') @@ -107,9 +103,38 @@ class PurchaseOrderExport extends BaseExport $query = $this->addDateRange($query); - // if(isset($this->input['status'])) { - // $query = $this->addPurchaseOrderStatusFilter($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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $report = $query->cursor() + ->map(function ($resource) { + return $this->buildRow($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() ->each(function ($purchase_order) { @@ -126,23 +151,16 @@ class PurchaseOrderExport 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("purchase_order.", "", $key), $this->entity_keys) ?? $key; - } + $parts = explode('.', $key); - if(!$keyval) { - $keyval = $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]; + if (is_array($parts) && $parts[0] == 'purchase_order' && array_key_exists($parts[1], $transformed_purchase_order)) { + $entity[$key] = $transformed_purchase_order[$parts[1]]; } 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); diff --git a/app/Export/CSV/PurchaseOrderItemExport.php b/app/Export/CSV/PurchaseOrderItemExport.php index 2bb1eef01591..9b55f78a4e9c 100644 --- a/app/Export/CSV/PurchaseOrderItemExport.php +++ b/app/Export/CSV/PurchaseOrderItemExport.php @@ -16,6 +16,7 @@ use App\Models\Company; use App\Models\PurchaseOrder; use App\Transformers\PurchaseOrderTransformer; use App\Utils\Ninja; +use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Support\Facades\App; use League\Csv\Writer; @@ -30,70 +31,7 @@ class PurchaseOrderItemExport extends BaseExport private bool $force_keys = false; - public array $entity_keys = [ - '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 = [ - 'client', - 'currency_id', - 'status' - ]; + private array $storage_array = []; public function __construct(Company $company, array $input) { @@ -102,25 +40,20 @@ class PurchaseOrderItemExport extends BaseExport $this->purchase_order_transformer = new PurchaseOrderTransformer(); } - public function run() + 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)); - //load the CSV document from a string - $this->csv = Writer::createFromString(); - if (count($this->input['report_keys']) == 0) { - $this->force_keys = true; - $this->input['report_keys'] = array_values($this->entity_keys); + // $this->force_keys = true; + $this->input['report_keys'] = array_values($this->mergeItemsKeys('purchase_order_report_keys')); } - //insert the header - $this->csv->insertOne($this->buildHeader()); - $query = PurchaseOrder::query() ->withTrashed() ->with('vendor')->where('company_id', $this->company->id) @@ -128,12 +61,47 @@ class PurchaseOrderItemExport extends BaseExport $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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $query->cursor() + ->each(function ($resource) { + $this->iterateItems($resource); + }); + + return array_merge(['columns' => $header], $this->storage_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() ->each(function ($purchase_order) { $this->iterateItems($purchase_order); }); + $this->csv->insertAll($this->storage_array); + return $this->csv->toString(); + } private function iterateItems(PurchaseOrder $purchase_order) @@ -141,7 +109,7 @@ class PurchaseOrderItemExport extends BaseExport $transformed_purchase_order = $this->buildRow($purchase_order); $transformed_items = []; - +nlog($purchase_order->toArray()); foreach ($purchase_order->line_items as $item) { $item_array = []; @@ -151,10 +119,6 @@ class PurchaseOrderItemExport extends BaseExport $key = str_replace("item.", "", $key); - $keyval = $key; - - $keyval = str_replace("custom_value", "purchase_order", $key); - if($key == 'type_id') { $keyval = 'type'; } @@ -164,29 +128,17 @@ class PurchaseOrderItemExport extends BaseExport } if (property_exists($item, $key)) { - $item_array[$keyval] = $item->{$key}; + $item_array[$key] = $item->{$key}; } 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); $entity = $this->decorateAdvancedFields($purchase_order, $transformed_items); - $this->csv->insertOne($entity); + $this->storage_array[] = $entity; } } @@ -197,22 +149,18 @@ class PurchaseOrderItemExport extends BaseExport $entity = []; foreach (array_values($this->input['report_keys']) as $key) { - $keyval = array_search($key, $this->entity_keys); + $parts = explode('.', $key); - if(!$keyval) { - $keyval = array_search(str_replace("purchase_order.", "", $key), $this->entity_keys) ?? $key; + if(is_array($parts) && $parts[0] == 'item') { + continue; } - if(!$keyval) { - $keyval = $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]; + if (is_array($parts) && $parts[0] == 'purchase_order' && array_key_exists($parts[1], $transformed_purchase_order)) { + $entity[$key] = $transformed_purchase_order[$parts[1]]; + } elseif (array_key_exists($key, $transformed_purchase_order)) { + $entity[$key] = $transformed_purchase_order[$key]; } else { - $entity[$keyval] = $this->resolveKey($keyval, $purchase_order, $this->purchase_order_transformer); + $entity[$key] = $this->resolveKey($key, $purchase_order, $this->purchase_order_transformer); } } diff --git a/app/Export/CSV/QuoteExport.php b/app/Export/CSV/QuoteExport.php index 2f7d5d736c44..a84becb20eb2 100644 --- a/app/Export/CSV/QuoteExport.php +++ b/app/Export/CSV/QuoteExport.php @@ -16,6 +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\Support\Facades\App; use League\Csv\Writer; @@ -28,43 +29,6 @@ class QuoteExport 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', - '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 = [ 'client', 'currency', @@ -78,24 +42,20 @@ class QuoteExport extends BaseExport $this->quote_transformer = new QuoteTransformer(); } - public function run() + 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)); - //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->quote_report_keys); } - //insert the header - $this->csv->insertOne($this->buildHeader()); - $query = Quote::query() ->withTrashed() ->with('client') @@ -104,6 +64,40 @@ class QuoteExport extends BaseExport $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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $report = $query->cursor() + ->map(function ($resource) { + return $this->buildRow($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() ->each(function ($quote) { $this->csv->insertOne($this->buildRow($quote)); @@ -114,50 +108,42 @@ class QuoteExport extends BaseExport private function buildRow(Quote $quote) :array { - $transformed_entity = $this->quote_transformer->transform($quote); + $transformed_invoice = $this->quote_transformer->transform($quote); $entity = []; foreach (array_values($this->input['report_keys']) as $key) { - $keyval = array_search($key, $this->entity_keys); - if(!$keyval) { - $keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key; + $parts = explode('.', $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); } + private function decorateAdvancedFields(Quote $quote, array $entity) :array { - if (in_array('currency_id', $this->input['report_keys'])) { - $entity['currency'] = $quote->client->currency()->code; + if (in_array('quote.currency_id', $this->input['report_keys'])) { + $entity['quote.currency'] = $quote->client->currency()->code; } - if (in_array('client_id', $this->input['report_keys'])) { - $entity['client'] = $quote->client->present()->name(); + if (in_array('quote.client_id', $this->input['report_keys'])) { + $entity['quote.client'] = $quote->client->present()->name(); } - if (in_array('status_id', $this->input['report_keys'])) { - $entity['status'] = $quote->stringStatus($quote->status_id); + if (in_array('quote.status', $this->input['report_keys'])) { + $entity['quote.status'] = $quote->stringStatus($quote->status_id); } - if (in_array('invoice_id', $this->input['report_keys'])) { - $entity['invoice'] = $quote->invoice ? $quote->invoice->number : ''; + if (in_array('quote.invoice_id', $this->input['report_keys'])) { + $entity['quote.invoice'] = $quote->invoice ? $quote->invoice->number : ''; } return $entity; diff --git a/app/Export/CSV/QuoteItemExport.php b/app/Export/CSV/QuoteItemExport.php index 9af20df7b5ca..a2f78d16ce41 100644 --- a/app/Export/CSV/QuoteItemExport.php +++ b/app/Export/CSV/QuoteItemExport.php @@ -16,6 +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\Support\Facades\App; use League\Csv\Writer; @@ -28,63 +29,7 @@ class QuoteItemExport 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', - '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 $storage_array; private array $decorate_keys = [ 'client', @@ -98,37 +43,70 @@ class QuoteItemExport extends BaseExport $this->quote_transformer = new QuoteTransformer(); } - public function run() + public 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)); + + 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' => $value, 'display_value' => $headerdisplay[$value]]; + })->toArray(); + + $query->cursor() + ->each(function ($resource) { + $this->iterateItems($resource); + }); + + return array_merge(['columns' => $header], $this->storage_array); + } + + + public function run() + { + //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); - } + $query = $this->init(); //insert the header $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() ->each(function ($quote) { $this->iterateItems($quote); }); + $this->csv->insertAll($this->storage_array); + return $this->csv->toString(); + } private function iterateItems(Quote $quote) @@ -137,51 +115,34 @@ class QuoteItemExport extends BaseExport $transformed_items = []; - $transformed_items = []; - foreach ($quote->line_items as $item) { $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.")) { $key = str_replace("item.", "", $key); - $keyval = $key; - - $keyval = str_replace("custom_value", "quote", $key); - if($key == 'type_id') - $keyval = 'type'; + $key = 'type'; if($key == 'tax_id') - $keyval = 'tax_category'; + $key = 'tax_category'; if (property_exists($item, $key)) { - $item_array[$keyval] = $item->{$key}; - } else { - $item_array[$keyval] = ''; + $item_array[$key] = $item->{$key}; + } + 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); $entity = $this->decorateAdvancedFields($quote, $transformed_items); - $this->csv->insertOne($entity); + $this->storage_array[] = $entity; } } @@ -192,26 +153,23 @@ class QuoteItemExport extends BaseExport $entity = []; foreach (array_values($this->input['report_keys']) as $key) { - $keyval = array_search($key, $this->entity_keys); + + $parts = explode('.', $key); - if(!$keyval) { - $keyval = array_search(str_replace("quote.", "", $key), $this->entity_keys) ?? $key; + if(is_array($parts) && $parts[0] == 'item') { + continue; } - if(!$keyval) { - $keyval = $key; - } - - if (array_key_exists($key, $transformed_quote)) { - $entity[$keyval] = $transformed_quote[$key]; - } elseif (array_key_exists($keyval, $transformed_quote)) { - $entity[$keyval] = $transformed_quote[$keyval]; - } - else { - $entity[$keyval] = $this->resolveKey($keyval, $quote, $this->quote_transformer); + if (is_array($parts) && $parts[0] == 'quote' && array_key_exists($parts[1], $transformed_quote)) { + $entity[$key] = $transformed_quote[$parts[1]]; + } elseif (array_key_exists($key, $transformed_quote)) { + $entity[$key] = $transformed_quote[$key]; + } else { + $entity[$key] = $this->resolveKey($key, $quote, $this->quote_transformer); } } + return $this->decorateAdvancedFields($quote, $entity); } private function decorateAdvancedFields(Quote $quote, array $entity) :array diff --git a/app/Export/CSV/VendorExport.php b/app/Export/CSV/VendorExport.php index efc8bf32134e..011484b054a3 100644 --- a/app/Export/CSV/VendorExport.php +++ b/app/Export/CSV/VendorExport.php @@ -67,10 +67,6 @@ class VendorExport extends BaseExport 'vendor.currency', ]; - public array $forced_keys = [ - // 'vendor.status' - ]; - public function __construct(Company $company, array $input) { $this->company = $company; diff --git a/app/Filters/QueryFilters.php b/app/Filters/QueryFilters.php index e58f88c8c388..718ba25a4f26 100644 --- a/app/Filters/QueryFilters.php +++ b/app/Filters/QueryFilters.php @@ -298,7 +298,7 @@ abstract class QueryFilters { return $this->builder->where(function ($query) { $query->whereHas('client', function ($sub_query) { - $sub_query->where('is_deleted', 0); + $sub_query->where('is_deleted', 0)->where('deleted_at', null); })->orWhere('client_id', null); }); } @@ -310,7 +310,7 @@ abstract class QueryFilters { return $this->builder->where(function ($query) { $query->whereHas('vendor', function ($sub_query) { - $sub_query->where('is_deleted', 0); + $sub_query->where('is_deleted', 0)->where('deleted_at', null); })->orWhere('vendor_id', null); }); } diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 74b4dcd0c4d5..591041c31c66 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -72,7 +72,7 @@ class AccountController extends BaseController 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(); diff --git a/app/Http/Controllers/BankTransactionController.php b/app/Http/Controllers/BankTransactionController.php index 69261d4882db..acfdf62c495a 100644 --- a/app/Http/Controllers/BankTransactionController.php +++ b/app/Http/Controllers/BankTransactionController.php @@ -71,15 +71,21 @@ class BankTransactionController extends BaseController 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); } public function store(StoreBankTransactionRequest $request) { + /** @var \App\Models\User $user */ + $user = auth()->user(); + //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); } diff --git a/app/Http/Controllers/EmailHistoryController.php b/app/Http/Controllers/EmailHistoryController.php new file mode 100644 index 000000000000..e8f2d4894fda --- /dev/null +++ b/app/Http/Controllers/EmailHistoryController.php @@ -0,0 +1,70 @@ +id) + ->where('category_id', SystemLog::CATEGORY_MAIL) + ->orderBy('id', 'DESC') + ->cursor() + ->map(function ($system_log) { + if($system_log->log['history'] ?? false) { + return $system_log->log['history']; + // return json_decode($system_log->log['history'], true); + } + }); + + 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'] ?? false) { + return $system_log->log['history']; + // return json_decode($system_log->log['history'], true); + } + }); + + return response()->json($data, 200); + + } +} diff --git a/app/Http/Controllers/GroupSettingController.php b/app/Http/Controllers/GroupSettingController.php index e69d6cab7d2b..ff22b55242c3 100644 --- a/app/Http/Controllers/GroupSettingController.php +++ b/app/Http/Controllers/GroupSettingController.php @@ -139,7 +139,9 @@ class GroupSettingController extends BaseController */ 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); diff --git a/app/Http/Controllers/Reports/ActivityReportController.php b/app/Http/Controllers/Reports/ActivityReportController.php index 24e1feb2e587..ed241a9e38f2 100644 --- a/app/Http/Controllers/Reports/ActivityReportController.php +++ b/app/Http/Controllers/Reports/ActivityReportController.php @@ -14,6 +14,7 @@ namespace App\Http\Controllers\Reports; use App\Utils\Traits\MakesHash; use App\Jobs\Report\SendToAdmin; use App\Export\CSV\ActivityExport; +use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; @@ -31,14 +32,27 @@ class ActivityReportController 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(), ActivityExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), ActivityExport::class, $this->filename); return response()->json(['message' => 'working...'], 200); } // 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(); diff --git a/app/Http/Controllers/Reports/ClientContactReportController.php b/app/Http/Controllers/Reports/ClientContactReportController.php index 39f8b353433f..e29eefe195f2 100644 --- a/app/Http/Controllers/Reports/ClientContactReportController.php +++ b/app/Http/Controllers/Reports/ClientContactReportController.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\Export\CSV\ContactExport; +use App\Jobs\Report\PreviewReport; 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 ClientContactReportController extends BaseController { @@ -62,13 +63,29 @@ class ClientContactReportController 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(), ContactExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), ContactExport::class, $this->filename); return response()->json(['message' => 'working...'], 200); } + + // 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(); diff --git a/app/Http/Controllers/Reports/ClientReportController.php b/app/Http/Controllers/Reports/ClientReportController.php index 462b090046c0..bcbc2c02d98d 100644 --- a/app/Http/Controllers/Reports/ClientReportController.php +++ b/app/Http/Controllers/Reports/ClientReportController.php @@ -11,13 +11,14 @@ 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\Jobs\Report\SendToAdmin; +use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; 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 { @@ -63,14 +64,26 @@ class ClientReportController 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(), ClientExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), ClientExport::class, $this->filename); 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(); diff --git a/app/Http/Controllers/Reports/ExpenseReportController.php b/app/Http/Controllers/Reports/ExpenseReportController.php index 2953f653a391..f1276cdaffdd 100644 --- a/app/Http/Controllers/Reports/ExpenseReportController.php +++ b/app/Http/Controllers/Reports/ExpenseReportController.php @@ -11,13 +11,14 @@ 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\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; 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 { @@ -63,14 +64,27 @@ class ExpenseReportController 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(), ExpenseExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), ExpenseExport::class, $this->filename); return response()->json(['message' => 'working...'], 200); } // 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(); diff --git a/app/Http/Controllers/Reports/InvoiceItemReportController.php b/app/Http/Controllers/Reports/InvoiceItemReportController.php index 77deb05478dd..dc568dfad629 100644 --- a/app/Http/Controllers/Reports/InvoiceItemReportController.php +++ b/app/Http/Controllers/Reports/InvoiceItemReportController.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\InvoiceItemExport; 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 InvoiceItemReportController extends BaseController { @@ -62,14 +63,26 @@ class InvoiceItemReportController 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(), InvoiceItemExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), InvoiceItemExport::class, $this->filename); 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(); diff --git a/app/Http/Controllers/Reports/InvoiceReportController.php b/app/Http/Controllers/Reports/InvoiceReportController.php index 60457bd70c76..c00687fb6885 100644 --- a/app/Http/Controllers/Reports/InvoiceReportController.php +++ b/app/Http/Controllers/Reports/InvoiceReportController.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\Export\CSV\InvoiceExport; +use App\Jobs\Report\PreviewReport; 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 InvoiceReportController extends BaseController { @@ -62,14 +63,26 @@ class InvoiceReportController 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(), InvoiceExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), InvoiceExport::class, $this->filename); 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(); diff --git a/app/Http/Controllers/Reports/PaymentReportController.php b/app/Http/Controllers/Reports/PaymentReportController.php index 44ea8d5e2059..cca6925ef98a 100644 --- a/app/Http/Controllers/Reports/PaymentReportController.php +++ b/app/Http/Controllers/Reports/PaymentReportController.php @@ -11,13 +11,14 @@ 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\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; 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 { @@ -63,14 +64,26 @@ class PaymentReportController 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(), PaymentExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), PaymentExport::class, $this->filename); return response()->json(['message' => 'working...'], 200); } // 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(); diff --git a/app/Http/Controllers/Reports/ProductReportController.php b/app/Http/Controllers/Reports/ProductReportController.php index dcc964677a5f..664bd51a698f 100644 --- a/app/Http/Controllers/Reports/ProductReportController.php +++ b/app/Http/Controllers/Reports/ProductReportController.php @@ -11,13 +11,14 @@ 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\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; 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 { @@ -63,14 +64,27 @@ class ProductReportController 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(), ProductExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), ProductExport::class, $this->filename); return response()->json(['message' => 'working...'], 200); } // 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(); diff --git a/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php b/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php index a708f1300ab4..71509576f582 100644 --- a/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php +++ b/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php @@ -11,11 +11,12 @@ 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\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 { @@ -30,14 +31,26 @@ class PurchaseOrderItemReportController 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(), PurchaseOrderItemExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), PurchaseOrderItemExport::class, $this->filename); return response()->json(['message' => 'working...'], 200); } // 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(); diff --git a/app/Http/Controllers/Reports/PurchaseOrderReportController.php b/app/Http/Controllers/Reports/PurchaseOrderReportController.php index 4bd0057aa91a..5899b20cfcef 100644 --- a/app/Http/Controllers/Reports/PurchaseOrderReportController.php +++ b/app/Http/Controllers/Reports/PurchaseOrderReportController.php @@ -11,11 +11,12 @@ 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\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; -use App\Jobs\Report\SendToAdmin; -use App\Utils\Traits\MakesHash; class PurchaseOrderReportController extends BaseController { @@ -30,14 +31,29 @@ class PurchaseOrderReportController 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(), PurchaseOrderExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), PurchaseOrderExport::class, $this->filename); return response()->json(['message' => 'working...'], 200); } // 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(); diff --git a/app/Http/Controllers/Reports/QuoteReportController.php b/app/Http/Controllers/Reports/QuoteReportController.php index 26c92952da10..9034b1a939c4 100644 --- a/app/Http/Controllers/Reports/QuoteReportController.php +++ b/app/Http/Controllers/Reports/QuoteReportController.php @@ -11,12 +11,13 @@ namespace App\Http\Controllers\Reports; +use Illuminate\Http\Response; 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\Requests\Report\GenericReportRequest; -use App\Jobs\Report\SendToAdmin; -use App\Utils\Traits\MakesHash; -use Illuminate\Http\Response; class QuoteReportController extends BaseController { @@ -62,14 +63,26 @@ class QuoteReportController 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(), QuoteExport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), QuoteExport::class, $this->filename); return response()->json(['message' => 'working...'], 200); } // 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(); diff --git a/app/Http/Requests/Email/ClientEmailHistoryRequest.php b/app/Http/Requests/Email/ClientEmailHistoryRequest.php new file mode 100644 index 000000000000..45d60b458b99 --- /dev/null +++ b/app/Http/Requests/Email/ClientEmailHistoryRequest.php @@ -0,0 +1,55 @@ +user(); + + return $user->can('view', $this->client); + + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + ]; + } + + public function prepareForValidation() + { + $input = $this->all(); + + $this->replace($input); + } + +} diff --git a/app/Http/Requests/Email/EntityEmailHistoryRequest.php b/app/Http/Requests/Email/EntityEmailHistoryRequest.php new file mode 100644 index 000000000000..2c506e653dd6 --- /dev/null +++ b/app/Http/Requests/Email/EntityEmailHistoryRequest.php @@ -0,0 +1,62 @@ +user(); + + return [ + 'entity' => 'bail|required|string|in:invoice,quote,credit,recurring_invoice,purchase_order', + 'entity_id' => ['bail','required',Rule::exists($this->entity_plural, 'id')->where('company_id', $user->company()->id)], + ]; + } + + public function prepareForValidation() + { + $input = $this->all(); + + $this->entity_plural = Str::plural($input['entity']) ?? ''; + $input['entity_id'] = $this->decodePrimaryKey($input['entity_id']); + + $this->replace($input); + } + +} diff --git a/app/Http/Requests/Email/SendEmailRequest.php b/app/Http/Requests/Email/SendEmailRequest.php index b0264eac2b3c..d917742dfac3 100644 --- a/app/Http/Requests/Email/SendEmailRequest.php +++ b/app/Http/Requests/Email/SendEmailRequest.php @@ -51,7 +51,10 @@ class SendEmailRequest extends Request { $input = $this->all(); - $settings = auth()->user()->company()->settings; + /** @var \App\Models\User $user */ + $user = auth()->user(); + + $settings = $user->company()->settings; if (empty($input['template'])) { $input['template'] = ''; diff --git a/app/Http/ValidationRules/Account/BlackListRule.php b/app/Http/ValidationRules/Account/BlackListRule.php index daa13495e671..7d353c429b53 100644 --- a/app/Http/ValidationRules/Account/BlackListRule.php +++ b/app/Http/ValidationRules/Account/BlackListRule.php @@ -19,6 +19,7 @@ use Illuminate\Contracts\Validation\Rule; class BlackListRule implements Rule { private array $blacklist = [ + 'pretreer.com', 'candassociates.com', 'vusra.com', 'fourthgenet.com', diff --git a/app/Jobs/PostMark/ProcessPostmarkWebhook.php b/app/Jobs/PostMark/ProcessPostmarkWebhook.php index d99455ab322e..18dde45e430c 100644 --- a/app/Jobs/PostMark/ProcessPostmarkWebhook.php +++ b/app/Jobs/PostMark/ProcessPostmarkWebhook.php @@ -11,27 +11,24 @@ namespace App\Jobs\PostMark; -use App\DataMapper\Analytics\Mail\EmailBounce; -use App\DataMapper\Analytics\Mail\EmailSpam; -use App\Jobs\Util\SystemLogger; +use App\Models\SystemLog; use App\Libraries\MultiDB; -use App\Models\Company; +use Postmark\PostmarkClient; +use Illuminate\Bus\Queueable; +use App\Jobs\Util\SystemLogger; +use App\Models\QuoteInvitation; use App\Models\CreditInvitation; use App\Models\InvoiceInvitation; -use App\Models\Payment; -use App\Models\PurchaseOrderInvitation; -use App\Models\QuoteInvitation; -use App\Models\RecurringInvoiceInvitation; -use App\Models\SystemLog; -use App\Notifications\Ninja\EmailBounceNotification; -use App\Notifications\Ninja\EmailSpamNotification; -use App\Utils\Ninja; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; -use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Turbo124\Beacon\Facades\LightLogs; +use App\Models\PurchaseOrderInvitation; +use Illuminate\Queue\InteractsWithQueue; +use App\Models\RecurringInvoiceInvitation; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; +use App\DataMapper\Analytics\Mail\EmailSpam; +use App\DataMapper\Analytics\Mail\EmailBounce; +use App\Notifications\Ninja\EmailSpamNotification; class ProcessPostmarkWebhook implements ShouldQueue { @@ -41,6 +38,16 @@ class ProcessPostmarkWebhook implements ShouldQueue public $invitation; + private $entity; + + private array $default_response = [ + 'recipients' => '', + 'subject' => 'Message not found.', + 'entity' => '', + 'entity_id' => '', + 'events' => [], + ]; + /** * Create a new job instance. * @@ -126,8 +133,10 @@ class ProcessPostmarkWebhook implements ShouldQueue $this->invitation->opened_date = now(); $this->invitation->save(); + $data = array_merge($this->request, ['history' => $this->fetchMessage()]); + (new SystemLogger( - $this->request, + $data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_OPENED, SystemLog::TYPE_WEBHOOK_RESPONSE, @@ -155,8 +164,10 @@ class ProcessPostmarkWebhook implements ShouldQueue $this->invitation->email_status = 'delivered'; $this->invitation->save(); + $data = array_merge($this->request, ['history' => $this->fetchMessage()]); + (new SystemLogger( - $this->request, + $data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_DELIVERY, SystemLog::TYPE_WEBHOOK_RESPONSE, @@ -204,7 +215,9 @@ class ProcessPostmarkWebhook implements ShouldQueue LightLogs::create($bounce)->send(); - (new SystemLogger($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); + $data = array_merge($this->request, ['history' => $this->fetchMessage()]); + + (new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); // if(config('ninja.notification.slack')) // $this->invitation->company->notification(new EmailBounceNotification($this->invitation->company->account))->ninja(); @@ -248,7 +261,9 @@ class ProcessPostmarkWebhook implements ShouldQueue LightLogs::create($spam)->send(); - (new SystemLogger($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); + $data = array_merge($this->request, ['history' => $this->fetchMessage()]); + + (new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); if (config('ninja.notification.slack')) { $this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja(); @@ -260,17 +275,65 @@ class ProcessPostmarkWebhook implements ShouldQueue $invitation = false; if ($invitation = InvoiceInvitation::where('message_id', $message_id)->first()) { + $this->entity = 'invoice'; return $invitation; } elseif ($invitation = QuoteInvitation::where('message_id', $message_id)->first()) { + $this->entity = 'quote'; return $invitation; } elseif ($invitation = RecurringInvoiceInvitation::where('message_id', $message_id)->first()) { + $this->entity = 'recurring_invoice'; return $invitation; } elseif ($invitation = CreditInvitation::where('message_id', $message_id)->first()) { + $this->entity = 'credit'; return $invitation; } elseif ($invitation = PurchaseOrderInvitation::where('message_id', $message_id)->first()) { + $this->entity = 'purchase_order'; return $invitation; } else { return $invitation; } } + + private function fetchMessage(): array + { + if(strlen($this->request['MessageID']) < 1){ + return $this->default_response; + } + + try { + + $postmark = new PostmarkClient(config('services.postmark.token')); + $messageDetail = $postmark->getOutboundMessageDetails($this->request['MessageID']); + + $recipients = collect($messageDetail['recipients'])->flatten()->implode(','); + $subject = $messageDetail->subject ?? ''; + + $events = collect($messageDetail->messageevents)->map(function ($event) { + + return [ + 'recipient' => $event->Recipient ?? '', + 'status' => $event->Type ?? '', + 'delivery_message' => $event->Details->DeliveryMessage ?? $event->Details->Summary ?? '', + 'server' => $event->Details->DestinationServer ?? '', + 'server_ip' => $event->Details->DestinationIP ?? '', + 'date' => \Carbon\Carbon::parse($event->ReceivedAt)->format('Y-m-d H:m:s') ?? '', + ]; + + })->toArray(); + + return [ + 'recipients' => $recipients, + 'subject' => $subject, + 'entity' => $this->entity ?? '', + 'entity_id' => $this->invitation->{$this->entity}->hashed_id ?? '', + 'events' => $events, + ]; + + } + catch (\Exception $e) { + + return $this->default_response; + + } + } } diff --git a/app/Jobs/Report/PreviewReport.php b/app/Jobs/Report/PreviewReport.php index abddca938758..ce07cbfc1c34 100644 --- a/app/Jobs/Report/PreviewReport.php +++ b/app/Jobs/Report/PreviewReport.php @@ -39,7 +39,8 @@ class PreviewReport implements ShouldQueue /** @var \App\Export\CSV\CreditExport $export */ $export = new $this->report_class($this->company, $this->request); $report = $export->returnJson(); - + nlog($report); + nlog($this->report_class); // nlog($report); Cache::put($this->hash, $report, 60 * 60); } diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php index d60fa8939f3e..68f17926ea41 100644 --- a/app/Mail/Engine/PaymentEmailEngine.php +++ b/app/Mail/Engine/PaymentEmailEngine.php @@ -159,6 +159,7 @@ class PaymentEmailEngine extends BaseEmailEngine $data['$entity'] = ['value' => '', 'label' => ctrans('texts.payment')]; $data['$payment.amount'] = ['value' => Number::formatMoney($this->payment->amount, $this->client) ?: ' ', 'label' => ctrans('texts.amount')]; $data['$payment.refunded'] = ['value' => Number::formatMoney($this->payment->refunded, $this->client) ?: ' ', 'label' => ctrans('texts.refund')]; + $data['$payment.unapplied'] = ['value' => Number::formatMoney(($this->payment->amount - $this->payment->refunded - $this->payment->applied), $this->client) ?: ' ', 'label' => ctrans('texts.refund')]; $data['$amount'] = &$data['$payment.amount']; $data['$payment.date'] = ['value' => $this->translateDate($this->payment->date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.payment_date')]; $data['$transaction_reference'] = ['value' => $this->payment->transaction_reference, 'label' => ctrans('texts.transaction_reference')]; diff --git a/app/PaymentDrivers/Square/SquareWebhook.php b/app/PaymentDrivers/Square/SquareWebhook.php index ebe46b0af4ee..c83b73fd4765 100644 --- a/app/PaymentDrivers/Square/SquareWebhook.php +++ b/app/PaymentDrivers/Square/SquareWebhook.php @@ -146,7 +146,7 @@ class SquareWebhook implements ShouldQueue $data = [ 'payment_type' => $this->source_type[$square_payment->source_type], - 'amount' => $payment_hash->amount_with_fee, + 'amount' => $payment_hash->amount_with_fee(), 'transaction_reference' => $square_payment->id, 'gateway_type_id' => GatewayType::BANK_TRANSFER, ]; diff --git a/app/PaymentDrivers/SquarePaymentDriver.php b/app/PaymentDrivers/SquarePaymentDriver.php index 9a14358be634..5e6e3ecbb738 100644 --- a/app/PaymentDrivers/SquarePaymentDriver.php +++ b/app/PaymentDrivers/SquarePaymentDriver.php @@ -394,8 +394,10 @@ class SquarePaymentDriver extends BaseDriver //getsubscriptionid here $subscription_id = $this->checkWebhooks(); - if(!$subscription_id) - return nlog('No Subscription Found'); + if(!$subscription_id){ + nlog('No Subscription Found'); + return; + } $api_response = $this->square->getWebhookSubscriptionsApi()->testWebhookSubscription($subscription_id, $body); diff --git a/app/Repositories/BaseRepository.php b/app/Repositories/BaseRepository.php index b2c5aaad97d2..f392d24f3693 100644 --- a/app/Repositories/BaseRepository.php +++ b/app/Repositories/BaseRepository.php @@ -153,7 +153,7 @@ class BaseRepository $model->client_id = $data['client_id']; } - $client = Client::with('group_settings')->where('id', $model->client_id)->withTrashed()->firstOrFail(); + $client = Client::query()->with('group_settings')->where('id', $model->client_id)->withTrashed()->firstOrFail(); $state = []; diff --git a/app/Repositories/ExpenseRepository.php b/app/Repositories/ExpenseRepository.php index b1b8794b98b7..6af0d453c6b6 100644 --- a/app/Repositories/ExpenseRepository.php +++ b/app/Repositories/ExpenseRepository.php @@ -113,6 +113,11 @@ class ExpenseRepository extends BaseRepository $expense->saveQuietly(); $expense->transaction->expense_id = $exp_ids; + + if(strlen($exp_ids) <= 2) { + $expense->transaction->status_id = 1; + } + $expense->transaction->saveQuietly(); } diff --git a/app/Services/Client/EmailHistory.php b/app/Services/Client/EmailHistory.php new file mode 100644 index 000000000000..f0715c49b3e3 --- /dev/null +++ b/app/Services/Client/EmailHistory.php @@ -0,0 +1,96 @@ + 'Message not found.', + 'status' => '', + 'recipient' => '', + 'type' => '', + 'delivery_message' => '', + 'server' => '', + 'server_ip' => '', + ]; + + public function __construct(public Client $client) + { + } + + public function run(): array + { + // $settings = $this->client->getMergedSettings(); + + // if($settings->email_sending_method == 'default'){ + // $this->postmark_token = config('services.postmark.token'); + // } + // elseif($settings->email_sending_method == 'client_postmark'){ + // $this->postmark_token = $settings->postmark_secret; + // } + // else{ + // return []; + // } + + // $this->postmark = new PostmarkClient($this->postmark_token); + + return SystemLog::query() + ->where('client_id', $this->client->id) + ->where('category_id', SystemLog::CATEGORY_MAIL) + ->orderBy('id','DESC') + ->cursor() + ->map(function ($system_log) { + + if($system_log->log['history'] ?? false){ + return json_decode($system_log->log['history'],true); + } + })->toArray(); + } + + private function fetchMessage(string $message_id): array + { + if(strlen($message_id) < 1){ + return $this->default_response; + } + + try { + + $messageDetail = $this->postmark->getOutboundMessageDetails($message_id); + + return [ + 'subject' => $messageDetail->subject ?? '', + 'status' => $messageDetail->status ?? '', + 'recipient' => $messageDetail->messageevents[0]['Recipient'] ?? '', + 'type' => $messageDetail->messageevents[0]->Type ?? '', + 'delivery_message' => $messageDetail->messageevents[0]->Details->DeliveryMessage ?? '', + 'server' => $messageDetail->messageevents[0]->Details->DestinationServer ?? '', + 'server_ip' => $messageDetail->messageevents[0]->Details->DestinationIP ?? '', + ]; + + } + catch (\Exception $e) { + + return $this->default_response; + + } + } +} \ No newline at end of file diff --git a/app/Services/Email/Email.php b/app/Services/Email/Email.php index 4c114d586d31..cebb8b7b6f79 100644 --- a/app/Services/Email/Email.php +++ b/app/Services/Email/Email.php @@ -240,7 +240,6 @@ class Email implements ShouldQueue } if ($this->client_mailgun_secret) { - $mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain, $this->client_mailgun_endpoint); } @@ -254,6 +253,7 @@ class Email implements ShouldQueue LightLogs::create(new EmailSuccess($this->company->company_key)) ->send(); + } catch(\Symfony\Component\Mime\Exception\RfcComplianceException $e) { nlog("Mailer failed with a Logic Exception {$e->getMessage()}"); $this->fail(); diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php index 27119ec5ca12..023e8148f34f 100644 --- a/app/Services/Payment/DeletePayment.php +++ b/app/Services/Payment/DeletePayment.php @@ -60,6 +60,7 @@ class DeletePayment BankTransaction::query()->where('payment_id', $this->payment->id)->cursor()->each(function ($bt){ $bt->payment_id = null; + $bt->status_id = 1; $bt->save(); }); diff --git a/composer.json b/composer.json index 92c31140f2c1..2c157beac4be 100644 --- a/composer.json +++ b/composer.json @@ -76,6 +76,7 @@ "omnipay/paypal": "^3.0", "payfast/payfast-php-sdk": "^1.1", "pragmarx/google2fa": "^8.0", + "psr/http-message": "^1.0", "pusher/pusher-php-server": "^7.2", "razorpay/razorpay": "2.*", "sentry/sentry-laravel": "^3", @@ -96,7 +97,7 @@ "twilio/sdk": "^6.40", "webpatser/laravel-countries": "dev-master#75992ad", "wepay/php-sdk": "^0.3", - "psr/http-message": "^1.0" + "wildbit/postmark-php": "^4.0" }, "require-dev": { "php": "^8.1", diff --git a/composer.lock b/composer.lock index e48122a29769..2d3df25d4127 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8e1e0864e98afc97b30e13631480c86b", + "content-hash": "7c3f126aafc640beb01f58c7047f6e23", "packages": [ { "name": "adrienrn/php-mimetyper", @@ -525,16 +525,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.279.7", + "version": "3.279.9", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "223f97f8f12765b42a682569b434ac0210cca93a" + "reference": "cbf446e410c04a405192cc0d018f29a91fe36375" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/223f97f8f12765b42a682569b434ac0210cca93a", - "reference": "223f97f8f12765b42a682569b434ac0210cca93a", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/cbf446e410c04a405192cc0d018f29a91fe36375", + "reference": "cbf446e410c04a405192cc0d018f29a91fe36375", "shasum": "" }, "require": { @@ -614,9 +614,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.279.7" + "source": "https://github.com/aws/aws-sdk-php/tree/3.279.9" }, - "time": "2023-08-25T18:07:43+00:00" + "time": "2023-08-29T18:11:18+00:00" }, { "name": "bacon/bacon-qr-code", @@ -2586,16 +2586,16 @@ }, { "name": "google/apiclient-services", - "version": "v0.312.1", + "version": "v0.313.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "d13797cf251ec0d62f00b70dfa8642aa9550900d" + "reference": "e41289c4488563af75bd291972f0fa00949e084a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/d13797cf251ec0d62f00b70dfa8642aa9550900d", - "reference": "d13797cf251ec0d62f00b70dfa8642aa9550900d", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/e41289c4488563af75bd291972f0fa00949e084a", + "reference": "e41289c4488563af75bd291972f0fa00949e084a", "shasum": "" }, "require": { @@ -2624,9 +2624,9 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.312.1" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.313.0" }, - "time": "2023-08-21T00:52:13+00:00" + "time": "2023-08-25T01:10:13+00:00" }, { "name": "google/auth", @@ -2803,22 +2803,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.7.0", + "version": "7.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -2909,7 +2909,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.7.0" + "source": "https://github.com/guzzle/guzzle/tree/7.8.0" }, "funding": [ { @@ -2925,7 +2925,7 @@ "type": "tidelift" } ], - "time": "2023-05-21T14:04:53+00:00" + "time": "2023-08-27T10:20:53+00:00" }, { "name": "guzzlehttp/promises", @@ -3012,16 +3012,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.6.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77" + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/8bd7c33a0734ae1c5d074360512beb716bef3f77", - "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", "shasum": "" }, "require": { @@ -3108,7 +3108,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.0" + "source": "https://github.com/guzzle/psr7/tree/2.6.1" }, "funding": [ { @@ -3124,20 +3124,20 @@ "type": "tidelift" } ], - "time": "2023-08-03T15:06:02+00:00" + "time": "2023-08-27T10:13:57+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.1", + "version": "v1.0.2", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2" + "reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/b945d74a55a25a949158444f09ec0d3c120d69e2", - "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/61bf437fc2197f587f6857d3ff903a24f1731b5d", + "reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d", "shasum": "" }, "require": { @@ -3145,15 +3145,11 @@ "symfony/polyfill-php80": "^1.17" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", "phpunit/phpunit": "^8.5.19 || ^9.5.8", "uri-template/tests": "1.0.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, "autoload": { "psr-4": { "GuzzleHttp\\UriTemplate\\": "src" @@ -3192,7 +3188,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.1" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.2" }, "funding": [ { @@ -3208,7 +3204,7 @@ "type": "tidelift" } ], - "time": "2021-10-07T12:57:01+00:00" + "time": "2023-08-27T10:19:19+00:00" }, { "name": "halaxa/json-machine", @@ -4026,16 +4022,16 @@ }, { "name": "jms/serializer", - "version": "3.27.0", + "version": "3.28.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", - "reference": "e8c812460d7b47b15bc0ccd78901276bd44ad452" + "reference": "5a5a03a71a28a480189c5a0ca95893c19f1d120c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/e8c812460d7b47b15bc0ccd78901276bd44ad452", - "reference": "e8c812460d7b47b15bc0ccd78901276bd44ad452", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/5a5a03a71a28a480189c5a0ca95893c19f1d120c", + "reference": "5a5a03a71a28a480189c5a0ca95893c19f1d120c", "shasum": "" }, "require": { @@ -4047,7 +4043,7 @@ "phpstan/phpdoc-parser": "^0.4 || ^0.5 || ^1.0" }, "require-dev": { - "doctrine/coding-standard": "^8.1", + "doctrine/coding-standard": "^12.0", "doctrine/orm": "~2.1", "doctrine/persistence": "^1.3.3|^2.0|^3.0", "doctrine/phpcr-odm": "^1.3|^2.0", @@ -4110,7 +4106,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/serializer/issues", - "source": "https://github.com/schmittjoh/serializer/tree/3.27.0" + "source": "https://github.com/schmittjoh/serializer/tree/3.28.0" }, "funding": [ { @@ -4118,7 +4114,7 @@ "type": "github" } ], - "time": "2023-07-29T22:33:44+00:00" + "time": "2023-08-03T14:43:08+00:00" }, { "name": "josemmo/facturae-php", @@ -4335,16 +4331,16 @@ }, { "name": "laravel/framework", - "version": "v10.20.0", + "version": "v10.21.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "a655dca3fbe83897e22adff652b1878ba352d041" + "reference": "96b15c7ac382a9adb4a56d40c640e782d669a112" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/a655dca3fbe83897e22adff652b1878ba352d041", - "reference": "a655dca3fbe83897e22adff652b1878ba352d041", + "url": "https://api.github.com/repos/laravel/framework/zipball/96b15c7ac382a9adb4a56d40c640e782d669a112", + "reference": "96b15c7ac382a9adb4a56d40c640e782d669a112", "shasum": "" }, "require": { @@ -4531,7 +4527,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-08-22T13:37:09+00:00" + "time": "2023-08-29T13:55:56+00:00" }, { "name": "laravel/prompts", @@ -4774,16 +4770,16 @@ }, { "name": "laravel/tinker", - "version": "v2.8.1", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "04a2d3bd0d650c0764f70bf49d1ee39393e4eb10" + "reference": "b936d415b252b499e8c3b1f795cd4fc20f57e1f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/04a2d3bd0d650c0764f70bf49d1ee39393e4eb10", - "reference": "04a2d3bd0d650c0764f70bf49d1ee39393e4eb10", + "url": "https://api.github.com/repos/laravel/tinker/zipball/b936d415b252b499e8c3b1f795cd4fc20f57e1f3", + "reference": "b936d415b252b499e8c3b1f795cd4fc20f57e1f3", "shasum": "" }, "require": { @@ -4796,6 +4792,7 @@ }, "require-dev": { "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^8.5.8|^9.3.3" }, "suggest": { @@ -4836,9 +4833,9 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.8.1" + "source": "https://github.com/laravel/tinker/tree/v2.8.2" }, - "time": "2023-02-15T16:40:09+00:00" + "time": "2023-08-15T14:27:00+00:00" }, { "name": "laravel/ui", @@ -9981,22 +9978,22 @@ }, { "name": "socialiteproviders/manager", - "version": "v4.3.0", + "version": "v4.4.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Manager.git", - "reference": "47402cbc5b7ef445317e799bf12fd5a12062206c" + "reference": "df5e45b53d918ec3d689f014d98a6c838b98ed96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/47402cbc5b7ef445317e799bf12fd5a12062206c", - "reference": "47402cbc5b7ef445317e799bf12fd5a12062206c", + "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/df5e45b53d918ec3d689f014d98a6c838b98ed96", + "reference": "df5e45b53d918ec3d689f014d98a6c838b98ed96", "shasum": "" }, "require": { "illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0", "laravel/socialite": "~5.0", - "php": "^7.4 || ^8.0" + "php": "^8.0" }, "require-dev": { "mockery/mockery": "^1.2", @@ -10051,7 +10048,7 @@ "issues": "https://github.com/socialiteproviders/manager/issues", "source": "https://github.com/socialiteproviders/manager" }, - "time": "2023-01-26T23:11:27+00:00" + "time": "2023-08-27T23:46:34+00:00" }, { "name": "socialiteproviders/microsoft", @@ -11747,16 +11744,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "shasum": "" }, "require": { @@ -11771,7 +11768,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -11809,7 +11806,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" }, "funding": [ { @@ -11825,20 +11822,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + "reference": "875e90aeea2777b6f135677f618529449334a612" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", "shasum": "" }, "require": { @@ -11850,7 +11847,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -11890,7 +11887,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" }, "funding": [ { @@ -11906,20 +11903,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c" + "reference": "e46b4da57951a16053cd751f63f4a24292788157" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/a3d9148e2c363588e05abbdd4ee4f971f0a5330c", - "reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e46b4da57951a16053cd751f63f4a24292788157", + "reference": "e46b4da57951a16053cd751f63f4a24292788157", "shasum": "" }, "require": { @@ -11931,7 +11928,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -11977,7 +11974,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.28.0" }, "funding": [ { @@ -11993,20 +11990,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-03-21T17:27:24+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da" + "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", + "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", "shasum": "" }, "require": { @@ -12020,7 +12017,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -12064,7 +12061,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" }, "funding": [ { @@ -12080,20 +12077,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:30:37+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "shasum": "" }, "require": { @@ -12105,7 +12102,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -12148,7 +12145,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" }, "funding": [ { @@ -12164,20 +12161,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "42292d99c55abe617799667f454222c54c60e229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", "shasum": "" }, "require": { @@ -12192,7 +12189,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -12231,7 +12228,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" }, "funding": [ { @@ -12247,20 +12244,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-07-28T09:04:16+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97" + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", "shasum": "" }, "require": { @@ -12269,7 +12266,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -12307,7 +12304,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" }, "funding": [ { @@ -12323,20 +12320,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" + "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5", + "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5", "shasum": "" }, "require": { @@ -12345,7 +12342,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -12386,7 +12383,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.28.0" }, "funding": [ { @@ -12402,20 +12399,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "shasum": "" }, "require": { @@ -12424,7 +12421,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -12469,7 +12466,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" }, "funding": [ { @@ -12485,20 +12482,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "508c652ba3ccf69f8c97f251534f229791b52a57" + "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/508c652ba3ccf69f8c97f251534f229791b52a57", - "reference": "508c652ba3ccf69f8c97f251534f229791b52a57", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", "shasum": "" }, "require": { @@ -12508,7 +12505,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -12521,7 +12518,10 @@ ], "psr-4": { "Symfony\\Polyfill\\Php83\\": "" - } + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -12546,7 +12546,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0" }, "funding": [ { @@ -12562,20 +12562,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-08-16T06:22:46+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166" + "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/f3cf1a645c2734236ed1e2e671e273eeb3586166", - "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/9c44518a5aff8da565c8a55dbe85d2769e6f630e", + "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e", "shasum": "" }, "require": { @@ -12590,7 +12590,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -12628,7 +12628,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.28.0" }, "funding": [ { @@ -12644,7 +12644,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/postmark-mailer", @@ -14277,6 +14277,44 @@ "source": "https://github.com/wepay/PHP-SDK/tree/master" }, "time": "2017-01-21T07:03:26+00:00" + }, + { + "name": "wildbit/postmark-php", + "version": "v4.0.5", + "source": { + "type": "git", + "url": "https://github.com/ActiveCampaign/postmark-php.git", + "reference": "b71efba061de7cf7e1f853d211b1c5edce4e3c5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ActiveCampaign/postmark-php/zipball/b71efba061de7cf7e1f853d211b1c5edce4e3c5b", + "reference": "b71efba061de7cf7e1f853d211b1c5edce4e3c5b", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0|^7.0", + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Postmark\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The officially supported client for Postmark (http://postmarkapp.com)", + "support": { + "issues": "https://github.com/ActiveCampaign/postmark-php/issues", + "source": "https://github.com/ActiveCampaign/postmark-php/tree/v4.0.5" + }, + "time": "2023-02-03T15:00:17+00:00" } ], "packages-dev": [ @@ -14512,16 +14550,16 @@ }, { "name": "brianium/paratest", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "4d7ad5b6564f63baa1b948ecad05439f22880942" + "reference": "7f372b5bb59b4271adedc67d3129df29b84c4173" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/4d7ad5b6564f63baa1b948ecad05439f22880942", - "reference": "4d7ad5b6564f63baa1b948ecad05439f22880942", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/7f372b5bb59b4271adedc67d3129df29b84c4173", + "reference": "7f372b5bb59b4271adedc67d3129df29b84c4173", "shasum": "" }, "require": { @@ -14535,19 +14573,19 @@ "phpunit/php-code-coverage": "^10.1.3", "phpunit/php-file-iterator": "^4.0.2", "phpunit/php-timer": "^6.0", - "phpunit/phpunit": "^10.3.1", + "phpunit/phpunit": "^10.3.2", "sebastian/environment": "^6.0.1", - "symfony/console": "^6.3.2", - "symfony/process": "^6.3.2" + "symfony/console": "^6.3.4", + "symfony/process": "^6.3.4" }, "require-dev": { "doctrine/coding-standard": "^12.0.0", "ext-pcov": "*", "ext-posix": "*", "infection/infection": "^0.27.0", - "phpstan/phpstan": "^1.10.26", - "phpstan/phpstan-deprecation-rules": "^1.1.3", - "phpstan/phpstan-phpunit": "^1.3.13", + "phpstan/phpstan": "^1.10.32", + "phpstan/phpstan-deprecation-rules": "^1.1.4", + "phpstan/phpstan-phpunit": "^1.3.14", "phpstan/phpstan-strict-rules": "^1.5.1", "squizlabs/php_codesniffer": "^3.7.2", "symfony/filesystem": "^6.3.1" @@ -14591,7 +14629,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.2.5" + "source": "https://github.com/paratestphp/paratest/tree/v7.2.6" }, "funding": [ { @@ -14603,7 +14641,7 @@ "type": "paypal" } ], - "time": "2023-08-08T13:23:59+00:00" + "time": "2023-08-29T07:47:39+00:00" }, { "name": "composer/class-map-generator", @@ -15030,16 +15068,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.23.0", + "version": "v3.24.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "35af3cbbacfa91e164b252a28ec0b644f1ed4e78" + "reference": "bb6c9d7945dcbf6942e151b018c44d3767e21403" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/35af3cbbacfa91e164b252a28ec0b644f1ed4e78", - "reference": "35af3cbbacfa91e164b252a28ec0b644f1ed4e78", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/bb6c9d7945dcbf6942e151b018c44d3767e21403", + "reference": "bb6c9d7945dcbf6942e151b018c44d3767e21403", "shasum": "" }, "require": { @@ -15115,7 +15153,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.23.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.24.0" }, "funding": [ { @@ -15123,7 +15161,7 @@ "type": "github" } ], - "time": "2023-08-14T12:27:35+00:00" + "time": "2023-08-29T23:18:45+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -17598,16 +17636,16 @@ }, { "name": "symfony/polyfill-php81", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", "shasum": "" }, "require": { @@ -17616,7 +17654,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -17657,7 +17695,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" }, "funding": [ { @@ -17673,7 +17711,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/stopwatch", diff --git a/lang/en/texts.php b/lang/en/texts.php index a96969812c96..183cbf5c8c04 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -1150,7 +1150,7 @@ $LANG = array( 'plan_status' => 'Plan Status', 'plan_upgrade' => 'Upgrade', - 'plan_change' => 'Change Plan', + 'plan_change' => 'Manage Plan', 'pending_change_to' => 'Changes To', 'plan_changes_to' => ':plan on :date', 'plan_term_changes_to' => ':plan (:term) on :date', @@ -4330,7 +4330,7 @@ $LANG = array( 'include_drafts' => 'Include Drafts', 'include_drafts_help' => 'Include draft records in reports', 'is_invoiced' => 'Is Invoiced', - 'change_plan' => 'Change Plan', + 'change_plan' => 'Manage Plan', 'persist_data' => 'Persist Data', 'customer_count' => 'Customer Count', 'verify_customers' => 'Verify Customers', @@ -5158,8 +5158,7 @@ $LANG = array( 'unlinked_transaction' => 'Successfully unlinked transaction', 'view_dashboard_permission' => 'Allow user to access the dashboard, data is limited to available permissions', 'marked_sent_credits' => 'Successfully marked credits sent', - -); +); return $LANG; diff --git a/routes/api.php b/routes/api.php index 34e6c57c308b..aa4e108a5273 100644 --- a/routes/api.php +++ b/routes/api.php @@ -58,6 +58,7 @@ use App\Http\Controllers\TaskStatusController; use App\Http\Controllers\Bank\YodleeController; use App\Http\Controllers\CompanyUserController; use App\Http\Controllers\PaymentTermController; +use App\Http\Controllers\EmailHistoryController; use App\Http\Controllers\GroupSettingController; use App\Http\Controllers\OneTimeTokenController; use App\Http\Controllers\SubscriptionController; @@ -202,6 +203,8 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale'] Route::post('documents/bulk', [DocumentController::class, 'bulk'])->name('documents.bulk'); Route::post('emails', [EmailController::class, 'send'])->name('email.send')->middleware('user_verified'); + Route::post('emails/clientHistory/{client}', [EmailHistoryController::class, 'clientHistory'])->name('email.clientHistory'); + Route::post('emails/entityHistory', [EmailHistoryController::class, 'entityHistory'])->name('email.entityHistory'); Route::resource('expenses', ExpenseController::class); // name = (expenses. index / create / show / update / destroy / edit Route::put('expenses/{expense}/upload', [ExpenseController::class, 'upload']); diff --git a/tests/Feature/Export/ReportApiTest.php b/tests/Feature/Export/ReportApiTest.php index 408177031db8..9a8354b13c8b 100644 --- a/tests/Feature/Export/ReportApiTest.php +++ b/tests/Feature/Export/ReportApiTest.php @@ -43,6 +43,23 @@ class ReportApiTest extends TestCase } + + public function testActivityCSVExport() + { + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/activities', $data) + ->assertStatus(200); + + } + public function testUserSalesReportApiRoute() { $data = [ @@ -126,6 +143,8 @@ class ReportApiTest extends TestCase } + + public function testClientBalanceReportApiRoute() { $data = [ diff --git a/tests/Feature/Export/ReportCsvGenerationTest.php b/tests/Feature/Export/ReportCsvGenerationTest.php index a0ead0a357f2..32e264c3e251 100644 --- a/tests/Feature/Export/ReportCsvGenerationTest.php +++ b/tests/Feature/Export/ReportCsvGenerationTest.php @@ -527,7 +527,7 @@ class ReportCsvGenerationTest extends TestCase ])->post('/api/v1/reports/products', $data); $csv = $response->streamedContent(); - +// nlog($csv); $this->assertEquals('product_key', $this->getFirstValueByColumn($csv, 'Product')); $this->assertEquals('notes', $this->getFirstValueByColumn($csv, 'Notes')); $this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Cost')); @@ -649,11 +649,11 @@ class ReportCsvGenerationTest extends TestCase $csv = $response->streamedContent(); - $this->assertEquals(500, $this->getFirstValueByColumn($csv, 'Amount')); - $this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Applied')); - $this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Refunded')); - $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Date')); - $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Transaction Reference')); + $this->assertEquals(500, $this->getFirstValueByColumn($csv, 'Payment Amount')); + $this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Payment Applied')); + $this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Payment Refunded')); + $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Payment Date')); + $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Payment Transaction Reference')); } @@ -673,7 +673,7 @@ class ReportCsvGenerationTest extends TestCase ])->post('/api/v1/reports/clients', $data); $csv = $response->streamedContent(); - +// nlog($csv); $reader = Reader::createFromString($csv); $reader->setHeaderOffset(0); @@ -748,7 +748,7 @@ class ReportCsvGenerationTest extends TestCase $arr = $response->json(); - nlog($arr['message']); + // nlog($arr['message']); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), @@ -849,7 +849,7 @@ class ReportCsvGenerationTest extends TestCase ])->post('/api/v1/reports/invoices', $data); $csv = $response->streamedContent(); - +// nlog($csv); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number')); $this->assertEquals('Unpaid', $this->getFirstValueByColumn($csv, 'Payment Amount')); @@ -985,20 +985,20 @@ class ReportCsvGenerationTest extends TestCase ])->post('/api/v1/reports/invoice_items', $data); $csv = $response->streamedContent(); - +// nlog($csv);// $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number')); $this->assertEquals('Unpaid', $this->getFirstValueByColumn($csv, 'Payment Amount')); $this->assertEquals('', $this->getFirstValueByColumn($csv, 'Payment Date')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quantity')); - $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Cost')); - $this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Line Total')); - $this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Discount')); - $this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Notes')); - $this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Product')); - $this->assertEquals('custom 1', $this->getFirstValueByColumn($csv, 'Custom Invoice 1')); - $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Tax Name 1')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Quantity')); + $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Item Cost')); + $this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Item Line Total')); + $this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Item Discount')); + $this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Item Notes')); + $this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Item Product')); + $this->assertEquals('custom 1', $this->getFirstValueByColumn($csv, 'Item Custom Value 1')); + $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1')); $data = [ @@ -1082,15 +1082,15 @@ class ReportCsvGenerationTest extends TestCase $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Quote Number')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quantity')); - $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Cost')); - $this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Line Total')); - $this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Discount')); - $this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Notes')); - $this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Product')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Quantity')); + $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Item Cost')); + $this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Item Line Total')); + $this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Item Discount')); + $this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Item Notes')); + $this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Item Product')); $this->assertEquals('custom 1', $this->getFirstValueByColumn($csv, 'Item Custom Value 1')); - $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Tax Name 1')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1')); + $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1')); $data = [ @@ -1222,15 +1222,15 @@ class ReportCsvGenerationTest extends TestCase $this->assertEquals('Vendor 1', $this->getFirstValueByColumn($csv, 'Vendor Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Purchase Order Number')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quantity')); - $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Cost')); - $this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Line Total')); - $this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Discount')); - $this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Notes')); - $this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Product')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Quantity')); + $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Item Cost')); + $this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Item Line Total')); + $this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Item Discount')); + $this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Item Notes')); + $this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Item Product')); $this->assertEquals('custom 1', $this->getFirstValueByColumn($csv, 'Item Custom Value 1')); - $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Tax Name 1')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1')); + $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1')); } @@ -1347,17 +1347,17 @@ class ReportCsvGenerationTest extends TestCase $reader = Reader::createFromString($csv); $reader->setHeaderOffset(0); - $res = $reader->fetchColumnByName('First Name'); + $res = $reader->fetchColumnByName('Contact First Name'); $res = iterator_to_array($res, true); $this->assertEquals('john', $res[1]); - $res = $reader->fetchColumnByName('Last Name'); + $res = $reader->fetchColumnByName('Contact Last Name'); $res = iterator_to_array($res, true); $this->assertEquals('doe', $res[1]); - $res = $reader->fetchColumnByName('Email'); + $res = $reader->fetchColumnByName('Contact Email'); $res = iterator_to_array($res, true); $this->assertEquals('john@doe.com', $res[1]); @@ -1406,14 +1406,14 @@ class ReportCsvGenerationTest extends TestCase $response->assertStatus(200); $csv = $response->streamedContent(); -nlog($csv); - $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Amount')); - $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Balance')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Discount')); - $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'PO Number')); - $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes')); - $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes')); - $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Terms')); + + $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Credit Amount')); + $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Credit Balance')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Credit Discount')); + $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Credit PO Number')); + $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Credit Public Notes')); + $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Credit Private Notes')); + $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Credit Terms')); $data = [ @@ -1492,29 +1492,29 @@ nlog($csv); $csv = $response->streamedContent(); - $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Amount')); - $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Balance')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Discount')); - $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'PO Number')); - $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes')); - $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes')); - $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Terms')); - $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Date')); - $this->assertEquals('2021-01-02', $this->getFirstValueByColumn($csv, 'Due Date')); - $this->assertEquals('2021-01-03', $this->getFirstValueByColumn($csv, 'Partial Due Date')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Partial/Deposit')); - $this->assertEquals('Custom 1', $this->getFirstValueByColumn($csv, 'Custom Value 1')); - $this->assertEquals('Custom 2', $this->getFirstValueByColumn($csv, 'Custom Value 2')); - $this->assertEquals('Custom 3', $this->getFirstValueByColumn($csv, 'Custom Value 3')); - $this->assertEquals('Custom 4', $this->getFirstValueByColumn($csv, 'Custom Value 4')); - $this->assertEquals('Footer', $this->getFirstValueByColumn($csv, 'Footer')); - $this->assertEquals('Tax 1', $this->getFirstValueByColumn($csv, 'Tax Name 1')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1')); - $this->assertEquals('Tax 2', $this->getFirstValueByColumn($csv, 'Tax Name 2')); - $this->assertEquals('20', $this->getFirstValueByColumn($csv, 'Tax Rate 2')); - $this->assertEquals('Tax 3', $this->getFirstValueByColumn($csv, 'Tax Name 3')); - $this->assertEquals('30', $this->getFirstValueByColumn($csv, 'Tax Rate 3')); - $this->assertEquals('Sent', $this->getFirstValueByColumn($csv, 'Status')); + $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Invoice Amount')); + $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Invoice Balance')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Invoice Discount')); + $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Invoice PO Number')); + $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Invoice Public Notes')); + $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Invoice Private Notes')); + $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Invoice Terms')); + $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Invoice Date')); + $this->assertEquals('2021-01-02', $this->getFirstValueByColumn($csv, 'Invoice Due Date')); + $this->assertEquals('2021-01-03', $this->getFirstValueByColumn($csv, 'Invoice Partial Due Date')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Invoice Partial/Deposit')); + $this->assertEquals('Custom 1', $this->getFirstValueByColumn($csv, 'Invoice Custom Value 1')); + $this->assertEquals('Custom 2', $this->getFirstValueByColumn($csv, 'Invoice Custom Value 2')); + $this->assertEquals('Custom 3', $this->getFirstValueByColumn($csv, 'Invoice Custom Value 3')); + $this->assertEquals('Custom 4', $this->getFirstValueByColumn($csv, 'Invoice Custom Value 4')); + $this->assertEquals('Footer', $this->getFirstValueByColumn($csv, 'Invoice Footer')); + $this->assertEquals('Tax 1', $this->getFirstValueByColumn($csv, 'Invoice Tax Name 1')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Invoice Tax Rate 1')); + $this->assertEquals('Tax 2', $this->getFirstValueByColumn($csv, 'Invoice Tax Name 2')); + $this->assertEquals('20', $this->getFirstValueByColumn($csv, 'Invoice Tax Rate 2')); + $this->assertEquals('Tax 3', $this->getFirstValueByColumn($csv, 'Invoice Tax Name 3')); + $this->assertEquals('30', $this->getFirstValueByColumn($csv, 'Invoice Tax Rate 3')); + $this->assertEquals('Sent', $this->getFirstValueByColumn($csv, 'Invoice Status')); } @@ -1642,30 +1642,32 @@ nlog($csv); $response->assertStatus(200); $csv = $response->streamedContent(); + + //nlog($csv); - $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Amount')); - $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Balance')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Discount')); - $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'PO Number')); - $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes')); - $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes')); - $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Terms')); - $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Date')); - $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Valid Until')); - $this->assertEquals('2021-01-03', $this->getFirstValueByColumn($csv, 'Partial Due Date')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Partial/Deposit')); - $this->assertEquals('Custom 1', $this->getFirstValueByColumn($csv, 'Custom Value 1')); - $this->assertEquals('Custom 2', $this->getFirstValueByColumn($csv, 'Custom Value 2')); - $this->assertEquals('Custom 3', $this->getFirstValueByColumn($csv, 'Custom Value 3')); - $this->assertEquals('Custom 4', $this->getFirstValueByColumn($csv, 'Custom Value 4')); - $this->assertEquals('Footer', $this->getFirstValueByColumn($csv, 'Footer')); - $this->assertEquals('Tax 1', $this->getFirstValueByColumn($csv, 'Tax Name 1')); - $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1')); - $this->assertEquals('Tax 2', $this->getFirstValueByColumn($csv, 'Tax Name 2')); - $this->assertEquals('20', $this->getFirstValueByColumn($csv, 'Tax Rate 2')); - $this->assertEquals('Tax 3', $this->getFirstValueByColumn($csv, 'Tax Name 3')); - $this->assertEquals('30', $this->getFirstValueByColumn($csv, 'Tax Rate 3')); - $this->assertEquals('Expired', $this->getFirstValueByColumn($csv, 'Status')); + $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Quote Amount')); + $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Quote Balance')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quote Discount')); + $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Quote PO Number')); + $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Quote Public Notes')); + $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Quote Private Notes')); + $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Quote Terms')); + $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Quote Date')); + $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Quote Valid Until')); + $this->assertEquals('2021-01-03', $this->getFirstValueByColumn($csv, 'Quote Partial Due Date')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quote Partial/Deposit')); + $this->assertEquals('Custom 1', $this->getFirstValueByColumn($csv, 'Quote Custom Value 1')); + $this->assertEquals('Custom 2', $this->getFirstValueByColumn($csv, 'Quote Custom Value 2')); + $this->assertEquals('Custom 3', $this->getFirstValueByColumn($csv, 'Quote Custom Value 3')); + $this->assertEquals('Custom 4', $this->getFirstValueByColumn($csv, 'Quote Custom Value 4')); + $this->assertEquals('Footer', $this->getFirstValueByColumn($csv, 'Quote Footer')); + $this->assertEquals('Tax 1', $this->getFirstValueByColumn($csv, 'Quote Tax Name 1')); + $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quote Tax Rate 1')); + $this->assertEquals('Tax 2', $this->getFirstValueByColumn($csv, 'Quote Tax Name 2')); + $this->assertEquals('20', $this->getFirstValueByColumn($csv, 'Quote Tax Rate 2')); + $this->assertEquals('Tax 3', $this->getFirstValueByColumn($csv, 'Quote Tax Name 3')); + $this->assertEquals('30', $this->getFirstValueByColumn($csv, 'Quote Tax Rate 3')); + $this->assertEquals('Expired', $this->getFirstValueByColumn($csv, 'Quote Status')); } @@ -1696,10 +1698,10 @@ nlog($csv); $csv = $response->streamedContent(); - $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Amount')); - $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes')); - $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes')); - $this->assertEquals($this->user->present()->name(), $this->getFirstValueByColumn($csv, 'User')); + $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Expense Amount')); + $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Expense Public Notes')); + $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Expense Private Notes')); + $this->assertEquals($this->user->present()->name(), $this->getFirstValueByColumn($csv, 'Expense User')); $data = [ @@ -1758,8 +1760,8 @@ nlog($csv); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('Vendor 1', $this->getFirstValueByColumn($csv, 'Vendor Name')); - $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Amount')); - $this->assertEquals('USD', $this->getFirstValueByColumn($csv, 'Currency')); + $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Expense Amount')); + $this->assertEquals('USD', $this->getFirstValueByColumn($csv, 'Expense Currency')); } diff --git a/tests/Feature/Export/ReportPreviewTest.php b/tests/Feature/Export/ReportPreviewTest.php index 75516cea6e58..5d8c77291bb3 100644 --- a/tests/Feature/Export/ReportPreviewTest.php +++ b/tests/Feature/Export/ReportPreviewTest.php @@ -12,10 +12,24 @@ namespace Tests\Feature\Export; use Tests\TestCase; +use App\Models\Client; +use App\Models\Expense; +use App\Models\Document; use Tests\MockAccountData; +use App\Export\CSV\QuoteExport; use App\Utils\Traits\MakesHash; +use App\Export\CSV\ClientExport; use App\Export\CSV\CreditExport; +use App\Export\CSV\ContactExport; +use App\Export\CSV\ExpenseExport; +use App\Export\CSV\InvoiceExport; +use App\Export\CSV\PaymentExport; +use App\Export\CSV\ProductExport; +use App\Export\CSV\ActivityExport; +use App\Export\CSV\DocumentExport; use App\Jobs\Report\PreviewReport; +use Illuminate\Support\Facades\Cache; +use App\Export\CSV\PurchaseOrderExport; use Illuminate\Routing\Middleware\ThrottleRequests; /** @@ -44,6 +58,407 @@ class ReportPreviewTest extends TestCase } + + public function testProductJsonExport() + { + \App\Models\Product::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/products?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, ProductExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + } + + + public function testPaymentJsonExport() + { + \App\Models\Payment::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/payments?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, PaymentExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + } + + + public function testPurchaseOrderItemJsonExport() + { + \App\Models\PurchaseOrder::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'vendor_id' => $this->vendor->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/purchase_order_items?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, \App\Export\CSV\PurchaseOrderItemExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + //nlog($r); + + } + + public function testQuoteItemJsonExport() + { + \App\Models\Quote::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/quote_items?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, \App\Export\CSV\QuoteItemExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + //nlog($r); + + } + + + public function testInvoiceItemJsonExport() + { + \App\Models\Invoice::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/invoice_items?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, \App\Export\CSV\InvoiceItemExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + //nlog($r); + + } + + + + public function testPurchaseOrderJsonExport() + { + \App\Models\PurchaseOrder::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'vendor_id' => $this->vendor->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/purchase_orders?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, PurchaseOrderExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + } + + public function testQuoteJsonExport() + { + \App\Models\Quote::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/quotes?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, QuoteExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + } + + public function testInvoiceJsonExport() + { + \App\Models\Invoice::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/invoices?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, InvoiceExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + } + + public function testExpenseJsonExport() + { + Expense::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/expenses?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, ExpenseExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); +//nlog($r); + } + + public function testDocumentJsonExport() + { + Document::factory()->count(5)->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'documentable_type' => Client::class, + 'documentable_id' => $this->client->id, + ]); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/documents?output=json', $data) + ->assertStatus(200); + + $p = (new PreviewReport($this->company, $data, DocumentExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); +//nlog($r); + } + + public function testClientExportJson() + { + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/clients?output=json', $data) + ->assertStatus(200); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => ['client.name','client.balance'], + ]; + + + $p = (new PreviewReport($this->company, $data, ClientExport::class, 'client_export1'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('client_export1'); + + $this->assertNotNull($r); + + + } + + public function testClientContactExportJsonLimitedKeys() + { + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/client_contacts?output=json', $data) + ->assertStatus(200); + + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => ['client.name','client.balance','contact.email'], + ]; + + + $p = (new PreviewReport($this->company, $data, ContactExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + } + + public function testActivityCSVExportJson() + { + $data = [ + 'send_email' => false, + 'date_range' => 'all', + 'report_keys' => [], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/reports/activities?output=json', $data) + ->assertStatus(200); + + + $p = (new PreviewReport($this->company, $data, ActivityExport::class, '123'))->handle(); + + $this->assertNull($p); + + $r = Cache::pull('123'); + + $this->assertNotNull($r); + + + } + public function testCreditExportPreview() { @@ -57,6 +472,10 @@ class ReportPreviewTest extends TestCase $this->assertNull($p); + $r = Cache::pull('123'); + + $this->assertNotNull($r); + } public function testCreditPreview() @@ -73,5 +492,6 @@ class ReportPreviewTest extends TestCase ])->postJson('/api/v1/reports/credits?output=json', $data) ->assertStatus(200); + } } \ No newline at end of file diff --git a/tests/Feature/InvoiceEmailTest.php b/tests/Feature/InvoiceEmailTest.php index 9bfcb5512402..a08b306aa44d 100644 --- a/tests/Feature/InvoiceEmailTest.php +++ b/tests/Feature/InvoiceEmailTest.php @@ -11,15 +11,16 @@ namespace Tests\Feature; +use Tests\TestCase; +use App\Models\SystemLog; +use Tests\MockAccountData; use App\Jobs\Entity\EmailEntity; use App\Utils\Traits\GeneratesCounter; use Illuminate\Database\Eloquent\Model; -use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Bus; use Illuminate\Support\Facades\Session; use Illuminate\Validation\ValidationException; -use Tests\MockAccountData; -use Tests\TestCase; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @test @@ -47,6 +48,109 @@ class InvoiceEmailTest extends TestCase } + public function testClientEmailHistory() + { + $system_log = new SystemLog(); + $system_log->company_id = $this->company->id; + $system_log->client_id = $this->client->id; + $system_log->category_id = SystemLog::CATEGORY_MAIL; + $system_log->event_id = SystemLog::EVENT_MAIL_SEND; + $system_log->type_id = SystemLog::TYPE_WEBHOOK_RESPONSE; + $system_log->log = [ + 'history' => [ + 'entity_id' => $this->invoice->hashed_id, + 'entity_type' => 'invoice', + 'subject' => 'Invoice #1', + 'events' => [ + [ + 'recipient' => 'bob@gmail.com', + 'status' => 'Delivered', + 'delivery_message' => 'A message that was deliveryed', + 'server' => 'email.mx.com', + 'server_ip' => '127.0.0.1', + 'date' => \Carbon\Carbon::parse('2023-10-10')->format('Y-m-d H:m:s') ?? '', + ], + ], + ] + ]; + + $system_log->save(); + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/emails/clientHistory/'.$this->client->hashed_id); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('invoice', $arr[0]['entity_type']); + + $count = SystemLog::where('client_id', $this->client->id) + ->where('category_id', SystemLog::CATEGORY_MAIL) + ->orderBy('id', 'DESC') + ->count(); + + $this->assertEquals(1, $count); + } + + public function testEntityEmailHistory() + { + $system_log = new SystemLog(); + $system_log->company_id = $this->company->id; + $system_log->client_id = $this->client->id; + $system_log->category_id = SystemLog::CATEGORY_MAIL; + $system_log->event_id = SystemLog::EVENT_MAIL_SEND; + $system_log->type_id = SystemLog::TYPE_WEBHOOK_RESPONSE; + $system_log->log = [ + 'history' => [ + 'entity_id' => $this->invoice->hashed_id, + 'entity_type' => 'invoice', + 'subject' => 'Invoice #1', + 'events' => [ + [ + 'recipient' => 'bob@gmail.com', + 'status' => 'Delivered', + 'delivery_message' => 'A message that was deliveryed', + 'server' => 'email.mx.com', + 'server_ip' => '127.0.0.1', + 'date' => \Carbon\Carbon::parse('2023-10-10')->format('Y-m-d H:m:s') ?? '', + ], + ], + ] + ]; + + $system_log->save(); + + $data = [ + 'entity' => 'invoice', + 'entity_id' => $this->invoice->hashed_id, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/emails/entityHistory/', $data); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('invoice', $arr[0]['entity_type']); + $this->assertEquals($this->invoice->hashed_id, $arr[0]['entity_id']); + + $count = SystemLog::where('company_id', $this->company->id) + ->where('category_id', SystemLog::CATEGORY_MAIL) + ->whereJsonContains('log->history->entity_id', $this->invoice->hashed_id) + ->count(); + + $this->assertEquals(1, $count); + + } + + public function testTemplateValidation() { $data = [ diff --git a/tests/Feature/ReminderTest.php b/tests/Feature/ReminderTest.php index 2d77e88e8ad9..ca4265d2ebc1 100644 --- a/tests/Feature/ReminderTest.php +++ b/tests/Feature/ReminderTest.php @@ -11,15 +11,23 @@ namespace Tests\Feature; -use App\Jobs\Util\ReminderJob; -use App\Models\Invoice; -use App\Utils\Traits\MakesHash; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Foundation\Testing\DatabaseTransactions; -use Illuminate\Routing\Middleware\ThrottleRequests; -use Illuminate\Support\Carbon; -use Tests\MockAccountData; use Tests\TestCase; +use App\Models\User; +use App\Models\Client; +use App\Models\Account; +use App\Models\Company; +use App\Models\Invoice; +use Tests\MockAccountData; +use App\Models\CompanyToken; +use App\Models\ClientContact; +use App\Jobs\Util\ReminderJob; +use Illuminate\Support\Carbon; +use App\Utils\Traits\MakesHash; +use App\DataMapper\CompanySettings; +use App\Factory\CompanyUserFactory; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @test @@ -49,10 +57,201 @@ class ReminderTest extends TestCase $this->withoutExceptionHandling(); } + public $company; + + public $user; + + public $payload; + + public $account; + + public $client; + + public $token; + + public $cu; + + public $invoice; + + private function buildData($settings = null) + { + $this->account = Account::factory()->create([ + 'hosted_client_count' => 1000, + 'hosted_company_count' => 1000, + ]); + + $this->account->num_users = 3; + $this->account->save(); + + $this->user = User::factory()->create([ + 'account_id' => $this->account->id, + 'confirmation_code' => 'xyz123', + 'email' => $this->faker->unique()->safeEmail(), + ]); + + if(!$settings) + { + $settings = CompanySettings::defaults(); + $settings->client_online_payment_notification = false; + $settings->client_manual_payment_notification = false; + } + + $this->company = Company::factory()->create([ + 'account_id' => $this->account->id, + 'settings' => $settings, + ]); + + $this->company->settings = $settings; + $this->company->save(); + + $this->cu = CompanyUserFactory::create($this->user->id, $this->company->id, $this->account->id); + $this->cu->is_owner = true; + $this->cu->is_admin = true; + $this->cu->is_locked = false; + $this->cu->save(); + + $this->token = \Illuminate\Support\Str::random(64); + + $company_token = new CompanyToken; + $company_token->user_id = $this->user->id; + $company_token->company_id = $this->company->id; + $company_token->account_id = $this->account->id; + $company_token->name = 'test token'; + $company_token->token = $this->token; + $company_token->is_system = true; + + $company_token->save(); + + $this->client = Client::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'is_deleted' => 0, + 'name' => 'bob', + 'address1' => '1234', + 'balance' => 100, + 'paid_to_date' => 50, + ]); + + ClientContact::factory()->create([ + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'company_id' => $this->company->id, + 'is_primary' => 1, + 'first_name' => 'john', + 'last_name' => 'doe', + 'email' => 'john@doe.com' + ]); + + $this->invoice = Invoice::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'client_id' => $this->client->id, + 'date' => now()->addSeconds($this->client->timezone_offset())->format('Y-m-d'), + 'next_send_date' => null, + 'due_date' => Carbon::now()->addSeconds($this->client->timezone_offset())->addDays(5)->format('Y-m-d'), + 'last_sent_date' => now()->addSeconds($this->client->timezone_offset()), + 'reminder_last_sent' => null, + 'status_id' => 2, + 'amount' => 10, + 'balance' => 10, + ]); + + } + + public function testsForTranslationsInReminders() + { + + $translations = new \stdClass; + $translations->late_fee_added = "Fee added :date"; + + $settings = $this->company->settings; + $settings->enable_reminder1 = true; + $settings->schedule_reminder1 = 'after_invoice_date'; + $settings->num_days_reminder1 = 1; + $settings->enable_reminder2 = true; + $settings->schedule_reminder2 = 'after_invoice_date'; + $settings->num_days_reminder2 = 2; + $settings->enable_reminder3 = true; + $settings->schedule_reminder3 = 'after_invoice_date'; + $settings->num_days_reminder3 = 3; + $settings->timezone_id = '29'; + $settings->entity_send_time = 0; + $settings->endless_reminder_frequency_id = ''; + $settings->enable_reminder_endless = false; + $settings->translations = $translations; + $settings->late_fee_amount1 = '101'; + $settings->late_fee_amount2 = '102'; + $settings->late_fee_amount3 = '103'; + + $this->buildData(($settings)); + + $this->assertEquals("Fee added :date", $this->company->settings->translations->late_fee_added); + $fetched_settings = $this->client->getMergedSettings(); + $this->assertEquals("Fee added :date", $fetched_settings->translations->late_fee_added); + + $this->invoice->service()->setReminder($settings)->save(); + + $this->invoice = $this->invoice->fresh(); + + $this->assertEquals(now()->addSeconds($this->client->timezone_offset())->format('Y-m-d'), $this->invoice->date); + $this->assertNotNull($this->invoice->next_send_date); + $this->assertEquals(now()->addDay()->addSeconds($this->client->timezone_offset())->format('Y-m-d 00:00:00'), $this->invoice->next_send_date); + + $this->travelTo(now()->addDay()->startOfDay()->addHour()); + + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + $this->assertNotNull($this->invoice->reminder1_sent); + $this->assertNotNull($this->invoice->reminder_last_sent); + + $fee = collect($this->invoice->line_items)->where('type_id', 5)->first(); + + $this->assertEquals(101, $fee->cost); + $this->assertEquals('Fee added '.now()->format('d/M/Y'), $fee->notes); + + $this->travelTo(now()->addDay()->startOfDay()->addHour()); + + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + $this->assertNotNull($this->invoice->reminder2_sent); + $this->assertNotNull($this->invoice->reminder_last_sent); + + $fee = collect($this->invoice->line_items)->where('cost', 102)->first(); + + $this->assertEquals(102, $fee->cost); + $this->assertEquals('Fee added '.now()->format('d/M/Y'), $fee->notes); + + $this->travelTo(now()->addDay()->startOfDay()->addHour()); + + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + $this->assertNotNull($this->invoice->reminder3_sent); + $this->assertNotNull($this->invoice->reminder_last_sent); + + $fee = collect($this->invoice->line_items)->where('cost', 103)->first(); + + $this->assertEquals(103, $fee->cost); + $this->assertEquals('Fee added '.now()->format('d/M/Y'), $fee->notes); + + + + + + + + // $this->travelTo(now()->addHours(1)); +// } + + + $this->travelBack(); + + } public function testForReminderFiringCorrectly() { - + $this->invoice->status_id = 2; + $this->invoice->amount = 10; + $this->invoice->balance = 10; $this->invoice->next_send_date = null; $this->invoice->date = now()->format('Y-m-d'); $this->invoice->last_sent_date = now(); diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index f00d619ee2a9..a49d26bcf7eb 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -572,6 +572,8 @@ trait MockAccountData $this->purchase_order->tax_rate2 = 0; $this->purchase_order->tax_rate3 = 0; + $this->purchase_order->line_items = InvoiceItemFactory::generate(5); + $this->purchase_order->uses_inclusive_taxes = false; $this->purchase_order->save();