diff --git a/app/DataMapper/EmailTemplateDefaults.php b/app/DataMapper/EmailTemplateDefaults.php index d7137ce7f1e7..721114771cff 100644 --- a/app/DataMapper/EmailTemplateDefaults.php +++ b/app/DataMapper/EmailTemplateDefaults.php @@ -173,7 +173,6 @@ class EmailTemplateDefaults public static function emailReminder1Subject() { - info("reminder 1 subject"); return ctrans('texts.reminder_subject', ['invoice'=>'$invoice.number', 'account'=>'$company.name']); } diff --git a/app/Events/Product/ProductWasArchived.php b/app/Events/Product/ProductWasArchived.php index 14a54db71aaa..38ab2990c0bf 100644 --- a/app/Events/Product/ProductWasArchived.php +++ b/app/Events/Product/ProductWasArchived.php @@ -11,6 +11,7 @@ namespace App\Events\Product; +use App\Models\Company; use App\Models\Product; use Illuminate\Queue\SerializesModels; diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 1f71590459a8..690f572ea15f 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -68,6 +68,7 @@ class Handler extends ExceptionHandler */ public function report(Throwable $exception) { + if (! Schema::hasTable('accounts')) { info('account table not found'); return; @@ -90,8 +91,6 @@ class Handler extends ExceptionHandler } }); -// app('sentry')->setRelease(config('ninja.app_version')); - if($this->validException($exception)) app('sentry')->captureException($exception); } @@ -102,15 +101,14 @@ class Handler extends ExceptionHandler private function validException($exception) { - if(strpos($exception->getMessage(), 'file_put_contents') === TRUE) + if(strpos($exception->getMessage(), 'file_put_contents') !== FALSE) return FALSE; - if(strpos($exception->getMessage(), 'Permission denied') === TRUE) - return FALSE; - - if(strpos($exception->getMessage(), 'flock()') === TRUE) + if(strpos($exception->getMessage(), 'Permission denied') !== FALSE) return FALSE; + if(strpos($exception->getMessage(), 'flock()') !== FALSE) + return FALSE; return TRUE; } diff --git a/app/Export/CSV/InvoiceExport.php b/app/Export/CSV/InvoiceExport.php new file mode 100644 index 000000000000..2f7b402afc97 --- /dev/null +++ b/app/Export/CSV/InvoiceExport.php @@ -0,0 +1,39 @@ +company = $company; + } + + public function export() + { + // $fileName = 'test.csv'; + + // $data = $this->company->invoices->get(); + + // return Excel::create($fileName, function ($excel) use ($data) { + // $excel->sheet('', function ($sheet) use ($data) { + // $sheet->loadView('export', $data); + // }); + // })->download('csv'); + + } +} \ No newline at end of file diff --git a/app/Filters/ClientFilters.php b/app/Filters/ClientFilters.php index 9221b5da4fdf..e367708d17f5 100644 --- a/app/Filters/ClientFilters.php +++ b/app/Filters/ClientFilters.php @@ -190,7 +190,6 @@ class ClientFilters extends QueryFilters * limit the user to only the invoices they have created */ if (Gate::denies('view-list', Client::class)) { - info('the gate!'); $query->where('clients.user_id', '=', $user->id); } diff --git a/app/Http/Controllers/ClientPortal/DocumentController.php b/app/Http/Controllers/ClientPortal/DocumentController.php index be7332e4d33d..ee485174bb5a 100644 --- a/app/Http/Controllers/ClientPortal/DocumentController.php +++ b/app/Http/Controllers/ClientPortal/DocumentController.php @@ -54,15 +54,12 @@ class DocumentController extends Controller return Storage::disk($document->disk)->download($document->url, $document->name); } - public function publicDownload(string $contact_key, Document $document) + public function publicDownload(string $document_hash) { - //return failure if the contact is not associated with the document - $contact = ClientContact::where('contact_key', $contact_key)->firstOrFail(); - if($contact->company_id == $document->company_id) + $document = Document::where('hash', $document_hash)->firstOrFail(); + return Storage::disk($document->disk)->download($document->url, $document->name); - - return response()->json(['message' => 'Access denied']); } public function downloadMultiple(DownloadMultipleDocumentsRequest $request) diff --git a/app/Http/Controllers/EmailController.php b/app/Http/Controllers/EmailController.php index e639340df6dd..580fbeb483a4 100644 --- a/app/Http/Controllers/EmailController.php +++ b/app/Http/Controllers/EmailController.php @@ -170,6 +170,6 @@ class EmailController extends BaseController $this->entity_transformer = RecurringInvoiceTransformer::class; } - return $this->itemResponse($entity_obj); + return $this->itemResponse($entity_obj->fresh()); } } diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php index 6d9c7eeeb2c2..2d722ffb47bd 100644 --- a/app/Http/Controllers/ImportController.php +++ b/app/Http/Controllers/ImportController.php @@ -13,11 +13,12 @@ namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Http\Requests\Import\PreImportRequest; +use App\Import\Definitions\Import\ImportMap; use Illuminate\Http\Request; -use League\Csv\Reader; -use League\Csv\Statement; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Str; +use League\Csv\Reader; +use League\Csv\Statement; class ImportController extends Controller { @@ -80,8 +81,9 @@ class ImportController extends Controller //parse CSV $csv_array = $this->getCsvData(file_get_contents($request->file('file')->getPathname())); - $data['data'] = [ + $data = [ 'hash' => $hash, + 'available' => InvoiceMap::importable(), 'headers' => array_slice($csv_array, 0, 2) ]; diff --git a/app/Http/Requests/Expense/StoreExpenseRequest.php b/app/Http/Requests/Expense/StoreExpenseRequest.php index e2b5aa3ff2ee..544fb576c3ea 100644 --- a/app/Http/Requests/Expense/StoreExpenseRequest.php +++ b/app/Http/Requests/Expense/StoreExpenseRequest.php @@ -58,8 +58,8 @@ class StoreExpenseRequest extends Request $input['category_id'] = $this->decodePrimaryKey($input['category_id']); } - if (! array_key_exists('currency_id', $input)) { - $input['currency_id'] = auth()->user()->company()->settings->currency_id; + if (! array_key_exists('currency_id', $input) || strlen($input['currency_id']) == 0) { + $input['currency_id'] = (string)auth()->user()->company()->settings->currency_id; } $this->replace($input); diff --git a/app/Import/Definitions/InvoiceMap.php b/app/Import/Definitions/InvoiceMap.php new file mode 100644 index 000000000000..8245bef32109 --- /dev/null +++ b/app/Import/Definitions/InvoiceMap.php @@ -0,0 +1,98 @@ + 'number', + 1 => 'user_id', + 2 => 'amount', + 3 => 'balance', + 4 => 'client_id', + 5 => 'status_id', + 6 => 'is_deleted', + 7 => 'discount', + 8 => 'po_number', + 9 => 'date', + 10 => 'due_date', + 11 => 'terms', + 12 => 'public_notes', + 13 => 'private_notes', + 14 => 'uses_inclusive_taxes', + 15 => 'tax_name1', + 16 => 'tax_rate1', + 17 => 'tax_name2', + 18 => 'tax_rate2', + 19 => 'tax_name3', + 20 => 'tax_rate3', + 21 => 'is_amount_discount', + 22 => 'footer', + 23 => 'partial', + 24 => 'partial_due_date', + 25 => 'custom_value1', + 26 => 'custom_value2', + 27 => 'custom_value3', + 28 => 'custom_value4', + 29 => 'custom_surcharge1', + 30 => 'custom_surcharge2', + 31 => 'custom_surcharge3', + 32 => 'custom_surcharge4', + 33 => 'exchange_rate', + 34 => 'line_items', + ]; + } + + public static function import_keys() + { + return [ + 0 => 'texts.invoice_number', + 1 => 'texts.user', + 2 => 'texts.amount', + 3 => 'texts.balance', + 4 => 'texts.client', + 5 => 'texts.status', + 6 => 'texts.deleted', + 7 => 'texts.discount', + 8 => 'texts.po_number', + 9 => 'texts.date', + 10 => 'texts.due_date', + 11 => 'texts.terms', + 12 => 'texts.public_notes', + 13 => 'texts.private_notes', + 14 => 'texts.uses_inclusive_taxes', + 15 => 'texts.tax_name1', + 16 => 'texts.tax_rate', + 17 => 'texts.tax_name', + 18 => 'texts.tax_rate', + 19 => 'texts.tax_name', + 20 => 'texts.tax_rate', + 21 => 'texts.is_amount_discount', + 22 => 'texts.footer', + 23 => 'texts.partial', + 24 => 'texts.partial_due_date', + 25 => 'texts.custom_value1', + 26 => 'texts.custom_value2', + 27 => 'texts.custom_value3', + 28 => 'texts.custom_value4', + 29 => 'texts.surcharge', + 30 => 'texts.surcharge', + 31 => 'texts.surcharge', + 32 => 'texts.surcharge', + 33 => 'texts.exchange_rate', + 34 => 'texts.items', + ]; + } +} \ No newline at end of file diff --git a/app/Jobs/Entity/CreateEntityPdf.php b/app/Jobs/Entity/CreateEntityPdf.php index a63b3590b13f..9b92d5316f47 100644 --- a/app/Jobs/Entity/CreateEntityPdf.php +++ b/app/Jobs/Entity/CreateEntityPdf.php @@ -164,4 +164,9 @@ class CreateEntityPdf implements ShouldQueue return $file_path; } + + public function failed(\Exception $exception) + { + info("help!"); + } } diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index b3b30d3c724c..e8aea5395052 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -1048,13 +1048,11 @@ class Import implements ShouldQueue $cgt = ClientGatewayToken::Create($modified); - $old_user_key = array_key_exists('user_id', $resource) ?? $this->user->id; + $key = "client_gateway_tokens_{$resource['id']}"; - $this->ids['client_gateway_tokens'] = [ - "client_gateway_tokens_{$old_user_key}" => [ - 'old' => $resource['id'], - 'new' => $cgt->id, - ], + $this->ids['client_gateway_tokens'][$key] = [ + 'old' => $resource['id'], + 'new' => $cgt->id, ]; } @@ -1079,13 +1077,11 @@ class Import implements ShouldQueue $task_status = TaskStatus::Create($modified); - $old_user_key = array_key_exists('user_id', $resource) ?? $this->user->id; + $key = "task_statuses_{$resource['id']}"; - $this->ids['task_statuses'] = [ - "task_statuses_{$old_user_key}" => [ - 'old' => $resource['id'], - 'new' => $task_status->id, - ], + $this->ids['task_statuses'][$key] = [ + 'old' => $resource['id'], + 'new' => $task_status->id, ]; } diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index d5ee8ca346b2..1f06e03b64a5 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -280,7 +280,7 @@ class CompanyGateway extends BaseModel if ($fees_and_limits->fee_amount) { $fee += $fees_and_limits->fee_amount; - info("fee after adding fee amount = {$fee}"); + // info("fee after adding fee amount = {$fee}"); } if ($fees_and_limits->fee_percent) { @@ -289,7 +289,7 @@ class CompanyGateway extends BaseModel } else { $fee += round(($amount * $fees_and_limits->fee_percent / 100), 2); } - info("fee after adding fee percent = {$fee}"); + // info("fee after adding fee percent = {$fee}"); } /* Cap fee if we have to here. */ @@ -303,17 +303,17 @@ class CompanyGateway extends BaseModel if ($include_taxes) { if ($fees_and_limits->fee_tax_rate1) { $fee += round(($pre_tax_fee * $fees_and_limits->fee_tax_rate1 / 100), 2); - info("fee after adding fee tax 1 = {$fee}"); + // info("fee after adding fee tax 1 = {$fee}"); } if ($fees_and_limits->fee_tax_rate2) { $fee += round(($pre_tax_fee * $fees_and_limits->fee_tax_rate2 / 100), 2); - info("fee after adding fee tax 2 = {$fee}"); + // info("fee after adding fee tax 2 = {$fee}"); } if ($fees_and_limits->fee_tax_rate3) { $fee += round(($pre_tax_fee * $fees_and_limits->fee_tax_rate3 / 100), 2); - info("fee after adding fee tax 3 = {$fee}"); + // info("fee after adding fee tax 3 = {$fee}"); } } diff --git a/app/Repositories/ExpenseRepository.php b/app/Repositories/ExpenseRepository.php index e08a7b88cc5f..e5058c21ba62 100644 --- a/app/Repositories/ExpenseRepository.php +++ b/app/Repositories/ExpenseRepository.php @@ -33,6 +33,7 @@ class ExpenseRepository extends BaseRepository */ public function save(array $data, Expense $expense) : ?Expense { + $expense->fill($data); $expense->number = empty($expense->number) ? $this->getNextExpenseNumber($expense) : $expense->number; $expense->save(); diff --git a/app/Services/Invoice/ApplyPayment.php b/app/Services/Invoice/ApplyPayment.php index ead9cd9b4135..0a67d4070b8f 100644 --- a/app/Services/Invoice/ApplyPayment.php +++ b/app/Services/Invoice/ApplyPayment.php @@ -36,14 +36,13 @@ class ApplyPayment extends AbstractService ->ledger() ->updatePaymentBalance($this->payment_amount * -1); - info("apply payment method - current client balance = {$this->payment->client->balance}"); + // info("apply payment method - current client balance = {$this->payment->client->balance}"); - info("reducing client balance by payment amount {$this->payment_amount}"); + // info("reducing client balance by payment amount {$this->payment_amount}"); $this->invoice->client->service()->updateBalance($this->payment_amount * -1)->save(); -// $this->invoice->client->service()->updateBalance($this->payment_amount*-1)->updatePaidToDate($this->payment_amount)->save(); - info("post client balance = {$this->invoice->client->balance}"); + // info("post client balance = {$this->invoice->client->balance}"); /* Update Pivot Record amount */ $this->payment->invoices->each(function ($inv) { @@ -55,8 +54,8 @@ class ApplyPayment extends AbstractService $this->invoice->fresh('client'); - info("1 end of apply payment method the client balance = {$this->invoice->client->balance}"); - + // info("1 end of apply payment method the client balance = {$this->invoice->client->balance}"); + if ($this->invoice->hasPartial()) { //is partial and amount is exactly the partial amount if ($this->invoice->partial == $this->payment_amount) { @@ -71,11 +70,11 @@ class ApplyPayment extends AbstractService } elseif ($this->payment_amount < $this->invoice->balance) { //partial invoice payment made $this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($this->payment_amount * -1); } - info("2 end of apply payment method the client balnace = {$this->invoice->client->balance}"); + // info("2 end of apply payment method the client balnace = {$this->invoice->client->balance}"); $this->invoice->service()->applyNumber()->save(); - info("3 end of apply payment method the client balnace = {$this->invoice->client->balance}"); + // info("3 end of apply payment method the client balnace = {$this->invoice->client->balance}"); return $this->invoice; } diff --git a/app/Services/Invoice/MarkSent.php b/app/Services/Invoice/MarkSent.php index 839f484f0dc6..ed8c8daaa7f1 100644 --- a/app/Services/Invoice/MarkSent.php +++ b/app/Services/Invoice/MarkSent.php @@ -37,9 +37,6 @@ class MarkSent extends AbstractService return $this->invoice; } -info("in mark sent"); -info($this->invoice->balance); - $this->invoice->markInvitationsSent(); $this->invoice->setReminder(); @@ -52,12 +49,8 @@ info($this->invoice->balance); ->updateBalance($this->invoice->amount) ->save(); -info($this->invoice->balance); - $this->client->service()->updateBalance($this->invoice->balance)->save(); -info($this->client->balance); - $this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance); event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars())); diff --git a/app/Transformers/ExpenseTransformer.php b/app/Transformers/ExpenseTransformer.php index 2760fe9c0033..b7f3c5474815 100644 --- a/app/Transformers/ExpenseTransformer.php +++ b/app/Transformers/ExpenseTransformer.php @@ -59,7 +59,7 @@ class ExpenseTransformer extends EntityTransformer 'bank_id' => (string) $expense->bank_id ?: '', 'invoice_currency_id' => (string) $expense->invoice_currency_id ?: '', 'expense_currency_id' => '', //todo remove redundant in 5.0.25 - 'currency_id' => (string) $expense->expense_currency_id ?: '', + 'currency_id' => (string) $expense->currency_id ?: '', 'category_id' => $this->encodePrimaryKey($expense->category_id), 'payment_type_id' => (string) $expense->payment_type_id ?: '', 'recurring_expense_id' => (string) $expense->recurring_expense_id ?: '', diff --git a/composer.lock b/composer.lock index a710907da364..578bffb04798 100644 --- a/composer.lock +++ b/composer.lock @@ -116,16 +116,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.168.2", + "version": "3.168.3", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "1d6a976da857d13b156bd63613ee086c13f6dc29" + "reference": "49ef1f905388c8185012c9651b80941b8f2a218d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1d6a976da857d13b156bd63613ee086c13f6dc29", - "reference": "1d6a976da857d13b156bd63613ee086c13f6dc29", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/49ef1f905388c8185012c9651b80941b8f2a218d", + "reference": "49ef1f905388c8185012c9651b80941b8f2a218d", "shasum": "" }, "require": { @@ -200,9 +200,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.168.2" + "source": "https://github.com/aws/aws-sdk-php/tree/3.168.3" }, - "time": "2020-12-10T19:35:18+00:00" + "time": "2020-12-11T19:12:18+00:00" }, { "name": "brick/math", diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 0b322170be22..565053ca7601 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -3321,4 +3321,9 @@ return [ 'notification_invoice_reminder2_sent_subject' => 'Reminder 2 for Invoice :invoice was sent to :client', 'notification_invoice_reminder3_sent_subject' => 'Reminder 3 for Invoice :invoice was sent to :client', 'notification_invoice_reminder_endless_sent_subject' => 'Endless reminder for Invoice :invoice was sent to :client', + 'assigned_user' => 'Assigned User', + 'custom_value3' => 'Custom Value', + 'custom_value4' => 'Custom Value', + 'inclusive_taxes' => 'Include taxes', + ]; diff --git a/routes/client.php b/routes/client.php index b78370876d23..e66659765fc9 100644 --- a/routes/client.php +++ b/routes/client.php @@ -22,7 +22,7 @@ Route::post('view/{entity_type}/{invitation_key}/password', 'ClientPortal\Entity Route::get('tmp_pdf/{hash}', 'ClientPortal\TempRouteController@index')->name('tmp_pdf'); Route::get('client/key_login/{contact_key}', 'ClientPortal\ContactHashLoginController@login')->name('client.contact_login')->middleware(['contact_key_login']); -Route::get('documents/{contact_key}/{document}/download', 'ClientPortal\DocumentController@publicDownload')->name('documents.public_download'); +Route::get('documents/{document_hash}', 'ClientPortal\DocumentController@publicDownload')->name('documents.public_download'); //todo implement domain DB Route::group(['middleware' => ['auth:contact', 'locale', 'check_client_existence'], 'prefix' => 'client', 'as' => 'client.'], function () { diff --git a/tests/Feature/Export/ExportCsvTest.php b/tests/Feature/Export/ExportCsvTest.php new file mode 100644 index 000000000000..2662b606358b --- /dev/null +++ b/tests/Feature/Export/ExportCsvTest.php @@ -0,0 +1,93 @@ +withoutMiddleware( + ThrottleRequests::class + ); + + // $this->faker = \Faker\Factory::create(); + + $this->makeTestData(); + + $this->withoutExceptionHandling(); + } + + public function testExportCsv() + { + $csv = Writer::createFromFileObject(new \SplTempFileObject()); + + $header_invoice = Invoice::take(10)->get()->toArray(); + $header_item = $header_invoice[0]['line_items'][0]; + unset($header_invoice[0]['line_items']); + + $header_invoice_keys = array_keys($header_invoice[0]); + $header_item_keys = array_keys((array)$header_item); + + $header_invoice_values = array_values($header_invoice[0]); + $header_item_values = array_values((array)$header_item); + + $merged_values = array_merge($header_invoice_values, (array)$header_item_values); + $merged_keys = array_merge($header_invoice_keys, (array)$header_item_keys); + + info(print_r( $merged_keys,1)); + info(print_r( $merged_values,1)); + + + foreach($merged_keys as &$key) { + $key = ctrans('texts.'.$key); + } + + $csv->insertOne($merged_keys); + + foreach(Invoice::take(10)->get() as $invoice){ + + foreach($invoice->line_items as $item) { + + unset($invoice->line_items); + + $csv->insertOne(array_merge($invoice->toArray(), (array)$item)); + + } + + + } + + Storage::put(base_path('invy.csv'), $csv->getContent()); + + } + +} \ No newline at end of file