diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..8386bafc38 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Release notes + +## [Unreleased (daily channel)](https://github.com/invoiceninja/invoiceninja/tree/v5-develop) + +### Added: + +### Fixed: + +### Removed: diff --git a/VERSION.txt b/VERSION.txt index f66977e2e4..0b8b1f0187 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.1.42 \ No newline at end of file +5.1.43 \ No newline at end of file diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index 0bda4f8ed9..097bfe453e 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -595,14 +595,14 @@ class CompanySettings extends BaseSettings $variables = [ 'client_details' => [ '$client.name', - '$client.id_number', + '$client.number', '$client.vat_number', '$client.address1', '$client.address2', '$client.city_state_postal', '$client.country', - '$contact.email', '$client.phone', + '$contact.email', ], 'company_details' => [ '$company.name', @@ -668,7 +668,7 @@ class CompanySettings extends BaseSettings '$total_taxes', '$line_taxes', '$paid_to_date', - '$outstanding', + '$total', ], ]; diff --git a/app/Http/Controllers/SelfUpdateController.php b/app/Http/Controllers/SelfUpdateController.php index 0f48d86bad..7c666fad7d 100644 --- a/app/Http/Controllers/SelfUpdateController.php +++ b/app/Http/Controllers/SelfUpdateController.php @@ -12,8 +12,6 @@ namespace App\Http\Controllers; use App\Utils\Ninja; -use Cz\Git\GitException; -use Cz\Git\GitRepository; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Support\Facades\Artisan; @@ -54,50 +52,42 @@ class SelfUpdateController extends BaseController * ), * ) */ - public function update() + public function update(\Codedge\Updater\UpdaterManager $updater) { + set_time_limit(0); define('STDIN', fopen('php://stdin', 'r')); if (Ninja::isNinja()) { return response()->json(['message' => ctrans('texts.self_update_not_available')], 403); } - /* .git MUST be owned/writable by the webserver user */ - $repo = new GitRepository(base_path()); + // Check if new version is available + if($updater->source()->isNewVersionAvailable()) { - nlog('Are there changes to pull? '.$repo->hasChanges()); - $output = ''; + // Get the new version available + $versionAvailable = $updater->source()->getVersionAvailable(); - try { - - $cacheCompiled = base_path('bootstrap/cache/compiled.php'); - if (file_exists($cacheCompiled)) { unlink ($cacheCompiled); } - $cacheServices = base_path('bootstrap/cache/services.php'); - if (file_exists($cacheServices)) { unlink ($cacheServices); } + // Create a release + $release = $updater->source()->fetch($versionAvailable); - Artisan::call('clear-compiled'); - Artisan::call('cache:clear'); - Artisan::call('debugbar:clear'); - Artisan::call('route:clear'); - Artisan::call('view:clear'); - Artisan::call('config:clear'); + $updater->source()->update($release); - // $output = $repo->execute('stash'); - // $output = $repo->execute('reset --hard origin/v5-stable'); - $output = $repo->execute('pull origin'); - - } catch (GitException $e) { - - nlog($output); - nlog($e->getMessage()); - return response()->json(['message'=>$e->getMessage()], 500); } + + $cacheCompiled = base_path('bootstrap/cache/compiled.php'); + if (file_exists($cacheCompiled)) { unlink ($cacheCompiled); } + $cacheServices = base_path('bootstrap/cache/services.php'); + if (file_exists($cacheServices)) { unlink ($cacheServices); } - dispatch(function () { - Artisan::call('ninja:post-update'); - }); + Artisan::call('clear-compiled'); + Artisan::call('cache:clear'); + Artisan::call('debugbar:clear'); + Artisan::call('route:clear'); + Artisan::call('view:clear'); + Artisan::call('config:clear'); + + return response()->json(['message' => 'Update completed'], 200); - return response()->json(['message' => $output], 200); } public function checkVersion() diff --git a/app/Models/Account.php b/app/Models/Account.php index ed0a7484f2..79ec7439a6 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -14,6 +14,7 @@ namespace App\Models; use App\Models\Presenters\AccountPresenter; use App\Utils\Ninja; use App\Utils\Traits\MakesHash; +use Carbon\Carbon; use DateTime; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Laracasts\Presenter\PresentableTrait; @@ -257,8 +258,8 @@ class Account extends BaseModel $plan_active = true; $plan_expires = false; } else { - $plan_expires = DateTime::createFromFormat('Y-m-d', $this->plan_expires); - if ($plan_expires >= date_create()) { + $plan_expires = Carbon::parse($this->plan_expires); + if ($plan_expires->greaterThan(now())) { $plan_active = true; } } diff --git a/app/Repositories/PaymentRepository.php b/app/Repositories/PaymentRepository.php index 95e3c4ba4c..b94161609f 100644 --- a/app/Repositories/PaymentRepository.php +++ b/app/Repositories/PaymentRepository.php @@ -114,6 +114,7 @@ class PaymentRepository extends BaseRepository { /*Iterate through invoices and apply payments*/ if (array_key_exists('invoices', $data) && is_array($data['invoices']) && count($data['invoices']) > 0) { + $invoice_totals = array_sum(array_column($data['invoices'], 'amount')); $invoices = Invoice::whereIn('id', array_column($data['invoices'], 'invoice_id'))->get(); @@ -125,7 +126,10 @@ class PaymentRepository extends BaseRepository { $invoice = Invoice::whereId($paid_invoice['invoice_id'])->first(); if ($invoice) { - $invoice = $invoice->service()->markSent()->applyPayment($payment, $paid_invoice['amount'])->save(); + $invoice = $invoice->service() + ->markSent() + ->applyPayment($payment, $paid_invoice['amount']) + ->save(); } } } else { diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index 6f056e7e90..86296b632a 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -101,6 +101,8 @@ class InvoiceService */ public function applyPayment(Payment $payment, float $payment_amount) { + $this->deletePdf(); + $this->invoice = (new ApplyPayment($this->invoice, $payment, $payment_amount))->run(); return $this; @@ -295,6 +297,7 @@ class InvoiceService public function deletePdf() { + nlog("delete PDF"); //UnlinkFile::dispatchNow(config('filesystems.default'), $this->invoice->client->invoice_filepath() . $this->invoice->numberFormatter().'.pdf'); Storage::disk(config('filesystems.default'))->delete($this->invoice->client->invoice_filepath() . $this->invoice->numberFormatter().'.pdf'); diff --git a/composer.json b/composer.json index 85a2820370..9b29fe5258 100644 --- a/composer.json +++ b/composer.json @@ -36,12 +36,11 @@ "checkout/checkout-sdk-php": "^1.0", "cleverit/ubl_invoice": "^1.3", "coconutcraig/laravel-postmark": "^2.10", + "codedge/laravel-selfupdater": "^3.2", "composer/composer": "^2", - "czproject/git-php": "^3.17", - "turbo124/laravel-gmail": "^5", "doctrine/dbal": "^2.10", - "fideloper/proxy": "^4.2", "fakerphp/faker": "^1.14", + "fideloper/proxy": "^4.2", "google/apiclient": "^2.7", "guzzlehttp/guzzle": "^7.0.1", "hashids/hashids": "^4.0", @@ -67,6 +66,7 @@ "stripe/stripe-php": "^7.50", "symfony/http-client": "^5.2", "turbo124/beacon": "^1.0", + "turbo124/laravel-gmail": "^5", "webpatser/laravel-countries": "dev-master#75992ad", "wildbit/swiftmailer-postmark": "^3.3" }, diff --git a/composer.lock b/composer.lock index a665a1d18c..e426f659b2 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": "64a35682f0e808b80b4784d812271f0b", + "content-hash": "56b8467dfddd19762a9124d0624a5003", "packages": [ { "name": "authorizenet/authorizenet", @@ -51,16 +51,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.176.9", + "version": "3.178.0", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "17dc67514b148979994758fbfb54088a8a3393bf" + "reference": "214e3d98c54277cd8965f1cf307dce39631407bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/17dc67514b148979994758fbfb54088a8a3393bf", - "reference": "17dc67514b148979994758fbfb54088a8a3393bf", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/214e3d98c54277cd8965f1cf307dce39631407bf", + "reference": "214e3d98c54277cd8965f1cf307dce39631407bf", "shasum": "" }, "require": { @@ -135,9 +135,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.176.9" + "source": "https://github.com/aws/aws-sdk-php/tree/3.178.0" }, - "time": "2021-04-06T18:13:47+00:00" + "time": "2021-04-08T18:13:16+00:00" }, { "name": "bacon/bacon-qr-code", @@ -563,6 +563,88 @@ ], "time": "2021-02-24T13:45:30+00:00" }, + { + "name": "codedge/laravel-selfupdater", + "version": "3.2.3", + "source": { + "type": "git", + "url": "https://github.com/codedge/laravel-selfupdater.git", + "reference": "60bca20f30d36259ef5eff65bc84d0dcb61267f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codedge/laravel-selfupdater/zipball/60bca20f30d36259ef5eff65bc84d0dcb61267f7", + "reference": "60bca20f30d36259ef5eff65bc84d0dcb61267f7", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-zip": "*", + "guzzlehttp/guzzle": "6.* || 7.*", + "laravel/framework": "^8.36.2", + "php": "^7.3 || ^7.4 || ^8.0" + }, + "require-dev": { + "dg/bypass-finals": "^1.3", + "mikey179/vfsstream": "^1.6", + "mockery/mockery": "^1.4", + "orchestra/testbench": "^6.17.0", + "phpunit/phpunit": "^9.5.4" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Updater": "Codedge\\Updater\\UpdaterFacade" + }, + "providers": [ + "Codedge\\Updater\\UpdaterServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Codedge\\Updater\\": "src/" + }, + "files": [ + "src/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Holger Lösken", + "email": "holger.loesken@codedge.de", + "homepage": "http://codedge.de", + "role": "Developer" + } + ], + "description": "Providing an auto-updating functionality for your self-hosted Laravel application.", + "keywords": [ + "auto update", + "auto-update", + "laravel", + "laravel application", + "self update", + "self-hosted laravel application", + "self-update", + "update" + ], + "support": { + "issues": "https://github.com/codedge/laravel-selfupdater/issues", + "source": "https://github.com/codedge/laravel-selfupdater" + }, + "funding": [ + { + "url": "https://github.com/codedge", + "type": "github" + } + ], + "time": "2021-04-09T08:47:03+00:00" + }, { "name": "composer/ca-bundle", "version": "1.2.9", @@ -960,52 +1042,6 @@ ], "time": "2021-03-25T17:01:18+00:00" }, - { - "name": "czproject/git-php", - "version": "v3.18.2", - "source": { - "type": "git", - "url": "https://github.com/czproject/git-php.git", - "reference": "cb3bfc6f1e487e572870afae5d52ef3c7d250d8a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/czproject/git-php/zipball/cb3bfc6f1e487e572870afae5d52ef3c7d250d8a", - "reference": "cb3bfc6f1e487e572870afae5d52ef3c7d250d8a", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "nette/tester": "^1.1" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jan Pecha", - "email": "janpecha@email.cz" - } - ], - "description": "Library for work with Git repository in PHP.", - "keywords": [ - "git" - ], - "support": { - "issues": "https://github.com/czproject/git-php/issues", - "source": "https://github.com/czproject/git-php/tree/v3.18.2" - }, - "time": "2021-02-15T11:41:33+00:00" - }, { "name": "dasprid/enum", "version": "1.0.3", @@ -2759,16 +2795,16 @@ }, { "name": "laravel/framework", - "version": "v8.36.1", + "version": "v8.36.2", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "91c454715b81b9a39f718651d4e2f8104d45e7c2" + "reference": "0debd8ad6b5aa1f61ccc73910adf049af4ca0444" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/91c454715b81b9a39f718651d4e2f8104d45e7c2", - "reference": "91c454715b81b9a39f718651d4e2f8104d45e7c2", + "url": "https://api.github.com/repos/laravel/framework/zipball/0debd8ad6b5aa1f61ccc73910adf049af4ca0444", + "reference": "0debd8ad6b5aa1f61ccc73910adf049af4ca0444", "shasum": "" }, "require": { @@ -2923,7 +2959,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-04-06T21:14:06+00:00" + "time": "2021-04-07T12:37:22+00:00" }, { "name": "laravel/slack-notification-channel", @@ -10828,16 +10864,16 @@ }, { "name": "facade/flare-client-php", - "version": "1.5.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/facade/flare-client-php.git", - "reference": "9dd6f2b56486d939c4467b3f35475d44af57cf17" + "reference": "f2b0969f2d9594704be74dbeb25b201570a98098" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/flare-client-php/zipball/9dd6f2b56486d939c4467b3f35475d44af57cf17", - "reference": "9dd6f2b56486d939c4467b3f35475d44af57cf17", + "url": "https://api.github.com/repos/facade/flare-client-php/zipball/f2b0969f2d9594704be74dbeb25b201570a98098", + "reference": "f2b0969f2d9594704be74dbeb25b201570a98098", "shasum": "" }, "require": { @@ -10881,7 +10917,7 @@ ], "support": { "issues": "https://github.com/facade/flare-client-php/issues", - "source": "https://github.com/facade/flare-client-php/tree/1.5.0" + "source": "https://github.com/facade/flare-client-php/tree/1.6.1" }, "funding": [ { @@ -10889,26 +10925,26 @@ "type": "github" } ], - "time": "2021-03-31T07:32:54+00:00" + "time": "2021-04-08T08:50:01+00:00" }, { "name": "facade/ignition", - "version": "2.7.0", + "version": "2.8.2", "source": { "type": "git", "url": "https://github.com/facade/ignition.git", - "reference": "bdc8b0b32c888f6edc838ca641358322b3d9506d" + "reference": "cb7f790e6306caeb4a9ffe21e59942b7128cc630" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/ignition/zipball/bdc8b0b32c888f6edc838ca641358322b3d9506d", - "reference": "bdc8b0b32c888f6edc838ca641358322b3d9506d", + "url": "https://api.github.com/repos/facade/ignition/zipball/cb7f790e6306caeb4a9ffe21e59942b7128cc630", + "reference": "cb7f790e6306caeb4a9ffe21e59942b7128cc630", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", - "facade/flare-client-php": "^1.3.7", + "facade/flare-client-php": "^1.6", "facade/ignition-contracts": "^1.0.2", "filp/whoops": "^2.4", "illuminate/support": "^7.0|^8.0", @@ -10966,7 +11002,7 @@ "issues": "https://github.com/facade/ignition/issues", "source": "https://github.com/facade/ignition" }, - "time": "2021-03-30T15:55:38+00:00" + "time": "2021-04-08T10:42:53+00:00" }, { "name": "facade/ignition-contracts", diff --git a/config/ninja.php b/config/ninja.php index 35197d2027..81376365d8 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -14,7 +14,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', ''), - 'app_version' => '5.1.42', + 'app_version' => '5.1.43', + 'app_tag' => '5.1.43-release', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false), diff --git a/config/self-update.php b/config/self-update.php new file mode 100644 index 0000000000..7a61c05a42 --- /dev/null +++ b/config/self-update.php @@ -0,0 +1,149 @@ + env('SELF_UPDATER_SOURCE', 'github'), + + /* + |-------------------------------------------------------------------------- + | Version installed + |-------------------------------------------------------------------------- + | + | Set this to the version of your software installed on your system. + | + */ + + 'version_installed' => env('SELF_UPDATER_VERSION_INSTALLED', config('ninja.app_tag')), + + /* + |-------------------------------------------------------------------------- + | Repository types + |-------------------------------------------------------------------------- + | + | A repository can be of different types, which can be specified here. + | Current options: + | - github + | - http + | + */ + + 'repository_types' => [ + 'github' => [ + 'type' => 'github', + 'repository_vendor' => env('SELF_UPDATER_REPO_VENDOR', 'invoiceninja'), + 'repository_name' => env('SELF_UPDATER_REPO_NAME', 'invoiceninja'), + 'repository_url' => 'https://github.com/', + 'download_path' => env('SELF_UPDATER_DOWNLOAD_PATH', '/tmp'), + 'private_access_token' => env('SELF_UPDATER_GITHUB_PRIVATE_ACCESS_TOKEN', ''), + 'use_branch' => env('SELF_UPDATER_USE_BRANCH', ''), + ], + 'http' => [ + 'type' => 'http', + 'repository_url' => env('SELF_UPDATER_REPO_URL', ''), + 'pkg_filename_format' => env('SELF_UPDATER_PKG_FILENAME_FORMAT', 'v_VERSION_'), + 'download_path' => env('SELF_UPDATER_DOWNLOAD_PATH', '/tmp'), + 'private_access_token' => env('SELF_UPDATER_HTTP_PRIVATE_ACCESS_TOKEN', ''), + ], + ], + + /* + |-------------------------------------------------------------------------- + | Exclude folders from update + |-------------------------------------------------------------------------- + | + | Specific folders which should not be updated and will be skipped during the + | update process. + | + | Here's already a list of good examples to skip. You may want to keep those. + | + */ + + 'exclude_folders' => [ + '__MACOSX', + 'node_modules', + 'bootstrap/cache', + 'bower', + 'storage/app', + 'storage/framework', + 'storage/logs', + 'storage/self-update', + 'public/storage', + 'vendor', + ], + + /* + |-------------------------------------------------------------------------- + | Event Logging + |-------------------------------------------------------------------------- + | + | Configure if fired events should be logged + | + */ + + 'log_events' => env('SELF_UPDATER_LOG_EVENTS', true), + + /* + |-------------------------------------------------------------------------- + | Notifications + |-------------------------------------------------------------------------- + | + | Specify for which events you want to get notifications. Out of the box you can use 'mail'. + | + */ + + 'notifications' => [ + 'notifications' => [ + \Codedge\Updater\Notifications\Notifications\UpdateSucceeded::class => ['mail'], + \Codedge\Updater\Notifications\Notifications\UpdateFailed::class => ['mail'], + \Codedge\Updater\Notifications\Notifications\UpdateAvailable::class => ['mail'], + ], + + /* + * Here you can specify the notifiable to which the notifications should be sent. The default + * notifiable will use the variables specified in this config file. + */ + 'notifiable' => \Codedge\Updater\Notifications\Notifiable::class, + + 'mail' => [ + 'to' => [ + 'address' => env('SELF_UPDATER_MAILTO_ADDRESS', 'notifications@example.com'), + 'name' => env('SELF_UPDATER_MAILTO_NAME', ''), + ], + + 'from' => [ + 'address' => env('SELF_UPDATER_MAIL_FROM_ADDRESS', 'updater@example.com'), + 'name' => env('SELF_UPDATER_MAIL_FROM_NAME', 'Update'), + ], + ], + ], + + /* + |--------------------------------------------------------------------------- + | Register custom artisan commands + |--------------------------------------------------------------------------- + */ + + 'artisan_commands' => [ + 'pre_update' => [ + //'command:signature' => [ + // 'class' => Command class + // 'params' => [] + //] + ], + 'post_update' => [ + 'postupdate:cleanup' => [ + 'class' => \App\Console\Commands\PostUpdate::class, + ], + ] + ], + +]; diff --git a/routes/web.php b/routes/web.php index 914077b0b8..119d7cd219 100644 --- a/routes/web.php +++ b/routes/web.php @@ -5,6 +5,7 @@ use Illuminate\Support\Facades\Route; //Auth::routes(['password.reset' => false]); Route::get('/', 'BaseController@flutterRoute')->middleware('guest'); + // Route::get('self-update', 'SelfUpdateController@update')->middleware('guest'); Route::get('setup', 'SetupController@index')->middleware('guest'); Route::post('setup', 'SetupController@doSetup')->middleware('guest');