From 2d437d40f29e4535d46b1d709dfcaf1d22401780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=BCneyt=20=C5=9Eent=C3=BCrk?= Date: Mon, 28 Sep 2020 14:45:10 +0300 Subject: [PATCH 1/3] dynamic component form issue solved. --- resources/assets/js/mixins/global.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/assets/js/mixins/global.js b/resources/assets/js/mixins/global.js index 28194946c..7987791f6 100644 --- a/resources/assets/js/mixins/global.js +++ b/resources/assets/js/mixins/global.js @@ -284,7 +284,7 @@ export default { }, created: function() { - this.form = new Form('form-create'); + this.form = new Form('form-dynamic-component'); }, mounted() { From 95133dd15a471d36d4dcf9c071cef8ee9e70e612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=BCneyt=20=C5=9Eent=C3=BCrk?= Date: Mon, 28 Sep 2020 14:47:47 +0300 Subject: [PATCH 2/3] psr-4 fix for composer 2.0 --- composer.json | 2 +- composer.lock | 255 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 167 insertions(+), 90 deletions(-) diff --git a/composer.json b/composer.json index 6ab525926..2fc7416bd 100644 --- a/composer.json +++ b/composer.json @@ -76,7 +76,7 @@ "Modules\\": "modules/", "Akaunting\\Module\\Commands\\": "overrides/akaunting/module/Commands/", "Illuminate\\Translation\\": "overrides/Illuminate/Translation/", - "Illuminate\\View\\": "overrides/Illuminate/View/", + "Illuminate\\View\\Concerns\\": "overrides/Illuminate/View/Concerns/", "Symfony\\Component\\Process\\": "overrides/symfony/process/" }, "exclude-from-classmap": [ diff --git a/composer.lock b/composer.lock index 1ae3154a0..ff9233d43 100644 --- a/composer.lock +++ b/composer.lock @@ -1126,16 +1126,16 @@ }, { "name": "composer/semver", - "version": "1.7.0", + "version": "1.7.1", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "114f819054a2ea7db03287f5efb757e2af6e4079" + "reference": "38276325bd896f90dfcfe30029aa5db40df387a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/114f819054a2ea7db03287f5efb757e2af6e4079", - "reference": "114f819054a2ea7db03287f5efb757e2af6e4079", + "url": "https://api.github.com/repos/composer/semver/zipball/38276325bd896f90dfcfe30029aa5db40df387a7", + "reference": "38276325bd896f90dfcfe30029aa5db40df387a7", "shasum": "" }, "require": { @@ -1197,7 +1197,7 @@ "type": "tidelift" } ], - "time": "2020-09-09T09:34:06+00:00" + "time": "2020-09-27T13:13:07+00:00" }, { "name": "composer/spdx-licenses", @@ -2252,16 +2252,16 @@ }, { "name": "egulias/email-validator", - "version": "2.1.21", + "version": "2.1.22", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "563d0cdde5d862235ffe24a158497f4d490191b5" + "reference": "68e418ec08fbfc6f58f6fd2eea70ca8efc8cc7d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/563d0cdde5d862235ffe24a158497f4d490191b5", - "reference": "563d0cdde5d862235ffe24a158497f4d490191b5", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/68e418ec08fbfc6f58f6fd2eea70ca8efc8cc7d5", + "reference": "68e418ec08fbfc6f58f6fd2eea70ca8efc8cc7d5", "shasum": "" }, "require": { @@ -2306,7 +2306,7 @@ "validation", "validator" ], - "time": "2020-09-19T14:37:56+00:00" + "time": "2020-09-26T15:48:38+00:00" }, { "name": "fideloper/proxy", @@ -5552,16 +5552,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.10.0", + "version": "v4.10.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1c13d05035deff45f1230ca68bd7d74d621762d9" + "reference": "658f1be311a230e0907f5dfe0213742aff0596de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1c13d05035deff45f1230ca68bd7d74d621762d9", - "reference": "1c13d05035deff45f1230ca68bd7d74d621762d9", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/658f1be311a230e0907f5dfe0213742aff0596de", + "reference": "658f1be311a230e0907f5dfe0213742aff0596de", "shasum": "" }, "require": { @@ -5600,7 +5600,7 @@ "parser", "php" ], - "time": "2020-09-19T14:52:48+00:00" + "time": "2020-09-26T10:30:38+00:00" }, { "name": "omnipay/common", @@ -7829,16 +7829,16 @@ }, { "name": "symfony/console", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "186f395b256065ba9b890c0a4e48a91d598fa2cf" + "reference": "04c3a31fe8ea94b42c9e2d1acc93d19782133b00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/186f395b256065ba9b890c0a4e48a91d598fa2cf", - "reference": "186f395b256065ba9b890c0a4e48a91d598fa2cf", + "url": "https://api.github.com/repos/symfony/console/zipball/04c3a31fe8ea94b42c9e2d1acc93d19782133b00", + "reference": "04c3a31fe8ea94b42c9e2d1acc93d19782133b00", "shasum": "" }, "require": { @@ -7918,11 +7918,11 @@ "type": "tidelift" } ], - "time": "2020-09-02T07:07:40+00:00" + "time": "2020-09-18T14:27:32+00:00" }, { "name": "symfony/css-selector", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -7989,16 +7989,16 @@ }, { "name": "symfony/debug", - "version": "v4.4.13", + "version": "v4.4.14", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "aeb73aca16a8f1fe958230fe44e6cf4c84cbb85e" + "reference": "726b85e69342e767d60e3853b98559a68ff74183" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/aeb73aca16a8f1fe958230fe44e6cf4c84cbb85e", - "reference": "aeb73aca16a8f1fe958230fe44e6cf4c84cbb85e", + "url": "https://api.github.com/repos/symfony/debug/zipball/726b85e69342e767d60e3853b98559a68ff74183", + "reference": "726b85e69342e767d60e3853b98559a68ff74183", "shasum": "" }, "require": { @@ -8056,7 +8056,7 @@ "type": "tidelift" } ], - "time": "2020-08-10T07:47:39+00:00" + "time": "2020-09-09T05:20:36+00:00" }, { "name": "symfony/deprecation-contracts", @@ -8124,16 +8124,16 @@ }, { "name": "symfony/error-handler", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "525636d4b84e06c6ca72d96b6856b5b169416e6a" + "reference": "d2f1d4996d5499f1261164d10080e4120001f041" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/525636d4b84e06c6ca72d96b6856b5b169416e6a", - "reference": "525636d4b84e06c6ca72d96b6856b5b169416e6a", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/d2f1d4996d5499f1261164d10080e4120001f041", + "reference": "d2f1d4996d5499f1261164d10080e4120001f041", "shasum": "" }, "require": { @@ -8191,20 +8191,20 @@ "type": "tidelift" } ], - "time": "2020-08-17T10:01:29+00:00" + "time": "2020-09-27T03:44:28+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "94871fc0a69c3c5da57764187724cdce0755899c" + "reference": "d5de97d6af175a9e8131c546db054ca32842dd0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/94871fc0a69c3c5da57764187724cdce0755899c", - "reference": "94871fc0a69c3c5da57764187724cdce0755899c", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d5de97d6af175a9e8131c546db054ca32842dd0f", + "reference": "d5de97d6af175a9e8131c546db054ca32842dd0f", "shasum": "" }, "require": { @@ -8224,6 +8224,7 @@ "psr/log": "~1.0", "symfony/config": "^4.4|^5.0", "symfony/dependency-injection": "^4.4|^5.0", + "symfony/error-handler": "^4.4|^5.0", "symfony/expression-language": "^4.4|^5.0", "symfony/http-foundation": "^4.4|^5.0", "symfony/service-contracts": "^1.1|^2", @@ -8277,7 +8278,7 @@ "type": "tidelift" } ], - "time": "2020-08-13T14:19:42+00:00" + "time": "2020-09-18T14:27:32+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -8357,16 +8358,16 @@ }, { "name": "symfony/filesystem", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "f7b9ed6142a34252d219801d9767dedbd711da1a" + "reference": "f3194303d3077829dbbc1d18f50288b2a01146f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/f7b9ed6142a34252d219801d9767dedbd711da1a", - "reference": "f7b9ed6142a34252d219801d9767dedbd711da1a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/f3194303d3077829dbbc1d18f50288b2a01146f2", + "reference": "f3194303d3077829dbbc1d18f50288b2a01146f2", "shasum": "" }, "require": { @@ -8417,20 +8418,20 @@ "type": "tidelift" } ], - "time": "2020-08-21T17:19:47+00:00" + "time": "2020-09-02T16:23:27+00:00" }, { "name": "symfony/finder", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2b765f0cf6612b3636e738c0689b29aa63088d5d" + "reference": "2c3ba7ad6884e6c4451ce2340e2dc23f6fa3e0d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2b765f0cf6612b3636e738c0689b29aa63088d5d", - "reference": "2b765f0cf6612b3636e738c0689b29aa63088d5d", + "url": "https://api.github.com/repos/symfony/finder/zipball/2c3ba7ad6884e6c4451ce2340e2dc23f6fa3e0d8", + "reference": "2c3ba7ad6884e6c4451ce2340e2dc23f6fa3e0d8", "shasum": "" }, "require": { @@ -8480,20 +8481,95 @@ "type": "tidelift" } ], - "time": "2020-08-17T10:01:29+00:00" + "time": "2020-09-02T16:23:27+00:00" }, { - "name": "symfony/http-foundation", - "version": "v5.1.5", + "name": "symfony/http-client-contracts", + "version": "v2.2.0", "source": { "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "41a4647f12870e9d41d9a7d72ff0614a27208558" + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "3a5d0fe7908daaa23e3dbf4cee3ba4bfbb19fdd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/41a4647f12870e9d41d9a7d72ff0614a27208558", - "reference": "41a4647f12870e9d41d9a7d72ff0614a27208558", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/3a5d0fe7908daaa23e3dbf4cee3ba4bfbb19fdd3", + "reference": "3a5d0fe7908daaa23e3dbf4cee3ba4bfbb19fdd3", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "suggest": { + "symfony/http-client-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-09-07T11:33:47+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v5.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "6cca6b2e4b69fc5bace160d14cf1ee5f71483db4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6cca6b2e4b69fc5bace160d14cf1ee5f71483db4", + "reference": "6cca6b2e4b69fc5bace160d14cf1ee5f71483db4", "shasum": "" }, "require": { @@ -8555,20 +8631,20 @@ "type": "tidelift" } ], - "time": "2020-08-17T07:48:54+00:00" + "time": "2020-09-13T05:01:27+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "3e32676e6cb5d2081c91a56783471ff8a7f7110b" + "reference": "17227644c3c66dcf32bdfeceff4364d090cd6756" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3e32676e6cb5d2081c91a56783471ff8a7f7110b", - "reference": "3e32676e6cb5d2081c91a56783471ff8a7f7110b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/17227644c3c66dcf32bdfeceff4364d090cd6756", + "reference": "17227644c3c66dcf32bdfeceff4364d090cd6756", "shasum": "" }, "require": { @@ -8577,6 +8653,7 @@ "symfony/deprecation-contracts": "^2.1", "symfony/error-handler": "^4.4|^5.0", "symfony/event-dispatcher": "^5.0", + "symfony/http-client-contracts": "^1.1|^2", "symfony/http-foundation": "^4.4|^5.0", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-php73": "^1.9", @@ -8668,20 +8745,20 @@ "type": "tidelift" } ], - "time": "2020-09-02T08:15:18+00:00" + "time": "2020-09-27T04:33:19+00:00" }, { "name": "symfony/mime", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "89a2c9b4cb7b5aa516cf55f5194c384f444c81dc" + "reference": "4404d6545125863561721514ad9388db2661eec5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/89a2c9b4cb7b5aa516cf55f5194c384f444c81dc", - "reference": "89a2c9b4cb7b5aa516cf55f5194c384f444c81dc", + "url": "https://api.github.com/repos/symfony/mime/zipball/4404d6545125863561721514ad9388db2661eec5", + "reference": "4404d6545125863561721514ad9388db2661eec5", "shasum": "" }, "require": { @@ -8745,7 +8822,7 @@ "type": "tidelift" } ], - "time": "2020-08-17T10:01:29+00:00" + "time": "2020-09-02T16:23:27+00:00" }, { "name": "symfony/polyfill-ctype", @@ -9529,16 +9606,16 @@ }, { "name": "symfony/process", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "1864216226af21eb76d9477f691e7cbf198e0402" + "reference": "d3a2e64866169586502f0cd9cab69135ad12cee9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/1864216226af21eb76d9477f691e7cbf198e0402", - "reference": "1864216226af21eb76d9477f691e7cbf198e0402", + "url": "https://api.github.com/repos/symfony/process/zipball/d3a2e64866169586502f0cd9cab69135ad12cee9", + "reference": "d3a2e64866169586502f0cd9cab69135ad12cee9", "shasum": "" }, "require": { @@ -9589,20 +9666,20 @@ "type": "tidelift" } ], - "time": "2020-07-23T08:36:24+00:00" + "time": "2020-09-02T16:23:27+00:00" }, { "name": "symfony/routing", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "47b0218344cb6af25c93ca8ee1137fafbee5005d" + "reference": "d36e06eb02a55522a8eed070c1cbc3dc3c389876" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/47b0218344cb6af25c93ca8ee1137fafbee5005d", - "reference": "47b0218344cb6af25c93ca8ee1137fafbee5005d", + "url": "https://api.github.com/repos/symfony/routing/zipball/d36e06eb02a55522a8eed070c1cbc3dc3c389876", + "reference": "d36e06eb02a55522a8eed070c1cbc3dc3c389876", "shasum": "" }, "require": { @@ -9681,7 +9758,7 @@ "type": "tidelift" } ], - "time": "2020-08-10T08:03:57+00:00" + "time": "2020-09-02T16:23:27+00:00" }, { "name": "symfony/service-contracts", @@ -9761,16 +9838,16 @@ }, { "name": "symfony/string", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "0de4cc1e18bb596226c06a82e2e7e9bc6001a63a" + "reference": "4a9afe9d07bac506f75bcee8ed3ce76da5a9343e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/0de4cc1e18bb596226c06a82e2e7e9bc6001a63a", - "reference": "0de4cc1e18bb596226c06a82e2e7e9bc6001a63a", + "url": "https://api.github.com/repos/symfony/string/zipball/4a9afe9d07bac506f75bcee8ed3ce76da5a9343e", + "reference": "4a9afe9d07bac506f75bcee8ed3ce76da5a9343e", "shasum": "" }, "require": { @@ -9842,20 +9919,20 @@ "type": "tidelift" } ], - "time": "2020-08-17T07:48:54+00:00" + "time": "2020-09-15T12:23:47+00:00" }, { "name": "symfony/translation", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "917b02cdc5f33e0309b8e9d33ee1480b20687413" + "reference": "e3cdd5119b1b5bf0698c351b8ee20fb5a4ea248b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/917b02cdc5f33e0309b8e9d33ee1480b20687413", - "reference": "917b02cdc5f33e0309b8e9d33ee1480b20687413", + "url": "https://api.github.com/repos/symfony/translation/zipball/e3cdd5119b1b5bf0698c351b8ee20fb5a4ea248b", + "reference": "e3cdd5119b1b5bf0698c351b8ee20fb5a4ea248b", "shasum": "" }, "require": { @@ -9934,7 +10011,7 @@ "type": "tidelift" } ], - "time": "2020-08-17T10:01:29+00:00" + "time": "2020-09-27T03:44:28+00:00" }, { "name": "symfony/translation-contracts", @@ -10013,16 +10090,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.1.5", + "version": "v5.1.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "b43a3905262bcf97b2510f0621f859ca4f5287be" + "reference": "c976c115a0d788808f7e71834c8eb0844f678d02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/b43a3905262bcf97b2510f0621f859ca4f5287be", - "reference": "b43a3905262bcf97b2510f0621f859ca4f5287be", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c976c115a0d788808f7e71834c8eb0844f678d02", + "reference": "c976c115a0d788808f7e71834c8eb0844f678d02", "shasum": "" }, "require": { @@ -10099,7 +10176,7 @@ "type": "tidelift" } ], - "time": "2020-08-17T07:42:30+00:00" + "time": "2020-09-18T14:27:32+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -12278,4 +12355,4 @@ }, "platform-dev": [], "plugin-api-version": "1.1.0" -} +} \ No newline at end of file From 015a1a34e19561f1fbf43e9cca96042d7137c72a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=BCneyt=20=C5=9Eent=C3=BCrk?= Date: Mon, 28 Sep 2020 14:54:25 +0300 Subject: [PATCH 3/3] improved recurring check --- app/Console/Commands/RecurringCheck.php | 184 ++++++++++++------ app/Events/Banking/TransactionRecurring.php | 22 +++ app/Traits/Recurring.php | 119 +++++------ app/Utilities/Recurring.php | 4 +- .../views/purchases/bills/show.blade.php | 2 +- .../views/purchases/payments/edit.blade.php | 2 +- resources/views/sales/invoices/show.blade.php | 2 +- resources/views/sales/revenues/edit.blade.php | 2 +- 8 files changed, 218 insertions(+), 119 deletions(-) create mode 100644 app/Events/Banking/TransactionRecurring.php diff --git a/app/Console/Commands/RecurringCheck.php b/app/Console/Commands/RecurringCheck.php index e69ef3c74..f2a5d2ba4 100644 --- a/app/Console/Commands/RecurringCheck.php +++ b/app/Console/Commands/RecurringCheck.php @@ -2,21 +2,21 @@ namespace App\Console\Commands; +use App\Events\Banking\TransactionCreated; +use App\Events\Banking\TransactionRecurring; use App\Events\Purchase\BillCreated; use App\Events\Purchase\BillRecurring; use App\Events\Sale\InvoiceCreated; use App\Events\Sale\InvoiceRecurring; +use App\Models\Banking\Transaction; use App\Models\Common\Company; -use App\Traits\Sales; +use App\Models\Sale\Invoice; use App\Utilities\Overrider; -use Carbon\Carbon; use Date; use Illuminate\Console\Command; class RecurringCheck extends Command { - use Sales; - /** * The name and signature of the console command. * @@ -34,7 +34,7 @@ class RecurringCheck extends Command /** * The current day. * - * @var Carbon + * @var \Carbon\Carbon */ protected $today; @@ -64,8 +64,16 @@ class RecurringCheck extends Command $this->today = Date::today(); foreach ($company->recurring as $recurring) { - foreach ($recurring->schedule() as $schedule) { - $this->recur($recurring, $schedule); + if (!$model = $recurring->recurable) { + continue; + } + + foreach ($recurring->getRecurringSchedule() as $schedule) { + $schedule_date = Date::parse($schedule->getStart()->format('Y-m-d')); + + \DB::transaction(function () use ($model, $recurring, $schedule_date) { + $this->recur($model, $recurring->recurable_type, $schedule_date); + }); } } } @@ -75,97 +83,161 @@ class RecurringCheck extends Command setting()->forgetAll(); } - protected function recur($recurring, $schedule) + protected function recur($model, $type, $schedule_date) { - $schedule_date = Date::parse($schedule->getStart()->format('Y-m-d')); - - // Check if should recur today - if ($this->today->ne($schedule_date)) { + // Don't recur the future + if ($schedule_date->greaterThan($this->today)) { return; } - if (!$model = $recurring->recurable) { + if (!$clone = $this->getClone($model, $schedule_date)) { return; } - switch ($recurring->recurable_type) { + switch ($type) { case 'App\Models\Purchase\Bill': - if (!$clone = $this->getDocumentClone($model, 'billed_at')) { - break; - } - event(new BillCreated($clone)); event(new BillRecurring($clone)); break; case 'App\Models\Sale\Invoice': - if (!$clone = $this->getDocumentClone($model, 'invoiced_at')) { - break; - } - event(new InvoiceCreated($clone)); event(new InvoiceRecurring($clone)); break; case 'App\Models\Banking\Transaction': - // Skip model created on the same day, but scheduler hasn't run yet - if ($this->today->eq(Date::parse($model->paid_at->format('Y-m-d')))) { - break; - } + event(new TransactionCreated($clone)); - $model->cloneable_relations = []; - - // Create new record - $clone = $model->duplicate(); - - $clone->parent_id = $model->id; - $clone->paid_at = $this->today->format('Y-m-d'); - $clone->save(); + event(new TransactionRecurring($clone)); break; } } + /** + * Clone the model and return it. + * + * @param $model + * @param $schedule_date + * + * @return boolean|object + */ + protected function getClone($model, $schedule_date) + { + if ($this->skipThisClone($model, $schedule_date)) { + return false; + } + + $function = ($model instanceof Transaction) ? 'getTransactionClone' : 'getDocumentClone'; + + try { + return $this->$function($model, $schedule_date); + } catch (\Exception | \Throwable | \Swift_RfcComplianceException| \Swift_TransportException | \Illuminate\Database\QueryException $e) { + $this->error($e->getMessage()); + + logger('Recurring check:: ' . $e->getMessage()); + + return false; + } + } + /** * Clone the document and return it. * * @param $model - * @param $date_field + * @param $schedule_date * * @return boolean|object */ - protected function getDocumentClone($model, $date_field) + protected function getDocumentClone($model, $schedule_date) { - // Skip model created on the same day, but scheduler hasn't run yet - if ($this->today->eq(Date::parse($model->$date_field->format('Y-m-d')))) { - return false; - } - $model->cloneable_relations = ['items', 'totals']; - try { - $clone = $model->duplicate(); - } catch (\Exception | \Throwable | \Swift_RfcComplianceException | \Illuminate\Database\QueryException $e) { - $this->error($e->getMessage()); + $clone = $model->duplicate(); - logger('Recurring check:: ' . $e->getMessage()); - - return false; - } - - // Set original model id - $clone->parent_id = $model->id; + $date_field = $this->getDateField($model); // Days between issued and due date $diff_days = Date::parse($clone->due_at)->diffInDays(Date::parse($clone->$date_field)); - // Update dates - $clone->$date_field = $this->today->format('Y-m-d'); - $clone->due_at = $this->today->copy()->addDays($diff_days)->format('Y-m-d'); + $clone->parent_id = $model->id; + $clone->$date_field = $schedule_date->format('Y-m-d'); + $clone->due_at = $schedule_date->copy()->addDays($diff_days)->format('Y-m-d'); $clone->save(); return $clone; } -} + + /** + * Clone the transaction and return it. + * + * @param $model + * @param $schedule_date + * + * @return boolean|object + */ + protected function getTransactionClone($model, $schedule_date) + { + $model->cloneable_relations = []; + + $clone = $model->duplicate(); + + $clone->parent_id = $model->id; + $clone->paid_at = $schedule_date->format('Y-m-d'); + $clone->save(); + + return $clone; + } + + protected function skipThisClone($model, $schedule_date) + { + $date_field = $this->getDateField($model); + + // Skip model created on the same day, but scheduler hasn't run yet + if ($schedule_date->equalTo(Date::parse($model->$date_field->format('Y-m-d')))) { + return true; + } + + $table = $this->getTable($model); + + $already_cloned = \DB::table($table) + ->where('parent_id', $model->id) + ->whereDate($date_field, $schedule_date) + ->value('id'); + + // Skip if already cloned + if ($already_cloned) { + return true; + } + + return false; + } + + protected function getDateField($model) + { + if ($model instanceof Transaction) { + return 'paid_at'; + } + + if ($model instanceof Invoice) { + return 'invoiced_at'; + } + + return 'billed_at'; + } + + protected function getTable($model) + { + if ($model instanceof Transaction) { + return 'transactions'; + } + + if ($model instanceof Invoice) { + return 'invoices'; + } + + return 'bills'; + } +} \ No newline at end of file diff --git a/app/Events/Banking/TransactionRecurring.php b/app/Events/Banking/TransactionRecurring.php new file mode 100644 index 000000000..2622a5617 --- /dev/null +++ b/app/Events/Banking/TransactionRecurring.php @@ -0,0 +1,22 @@ +transaction = $transaction; + } +} \ No newline at end of file diff --git a/app/Traits/Recurring.php b/app/Traits/Recurring.php index bbbe671b5..271271f2c 100644 --- a/app/Traits/Recurring.php +++ b/app/Traits/Recurring.php @@ -59,18 +59,71 @@ trait Recurring ]); } - public function current() + public function getRecurringSchedule() { - if (!$schedule = $this->schedule()) { + $config = new ArrayTransformerConfig(); + $config->enableLastDayOfMonthFix(); + + $transformer = new ArrayTransformer(); + $transformer->setConfig($config); + + return $transformer->transform($this->getRecurringRule()); + } + + public function getRecurringRule() + { + $rule = (new Rule()) + ->setStartDate($this->getRecurringRuleStartDate()) + ->setTimezone($this->getRecurringRuleTimeZone()) + ->setFreq($this->getRecurringRuleFrequency()) + ->setInterval($this->getRecurringRuleInterval()); + + // 0 means infinite + if ($this->count != 0) { + $rule->setCount($this->getRecurringRuleCount()); + } + + return $rule; + } + + public function getRecurringRuleStartDate() + { + return new \DateTime($this->started_at, new \DateTimeZone($this->getRecurringRuleTimeZone())); + } + + public function getRecurringRuleTimeZone() + { + return setting('localisation.timezone'); + } + + public function getRecurringRuleCount() + { + // Fix for humans + return $this->count + 1; + } + + public function getRecurringRuleFrequency() + { + return strtoupper($this->frequency); + } + + public function getRecurringRuleInterval() + { + return $this->interval; + } + + public function getCurrentRecurring() + { + if (!$schedule = $this->getRecurringSchedule()) { return false; } return $schedule->current()->getStart(); } - public function next() + public function getNextRecurring() { - if (!$schedule = $this->schedule()) { + if (!$schedule = $this->getRecurringSchedule()) { return false; } @@ -81,69 +134,21 @@ trait Recurring return $next->getStart(); } - public function first() + public function getFirstRecurring() { - if (!$schedule = $this->schedule()) { + if (!$schedule = $this->getRecurringSchedule()) { return false; } return $schedule->first()->getStart(); } - public function last() + public function getLastRecurring() { - if (!$schedule = $this->schedule()) { + if (!$schedule = $this->getRecurringSchedule()) { return false; } return $schedule->last()->getStart(); } - - public function schedule() - { - $config = new ArrayTransformerConfig(); - $config->enableLastDayOfMonthFix(); - - $transformer = new ArrayTransformer(); - $transformer->setConfig($config); - - return $transformer->transform($this->getRule()); - } - - public function getRule() - { - $rule = (new Rule()) - ->setStartDate($this->getRuleStartDate()) - ->setTimezone($this->getRuleTimeZone()) - ->setFreq($this->getRuleFrequency()) - ->setInterval($this->interval); - - // 0 means infinite - if ($this->count != 0) { - $rule->setCount($this->getRuleCount()); - } - - return $rule; - } - - public function getRuleStartDate() - { - return new \DateTime($this->started_at, new \DateTimeZone($this->getRuleTimeZone())); - } - - public function getRuleTimeZone() - { - return setting('localisation.timezone'); - } - - public function getRuleCount() - { - // Fix for humans - return $this->count + 1; - } - - public function getRuleFrequency() - { - return strtoupper($this->frequency); - } -} +} \ No newline at end of file diff --git a/app/Utilities/Recurring.php b/app/Utilities/Recurring.php index ee915ec46..2f2562cf4 100644 --- a/app/Utilities/Recurring.php +++ b/app/Utilities/Recurring.php @@ -16,9 +16,9 @@ class Recurring continue; } - foreach ($item->recurring->schedule() as $recurr) { + foreach ($item->recurring->getRecurringSchedule() as $schedule) { $issued = Date::parse($item->$issued_date_field); - $start = $recurr->getStart(); + $start = $schedule->getStart(); if ($issued->format('Y') != $start->format('Y')) { continue; diff --git a/resources/views/purchases/bills/show.blade.php b/resources/views/purchases/bills/show.blade.php index ed597f760..7f42610c7 100644 --- a/resources/views/purchases/bills/show.blade.php +++ b/resources/views/purchases/bills/show.blade.php @@ -4,7 +4,7 @@ @section('content') @stack('recurring_message_start') - @if (($recurring = $bill->recurring) && ($next = $recurring->next())) + @if (($recurring = $bill->recurring) && ($next = $recurring->getNextRecurring()))
diff --git a/resources/views/purchases/payments/edit.blade.php b/resources/views/purchases/payments/edit.blade.php index ad19b9955..5b5799fe7 100644 --- a/resources/views/purchases/payments/edit.blade.php +++ b/resources/views/purchases/payments/edit.blade.php @@ -3,7 +3,7 @@ @section('title', trans('general.title.edit', ['type' => trans_choice('general.payments', 1)])) @section('content') - @if (($recurring = $payment->recurring) && ($next = $recurring->next())) + @if (($recurring = $payment->recurring) && ($next = $recurring->getNextRecurring()))
diff --git a/resources/views/sales/invoices/show.blade.php b/resources/views/sales/invoices/show.blade.php index a57843b54..0411052bc 100644 --- a/resources/views/sales/invoices/show.blade.php +++ b/resources/views/sales/invoices/show.blade.php @@ -4,7 +4,7 @@ @section('content') @stack('recurring_message_start') - @if (($recurring = $invoice->recurring) && ($next = $recurring->next())) + @if (($recurring = $invoice->recurring) && ($next = $recurring->getNextRecurring()))
diff --git a/resources/views/sales/revenues/edit.blade.php b/resources/views/sales/revenues/edit.blade.php index 8d547b717..e11c41f02 100644 --- a/resources/views/sales/revenues/edit.blade.php +++ b/resources/views/sales/revenues/edit.blade.php @@ -3,7 +3,7 @@ @section('title', trans('general.title.edit', ['type' => trans_choice('general.revenues', 1)])) @section('content') - @if (($recurring = $revenue->recurring) && ($next = $recurring->next())) + @if (($recurring = $revenue->recurring) && ($next = $recurring->getNextRecurring()))