diff --git a/VERSION.txt b/VERSION.txt index 23900d674d..72cf891338 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.7.3 \ No newline at end of file +5.7.5 \ No newline at end of file diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index e4c743923c..741f21a2a3 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', @@ -271,6 +270,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 +283,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", @@ -832,14 +836,16 @@ class BaseExport 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) { @@ -913,11 +919,37 @@ 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'])) + + 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 { @@ -925,8 +957,8 @@ class BaseExport } } - // nlog($header); - + nlog($header); + return $header; } } diff --git a/app/Export/CSV/ClientExport.php b/app/Export/CSV/ClientExport.php index 6e4dded881..0335be61c4 100644 --- a/app/Export/CSV/ClientExport.php +++ b/app/Export/CSV/ClientExport.php @@ -79,9 +79,6 @@ class ClientExport extends BaseExport 'client.industry', ]; - public array $forced_keys = [ - ]; - public function __construct(Company $company, array $input) { $this->company = $company; diff --git a/app/Export/CSV/CreditExport.php b/app/Export/CSV/CreditExport.php index 2cf25cb568..d964189537 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; @@ -87,11 +42,10 @@ class CreditExport extends BaseExport $query = $this->init(); $headerdisplay = $this->buildHeader(); - $header = []; - foreach ($this->input['report_keys'] as $key => $value) { - $header[] = ['identifier' => $value, 'display_value' => $headerdisplay[$key]]; - } + $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) { @@ -105,21 +59,18 @@ class CreditExport extends BaseExport 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]; @@ -139,12 +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'] = 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); @@ -160,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)); }); @@ -178,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/VendorExport.php b/app/Export/CSV/VendorExport.php index efc8bf3213..011484b054 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/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 74b4dcd0c4..591041c31c 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/GroupSettingController.php b/app/Http/Controllers/GroupSettingController.php index e69d6cab7d..ff22b55242 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/Requests/Email/SendEmailRequest.php b/app/Http/Requests/Email/SendEmailRequest.php index b0264eac2b..d917742dfa 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 daa13495e6..7d353c429b 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/PaymentDrivers/Square/SquareWebhook.php b/app/PaymentDrivers/Square/SquareWebhook.php index ebe46b0af4..c83b73fd47 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/config/ninja.php b/config/ninja.php index 1739429de5..bce6cfbcfb 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.3'), - 'app_tag' => env('APP_TAG','5.7.3'), + 'app_version' => env('APP_VERSION','5.7.5'), + 'app_tag' => env('APP_TAG','5.7.5'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''), diff --git a/tests/Feature/Export/ReportCsvGenerationTest.php b/tests/Feature/Export/ReportCsvGenerationTest.php index a0ead0a357..b641fb4b23 100644 --- a/tests/Feature/Export/ReportCsvGenerationTest.php +++ b/tests/Feature/Export/ReportCsvGenerationTest.php @@ -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); @@ -996,7 +996,7 @@ class ReportCsvGenerationTest extends TestCase $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('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')); @@ -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 = [ diff --git a/tests/Feature/Export/ReportPreviewTest.php b/tests/Feature/Export/ReportPreviewTest.php index 75516cea6e..2f029a125c 100644 --- a/tests/Feature/Export/ReportPreviewTest.php +++ b/tests/Feature/Export/ReportPreviewTest.php @@ -73,5 +73,6 @@ class ReportPreviewTest extends TestCase ])->postJson('/api/v1/reports/credits?output=json', $data) ->assertStatus(200); + } } \ No newline at end of file