From 3ac6f4c2a76ca37041528cfc40d70531fcdb9acf Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 15 Oct 2023 17:27:00 +1100 Subject: [PATCH 01/15] Catch missing props --- app/PaymentDrivers/Eway/CreditCard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index 11dbafdcfe2b..d4203d0eab9f 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -251,7 +251,7 @@ class CreditCard $response = $this->eway_driver->init()->eway->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); - if ($response->TransactionStatus) { + if ($response->TransactionStatus ?? false) { $this->logResponse($response, true); $payment = $this->storePayment($response); } else { From bf935896073f1a5b7b7927c030b653a452929dca Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Oct 2023 06:27:37 +1100 Subject: [PATCH 02/15] Only add shipping address to einvoice if country is set. --- app/Services/Invoice/EInvoice/ZugferdEInvoice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Services/Invoice/EInvoice/ZugferdEInvoice.php b/app/Services/Invoice/EInvoice/ZugferdEInvoice.php index 6b7dbe884350..539e78f6e270 100644 --- a/app/Services/Invoice/EInvoice/ZugferdEInvoice.php +++ b/app/Services/Invoice/EInvoice/ZugferdEInvoice.php @@ -75,7 +75,7 @@ class ZugferdEInvoice extends AbstractService } else { $this->xrechnung->setDocumentBuyerReference($client->routing_id); } - if (!empty($client->shipping_address1)){ + if (!empty($client->shipping_address1) && $client->shipping_country->exists()){ $this->xrechnung->setDocumentShipToAddress($client->shipping_address1, $client->shipping_address2, "", $client->shipping_postal_code, $client->shipping_city, $client->shipping_country->iso_3166_2, $client->shipping_state); } From 55f71a27c7df25b10fa8e075d5521acdfd6f90b4 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Oct 2023 07:25:47 +1100 Subject: [PATCH 03/15] Fixes for square autobill --- app/PaymentDrivers/Square/SquareWebhook.php | 10 ++++++++-- app/Services/Invoice/AutoBillInvoice.php | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/PaymentDrivers/Square/SquareWebhook.php b/app/PaymentDrivers/Square/SquareWebhook.php index c83b73fd4765..c638e2ad3bb7 100644 --- a/app/PaymentDrivers/Square/SquareWebhook.php +++ b/app/PaymentDrivers/Square/SquareWebhook.php @@ -134,8 +134,14 @@ class SquareWebhook implements ShouldQueue nlog("Searching by payment hash"); - $payment_hash_id = $apiResponse->getPayment()->getReferenceId() ?? false; - $square_payment = $apiResponse->getPayment()->jsonSerialize(); + $body = json_decode($apiResponse->getBody()); + + $payment_hash_id = $body->payment->reference_id ?? false; + $square_payment = $body->payment ?? false; + + if(!$payment_hash_id) + return; + $payment_hash = PaymentHash::query()->where('hash', $payment_hash_id)->firstOrFail(); $payment_hash->data = array_merge((array) $payment_hash->data, (array)$square_payment); diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index 0585f888bd66..19a366fdc507 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -120,7 +120,7 @@ class AutoBillInvoice extends AbstractService /* Build payment hash */ $payment_hash = PaymentHash::create([ - 'hash' => Str::random(64), + 'hash' => Str::random(32), 'data' => [ 'amount_with_fee' => $amount + $fee, 'invoices' => [ From 0694378bb5e83ffacab896751c1c8e53fafad6a8 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Oct 2023 07:28:17 +1100 Subject: [PATCH 04/15] Fixes for square autobill --- app/PaymentDrivers/Square/SquareWebhook.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/app/PaymentDrivers/Square/SquareWebhook.php b/app/PaymentDrivers/Square/SquareWebhook.php index c638e2ad3bb7..67d656e8c926 100644 --- a/app/PaymentDrivers/Square/SquareWebhook.php +++ b/app/PaymentDrivers/Square/SquareWebhook.php @@ -134,14 +134,8 @@ class SquareWebhook implements ShouldQueue nlog("Searching by payment hash"); - $body = json_decode($apiResponse->getBody()); - - $payment_hash_id = $body->payment->reference_id ?? false; - $square_payment = $body->payment ?? false; - - if(!$payment_hash_id) - return; - + $payment_hash_id = $apiResponse->getResult()->getPayment()->getReferenceId() ?? false; + $square_payment = $apiResponse->getResult()->getPayment()->jsonSerialize(); $payment_hash = PaymentHash::query()->where('hash', $payment_hash_id)->firstOrFail(); $payment_hash->data = array_merge((array) $payment_hash->data, (array)$square_payment); From fb3c0120ec7ff82c65ee6bf2bcd74098e84725a3 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 17 Oct 2023 13:39:36 +1100 Subject: [PATCH 05/15] Fixes for Email histoyr --- .../Controllers/EmailHistoryController.php | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/EmailHistoryController.php b/app/Http/Controllers/EmailHistoryController.php index 4da69ba7b6dc..aea6a5e2008f 100644 --- a/app/Http/Controllers/EmailHistoryController.php +++ b/app/Http/Controllers/EmailHistoryController.php @@ -31,11 +31,11 @@ class EmailHistoryController extends BaseController ->where('category_id', SystemLog::CATEGORY_MAIL) ->orderBy('id', 'DESC') ->cursor() - ->map(function ($system_log) { - if(($system_log->log['history'] && $system_log->log['history']['events'] && count($system_log->log['history']['events']) >=1) ?? false) { - return $system_log->log['history']; - } - }); + ->filter(function ($system_log) { + return ($system_log->log['history'] && isset($system_log->log['history']['events']) && count($system_log->log['history']['events']) >=1) !== false; + })->map(function ($system_log) { + return $system_log->log['history']; + })->values()->all(); return response()->json($data, 200); @@ -51,16 +51,17 @@ class EmailHistoryController extends BaseController /** @var \App\Models\User $user */ $user = auth()->user(); + $data = SystemLog::where('company_id', $user->company()->id) - ->where('category_id', SystemLog::CATEGORY_MAIL) - ->whereJsonContains('log->history->entity_id', $this->encodePrimaryKey($request->entity_id)) - ->orderBy('id', 'DESC') - ->cursor() - ->map(function ($system_log) { - if(($system_log->log['history'] && $system_log->log['history']['events'] && count($system_log->log['history']['events']) >=1) ?? false) { - return $system_log->log['history']; - } - }); + ->where('category_id', SystemLog::CATEGORY_MAIL) + ->whereJsonContains('log->history->entity_id', $this->encodePrimaryKey($request->entity_id)) + ->orderBy('id', 'DESC') + ->cursor() + ->filter(function ($system_log) { + return ($system_log->log['history'] && isset($system_log->log['history']['events']) && count($system_log->log['history']['events']) >=1) !== false; + })->map(function ($system_log) { + return $system_log->log['history']; + })->values()->all(); return response()->json($data, 200); From c955dfc910141f63c66cd19a82c20631c8634cad Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 17 Oct 2023 21:38:35 +1100 Subject: [PATCH 06/15] Fixes for recurring invoice export --- app/Export/CSV/BaseExport.php | 1 + app/Export/CSV/InvoiceExport.php | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index e0344792895c..dc371aa28013 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -168,6 +168,7 @@ class BaseExport 'tax_rate1' => 'invoice.tax_rate1', 'tax_rate2' => 'invoice.tax_rate2', 'tax_rate3' => 'invoice.tax_rate3', + 'recurring_invoice' => 'invoice.recurring_id', ]; protected array $recurring_invoice_report_keys = [ diff --git a/app/Export/CSV/InvoiceExport.php b/app/Export/CSV/InvoiceExport.php index 0a8f3188f2c3..741f5e22a029 100644 --- a/app/Export/CSV/InvoiceExport.php +++ b/app/Export/CSV/InvoiceExport.php @@ -142,6 +142,11 @@ class InvoiceExport extends BaseExport if (in_array('invoice.status', $this->input['report_keys'])) { $entity['invoice.status'] = $invoice->stringStatus($invoice->status_id); } + + if (in_array('invoice.recurring_id', $this->input['report_keys'])) { + $entity['invoice.recurring_id'] = $invoice->recurring_invoice->number ?? ''; + } + return $entity; } From d06f383a98c16a08056c9f65be852cadc5338be6 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Oct 2023 10:14:14 +1100 Subject: [PATCH 07/15] Minor fixes --- app/Models/Presenters/ClientPresenter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Presenters/ClientPresenter.php b/app/Models/Presenters/ClientPresenter.php index ac4b184d94e1..aed92c0eb8c9 100644 --- a/app/Models/Presenters/ClientPresenter.php +++ b/app/Models/Presenters/ClientPresenter.php @@ -23,7 +23,7 @@ class ClientPresenter extends EntityPresenter */ public function name() { - if ($this->entity->name) { + if (strlen($this->entity->name) > 1) { return $this->entity->name; } From d62bdbedcbd7e5d61f40755d18933a453459ffad Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Oct 2023 10:30:45 +1100 Subject: [PATCH 08/15] Fixes for showing tasks in client portal --- app/Http/Controllers/RecurringInvoiceController.php | 1 + app/Http/Livewire/TasksTable.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/RecurringInvoiceController.php b/app/Http/Controllers/RecurringInvoiceController.php index d09d31e80220..94c2192d178a 100644 --- a/app/Http/Controllers/RecurringInvoiceController.php +++ b/app/Http/Controllers/RecurringInvoiceController.php @@ -157,6 +157,7 @@ class RecurringInvoiceController extends BaseController $user = auth()->user(); $recurring_invoice = RecurringInvoiceFactory::create($user->company()->id, $user->id); + $recurring_invoice->auto_bill = $user->company()->settings->auto_bill; return $this->itemResponse($recurring_invoice); } diff --git a/app/Http/Livewire/TasksTable.php b/app/Http/Livewire/TasksTable.php index 40106c390bd6..f229db889f46 100644 --- a/app/Http/Livewire/TasksTable.php +++ b/app/Http/Livewire/TasksTable.php @@ -39,11 +39,11 @@ class TasksTable extends Component ->where('is_deleted', false) ->where('client_id', auth()->guard('contact')->user()->client_id); - if ($this->company->getSetting('show_all_tasks_client_portal') === 'invoiced') { + if ( auth()->guard('contact')->user()->client->getSetting('show_all_tasks_client_portal') === 'invoiced') { $query = $query->whereNotNull('invoice_id'); } - if ($this->company->getSetting('show_all_tasks_client_portal') === 'uninvoiced') { + if ( auth()->guard('contact')->user()->client->getSetting('show_all_tasks_client_portal') === 'uninvoiced') { $query = $query->whereNull('invoice_id'); } From 1163c42fd8a53eae74fd82d74d162a8a53ae73c4 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Oct 2023 15:22:38 +1100 Subject: [PATCH 09/15] Fixes for report exports --- app/Export/CSV/BaseExport.php | 10 +++- app/Export/CSV/CreditExport.php | 2 + app/Export/CSV/InvoiceExport.php | 2 + app/Export/CSV/InvoiceItemExport.php | 23 ++++++++ app/Export/CSV/PaymentExport.php | 2 + app/Export/CSV/PurchaseOrderExport.php | 9 ++- app/Export/CSV/PurchaseOrderItemExport.php | 2 + app/Export/CSV/QuoteExport.php | 2 + app/Export/CSV/QuoteItemExport.php | 2 + app/Export/CSV/RecurringInvoiceExport.php | 6 +- app/Export/CSV/TaskExport.php | 2 + .../Export/ReportCsvGenerationTest.php | 58 +++++++++++++++++-- 12 files changed, 110 insertions(+), 10 deletions(-) diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index dc371aa28013..0db407e3440f 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -231,7 +231,7 @@ class BaseExport 'po_number' => 'purchase_order.po_number', 'private_notes' => 'purchase_order.private_notes', 'public_notes' => 'purchase_order.public_notes', - 'status' => 'purchase_order.status_id', + 'status' => 'purchase_order.status', 'tax_name1' => 'purchase_order.tax_name1', 'tax_name2' => 'purchase_order.tax_name2', 'tax_name3' => 'purchase_order.tax_name3', @@ -430,6 +430,14 @@ class BaseExport 'project' => 'task.project_id', ]; + protected array $forced_client_fields = [ + "name" => "client.name", + ]; + + protected array $forced_vendor_fields = [ + "name" => "vendor.name", + ]; + protected function filterByClients($query) { if (isset($this->input['client_id']) && $this->input['client_id'] != 'all') { diff --git a/app/Export/CSV/CreditExport.php b/app/Export/CSV/CreditExport.php index 29afbfa16100..c5c05f3c23e2 100644 --- a/app/Export/CSV/CreditExport.php +++ b/app/Export/CSV/CreditExport.php @@ -93,6 +93,8 @@ class CreditExport extends BaseExport $this->input['report_keys'] = array_values($this->credit_report_keys); } + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys'])); + $query = Credit::query() ->withTrashed() ->with('client') diff --git a/app/Export/CSV/InvoiceExport.php b/app/Export/CSV/InvoiceExport.php index 741f5e22a029..4dc4ee3d8b94 100644 --- a/app/Export/CSV/InvoiceExport.php +++ b/app/Export/CSV/InvoiceExport.php @@ -50,6 +50,8 @@ class InvoiceExport extends BaseExport $this->input['report_keys'] = array_values($this->invoice_report_keys); } + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys'])); + $query = Invoice::query() ->withTrashed() ->with('client') diff --git a/app/Export/CSV/InvoiceItemExport.php b/app/Export/CSV/InvoiceItemExport.php index 74c1a64c25b0..5ac3c9fb2fbf 100644 --- a/app/Export/CSV/InvoiceItemExport.php +++ b/app/Export/CSV/InvoiceItemExport.php @@ -62,6 +62,8 @@ class InvoiceItemExport extends BaseExport $this->input['report_keys'] = array_values($this->mergeItemsKeys('invoice_report_keys')); } + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys'])); + $query = Invoice::query() ->withTrashed() ->with('client') @@ -200,6 +202,27 @@ class InvoiceItemExport extends BaseExport $entity['tax_category'] = $invoice->taxTypeString($entity['tax_category']); } + if (in_array('invoice.country_id', $this->input['report_keys'])) { + $entity['invoice.country_id'] = $invoice->client->country ? ctrans("texts.country_{$invoice->client->country->name}") : ''; + } + + 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; + } + + if (in_array('invoice.client_id', $this->input['report_keys'])) { + $entity['invoice.client_id'] = $invoice->client->present()->name(); + } + + if (in_array('invoice.status', $this->input['report_keys'])) { + $entity['invoice.status'] = $invoice->stringStatus($invoice->status_id); + } + + if (in_array('invoice.recurring_id', $this->input['report_keys'])) { + $entity['invoice.recurring_id'] = $invoice->recurring_invoice->number ?? ''; + } + + return $entity; } diff --git a/app/Export/CSV/PaymentExport.php b/app/Export/CSV/PaymentExport.php index 01c8641b0725..48f996fae794 100644 --- a/app/Export/CSV/PaymentExport.php +++ b/app/Export/CSV/PaymentExport.php @@ -48,6 +48,8 @@ class PaymentExport extends BaseExport $this->input['report_keys'] = array_values($this->payment_report_keys); } + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys'])); + $query = Payment::query() ->withTrashed() ->where('company_id', $this->company->id) diff --git a/app/Export/CSV/PurchaseOrderExport.php b/app/Export/CSV/PurchaseOrderExport.php index 88145822b10a..45e8a6adb1b7 100644 --- a/app/Export/CSV/PurchaseOrderExport.php +++ b/app/Export/CSV/PurchaseOrderExport.php @@ -54,7 +54,7 @@ class PurchaseOrderExport extends BaseExport 'po_number' => 'purchase_order.po_number', 'private_notes' => 'purchase_order.private_notes', 'public_notes' => 'purchase_order.public_notes', - 'status' => 'purchase_order.status_id', + 'status' => 'purchase_order.status', 'tax_name1' => 'purchase_order.tax_name1', 'tax_name2' => 'purchase_order.tax_name2', 'tax_name3' => 'purchase_order.tax_name3', @@ -95,6 +95,9 @@ class PurchaseOrderExport extends BaseExport if (count($this->input['report_keys']) == 0) { $this->input['report_keys'] = array_values($this->purchase_order_report_keys); } + + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_vendor_fields, $this->input['report_keys'])); + $query = PurchaseOrder::query() ->withTrashed() ->with('vendor') @@ -181,8 +184,8 @@ class PurchaseOrderExport extends BaseExport $entity['vendor'] = $purchase_order->vendor->present()->name(); } - if (in_array('status_id', $this->input['report_keys'])) { - $entity['status'] = $purchase_order->stringStatus($purchase_order->status_id); + if (in_array('purchase_order.status', $this->input['report_keys'])) { + $entity['purchase_order.status'] = $purchase_order->stringStatus($purchase_order->status_id); } return $entity; diff --git a/app/Export/CSV/PurchaseOrderItemExport.php b/app/Export/CSV/PurchaseOrderItemExport.php index 9ebf2991c95b..fb09ea6fa8e9 100644 --- a/app/Export/CSV/PurchaseOrderItemExport.php +++ b/app/Export/CSV/PurchaseOrderItemExport.php @@ -55,6 +55,8 @@ class PurchaseOrderItemExport extends BaseExport $this->input['report_keys'] = array_values($this->mergeItemsKeys('purchase_order_report_keys')); } + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_vendor_fields, $this->input['report_keys'])); + $query = PurchaseOrder::query() ->withTrashed() ->with('vendor')->where('company_id', $this->company->id) diff --git a/app/Export/CSV/QuoteExport.php b/app/Export/CSV/QuoteExport.php index 8083c0a71e7a..eba6adbcef26 100644 --- a/app/Export/CSV/QuoteExport.php +++ b/app/Export/CSV/QuoteExport.php @@ -56,6 +56,8 @@ class QuoteExport extends BaseExport $this->input['report_keys'] = array_values($this->quote_report_keys); } + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys'])); + $query = Quote::query() ->withTrashed() ->with('client') diff --git a/app/Export/CSV/QuoteItemExport.php b/app/Export/CSV/QuoteItemExport.php index f85a82dd4c12..48bc25b95e6a 100644 --- a/app/Export/CSV/QuoteItemExport.php +++ b/app/Export/CSV/QuoteItemExport.php @@ -57,6 +57,8 @@ class QuoteItemExport extends BaseExport $this->input['report_keys'] = array_values($this->mergeItemsKeys('quote_report_keys')); } + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys'])); + $query = Quote::query() ->withTrashed() ->with('client')->where('company_id', $this->company->id) diff --git a/app/Export/CSV/RecurringInvoiceExport.php b/app/Export/CSV/RecurringInvoiceExport.php index d30359510c80..3234b0674337 100644 --- a/app/Export/CSV/RecurringInvoiceExport.php +++ b/app/Export/CSV/RecurringInvoiceExport.php @@ -48,6 +48,8 @@ class RecurringInvoiceExport extends BaseExport $this->input['report_keys'] = array_values($this->recurring_invoice_report_keys); } + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys'])); + $query = RecurringInvoice::query() ->withTrashed() ->with('client') @@ -135,8 +137,8 @@ class RecurringInvoiceExport extends BaseExport $entity['client'] = $invoice->client->present()->name(); } - if (in_array('status_id', $this->input['report_keys'])) { - $entity['status'] = $invoice->stringStatus($invoice->status_id); + if (in_array('recurring_invoice.status', $this->input['report_keys'])) { + $entity['recurring_invoice.status'] = $invoice->stringStatus($invoice->status_id); } if (in_array('project_id', $this->input['report_keys'])) { diff --git a/app/Export/CSV/TaskExport.php b/app/Export/CSV/TaskExport.php index 87834c6aee4f..b2eb6425c527 100644 --- a/app/Export/CSV/TaskExport.php +++ b/app/Export/CSV/TaskExport.php @@ -60,6 +60,8 @@ class TaskExport extends BaseExport $this->input['report_keys'] = array_values($this->task_report_keys); } + $this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys'])); + $query = Task::query() ->withTrashed() ->where('company_id', $this->company->id) diff --git a/tests/Feature/Export/ReportCsvGenerationTest.php b/tests/Feature/Export/ReportCsvGenerationTest.php index c7f400db7420..87c967c883bf 100644 --- a/tests/Feature/Export/ReportCsvGenerationTest.php +++ b/tests/Feature/Export/ReportCsvGenerationTest.php @@ -20,7 +20,6 @@ use App\Models\Account; use App\Models\Company; use App\Models\Expense; use App\Models\Invoice; -use Tests\MockAccountData; use App\Models\CompanyToken; use App\Models\ClientContact; use App\Export\CSV\TaskExport; @@ -30,8 +29,6 @@ use App\Export\CSV\ProductExport; use App\DataMapper\CompanySettings; use App\Export\CSV\PaymentExport; use App\Factory\CompanyUserFactory; -use App\Factory\InvoiceItemFactory; -use App\Services\Report\ARDetailReport; use Illuminate\Routing\Middleware\ThrottleRequests; /** @@ -262,6 +259,21 @@ class ReportCsvGenerationTest extends TestCase } + public function testForcedInsertionOfMandatoryColumns() + { + $forced = ['client.name']; + + $report_keys = ['invoice.number','client.name', 'invoice.amount']; + $array = array_merge($report_keys, array_diff($forced, $report_keys)); + + $this->assertEquals('client.name', $array[1]); + + $report_keys = ['invoice.number','invoice.amount']; + $array = array_merge($report_keys, array_diff($forced, $report_keys)); + + $this->assertEquals('client.name', $array[2]); + + } public function testVendorCsvGeneration() { @@ -322,7 +334,7 @@ class ReportCsvGenerationTest extends TestCase $data = $export->returnJson(); $this->assertNotNull($data); -// nlog($data); + // nlog($data); // $this->assertEquals(0, $this->traverseJson($data, 'columns.0.identifier')); $this->assertEquals('Vendor Name', $this->traverseJson($data, 'columns.9.display_value')); $this->assertEquals('vendor', $this->traverseJson($data, '0.0.entity')); @@ -1021,6 +1033,44 @@ class ReportCsvGenerationTest extends TestCase 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/recurring_invoices', $data)->assertStatus(200); + } + + + public function testRecurringInvoiceColumnsCsvGeneration() + { + + \App\Models\RecurringInvoice::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'client_id' => $this->client->id, + 'amount' => 100, + 'balance' => 50, + 'number' => '1234', + 'status_id' => 2, + 'discount' => 10, + 'po_number' => '1234', + 'public_notes' => 'Public', + 'private_notes' => 'Private', + 'terms' => 'Terms', + 'frequency_id' => 1, + ]); + + $data = [ + 'date_range' => 'all', + 'report_keys' => [], + 'send_email' => false, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/reports/recurring_invoices', $data); + + $csv = $response->streamedContent(); + + $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Recurring Invoice Invoice Number')); + $this->assertEquals('Daily', $this->getFirstValueByColumn($csv, 'Recurring Invoice How Often')); + $this->assertEquals('Active', $this->getFirstValueByColumn($csv, 'Recurring Invoice Status')); } From cdcfcf715ce1edad6c7a6caa13539a2529b65942 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Oct 2023 15:38:45 +1100 Subject: [PATCH 10/15] Fixes for report exports --- app/Export/CSV/BaseExport.php | 5 +++-- app/Export/CSV/PaymentExport.php | 4 ++++ app/Services/Email/Email.php | 5 +++++ tests/Feature/InvoiceEmailTest.php | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index 0db407e3440f..fd1c1b5a3ef4 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -378,6 +378,7 @@ class BaseExport "custom_value4" => "payment.custom_value4", "user" => "payment.user_id", "assigned_user" => "payment.assigned_user_id", + ]; protected array $expense_report_keys = [ @@ -431,11 +432,11 @@ class BaseExport ]; protected array $forced_client_fields = [ - "name" => "client.name", + "client.name", ]; protected array $forced_vendor_fields = [ - "name" => "vendor.name", + "vendor.name", ]; protected function filterByClients($query) diff --git a/app/Export/CSV/PaymentExport.php b/app/Export/CSV/PaymentExport.php index 48f996fae794..ef9a4479bca2 100644 --- a/app/Export/CSV/PaymentExport.php +++ b/app/Export/CSV/PaymentExport.php @@ -67,10 +67,14 @@ class PaymentExport extends BaseExport $headerdisplay = $this->buildHeader(); + nlog($headerdisplay); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; })->toArray(); + nlog($header); + $report = $query->cursor() ->map(function ($resource) { $row = $this->buildRow($resource); diff --git a/app/Services/Email/Email.php b/app/Services/Email/Email.php index cebb8b7b6f79..6fada767e07b 100644 --- a/app/Services/Email/Email.php +++ b/app/Services/Email/Email.php @@ -413,6 +413,11 @@ class Email implements ShouldQueue if ($address_object->address == " ") { return true; } + + if ($address_object->address == "") { + return true; + } + } diff --git a/tests/Feature/InvoiceEmailTest.php b/tests/Feature/InvoiceEmailTest.php index a08b306aa44d..89ef93a1d3b8 100644 --- a/tests/Feature/InvoiceEmailTest.php +++ b/tests/Feature/InvoiceEmailTest.php @@ -32,6 +32,8 @@ class InvoiceEmailTest extends TestCase use DatabaseTransactions; use GeneratesCounter; + public $faker; + protected function setUp() :void { parent::setUp(); From e41228a1151998a0f4f8c826603e59674916e31c Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Oct 2023 15:54:55 +1100 Subject: [PATCH 11/15] Fixes for null/not set client contact passwords --- app/Http/Requests/Request.php | 2 +- tests/Feature/ClientTest.php | 28 ++++++++++++++++++++++++++++ tests/Feature/InvoiceEmailTest.php | 10 +++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index 2fb9a589e082..8d7eb2acd05b 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -180,7 +180,7 @@ class Request extends FormRequest } //Filter the client contact password - if it is sent with ***** we should ignore it! - if (isset($contact['password'])) { + if (isset($contact['password']) && is_string($contact['password'])) { if (strlen($contact['password']) == 0) { $input['contacts'][$key]['password'] = ''; } else { diff --git a/tests/Feature/ClientTest.php b/tests/Feature/ClientTest.php index 0244a3e8227b..89b49d945c6a 100644 --- a/tests/Feature/ClientTest.php +++ b/tests/Feature/ClientTest.php @@ -65,6 +65,34 @@ class ClientTest extends TestCase $this->makeTestData(); } + public function testStoreClientFixes() + { + $data = [ + "contacts" => [ + [ + "email" => "tenda@gmail.com", + "first_name" => "Tenda", + "is_primary" => True, + "last_name" => "Bavuma", + "password" => null, + "send_email" => True + ], + ], + "country_id" => "356", + "display_name" => "Tenda Bavuma", + "name" => "Tenda Bavuma", + "shipping_country_id" => "356", + ]; + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/clients', $data); + + $response->assertStatus(200); + } + public function testClientMergeContactDrop() { diff --git a/tests/Feature/InvoiceEmailTest.php b/tests/Feature/InvoiceEmailTest.php index 89ef93a1d3b8..23ba03236086 100644 --- a/tests/Feature/InvoiceEmailTest.php +++ b/tests/Feature/InvoiceEmailTest.php @@ -33,7 +33,7 @@ class InvoiceEmailTest extends TestCase use GeneratesCounter; public $faker; - + protected function setUp() :void { parent::setUp(); @@ -50,6 +50,14 @@ class InvoiceEmailTest extends TestCase } + public function testInvalidEmailParsing() + { + $email = 'illegal@example.com'; + + $this->assertTrue(strpos($email, '@example.com') !== false); + } + + public function testClientEmailHistory() { $system_log = new SystemLog(); From 25ceba275cfc44534c0236cbccd65b29813ec051 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Oct 2023 17:28:10 +1100 Subject: [PATCH 12/15] Add suppressions for user notifications --- app/Export/CSV/PaymentExport.php | 4 +- app/Jobs/Mail/NinjaMailerObject.php | 4 +- app/Listeners/User/UpdateUserLastLogin.php | 3 +- app/Mail/TemplateEmail.php | 11 +++-- app/Mail/VendorTemplateEmail.php | 20 +++++++-- app/Models/User.php | 4 +- app/Services/Email/Email.php | 5 ++- app/Services/Email/EmailDefaults.php | 4 +- app/Transformers/UserTransformer.php | 1 + ...1415_add_user_notification_suppression.php | 43 +++++++++++++++++++ database/seeders/CurrenciesSeeder.php | 1 + lang/en/texts.php | 5 ++- .../ninja2020/invoices/payment.blade.php | 2 +- 13 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 database/migrations/2023_10_18_061415_add_user_notification_suppression.php diff --git a/app/Export/CSV/PaymentExport.php b/app/Export/CSV/PaymentExport.php index ef9a4479bca2..7f77563f9b92 100644 --- a/app/Export/CSV/PaymentExport.php +++ b/app/Export/CSV/PaymentExport.php @@ -67,14 +67,12 @@ class PaymentExport extends BaseExport $headerdisplay = $this->buildHeader(); - nlog($headerdisplay); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; })->toArray(); nlog($header); - + $report = $query->cursor() ->map(function ($resource) { $row = $this->buildRow($resource); diff --git a/app/Jobs/Mail/NinjaMailerObject.php b/app/Jobs/Mail/NinjaMailerObject.php index 1d973cb90275..44eea91cc5e1 100644 --- a/app/Jobs/Mail/NinjaMailerObject.php +++ b/app/Jobs/Mail/NinjaMailerObject.php @@ -32,12 +32,12 @@ class NinjaMailerObject /* Variable for cascading notifications */ public $entity_string = false; - /* @var bool | App\Models\InvoiceInvitation | app\Models\QuoteInvitation | app\Models\CreditInvitation | app\Models\RecurringInvoiceInvitation | app\Models\PurchaseOrderInvitation $invitation*/ + /* @var bool | App\Models\InvoiceInvitation | App\Models\QuoteInvitation | App\Models\CreditInvitation | App\Models\RecurringInvoiceInvitation | App\Models\PurchaseOrderInvitation $invitation*/ public $invitation = false; public $template = false; - /* @var bool | App\Models\Invoice | app\Models\Quote | app\Models\Credit | app\Models\RecurringInvoice | app\Models\PurchaseOrder $invitation*/ + /* @var bool | App\Models\Invoice | App\Models\Quote | App\Models\Credit | App\Models\RecurringInvoice | App\Models\PurchaseOrder | App\Models\Payment $entity*/ public $entity = false; public $reminder_template = ''; diff --git a/app/Listeners/User/UpdateUserLastLogin.php b/app/Listeners/User/UpdateUserLastLogin.php index 9fc383db207f..94e20512eefc 100644 --- a/app/Listeners/User/UpdateUserLastLogin.php +++ b/app/Listeners/User/UpdateUserLastLogin.php @@ -55,7 +55,7 @@ class UpdateUserLastLogin implements ShouldQueue $key = "user_logged_in_{$user->id}{$event->company->db}"; - if ($user->ip != $ip && is_null(Cache::get($key))) { + if ($user->ip != $ip && is_null(Cache::get($key)) && $user->user_logged_in_notification) { $nmo = new NinjaMailerObject; $nmo->mailable = new UserLoggedIn($user, $user->account->companies->first(), $ip); $nmo->company = $user->account->companies->first(); @@ -69,6 +69,7 @@ class UpdateUserLastLogin implements ShouldQueue Cache::put($key, true, 60 * 24); $arr = json_encode(['ip' => $ip]); + $arr = ctrans('texts.new_login_detected'). " {$ip}"; SystemLogger::dispatch( $arr, diff --git a/app/Mail/TemplateEmail.php b/app/Mail/TemplateEmail.php index 984029cefe26..63794936e5c8 100644 --- a/app/Mail/TemplateEmail.php +++ b/app/Mail/TemplateEmail.php @@ -108,12 +108,15 @@ class TemplateEmail extends Mailable if (strlen($settings->bcc_email) > 1) { if (Ninja::isHosted()) { - $bccs = explode(',', str_replace(' ', '', $settings->bcc_email)); - $this->bcc(array_slice($bccs, 0, 2)); - //$this->bcc(reset($bccs)); //remove whitespace if any has been inserted. + + if($company->account->isPaid()) { + $bccs = explode(',', str_replace(' ', '', $settings->bcc_email)); + $this->bcc(array_slice($bccs, 0, 5)); + } + } else { $this->bcc(explode(',', str_replace(' ', '', $settings->bcc_email))); - }//remove whitespace if any has been inserted. + } } $this->subject(str_replace("
", "", $this->build_email->getSubject())) diff --git a/app/Mail/VendorTemplateEmail.php b/app/Mail/VendorTemplateEmail.php index 2ac0987b8045..bdfb818b0091 100644 --- a/app/Mail/VendorTemplateEmail.php +++ b/app/Mail/VendorTemplateEmail.php @@ -11,10 +11,11 @@ namespace App\Mail; +use App\Utils\Ninja; use App\Models\VendorContact; -use App\Services\PdfMaker\Designs\Utilities\DesignHelpers; -use App\Utils\VendorHtmlEngine; use Illuminate\Mail\Mailable; +use App\Utils\VendorHtmlEngine; +use App\Services\PdfMaker\Designs\Utilities\DesignHelpers; class VendorTemplateEmail extends Mailable { @@ -102,8 +103,19 @@ class VendorTemplateEmail extends Mailable $this->from(config('mail.from.address'), $email_from_name); if (strlen($settings->bcc_email) > 1) { - $this->bcc(explode(',', str_replace(' ', '', $settings->bcc_email))); - }//remove whitespace if any has been inserted. + + if (Ninja::isHosted()) { + + if($this->company->account->isPaid()) { + $bccs = explode(',', str_replace(' ', '', $settings->bcc_email)); + $this->bcc(array_slice($bccs, 0, 5)); + } + + } else { + $this->bcc(explode(',', str_replace(' ', '', $settings->bcc_email))); + } + + } $this->subject($this->build_email->getSubject()) ->text('email.template.text', [ diff --git a/app/Models/User.php b/app/Models/User.php index 22e5130d0df1..aec9b0e787d5 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -73,7 +73,8 @@ use Illuminate\Foundation\Auth\User as Authenticatable; * @property int|null $deleted_at * @property string|null $oauth_user_refresh_token * @property string|null $last_confirmed_email_address - * @property int $has_password + * @property bool $has_password + * @property bool $user_logged_in_notification * @property Carbon|null $oauth_user_token_expiry * @property string|null $sms_verification_code * @property bool $verified_phone_number @@ -140,6 +141,7 @@ class User extends Authenticatable implements MustVerifyEmail * */ protected $fillable = [ + 'user_logged_in_notification', 'first_name', 'last_name', 'email', diff --git a/app/Services/Email/Email.php b/app/Services/Email/Email.php index 6fada767e07b..c539d075d445 100644 --- a/app/Services/Email/Email.php +++ b/app/Services/Email/Email.php @@ -140,7 +140,7 @@ class Email implements ShouldQueue $this->email_object->client_id ? $this->email_object->settings = $this->email_object->client->getMergedSettings() : $this->email_object->settings = $this->company->settings; - $this->email_object->client_id ? nlog("client settings") : nlog("company settings "); + // $this->email_object->client_id ? nlog("client settings") : nlog("company settings "); $this->email_object->whitelabel = $this->company->account->isPaid() ? true : false; @@ -418,6 +418,9 @@ class Email implements ShouldQueue return true; } + if($address_object->name == " " || $address_object->name == "") { + return true; + } } diff --git a/app/Services/Email/EmailDefaults.php b/app/Services/Email/EmailDefaults.php index 401060b6c7b4..1f78facaa1e5 100644 --- a/app/Services/Email/EmailDefaults.php +++ b/app/Services/Email/EmailDefaults.php @@ -255,8 +255,8 @@ class EmailDefaults if (strlen($this->email->email_object->settings->bcc_email) > 1) { if (Ninja::isHosted() && $this->email->company->account->isPaid()) { - $bccs = array_slice(explode(',', str_replace(' ', '', $this->email->email_object->settings->bcc_email)), 0, 2); - } elseif (Ninja::isSelfHost()) { + $bccs = array_slice(explode(',', str_replace(' ', '', $this->email->email_object->settings->bcc_email)), 0, 5); + } else { $bccs = (explode(',', str_replace(' ', '', $this->email->email_object->settings->bcc_email))); } } diff --git a/app/Transformers/UserTransformer.php b/app/Transformers/UserTransformer.php index ffe029fbb0fe..0971c7dc2b02 100644 --- a/app/Transformers/UserTransformer.php +++ b/app/Transformers/UserTransformer.php @@ -64,6 +64,7 @@ class UserTransformer extends EntityTransformer 'oauth_user_token' => empty($user->oauth_user_token) ? '' : '***', 'verified_phone_number' => (bool) $user->verified_phone_number, 'language_id' => (string) $user->language_id ?? '', + 'user_logged_in_notification' => (bool) $user->user_logged_in_notification, ]; } diff --git a/database/migrations/2023_10_18_061415_add_user_notification_suppression.php b/database/migrations/2023_10_18_061415_add_user_notification_suppression.php new file mode 100644 index 000000000000..4c01624a02ac --- /dev/null +++ b/database/migrations/2023_10_18_061415_add_user_notification_suppression.php @@ -0,0 +1,43 @@ +boolean('user_logged_in_notification')->default(true); + }); + + + $cur = Currency::find(120); + + if(!$cur) { + $cur = new \App\Models\Currency(); + $cur->id = 120; + $cur->code = 'TOP'; + $cur->name = "Tongan Pa'anga"; + $cur->symbol = 'T$'; + $cur->thousand_separator = ','; + $cur->decimal_separator = '.'; + $cur->precision = 2; + $cur->save(); + } + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + } +}; diff --git a/database/seeders/CurrenciesSeeder.php b/database/seeders/CurrenciesSeeder.php index b2c8b35af751..e6976622ee86 100644 --- a/database/seeders/CurrenciesSeeder.php +++ b/database/seeders/CurrenciesSeeder.php @@ -142,6 +142,7 @@ class CurrenciesSeeder extends Seeder ['id' => 117, 'name' => 'Gold Troy Ounce', 'code' => 'XAU', 'symbol' => 'XAU', 'precision' => '3', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['id' => 118, 'name' => 'Nicaraguan Córdoba', 'code' => 'NIO', 'symbol' => 'C$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['id' => 119, 'name' => 'Malagasy ariary', 'code' => 'MGA', 'symbol' => 'Ar', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['id' => 120, 'name' => "Tongan Pa anga", 'code' => 'TOP', 'symbol' => 'T$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ]; foreach ($currencies as $currency) { diff --git a/lang/en/texts.php b/lang/en/texts.php index 5fe2741906a1..c7bdffb4bd50 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -2402,7 +2402,10 @@ $LANG = array( 'currency_libyan_dinar' => 'Libyan Dinar', 'currency_silver_troy_ounce' => 'Silver Troy Ounce', 'currency_gold_troy_ounce' => 'Gold Troy Ounce', - + 'currency_nicaraguan_córdoba' => 'Nicaraguan Córdoba', + 'currency_malagasy_ariary' => 'Malagasy ariary', + "currency_tongan_pa_anga" => "Tongan Pa'anga", + 'review_app_help' => 'We hope you\'re enjoying using the app.
If you\'d consider :link we\'d greatly appreciate it!', 'writing_a_review' => 'writing a review', diff --git a/resources/views/portal/ninja2020/invoices/payment.blade.php b/resources/views/portal/ninja2020/invoices/payment.blade.php index 8d5df833d326..a0d786ff4610 100644 --- a/resources/views/portal/ninja2020/invoices/payment.blade.php +++ b/resources/views/portal/ninja2020/invoices/payment.blade.php @@ -64,7 +64,7 @@ {{ ctrans('texts.public_notes') }}
- {{ $invoice->public_notes }} + {!! html_entity_decode($invoice->public_notes) !!}
@else
From d49909e799e03d72a204d5a3359f2688a22bead3 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Oct 2023 17:43:26 +1100 Subject: [PATCH 13/15] Add user login notification suppression --- app/Factory/UserFactory.php | 3 ++- lang/en/texts.php | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/Factory/UserFactory.php b/app/Factory/UserFactory.php index d31a0019b2c9..9b15037f625c 100644 --- a/app/Factory/UserFactory.php +++ b/app/Factory/UserFactory.php @@ -27,7 +27,8 @@ class UserFactory $user->last_login = now(); $user->failed_logins = 0; $user->signature = ''; - $user->theme_id = 0; + $user->theme_id = 0; + $user->user_logged_in_notification = true; return $user; } diff --git a/lang/en/texts.php b/lang/en/texts.php index c7bdffb4bd50..48cfe30beb3a 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -2405,7 +2405,7 @@ $LANG = array( 'currency_nicaraguan_córdoba' => 'Nicaraguan Córdoba', 'currency_malagasy_ariary' => 'Malagasy ariary', "currency_tongan_pa_anga" => "Tongan Pa'anga", - + 'review_app_help' => 'We hope you\'re enjoying using the app.
If you\'d consider :link we\'d greatly appreciate it!', 'writing_a_review' => 'writing a review', @@ -5183,6 +5183,8 @@ $LANG = array( 'upcoming' => 'Upcoming', 'client_contact' => 'Client Contact', 'uncategorized' => 'Uncategorized', + 'login_notification' => 'Login Notification', + 'login_notification_help' => 'Sends an email notifying that a login has taken place.' ); return $LANG; From bde9f60aeece6f7b0e7527e783735c5f6d216c85 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Oct 2023 18:42:16 +1100 Subject: [PATCH 14/15] Add group settings to client transformer --- app/Jobs/Mail/NinjaMailerObject.php | 2 +- app/Transformers/ClientTransformer.php | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/Jobs/Mail/NinjaMailerObject.php b/app/Jobs/Mail/NinjaMailerObject.php index 44eea91cc5e1..df33c35c2a11 100644 --- a/app/Jobs/Mail/NinjaMailerObject.php +++ b/app/Jobs/Mail/NinjaMailerObject.php @@ -37,7 +37,7 @@ class NinjaMailerObject public $template = false; - /* @var bool | App\Models\Invoice | App\Models\Quote | App\Models\Credit | App\Models\RecurringInvoice | App\Models\PurchaseOrder | App\Models\Payment $entity*/ + /* @var bool | App\Models\Invoice | App\Models\Quote | App\Models\Credit | App\Models\RecurringInvoice | App\Models\PurchaseOrder | App\Models\Payment $entity */ public $entity = false; public $reminder_template = ''; diff --git a/app/Transformers/ClientTransformer.php b/app/Transformers/ClientTransformer.php index 711c9cfec5ba..4cfb7742b3e4 100644 --- a/app/Transformers/ClientTransformer.php +++ b/app/Transformers/ClientTransformer.php @@ -17,6 +17,7 @@ use App\Models\ClientContact; use App\Models\ClientGatewayToken; use App\Models\CompanyLedger; use App\Models\Document; +use App\Models\GroupSetting; use App\Models\SystemLog; use App\Utils\Traits\MakesHash; use League\Fractal\Resource\Collection; @@ -42,6 +43,7 @@ class ClientTransformer extends EntityTransformer 'activities', 'ledger', 'system_logs', + 'group_settings', ]; /** @@ -96,6 +98,16 @@ class ClientTransformer extends EntityTransformer return $this->includeCollection($client->system_logs, $transformer, SystemLog::class); } + public function includeGroupSettings(Client $client) + { + if (!$client->group_settings) + return null; + + $transformer = new GroupSettingTransformer($this->serializer); + + return $this->includeItem($client->group_settings, $transformer, GroupSetting::class); + } + /** * @param Client $client * From 3ae1d3e694da8dc143a28ff25ac893350a0b26ed Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Oct 2023 20:03:26 +1100 Subject: [PATCH 15/15] v5.7.31 --- VERSION.txt | 2 +- app/Helpers/Epc/EpcQrGenerator.php | 7 ++++++- app/Helpers/SwissQr/SwissQrGenerator.php | 11 ++++++++--- config/ninja.php | 4 ++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 25285daaef52..557bab7d4518 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.7.30 \ No newline at end of file +5.7.31 \ No newline at end of file diff --git a/app/Helpers/Epc/EpcQrGenerator.php b/app/Helpers/Epc/EpcQrGenerator.php index 62d61a0a15bb..342c5f775f06 100644 --- a/app/Helpers/Epc/EpcQrGenerator.php +++ b/app/Helpers/Epc/EpcQrGenerator.php @@ -50,7 +50,8 @@ class EpcQrGenerator ); $writer = new Writer($renderer); - $this->validateFields(); + if($this->validateFields()) + return ''; $qr = $writer->writeString($this->encodeMessage(), 'utf-8'); @@ -87,12 +88,16 @@ class EpcQrGenerator private function validateFields() { if (Ninja::isSelfHost() && isset($this->company?->custom_fields?->company2)) { + return true; nlog('The BIC field is not present and _may_ be a required fields for EPC QR codes'); } if (Ninja::isSelfHost() && isset($this->company?->custom_fields?->company1)) { + return true; nlog('The IBAN field is required'); } + + return false; } private function formatMoney($value) diff --git a/app/Helpers/SwissQr/SwissQrGenerator.php b/app/Helpers/SwissQr/SwissQrGenerator.php index abacbb57c056..d8c1ad77304c 100644 --- a/app/Helpers/SwissQr/SwissQrGenerator.php +++ b/app/Helpers/SwissQr/SwissQrGenerator.php @@ -174,9 +174,14 @@ class SwissQrGenerator return $html; } catch (\Exception $e) { - foreach ($qrBill->getViolations() as $key => $violation) { - nlog("qr"); - nlog($violation); + + if(is_iterable($qrBill->getViolations())) { + + foreach ($qrBill->getViolations() as $key => $violation) { + nlog("qr"); + nlog($violation); + } + } nlog($e->getMessage()); diff --git a/config/ninja.php b/config/ninja.php index 7ef548ab7efa..df657179e40b 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -15,8 +15,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION','5.7.30'), - 'app_tag' => env('APP_TAG','5.7.30'), + 'app_version' => env('APP_VERSION','5.7.31'), + 'app_tag' => env('APP_TAG','5.7.31'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''),